From 632105ed5d10581dde3b12d605fd623c1bd62007 Mon Sep 17 00:00:00 2001 From: Max Date: Sun, 1 May 2022 18:07:53 +0700 Subject: [PATCH 1/2] fix: Ledger should have correct signature v value --- ethers-signers/src/ledger/app.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/ethers-signers/src/ledger/app.rs b/ethers-signers/src/ledger/app.rs index 346231fc0..22ff5fb05 100644 --- a/ethers-signers/src/ledger/app.rs +++ b/ethers-signers/src/ledger/app.rs @@ -119,7 +119,31 @@ impl LedgerEthereum { pub async fn sign_tx(&self, tx: &TypedTransaction) -> Result { let mut payload = Self::path_to_bytes(&self.derivation); payload.extend_from_slice(tx.rlp().as_ref()); - self.sign_payload(INS::SIGN, payload).await + + let mut signature = self.sign_payload(INS::SIGN, payload).await?; + + // modify `v` value of signature to match EIP-155 for chains with large chain ID + // The logic is derived from Ledger's library + // https://github.com/LedgerHQ/ledgerjs/blob/e78aac4327e78301b82ba58d63a72476ecb842fc/packages/hw-app-eth/src/Eth.ts#L300 + let eip155_chain_id = self.chain_id * 2 + 35; + if eip155_chain_id + 1 > 255 { + let one_byte_chain_id = eip155_chain_id % 256; + // May use `let ecc_parity = signature.v.abs_diff(one_byte_chain_id)` instead after updated to Rust 1.60 + let ecc_parity = if signature.v > one_byte_chain_id { + signature.v - one_byte_chain_id + } else { + one_byte_chain_id - signature.v + }; + + signature.v = match tx { + TypedTransaction::Eip2930(_) | TypedTransaction::Eip1559(_) => { + if ecc_parity % 2 == 1 { 0 } else { 1 } + }, + TypedTransaction::Legacy(_) => eip155_chain_id + ecc_parity, + }; + } + + Ok(signature) } /// Signs an ethereum personal message From 717bc0131d57f154a16d04afc8b543ffae80c375 Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 2 May 2022 09:25:26 +0700 Subject: [PATCH 2/2] format code --- ethers-signers/src/ledger/app.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/ethers-signers/src/ledger/app.rs b/ethers-signers/src/ledger/app.rs index 22ff5fb05..2d4c326f4 100644 --- a/ethers-signers/src/ledger/app.rs +++ b/ethers-signers/src/ledger/app.rs @@ -119,16 +119,15 @@ impl LedgerEthereum { pub async fn sign_tx(&self, tx: &TypedTransaction) -> Result { let mut payload = Self::path_to_bytes(&self.derivation); payload.extend_from_slice(tx.rlp().as_ref()); - + let mut signature = self.sign_payload(INS::SIGN, payload).await?; // modify `v` value of signature to match EIP-155 for chains with large chain ID // The logic is derived from Ledger's library - // https://github.com/LedgerHQ/ledgerjs/blob/e78aac4327e78301b82ba58d63a72476ecb842fc/packages/hw-app-eth/src/Eth.ts#L300 + // https://github.com/LedgerHQ/ledgerjs/blob/e78aac4327e78301b82ba58d63a72476ecb842fc/packages/hw-app-eth/src/Eth.ts#L300 let eip155_chain_id = self.chain_id * 2 + 35; if eip155_chain_id + 1 > 255 { let one_byte_chain_id = eip155_chain_id % 256; - // May use `let ecc_parity = signature.v.abs_diff(one_byte_chain_id)` instead after updated to Rust 1.60 let ecc_parity = if signature.v > one_byte_chain_id { signature.v - one_byte_chain_id } else { @@ -137,8 +136,12 @@ impl LedgerEthereum { signature.v = match tx { TypedTransaction::Eip2930(_) | TypedTransaction::Eip1559(_) => { - if ecc_parity % 2 == 1 { 0 } else { 1 } - }, + if ecc_parity % 2 == 1 { + 0 + } else { + 1 + } + } TypedTransaction::Legacy(_) => eip155_chain_id + ecc_parity, }; }