Skip to content

Commit f251bc6

Browse files
authored
feat(cluster/lock): implement verify_signature (#265)
* feat(cluster/lock): implement verify_signature * fix: address comments
1 parent 2dd4871 commit f251bc6

2 files changed

Lines changed: 320 additions & 68 deletions

File tree

crates/cluster/src/definition.rs

Lines changed: 27 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -311,13 +311,6 @@ pub enum DefinitionError {
311311
#[error("invalid creator config signature")]
312312
InvalidCreatorConfigSignature,
313313

314-
/// Missing ETH1 client for contract signature verification.
315-
#[error("missing eth1 client for contract signature verification: {contract_address}")]
316-
MissingEth1ClientForContractSignature {
317-
/// Contract address used for signature verification.
318-
contract_address: String,
319-
},
320-
321314
/// Invalid EIP-712 digest length
322315
#[error("invalid eip712 digest length: expected {expected}, actual {actual}")]
323316
InvalidEIP712DigestLength {
@@ -474,7 +467,7 @@ impl Definition {
474467

475468
/// Returns `Ok(())` if all config signatures are fully
476469
/// populated and valid. A verified definition is ready for use in DKG.
477-
pub async fn verify_signatures(&self, eth1: Option<&EthClient>) -> Result<(), DefinitionError> {
470+
pub async fn verify_signatures(&self, eth1: &EthClient) -> Result<(), DefinitionError> {
478471
// Skip signature verification for definition versions earlier than v1.3 since
479472
// there are no EIP712 signatures before v1.3.0. For definition versions
480473
// earlier than v1.3.0, error if either config signature or enr signature for
@@ -718,17 +711,11 @@ impl Definition {
718711
}
719712

720713
async fn verify_contract_signature(
721-
eth1: Option<&EthClient>,
714+
eth1: &EthClient,
722715
contract_address: &str,
723716
digest: &[u8],
724717
sig: &[u8],
725718
) -> Result<bool, DefinitionError> {
726-
let Some(eth1_client) = eth1 else {
727-
return Err(DefinitionError::MissingEth1ClientForContractSignature {
728-
contract_address: contract_address.to_string(),
729-
});
730-
};
731-
732719
let digest_hash: [u8; 32] =
733720
digest
734721
.try_into()
@@ -737,8 +724,7 @@ impl Definition {
737724
actual: digest.len(),
738725
})?;
739726

740-
eth1_client
741-
.verify_smart_contract_based_signature(contract_address, digest_hash, sig)
727+
eth1.verify_smart_contract_based_signature(contract_address, digest_hash, sig)
742728
.await
743729
.map_err(DefinitionError::FailedToVerifyContractSignature)
744730
}
@@ -1587,6 +1573,10 @@ mod tests {
15871573
serde_json::from_value(value).unwrap()
15881574
}
15891575

1576+
async fn test_eth1_client() -> EthClient {
1577+
EthClient::new("http://127.0.0.1:8545").await.unwrap()
1578+
}
1579+
15901580
#[test]
15911581
fn cluster_definition_v1_10_0_fields() {
15921582
let definition = serde_json::from_str::<Definition>(include_str!(
@@ -1833,7 +1823,9 @@ mod tests {
18331823
#[tokio::test]
18341824
async fn verify_signatures_examples(definition_json: &str) {
18351825
let definition = parse_example_definition(definition_json);
1836-
assert!(definition.verify_signatures(None).await.is_ok());
1826+
let eth1 = test_eth1_client().await;
1827+
1828+
assert!(definition.verify_signatures(&eth1).await.is_ok());
18371829
}
18381830

18391831
#[tokio::test]
@@ -1842,7 +1834,9 @@ mod tests {
18421834
"testdata/cluster_definition_v1_2_0.json"
18431835
))
18441836
.unwrap();
1845-
assert!(definition.verify_signatures(None).await.is_ok());
1837+
let eth1 = test_eth1_client().await;
1838+
1839+
assert!(definition.verify_signatures(&eth1).await.is_ok());
18461840
}
18471841

18481842
#[tokio::test]
@@ -1852,8 +1846,9 @@ mod tests {
18521846
))
18531847
.unwrap();
18541848
definition.operators[0].config_signature = vec![1];
1849+
let eth1 = test_eth1_client().await;
18551850

1856-
let result = definition.verify_signatures(None).await;
1851+
let result = definition.verify_signatures(&eth1).await;
18571852
assert!(matches!(
18581853
result,
18591854
Err(DefinitionError::OlderVersionSignaturesNotSupported)
@@ -1865,8 +1860,9 @@ mod tests {
18651860
let mut definition =
18661861
parse_example_definition(include_str!("examples/cluster-definition-001.json"));
18671862
definition.operators[0].enr_signature = Vec::new();
1863+
let eth1 = test_eth1_client().await;
18681864

1869-
let result = definition.verify_signatures(None).await;
1865+
let result = definition.verify_signatures(&eth1).await;
18701866
assert!(matches!(
18711867
result,
18721868
Err(DefinitionError::EmptyOperatorENRSignature { .. })
@@ -1878,8 +1874,9 @@ mod tests {
18781874
let mut definition =
18791875
parse_example_definition(include_str!("examples/cluster-definition-001.json"));
18801876
definition.operators[0].config_signature = Vec::new();
1877+
let eth1 = test_eth1_client().await;
18811878

1882-
let result = definition.verify_signatures(None).await;
1879+
let result = definition.verify_signatures(&eth1).await;
18831880
assert!(matches!(
18841881
result,
18851882
Err(DefinitionError::EmptyOperatorConfigSignature { .. })
@@ -1891,8 +1888,9 @@ mod tests {
18911888
let mut definition =
18921889
parse_example_definition(include_str!("examples/cluster-definition-001.json"));
18931890
definition.operators[0] = Operator::default();
1891+
let eth1 = test_eth1_client().await;
18941892

1895-
let result = definition.verify_signatures(None).await;
1893+
let result = definition.verify_signatures(&eth1).await;
18961894
assert!(matches!(
18971895
result,
18981896
Err(DefinitionError::SomeOperatorsSignedWhileOthersDidNot)
@@ -1904,8 +1902,9 @@ mod tests {
19041902
let mut definition =
19051903
parse_example_definition(include_str!("examples/cluster-definition-001.json"));
19061904
definition.creator.config_signature = Vec::new();
1905+
let eth1 = test_eth1_client().await;
19071906

1908-
let result = definition.verify_signatures(None).await;
1907+
let result = definition.verify_signatures(&eth1).await;
19091908
assert!(matches!(
19101909
result,
19111910
Err(DefinitionError::EmptyCreatorConfigSignature)
@@ -1918,33 +1917,22 @@ mod tests {
19181917
parse_example_definition(include_str!("examples/cluster-definition-001.json"));
19191918
definition.creator = Creator::default();
19201919
definition.operators = vec![Operator::default(), Operator::default()];
1920+
let eth1 = test_eth1_client().await;
19211921

1922-
assert!(definition.verify_signatures(None).await.is_ok());
1922+
assert!(definition.verify_signatures(&eth1).await.is_ok());
19231923
}
19241924

19251925
#[tokio::test]
19261926
async fn verify_signatures_v1_3_rejects_creator_signature() {
19271927
let mut definition =
19281928
parse_example_definition(include_str!("examples/cluster-definition-000.json"));
19291929
definition.creator.config_signature = vec![1];
1930+
let eth1 = test_eth1_client().await;
19301931

1931-
let result = definition.verify_signatures(None).await;
1932+
let result = definition.verify_signatures(&eth1).await;
19321933
assert!(matches!(
19331934
result,
19341935
Err(DefinitionError::UnexpectedCreatorConfigSignatureInOldVersion)
19351936
));
19361937
}
1937-
1938-
#[tokio::test]
1939-
async fn verify_signatures_missing_eth1_client_for_contract_fallback() {
1940-
let mut definition =
1941-
parse_example_definition(include_str!("examples/cluster-definition-001.json"));
1942-
definition.operators[0].config_signature = definition.operators[1].config_signature.clone();
1943-
1944-
let result = definition.verify_signatures(None).await;
1945-
assert!(matches!(
1946-
result,
1947-
Err(DefinitionError::MissingEth1ClientForContractSignature { .. })
1948-
));
1949-
}
19501938
}

0 commit comments

Comments
 (0)