From 8a7b3cd734a208ba658678a59e809aa072dddda8 Mon Sep 17 00:00:00 2001 From: Ignasi Date: Mon, 29 Jan 2024 17:16:44 +0100 Subject: [PATCH] Improve virtual counters --- package.json | 2 +- src/virtual-counters-manager.js | 62 +++++++++++++++++++++------------ 2 files changed, 40 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index 6a0e9c24..7f354c42 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "@ethereumjs/block": "^3.6.2", "@ethereumjs/tx": "^3.4.0", "@polygon-hermez/common": "2.6.4", - "@polygon-hermez/vm": "6.0.10", + "@polygon-hermez/vm": "6.0.11", "ethereumjs-util": "^7.1.4", "ethers": "^5.5.4", "ffjavascript": "^0.2.55", diff --git a/src/virtual-counters-manager.js b/src/virtual-counters-manager.js index 93a8386d..2ba7f13e 100644 --- a/src/virtual-counters-manager.js +++ b/src/virtual-counters-manager.js @@ -507,7 +507,7 @@ module.exports = class VirtualCountersManager { this._checkInput(input, ['inputSize']); this._reduceCounters(100, 'S'); this._reduceCounters(2, 'B'); - this._saveMem(); + this._saveMem({length: input.inputSize}); this._offsetUtil(); this._multiCall('_opCalldataCopyLoop', Math.floor(input.inputSize / 32)); this._readFromCalldataOffset(); @@ -544,7 +544,7 @@ module.exports = class VirtualCountersManager { this._reduceCounters(2 * MCP + Math.ceil(input.bytecodeLen / 56), 'P'); this._reduceCounters(Math.ceil(input.bytecodeLen / 56), 'D'); this._multiCall('_divArith', 2); - this._saveMem(); + this._saveMem({length: input.inputSize}); this._mulArith(); this._reduceCounters(input.inputSize, 'M'); this._multiCall('_opCodeCopyLoop', input.inputSize); @@ -559,7 +559,7 @@ module.exports = class VirtualCountersManager { } else { this._reduceCounters(40, 'S'); this._reduceCounters(3, 'B'); - this._saveMem(); + this._saveMem({length: input.inputSize}); this._divArith(); this._mulArith(); this._multiCall('_opCodeCopyLoop', input.inputSize); @@ -584,7 +584,7 @@ module.exports = class VirtualCountersManager { this._checkInput(input, ['inputSize']); this._reduceCounters(50, 'S'); this._reduceCounters(2, 'B'); - this._saveMem(); + this._saveMem({length: input.inputSize}); this._divArith(); this._mulArith(); this._multiCall('_returnDataCopyLoop', Math.floor(input.inputSize / 32)); @@ -705,11 +705,11 @@ module.exports = class VirtualCountersManager { opCreate(input) { this._opcode(input); - this._checkInput(input, ['bytesNonceLength']); + this._checkInput(input, ['bytesNonceLength','inLength']); this._reduceCounters(70, 'S'); this._reduceCounters(3, 'B'); this._reduceCounters(3 * MCP, 'P'); - this._saveMem(); + this._saveMem({length: input.inLength}); this._getLenBytes({ lenBytesInput: input.bytesNonceLength }); this._computeGasSendCall(); this._saveCalldataPointer(); @@ -719,10 +719,12 @@ module.exports = class VirtualCountersManager { opCall(input) { this._opcode(input); + this._checkInput(input, ['inLength', 'outLength']); this._reduceCounters(80, 'S'); this._reduceCounters(5, 'B'); this._maskAddress(); - this._multiCall('_saveMem', 2); + this._saveMem({length: input.inLength}); + this._saveMem({length: input.outLength}); this._isColdAddress(); this._isEmptyAccount(); this._computeGasSendCall(); @@ -733,10 +735,12 @@ module.exports = class VirtualCountersManager { opCallCode(input) { this._opcode(input); + this._checkInput(input, ['inLength', 'outLength']); this._reduceCounters(80, 'S'); this._reduceCounters(5, 'B'); this._maskAddress(); - this._multiCall('_saveMem', 2); + this._saveMem({length: input.inLength}); + this._saveMem({length: input.outLength}); this._isColdAddress(); this._computeGasSendCall(); this._saveCalldataPointer(); @@ -746,9 +750,11 @@ module.exports = class VirtualCountersManager { opDelegateCall(input) { this._opcode(input); + this._checkInput(input, ['inLength', 'outLength']); this._reduceCounters(80, 'S'); this._maskAddress(); - this._multiCall('_saveMem', 2); + this._saveMem({length: input.inLength}); + this._saveMem({length: input.outLength}); this._isColdAddress(); this._computeGasSendCall(); this._saveCalldataPointer(); @@ -758,9 +764,11 @@ module.exports = class VirtualCountersManager { opStaticCall(input) { this._opcode(input); + this._checkInput(input, ['inLength', 'outLength']); this._reduceCounters(80, 'S'); this._maskAddress(); - this._multiCall('_saveMem', 2); + this._saveMem({length: input.inLength}); + this._saveMem({length: input.outLength}); this._isColdAddress(); this._computeGasSendCall(); this._saveCalldataPointer(); @@ -770,11 +778,11 @@ module.exports = class VirtualCountersManager { opCreate2(input) { this._opcode(input); - this._checkInput(input, ['bytesNonceLength']); + this._checkInput(input, ['bytesNonceLength','inLength']); this._reduceCounters(80, 'S'); this._reduceCounters(4, 'B'); this._reduceCounters(2 * MCP, 'P'); - this._saveMem(); + this._saveMem({length: input.inLength}); this._divArith(); this._getLenBytes({ lenBytesInput: input.bytesNonceLength }); this._computeGasSendCall(); @@ -785,13 +793,12 @@ module.exports = class VirtualCountersManager { opReturn(input) { this._opcode(input); - this._checkInput(input, ['isCreate', 'isDeploy']); + this._checkInput(input, ['isCreate', 'isDeploy','returnLength']); this._reduceCounters(30, 'S'); this._reduceCounters(1, 'B'); - this._saveMem(); + this._saveMem({length: input.returnLength}); if (input.isCreate || input.isDeploy) { if (input.isCreate) { - this._checkInput(input, ['returnLength']); this._reduceCounters(25, 'S'); this._reduceCounters(2, 'B'); this._reduceCounters(2 * MCP, 'P'); @@ -819,7 +826,7 @@ module.exports = class VirtualCountersManager { this._reduceCounters(1, 'B'); this._revertTouched(); this._revertBlockInfoTree(); - this._saveMem(); + this._saveMem({length: input.revertSize}); this._multiCall('_opRevertLoop', Math.floor(input.revertSize / 32)); this._mLoadX(); this._mStoreX(); @@ -896,7 +903,7 @@ module.exports = class VirtualCountersManager { this._checkInput(input, ['inputSize']); this._reduceCounters(40, 'S'); this._reduceCounters(Math.ceil((input.inputSize + 1) / 32), 'K'); - this._saveMem(); + this._saveMem({length: input.inputSize}); this._multiCall('_divArith', 2); this._mulArith(); this._multiCall('_opSha3Loop', Math.floor(input.inputSize / 32)); @@ -969,7 +976,7 @@ module.exports = class VirtualCountersManager { this._opcode(input); this._checkInput(input, ['inputSize']); this._reduceCounters(30 + 8 * 4, 'S'); // Count steps as if topics is 4 - this._saveMem(); + this._saveMem({length: input.inputSize}); this._mulArith(); this._divArith(); this._reduceCounters(Math.ceil(input.inputSize / 56) + 4, 'P'); @@ -1288,7 +1295,7 @@ module.exports = class VirtualCountersManager { opMLoad(input) { this._opcode(input); this._reduceCounters(8, 'S'); - this._saveMem(); + this._saveMem({length: 32}); this._mLoad32(); } @@ -1296,7 +1303,7 @@ module.exports = class VirtualCountersManager { this._opcode(input); this._reduceCounters(22, 'S'); this._reduceCounters(1, 'M'); - this._saveMem(); + this._saveMem({length: 32}); this._offsetUtil(); } @@ -1304,7 +1311,7 @@ module.exports = class VirtualCountersManager { this._opcode(input); this._reduceCounters(13, 'S'); this._reduceCounters(1, 'M'); - this._saveMem(); + this._saveMem({length: 1}); this._offsetUtil(); } @@ -1518,7 +1525,13 @@ module.exports = class VirtualCountersManager { this._multiCall('_SHLarith', 2); } - _saveMem() { + _saveMem(input) { + this._checkInput(input, ['length']); + if(input.length === 0) { + this._reduceCounters(12, 'S'); + this._reduceCounters(1, 'B'); + return; + } this._reduceCounters(50, 'S'); this._reduceCounters(5, 'B'); this._mulArith(); @@ -1618,7 +1631,10 @@ module.exports = class VirtualCountersManager { } else { this._reduceCounters(Math.ceil((input.bytecodeLength + 1) / 56), 'P'); this._reduceCounters(Math.ceil((input.bytecodeLength + 1) / 56), 'D'); - this._divArith(); + // This arith is used to compute the keccaks consumption so its bytecodeLength / 56, in case bytecodeLength < 56, no ariths are used + if(input.bytecodeLength >= 56) { + this._divArith(); + } } }