diff --git a/crates/proposal-signing-backends/src/dkg.rs b/crates/proposal-signing-backends/src/dkg.rs index f1639f07d..f85362292 100644 --- a/crates/proposal-signing-backends/src/dkg.rs +++ b/crates/proposal-signing-backends/src/dkg.rs @@ -14,34 +14,25 @@ use webb::substrate::subxt::dynamic::Value; use webb_relayer_store::{QueueStore, SledStore}; use webb_relayer_store::sled::SledQueueKey; use webb_relayer_types::dynamic_payload::WebbDynamicTxPayload; -use webb::substrate::subxt::tx::{PairSigner}; +use webb::substrate::subxt::tx::PairSigner; use webb::substrate::dkg_runtime::api::runtime_types::sp_core::bounded::bounded_vec::BoundedVec; type DkgConfig = PolkadotConfig; type DkgClient = OnlineClient; /// A ProposalSigningBackend that uses the DKG System for Signing Proposals. +#[derive(typed_builder::TypedBuilder)] pub struct DkgProposalSigningBackend { + #[builder(setter(into))] pub client: DkgClient, pub pair: PairSigner, - pub typed_chain_id: webb_proposals::TypedChainId, /// Something that implements the QueueStore trait. + #[builder(setter(into))] store: Arc, -} - -impl DkgProposalSigningBackend { - pub fn new( - client: OnlineClient, - pair: PairSigner, - typed_chain_id: webb_proposals::TypedChainId, - store: Arc, - ) -> Self { - Self { - client, - pair, - typed_chain_id, - store, - } - } + /// The chain id of the chain that this backend is running on. + /// + /// This used as the source chain id for the proposals. + #[builder(setter(into))] + src_chain_id: webb_proposals::TypedChainId, } //AnchorUpdateProposal for evm @@ -53,9 +44,8 @@ impl super::ProposalSigningBackend for DkgProposalSigningBackend { ) -> webb_relayer_utils::Result { let header = proposal.header(); let resource_id = header.resource_id(); - let src_chain_id = - webb_proposals_typed_chain_converter(self.typed_chain_id); + webb_proposals_typed_chain_converter(self.src_chain_id); let chain_nonce_addrs = RuntimeApi::storage() .dkg_proposals() .chain_nonces(&src_chain_id); @@ -97,33 +87,61 @@ impl super::ProposalSigningBackend for DkgProposalSigningBackend { proposal: &(impl ProposalTrait + Sync + Send + 'static), _metrics: Arc>, ) -> webb_relayer_utils::Result<()> { + let my_chain_id_addr = + RuntimeApi::constants().dkg_proposals().chain_identifier(); + let my_chain_id = self.client.constants().at(&my_chain_id_addr)?; + let my_chain_id = match my_chain_id { + TypedChainId::Substrate(chain_id) => chain_id, + TypedChainId::PolkadotParachain(chain_id) => chain_id, + TypedChainId::KusamaParachain(chain_id) => chain_id, + _ => return Err(webb_relayer_utils::Error::Generic( + "dkg proposal signing backend only supports substrate chains", + )), + }; let tx_api = RuntimeApi::tx().dkg_proposals(); let resource_id = proposal.header().resource_id(); let nonce = proposal.header().nonce(); let src_chain_id = - webb_proposals_typed_chain_converter(self.typed_chain_id); - let nonce = Nonce::decode(&mut nonce.encode().as_slice())?; + webb_proposals_typed_chain_converter(self.src_chain_id); tracing::debug!( - nonce = %hex::encode(nonce.encode()), + ?nonce, resource_id = %hex::encode(resource_id.into_bytes()), - src_chain_id = ?self.typed_chain_id, + src_chain_id = ?self.src_chain_id, proposal = %hex::encode(proposal.to_vec()), "sending proposal to DKG runtime" ); + let nonce = Nonce::decode(&mut nonce.encode().as_slice())?; let xt = tx_api.acknowledge_proposal( nonce.clone(), src_chain_id, ResourceId(resource_id.into_bytes()), BoundedVec(proposal.to_vec()), ); + let src_chain_id = match self.src_chain_id { + webb_proposals::TypedChainId::Evm(chain_id) => { + Value::unnamed_variant( + "Evm", + [Value::u128(u128::from(chain_id))], + ) + } + webb_proposals::TypedChainId::Substrate(chain_id) => { + Value::unnamed_variant( + "Substrate", + [Value::u128(u128::from(chain_id))], + ) + } + _ => return Err(webb_relayer_utils::Error::Generic( + "dkg proposal signing backend only supports EVM and Substrate chains", + )), + }; // webb dynamic payload - let execute_proposal_tx = WebbDynamicTxPayload { + let acknowledge_proposal_tx = WebbDynamicTxPayload { pallet_name: Cow::Borrowed("DKGProposals"), call_name: Cow::Borrowed("acknowledge_proposal"), fields: vec![ Value::u128(u128::from(nonce.0)), - Value::u128(u128::from(self.typed_chain_id.chain_id())), + src_chain_id, Value::from_bytes( ResourceId(resource_id.into_bytes()).encode(), ), @@ -132,14 +150,14 @@ impl super::ProposalSigningBackend for DkgProposalSigningBackend { }; let data_hash = utils::keccak256(xt.call_data().encode()); let tx_key = SledQueueKey::from_substrate_with_custom_key( - self.typed_chain_id.underlying_chain_id(), + my_chain_id, make_acknowledge_proposal_key(data_hash), ); // Enqueue WebbDynamicTxPayload in protocol-substrate transaction queue QueueStore::::enqueue_item( &self.store, tx_key, - execute_proposal_tx, + acknowledge_proposal_tx, )?; Ok(()) diff --git a/crates/tx-queue/src/substrate/substrate_tx_queue.rs b/crates/tx-queue/src/substrate/substrate_tx_queue.rs index d25b72155..37e2cedd7 100644 --- a/crates/tx-queue/src/substrate/substrate_tx_queue.rs +++ b/crates/tx-queue/src/substrate/substrate_tx_queue.rs @@ -16,6 +16,7 @@ use futures::StreamExt; use futures::TryFutureExt; use rand::Rng; use webb::substrate::subxt::config::ExtrinsicParams; +use webb::substrate::subxt::tx::TxPayload; use webb_relayer_context::RelayerContext; use webb_relayer_store::sled::SledQueueKey; use webb_relayer_store::QueueStore; @@ -43,6 +44,7 @@ where store: Arc, _marker: PhantomData<&'a ()>, } + impl<'a, S> SubstrateTxQueue<'a, S> where S: QueueStore, Key = SledQueueKey>, @@ -123,16 +125,31 @@ where payload.call_name, payload.fields, ); - let signed_extrinsic = client + let signed_extrinsic_result = client .tx() .create_signed( &dynamic_tx_payload, &signer, Default::default(), ) - .map_err(Into::into) + .map_err(webb_relayer_utils::Error::from) .map_err(backoff::Error::transient) - .await?; + .await; + let signed_extrinsic = match signed_extrinsic_result { + Ok(signed_extrinsic) => signed_extrinsic, + Err(err) => { + tracing::event!( + target: webb_relayer_utils::probe::TARGET, + tracing::Level::ERROR, + kind = %webb_relayer_utils::probe::Kind::TxQueue, + ty = "SUBSTRATE", + chain_id = %chain_id, + errored = true, + error = %err, + ); + continue; + } + }; // dry run test let dry_run_outcome = signed_extrinsic.dry_run(None).await; match dry_run_outcome { diff --git a/services/webb-relayer/src/service/mod.rs b/services/webb-relayer/src/service/mod.rs index 2aa4901e3..e273683c7 100644 --- a/services/webb-relayer/src/service/mod.rs +++ b/services/webb-relayer/src/service/mod.rs @@ -133,12 +133,12 @@ pub async fn make_proposal_signing_backend( ) .await?; let pair = ctx.substrate_wallet(&c.chain_id.to_string()).await?; - let backend = DkgProposalSigningBackend::new( - dkg_client, - subxt::tx::PairSigner::new(pair), - typed_chain_id, - store.clone(), - ); + let backend = DkgProposalSigningBackend::builder() + .client(dkg_client) + .pair(subxt::tx::PairSigner::new(pair)) + .src_chain_id(typed_chain_id) + .store(store.clone()) + .build(); Ok(ProposalSigningBackendSelector::Dkg(backend)) } Some(ProposalSigningBackendConfig::Mocked(mocked)) => {