From e37ef098c841157b616ef34ce514e4a6ed0dda9b Mon Sep 17 00:00:00 2001 From: Nutomic Date: Thu, 9 Mar 2023 17:42:20 +0100 Subject: [PATCH] Add bridges list in genesis config (fixes #515) (#520) * Add bridges list in genesis config (fixes #515) * ci fixes --- Cargo.lock | 2 + dkg-test-suite/scripts/submitProposals.ts | 21 ++++--- pallets/bridge-registry/Cargo.toml | 2 + pallets/bridge-registry/src/lib.rs | 13 +++- pallets/bridge-registry/src/mock.rs | 7 ++- pallets/bridge-registry/src/types.rs | 70 ++++++++++++++++++++- pallets/dkg-proposals/src/lib.rs | 4 +- scripts/run-standalone.sh | 6 +- standalone/node/Cargo.toml | 1 + standalone/node/src/chain_spec.rs | 75 ++++++++++------------- standalone/runtime/src/lib.rs | 3 +- 11 files changed, 141 insertions(+), 63 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a034c46fa..75027a5d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2291,6 +2291,7 @@ dependencies = [ "futures", "hex-literal", "jsonrpsee", + "pallet-bridge-registry", "pallet-im-online", "pallet-transaction-payment", "pallet-transaction-payment-rpc", @@ -5648,6 +5649,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "hex", "pallet-balances", "pallet-identity", "parity-scale-codec", diff --git a/dkg-test-suite/scripts/submitProposals.ts b/dkg-test-suite/scripts/submitProposals.ts index a536e13e4..41d581748 100755 --- a/dkg-test-suite/scripts/submitProposals.ts +++ b/dkg-test-suite/scripts/submitProposals.ts @@ -47,7 +47,7 @@ async function run() { sudoAccount.address ); let nonce = accountNonce.toNumber(); - setInterval(async () => { + while(true) { // Create the header const proposalHeader = createHeader(nonce); assert( @@ -84,17 +84,20 @@ async function run() { prop.toU8a() ); // Sign and send the transaction - const unsub = await api.tx.sudo - .sudo(call) - .signAndSend(sudoAccount, (result) => { - if (result.isFinalized || result.isError) { - console.log(result.txHash.toHex(), 'is', result.status.type); - unsub(); + await new Promise(async (resolve, reject) => { + const unsub = await api.tx.sudo + .sudo(call) + .signAndSend(sudoAccount, (result) => { + if (result.isFinalized || result.isInBlock || result.isError) { + unsub(); + console.log(result.txHash.toHex(), "is", result.status.type); + resolve(result.isFinalized); } - }); + }); + }); nonce += 1; - }, 20_000); + }; // a perodic task to print How many proposals that have been submitted, unsigned and signed. // This is just for debugging purpose. diff --git a/pallets/bridge-registry/Cargo.toml b/pallets/bridge-registry/Cargo.toml index 2974512de..fa202150e 100644 --- a/pallets/bridge-registry/Cargo.toml +++ b/pallets/bridge-registry/Cargo.toml @@ -19,6 +19,8 @@ frame-support = { workspace = true } frame-system = { workspace = true } sp-runtime = { workspace = true } sp-std = { workspace = true } +serde = { workspace = true } +hex = { workspace = true } frame-benchmarking = { workspace = true, optional = true } pallet-identity = { workspace = true } diff --git a/pallets/bridge-registry/src/lib.rs b/pallets/bridge-registry/src/lib.rs index 40b18fddf..a1a961350 100644 --- a/pallets/bridge-registry/src/lib.rs +++ b/pallets/bridge-registry/src/lib.rs @@ -47,7 +47,7 @@ pub mod mock; mod tests; mod benchmarking; -mod types; +pub mod types; mod weights; use weights::WeightInfo; @@ -107,12 +107,13 @@ pub mod pallet { #[pallet::genesis_config] pub struct GenesisConfig, I: 'static = ()> { pub phantom: (PhantomData, PhantomData), + pub bridges: Vec>, } #[cfg(feature = "std")] impl, I: 'static> Default for GenesisConfig { fn default() -> Self { - Self { phantom: Default::default() } + Self { phantom: Default::default(), bridges: Default::default() } } } @@ -120,6 +121,14 @@ pub mod pallet { impl, I: 'static> GenesisBuild for GenesisConfig { fn build(&self) { NextBridgeIndex::::put(T::BridgeIndex::one()); + for bridge in &self.bridges { + let idx: T::BridgeIndex = NextBridgeIndex::::get(); + Bridges::::insert(idx, bridge); + NextBridgeIndex::::put(idx + T::BridgeIndex::one()); + for rid in &bridge.resource_ids { + ResourceToBridgeIndex::::set(rid, Some(idx)); + } + } } } diff --git a/pallets/bridge-registry/src/mock.rs b/pallets/bridge-registry/src/mock.rs index 053a03440..69d9f6cb3 100644 --- a/pallets/bridge-registry/src/mock.rs +++ b/pallets/bridge-registry/src/mock.rs @@ -102,8 +102,11 @@ pub fn new_test_ext() -> sp_io::TestExternalities { ], } .assimilate_storage(&mut storage); - let _ = pallet_bridge_registry::GenesisConfig:: { phantom: Default::default() } - .assimilate_storage(&mut storage); + let _ = pallet_bridge_registry::GenesisConfig:: { + phantom: Default::default(), + bridges: vec![], + } + .assimilate_storage(&mut storage); storage.into() } diff --git a/pallets/bridge-registry/src/types.rs b/pallets/bridge-registry/src/types.rs index d8bca851c..f4af0a60c 100644 --- a/pallets/bridge-registry/src/types.rs +++ b/pallets/bridge-registry/src/types.rs @@ -40,19 +40,82 @@ use sp_std::prelude::*; RuntimeDebugNoBound, TypeInfo, )] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] #[codec(mel_bound())] #[scale_info(skip_type_params(FieldLimit))] pub struct BridgeInfo> { /// Additional fields of the metadata that are not catered for with the struct's explicit /// fields. - pub additional: BoundedVec<(Data, Data), FieldLimit>, + #[cfg_attr(feature = "std", serde(bound = ""))] + pub additional: BoundedVec<(SerdeData, SerdeData), FieldLimit>, /// A reasonable display name for the bridge. This should be whatever it is /// that it is typically known as and should not be confusable with other entities, given /// reasonable context. /// /// Stored as UTF-8. - pub display: Data, + pub display: SerdeData, +} + +#[derive( + Clone, + Eq, + PartialEq, + frame_support::RuntimeDebug, + MaxEncodedLen, + Encode, + TypeInfo, + Decode, + Default, +)] +pub struct SerdeData(Data); + +#[cfg(feature = "std")] +mod serde_ { + use super::*; + use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer}; + struct DataVisitor; + use std::{fmt::Formatter, str::FromStr}; + + impl FromStr for SerdeData { + type Err = (); + + fn from_str(s: &str) -> Result { + Ok(SerdeData(Data::Raw(s.as_bytes().to_vec().try_into().unwrap()))) + } + } + + impl<'de> Visitor<'de> for DataVisitor { + type Value = SerdeData; + + fn expecting(&self, formatter: &mut Formatter) -> core::fmt::Result { + formatter.write_str("a hex string with at most 32 bytes") + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + Ok(SerdeData(Data::Raw(hex::decode(v).unwrap().try_into().unwrap()))) + } + } + impl<'de> Deserialize<'de> for SerdeData { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_str(DataVisitor) + } + } + + impl Serialize for SerdeData { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&hex::encode(self.0.encode())) + } + } } /// Information concerning the identity of the controller of an account. @@ -62,13 +125,16 @@ pub struct BridgeInfo> { #[derive( CloneNoBound, Encode, Eq, MaxEncodedLen, PartialEqNoBound, RuntimeDebugNoBound, TypeInfo, )] +#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))] #[codec(mel_bound())] #[scale_info(skip_type_params(MaxResources, MaxAdditionalFields))] pub struct BridgeMetadata, MaxAdditionalFields: Get> { /// A list of resource IDs for the bridge + #[cfg_attr(feature = "std", serde(bound = ""))] pub resource_ids: BoundedVec, /// Auxilliary information on the bridge. + #[cfg_attr(feature = "std", serde(bound = ""))] pub info: BridgeInfo, } diff --git a/pallets/dkg-proposals/src/lib.rs b/pallets/dkg-proposals/src/lib.rs index a9ea51cd8..b0b97b24a 100644 --- a/pallets/dkg-proposals/src/lib.rs +++ b/pallets/dkg-proposals/src/lib.rs @@ -318,7 +318,7 @@ pub mod pallet { pub struct GenesisConfig { /// Typed ChainId (chain type, chain id) pub initial_chain_ids: Vec<[u8; 6]>, - pub initial_r_ids: Vec<([u8; 32], Vec)>, + pub initial_r_ids: Vec<(ResourceId, Vec)>, pub initial_proposers: Vec, } @@ -345,7 +345,7 @@ pub mod pallet { ChainNonces::::insert(chain_id, ProposalNonce::from(0)); } for (r_id, r_data) in self.initial_r_ids.iter() { - Resources::::insert(ResourceId::from(*r_id), r_data.clone()); + Resources::::insert(r_id, r_data.clone()); } for proposer in self.initial_proposers.iter() { diff --git a/scripts/run-standalone.sh b/scripts/run-standalone.sh index 7529aa020..c0a6bac36 100755 --- a/scripts/run-standalone.sh +++ b/scripts/run-standalone.sh @@ -31,17 +31,17 @@ cd "$PROJECT_ROOT" echo "*** Start Webb DKG Node ***" # Alice -./target/release/dkg-standalone-node --base-path=./tmp/alice --chain local -lerror --alice \ +cargo run --bin dkg-standalone-node --release -- --base-path=./tmp/alice --chain local -lerror --alice \ --rpc-cors all --ws-external \ --port 30304 \ --ws-port 9944 & # Bob -./target/release/dkg-standalone-node --base-path=./tmp/bob --chain local -lerror --bob \ +cargo run --bin dkg-standalone-node --release -- --base-path=./tmp/bob --chain local -lerror --bob \ --rpc-cors all --ws-external \ --port 30305 \ --ws-port 9945 & # Charlie -./target/release/dkg-standalone-node --base-path=./tmp/charlie --chain local -linfo --charlie \ +cargo run --bin dkg-standalone-node --release -- --base-path=./tmp/charlie --chain local -linfo --charlie \ --rpc-cors all --ws-external \ --ws-port 9948 \ --port 30308 \ diff --git a/standalone/node/Cargo.toml b/standalone/node/Cargo.toml index 95a2836b7..e6badf1e3 100644 --- a/standalone/node/Cargo.toml +++ b/standalone/node/Cargo.toml @@ -54,6 +54,7 @@ substrate-frame-rpc-system = { workspace = true } frame-system = { workspace = true } pallet-transaction-payment-rpc = { workspace = true } pallet-transaction-payment = { workspace = true } +pallet-bridge-registry = { workspace = true } # These dependencies are used for runtime benchmarking frame-benchmarking = { workspace = true } diff --git a/standalone/node/src/chain_spec.rs b/standalone/node/src/chain_spec.rs index 0811af97e..01616187f 100644 --- a/standalone/node/src/chain_spec.rs +++ b/standalone/node/src/chain_spec.rs @@ -12,23 +12,38 @@ // See the License for the specific language governing permissions and // limitations under the License. +use dkg_primitives::ResourceId; use dkg_standalone_runtime::{ constants::currency::{Balance, DOLLARS}, AccountId, BalancesConfig, DKGConfig, DKGId, DKGProposalsConfig, GenesisConfig, ImOnlineConfig, - MaxNominations, Perbill, ResourceId, SessionConfig, Signature, StakerStatus, StakingConfig, - SudoConfig, SystemConfig, WASM_BINARY, + MaxNominations, Perbill, SessionConfig, Signature, StakerStatus, StakingConfig, SudoConfig, + SystemConfig, WASM_BINARY, }; use hex_literal::hex; +use pallet_bridge_registry::types::{BridgeInfo, BridgeMetadata, SerdeData}; use pallet_im_online::sr25519::AuthorityId as ImOnlineId; use sc_service::ChainType; use sp_consensus_aura::sr25519::AuthorityId as AuraId; -use sp_core::{sr25519, Pair, Public}; +use sp_core::{bounded_vec, sr25519, Pair, Public}; use sp_finality_grandpa::AuthorityId as GrandpaId; use sp_runtime::traits::{IdentifyAccount, Verify}; +use std::str::FromStr; // The URL for the telemetry server. // const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/"; +/// Hermes (Evm, 5001) +const CHAIN_ID_HERMES: [u8; 6] = hex_literal::hex!("010000001389"); +/// Athena (Evm, 5002) +const CHAIN_ID_ATHENA: [u8; 6] = hex_literal::hex!("01000000138a"); + +const RESOURCE_ID_HERMES_ATHENA: ResourceId = ResourceId(hex_literal::hex!( + "0000000000000000e69a847cd5bc0c9480ada0b339d7f0a8cac2b6670000138a" +)); +const RESOURCE_ID_ATHENA_HERMES: ResourceId = ResourceId(hex_literal::hex!( + "000000000000d30c8839c1145609e564b986f667b273ddcb8496010000001389" +)); + /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type. pub type ChainSpec = sc_service::GenericChainSpec; @@ -79,7 +94,6 @@ fn dkg_session_keys( pub fn development_config() -> Result { let wasm_binary = WASM_BINARY.ok_or_else(|| "Development wasm not available".to_string())?; - Ok(ChainSpec::from_genesis( // Name "Development", @@ -117,26 +131,11 @@ pub fn development_config() -> Result { get_account_id_from_seed::("Ferdie//stash"), ], // Initial Chain Ids - vec![ - hex_literal::hex!("010000001389"), // Hermis (Evm, 5001) - hex_literal::hex!("01000000138a"), // Athena (Evm, 5002) - ], + vec![CHAIN_ID_HERMES, CHAIN_ID_ATHENA], // Initial resource Ids vec![ - // Resource ID for Chain Hermis => Athena - ( - hex_literal::hex!( - "000000000000e69a847cd5bc0c9480ada0b339d7f0a8cac2b66701000000138a" - ), - Default::default(), - ), - // Resource ID for Chain Athena => Hermis - ( - hex_literal::hex!( - "000000000000d30c8839c1145609e564b986f667b273ddcb8496010000001389" - ), - Default::default(), - ), + (RESOURCE_ID_HERMES_ATHENA, Default::default()), + (RESOURCE_ID_ATHENA_HERMES, Default::default()), ], // Initial proposers vec![ @@ -204,26 +203,11 @@ pub fn local_testnet_config() -> Result { })) .collect(), // Initial Chain Ids - vec![ - hex_literal::hex!("010000001389"), // Hermis (Evm, 5001) - hex_literal::hex!("01000000138a"), // Athena (Evm, 5002) - ], + vec![CHAIN_ID_HERMES, CHAIN_ID_ATHENA], // Initial resource Ids vec![ - // Resource ID for Chain Hermis => Athena - ( - hex_literal::hex!( - "0000000000000000e69a847cd5bc0c9480ada0b339d7f0a8cac2b6670000138a" - ), - Default::default(), - ), - // Resource ID for Chain Athena => Hermis - ( - hex_literal::hex!( - "0000000000000000d30c8839c1145609e564b986f667b273ddcb849600001389" - ), - Default::default(), - ), + (RESOURCE_ID_HERMES_ATHENA, Default::default()), + (RESOURCE_ID_ATHENA_HERMES, Default::default()), ], // Initial proposers vec![ @@ -380,7 +364,16 @@ fn testnet_genesis( authority_ids: initial_authorities.iter().map(|(x, ..)| x.clone()).collect::<_>(), }, dkg_proposals: DKGProposalsConfig { initial_chain_ids, initial_r_ids, initial_proposers }, - bridge_registry: Default::default(), + bridge_registry: pallet_bridge_registry::pallet::GenesisConfig { + bridges: bounded_vec![BridgeMetadata { + resource_ids: bounded_vec![RESOURCE_ID_HERMES_ATHENA, RESOURCE_ID_ATHENA_HERMES], + info: BridgeInfo { + additional: Default::default(), + display: SerdeData::from_str("hermes-athena").unwrap() + } + }], + ..Default::default() + }, im_online: ImOnlineConfig { keys: vec![] }, } } diff --git a/standalone/runtime/src/lib.rs b/standalone/runtime/src/lib.rs index fd8d9915b..aa9c50500 100644 --- a/standalone/runtime/src/lib.rs +++ b/standalone/runtime/src/lib.rs @@ -90,8 +90,7 @@ pub type Signature = MultiSignature; /// Some way of identifying an account on the chain. We intentionally make it equivalent /// to the public key of our transaction signing scheme. pub type AccountId = <::Signer as IdentifyAccount>::AccountId; -/// Resource ID type -pub type ResourceId = [u8; 32]; + /// Reputation type pub type Reputation = u128;