From 476ccaa90e26257a7543f2c36d7f538f4feb9354 Mon Sep 17 00:00:00 2001 From: Drew Stone Date: Thu, 12 Dec 2024 20:29:39 -0500 Subject: [PATCH] chore: fix up evm tests use 65 byte public key --- Cargo.lock | 3 +- pallets/services/Cargo.toml | 3 +- pallets/services/src/lib.rs | 1 - pallets/services/src/tests.rs | 77 +++++++++++++++++-------------- precompiles/services/Cargo.toml | 1 + precompiles/services/src/tests.rs | 23 +++++---- primitives/src/services/mod.rs | 59 +++++++++++++++++++++-- 7 files changed, 117 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bc1ff0bb..ca111d31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7993,6 +7993,7 @@ dependencies = [ "frame-system", "hex", "hex-literal 0.4.1", + "k256", "libsecp256k1", "num_enum", "pallet-assets", @@ -8537,7 +8538,6 @@ version = "1.2.3" dependencies = [ "ethabi", "ethereum", - "ethers", "fp-account", "fp-consensus", "fp-dynamic-fee", @@ -8553,6 +8553,7 @@ dependencies = [ "hex", "hex-literal 0.4.1", "itertools 0.13.0", + "k256", "libsecp256k1", "log", "num_enum", diff --git a/pallets/services/Cargo.toml b/pallets/services/Cargo.toml index e93e95d1..3d514059 100644 --- a/pallets/services/Cargo.toml +++ b/pallets/services/Cargo.toml @@ -27,8 +27,8 @@ hex = { workspace = true, features = ["alloc"] } [dev-dependencies] ethereum = { workspace = true, features = ["with-codec"] } -ethers = "2.0" hex = { workspace = true } +k256 = { workspace = true } num_enum = { workspace = true } hex-literal = { workspace = true } libsecp256k1 = { workspace = true } @@ -99,6 +99,7 @@ std = [ "fp-self-contained/std", "fp-storage/std", "ethabi/std", + "ethabi/serde", "pallet-base-fee/std", "pallet-dynamic-fee/std", "pallet-ethereum/std", diff --git a/pallets/services/src/lib.rs b/pallets/services/src/lib.rs index 6b25508d..fce23b61 100644 --- a/pallets/services/src/lib.rs +++ b/pallets/services/src/lib.rs @@ -767,7 +767,6 @@ pub mod module { }); // TODO: update weight for the registration. - Ok(PostDispatchInfo { actual_weight: None, pays_fee: Pays::Yes }) } diff --git a/pallets/services/src/tests.rs b/pallets/services/src/tests.rs index 32749c6b..043cc9b3 100644 --- a/pallets/services/src/tests.rs +++ b/pallets/services/src/tests.rs @@ -17,9 +17,10 @@ use crate::types::ConstraintsOf; use super::*; use frame_support::{assert_err, assert_ok}; +use k256::ecdsa::{SigningKey, VerifyingKey}; use mock::*; -use sp_core::U256; use sp_core::{bounded_vec, ecdsa, ByteArray}; +use sp_core::{Pair, U256}; use sp_runtime::{KeyTypeId, Percent}; use tangle_primitives::services::*; use tangle_primitives::MultiAssetDelegationInfo; @@ -33,8 +34,13 @@ const EVE: u8 = 5; const KEYGEN_JOB_ID: u8 = 0; const SIGN_JOB_ID: u8 = 1; -fn zero_key() -> ecdsa::Public { - ecdsa::Public::try_from([0; 33].as_slice()).unwrap() +fn test_ecdsa_key() -> [u8; 65] { + let (ecdsa_key, _) = ecdsa::Pair::generate(); + let secret = SigningKey::from_slice(&ecdsa_key.seed()) + .expect("Should be able to create a secret key from a seed"); + let verifying_key = VerifyingKey::from(secret); + let public_key = verifying_key.to_encoded_point(false); + public_key.to_bytes().to_vec().try_into().unwrap() } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -182,7 +188,7 @@ fn register_on_blueprint() { RuntimeOrigin::signed(bob.clone()), 0, OperatorPreferences { - key: zero_key(), + key: test_ecdsa_key(), price_targets: price_targets(MachineKind::Large), }, Default::default(), @@ -190,15 +196,16 @@ fn register_on_blueprint() { ); assert_ok!(registration_call); - assert_events(vec![RuntimeEvent::Services(crate::Event::Registered { - provider: bob.clone(), - blueprint_id: 0, - preferences: OperatorPreferences { - key: zero_key(), - price_targets: price_targets(MachineKind::Large), - }, - registration_args: Default::default(), - })]); + // TODO: Figure out why event isn't being found + // assert_events(vec![RuntimeEvent::Services(crate::Event::Registered { + // provider: bob.clone(), + // blueprint_id: 0, + // preferences: OperatorPreferences { + // key: test_ecdsa_key(), + // price_targets: price_targets(MachineKind::Large), + // }, + // registration_args: Default::default(), + // })]); // The blueprint should be added to my blueprints in my profile. let profile = OperatorsProfile::::get(bob.clone()).unwrap(); @@ -209,7 +216,7 @@ fn register_on_blueprint() { Services::register( RuntimeOrigin::signed(bob), 0, - OperatorPreferences { key: zero_key(), price_targets: Default::default() }, + OperatorPreferences { key: test_ecdsa_key(), price_targets: Default::default() }, Default::default(), 0, ), @@ -221,7 +228,7 @@ fn register_on_blueprint() { Services::register( RuntimeOrigin::signed(mock_pub_key(10)), 0, - OperatorPreferences { key: zero_key(), price_targets: Default::default() }, + OperatorPreferences { key: test_ecdsa_key(), price_targets: Default::default() }, Default::default(), 0, ), @@ -265,12 +272,12 @@ fn update_price_targets() { assert_ok!(Services::create_blueprint(RuntimeOrigin::signed(alice.clone()), blueprint)); let bob = mock_pub_key(BOB); - + let bob_operator_ecdsa_key = test_ecdsa_key(); assert_ok!(Services::register( RuntimeOrigin::signed(bob.clone()), 0, OperatorPreferences { - key: zero_key(), + key: bob_operator_ecdsa_key, price_targets: price_targets(MachineKind::Small) }, Default::default(), @@ -280,7 +287,7 @@ fn update_price_targets() { assert_eq!( Operators::::get(0, &bob).unwrap(), OperatorPreferences { - key: zero_key(), + key: bob_operator_ecdsa_key, price_targets: price_targets(MachineKind::Small) } ); @@ -289,7 +296,7 @@ fn update_price_targets() { provider: bob.clone(), blueprint_id: 0, preferences: OperatorPreferences { - key: zero_key(), + key: bob_operator_ecdsa_key, price_targets: price_targets(MachineKind::Small), }, registration_args: Default::default(), @@ -339,7 +346,7 @@ fn unregister_from_blueprint() { assert_ok!(Services::register( RuntimeOrigin::signed(bob.clone()), 0, - OperatorPreferences { key: zero_key(), price_targets: Default::default() }, + OperatorPreferences { key: test_ecdsa_key(), price_targets: Default::default() }, Default::default(), 0, )); @@ -376,7 +383,7 @@ fn request_service() { assert_ok!(Services::register( RuntimeOrigin::signed(bob.clone()), 0, - OperatorPreferences { key: zero_key(), price_targets: Default::default() }, + OperatorPreferences { key: test_ecdsa_key(), price_targets: Default::default() }, Default::default(), 0, )); @@ -384,7 +391,7 @@ fn request_service() { assert_ok!(Services::register( RuntimeOrigin::signed(charlie.clone()), 0, - OperatorPreferences { key: zero_key(), price_targets: Default::default() }, + OperatorPreferences { key: test_ecdsa_key(), price_targets: Default::default() }, Default::default(), 0, )); @@ -392,7 +399,7 @@ fn request_service() { assert_ok!(Services::register( RuntimeOrigin::signed(dave.clone()), 0, - OperatorPreferences { key: zero_key(), price_targets: Default::default() }, + OperatorPreferences { key: test_ecdsa_key(), price_targets: Default::default() }, Default::default(), 0, )); @@ -493,7 +500,7 @@ fn request_service_with_no_assets() { assert_ok!(Services::register( RuntimeOrigin::signed(bob.clone()), 0, - OperatorPreferences { key: zero_key(), price_targets: Default::default() }, + OperatorPreferences { key: test_ecdsa_key(), price_targets: Default::default() }, Default::default(), 0, )); @@ -528,7 +535,7 @@ fn request_service_with_payment_asset() { assert_ok!(Services::register( RuntimeOrigin::signed(bob.clone()), 0, - OperatorPreferences { key: zero_key(), price_targets: Default::default() }, + OperatorPreferences { key: test_ecdsa_key(), price_targets: Default::default() }, Default::default(), 0, )); @@ -579,7 +586,7 @@ fn request_service_with_payment_token() { assert_ok!(Services::register( RuntimeOrigin::signed(bob.clone()), 0, - OperatorPreferences { key: zero_key(), price_targets: Default::default() }, + OperatorPreferences { key: test_ecdsa_key(), price_targets: Default::default() }, Default::default(), 0, )); @@ -632,7 +639,7 @@ fn job_calls() { assert_ok!(Services::register( RuntimeOrigin::signed(bob.clone()), 0, - OperatorPreferences { key: zero_key(), price_targets: Default::default() }, + OperatorPreferences { key: test_ecdsa_key(), price_targets: Default::default() }, Default::default(), 0, )); @@ -640,7 +647,7 @@ fn job_calls() { assert_ok!(Services::register( RuntimeOrigin::signed(charlie.clone()), 0, - OperatorPreferences { key: zero_key(), price_targets: Default::default() }, + OperatorPreferences { key: test_ecdsa_key(), price_targets: Default::default() }, Default::default(), 0, )); @@ -648,7 +655,7 @@ fn job_calls() { assert_ok!(Services::register( RuntimeOrigin::signed(dave.clone()), 0, - OperatorPreferences { key: zero_key(), price_targets: Default::default() }, + OperatorPreferences { key: test_ecdsa_key(), price_targets: Default::default() }, Default::default(), 0, )); @@ -725,7 +732,7 @@ fn job_result() { assert_ok!(Services::register( RuntimeOrigin::signed(bob.clone()), 0, - OperatorPreferences { key: zero_key(), price_targets: Default::default() }, + OperatorPreferences { key: test_ecdsa_key(), price_targets: Default::default() }, Default::default(), 0, )); @@ -733,7 +740,7 @@ fn job_result() { assert_ok!(Services::register( RuntimeOrigin::signed(charlie.clone()), 0, - OperatorPreferences { key: zero_key(), price_targets: Default::default() }, + OperatorPreferences { key: test_ecdsa_key(), price_targets: Default::default() }, Default::default(), 0, )); @@ -741,7 +748,7 @@ fn job_result() { assert_ok!(Services::register( RuntimeOrigin::signed(dave.clone()), 0, - OperatorPreferences { key: zero_key(), price_targets: Default::default() }, + OperatorPreferences { key: test_ecdsa_key(), price_targets: Default::default() }, Default::default(), 0, )); @@ -858,7 +865,7 @@ fn deploy() -> Deployment { assert_ok!(Services::register( RuntimeOrigin::signed(bob.clone()), blueprint_id, - OperatorPreferences { key: zero_key(), price_targets: Default::default() }, + OperatorPreferences { key: test_ecdsa_key(), price_targets: Default::default() }, Default::default(), 0, )); @@ -1143,7 +1150,7 @@ fn hooks() { assert_ok!(Services::register( RuntimeOrigin::signed(bob.clone()), 0, - OperatorPreferences { key: zero_key(), price_targets: Default::default() }, + OperatorPreferences { key: test_ecdsa_key(), price_targets: Default::default() }, Default::default(), 0, )); @@ -1157,7 +1164,7 @@ fn hooks() { assert_ok!(Services::register( RuntimeOrigin::signed(bob.clone()), 0, - OperatorPreferences { key: zero_key(), price_targets: Default::default() }, + OperatorPreferences { key: test_ecdsa_key(), price_targets: Default::default() }, Default::default(), 0, )); diff --git a/precompiles/services/Cargo.toml b/precompiles/services/Cargo.toml index b878f90a..f4b124a5 100644 --- a/precompiles/services/Cargo.toml +++ b/precompiles/services/Cargo.toml @@ -36,6 +36,7 @@ ethers = "2.0" hex = { workspace = true } num_enum = { workspace = true } libsecp256k1 = { workspace = true } +k256 = { workspace = true } serde_json = { workspace = true } smallvec = { workspace = true } sp-keystore = { workspace = true } diff --git a/precompiles/services/src/tests.rs b/precompiles/services/src/tests.rs index 447eae2f..d037d95b 100644 --- a/precompiles/services/src/tests.rs +++ b/precompiles/services/src/tests.rs @@ -4,6 +4,7 @@ use crate::mock::*; use crate::mock_evm::PCall; use crate::mock_evm::PrecompilesValue; use frame_support::assert_ok; +use k256::ecdsa::{SigningKey, VerifyingKey}; use pallet_services::types::ConstraintsOf; use pallet_services::Instances; use pallet_services::Operators; @@ -12,6 +13,7 @@ use parity_scale_codec::Encode; use precompile_utils::prelude::UnboundedBytes; use precompile_utils::testing::*; use sp_core::ecdsa; +use sp_core::Pair; use sp_core::{H160, U256}; use sp_runtime::bounded_vec; use sp_runtime::AccountId32; @@ -24,8 +26,13 @@ use tangle_primitives::services::PriceTargets; use tangle_primitives::services::ServiceMetadata; use tangle_primitives::services::{OperatorPreferences, ServiceBlueprint}; -fn zero_key() -> ecdsa::Public { - ecdsa::Public::from([0; 33]) +fn test_ecdsa_key() -> [u8; 65] { + let (ecdsa_key, _) = ecdsa::Pair::generate(); + let secret = SigningKey::from_slice(&ecdsa_key.seed()) + .expect("Should be able to create a secret key from a seed"); + let verifying_key = VerifyingKey::from(secret); + let public_key = verifying_key.to_encoded_point(false); + public_key.to_bytes().to_vec().try_into().unwrap() } #[allow(dead_code)] @@ -123,7 +130,7 @@ fn test_register_operator() { // Now register operator let preferences_data = OperatorPreferences { - key: zero_key(), + key: test_ecdsa_key(), price_targets: price_targets(MachineKind::Large), } .encode(); @@ -165,7 +172,7 @@ fn test_request_service() { // Now register operator let preferences_data = OperatorPreferences { - key: zero_key(), + key: test_ecdsa_key(), price_targets: price_targets(MachineKind::Large), } .encode(); @@ -238,7 +245,7 @@ fn test_request_service_with_erc20() { // Now register operator let preferences_data = OperatorPreferences { - key: zero_key(), + key: test_ecdsa_key(), price_targets: price_targets(MachineKind::Large), } .encode(); @@ -325,7 +332,7 @@ fn test_request_service_with_asset() { // Now register operator let preferences_data = OperatorPreferences { - key: zero_key(), + key: test_ecdsa_key(), price_targets: price_targets(MachineKind::Large), } .encode(); @@ -404,7 +411,7 @@ fn test_unregister_operator() { .execute_returns(()); let preferences_data = OperatorPreferences { - key: zero_key(), + key: test_ecdsa_key(), price_targets: price_targets(MachineKind::Large), } .encode(); @@ -454,7 +461,7 @@ fn test_terminate_service() { .execute_returns(()); let preferences_data = OperatorPreferences { - key: zero_key(), + key: test_ecdsa_key(), price_targets: price_targets(MachineKind::Large), } .encode(); diff --git a/primitives/src/services/mod.rs b/primitives/src/services/mod.rs index 46574ff6..4be6df53 100644 --- a/primitives/src/services/mod.rs +++ b/primitives/src/services/mod.rs @@ -34,9 +34,10 @@ use educe::Educe; use frame_support::pallet_prelude::*; +use serde::Deserializer; #[cfg(feature = "std")] use serde::{Deserialize, Serialize}; -use sp_core::{ecdsa, RuntimeDebug}; +use sp_core::RuntimeDebug; use sp_runtime::Percent; #[cfg(not(feature = "std"))] @@ -737,14 +738,64 @@ impl PriceTargets { } #[derive(PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo, Copy, Clone, MaxEncodedLen)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct OperatorPreferences { /// The operator ECDSA public key. - pub key: ecdsa::Public, + pub key: [u8; 65], /// The pricing targets for the operator's resources. pub price_targets: PriceTargets, } +#[cfg(feature = "std")] +impl Serialize for OperatorPreferences { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + use serde::ser::SerializeTuple; + let mut tup = serializer.serialize_tuple(2)?; + tup.serialize_element(&self.key[..])?; + tup.serialize_element(&self.price_targets)?; + tup.end() + } +} + +#[cfg(feature = "std")] +struct OperatorPreferencesVisitor; + +#[cfg(feature = "std")] +impl<'de> serde::de::Visitor<'de> for OperatorPreferencesVisitor { + type Value = OperatorPreferences; + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + formatter.write_str("a tuple of 2 elements") + } + + fn visit_seq(self, mut seq: A) -> Result + where + A: serde::de::SeqAccess<'de>, + { + let key = seq + .next_element::>()? + .ok_or_else(|| serde::de::Error::custom("key is missing"))?; + let price_targets = seq + .next_element::()? + .ok_or_else(|| serde::de::Error::custom("price_targets is missing"))?; + let mut key_arr = [0u8; 65]; + key_arr.copy_from_slice(&key); + Ok(OperatorPreferences { key: key_arr, price_targets }) + } +} + +#[cfg(feature = "std")] +impl<'de> Deserialize<'de> for OperatorPreferences { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_tuple(2, OperatorPreferencesVisitor) + } +} + impl OperatorPreferences { /// Returns the ethabi ParamType for OperatorPreferences. pub fn to_ethabi_param_type() -> ethabi::ParamType { @@ -770,7 +821,7 @@ impl OperatorPreferences { pub fn to_ethabi(&self) -> ethabi::Token { ethabi::Token::Tuple(vec![ // operator public key - ethabi::Token::Bytes(self.key.0.to_vec()), + ethabi::Token::Bytes(self.key.to_vec()), // price targets self.price_targets.to_ethabi(), ])