0

I'm trying to benchmark a private blockchain network (3 Vagrant nodes with 2gb of RAM running Geth Clique PoA, on an i7 7th gen Intel Core machine), following this process:

  • A function launch n functions per second
  • Those launched functions are reading a JSON file indicating what they should do (ex: deploy a contract and execute those 2 functions).
  • Thus, they compile, deploy and transact with the smart contract according to the JSON file using Web3 library and Solc.

The problem is the following: Sometimes, transactions are failing for multiple reasons, such as:

  • Error: The contract code couldn't be stored, please check your gas limit.
  • Error: Invalid JSON RPC response: ""
  • Error: Returned error: known transaction: 81fef157995faa9fe32b685e2c5b8d274612a6c2a31fa32008d06e8e3ea05cb8
  • Error: Failed to check for transaction receipt:

Block time is set at 0 (if I understood well, every incoming tx is automatically added to a block), the gas limit is very high (0x346DC5D638865) and gas price is set to 0 (and even so, accounts are well funded).

As an example, for a benchmark of 100 functions launched by second, that have to deploy a smart-contract and execute 1 send/1 call function, benchmark duration being 50 seconds, results are the following:

[50037.15841400018] Tasks launched: 1891 [50037.18162100017] Tasks successfully finished: 561 [50037.19864200009] Benchmarks functions launched: 5000 [50037.21361899981] Benchmarks functions done: 567 [50037.228593999986] Benchmarks functions failed: 1600

Only 567 function execution was completed, 1600 failed and others were executing when benchmark stops ...

https://github.com/nicoSix/sc-archi-gen/tree/supply-chain-bench my code is available here, but the 2 main functions are the following:

//runWorkflow
//- read a json file containing benchmark instructions, deploys linked smart-contract then perform each function at once
async function runWorkflow(idBench) {
    benchmarkLaunchedCount++;
    var execResult = true;
    var startTime = performance.now();
    var machineId = allocateTaskToMachine();
    var scWorkflow = require("./contracts/" + benchmarkContractFN.split('.').slice(0, -1).join('.') + ".json")

    try {
        var contract = await deployContract(machineId, scWorkflow[0]);
    }
    catch(e) {
        execResult = false;
        if (VERBOSE) tlog(e);
    }

    if(execResult) {
        for(var i = 1; i < scWorkflow.length; i++) {
            opLaunchCount++;

            try {
                var parameters = resolveParameters(scWorkflow[i].parameters, machineId);
                var execResult = await contract.methods[scWorkflow[i].name](...parameters)[scWorkflow[i].type]({from: machines[machineId].address, gas: '0x346DC5D638', gasPrice: '0x0'});

                if(execResult.transactionHash || execResult) {
                    opSuccessCount++;
                }
                else {
                    execResult = false;
                    break;
                }
            }
            catch(e) {
                execResult = false;
                if (VERBOSE) tlog(e);
            }
        }
    }

    var endTime = performance.now();

    machines[machineId].load -= 1;

    ... just saving results after this line ...
}
//deployContract
//- deploys a smart-contract
async function deployContract(machineId, constructorDef) {
    // Compile the source code

    const parameters = resolveParameters(constructorDef.parameters, machineId);

    //Deploy the contract and return instance
    var contract = await new machines[machineId]["provider"].eth.Contract(contractCode.abi)
        .deploy({
            data: '0x' + contractCode.bytecode,
            arguments: parameters
        })
        .send({
            from: machines[machineId].address,
            gas: '0x346DC5D638',
            gasPrice: '0x0'
        })

    return contract;
}

What could cause transaction failure? Could it be bad management of nonce or other related stuff in Web3? Could nodes struggle that much for that amount of incoming transactions?

  • 1
    I'd suggest to analyze each error separately: 1) can be a problem with failure to compile correctly, incorrect parameters 2) it looks like a resource exhaustion/timeout in geth 3) you send the exactly same transaction more than once (or you find a keccak collision) 4) never seen that error (perhaps failed to get tx receipt). Check your resources 2Gb of RAM doesn't seem much, don't go directly for thousands of transactions, start with tens an increase to known your setup limitations. Ethereum mainnet is in the 10-20 TPS. – Ismael Jan 17 at 11:58
  • @Ismael I tried several things following your response : I checked compiler parameters, and add randomness to contract constructor parameters, I ran the benchmark on 64gb RAM nodes and I increased transaction pool size on every node, without any success. I also tried to set up the nonce manualy but transactions wont complete anymore, due to a too high or too low nonce (stuck in queue or rejected). – Nicolas Six Jan 24 at 15:24
  • Do you know why transactions are stuck? If it is related to gap in the nonces one possible cause is geth might have dropped transactions if they took too long to be mined. Nonce too high or low can be caused by using the same account from two different clients. – Ismael Jan 30 at 21:41

Your Answer

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

Browse other questions tagged or ask your own question.