Skip to content

Commit

Permalink
Fixes recovery_id bug.
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesduncombe committed Oct 9, 2023
1 parent 59ca3f7 commit 49280aa
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 11 deletions.
9 changes: 1 addition & 8 deletions lib/tt_eth/transactions/eip1559_transaction.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ defmodule TTEth.Transactions.EIP1559Transaction do
init: <<>>,
data: <<>>

# Base recovery V minimum.
@base_recovery_id 27

# The transaction envelope version for an EIP-1559 transaction.
# SEE: https://eips.ethereum.org/EIPS/eip-2718
# SEE: https://eips.ethereum.org/EIPS/eip-1559
Expand Down Expand Up @@ -94,7 +91,7 @@ defmodule TTEth.Transactions.EIP1559Transaction do
def sign_hash(hash, private_key) do
{:ok, {<<r::size(256), s::size(256)>>, v}} = Secp256k1.ecdsa_sign_compact(hash, private_key)

{v |> v_to_parity(), r, s}
{v, r, s}
end

@doc """
Expand Down Expand Up @@ -129,10 +126,6 @@ defmodule TTEth.Transactions.EIP1559Transaction do

## Private.

# Converts the `v` value to a parity value.
defp v_to_parity(@base_recovery_id), do: 0
defp v_to_parity(_), do: 1

# Optionally add the YRS values.
defp maybe_add_yrs(base, %__MODULE__{} = trx, _include_vrs = true),
do:
Expand Down
60 changes: 57 additions & 3 deletions test/tt_eth/transactions/eip1559_transaction_test.exs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
defmodule TTEth.Transactions.EIP1559TransactionTest do
use TTEth.Case
alias TTEth.Transactions.EIP1559Transaction
alias TTEth.Type.{Address, PrivateKey, PublicKey}

# Polygon Mumbai.
@chain_id 80001

@private_key_human "0x62aa6ec41b56439d2c5df352c45a00389cef262b3761e13c6481e35ab027d262"
@private_key @private_key_human |> TTEth.Type.PrivateKey.from_human!()
@private_key @private_key_human |> PrivateKey.from_human!()
@to_address_human "0x38f153fdd399ff2cf64704c6a4b16d3fd9ddcd69"
@to_address @to_address_human |> TTEth.Type.Address.from_human!()
@to_address @to_address_human |> Address.from_human!()
# transfer(address,uint256)
@tx_data_human "a9059cbb00000000000000000000000038f153fdd399ff2cf64704c6a4b16d3fd9ddcd69000000000000000000000000000000000000000000000000000000000000000a"
@tx_data @tx_data_human |> Base.decode16!(case: :lower)
Expand Down Expand Up @@ -58,6 +59,46 @@ defmodule TTEth.Transactions.EIP1559TransactionTest do
|> encode_and_pad()
|> assert_match(@valid_transaction_data)
end

test "from address is correct when checking signature", %{trx: trx} do
# Build the trx_data but randomize the nonce.
built_trx_data =
%{trx | nonce: Enum.random(10..100)}
|> EIP1559Transaction.build(@private_key)
|> encode_and_pad()

# Decode the transaction data.
decoded = built_trx_data |> fully_decode_trx_data()

# Get signature params.
[y_parity, r, s] = decoded |> Enum.take(_signature_params = -3)

# Get the raw public key from the signature.
{:ok, public_raw} =
decoded
|> Enum.take(_everything_but_the_signature = 9)
|> ExRLP.encode()
|> put_trx_envelope()
|> TTEth.keccak()
|> TTEth.Secp256k1.ecdsa_recover_compact(
_signature = r <> s,
_recovery_id = y_parity |> :binary.decode_unsigned()
)

# Get the formatted public key from the private key.
original_public_key =
@private_key_human
|> PrivateKey.from_human!()
|> PublicKey.from_private_key!()
|> Address.from_public_key!()
|> Address.encode_eth_address!()

# Attempt to match the public key from the signature with the private key's public key.
public_raw
|> Address.from_public_key!()
|> Address.encode_eth_address!()
|> assert_match(^original_public_key)
end
end

## Private.
Expand All @@ -82,5 +123,18 @@ defmodule TTEth.Transactions.EIP1559TransactionTest do
do:
bin
|> Base.encode16(case: :lower)
|> (&("0x" <> &1)).()
|> TTEth.hex_prefix!()

# Decode the hex encoded transaction.
defp fully_decode_trx_data("0x" <> data),
do:
data
|> Base.decode16!(case: :lower)
|> :binary.bin_to_list()
|> Enum.drop(_drop_transaction_envelope = 1)
|> :binary.list_to_bin()
|> ExRLP.decode()

defp put_trx_envelope(data),
do: <<2>> <> data
end

0 comments on commit 49280aa

Please sign in to comment.