blockchain v0.1.1 Blockchain.Transaction.Signature
Defines helper functions for signing and getting the signature of a transaction, as defined in Appendix F of the Yellow Paper.
Link to this section Summary
Functions
Given a private key, this will return an associated ethereum address, as defined in Eq.(213)
Given a public key, this will return an associated ethereum address, as defined (in part) in Eq.(213)
Given a private key, returns a public key
Verifies a given signature is valid, as defined in Eq.(209), Eq.(210), Eq.(211)
Recovers a public key from a signed hash
Given a transaction, we will determine the sender of the message
Returns a ECDSA signature (v,r,s) for a given hashed value
Takes a given transaction and returns a version signed with the given private key. This is defined in Eq.(216) and Eq.(217) of the Yellow Paper
Returns a hash of a given transaction according to the formula defined in Eq.(214) and Eq.(215) of the Yellow Paper
Link to this section Types
Link to this section Functions
address_from_private(private_key) :: EVM.address
Given a private key, this will return an associated ethereum address, as defined in Eq.(213).
This returns the rightmost 160-bits of the Keecak-256 of the public key.
Examples
iex> Blockchain.Transaction.Signature.address_from_private(<<1::256>>)
<<82, 43, 246, 253, 8, 130, 229, 143, 111, 235, 9, 107, 65, 65, 123, 79, 140, 105, 44, 57>>
address_from_public(public_key) :: EVM.address
Given a public key, this will return an associated ethereum address, as defined (in part) in Eq.(213).
This returns the rightmost 160-bits of the Keecak-256 of the public key.
Examples
iex> Blockchain.Transaction.Signature.address_from_public(<<1::256>>)
<<242, 147, 250, 79, 184, 253, 30, 235, 192, 201, 54, 126, 124, 145, 6, 103, 138, 137, 61, 241>>
get_public_key(private_key) :: {:ok, public_key} | {:error, String.t}
Given a private key, returns a public key.
This covers Eq.(206) of the Yellow Paper.
Examples
iex> Blockchain.Transaction.Signature.get_public_key(<<1::256>>)
{:ok, <<4, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149,
206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89,
242, 129, 91, 22, 248, 23, 152, 72, 58, 218, 119, 38, 163,
196, 101, 93, 164, 251, 252, 14, 17, 8, 168, 253, 23, 180,
72, 166, 133, 84, 25, 156, 71, 208, 143, 251, 16, 212, 184>>}
iex> Blockchain.Transaction.Signature.get_public_key(<<1>>)
{:error, "Private key size not 32 bytes"}
is_signature_valid?(boolean, integer, integer, integer) :: boolean
Verifies a given signature is valid, as defined in Eq.(209), Eq.(210), Eq.(211)
Examples
iex> Blockchain.Transaction.Signature.is_signature_valid?(true, 1, 1, 27) true
iex> Blockchain.Transaction.Signature.is_signature_valid?(true, 1, 1, 20) # invalid v false
iex> secp256k1n = 115792089237316195423570985008687907852837564279074904382605163141518161494337 iex> Blockchain.Transaction.Signature.is_signature_valid?(false, secp256k1n - 1, 1, 28) # r okay true
iex> secp256k1n = 115792089237316195423570985008687907852837564279074904382605163141518161494337 iex> Blockchain.Transaction.Signature.is_signature_valid?(false, secp256k1n + 1, 1, 28) # r too high false
iex> secp256k1n = 115792089237316195423570985008687907852837564279074904382605163141518161494337 iex> Blockchain.Transaction.Signature.is_signature_valid?(false, 1, secp256k1n + 1, 28) # s too high for non-homestead false
iex> secp256k1n = 115792089237316195423570985008687907852837564279074904382605163141518161494337 iex> Blockchain.Transaction.Signature.is_signature_valid?(false, 1, secp256k1n - 1, 28) # s okay for non-homestead true
iex> secp256k1n = 115792089237316195423570985008687907852837564279074904382605163141518161494337 iex> Blockchain.Transaction.Signature.is_signature_valid?(true, 1, secp256k1n - 1, 28) # s too high for homestead false
iex> secp256k1n = 115792089237316195423570985008687907852837564279074904382605163141518161494337 iex> secp256k1n_2 = round(:math.floor(secp256k1n / 2)) iex> Blockchain.Transaction.Signature.is_signature_valid?(true, secp256k1n_2 - 1, 1, 28) # s okay for homestead true
recover_public(BitHelper.keccak_hash, hash_v, hash_r, hash_s) :: {:ok, public_key} | {:error, String.t}
Recovers a public key from a signed hash.
This implements Eq.(208) of the Yellow Paper, adapted from https://stackoverflow.com/a/20000007
Examples
iex> Blockchain.Transaction.Signature.recover_public(<<2::256>>, 28, 38938543279057362855969661240129897219713373336787331739561340553100525404231, 23772455091703794797226342343520955590158385983376086035257995824653222457926) {:ok, <<4, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149,
206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242,
129, 91, 22, 248, 23, 152, 72, 58, 218, 119, 38, 163, 196, 101,
93, 164, 251, 252, 14, 17, 8, 168, 253, 23, 180, 72, 166, 133,
84, 25, 156, 71, 208, 143, 251, 16, 212, 184>>}
iex> Blockchain.Transaction.Signature.recover_public(<<2::256>>, 55, 38938543279057362855969661240129897219713373336787331739561340553100525404231, 23772455091703794797226342343520955590158385983376086035257995824653222457926)
sender(Blockchain.Transaction.t) :: {:ok, EVM.address} | {:error, String.t}
Given a transaction, we will determine the sender of the message.
This is defined in Eq.(218) of the Yellow Paper, verified by Eq.(219).
Examples
iex> Blockchain.Transaction.Signature.sender(%Blockchain.Transaction{data: nil, gas_limit: 7, gas_price: 6, init: <<1>>, nonce: 5, r: 38889131630470350300468726261158724183878062819625353581392042110782473464074, s: 56013001490976921811414879795854011730332692343890561111314022658085426919315, to: "", v: 27, value: 5})
{:ok, <<82, 43, 246, 253, 8, 130, 229, 143, 111, 235, 9, 107, 65, 65, 123, 79, 140, 105, 44, 57>>}
iex> Blockchain.Transaction.Signature.sender(%Blockchain.Transaction{data: nil, gas_limit: 7, gas_price: 6, init: <<1>>, nonce: 5, r: 0, s: 0, to: "", v: 0, value: 5})
{:error, "Recovery id invalid 0-3"}
sign_hash(BitHelper.keccak_hash, private_key) :: {hash_v, hash_r, hash_s}
Returns a ECDSA signature (v,r,s) for a given hashed value.
This implementes Eq.(207) of the Yellow Paper.
Examples
iex> Blockchain.Transaction.Signature.sign_hash(<<2::256>>, <<1::256>>) {28, 38938543279057362855969661240129897219713373336787331739561340553100525404231, 23772455091703794797226342343520955590158385983376086035257995824653222457926}
iex> Blockchain.Transaction.Signature.sign_hash(<<5::256>>, <<1::256>>) {27, 74927840775756275467012999236208995857356645681540064312847180029125478834483, 56037731387691402801139111075060162264934372456622294904359821823785637523849}
sign_transaction(Blockchain.Transaction.t, private_key) :: Blockchain.Transaction.t
Takes a given transaction and returns a version signed with the given private key. This is defined in Eq.(216) and Eq.(217) of the Yellow Paper.
Examples
iex> Blockchain.Transaction.Signature.sign_transaction(%Blockchain.Transaction{nonce: 5, gas_price: 6, gas_limit: 7, to: <<>>, value: 5, init: <<1>>}, <<1::256>>)
%Blockchain.Transaction{data: <<>>, gas_limit: 7, gas_price: 6, init: <<1>>, nonce: 5, r: 38889131630470350300468726261158724183878062819625353581392042110782473464074, s: 56013001490976921811414879795854011730332692343890561111314022658085426919315, to: "", v: 27, value: 5}
transaction_hash(Blockchain.Transaction.t) :: BitHelper.keccak_hash
Returns a hash of a given transaction according to the formula defined in Eq.(214) and Eq.(215) of the Yellow Paper.
TODO: Are we supposed to RLP encode Ls before hashing, or maybe
just concatencate the fields? Confused about Eq 214/5.
Examples
iex> Blockchain.Transaction.Signature.transaction_hash(%Blockchain.Transaction{nonce: 5, gas_price: 6, gas_limit: 7, to: <<>>, value: 5, init: <<1>>})
<<187, 197, 72, 40, 247, 126, 117, 11, 218, 201, 187, 47, 109, 167, 131, 80, 40, 46, 5, 168, 185, 183, 20, 24, 165, 38, 170, 148, 7, 7, 97, 138>>
iex> Blockchain.Transaction.Signature.transaction_hash(%Blockchain.Transaction{nonce: 5, gas_price: 6, gas_limit: 7, to: <<1>>, value: 5, data: <<1>>})
<<190, 212, 214, 101, 94, 148, 22, 238, 110, 177, 41, 32, 137, 25, 21, 242, 180, 17, 162, 187, 227, 164, 95, 46, 83, 245, 198, 0, 1, 73, 82, 180>>