lets assume I have this private key (test account on ropsten, no need to worry):


When I use Pyethereum to run

v, r, s = ecsign(tx['hash'], normalize_key(private_key))

then v, r, s = (28, 70432465444433342622726730664370509023990924819271715983647847605365849029795, 7960080711554037742197166599216482712965266632510536462814358773930726674178)

When I compare this with the actual transaction:

{'blockHash': HexBytes('0x47b8f62c1400dae65105d2f8e03824bfc58481c0b32f45788ad3378fbc05e9f6'), 
'blockNumber': 4156209, 
'from': '0x4e5C95B38bd0B18B83f130a1ffae58cFC58961DE', 
'gas': 21000, 
'gasPrice': 8000000000, 
'hash': HexBytes('0x8ec420a3ba331f2a967ecdaf69b78bbb604ebbb2554a8c635142b7b306defaae'), 
'input': '0x', 
'nonce': 0, 
'r': HexBytes('0xe298a05754cc5a24790bb8c21ecb60fd93f2d096146af7397440697a338dff46'), 
's': HexBytes('0x5999f680f17e505c979c43a3a9e7707c817efde705f967681d8a5066b49e5352'), 
'to': '0xED6CA7d908f897d0B0D5f9B9E7Aa470698E10b1b', 
'transactionIndex': 27, 
'v': 42, 
'value': 1000000000000000000}

The Values for r,s,v are very different. (Event when I convert them with bytes.from_hex(tx['r']))

Q1: Dose anyone know what I am doing Wrong?

Just to make sure: The transaction was made with metamask and then the key was exported from metamask, so there is no chance that the key to sign the transaction was different.

Q2: Is there a better way to do this?

Thanks in advance :)


The values that you present for the result of the signature are not correct. I did this using the same transaction you show and the privatekey provided by you. When you sign the transaction using the private key that you show, you get:

'r': 102492371167525662808729438177964772018202086674566648709527465604425496526662,

's': 40527872430728510063557974166309434109284218396283342950340797635881485620050,

'v': 42

the representation of r and s in hexadecimal are s = '0x5999f680f17e505c979c43a3a9e7707c817efde705f967681d8a5066b49e5352' r = '0xe298a05754cc5a24790bb8c21ecb60fd93f2d096146af7397440697a338dff46'

that are the values that you show for the actual transaction.


privatekey = '0x785cdcd731a1b2438ec4511a25d04efbdc499ed350df612364af1aa6f4fd6abd'
transaction = {
     'to': '0xED6CA7d908f897d0B0D5f9B9E7Aa470698E10b1b',
     'value': 1000000000000000000,
     'gas': 21000,
     'gasPrice': 8000000000,
     'nonce': 0,
     'chainId': 3}

signed = w3.eth.account.signTransaction(transaction,privatekey)

Note that as @Ismael points out, the issue in your code is that the hash that you are using is not the correct one.

Hope this helps.

| improve this answer | |
  • 1
    It is unrelated to normalize_key but how you sign the transaction. – Ismael Oct 15 '18 at 15:48
  • Hey, thank You for your answer. Could you post the code that worked for you? – SimonSchuler Oct 16 '18 at 10:39
  • 1
    I did this using web3py, I added it to my answer. – Jaime Oct 16 '18 at 12:37

Before EIP155 to sign you hash the RLP encoding of the transaction without r, s, v. See https://github.com/ethereum/pyethereum/blob/develop/ethereum/transactions.py#L133.

The default of tx["hash"] is to include r, s and v in the hash. And your transaction will not validate.

After EIP155 the procedure indicates you have to replace r, s and v for some specific values (the chain_id and zeros).

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.