EEVM.Transaction.Signer (eevm v0.1.0)

Copy Markdown View Source

Transaction signing, signing hashes, and sender recovery.

Example

iex> alias EEVM.Transaction.{FeeMarket, Signer}
iex> tx = %FeeMarket{max_priority_fee_per_gas: 1, max_fee_per_gas: 10, gas_limit: 21_000, to: 0xB0B}
iex> private_key = :binary.copy(<<0x46>>, 32)
iex> {:ok, signed} = Signer.sign(tx, private_key, EEVM.Config.new(:cancun, chain_id: 5))
iex> signed.chain_id
5
iex> {:ok, sender} = Signer.recover_sender(signed, 5)
iex> EEVM.hex(<<sender::160>>)
"0x9d8a62f656a8d1615c1294fd71e9cfb3e4855a4f"

Summary

Functions

Returns the address of the secp256k1 private_key: the last 20 bytes of the keccak256 hash of its uncompressed public key (Yellow Paper, Appendix F).

Recover the authority (signer) of an EIP-7702 authorization tuple.

Recover the sender address, as an integer, from a transaction signed for chain chain_id.

Signs tx with the 32-byte secp256k1 private_key for config's chain.

Compute the signing hash for a transaction.

Functions

address(private_key)

@spec address(<<_::256>>) ::
  {:ok, EEVM.Transaction.address()} | {:error, :invalid_private_key}

Returns the address of the secp256k1 private_key: the last 20 bytes of the keccak256 hash of its uncompressed public key (Yellow Paper, Appendix F).

Returns {:error, :invalid_private_key} when the key is zero or not below the curve order.

Example

iex> # The private key from the EIP-155 example.
iex> {:ok, address} = EEVM.Transaction.Signer.address(:binary.copy(<<0x46>>, 32))
iex> EEVM.hex(<<address::160>>)
"0x9d8a62f656a8d1615c1294fd71e9cfb3e4855a4f"

recover_authority(auth)

@spec recover_authority(EEVM.Transaction.Authorization.t()) ::
  {:ok, EEVM.Transaction.address()} | {:error, atom()}

Recover the authority (signer) of an EIP-7702 authorization tuple.

The signed message is keccak256(0x05 || rlp([chain_id, address, nonce])). Signatures with y_parity outside 0..1, r outside 1..n-1, or a high s (EIP-2) are rejected with {:error, :invalid_signature}.

recover_sender(tx, chain_id)

@spec recover_sender(EEVM.Transaction.t(), non_neg_integer()) ::
  {:ok, EEVM.Transaction.address()} | {:error, atom()}

Recover the sender address, as an integer, from a transaction signed for chain chain_id.

A transaction signed for another chain fails with {:error, :invalid_chain_id}, so it can't be replayed across chains: a typed transaction's chain_id, or the chain id an EIP-155 legacy v encodes, must equal chain_id. A pre-EIP-155 legacy transaction (v of 27 or 28) names no chain and is valid on any. Other legacy v values fail with {:error, :invalid_v}.

sign(tx, private_key, config)

@spec sign(EEVM.Transaction.t(), <<_::256>>, EEVM.Config.t()) ::
  {:ok, EEVM.Transaction.t()} | {:error, :invalid_private_key}

Signs tx with the 32-byte secp256k1 private_key for config's chain.

A legacy transaction is signed with EIP-155 replay protection, so its v becomes chain_id * 2 + 35 + y_parity. A typed transaction whose chain_id is nil takes the config's; one that already has a chain_id keeps it. Any existing signature is replaced. Signatures are low-s (EIP-2).

Returns {:ok, signed_tx}, or {:error, :invalid_private_key} when the key is zero or not below the curve order. Raises ArgumentError naming the field when a field has the wrong type, such as a hex string for to.

signing_hash(tx, chain_id)

@spec signing_hash(EEVM.Transaction.t(), non_neg_integer()) :: binary()

Compute the signing hash for a transaction.

Raises ArgumentError naming the field when a field has the wrong type, such as a hex string for to.