diff --git a/crates/cluster/src/definition.rs b/crates/cluster/src/definition.rs index ae4e4633..8abf21f5 100644 --- a/crates/cluster/src/definition.rs +++ b/crates/cluster/src/definition.rs @@ -556,7 +556,7 @@ impl Definition { } let operator_config_hash_digest = digest_eip712( - &get_operator_eip712_type(self.version.as_str()), + &get_operator_eip712_type(self.version.as_str())?, self, &Operator::default(), )?; @@ -1908,6 +1908,18 @@ mod tests { assert!(definition.verify_hashes().is_ok()); } + #[test] + fn cluster_definition_v1_3_0_unsigned_operators() { + for fixture in [ + include_str!("testdata/cluster_definition_v1_3_0_unsigned.json"), + include_str!("testdata/cluster_definition_v1_3_0_partial_sigs.json"), + ] { + let definition = serde_json::from_str::(fixture).unwrap(); + + assert!(definition.verify_hashes().is_ok()); + } + } + #[test] fn cluster_definition_v1_4_0() { let json_str = include_str!("testdata/cluster_definition_v1_4_0.json"); diff --git a/crates/cluster/src/eip712sigs.rs b/crates/cluster/src/eip712sigs.rs index 87ec946a..916d43fe 100644 --- a/crates/cluster/src/eip712sigs.rs +++ b/crates/cluster/src/eip712sigs.rs @@ -26,6 +26,10 @@ pub enum EIP712Error { /// Failed to sign EIP-712. #[error("Failed to sign EIP-712: {0}")] FailedToSign(pluto_k1util::K1UtilError), + + /// Definition version does not support EIP-712 signatures. + #[error("Version does not support EIP-712 signatures: {0}")] + UnsupportedVersion(String), } struct EIP712TypeField { @@ -116,16 +120,16 @@ fn eip712_terms_and_conditions() -> EIP712Type { } /// Returns the latest or legacy operator eip712 type. -pub(crate) fn get_operator_eip712_type(version: &str) -> EIP712Type { +pub(crate) fn get_operator_eip712_type(version: &str) -> Result { if !Definition::support_eip712_sigs(version) { - unreachable!("invalid eip712 signature version"); // This should never happen + return Err(EIP712Error::UnsupportedVersion(version.to_string())); } if version == V1_3 { - return eip712_v1x3_config_hash(); + return Ok(eip712_v1x3_config_hash()); } - eip712_operator_config_hash() + Ok(eip712_operator_config_hash()) } /// Returns the digest for the EIP712 structured type for the provided @@ -240,6 +244,14 @@ mod tests { assert_eq!(signature, expected_signature); } + #[test] + fn get_operator_eip712_type_rejects_unsupported_version() { + assert!(matches!( + get_operator_eip712_type(crate::version::V1_2), + Err(EIP712Error::UnsupportedVersion(_)) + )); + } + #[test] fn enr_digest() { let definition = serde_json::from_str::(include_str!( diff --git a/crates/cluster/src/helpers.rs b/crates/cluster/src/helpers.rs index 28fcdbf5..5f27f02a 100644 --- a/crates/cluster/src/helpers.rs +++ b/crates/cluster/src/helpers.rs @@ -178,7 +178,7 @@ pub fn sign_operator( ) -> Result<(), crate::eip712sigs::EIP712Error> { let config_signature = crate::eip712sigs::sign_eip712( secret, - &crate::eip712sigs::get_operator_eip712_type(&definition.version), + &crate::eip712sigs::get_operator_eip712_type(&definition.version)?, definition, operator, )?; diff --git a/crates/cluster/src/ssz.rs b/crates/cluster/src/ssz.rs index 5cf1a448..44126780 100644 --- a/crates/cluster/src/ssz.rs +++ b/crates/cluster/src/ssz.rs @@ -323,10 +323,12 @@ pub(crate) fn hash_definition_v1x3or4( put_byte_list(hh, o.enr.as_bytes(), SSZ_MAX_ENR, "enr")?; // Field (2) 'ConfigSignature' Bytes65 - put_bytes_n(hh, &o.config_signature, SSZ_LEN_K1_SIG)?; + hh.put_bytes(&o.config_signature) + .map_err(SSZError::::HashWalkerError)?; // Field (3) 'ENRSignature' Bytes65 - put_bytes_n(hh, &o.enr_signature, SSZ_LEN_K1_SIG)?; + hh.put_bytes(&o.enr_signature) + .map_err(SSZError::::HashWalkerError)?; } hh.merkleize(op_sub_idx) diff --git a/crates/cluster/src/testdata/cluster_definition_v1_3_0_partial_sigs.json b/crates/cluster/src/testdata/cluster_definition_v1_3_0_partial_sigs.json new file mode 100644 index 00000000..877271aa --- /dev/null +++ b/crates/cluster/src/testdata/cluster_definition_v1_3_0_partial_sigs.json @@ -0,0 +1,28 @@ +{ + "name": "test definition", + "operators": [ + { + "address": "0x019192c24224e2cafccae3a61fb586b14323a6bc", + "enr": "enr://ea6f5b3af6de0374366c4719e43a1b067d89bc7f01f1f573981659a44ff17a4c", + "config_signature": "", + "enr_signature": "" + }, + { + "address": "0xa6430105220d0b29688b734b8ea0f3ca9936e846", + "enr": "enr://f6a63b7f3dfd2567c18979e4d60f26686d9bf2fb26c901ff354cde1607ee294b", + "config_signature": "0x39f32b7c7822ba64f84ab43ca0c6e6b91c1fd3be8990434179d3af4491a369012db92d184fc39d1734ff5716428953bb6865fcf92b0c3a17c9028be9914eb7641c", + "enr_signature": "0x6c9347800979d1830356f2a54c3deab2a4b4475d63afbe8fb56987c77f5818526f1814be823350eab13935f31d84484517e924aef78ae151c00755925836b7071b" + } + ], + "uuid": "0194FDC2-FA2F-4CC0-81D3-FF12045B73C8", + "version": "v1.3.0", + "timestamp": "2022-07-19T18:19:58+02:00", + "num_validators": 2, + "threshold": 3, + "fee_recipient_address": "0x52fdfc072182654f163f5f0f9a621d729566c74d", + "withdrawal_address": "0x81855ad8681d0d86d1e91e00167939cb6694d2c4", + "dkg_algorithm": "default", + "fork_version": "0x90000069", + "config_hash": "0xc6d3acd4b419aa59ddde2ef268d9fdbf01d68185c7d5151e6d5885058e4a3f26", + "definition_hash": "0x52de1a6dad5265cd698a5622b22dd88b7ab2e894554232d28770a9b7aa7ba71d" +} \ No newline at end of file diff --git a/crates/cluster/src/testdata/cluster_definition_v1_3_0_unsigned.json b/crates/cluster/src/testdata/cluster_definition_v1_3_0_unsigned.json new file mode 100644 index 00000000..a6e17f3d --- /dev/null +++ b/crates/cluster/src/testdata/cluster_definition_v1_3_0_unsigned.json @@ -0,0 +1,28 @@ +{ + "name": "test definition", + "operators": [ + { + "address": "0x019192c24224e2cafccae3a61fb586b14323a6bc", + "enr": "enr://ea6f5b3af6de0374366c4719e43a1b067d89bc7f01f1f573981659a44ff17a4c", + "config_signature": "", + "enr_signature": "" + }, + { + "address": "0xa6430105220d0b29688b734b8ea0f3ca9936e846", + "enr": "enr://f6a63b7f3dfd2567c18979e4d60f26686d9bf2fb26c901ff354cde1607ee294b", + "config_signature": "", + "enr_signature": "" + } + ], + "uuid": "0194FDC2-FA2F-4CC0-81D3-FF12045B73C8", + "version": "v1.3.0", + "timestamp": "2022-07-19T18:19:58+02:00", + "num_validators": 2, + "threshold": 3, + "fee_recipient_address": "0x52fdfc072182654f163f5f0f9a621d729566c74d", + "withdrawal_address": "0x81855ad8681d0d86d1e91e00167939cb6694d2c4", + "dkg_algorithm": "default", + "fork_version": "0x90000069", + "config_hash": "0xc6d3acd4b419aa59ddde2ef268d9fdbf01d68185c7d5151e6d5885058e4a3f26", + "definition_hash": "0xb6333215f08427104e50f8fba4fa1fa089dc4974b5029f19de84fe85955584e2" +} \ No newline at end of file