Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eth_getLogs: invalid argument 0: hex number with leading zero digits #3379

Closed
Troublor opened this issue Feb 19, 2020 · 8 comments
Closed

eth_getLogs: invalid argument 0: hex number with leading zero digits #3379

Troublor opened this issue Feb 19, 2020 · 8 comments
Labels
1.x 1.0 related issues Needs Clarification Requires additional input

Comments

@Troublor
Copy link

Troublor commented Feb 19, 2020

Expected behavior

Event listeners should work as expected

Actual behavior

Sometimes, especially when eth.blockNumber < 0x10, when an event is emitted in smart contract, error shows up on Geth console, saying

WARN [02-19|16:11:41.797] Served eth_getLogs                       conn=127.0.0.1:54766 reqid=7427621993364793 t=40.278µs err="invalid argument 0: hex number with leading zero digits"

and the event listener does not work.

Steps to reproduce the behavior

  1. Initialize a new private blockchain using geth, and make it only have less than 16 blocks.
  2. Listen to events using web3.js
let inst = new web3.eth.Contract(abi, contractAddr);
    inst.events.allEvents({
        fromBlock: 'genesis'
    }, function (err, event) {
        console.log("event:", event);
    }).on("connected", function (subscriptionId) {
        console.log("connected:", subscriptionId);
    })
        .on('data', function (event) {
            console.log("data:", event); // same results as the optional callback above
        })
        .on('changed', function (event) {
            // remove event from local database
            console.log("changed:", event);
        })
        .on('error', function (error, receipt) { // If the transaction was rejected by the network with a receipt, the second parameter will be the receipt.
            console.log("err:", error);
            console.log(receipt)
        });
  1. Send a transaction which invokes a smart contract method which emits an event and mine it.
  2. Geth will output error when web3.js tries to get logs from blockchain with fromBlock < 0x10
WARN [02-19|16:11:41.797] Served eth_getLogs                       conn=127.0.0.1:54766 reqid=7427621993364793 t=40.278µs err="invalid argument 0: hex number with leading zero digits"

Logs

JavaScript console from web3.js

no errors

Geth console
INFO [02-19|16:11:32.237] Commit new mining work                   number=5 sealhash=3ee081…e7f8e4 uncles=0 txs=0 gas=0 fees=0 elapsed=102.326µs
INFO [02-19|16:11:32.237] Commit new mining work                   number=5 sealhash=b1ac95…e09d8a uncles=0 txs=1 gas=23714 fees=2.3714e-05 elapsed=306.395µs
INFO [02-19|16:11:32.425] Successfully sealed new block            number=5 sealhash=b1ac95…e09d8a hash=06b6f1…f4dea3 elapsed=187.932ms
INFO [02-19|16:11:32.425] 🔨 mined potential block                  number=5 hash=06b6f1…f4dea3
> miner.stop()

null
> WARN [02-19|16:11:41.797] Served eth_getLogs                       conn=127.0.0.1:54766 reqid=7427621993364793 t=40.278µs err="invalid argument 0: hex number with leading zero digits"

JSON-RPC Package using Wireshark
EàA@@ù	Æ!a¨-@aëÕ
"ôæ¿"ôæ¿POST / HTTP/1.1
Host: 127.0.0.1:8545
Connection: keep-alive
Content-Length: 179
Accept: application/json
Sec-Fetch-Dest: empty
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.106 Safari/537.36
Content-Type: application/json
Origin: chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn
Sec-Fetch-Site: none
Sec-Fetch-Mode: cors
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,zh-HK;q=0.6,zh-TW;q=0.5

{"id":7427621993364686,"jsonrpc":"2.0","method":"eth_getLogs","params":[{"fromBlock":"0x05","toBlock":"0x5","address":["0x0aa27e4b13d5c08a8767b36a0acb76ed4549b7ea"],"topics":[]}]}

Versions

Web3.js: 1.2.6, installed using Node.js v8.17.0 with NPM v6.13.4
Geth: 1.9.10-stable

@Troublor
Copy link
Author

Judging from the JSON-RPC Http package, I suspect there is a bug in web3.js when trying to fill the fromBlock field of eth_getLogs JSON-RPC, which is failing to strip prefix zeros.

@nivida
Copy link
Contributor

nivida commented Feb 20, 2020

Thanks for opening this issue! We will check that closer asap.

@nivida nivida added 1.x 1.0 related issues Needs Clarification Requires additional input labels Feb 20, 2020
@Troublor
Copy link
Author

@nivida By the way, I used MetaMask as ethereum provider by const web3 = new Web3(ethereum);. I am not sure if this problem is induced by MetaMask or not.

@cgewecke
Copy link
Collaborator

cgewecke commented Feb 24, 2020

@Troublor

I wasn't able to reproduce this using 'genesis'.

It does seem like an issue if you use a hex string as the argument to fromBlock, but that's not really one of the supported formats

# String here means 'latest', 'earliest', etc...
Number|String|BN|BigNumber 

In your wireshark output I see...

"params":[{"fromBlock":"0x05","toBlock":"0x5"...

Are you setting that 0x05 yourself?

@Troublor
Copy link
Author

Troublor commented Feb 25, 2020

@cgewecke I didn't set the fromBlock using hex string. I simplified the steps of reproduction as follows:

  1. Initialize a new private chain using genesis.json:
{
  "config": {
    "chainId": 2020,
    "homesteadBlock": 0,
    "eip150Block": 0,
    "eip155Block": 0,
    "eip158Block": 0,
    "byzantiumBlock": 0,
    "constantinopleBlock": 0,
    "petersburgBlock": 0,
    "istanbulBlock": 0,
    "muirGlacierBlock": 0
  },
  "alloc": {
    "2ecB718297080fF730269176E42C8278aA193434": {
        "balance": "1606938044258990275541962092341162602522202993782792835301376"
    }
  },
  "nonce": "0x000000000000002a",
  "difficulty": "0x02000",
  "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "coinbase": "0x0000000000000000000000000000000000000000",
  "timestamp": "0x00",
  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "extraData": "0x",
  "gasLimit": "0x5f5e100"
}

I allocated some balance to this account 2ecB718297080fF730269176E42C8278aA193434, which will be used later to send transaction.

  1. Start geth console:
geth --datadir testDir/ init testDir/genesis.json 
geth --datadir testDir/ --networkid 2020 --nodiscover --ipcdisable --port 30301 --rpc --rpcport 8545 --syncmode full console
  1. Connect to private chain using MetaMask:
http://127.0.0.1:8545

Reset the MetaMask to reset the account nounce.

  1. open a webpage in browser:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Test 1</title>
    <script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script>
</head>
<body>
<button onclick="Deploy()">Deploy Contract</button>
<script>
    const from = '0x2ecb718297080ff730269176e42c8278aa193434'; // This account is the one allocated in genesis.json
    const web3 = new Web3(ethereum);
    const bytecode = "6080604052348015600f57600080fd5b507f4be3cc765465b935ed0199e6e8b6be8003a65e3329002a60e7a817f3b734e88233604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a1603f8060806000396000f3fe6080604052600080fdfea2646970667358221220fd91b74592ed3d345b06a1ca136ed6ed155ee97c1f8467ec97bdf78c4b91a8fd64736f6c63430006020033";
    const abi = [
        {
            "inputs": [],
            "stateMutability": "nonpayable",
            "type": "constructor"
        },
        {
            "anonymous": false,
            "inputs": [
                {
                    "indexed": false,
                    "internalType": "address",
                    "name": "owner",
                    "type": "address"
                }
            ],
            "name": "ConstructEvent",
            "type": "event"
        }
    ];
    web3.eth.subscribe('logs', {}, function (error, result) {
        if (!error)
            console.log("result:", result);
        else
            console.log("err:", error);
    });

    function Deploy() {
        let myContract = new web3.eth.Contract(abi);
        myContract.deploy({
            data: bytecode,
        }).send({
            from: from,
        }).on('error', function (error) {
            console.log("error:", error)
        }).on('transactionHash', function (transactionHash) {
            console.log("hash:", transactionHash);
        }).on('receipt', function (receipt) {
            console.log("receipt:", receipt)
        });
    }
</script>
</body>
</html>

The smart contract is:

contract TestContract {
    event ConstructEvent(address owner);
    constructor() public {
        emit ConstructEvent(msg.sender);
    }
}

Compiled using Solidity 0.6.2 in Remix.

  1. Click the button in the webpage which is meant to send transaction and create a new contract.

  2. In the geth console, miner.start(), and after the transaction is mined, stop mining by miner.stop(). Note that the current blockNumber should be lower than 16.

  3. Wait until MetaMask posts a notification saying the transaction has been mined and check the geth console, there is an error message:

WARN [02-25|13:18:14.476] Served eth_getLogs                       conn=127.0.0.1:58718 reqid=3956408619580516 t=68.506µs  err="invalid argument 0: hex number with leading zero digits"

@cgewecke
Copy link
Collaborator

@Troublor Thanks for producing that example.

Have a further simplified this case as a geth unit test PR #3394. It passes, successfully reporting an event from block number 5 on Travis here. (See logged output).

The test is:

  • running on a geth instance with the --dev config and websockets enabled, at 20s mining interval
  • connecting to geth via WebsocketProvider (this is the principal mode Web3 support subscriptions for - not http)

The test suggests the underlying issue may be with Metamask which implements it's own subscription strategy over HTTP using polling behind the scenes.

Could you try running some version of the example in #3394 locally using just a node script or mocha test, connecting over websockets and seeing if that works?

@Troublor
Copy link
Author

@cgewecke Indeed, the issue does not exist with websocket provider. Its seems like this is an issue in the provider offered by MetaMask. MetaMask doesn't support websocket provider yet. I might consider report this issue to MetaMask.

Thanks for your effort.

@cgewecke
Copy link
Collaborator

@Troublor Thanks for reporting and figuring this out! I'm sure other people will run into this as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
1.x 1.0 related issues Needs Clarification Requires additional input
Projects
None yet
Development

No branches or pull requests

3 participants