Go-ethereum: Simple ETH sendTransaction fails in --dev mode with new 1.8.0 release

Created on 14 Feb 2018  Â·  13Comments  Â·  Source: ethereum/go-ethereum

System information

Geth version: 1.8.0
OS & Version: Linux 64-bit
Commit hash : downloaded release version

Expected behaviour

Transaction receipt is returned when requested.

Actual behaviour

eth_getTransactionReceipt returns "unknown transaction" in dev mode.

Steps to reproduce the behaviour

Run geth in --dev --dev.period=1 mode. Execute a simple send transaction of ETH from one account to another using web3 1.0.

web3.eth.sendTransaction({from:accounts[0],to:accounts[1],value:web3.utils.toWei('10')})

JSON RPC trace:

{"jsonrpc":"2.0","id":15,"method":"eth_sendTransaction","params":[{"from":"0x494ffe3c7e8bd95833d60cd1a3722efef3e8c246","to":"0xd6793d4f4ae1c88065578d0b097d016118128321","value":"0x3635c9adc5dea00000","gasPrice":"0x1"}]}
{"jsonrpc":"2.0","id":15,"result":"0x5acc370a3517ed67951a7525fccc1c2e0fd394f4e6796ebbbf98ae1a1cc50384"}\n
{"jsonrpc":"2.0","id":16,"method":"eth_getTransactionReceipt","params":["0x5acc370a3517ed67951a7525fccc1c2e0fd394f4e6796ebbbf98ae1a1cc50384"]}
{"jsonrpc":"2.0","id":16,"error":{"code":-32000,"message":"unknown transaction"}}\n

Most helpful comment

There's been a change in geth's behavior when a receipt for an unknown transaction hash is requested between 1.7.x and 1.8.0. Previously, calling eth_getTransactionReceipt simply returned 'null' (as success jsonrpc response, not an error).

In 1.8.0, geth returns a (nowhere-documented) jsonrpc error response (with a generic -32000 error code).

Please see the following curl transcripts:

  • Old Behavior
$ curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":1}' https://mainnet.infura.io/XXXXXXXXXXX
{"jsonrpc":"2.0","id":1,"result":"Geth/v1.7.3-stable-8c95ba44/linux-amd64/go1.9.2"}

$ curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],"id":1}' https://mainnet.infura.io/XXXXXXXXXXX
{"jsonrpc":"2.0","id":1,"result":null}
  • New behavior
$ curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":1}' http://ethjsonrpc.mchange.com:8545/
{"jsonrpc":"2.0","id":1,"result":"Geth/v1.8.0-stable/linux-amd64/go1.9.3"}

$ curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],"id":1}' http://ethjsonrpc.mchange.com:8545/
{"jsonrpc":"2.0","id":1,"error":{"code":-32000,"message":"unknown transaction"}}

This change breaks other applications expecting the old behavior, not just the Javascript web3 library. Whichever way it is ultimately handled, this case (asking for a transaction receipt of an unknown or pending transaction) should be specified and documented in the Ethereum jsonrpc spec somewhere, I think.

All 13 comments

Hmmm, seems to work for me https://gist.github.com/karalabe/ed1ca7128f75e1f7d694dbd4a5b7e7cd.

Could you detail a bit more about your setup? Perhaps you're simply not waiting for the transaction to be mined and that's why it returns "unknown"?

Hmm, interesting. I'm running code that works on 1.7.3 and consistently breaks on 1.8.0. I thought that would be enough to reproduce. Let me try to create a script and attach it.

Ok, the following script reproduces the issue on my machine:

(async () => {
  const Web3 = require('web3')
  const web3 = new Web3('ws://localhost:8546')

  const accounts = await web3.eth.getAccounts()

  if (accounts.length == 1) {
    // Create new account
    const newAccount = await web3.eth.personal.newAccount("password")
    accounts.push(newAccount)
  }

  console.log("accounts=" + accounts)

  const tx = await web3.eth.sendTransaction({
    from: accounts[0],
    to: accounts[1],
    value: web3.utils.toWei('1000')
  })

  console.log("tx=" + tx)

})()

This happens running geth using the following command line options, on an Ubuntu Linux box using the 1.8.0 x64 release.

geth --dev -dev.period 1 --networkid 1001 --ws --wsapi web3,eth,net,admin,personal,debug --wsaddr "0.0.0.0" --wsport 8546 --wsorigins "*" --targetgaslimit 7500000 console

The only package dependency is web3. The script simply creates a new account if there's only the single dev account, then does a send transaction. The variable tx is never returned, web3 throws an error waiting for the Tx receipt. The output I get is:

$ node script.js 
accounts=0xf89C75381ECb3f173D9Bed88b607fD4D5dE1A086,0x91666A5DF6022A2eb305180F7c07463fac720eAb
(node:19598) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Failed to check for transaction receipt:
{}

The JSON RPC capture is:

$ ./monitor.sh 
Capturing on 'Loopback'
{"jsonrpc":"2.0","id":1,"method":"eth_accounts","params":[]}
{"jsonrpc":"2.0","id":1,"result":["0xe7daaa0d61fd45280ef8bd39f9d566226fe198ce"]}\n
{"jsonrpc":"2.0","id":2,"method":"personal_newAccount","params":["password"]}
{"jsonrpc":"2.0","id":2,"result":"0x6481a7128bc66ce03184ddbfe1ddd6a12bb0eb08"}\n
{"jsonrpc":"2.0","id":3,"method":"eth_gasPrice","params":[]}
{"jsonrpc":"2.0","id":3,"result":"0x1"}\n
{"jsonrpc":"2.0","id":4,"method":"eth_sendTransaction","params":[{"from":"0xe7daaa0d61fd45280ef8bd39f9d566226fe198ce","to":"0x6481a7128bc66ce03184ddbfe1ddd6a12bb0eb08","value":"0x3635c9adc5dea00000","gasPrice":"0x1"}]}
{"jsonrpc":"2.0","id":4,"result":"0x55375b2a82edcaf43f76250e1f356c0eb8ea11454ac3c86d283d84f720176c6b"}\n
{"jsonrpc":"2.0","id":5,"method":"eth_getTransactionReceipt","params":["0x55375b2a82edcaf43f76250e1f356c0eb8ea11454ac3c86d283d84f720176c6b"]}
{"jsonrpc":"2.0","id":5,"error":{"code":-32000,"message":"unknown transaction"}}\n
{"jsonrpc":"2.0","id":6,"method":"eth_subscribe","params":["newHeads"]}
{"jsonrpc":"2.0","id":6,"result":"0x90cec22a723fcc725fb2462733c2880f"}\n
 [truncated]{"jsonrpc":"2.0","method":"eth_subscription","params":{"subscription":"0x90cec22a723fcc725fb2462733c2880f","result":{"parentHash":"0xb3203b0bf1d8ec4f8bb3e2c7961b6c2a2f117c1c595d11c587acf4dcc7452782","sha3Uncles":"0x1dcc4de8dec7
{"jsonrpc":"2.0","id":7,"method":"eth_getTransactionReceipt","params":["0x55375b2a82edcaf43f76250e1f356c0eb8ea11454ac3c86d283d84f720176c6b"]}
{"jsonrpc":"2.0","id":7,"error":{"code":-32000,"message":"unknown transaction"}}\n
{"jsonrpc":"2.0","id":8,"method":"eth_unsubscribe","params":["0x90cec22a723fcc725fb2462733c2880f"]}
{"jsonrpc":"2.0","id":8,"result":true}\n

This is the output running the identical script using geth 1.7.3 from the command line with the identical options:

$ node script
accounts=0x8224FCb942d79d6803217ABF88084c204E797139,0xeC67e0996ade626204C17f1e10f5612175f5603e
tx={"blockHash":"0xb75dd1d1e75baaad97823334c25b4ba7e16c2fa5e3a91604d55060228069ff71","blockNumber":22,"contractAddress":null,"cumulativeGasUsed":21000,"from":"0x8224fcb942d79d6803217abf88084c204e797139","gasUsed":21000,"logs":[],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","status":"0x1","to":"0xec67e0996ade626204c17f1e10f5612175f5603e","transactionHash":"0x4cbdabc9d0c3c4b0613b6781aeeab5dcbaf8babf4a44873bf1200ac4e833b163","transactionIndex":0}

Hope that helps reproduce there. Let me know if you have any additional questions.

Thanks

System information
Geth version: 1.8.0
OS & Version: MAC OS X

Facing same issue for geth api sendTransaction,
api returning error

Error: Failed to check for transaction receipt: {} at Object._fireError (/Users/Sachin/openst-platform/node_modules/web3-utils/src/index.js:56:17) at /Users/Sachin/openst-platform/node_modules/web3-core-method/src/index.js:259:23 at tryCatcher (/Users/Sachin/openst-platform/node_modules/web3-core-promievent/node_modules/bluebird/js/release/util.js:16:23) at Promise._settlePromiseFromHandler (/Users/Sachin/openst-platform/node_modules/web3-core-promievent/node_modules/bluebird/js/release/promise.js:497:31) at Promise._settlePromise (/Users/Sachin/openst-platform/node_modules/web3-core-promievent/node_modules/bluebird/js/release/promise.js:555:18) at Promise._settlePromise0 (/Users/Sachin/openst-platform/node_modules/web3-core-promievent/node_modules/bluebird/js/release/promise.js:600:10) at Promise._settlePromises (/Users/Sachin/openst-platform/node_modules/web3-core-promievent/node_modules/bluebird/js/release/promise.js:679:18) at Async._drainQueue (/Users/Sachin/openst-platform/node_modules/web3-core-promievent/node_modules/bluebird/js/release/async.js:125:16) at Async._drainQueues (/Users/Sachin/openst-platform/node_modules/web3-core-promievent/node_modules/bluebird/js/release/async.js:135:10) at Immediate.Async.drainQueues (/Users/Sachin/openst-platform/node_modules/web3-core-promievent/node_modules/bluebird/js/release/async.js:16:14) at runCallback (timers.js:800:20) at tryOnImmediate (timers.js:762:5) at processImmediate [as _immediateCallback] (timers.js:733:5)

Can repro it locally too, looking into it.

Hmmm, this may be a bug in web3 actually, or a combo bug. I've printed some detailed logs, about what Geth is doing while web3 is poking it:

Geth starts mining block 6, which is empty at this point:

INFO [02-14|21:29:18] Commit new mining work                   number=6 txs=0 uncles=0 elapsed=359.345µs

Web3 submits the transaction and Geth acknowledges it.

{"jsonrpc":"2.0","id":4,"method":"eth_sendTransaction","params":[{"from":"0x6bca31e6c211c21e0d95033230660f6f623c31f4","to":"0x3603ea324d3b4ebf581869d647ef90e1f52d7d15","value":"0x3635c9adc5dea00000","gasPrice":"0x1"}]}
INFO [02-14|21:29:18] Submitted transaction                    fullhash=0xb4a9f0b9f3b1e03a561f35f3e3095b45ba5519496dfc6e678c0d9338d5648d17 recipient=0x3603EA324D3b4EBF581869D647Ef90e1F52D7D15

Web3 tries to instantly retrieve the receipt, it cannot be found, so it subscribes to new blocks:

{"jsonrpc":"2.0","id":5,"method":"eth_getTransactionReceipt","params":["0xb4a9f0b9f3b1e03a561f35f3e3095b45ba5519496dfc6e678c0d9338d5648d17"]}
{"jsonrpc":"2.0","id":6,"method":"eth_subscribe","params":["newHeads"]}

Geth finishes mining the empty block 6, announces it to web3 and starts mining block 7 with the transaction in it:

INFO [02-14|21:29:19] Successfully sealed new block            number=6 hash=f0db33…60af0d
TRACE[02-14|21:29:19] Announced block                          hash=f0db33…60af0d recipients=0 duration=2562047h47m16.854s
INFO [02-14|21:29:19] Commit new mining work                   number=7 txs=1 uncles=0 elapsed=1.343ms

Web3 tries to retrieve the receipt, which is not yet ready (being mined), so it aborts:

{"jsonrpc":"2.0","id":7,"method":"eth_getTransactionReceipt","params":["0xb4a9f0b9f3b1e03a561f35f3e3095b45ba5519496dfc6e678c0d9338d5648d17"]}
{"jsonrpc":"2.0","id":8,"method":"eth_unsubscribe","params":["0xc02d3086f920ccd7c84386ecd76e58d7"]}

Geth finishes mining the block with the transaction.

INFO [02-14|21:29:20] Successfully sealed new block            number=7 hash=f46a90…91e7ef

Geth's fault: While a transaction is pooled up but not yet mined, it doesn't return any receipt for it. Question is, should it?

Web3's fault: Why does it stop fetching receipts after the first block (which doesn't contain said transaction)?

According to https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionreceipt:

Note That the receipt is not available for pending transactions.

Which would mean Geth is correct in its behavior.

@evertonfraga @frozeman ?

i wonder if this might be related to another issue I've seen with dev.period=0 (instaseal). intermittently, an event will not be returned synchronously with the transaction. it causes the communication to lock up (web3 waiting) and geth won't deliver the event until you prod it with another sendTransaction(). fairly easy to reproduce and similar feel. just thinking aloud, have not been in the code at all...

facing exactly the same issue. A very simple basic web3.eth.sendTransaction() leads to this failure.

There's been a change in geth's behavior when a receipt for an unknown transaction hash is requested between 1.7.x and 1.8.0. Previously, calling eth_getTransactionReceipt simply returned 'null' (as success jsonrpc response, not an error).

In 1.8.0, geth returns a (nowhere-documented) jsonrpc error response (with a generic -32000 error code).

Please see the following curl transcripts:

  • Old Behavior
$ curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":1}' https://mainnet.infura.io/XXXXXXXXXXX
{"jsonrpc":"2.0","id":1,"result":"Geth/v1.7.3-stable-8c95ba44/linux-amd64/go1.9.2"}

$ curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],"id":1}' https://mainnet.infura.io/XXXXXXXXXXX
{"jsonrpc":"2.0","id":1,"result":null}
  • New behavior
$ curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"web3_clientVersion","params":[],"id":1}' http://ethjsonrpc.mchange.com:8545/
{"jsonrpc":"2.0","id":1,"result":"Geth/v1.8.0-stable/linux-amd64/go1.9.3"}

$ curl -X POST -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238"],"id":1}' http://ethjsonrpc.mchange.com:8545/
{"jsonrpc":"2.0","id":1,"error":{"code":-32000,"message":"unknown transaction"}}

This change breaks other applications expecting the old behavior, not just the Javascript web3 library. Whichever way it is ultimately handled, this case (asking for a transaction receipt of an unknown or pending transaction) should be specified and documented in the Ethereum jsonrpc spec somewhere, I think.

I'm guessing this is the change what done it... https://github.com/ethereum/go-ethereum/commit/e9971d356bf977d2a3f63e50296d7410ade2d075#diff-607ee6300c766df112070d851a1661c9

https://github.com/ethereum/go-ethereum/pull/16217 should fix this issue (pending review). We didn't realize that the changed linked above violated an API behavioral expectancy.

Whilst I can't unilaterally say the old behavior is the good one and the new is the bad one, there's obviously problems in the RPC spec that it does not specify any error handling whatsoever, so people grew to the current behavior. Not happy about it, but I agree that we shouldn't break it.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

vogelito picture vogelito  Â·  3Comments

freshonline picture freshonline  Â·  3Comments

VenusHu picture VenusHu  Â·  3Comments

362228416 picture 362228416  Â·  3Comments

wighawag picture wighawag  Â·  3Comments