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?