Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Move tx signing logic to the substrate transaction queue #525

Merged
merged 10 commits into from
May 29, 2023
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ libsecp256k1 = "0.7.1"
serde = { version = "^1", default-features = false, features = ["derive"] }
glob = "^0.3"
serde_path_to_error = "0.1.9"
serde_bytes = "0.11"

# eth2 light client crates
eth-rpc-client = { package = "eth_rpc_client", git = "https://github.com/webb-tools/pallet-eth2-light-client" }
Expand Down
5 changes: 2 additions & 3 deletions crates/event-watcher-traits/src/substrate/bridge_watcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,8 @@ where
webb_proposals::TypedChainId::Substrate(chain_id);
let bridge_key = BridgeKey::new(typed_chain_id);
let key = SledQueueKey::from_bridge_key(bridge_key);
let client = ctx
.substrate_provider::<RuntimeConfig>(&chain_id.to_string())
.await?;
let client =
ctx.substrate_provider::<RuntimeConfig, _>(chain_id).await?;
let client = Arc::new(client);

loop {
Expand Down
5 changes: 2 additions & 3 deletions crates/event-watcher-traits/src/substrate/event_watcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,9 +156,8 @@ where
};
let metrics_clone = metrics.clone();
let task = || async {
let maybe_client = ctx
.substrate_provider::<RuntimeConfig>(&chain_id.to_string())
.await;
let maybe_client =
ctx.substrate_provider::<RuntimeConfig, _>(chain_id).await;
let client = match maybe_client {
Ok(client) => client,
Err(err) => {
Expand Down
36 changes: 7 additions & 29 deletions crates/proposal-signing-backends/src/dkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use webb::substrate::tangle_runtime::api::runtime_types::bounded_collections::bo
use webb::substrate::tangle_runtime::api::runtime_types::webb_proposals::header::{TypedChainId, ResourceId};
use webb::substrate::tangle_runtime::api::runtime_types::webb_proposals::nonce::Nonce;
use webb::substrate::subxt::{OnlineClient, PolkadotConfig};
use sp_core::sr25519::Pair as Sr25519Pair;
use webb::evm::ethers::utils;
use webb::substrate::tangle_runtime::api::runtime_types::webb_proposals::proposal::{Proposal, ProposalKind};
use webb_proposals::ProposalTrait;
Expand All @@ -13,7 +12,7 @@ use webb_relayer_utils::metric;
use webb::substrate::tangle_runtime::api as RuntimeApi;
use webb_relayer_store::{QueueStore, SledStore};
use webb_relayer_store::sled::SledQueueKey;
use webb::substrate::subxt::tx::PairSigner;
use webb_relayer_utils::static_tx_payload::TypeErasedStaticTxPayload;

type DkgConfig = PolkadotConfig;
type DkgClient = OnlineClient<DkgConfig>;
Expand All @@ -22,7 +21,6 @@ type DkgClient = OnlineClient<DkgConfig>;
pub struct DkgProposalSigningBackend {
#[builder(setter(into))]
pub client: DkgClient,
pub pair: PairSigner<PolkadotConfig, Sr25519Pair>,
/// Something that implements the QueueStore trait.
#[builder(setter(into))]
store: Arc<SledStore>,
Expand Down Expand Up @@ -102,10 +100,10 @@ impl super::ProposalSigningBackend for DkgProposalSigningBackend {
let src_chain_id =
webb_proposals_typed_chain_converter(self.src_chain_id);
tracing::debug!(
?nonce,
resource_id = %hex::encode(resource_id.into_bytes()),
nonce = nonce.0,
resource_id = hex::encode(resource_id.into_bytes()),
src_chain_id = ?self.src_chain_id,
proposal = %hex::encode(proposal.to_vec()),
proposal = hex::encode(proposal.to_vec()),
"sending proposal to DKG runtime"
);

Expand All @@ -115,41 +113,21 @@ impl super::ProposalSigningBackend for DkgProposalSigningBackend {
data: BoundedVec(proposal.to_vec()),
};
let acknowledge_proposal_tx = tx_api.acknowledge_proposal(
nonce.clone(),
nonce,
src_chain_id,
ResourceId(resource_id.into_bytes()),
unsigned_proposal,
);

let signer = &self.pair;
let maybe_signed_acknowledge_proposal_tx = self
.client
.tx()
.create_signed(&acknowledge_proposal_tx, signer, Default::default())
.await;
let signed_acknowledge_proposal_tx =
match maybe_signed_acknowledge_proposal_tx {
Ok(tx) => tx,
Err(e) => {
tracing::error!(?e, "failed to sign tx");
return Err(webb_relayer_utils::Error::Generic(
"failed to sign tx",
));
}
};
let data_hash =
utils::keccak256(acknowledge_proposal_tx.call_data().encode());
let tx_key = SledQueueKey::from_substrate_with_custom_key(
my_chain_id,
make_acknowledge_proposal_key(data_hash),
);
let tx = TypeErasedStaticTxPayload::try_from(acknowledge_proposal_tx)?;
// Enqueue transaction in protocol-substrate transaction queue
QueueStore::<Vec<u8>>::enqueue_item(
&self.store,
tx_key,
signed_acknowledge_proposal_tx.into_encoded(),
)?;

QueueStore::enqueue_item(&self.store, tx_key, tx)?;
Ok(())
}
}
Expand Down
16 changes: 13 additions & 3 deletions crates/proposal-signing-backends/src/proposal_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,15 @@ where
Ok(())
}

// create anchor update proposal for Evm target system
/// create anchor update proposal for Evm target system
#[tracing::instrument(
skip_all,
fields(
proposal_type = "AnchorUpdateProposal",
from = ?src_resource_id.typed_chain_id(),
to = ?target_resource_id.typed_chain_id(),
leaf_index,
merkle_root = ?hex::encode(merkle_root),
nonce = leaf_index,
merkle_root = hex::encode(merkle_root),
)
)]
pub fn evm_anchor_update_proposal(
Expand Down Expand Up @@ -82,6 +82,16 @@ pub fn evm_anchor_update_proposal(
}

// create anchor update proposal for substrate system
#[tracing::instrument(
skip_all,
fields(
proposal_type = "AnchorUpdateProposal",
from = ?src_resource_id.typed_chain_id(),
to = ?target_resource_id.typed_chain_id(),
nonce = leaf_index,
merkle_root = hex::encode(merkle_root),
)
)]
pub fn substrate_anchor_update_proposal(
merkle_root: [u8; 32],
leaf_index: u32,
Expand Down
28 changes: 15 additions & 13 deletions crates/relayer-context/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,12 +202,14 @@ impl RelayerContext {
///
/// * `chain_id` - A string representing the chain ID.
#[cfg(feature = "substrate")]
pub async fn substrate_provider<C: subxt::Config>(
pub async fn substrate_provider<C: subxt::Config, I: Into<types::U256>>(
&self,
chain_id: &str,
chain_id: I,
) -> webb_relayer_utils::Result<subxt::OnlineClient<C>> {
let chain_id: types::U256 = chain_id.into();
let chain_name = chain_id.to_string();
let node_config =
self.config.substrate.get(chain_id).ok_or_else(|| {
self.config.substrate.get(&chain_name).ok_or_else(|| {
webb_relayer_utils::Error::NodeNotFound {
chain_id: chain_id.to_string(),
}
Expand All @@ -224,18 +226,18 @@ impl RelayerContext {
///
/// * `chain_id` - A string representing the chain ID.
#[cfg(feature = "substrate")]
pub async fn substrate_wallet(
pub async fn substrate_wallet<I: Into<types::U256>>(
&self,
chain_id: &str,
chain_id: I,
) -> webb_relayer_utils::Result<Sr25519Pair> {
let node_config = self
.config
.substrate
.get(chain_id)
.cloned()
.ok_or_else(|| webb_relayer_utils::Error::NodeNotFound {
chain_id: chain_id.to_string(),
})?;
let chain_id: types::U256 = chain_id.into();
let chain_name = chain_id.to_string();
let node_config =
self.config.substrate.get(&chain_name).cloned().ok_or_else(
|| webb_relayer_utils::Error::NodeNotFound {
chain_id: chain_id.to_string(),
},
)?;
let suri_key = node_config
.suri
.ok_or(webb_relayer_utils::Error::MissingSecrets)?;
Expand Down
2 changes: 1 addition & 1 deletion crates/relayer-types/src/suri.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use sp_core::Pair;

/// [`Substrate Uri`](https://polkadot.js.org/docs/keyring/start/suri/)
#[derive(Clone)]
pub struct Suri(Sr25519Pair);
pub struct Suri(pub Sr25519Pair);

impl std::fmt::Debug for Suri {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Expand Down
2 changes: 2 additions & 0 deletions crates/relayer-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ backoff = { workspace = true }
serde_path_to_error = { workspace = true }
webb-proposals = { workspace = true }
webb = { workspace = true }
serde = { workspace = true }
serde_bytes = { workspace = true }
# Used by ethers (but we need it to be vendored with the lib).
native-tls = { workspace = true, optional = true }
glob = { workspace = true }
Expand Down
7 changes: 7 additions & 0 deletions crates/relayer-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ pub mod metric;
pub mod probe;
/// Retry functionality
pub mod retry;
/// type-erased StaticTxPayload for Substrate Transaction queue.
pub mod static_tx_payload;

/// An enum of all possible errors that could be encountered during the execution of the Webb
/// Relayer.
Expand Down Expand Up @@ -202,6 +204,11 @@ pub enum Error {
/// Invalid Merkle root
#[error("Invalid Merkle root at index {}", _0)]
InvalidMerkleRootError(u32),
/// Missing Static Transaction Validation Details
/// This error is raised when the static transaction validation details
/// are missing.
#[error("Missing Substrate Static Transaction Validation Details")]
MissingValidationDetails,
}

/// A type alias for the result for webb relayer, that uses the `Error` enum.
Expand Down
72 changes: 72 additions & 0 deletions crates/relayer-utils/src/static_tx_payload.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use core::fmt;

use webb::substrate::{
scale::Encode,
subxt::tx::{StaticTxPayload, TxPayload},
};

#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct TypeErasedStaticTxPayload {
pub pallet_name: String,
pub call_name: String,
#[serde(with = "serde_bytes")]
pub call_data: Vec<u8>,
}

impl std::fmt::Debug for TypeErasedStaticTxPayload {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TypeErasedStaticTxPayload")
.field("pallet_name", &self.pallet_name)
.field("call_name", &self.call_name)
.field("call_data", &hex::encode(&self.call_data))
.finish()
}
}

impl fmt::Display for TypeErasedStaticTxPayload {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(
f,
"{}.{}({})",
self.pallet_name,
self.call_name,
hex::encode(&self.call_data)
)
}
}

impl<CallData: Encode> TryFrom<StaticTxPayload<CallData>>
for TypeErasedStaticTxPayload
{
type Error = super::Error;
fn try_from(
payload: StaticTxPayload<CallData>,
) -> Result<Self, Self::Error> {
let details = payload
.validation_details()
.ok_or_else(|| Self::Error::MissingValidationDetails)?;
let call_data = payload.call_data().encode();
Ok(Self {
pallet_name: details.pallet_name.to_owned(),
call_name: details.call_name.to_owned(),
call_data,
})
}
}

impl TxPayload for TypeErasedStaticTxPayload {
fn encode_call_data_to(
&self,
metadata: &webb::substrate::subxt::Metadata,
out: &mut Vec<u8>,
) -> Result<(), webb::substrate::subxt::Error> {
let pallet = metadata.pallet(&self.pallet_name)?;
let pallet_index = pallet.index();
let call_index = pallet.call_index(&self.call_name)?;

pallet_index.encode_to(out);
call_index.encode_to(out);
out.extend_from_slice(&self.call_data);
Ok(())
}
}
5 changes: 5 additions & 0 deletions crates/tx-queue/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,8 @@ default = ["std", "evm", "substrate"]
std = []
evm = ["webb-relayer-context/evm"]
substrate = ["webb-relayer-context/substrate", "sp-core", "sp-runtime"]

[dev-dependencies]
webb-relayer-config = { workspace = true }
url = { workspace = true }
tracing-subscriber = { workspace = true }
2 changes: 1 addition & 1 deletion crates/tx-queue/src/evm/evm_tx_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ where
let metrics_clone = self.ctx.metrics.clone();
let task = || async {
loop {
// tracing::trace!("Checking for any txs in the queue ...");
let maybe_tx = store
.dequeue_item(SledQueueKey::from_evm_chain_id(chain_id))?;
let maybe_explorer = &chain_config.explorer;
Expand All @@ -115,6 +114,7 @@ where
raw_tx.set_chain_id(U64::from(chain_id)).clone();
let my_tx_hash = raw_tx.sighash();
tx_hash = my_tx_hash;
tracing::debug!(?tx_hash, tx = ?raw_tx, "Found tx in queue");
// dry run test
let dry_run_outcome =
client.call(&raw_tx.clone(), None).await;
Expand Down
Loading