3

What's the best way to know the block number associated with the result of an eth_call? Assume I have several nodes that i'm running and i'm making calls to all of them (for redundancy). My goal is to get the latest result of an eth_call and maximize the likelyhood that it's accurate.

Option 1.) I can make a call for eth_blockNumber with the 'latest' parameter and then a separate call for my eth_call also with the 'latest' parameter, but there I have no guarantee that the block number didn't change by the time the eth_call was made.

payload = {
        "id": randint(0, 99999999999999),
        "jsonrpc": "2.0",
        "method": "eth_call",
        "params": [
            {
                "data": <DataGoesHere>,
                "to": <ContractAddressGoeshere>
            },
            "latest"
        ]
    }

Option 2.) Or I can specify the specific block number in my eth_call but that seems a little silly because i'm having to guess what the latest block number is. Silly because a node can be a few blocks behind and can catch up at any moment. I can get the current block number and then also in parallel make calls for current + 1 and current + 2 just incase another block or two got quickly mined in.

payload = {
        "id": randint(0, 99999999999999),
        "jsonrpc": "2.0",
        "method": "eth_call",
        "params": [
            {
                "data": <DataGoesHere>,
                "to": <ContractAddressGoeshere>
            },
            currentBlockNumber_hex
        ]
    }

I could also (just to be careful) make a call for currentBlockNumber_hex + 1

payload = {
        "id": randint(0, 99999999999999),
        "jsonrpc": "2.0",
        "method": "eth_call",
        "params": [
            {
                "data": <DataGoesHere>,
                "to": <ContractAddressGoeshere>
            },
            currentBlockNumber_hex + 1
        ]
    }

And while i'm at it, may as well do currentBlockNumber_hex + 2

payload = {
        "id": randint(0, 99999999999999),
        "jsonrpc": "2.0",
        "method": "eth_call",
        "params": [
            {
                "data": <DataGoesHere>,
                "to": <ContractAddressGoeshere>
            },
            currentBlockNumber_hex + 2
        ]
    }

But this seems silly. Is there a better way? I have a lot of nodes for redundancy purposes. And I've noticed that they aren't always perfectly agreeing on the latest data. One or two may get a few blocks behind for various reasons.

For example, I may make an eth_call to all 3 nodes and here are the results:

{
  'node1': {
    'jsonrpc': '2.0',
    'result': '0x14ef054e8f9ef79',
    'id': 38577622847874
  },
  'node2': {
    'jsonrpc': '2.0',
    'result': '0x14ef054e8f9ef79',
    'id': 38577622847874
  },
  'node3': {
    'jsonrpc': '2.0',
    'result': '0x14ef054e8f9ef79',
    'id': 50123622847874
  }
}

And here are the latest block numbers:

node1: 6262258
node2: 6262257
node3: 6262259

Notice that Node 3 is ahead and just so happened to have the latest value, while nodes 1 and 2 are behind and don't yet have the latest state.

If I go with Option 1.) from above, I have no way of knowing if node3's result of 0x14ef054e8f9ef79 is actually from block 6262259 because it was called separately with the 'latest' parameter.

if I go with Option 2.) from above i'm having to make an insane amount of calls just to verify that this is the latest value. I'll be making 9 calls. Node1 on block 6262258, Node1 on block (6262258 + 1), Node1 on block (6262258 + 2). Then Node2 on block 6262257, Node2 on block (6262257 + 1), Node2 on block (6262257 + 2). Then Node3 on block 6262259, Node3 on block (6262259 + 1), Node3 on block (6262259 + 2). So that's 9 calls just to get one value. Granted it's going to increase the likely hood that I have the absolute latest value (compared to Option 1.) so it may be worth it.

Edit: I'm thinking it makes sense to make a websocket connection to each node to listen for a new block number. Then go with that block number for option 2 and not bothering with the +1, +2 future block thingy since it will result it lots of extra calls.

1 Answer 1

0

I implemented Option 2 from my above post and it works very well. I even implemented the ability to, simultaneously and in parallel, inquire for block numbers in the future (the current, current+1, current+2 thing). After lots of testing, I determined that the +1, +2 thing wasn't necessary after doing the following:

1.) Allocate more resources to the machine running the node, specifically more memory. I found that parity nodes with more memory (8gb minimum) are way less likely to get behind a few blocks and even less likely to crash.
2.) poll more aggressively for latest block number.
3.) (still testing with this one vs 2.) Use websocket connection to node to get latest data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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