diff --git a/Cargo.lock b/Cargo.lock index 639c6e545..f89519d5d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -166,9 +166,9 @@ dependencies = [ [[package]] name = "async-global-executor" -version = "1.3.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fefeb39da249f4c33af940b779a56723ce45809ef5c54dad84bb538d4ffb6d9e" +checksum = "124ac8c265e407641c3362b8f4d39cdb4e243885b71eef087be27199790f5a3a" dependencies = [ "async-executor", "async-io", @@ -247,9 +247,9 @@ dependencies = [ [[package]] name = "async-task" -version = "4.0.2" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ab27c1aa62945039e44edaeee1dc23c74cc0c303dd5fe0fb462a184f1c3a518" +checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" [[package]] name = "async-tls" @@ -463,9 +463,9 @@ checksum = "476e9cd489f9e121e02ffa6014a8ef220ecb15c05ed23fc34cca13925dc283fb" [[package]] name = "bstr" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31accafdb70df7871592c058eca3985b71104e15ac32f64706022c58867da931" +checksum = "473fc6b38233f9af7baa94fb5852dca389e3d95b8e21c8e3719301462c5d9faf" dependencies = [ "memchr", ] @@ -683,7 +683,7 @@ dependencies = [ [[package]] name = "darwinia-bridge-primitives" version = "0.0.10" -source = "git+https://github.com/darwinia-network/bridge-primitives.git?branch=bump#604b09c38275bdc3e0695517b9b7b575a92ca87c" +source = "git+https://github.com/darwinia-network/bridge-primitives.git#a1c7d09f96e1c1cd1038af5ed980fa8d42ad9048" dependencies = [ "frame-support", "pallet-im-online", @@ -698,7 +698,7 @@ dependencies = [ [[package]] name = "darwinia-bridger" -version = "0.0.2" +version = "0.0.3" dependencies = [ "async-trait", "darwinia-bridge-primitives", @@ -802,9 +802,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c53dc3a653e0f64081026e4bf048d48fec9fce90c66e8326ca7292df0ff2d82" +checksum = "d55796afa1b20c2945ca8eabfc421839f2b766619209f1ede813cf2484f31804" [[package]] name = "ed25519" @@ -1262,7 +1262,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project", + "pin-project 0.4.27", "pin-utils", "proc-macro-hack", "proc-macro-nested", @@ -1515,7 +1515,7 @@ dependencies = [ "httparse", "httpdate", "itoa", - "pin-project", + "pin-project 0.4.27", "socket2", "tokio", "tower-service", @@ -1759,7 +1759,7 @@ dependencies = [ "lazy_static", "log", "parking_lot 0.10.2", - "pin-project", + "pin-project 0.4.27", "rand 0.7.3", "serde", "serde_json", @@ -1853,7 +1853,7 @@ dependencies = [ "multihash", "parity-multiaddr", "parking_lot 0.10.2", - "pin-project", + "pin-project 0.4.27", "smallvec 1.4.2", "wasm-timer", ] @@ -1878,7 +1878,7 @@ dependencies = [ "multistream-select", "parity-multiaddr", "parking_lot 0.10.2", - "pin-project", + "pin-project 0.4.27", "prost", "prost-build", "rand 0.7.3", @@ -2159,16 +2159,16 @@ checksum = "1255076139a83bb467426e7f8d0134968a8118844faa755985e077cf31850333" [[package]] name = "multistream-select" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9157e87afbc2ef0d84cc0345423d715f445edde00141c93721c162de35a05e5" +checksum = "fa0075eaaf3102b344f122e1a2e1cedf0f3d388c5fb27a0e31eb09c1151fbbd1" dependencies = [ "bytes", "futures 0.3.6", "log", - "pin-project", + "pin-project 1.0.1", "smallvec 1.4.2", - "unsigned-varint 0.4.0", + "unsigned-varint 0.5.1", ] [[package]] @@ -2471,9 +2471,9 @@ dependencies = [ [[package]] name = "parity-multiaddr" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2165a93382a93de55868dcbfa11e4a8f99676a9164eee6a2b4a9479ad319c257" +checksum = "4c7ad66970bbab360c97179b60906e2dc4aef1f7fca8ab4e5c5db8c97b16814a" dependencies = [ "arrayref", "bs58", @@ -2483,7 +2483,7 @@ dependencies = [ "percent-encoding 2.1.0", "serde", "static_assertions", - "unsigned-varint 0.4.0", + "unsigned-varint 0.5.1", "url 2.1.1", ] @@ -2683,7 +2683,16 @@ version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ffbc8e94b38ea3d2d8ba92aea2983b503cd75d0888d75b86bb37970b5698e15" dependencies = [ - "pin-project-internal", + "pin-project-internal 0.4.27", +] + +[[package]] +name = "pin-project" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee41d838744f60d959d7074e3afb6b35c7456d0f61cad38a24e35e6553f73841" +dependencies = [ + "pin-project-internal 1.0.1", ] [[package]] @@ -2697,6 +2706,17 @@ dependencies = [ "syn", ] +[[package]] +name = "pin-project-internal" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81a4ffa594b66bff340084d4081df649a7dc049ac8d7fc458d8e628bfbbb2f86" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "pin-project-lite" version = "0.1.10" @@ -2717,9 +2737,9 @@ checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" [[package]] name = "polling" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab773feb154f12c49ffcfd66ab8bdcf9a1843f950db48b0d8be9d4393783b058" +checksum = "a2a7bc6b2a29e632e45451c941832803a18cce6781db04de8a04696cdca8bde4" dependencies = [ "cfg-if 0.1.10", "libc", @@ -3265,7 +3285,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4da5fcb054c46f5a5dff833b129285a93d3f0179531735e6c866e8cc307d2020" dependencies = [ "futures 0.3.6", - "pin-project", + "pin-project 0.4.27", "static_assertions", ] @@ -3411,18 +3431,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5" +checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8" +checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e" dependencies = [ "proc-macro2", "quote", @@ -4363,9 +4383,9 @@ checksum = "343f3f510c2915908f155e94f17220b19ccfacf2a64a2a5d8004f2c3e311e7fd" [[package]] name = "syn" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e03e57e4fcbfe7749842d53e24ccb9aa12b7252dbe5e91d2acad31834c8b8fdd" +checksum = "ea9c5432ff16d6152371f808fb5a871cd67368171b09bb21b43df8e4a47a3556" dependencies = [ "proc-macro2", "quote", @@ -4676,11 +4696,13 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "twox-hash" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bfd5b7557925ce778ff9b9ef90e3ade34c524b5ff10e239c69a42d546d2af56" +checksum = "04f8ab788026715fa63b31960869617cba39117e520eb415b0139543e325ab59" dependencies = [ + "cfg-if 0.1.10", "rand 0.7.3", + "static_assertions", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 3d330b1ac..37ce84666 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ features = ["full"] package = "darwinia-bridge-primitives" version = "0.0.10" git = "https://github.com/darwinia-network/bridge-primitives.git" -# branch = "bump" +# branch = "sudo" # path = "../bridge-primitives" features = ["runtime"] diff --git a/src/api/darwinia.rs b/src/api/darwinia.rs index 3bb59679d..3b96ccb02 100644 --- a/src/api/darwinia.rs +++ b/src/api/darwinia.rs @@ -1,27 +1,51 @@ //! Darwinia API use crate::{pool::EthereumTransaction, result::Result, Config}; +use core::marker::PhantomData; use primitives::{ chain::eth::{EthereumReceiptProofThing, HeaderStuff, RedeemFor}, - frame::ethereum::{ - backing::{RedeemCallExt, VerifiedProofStoreExt}, - game::{EthereumRelayerGame, PendingHeadersStoreExt, ProposalsStoreExt}, - relay::{ConfirmedBlockNumbersStoreExt, SubmitProposalCallExt}, + frame::{ + collective::{ExecuteCallExt, MembersStoreExt}, + ethereum::{ + backing::{RedeemCallExt, VerifiedProofStoreExt}, + game::{EthereumRelayerGame, PendingHeadersStoreExt, ProposalsStoreExt}, + relay::{ + ApprovePendingHeader, ConfirmedBlockNumbersStoreExt, RejectPendingHeader, + SubmitProposalCallExt, + }, + }, + sudo::{KeyStoreExt, SudoCallExt}, }, runtime::DarwiniaRuntime, }; use sp_keyring::sr25519::sr25519::Pair; -use substrate_subxt::{sp_core::Pair as PairTrait, Client, ClientBuilder, PairSigner}; +use substrate_subxt::{ + sp_core::{Encode, Pair as PairTrait}, + Client, ClientBuilder, PairSigner, +}; use web3::types::H256; // Types type PendingHeader = ::PendingHeader; type RelayProposal = ::RelayProposal; +/// Account Role +#[derive(PartialEq, Eq)] +pub enum Role { + /// Sudo Account + Sudo, + /// Council Member + Council, + /// Normal Account + Normal, +} + /// Dawrinia API pub struct Darwinia { client: Client, /// Keyring signer pub signer: PairSigner, + /// Account Role + pub role: Role, } impl Darwinia { @@ -34,7 +58,55 @@ impl Darwinia { .build() .await?; - Ok(Darwinia { client, signer }) + let pk = signer.signer().public().to_string(); + let sudo = client.key(None).await?.to_string(); + let council = client.members(None).await?; + + Ok(Darwinia { + client, + signer, + role: if sudo == pk { + Role::Sudo + } else if council.iter().any(|cpk| cpk.to_string() == pk) { + Role::Council + } else { + Role::Normal + }, + }) + } + + /// Approve pending header + pub async fn approve_pending_header(&self, pending: u64) -> Result { + let ex = self.client.encode(ApprovePendingHeader { + pending, + _runtime: PhantomData::default(), + })?; + Ok(match self.role { + Role::Sudo => self.client.sudo(&self.signer, &ex).await?, + Role::Council => { + self.client + .execute(&self.signer, &ex, ex.size_hint() as u32) + .await? + } + Role::Normal => H256::from([0; 32]), + }) + } + + /// Reject pending header + pub async fn reject_pending_header(&self, pending: u64) -> Result { + let ex = self.client.encode(RejectPendingHeader { + pending, + _runtime: PhantomData::default(), + })?; + Ok(match self.role { + Role::Sudo => self.client.sudo(&self.signer, &ex).await?, + Role::Council => { + self.client + .execute(&self.signer, &ex, ex.size_hint() as u32) + .await? + } + Role::Normal => H256::from([0; 32]), + }) } /// Get relay proposals diff --git a/src/api/mod.rs b/src/api/mod.rs index 75963da9d..18a7cb31a 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -2,4 +2,7 @@ mod darwinia; mod shadow; -pub use self::{darwinia::Darwinia, shadow::Shadow}; +pub use self::{ + darwinia::{Darwinia, Role}, + shadow::Shadow, +}; diff --git a/src/config.rs b/src/config.rs index a90e24e35..53b3942fc 100644 --- a/src/config.rs +++ b/src/config.rs @@ -47,8 +47,10 @@ pub struct Step { pub ethereum: u64, /// Relay Step pub relay: u64, - /// Relay Step + /// Redeem Step pub redeem: u64, + /// Guard Step + pub guard: u64, } /// Bridger Config @@ -110,6 +112,7 @@ impl Default for Config { ethereum: 30, relay: 60, redeem: 90, + guard: 30, }, } } diff --git a/src/listener.rs b/src/listener.rs index 01a38b8c7..cc1950a15 100644 --- a/src/listener.rs +++ b/src/listener.rs @@ -3,7 +3,7 @@ use crate::{ api::{Darwinia, Shadow}, pool::Pool, result::{Error, Result}, - service::{EthereumService, RedeemService, RelayService, Service}, + service::{EthereumService, GuardService, RedeemService, RelayService, Service}, Config, }; use std::sync::{Arc, Mutex}; @@ -64,12 +64,14 @@ impl Listener { // 2. Relay Listener let ethereum = >::new_http(&config)?; let relay = RelayService::new(&config, shadow.clone(), darwinia.clone()); - let redeem = RedeemService::new(&config, shadow, darwinia); + let redeem = RedeemService::new(&config, shadow.clone(), darwinia.clone()); + let guard = GuardService::new(&config, shadow, darwinia); // Register l.register(ethereum)?; l.register(relay)?; l.register(redeem)?; + l.register(guard)?; Ok(l) } } diff --git a/src/service/darwinia.rs b/src/service/darwinia.rs deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/service/ethereum.rs b/src/service/ethereum.rs index daf955334..b9c808016 100644 --- a/src/service/ethereum.rs +++ b/src/service/ethereum.rs @@ -18,7 +18,7 @@ use web3::{ }; /// Attributes -const SERVICE_NAME: &str = "ethereum"; +const SERVICE_NAME: &str = "ETHEREUM"; /// Darwinia contract addresses pub struct ContractAddress { diff --git a/src/service/guard.rs b/src/service/guard.rs index e69de29bb..c7284bdad 100644 --- a/src/service/guard.rs +++ b/src/service/guard.rs @@ -0,0 +1,70 @@ +//! Guard Service +use crate::{ + api::{Darwinia, Role, Shadow}, + config::Config, + result::Result as BridgerResult, + service::Service, + Pool, +}; +use async_trait::async_trait; +use std::{ + sync::{Arc, Mutex}, + time::Duration, +}; + +/// Attributes +const SERVICE_NAME: &str = "GUARD"; + +/// Redeem Service +pub struct GuardService { + step: u64, + /// Shadow API + pub shadow: Arc, + /// Dawrinia API + pub darwinia: Arc, +} + +impl GuardService { + /// New redeem service + pub fn new(config: &Config, shadow: Arc, darwinia: Arc) -> GuardService { + GuardService { + darwinia, + shadow, + step: config.step.redeem, + } + } +} + +#[async_trait(?Send)] +impl Service for GuardService { + fn name<'e>(&self) -> &'e str { + SERVICE_NAME + } + + async fn run(&mut self, _: Arc>) -> BridgerResult<()> { + if self.darwinia.role == Role::Normal { + return Ok(()); + } + + loop { + trace!("Checking pending headers..."); + let pending_headers = self.darwinia.pending_headers().await?; + for header in pending_headers { + let ht = self + .shadow + .header_thing(header.2.header.number as usize) + .await?; + + if header.2 == ht { + info!("Approved header {}", header.1); + self.darwinia.approve_pending_header(header.1).await + } else { + info!("Rejected header {}", header.1); + self.darwinia.reject_pending_header(header.1).await + }?; + } + + tokio::time::delay_for(Duration::from_secs(self.step)).await; + } + } +} diff --git a/src/service/mod.rs b/src/service/mod.rs index d06cfb9e4..5a01696da 100644 --- a/src/service/mod.rs +++ b/src/service/mod.rs @@ -1,13 +1,17 @@ -//! Bridger services +//! Bridger Services use crate::{pool::Pool, result::Result}; use async_trait::async_trait; use std::sync::{Arc, Mutex}; mod ethereum; +mod guard; mod redeem; mod relay; +mod subscribe; -pub use self::{ethereum::EthereumService, redeem::RedeemService, relay::RelayService}; +pub use self::{ + ethereum::EthereumService, guard::GuardService, redeem::RedeemService, relay::RelayService, +}; /// Bridge service #[async_trait(?Send)] diff --git a/src/service/redeem.rs b/src/service/redeem.rs index 49bb6428f..8cdf5d89e 100644 --- a/src/service/redeem.rs +++ b/src/service/redeem.rs @@ -15,7 +15,7 @@ use std::{ }; /// Attributes -const SERVICE_NAME: &str = "redeem"; +const SERVICE_NAME: &str = "REDEEM"; /// Redeem Service pub struct RedeemService { diff --git a/src/service/relay.rs b/src/service/relay.rs index 483a1ce22..2af53e0f2 100644 --- a/src/service/relay.rs +++ b/src/service/relay.rs @@ -13,7 +13,7 @@ use std::{ }; /// Attributes -const SERVICE_NAME: &str = "relay"; +const SERVICE_NAME: &str = "RELAY"; /// Relay Service pub struct RelayService { diff --git a/src/service/subscribe/mod.rs b/src/service/subscribe/mod.rs new file mode 100644 index 000000000..030378b3d --- /dev/null +++ b/src/service/subscribe/mod.rs @@ -0,0 +1 @@ +//! Darwinia Subscribe