How can you find the signature of a transaction? web3.eth.getTransaction()
doesn't appear to make that available.
-
Transaction signature is not available by common APIs like JavaScript web3 and JSON RPC.– Paweł BylicaMar 21, 2016 at 22:11
-
Why do you need it?– Paweł BylicaMar 21, 2016 at 22:16
-
Raw transactions including the signature are available on other blockchain implementations such as Bitcoin. Why not on Ethereum?– dbrysonMar 22, 2016 at 2:15
-
2It's because ethereum doesn't need to store all transaction signatures, since it is state-based, not UTXO based– Tjaden HessMar 22, 2016 at 17:46
-
Good info. So does Ethereum actually store transaction signatures at all?– dbrysonMar 22, 2016 at 18:16
3 Answers
This can be done using EthereumJS: a collection of libraries and utilities for Ethereum. https://github.com/ethereumjs
First, obtain the raw encoding of the block containing your target transaction. This can be done on live.ether.camp.
Alternatively, if you don't want to copy from live.ether.camp, you can recover the raw block encodings by loading your Ethereum chaindata into a leveldb and querying by blockhash.
Finally, using ethereumjs (see ethereumjs-block and ethereumjs-tx modules) you can easily recover transaction signatures.
Transaction signature is not available by common APIs like JavaScript web3 and JSON RPC
- Pawel Bylica
The next natural question is: Why not?
Ethereum doesn't need to store all transaction signatures, since it is state-based, not UTXO (Unspent Transaction Output Set) based
- Tjaden Hess
The next natural question is: What is UTXO and what does it have to do with transactions and why doesn't Ethereum have UTXO?
Vitalik writes about UTXO here. Key points summarized below.
What is UTXO and what does it have to do with transactions?
In Bitcoin, the way that a transaction actually works “under the hood” is that it consumes a collection of objects called unspent transaction outputs (“UTXOs”) created by one or more previous transactions, and then produces one or more new UTXOs, which can then be consumed by future transactions...A user’s balance is thus not stored as a number; rather, it can be computed as the total sum of the denominations of UTXOs that they own.
Why doesn't Ethereum do this?
UTXOs are unnecessarily complicated, and the complexity gets even greater in the implementation than in the theory.
UTXOs are stateless, and so are not well-suited to applications more complex than asset issuance and transfer that are generally stateful, such as various kinds of smart contracts.
It is clear how UTXOs do not mesh well with stateful smart contracts: if there is a need to create a contract with multiple phases, eg. where multiple parties must provide some form of input, then after some period of time those parties must perform some additional operation, and then finally the contract disburses funds as a function of those operations, then it is difficult to see how to fit that model into fundamentally stateless objects that can only be spent or not spent.
In summation, there is no real reason you need signature for Ethereum which is why it isn't provided by common APIs.
As for now (Feb 2019) there is a signature in eth_getTransactionByHash
JSON RPC.
here is how you can retrievie a signature from Python:
In [1]: import web3
w3=web3.Web3(web3.HTTPProvider('https://geth.golem.network:55555'))
t=w3.eth.getTransactionFromBlock(w3.eth.blockNumber, 0)
t.hash
Out[1]: HexBytes('0xf4bbed857cc67a5ad8f49f12926e6e9b87f550cdd82542310bf196c8e78b838c')
In [2]: from eth_account.internal.signing import extract_chain_id, to_standard_v
s=w3.eth.account._keys.Signature(vrs=(to_standard_v(extract_chain_id(t.v)[1]), w3.toInt(t.r), w3.toInt(t.s)))
type(s)
Out[2]: eth_keys.datatypes.Signature
In [3]: s
Out[3]: '0xf8b1b27aa4746ee1950dcc125e10103e9aba49bdc03e7ccd101b02b94f9c062f17995e4d31cb5a7d8252c5628ec55635d67ba4d853a9a49dae49a05db3b05cef00'
You can use it further for example for recovering the public key of the signer.
In [4]: from eth_account.internal.transactions import ALLOWED_TRANSACTION_KEYS, serializable_unsigned_transaction_from_dict
tt={k:t[k] for k in ALLOWED_TRANSACTION_KEYS - {'chainId', 'data'}}
tt['data']=t.input
tt['chainId']=extract_chain_id(t.v)[0]
ut=serializable_unsigned_transaction_from_dict(tt)
In [5]: s.recover_public_key_from_msg_hash(ut.hash())
Out[5]: '0x58ed29a99e06f14a5b7dc33a3d670f3274dfa7ebe891c20e3b8df2aa5d1de12676a3a8ca747d703db52126197a743535640450bb1b89c68a3848129fe5751ac3'
In [6]: s.recover_public_key_from_msg_hash(ut.hash()).to_checksum_address()
Out[6]: '0x5E032243d507C743b061eF021e2EC7fcc6d3ab89'
In [6]: t['from']
Out[6]: '0x5E032243d507C743b061eF021e2EC7fcc6d3ab89'