Skip to content

Commit

Permalink
Make scw block number optional for front-end (#1112)
Browse files Browse the repository at this point in the history
* optional block number for the front-end

* a better path

* lint

* be more specific in trait

* return error instead of todo

* cleanup

* lint
  • Loading branch information
codabrink authored Oct 3, 2024
1 parent 2acfde8 commit 9f366f2
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 20 deletions.
2 changes: 2 additions & 0 deletions bindings_ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ pub enum GenericError {
SignatureRequestError(#[from] xmtp_id::associations::builder::SignatureRequestError),
#[error(transparent)]
Erc1271SignatureError(#[from] xmtp_id::associations::signature::SignatureError),
#[error(transparent)]
Verifier(#[from] xmtp_id::scw_verifier::VerifierError),
}

impl From<String> for GenericError {
Expand Down
13 changes: 12 additions & 1 deletion bindings_ffi/src/mls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,22 @@ impl FfiSignatureRequest {
signature_bytes: Vec<u8>,
address: String,
chain_id: u64,
block_number: u64,
block_number: Option<u64>,
) -> Result<(), GenericError> {
let mut inner = self.inner.lock().await;
let account_id = AccountId::new_evm(chain_id, address);

let block_number = match block_number {
Some(bn) => bn,
None => {
self.scw_verifier
.current_block_number(&chain_id.to_string())
.await
.map_err(GenericError::Verifier)?
.0[0]
}
};

let signature = UnverifiedSignature::new_smart_contract_wallet(
signature_bytes,
account_id,
Expand Down
6 changes: 5 additions & 1 deletion xmtp_id/src/associations/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use ed25519_dalek::SigningKey as Ed25519SigningKey;
use ethers::{
core::types::BlockNumber,
signers::{LocalWallet, Signer},
types::Bytes,
types::{Bytes, U64},
};
use rand::{distributions::Alphanumeric, Rng};
use sha2::{Digest, Sha512};
Expand Down Expand Up @@ -59,6 +59,10 @@ impl SmartContractSignatureVerifier for MockSmartContractSignatureVerifier {
) -> Result<bool, VerifierError> {
Ok(self.is_valid_signature)
}

async fn current_block_number(&self, _chain_id: &str) -> Result<U64, VerifierError> {
Ok(1.into())
}
}

pub async fn add_wallet_signature(signature_request: &mut SignatureRequest, wallet: &LocalWallet) {
Expand Down
2 changes: 1 addition & 1 deletion xmtp_id/src/associations/unverified.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ impl UnverifiedSignature {
scw_verifier,
&sig.signature_bytes,
sig.account_id.clone(),
sig.block_number,
Some(sig.block_number),
)
.await
}
Expand Down
6 changes: 3 additions & 3 deletions xmtp_id/src/associations/verified_signature.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![allow(dead_code)]

use ed25519_dalek::{Signature as Ed25519Signature, VerifyingKey as Ed25519VerifyingKey};
use ethers::types::{BlockNumber, Signature as EthersSignature, U64};
use ethers::types::Signature as EthersSignature;
use ethers::utils::hash_message;
use ethers::{core::k256::ecdsa::VerifyingKey as EcdsaVerifyingKey, utils::public_key_to_address};
use sha2::{Digest, Sha512};
Expand Down Expand Up @@ -125,14 +125,14 @@ impl VerifiedSignature {
signature_verifier: &dyn SmartContractSignatureVerifier,
signature_bytes: &[u8],
account_id: AccountId,
block_number: u64,
block_number: Option<u64>,
) -> Result<Self, SignatureError> {
let is_valid = signature_verifier
.is_valid_signature(
account_id.clone(),
hash_message(signature_text.as_ref()).into(),
signature_bytes.to_vec().into(),
Some(BlockNumber::Number(U64::from(block_number))),
block_number.map(|n| n.into()),
)
.await?;

Expand Down
16 changes: 11 additions & 5 deletions xmtp_id/src/scw_verifier/chain_rpc_verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use ethers::abi::{Constructor, Param, ParamType, Token};
use ethers::contract::abigen;
use ethers::providers::{Http, Middleware, Provider};
use ethers::types::transaction::eip2718::TypedTransaction;
use ethers::types::{Address, BlockNumber, Bytes, TransactionRequest};
use ethers::types::{Address, BlockNumber, Bytes, TransactionRequest, U64};
use hex::{FromHex, FromHexError};
use std::sync::Arc;

Expand Down Expand Up @@ -87,14 +87,20 @@ impl SmartContractSignatureVerifier for RpcSmartContractWalletVerifier {
];
let data = constructor.encode_input(code, tokens)?;
let tx: TypedTransaction = TransactionRequest::new().data(data).into();
let block_number = if let Some(number) = block_number {
number
} else {
BlockNumber::Number(self.provider.get_block_number().await?)
let block_number = match block_number {
Some(bn) => bn,
None => BlockNumber::Number(self.current_block_number(&signer.chain_id).await?),
};
let res = self.provider.call(&tx, Some(block_number.into())).await?;
Ok(res == Bytes::from_hex("0x01").expect("Hardcoded hex will not fail."))
}

async fn current_block_number(&self, _chain_id: &str) -> Result<U64, VerifierError> {
self.provider
.get_block_number()
.await
.map_err(VerifierError::Provider)
}
}

#[cfg(test)]
Expand Down
44 changes: 35 additions & 9 deletions xmtp_id/src/scw_verifier/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ use std::{collections::HashMap, fs, path::Path, str::FromStr};
use async_trait::async_trait;
use dyn_clone::DynClone;
use ethers::{
providers::{Http, Provider},
types::{BlockNumber, Bytes},
contract::ContractError,
providers::{Http, Provider, ProviderError},
types::{BlockNumber, Bytes, U64},
};
use thiserror::Error;
use url::Url;
Expand All @@ -33,6 +34,7 @@ pub enum VerifierError {

#[async_trait]
pub trait SmartContractSignatureVerifier: Send + Sync + DynClone + 'static {
async fn current_block_number(&self, chain_id: &str) -> Result<U64, VerifierError>;
async fn is_valid_signature(
&self,
account_id: AccountId,
Expand All @@ -57,6 +59,10 @@ impl<S: SmartContractSignatureVerifier + Clone> SmartContractSignatureVerifier f
.is_valid_signature(account_id, hash, signature, block_number)
.await
}

async fn current_block_number(&self, chain_id: &str) -> Result<U64, VerifierError> {
(**self).current_block_number(chain_id).await
}
}

#[derive(Clone)]
Expand Down Expand Up @@ -116,16 +122,36 @@ impl SmartContractSignatureVerifier for MultiSmartContractSignatureVerifier {
account_id: AccountId,
hash: [u8; 32],
signature: Bytes,
_block_number: Option<BlockNumber>,
block_number: Option<BlockNumber>,
) -> Result<bool, VerifierError> {
let id: u64 = account_id.chain_id.parse().unwrap();
let id: u64 = account_id.chain_id.parse().map_err(|e| {
VerifierError::Contract(ContractError::DecodingError(
ethers::core::abi::Error::ParseInt(e),
))
})?;
if let Some(verifier) = self.verifiers.get(&id) {
return verifier
.is_valid_signature(account_id, hash, signature, block_number)
.await;
}

Err(VerifierError::Provider(ProviderError::CustomError(
"Verifier not present".to_string(),
)))
}

async fn current_block_number(&self, chain_id: &str) -> Result<U64, VerifierError> {
let id: u64 = chain_id.parse().map_err(|e| {
VerifierError::Contract(ContractError::DecodingError(
ethers::core::abi::Error::ParseInt(e),
))
})?;
if let Some(verifier) = self.verifiers.get(&id) {
return Ok(verifier
.is_valid_signature(account_id, hash, signature, None)
.await
.unwrap());
return verifier.current_block_number(chain_id).await;
}

todo!()
Err(VerifierError::Provider(ProviderError::CustomError(
"Verifier not present".to_string(),
)))
}
}

0 comments on commit 9f366f2

Please sign in to comment.