fix(signer): use wallet chainid for tx signing (#1308)
* add a test checking that the wallet outputs a signature with a correct v
This commit is contained in:
parent
95862bc62c
commit
799660bd26
|
@ -119,10 +119,15 @@ impl<D: Sync + Send + DigestSigner<Sha256Proxy, RecoverableSignature>> Signer fo
|
||||||
|
|
||||||
impl<D: DigestSigner<Sha256Proxy, RecoverableSignature>> Wallet<D> {
|
impl<D: DigestSigner<Sha256Proxy, RecoverableSignature>> Wallet<D> {
|
||||||
/// Synchronously signs the provided transaction, normalizing the signature `v` value with
|
/// Synchronously signs the provided transaction, normalizing the signature `v` value with
|
||||||
/// EIP-155 using the transaction's `chain_id`.
|
/// EIP-155 using the transaction's `chain_id`, or the signer's `chain_id` if the transaction
|
||||||
|
/// does not specify one.
|
||||||
pub fn sign_transaction_sync(&self, tx: &TypedTransaction) -> Signature {
|
pub fn sign_transaction_sync(&self, tx: &TypedTransaction) -> Signature {
|
||||||
let sighash = tx.sighash();
|
// rlp (for sighash) must have the same chain id as v in the signature
|
||||||
let chain_id = tx.chain_id().map(|id| id.as_u64()).unwrap_or(self.chain_id);
|
let chain_id = tx.chain_id().map(|id| id.as_u64()).unwrap_or(self.chain_id);
|
||||||
|
let mut tx = tx.clone();
|
||||||
|
tx.set_chain_id(chain_id);
|
||||||
|
|
||||||
|
let sighash = tx.sighash();
|
||||||
let mut sig = self.sign_hash(sighash);
|
let mut sig = self.sign_hash(sighash);
|
||||||
|
|
||||||
// sign_hash sets `v` to recid + 27, so we need to subtract 27 before normalizing
|
// sign_hash sets `v` to recid + 27, so we need to subtract 27 before normalizing
|
||||||
|
|
|
@ -252,6 +252,47 @@ mod tests {
|
||||||
assert!(sig.verify(sighash, wallet.address).is_ok());
|
assert!(sig.verify(sighash, wallet.address).is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(not(feature = "celo"))]
|
||||||
|
fn signs_tx_empty_chain_id_sync() {
|
||||||
|
use crate::TypedTransaction;
|
||||||
|
use ethers_core::types::TransactionRequest;
|
||||||
|
|
||||||
|
let chain_id = 1337u64;
|
||||||
|
// retrieved test vector from:
|
||||||
|
// https://web3js.readthedocs.io/en/v1.2.0/web3-eth-accounts.html#eth-accounts-signtransaction
|
||||||
|
let tx: TypedTransaction = TransactionRequest {
|
||||||
|
from: None,
|
||||||
|
to: Some("F0109fC8DF283027b6285cc889F5aA624EaC1F55".parse::<Address>().unwrap().into()),
|
||||||
|
value: Some(1_000_000_000u64.into()),
|
||||||
|
gas: Some(2_000_000u64.into()),
|
||||||
|
nonce: Some(0u64.into()),
|
||||||
|
gas_price: Some(21_000_000_000u128.into()),
|
||||||
|
data: None,
|
||||||
|
chain_id: None,
|
||||||
|
}
|
||||||
|
.into();
|
||||||
|
let wallet: Wallet<SigningKey> =
|
||||||
|
"4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318".parse().unwrap();
|
||||||
|
let wallet = wallet.with_chain_id(chain_id);
|
||||||
|
|
||||||
|
// this should populate the tx chain_id as the signer's chain_id (1337) before signing and
|
||||||
|
// normalize the v
|
||||||
|
let sig = wallet.sign_transaction_sync(&tx);
|
||||||
|
|
||||||
|
// ensure correct v given the chain - first extract recid
|
||||||
|
let recid = (sig.v - 35) % 2;
|
||||||
|
// eip155 check
|
||||||
|
assert_eq!(sig.v, chain_id * 2 + 35 + recid);
|
||||||
|
|
||||||
|
// since we initialize with None we need to re-set the chain_id for the sighash to be
|
||||||
|
// correct
|
||||||
|
let mut tx = tx;
|
||||||
|
tx.set_chain_id(chain_id);
|
||||||
|
let sighash = tx.sighash();
|
||||||
|
assert!(sig.verify(sighash, wallet.address).is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn key_to_address() {
|
fn key_to_address() {
|
||||||
let wallet: Wallet<SigningKey> =
|
let wallet: Wallet<SigningKey> =
|
||||||
|
|
Loading…
Reference in New Issue