Skip to content

Instantly share code, notes, and snippets.

@cdetrio
Created April 2, 2019 18:07
Show Gist options
  • Save cdetrio/0045e1db6b142acdcc26c16519c8a6ee to your computer and use it in GitHub Desktop.
Save cdetrio/0045e1db6b142acdcc26c16519c8a6ee to your computer and use it in GitHub Desktop.
minimal node.js script for benchmarking ewasm contracts/precompiles
// node --experimental-wasm-bigint ewasm-bencher.js bn128mul_metered.wasm "039730ea8dff1254c0fee9c0ea777d29a9c710b7e616683f194f18c43b43b869073a5ffcc6fc7a28c30723d6e58ce577356982d65b833a5a5c15bf9024b43d98ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" "00a1a234d08efaa2616607e31eca1980128b00b415c845ff25bba3afcb81dc00242077290ed33906aeb8e42fd98c41bcb9057ba03421af3f2d08cfc441186024"
var args = process.argv.slice(2);
var wasmfile = args[0];
var input = args[1];
var expected = args[2];
if (args.length < 3) {
console.log('missing an arg!');
process.exit(1);
}
const readAsBinary = filename => {
if (typeof process === 'object' && typeof require === 'function') {
const binary = require('fs').readFileSync(filename);
return !binary.buffer ? new Uint8Array(binary) : binary;
} else
return typeof readbuffer === 'function'
? new Uint8Array(readbuffer(filename))
: read(filename, 'binary');
};
const wasmBytes = readAsBinary(wasmfile)
let totalGasUsed = BigInt(0);
let useGasCalls = 0;
let exported_mem;
const inputBytes = new Uint8Array(Math.ceil(input.length / 2));
function getCallDataSize() {
return inputBytes.length;
}
function useGas(a) {
totalGasUsed = totalGasUsed + a;
useGasCalls = useGasCalls + 1;
}
function callDataCopy(resultOffset, dataOffset, length) {
for (var i = 0; i < inputBytes.length; i++) inputBytes[i] = parseInt(inputHex.substr(i * 2, 2), 16);
const asBytes = new Uint8Array(exported_mem.buffer, resultOffset, length+1);
asBytes.set(inputBytes);
}
function revert (dataOffset, dataLength) {
console.log('revert dataOffset, dataLength', dataOffset, dataLength)
}
function finish (dataOffset, dataLength) {
const returnBytes = new Uint8Array(exported_mem.buffer, dataOffset, dataLength);
let convertedBack = '';
for (var i = 0; i < dataLength; i++) {
if (returnBytes[i] < 16) convertedBack += '0';
convertedBack += returnBytes[i].toString(16);
}
if (convertedBack == expected) {
throw "finished normally!";
} else {
console.error('Expected: ' + expected + ' got: ' + convertedBack);
throw "incorrect return val!"
}
}
const imports = {
ethereum: {
'getCallDataSize': getCallDataSize,
'useGas': useGas,
'callDataCopy': callDataCopy,
'finish': finish,
'revert': revert
},
env: {}
};
imports.env.memory = new WebAssembly.Memory({ initial: 10 })
console.time('instantiate');
WebAssembly.instantiate(wasmBytes, imports)
.then(r => {
exported_mem = r.instance.exports.memory;
console.timeEnd('instantiate');
console.time('exec');
try {
r.instance.exports.main();
console.timeEnd('exec');
} catch (e) {
console.timeEnd('exec');
if (e == "finished normally!") {
console.log('gas used:', totalGasUsed);
console.log('useGas calls:', useGasCalls);
} else {
console.log('caught error:', e)
}
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment