diff --git a/src/blob-inner/blob-outer-processor.js b/src/blob-inner/blob-outer-processor.js new file mode 100644 index 00000000..8135821e --- /dev/null +++ b/src/blob-inner/blob-outer-processor.js @@ -0,0 +1,155 @@ +/* eslint-disable max-len */ +/* eslint-disable no-restricted-syntax */ +/* eslint-disable no-continue */ +const { Scalar } = require('ffjavascript'); +const Constants = require('../constants'); + +module.exports = class BlobOuter { + /** + * constructor BlobOuterProcessor class + * @param {Object} blobInner - blobInner stark inputs - outputs + * @param {Object} aggBatches - aggregateBatches stark inputs - outputs + */ + constructor( + blobInner, + aggBatches, + ) { + // inputs + this.blobInner = blobInner; + this.aggBatches = aggBatches; + + // internal use + this.builded = false; + + // initialize outputs thta may chnage depending the blobInner and aggBatches + this.newStateRoot = this.blobInner.oldStateRoot; + this.newLocalExitRoot = Constants.ZERO_BYTES32; + this.starkInput = {}; + } + + /** + * Execute Blob Outer + */ + async execute() { + // build blobData + await this._processBlobOuter(); + + // compute stark input + await this._computeStarkInput(); + + this.builded = true; + } + + /** + * Process Blob Outer + */ + _processBlobOuter() { + // sanity check between blobInner and aggregation batches + // oldStateRoot + if (this.blobInner.oldStateRoot !== this.aggBatches.oldStateRoot) { + throw new Error('BlobOuter:_processBlobOuter: oldStateRoot mismatch'); + } + + // forkID + if (this.blobInner.forkID !== this.aggBatches.forkID) { + throw new Error('BlobOuter:_processBlobOuter: oldBlobStateRoot mismatch'); + } + + // add table to map final outputs + // | isInvalid | isZero(accBatch_blob) | isEqualAccBatch | isTimeOK | isIndexEqual | isRootEqual | **newLocalExitRoot** | **newStateRoot** | **FAIL PROOF** | + // |:---------:|:---------------------:|:---------------:|:--------:|:------------:|:-----------:|:--------------------:|:----------------:|:--------------:| + // | 1 | X | X | X | X | X | blob_ler | blob_SR | 0 | + // | 0 | 1 | X | X | X | X | blob_ler | blob_SR | 0 | + // | 0 | 0 | 0 | X | X | X | X | X | 1 | + // | 0 | 0 | 1 | 0 | X | X | blob_ler | blob_SR | 0 | + // | 0 | 0 | 1 | 1 | 0 | X | blob_ler | blob_SR | 0 | + // | 0 | 0 | 1 | 1 | 1 | 0 | X | X | 1 | + // | 0 | 0 | 1 | 1 | 1 | 1 | batch_SR | batch_ler | 0 | + + if (this.blobInner.isInvalid) { + this.newLocalExitRoot = this.blobInner.localExitRootFromBlob; + this.newStateRoot = this.blobInner.oldStateRoot; + + return; + } + + // isZero(accBatch_blob) + if (Scalar.eq(this.blobInner.newBlobAccInputHash, Constants.ZERO_BYTES32)) { + this.newLocalExitRoot = this.blobInner.localExitRootFromBlob; + this.newStateRoot = this.blobInner.oldStateRoot; + + return; + } + + if (Scalar.neq(this.blobInner.finalAccBatchHashData, this.aggBatches.newBatchAccInputHash)) { + throw new Error('BlobOuter:_processBlobOuter: accBatchHashData mismatch'); + } + + if (!Scalar.leq(this.aggBatches.newLastTimestamp, this.blobInner.timestampLimit)) { + this.newLocalExitRoot = this.blobInner.localExitRootFromBlob; + this.newStateRoot = this.blobInner.oldStateRoot; + + return; + } + + if (Scalar.neq(this.blobInner.lastL1InfoTreeIndex, this.aggBatches.currentL1InfoTreeIndex)) { + this.newLocalExitRoot = this.blobInner.localExitRootFromBlob; + this.newStateRoot = this.blobInner.oldStateRoot; + + return; + } + + if (Scalar.neq(this.blobInner.lastL1InfoTreeRoot, this.aggBatches.currentL1InfoTreeRoot)) { + throw new Error('BlobOuter:_processBlobOuter: L1InfoTreeRoot mismatch'); + } + + // set outputs from batch aggregation + this.newLocalExitRoot = this.aggBatches.newLocalExitRoot; + this.newStateRoot = this.aggBatches.newStateRoot; + } + + async _computeStarkInput() { + this.starkInput = { + // inputs + oldStateRoot: this.aggBatches.oldStateRoot, + oldBlobStateRoot: this.blobInner.oldBlobStateRoot, + oldBlobAccInputHash: this.blobInner.oldBlobAccInputHash, + oldNumBlob: this.blobInner.oldNumBlob, + chainID: this.aggBatches.chainID, + forkID: this.blobInner.forkID, + // outputs + newStateRoot: this.newStateRoot, + newBlobStateRoot: this.blobInner.newBlobStateRoot, + newBlobAccInputHash: this.blobInner.newBlobAccInputHash, + newNumBlob: this.blobInner.newNumBlob, + newLocalExitRoot: this.newLocalExitRoot, + }; + } + + /** + * Return stark input + */ + getStarkInput() { + this._isBuilded(); + + return this.starkInput; + } + + /** + * Throw error if blob outer is not already builded + */ + _isNotBuilded() { + if (this.builded) { + throw new Error('BlobProcessor:_isBuilded: already builded'); + } + } + + /** + * Throw error if blob outer is already builded + */ + _isBuilded() { + if (!this.builded) { + throw new Error('BlobProcessor:_isBuilded: must first be builded'); + } + } +}; diff --git a/src/blob-inner/blob-processor.js b/src/blob-inner/blob-processor.js index 8a2f7af5..c288b8e5 100644 --- a/src/blob-inner/blob-processor.js +++ b/src/blob-inner/blob-processor.js @@ -347,7 +347,7 @@ module.exports = class BlobProcessor { ); // invalidate blob - if (this.inInvalid === true) { + if (this.isInvalid === true) { this.finalAccBatchHashData = Constants.ZERO_BYTES32; } else { // compute finalAccBatchHashData @@ -357,7 +357,7 @@ module.exports = class BlobProcessor { this.finalAccBatchHashData, await computeBatchL2HashData(batchData), this.sequencerAddress, - this.forcedHashData, + (this.blobType === blobConstants.BLOB_TYPE.FORCED) ? this.forcedHashData : Constants.ZERO_BYTES32, ); } } diff --git a/src/constants.js b/src/constants.js index f2a7372c..52a06425 100644 --- a/src/constants.js +++ b/src/constants.js @@ -10,6 +10,15 @@ module.exports.DB_GLOBAL_EXIT_ROOT = ethers.utils.id(('ZKEVM_DB_GLOBAL_EXIT_ROOT module.exports.DB_ADDRESS_STORAGE = ethers.utils.id(('ZKEVM_DB_ADDRESS_STORAGE')); module.exports.DB_TOUCHED_ACCOUNTS = ethers.utils.id(('ZKEVM_DB_TOUCHED_ACCOUNTS')); module.exports.DB_STARK_INPUT = ethers.utils.id(('ZKEVM_DB_STARK_INPUT')); +module.exports.DB_AGG_BATCHES = ethers.utils.id(('ZKEVM_DB_AGG_BATCHES')); +module.exports.DB_STARK_BLOB_INNER = ethers.utils.id(('ZKEVM_DB_BLOB_INNER')); +// blob DB keys +module.exports.DB_OUTER_STATE_ROOT = ethers.utils.id(('DB_OUTER_STATE_ROOT')); +module.exports.DB_BLOB_STATE_ROOT = ethers.utils.id(('DB_BLOB_STATE_ROOT')); +module.exports.DB_BLOB_ACC_INPUT_HASH = ethers.utils.id(('DB_BLOB_ACC_INPUT_HASH')); +module.exports.DB_LAST_NUM_BLOB = ethers.utils.id(('DB_LAST_NUM_BLOB')); +module.exports.DB_OUTER_LOCAL_EXIT_ROOT = ethers.utils.id(('DB_OUTER_LOCAL_EXIT_ROOT')); +module.exports.DB_STARK_BLOB_OUTER = ethers.utils.id(('DB_STARK_BLOB_OUTER')); // Default values and global constants module.exports.DEFAULT_MAX_TX = 1000; diff --git a/src/contract-utils.js b/src/contract-utils.js index 5a0eeb76..e2c6b20c 100644 --- a/src/contract-utils.js +++ b/src/contract-utils.js @@ -3,62 +3,88 @@ const { Scalar } = require('ffjavascript'); const { sha256Snark, padZeros } = require('./utils'); /** - * Compute input for SNARK circuit: sha256(aggrAddress, oldStateRoot, oldAccInputHash, oldNumBatch, chainID, forkID, newStateRoot, newAccInputHash, newLocalExitRoot, newNumBatch) % FrSNARK - * @param {String} oldStateRoot - Current state Root - * @param {String} newStateRoot - New State root once the batch is processed - * @param {String} oldBatchAccInputHash - initial accumulateInputHash - * @param {String} newBatchAccInputHash - final accumulateInputHash - * @param {String} newLocalExitRoot - New local exit root once the all batches is processed - * @param {Number} oldNumBatch - initial batch number - * @param {Number} newNumBatch - final batch number - * @param {Number} chainID - L2 chainID - * @param {String} aggregatorAddress - Aggregator Ethereum address in hex string - * @param {Number} forkID - L2 rom fork identifier + * Compute input for SNARK circuit: sha256( + * initStateRoot, initBlobStateRoot, initBlobAccInputHash, initNumBlob, chainId, forkID + * finalStateRoot, finalBlobStateRoot, finalBlobAccInputHash, finalNumBlob, finalLocalExitRoot + * aggregatorAddress + * ) % FrSNARK + * @param {String} initStateRoot - old state root in hex encoding + * @param {String} initBlobStateRoot - old blob state root in hex encoding + * @param {String} initBlobAccInputHash - old blob account input hash in hex encoding + * @param {Number} initNumBlob - old number of blobs + * @param {Number} chainId - chain id + * @param {Number} forkID - fork id + * @param {String} initStateRoot - new state root in hex encoding + * @param {String} initBlobStateRoot - new blob state root in hex encoding + * @param {String} initBlobAccInputHash - new blob account input hash in hex encoding + * @param {Number} initNumBlob - new number of blobs + * @param {String} initLocalExitRoot - new local exit root in hex encoding + * @param {String} aggregatorAddress - aggregator address in hex encoding * @returns {String} - input snark in hex encoding */ async function calculateSnarkInput( - oldStateRoot, - newStateRoot, - newLocalExitRoot, - oldBatchAccInputHash, - newBatchAccInputHash, - chainID, - aggregatorAddress, + initStateRoot, + initBlobStateRoot, + initBlobAccInputHash, + initNumBlob, + chainId, forkID, + finalStateRoot, + finalBlobStateRoot, + finalBlobAccInputHash, + finalNumBlob, + finalLocalExitRoot, + aggregatorAddress, ) { - // 20 bytes aggregator address - const strAggregatorAddress = padZeros((Scalar.fromString(aggregatorAddress, 16)).toString(16), 40); + // 32 bytes each field element for initStateRoot + const strInitStateRoot = padZeros((Scalar.fromString(initStateRoot, 16)).toString(16), 64); + + // 32 bytes each field element for initBlobStateRoot + const strInitBlobStateRoot = padZeros((Scalar.fromString(initBlobStateRoot, 16)).toString(16), 64); - // 32 bytes each field element for oldStateRoot - const strOldStateRoot = padZeros((Scalar.fromString(oldStateRoot, 16)).toString(16), 64); + // 32 bytes each field element for initBlobAccInputHash + const strInitBlobAccInputHash = padZeros((Scalar.fromString(initBlobAccInputHash, 16)).toString(16), 64); - // 32 bytes each field element for oldStateRoot - const strOldBatchAccInputHash = padZeros((Scalar.fromString(oldBatchAccInputHash, 16)).toString(16), 64); + // 8 bytes for initNumBlob + const strInitNumBlob = padZeros(Scalar.e(initNumBlob).toString(16), 16); // 8 bytes for chainID - const strChainID = padZeros(Scalar.e(chainID).toString(16), 16); + const strChainID = padZeros(Scalar.e(chainId).toString(16), 16); // 8 bytes for forkID const strForkID = padZeros(Scalar.e(forkID).toString(16), 16); - // 32 bytes each field element for oldStateRoot - const strNewStateRoot = padZeros((Scalar.fromString(newStateRoot, 16)).toString(16), 64); + // 32 bytes each field element for finalStateRoot + const strFinalStateRoot = padZeros((Scalar.fromString(finalStateRoot, 16)).toString(16), 64); - // 32 bytes each field element for oldStateRoot - const strNewBatchAccInputHash = padZeros((Scalar.fromString(newBatchAccInputHash, 16)).toString(16), 64); + // 32 bytes each field element for finalBlobStateRoot + const strFinalBlobStateRoot = padZeros((Scalar.fromString(finalBlobStateRoot, 16)).toString(16), 64); - // 32 bytes each field element for oldStateRoot - const strNewLocalExitRoot = padZeros((Scalar.fromString(newLocalExitRoot, 16)).toString(16), 64); + // 32 bytes each field element for finalBlobAccInputHash + const strFinalBlobAccInputHash = padZeros((Scalar.fromString(finalBlobAccInputHash, 16)).toString(16), 64); + + // 8 bytes for finalNumBlob + const strFinalNumBlob = padZeros(Scalar.e(finalNumBlob).toString(16), 16); + + // 32 bytes each field element for finalLocalExitRoot + const strFinalLocalExitRoot = padZeros((Scalar.fromString(finalLocalExitRoot, 16)).toString(16), 64); + + // 20 bytes aggregator address + const strAggregatorAddress = padZeros((Scalar.fromString(aggregatorAddress, 16)).toString(16), 40); // build final bytes sha256 - const finalStr = strAggregatorAddress - .concat(strOldStateRoot) - .concat(strOldBatchAccInputHash) + const finalStr = strInitStateRoot + .concat(strInitBlobStateRoot) + .concat(strInitBlobAccInputHash) + .concat(strInitNumBlob) .concat(strChainID) .concat(strForkID) - .concat(strNewStateRoot) - .concat(strNewBatchAccInputHash) - .concat(strNewLocalExitRoot); + .concat(strFinalStateRoot) + .concat(strFinalBlobStateRoot) + .concat(strFinalBlobAccInputHash) + .concat(strFinalNumBlob) + .concat(strFinalLocalExitRoot) + .concat(strAggregatorAddress); return sha256Snark(finalStr); } diff --git a/src/processor.js b/src/processor.js index dd51a1e8..51e625c4 100644 --- a/src/processor.js +++ b/src/processor.js @@ -163,7 +163,7 @@ module.exports = class Processor { // Read Local exit root await this._readLocalExitRoot(); - // Calculate stark and snark input + // Calculate stark await this._computeStarkInput(); this.builded = true; @@ -977,7 +977,7 @@ module.exports = class Processor { const newStateRoot = smtUtils.h4toString(this.currentStateRoot); const oldBatchAccInputHash = smtUtils.h4toString(this.oldBatchAccInputHash); const newLocalExitRoot = smtUtils.h4toString(this.newLocalExitRoot); - const newTimestamp = this.newLastTimestamp.toString(); + const newLastTimestamp = this.newLastTimestamp.toString(); this.batchHashData = await computeBatchL2HashData( this.getBatchL2Data(), ); @@ -997,7 +997,7 @@ module.exports = class Processor { oldBatchAccInputHash, newBatchAccInputHash, // output newLocalExitRoot, // output - newTimestamp, // output + newLastTimestamp, // output chainID: this.chainID, forkID: this.forkID, forcedHashData: this.forcedHashData, diff --git a/src/zkevm-db.js b/src/zkevm-db.js index 81b0bbcd..234e3ea5 100644 --- a/src/zkevm-db.js +++ b/src/zkevm-db.js @@ -1,3 +1,4 @@ +/* eslint-disable max-len */ /* eslint-disable default-param-last */ /* eslint-disable multiline-comment-style */ /* eslint-disable no-restricted-syntax */ @@ -14,23 +15,26 @@ const clone = require('lodash/clone'); const Constants = require('./constants'); const Processor = require('./processor'); const BlobProcessor = require('./blob-inner/blob-processor'); +const BlobOuter = require('./blob-inner/blob-outer-processor'); const SMT = require('./smt'); const { getState, setAccountState, setContractBytecode, setContractStorage, getContractHashBytecode, getContractBytecodeLength, } = require('./state-utils'); -const { h4toString, stringToH4, hashContractBytecode } = require('./smt-utils'); +const { + h4toString, stringToH4, + hashContractBytecode, h4toScalar, +} = require('./smt-utils'); const { calculateSnarkInput } = require('./contract-utils'); class ZkEVMDB { - constructor(db, lastBatch, stateRoot, batchAccInputHash, localExitRoot, poseidon, vm, smt, chainID, forkID) { + constructor(db, lastBatch, stateRoot, localExitRoot, poseidon, vm, smt, chainID, forkID) { this.db = db; this.lastBatch = lastBatch || 0; this.poseidon = poseidon; this.F = poseidon.F; this.stateRoot = stateRoot || [this.F.zero, this.F.zero, this.F.zero, this.F.zero]; - this.batchAccInputHash = batchAccInputHash || [this.F.zero, this.F.zero, this.F.zero, this.F.zero]; this.localExitRoot = localExitRoot || [this.F.zero, this.F.zero, this.F.zero, this.F.zero]; this.chainID = chainID; this.forkID = forkID; @@ -44,11 +48,12 @@ class ZkEVMDB { } /** - * Return a new Processor with the current RollupDb state - * @param {Number} timestampLimit - Timestamp limit of the batch - * @param {String} sequencerAddress - ethereum address represented as hex - * @param {Array[Field]} l1InfoRoot - global exit root - * @param {Number} forcedBlockHashL1 - Forced blockHash + * Build Batch + * @param {String} sequencerAddress + * @param {String} forcedHashData + * @param {String} oldBatchAccInputHash + * @param {String} previousL1InfoTreeRoot + * @param {Number} previousL1InfoTreeIndex * @param {Scalar} maxNTx - Maximum number of transactions (optional) * @param {Object} options - additional batch options * @param {Bool} options.skipUpdateSystemStorage - Skips updates on system smrt contract at the end of processable transactions @@ -57,10 +62,12 @@ class ZkEVMDB { * @param {String} extraData.l1Info[x].globalExitRoot - global exit root * @param {String} extraData.l1Info[x].blockHash - l1 block hash at blockNumber - 1 * @param {BigInt} extraData.l1Info[x].timestamp - l1 block timestamp + * @returns {Object} batch processor */ async buildBatch( sequencerAddress, forcedHashData, + oldBatchAccInputHash, previousL1InfoTreeRoot, previousL1InfoTreeIndex, maxNTx = Constants.DEFAULT_MAX_TX, @@ -74,7 +81,7 @@ class ZkEVMDB { maxNTx, this.stateRoot, sequencerAddress, - this.batchAccInputHash, + stringToH4(oldBatchAccInputHash), this.chainID, this.forkID, forcedHashData, @@ -87,51 +94,6 @@ class ZkEVMDB { ); } - /** - * Return a new BlobProcessor with the current RollupDb state - * @param {Number} _lastL1InfoTreeIndex - Last L1 info tree index - * @param {String} _lastL1InfoTreeRoot - Last L1 info tree root - * @param {Scalar} _timestampLimit - Timestamp limit - * @param {Scalar} _zkGasLimit - zk gas limit - * @param {Number} _blobType - type of blob - * @param {String} _forcedHashData - forced hash data - * @returns - */ - async buildBlob( - _lastL1InfoTreeIndex, - _lastL1InfoTreeRoot, - _timestampLimit, - _zkGasLimit, - _blobType, - _forcedHashData, - ) { - // build globalInputs - const globalInputs = { - oldBlobStateRoot: this.blobRoot, - oldBlobAccInputHash: this.accBlobInputHash, - oldNumBlob: this.lastBlob, - oldStateRoot: this.stateRoot, - forkId: this.forkID, - }; - - // build privateInputs - const privateInputs = { - lastL1InfoTreeIndex: _lastL1InfoTreeIndex, - lastL1InfoTreeRoot: _lastL1InfoTreeRoot, - timestampLimit: _timestampLimit, - zkGasLimit: _zkGasLimit, - blobType: _blobType, - forcedHashData: _forcedHashData, - }; - - return new BlobProcessor( - this.db, - this.poseidon, - globalInputs, - privateInputs, - ); - } - /** * Consolidate a batch by writing it in the DB * @param {Object} processor - Processor object @@ -234,82 +196,286 @@ class ZkEVMDB { } /** - * Get batchL2Data for multiples batches + * Get inputs from batch aggregation * @param {Number} initNumBatch - initial num batch * @param {Number} finalNumBatch - final num batch */ - async sequenceMultipleBatches(initNumBatch, finalNumBatch) { - const dataBatches = []; + async aggregateBatches(initNumBatch, finalNumBatch) { + if (!(finalNumBatch >= initNumBatch)) { + throw new Error('Final batch must be greater than or equal initial batch'); + } + + const fullAggData = { + aggBatchData: {}, + singleBatchData: [], + }; + // get data batches that will be aggregated for (let i = initNumBatch; i <= finalNumBatch; i++) { const keyInitInput = Scalar.add(Constants.DB_STARK_INPUT, i); const value = await this.db.getValue(keyInitInput); if (value === null) { throw new Error(`Batch ${i} does not exist`); } + fullAggData.singleBatchData.push(value); + } + + // verify batch aggregation + // first batch has initial values set to 0 + if (fullAggData.singleBatchData[0].previousL1InfoTreeRoot !== Constants.ZERO_BYTES32) { + throw new Error('First batch must have previousL1InfoTreeRoot set to 0x00...00'); + } + + if (fullAggData.singleBatchData[0].previousL1InfoTreeIndex !== 0) { + throw new Error('First batch must have previousL1InfoTreeRoot set to 0x00...00'); + } + + if (fullAggData.singleBatchData[0].oldBatchAccInputHash !== Constants.ZERO_BYTES32) { + throw new Error('First batch must have previousL1InfoTreeRoot set to 0x00...00'); + } + + // intermediate fullAggData.singleBatchData signals are correct + for (let i = 0; i < fullAggData.singleBatchData.length - 1; i++) { + const current = fullAggData.singleBatchData[i]; + const next = fullAggData.singleBatchData[i + 1]; + + if (current.newStateRoot !== next.oldStateRoot) { + throw new Error(`Batch ${i} newStateRoot must be equal to next batch oldStateRoot`); + } - const dataBatch = { - transactions: value.batchL2Data, - l1InfoRoot: value.l1InfoRoot, - timestampLimit: value.timestampLimit, - forceBatchesTimestamp: [], - }; + if (current.newBatchAccInputHash !== next.oldBatchAccInputHash) { + throw new Error(`Batch ${i} newBatchAccInputHash must be equal to next batch oldBatchAccInputHash`); + } + + if (current.newL1InfoTreeRoot !== next.previousL1InfoTreeRoot) { + throw new Error(`Batch ${i} currentL1InfoTreeRoot must be equal to next batch previousL1InfoTreeRoot`); + } + + if (current.newL1InfoTreeIndex !== next.previousL1InfoTreeIndex) { + throw new Error(`Batch ${i} currentL1InfoTreeIndex must be equal to next batch previousL1InfoTreeIndex`); + } - dataBatches.push(dataBatch); + if (current.sequencerAddress !== next.sequencerAddress) { + throw new Error(`Batch ${i} sequencerAddress must be equal to next batch sequencerAddress`); + } } - return dataBatches; + // add common data + fullAggData.aggBatchData.oldBatchAccInputHash = Constants.ZERO_BYTES32; + fullAggData.aggBatchData.previousL1InfoTreeRoot = Constants.ZERO_BYTES32; + fullAggData.aggBatchData.previousL1InfoTreeIndex = 0; + fullAggData.aggBatchData.chainID = this.chainID; + fullAggData.aggBatchData.forkID = this.forkID; + fullAggData.aggBatchData.sequencerAddress = fullAggData.singleBatchData[0].sequencerAddr; + + // get data from the first batch + fullAggData.aggBatchData.oldStateRoot = fullAggData.singleBatchData[0].oldStateRoot; + + // get data from the last batch + fullAggData.aggBatchData.newStateRoot = fullAggData.singleBatchData[fullAggData.singleBatchData.length - 1].newStateRoot; + fullAggData.aggBatchData.newBatchAccInputHash = fullAggData.singleBatchData[fullAggData.singleBatchData.length - 1].newBatchAccInputHash; + fullAggData.aggBatchData.currentL1InfoTreeRoot = fullAggData.singleBatchData[fullAggData.singleBatchData.length - 1].newL1InfoTreeRoot; + fullAggData.aggBatchData.currentL1InfoTreeIndex = fullAggData.singleBatchData[fullAggData.singleBatchData.length - 1].newL1InfoTreeIndex; + fullAggData.aggBatchData.newLocalExitRoot = fullAggData.singleBatchData[fullAggData.singleBatchData.length - 1].newLocalExitRoot; + fullAggData.aggBatchData.newLastTimestamp = fullAggData.singleBatchData[fullAggData.singleBatchData.length - 1].newLastTimestamp; + + // hash initial and final batch to uniquely identify a batch aggregation + // eslint-disable-next-line max-len + const aggId = this.poseidon( + [initNumBatch, finalNumBatch, this.F.zero, this.F.zero, this.F.zero, this.F.zero, this.F.zero, this.F.zero], + [this.F.zero, this.F.zero, this.F.zero, this.F.zero], + ); + + // Set stark input + await this.db.setValue( + Scalar.add(Constants.DB_AGG_BATCHES, h4toScalar(aggId)), + fullAggData, + ); + + return fullAggData; } /** - * Get batchL2Data for multiples batches - * @param {Number} initNumBatch - initial num batch - * @param {Number} finalNumBatch - final num batch + * Return a new BlobProcessor with the current RollupDb state + * @param {Number} _initNumBatch - first batch of the blobInner + * @param {Number} _finalNumBatch - first batch of the blobInner + * @param {String} _lastL1InfoTreeRoot - Last L1 info tree root + * @param {Number} _lastL1InfoTreeIndex - Last L1 info tree index + * @param {Scalar} _timestampLimit - Timestamp limit + * @param {Scalar} _zkGasLimit - zk gas limit + * @param {Number} _blobType - type of blob + * @param {String} _forcedHashData - forced hash data + * @returns + */ + async buildBlobInner( + _initNumBatch, + _finalNumBatch, + _lastL1InfoTreeRoot, + _lastL1InfoTreeIndex, + _timestampLimit, + _zkGasLimit, + _blobType, + _forcedHashData, + ) { + const aggId = this.poseidon( + [_initNumBatch, _finalNumBatch, this.F.zero, this.F.zero, this.F.zero, this.F.zero, this.F.zero, this.F.zero], + [this.F.zero, this.F.zero, this.F.zero, this.F.zero], + ); + + // get aggregate batches inout stark + const keyInitInput = Scalar.add(Constants.DB_AGG_BATCHES, h4toScalar(aggId)); + const fullAggData = await this.db.getValue(keyInitInput); + if (fullAggData === null) { + throw new Error(`Aggregation batches ${_initNumBatch}__${_finalNumBatch} does not exist`); + } + + // build globalInputs + const globalInputs = { + oldBlobStateRoot: this.blobRoot, + oldBlobAccInputHash: h4toString(this.accBlobInputHash), + oldNumBlob: this.lastBlob, + oldStateRoot: stringToH4(fullAggData.aggBatchData.oldStateRoot), + forkID: this.forkID, + }; + + // build privateInputs + const privateInputs = { + lastL1InfoTreeIndex: _lastL1InfoTreeIndex, + lastL1InfoTreeRoot: _lastL1InfoTreeRoot, + timestampLimit: _timestampLimit, + zkGasLimit: _zkGasLimit, + blobType: _blobType, + forcedHashData: _forcedHashData, + sequencerAddress: fullAggData.aggBatchData.sequencerAddress, + }; + + const blobInner = new BlobProcessor( + this.db, + this.poseidon, + globalInputs, + privateInputs, + ); + + // add batch data + for (fullAggData.singleBatchData of fullAggData.singleBatchData) { + await blobInner.addBatchL2Data(fullAggData.singleBatchData.batchL2Data); + } + await blobInner.execute(); + + // save input blobInner + await this.db.setValue( + Scalar.add(Constants.DB_STARK_BLOB_INNER, blobInner.newNumBlob), + blobInner.starkInput, + ); + + const blobOuter = new BlobOuter(blobInner.starkInput, fullAggData.aggBatchData); + await blobOuter.execute(); + + const blobOuterInput = blobOuter.getStarkInput(); + + // consolidate blobOuter + // save state root + await this.db.setValue( + Scalar.add(Constants.DB_OUTER_STATE_ROOT, blobOuterInput.newNumBlob), + blobOuterInput.newStateRoot, + ); + + // save blob state root + this.blobRoot = stringToH4(blobOuterInput.newBlobStateRoot); + await this.db.setValue( + Scalar.add(Constants.DB_BLOB_STATE_ROOT, blobOuterInput.newNumBlob), + blobOuterInput.newBlobStateRoot, + ); + + // save blob acc input hash + this.accBlobInputHash = stringToH4(blobOuterInput.newBlobAccInputHash); + await this.db.setValue( + Scalar.add(Constants.DB_BLOB_ACC_INPUT_HASH, blobOuterInput.newNumBlob), + blobOuterInput.newBlobAccInputHash, + ); + + // save last num blob + this.lastBlob = blobOuterInput.newNumBlob; + await this.db.setValue( + Constants.DB_LAST_NUM_BLOB, + Scalar.toNumber(blobOuterInput.newNumBlob), + ); + + // save outer local exit root + await this.db.setValue( + Scalar.add(Constants.DB_OUTER_LOCAL_EXIT_ROOT, blobOuterInput.newNumBlob), + blobOuterInput.newLocalExitRoot, + ); + + // save stark blob outer + await this.db.setValue( + Scalar.add(Constants.DB_STARK_BLOB_OUTER, blobOuterInput.newNumBlob), + blobOuterInput, + ); + + return { + inputBlobInner: blobInner.starkInput, + inputBlobOuter: blobOuter.starkInput, + }; + } + + /** + * Aggregate multiple blob outers + * @param {Number} initNumBlob - initial num batch + * @param {Number} finalNumBlob - final num batch * @param {String} aggregatorAddress - aggregator Ethereum address */ - async verifyMultipleBatches(initNumBatch, finalNumBatch, aggregatorAddress) { - const dataVerify = {}; - dataVerify.singleBatchData = []; + async aggregateBlobOuters(initNumBlob, finalNumBlob, aggregatorAddress) { + const aggBlobOuter = { + singleData: [], + aggData: {}, + }; - for (let i = initNumBatch; i <= finalNumBatch; i++) { - const keyInitInput = Scalar.add(Constants.DB_STARK_INPUT, i); + for (let i = initNumBlob; i <= finalNumBlob; i++) { + const keyInitInput = Scalar.add(Constants.DB_STARK_BLOB_OUTER, i); const value = await this.db.getValue(keyInitInput); if (value === null) { - throw new Error(`Batch ${i} does not exist`); + throw new Error(`Blob outer ${i} does not exist`); } - if (i === initNumBatch) { - dataVerify.oldStateRoot = value.oldStateRoot; - dataVerify.oldBatchAccInputHash = value.oldBatchAccInputHash; - dataVerify.oldNumBatch = value.oldNumBatch; + if (i === initNumBlob) { + aggBlobOuter.aggData.oldStateRoot = value.oldStateRoot; + aggBlobOuter.aggData.oldBlobStateRoot = value.oldBlobStateRoot; + aggBlobOuter.aggData.oldBlobAccInputHash = value.oldBlobAccInputHash; + aggBlobOuter.aggData.oldNumBlob = value.oldNumBlob; } - if (i === finalNumBatch) { - dataVerify.newStateRoot = value.newStateRoot; - dataVerify.newBatchAccInputHash = value.newBatchAccInputHash; - dataVerify.newLocalExitRoot = value.newLocalExitRoot; - dataVerify.newNumBatch = value.newNumBatch; + if (i === finalNumBlob) { + aggBlobOuter.aggData.newStateRoot = value.newStateRoot; + aggBlobOuter.aggData.newBlobStateRoot = value.newBlobStateRoot; + aggBlobOuter.aggData.newBlobAccInputHash = value.newBlobAccInputHash; + aggBlobOuter.aggData.newNumBlob = value.newNumBlob; + aggBlobOuter.aggData.newLocalExitRoot = value.newLocalExitRoot; } - dataVerify.singleBatchData.push(value); + aggBlobOuter.singleData.push(value); } - dataVerify.chainID = this.chainID; - dataVerify.forkID = this.forkID; - dataVerify.aggregatorAddress = aggregatorAddress; - - dataVerify.inputSnark = `0x${Scalar.toString(await calculateSnarkInput( - dataVerify.oldStateRoot, - dataVerify.newStateRoot, - dataVerify.newLocalExitRoot, - dataVerify.oldBatchAccInputHash, - dataVerify.newBatchAccInputHash, - dataVerify.chainID, - dataVerify.aggregatorAddress, - dataVerify.forkID, + aggBlobOuter.aggData.chainID = this.chainID; + aggBlobOuter.aggData.forkID = this.forkID; + aggBlobOuter.aggData.aggregatorAddress = aggregatorAddress; + + aggBlobOuter.aggData.inputSnark = `0x${Scalar.toString(await calculateSnarkInput( + aggBlobOuter.aggData.oldStateRoot, + aggBlobOuter.aggData.oldBlobStateRoot, + aggBlobOuter.aggData.oldBlobAccInputHash, + aggBlobOuter.aggData.oldNumBlob, + aggBlobOuter.aggData.chainID, + aggBlobOuter.aggData.forkID, + aggBlobOuter.aggData.newStateRoot, + aggBlobOuter.aggData.newBlobStateRoot, + aggBlobOuter.aggData.newBlobAccInputHash, + aggBlobOuter.aggData.newNumBlob, + aggBlobOuter.aggData.newLocalExitRoot, + aggBlobOuter.aggData.aggregatorAddress, ), 16).padStart(64, '0')}`; - return dataVerify; + return aggBlobOuter; } /** @@ -366,7 +532,6 @@ class ZkEVMDB { * @param {Object} db - Mem db object * @param {Object} poseidon - Poseidon object * @param {Array[Fields]} stateRoot - state merkle root - * @param {Array[Fields]} batchAccInputHash - accumulate hash input * @param {Object} genesis - genesis block accounts (address, nonce, balance, bytecode, storage) * @param {Object} vm - evm if already instantiated * @param {Object} smt - smt if already instantiated @@ -374,7 +539,7 @@ class ZkEVMDB { * @param {Number} forkID - L2 rom fork identifier * @returns {Object} ZkEVMDB object */ - static async newZkEVM(db, poseidon, stateRoot, batchAccInputHash, genesis, vm, smt, chainID, forkID) { + static async newZkEVM(db, poseidon, stateRoot, genesis, vm, smt, chainID, forkID) { const common = Common.custom({ chainId: chainID }, { hardfork: Hardfork.Berlin }); common.setEIPs([3607, 3541, 3855]); const lastBatch = await db.getValue(Constants.DB_LAST_BATCH); @@ -441,7 +606,6 @@ class ZkEVMDB { db, 0, genesisStateRoot, - batchAccInputHash, null, // localExitRoot poseidon, newVm, @@ -453,14 +617,12 @@ class ZkEVMDB { // Update current zkevm instance const DBStateRoot = await db.getValue(Scalar.add(Constants.DB_STATE_ROOT, lastBatch)); - const DBAccInputHash = await db.getValue(Scalar.add(Constants.DB_ACC_INPUT_HASH, lastBatch)); const DBLocalExitRoot = await db.getValue(Scalar.add(Constants.DB_LOCAL_EXIT_ROOT, lastBatch)); return new ZkEVMDB( db, lastBatch, stringToH4(DBStateRoot), - stringToH4(DBAccInputHash), stringToH4(DBLocalExitRoot), poseidon, vm, diff --git a/test/blob-inner/blob-inner-processor.test.js b/test/blob-inner/blob-inner-processor.test.js index 24298ed5..c85caf08 100644 --- a/test/blob-inner/blob-inner-processor.test.js +++ b/test/blob-inner/blob-inner-processor.test.js @@ -104,6 +104,7 @@ describe('BlobProcessor', async function () { // get stark input const inputBlobInner = await blobInnerProcessor.getStarkInput(); + // check expected result if (!update) { expect(expected.newBlobStateRoot).to.be.equal(inputBlobInner.newBlobStateRoot); diff --git a/test/block-info.test.js b/test/block-info.test.js index bf28eeb8..a9db9e6b 100644 --- a/test/block-info.test.js +++ b/test/block-info.test.js @@ -73,12 +73,11 @@ describe('Block info tests', function () { db, poseidon, [F.zero, F.zero, F.zero, F.zero], - smtUtils.stringToH4(oldBatchAccInputHash), genesis, null, null, - chainID, // could be read from contracts - forkID, // could be read from contracts + chainID, + forkID, ); // Check evm contract params @@ -253,6 +252,7 @@ describe('Block info tests', function () { const batch = await zkEVMDB.buildBatch( sequencerAddress, forcedHashData, + oldBatchAccInputHash, previousL1InfoTreeRoot, previousL1InfoTreeIndex, Constants.DEFAULT_MAX_TX, diff --git a/test/contract-utils.test.js b/test/contract-utils.test.js index 0cf24851..e5630961 100644 --- a/test/contract-utils.test.js +++ b/test/contract-utils.test.js @@ -1,47 +1,41 @@ -const fs = require('fs'); -const path = require('path'); const { expect } = require('chai'); - const { contractUtils } = require('../index'); -const { pathTestVectors } = require('./helpers/test-utils'); - describe('contractUtils', function () { this.timeout(10000); - let testVector; - - const expectedSnarkInputHash = '1945042d70b86b81b1d301119ea2bffa6b131f651ebf66858796980298fb76f8'; - - before(async () => { - testVector = JSON.parse(fs.readFileSync(path.join(pathTestVectors, 'inputs-executor/input_executor.json'))); - }); it('calculateSnarkInput', async () => { - const aggregatorAddress = '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266'; + const expectedSnarkInputHash = '0xcb4024f9c037e6d88842ab51ece5c25f8c64fa4087c76e904e305bdb55e9090'; - const { - oldStateRoot, - newStateRoot, - newLocalExitRoot, - oldBatchAccInputHash, - newBatchAccInputHash, - - chainID, - forkID, - } = testVector; + const initStateRoot = '0x1'; + const initBlobStateRoot = '0x2'; + const initBlobAccInputHash = '0x3'; + const initNumBlob = 4; + const chainId = 5; + const forkID = 6; + const finalStateRoot = '0x7'; + const finalBlobStateRoot = '0x8'; + const finalBlobAccInputHash = '0x9'; + const finalNumBlob = 10; + const finalLocalExitRoot = '0xa'; + const aggregatorAddress = '0xb'; const computedSnark = await contractUtils.calculateSnarkInput( - oldStateRoot, - newStateRoot, - newLocalExitRoot, - oldBatchAccInputHash, - newBatchAccInputHash, - chainID, - aggregatorAddress, + initStateRoot, + initBlobStateRoot, + initBlobAccInputHash, + initNumBlob, + chainId, forkID, + finalStateRoot, + finalBlobStateRoot, + finalBlobAccInputHash, + finalNumBlob, + finalLocalExitRoot, + aggregatorAddress, ); - expect(computedSnark.toString(16)).to.be.equal(expectedSnarkInputHash); + expect(`0x${computedSnark.toString(16)}`).to.be.equal(expectedSnarkInputHash); }); it('generateSolidityInputs', async () => { diff --git a/test/e2e-circuits.test.js b/test/e2e-circuits.test.js new file mode 100644 index 00000000..40beac4d --- /dev/null +++ b/test/e2e-circuits.test.js @@ -0,0 +1,444 @@ +/* eslint-disable global-require */ +/* eslint-disable import/no-dynamic-require */ +/* eslint-disable no-unused-expressions */ +/* eslint-disable no-console */ +/* eslint-disable multiline-comment-style */ +/* eslint-disable no-restricted-syntax */ +/* eslint-disable no-await-in-loop */ +/* eslint-disable guard-for-in */ + +const fs = require('fs'); +const path = require('path'); +const { Scalar } = require('ffjavascript'); +const { argv } = require('yargs'); +const ethers = require('ethers'); +const { expect } = require('chai'); +const lodash = require('lodash'); + +const { + MemDB, ZkEVMDB, getPoseidon, processorUtils, smtUtils, Constants, +} = require('../index'); +const { pathTestVectors } = require('./helpers/test-utils'); + +const pathInputs = path.join(__dirname, '../tools/inputs-examples'); + +// 3 blob outers +// A --> 1 blobInner + 3 batchos +// B --> 1 blobInner + 1 batchos +// C --> 1 blobInner + 2 batchos + +describe('e2e circuits', function () { + this.timeout(300000); + const pathTests = path.join(pathTestVectors, 'end-to-end/e2e-circuits.json'); + let update; + let geninput; + let poseidon; + let F; + let testVectors; + + before(async () => { + poseidon = await getPoseidon(); + F = poseidon.F; + testVectors = JSON.parse(fs.readFileSync(pathTests)); + + update = argv.update === true; + geninput = argv.geninput === true; + }); + + it('Check test vectors', async () => { + for (let i = 0; i < testVectors.length; i++) { + const { + description, + genesis, + oldStateRoot, + blobOuters, + sequencerAddress, + aggregatorAddress, + forkID, + chainID, + expectedFinal, + } = testVectors[i]; + + const db = new MemDB(F); + // create a zkEVMDB to compile the sc + const zkEVMDB = await ZkEVMDB.newZkEVM( + db, + poseidon, + [F.zero, F.zero, F.zero, F.zero], + genesis, + null, + null, + chainID, + forkID, + ); + + // Check the state root + if (!update) { + expect(smtUtils.h4toString(zkEVMDB.stateRoot)).to.be.equal(oldStateRoot); + } else { + testVectors[i].oldStateRoot = smtUtils.h4toString(zkEVMDB.stateRoot); + } + + // iterate over each blobOuter + for (let n = 0; n < blobOuters.length; n++) { + const blobOuterData = blobOuters[n]; + const { + zkGasLimit, + blobType, + batches, + forcedHashData, + previousL1InfoTreeRoot, + previousL1InfoTreeIndex, + oldBatchAccInputHash, + expected, + } = blobOuterData; + + let initL1InfoTreeRoot = previousL1InfoTreeRoot; + let initL1InfoTreeIndex = previousL1InfoTreeIndex; + let initBatchAccInputHash = oldBatchAccInputHash; + const initBatchNum = zkEVMDB.lastBatch + 1; + let lastBatchInput = {}; + + const txProcessed = []; + const extraData = { l1Info: {} }; + + for (let k = 0; k < batches.length; k++) { + const { + txs, + newStateRoot, + expectedNewLeafs, + batchL2Data, + inputHash, + batchHashData, + newLocalExitRoot, + skipFirstChangeL2Block, + skipWriteBlockInfoRoot, + newL1InfoTreeRoot, + newL1InfoTreeIndex, + } = batches[k]; + + const rawTxs = []; + for (let j = 0; j < txs.length; j++) { + const txData = txs[j]; + + if (txData.type === Constants.TX_CHANGE_L2_BLOCK) { + const rawChangeL2BlockTx = processorUtils.serializeChangeL2Block(txData); + + // Append l1Info to l1Info object + extraData.l1Info[txData.indexL1InfoTree] = txData.l1Info; + + const customRawTx = `0x${rawChangeL2BlockTx}`; + rawTxs.push(customRawTx); + txProcessed.push(txData); + + if (!update) { + expect(customRawTx).to.equal(txData.customRawTx); + } else { + txData.customRawTx = customRawTx; + } + + // eslint-disable-next-line no-continue + continue; + } + + const tx = { + to: txData.to, + nonce: txData.nonce, + value: processorUtils.toHexStringRlp(ethers.utils.parseUnits(txData.value, 'wei')), + gasLimit: txData.gasLimit, + gasPrice: processorUtils.toHexStringRlp(ethers.utils.parseUnits(txData.gasPrice, 'wei')), + chainId: txData.chainId, + data: txData.data || '0x', + }; + + let customRawTx; + const address = genesis.find((o) => o.address === txData.from); + const wallet = new ethers.Wallet(address.pvtKey); + if (tx.chainId === 0) { + const signData = ethers.utils.RLP.encode([ + processorUtils.toHexStringRlp(Scalar.e(tx.nonce)), + processorUtils.toHexStringRlp(tx.gasPrice), + processorUtils.toHexStringRlp(tx.gasLimit), + processorUtils.addressToHexStringRlp(tx.to), + processorUtils.toHexStringRlp(tx.value), + processorUtils.toHexStringRlp(tx.data), + processorUtils.toHexStringRlp(tx.chainId), + '0x', + '0x', + ]); + const digest = ethers.utils.keccak256(signData); + const signingKey = new ethers.utils.SigningKey(address.pvtKey); + const signature = signingKey.signDigest(digest); + const r = signature.r.slice(2).padStart(64, '0'); // 32 bytes + const s = signature.s.slice(2).padStart(64, '0'); // 32 bytes + const v = (signature.v).toString(16).padStart(2, '0'); // 1 bytes + customRawTx = signData.concat(r).concat(s).concat(v); + } else { + const rawTxEthers = await wallet.signTransaction(tx); + if (!update) { + expect(rawTxEthers).to.equal(txData.rawTx); + } else { + txData.rawTx = rawTxEthers; + } + customRawTx = processorUtils.rawTxToCustomRawTx(rawTxEthers); + } + + if (!update) { + expect(customRawTx).to.equal(txData.customRawTx); + } else { + txData.customRawTx = customRawTx; + } + + if (txData.encodeInvalidData) { + customRawTx = customRawTx.slice(0, -6); + } + rawTxs.push(customRawTx); + txProcessed.push(txData); + } + + const batch = await zkEVMDB.buildBatch( + sequencerAddress, + forcedHashData, + initBatchAccInputHash, + initL1InfoTreeRoot, + initL1InfoTreeIndex, + Constants.DEFAULT_MAX_TX, + { + skipFirstChangeL2Block, + skipWriteBlockInfoRoot, + }, + {}, + ); + + for (let j = 0; j < rawTxs.length; j++) { + batch.addRawTx(rawTxs[j]); + } + + // execute the transactions added to the batch + await batch.executeTxs(); + // consolidate state + await zkEVMDB.consolidate(batch); + + const newRoot = batch.currentStateRoot; + if (!update) { + expect(smtUtils.h4toString(newRoot)).to.be.equal(newStateRoot); + } else { + testVectors[i].blobOuters[n].batches[k].newStateRoot = smtUtils.h4toString(newRoot); + } + + // Check balances and nonces + const updatedAccounts = batch.getUpdatedAccountsBatch(); + const newLeafs = {}; + for (const item in updatedAccounts) { + const address = item; + const account = updatedAccounts[address]; + newLeafs[address] = {}; + + const newLeaf = await zkEVMDB.getCurrentAccountState(address); + expect(newLeaf.balance.toString()).to.equal(account.balance.toString()); + expect(newLeaf.nonce.toString()).to.equal(account.nonce.toString()); + + const smtNewLeaf = await zkEVMDB.getCurrentAccountState(address); + expect(smtNewLeaf.balance.toString()).to.equal(account.balance.toString()); + expect(smtNewLeaf.nonce.toString()).to.equal(account.nonce.toString()); + + newLeafs[address].balance = account.balance.toString(); + newLeafs[address].nonce = account.nonce.toString(); + + if (account.isContract() || address.toLowerCase() === Constants.ADDRESS_SYSTEM.toLowerCase() + || address.toLowerCase() === Constants.ADDRESS_GLOBAL_EXIT_ROOT_MANAGER_L2.toLowerCase()) { + const storage = await zkEVMDB.dumpStorage(address); + newLeafs[address].storage = storage; + } + } + + if (!update) { + for (const [address, leaf] of Object.entries(expectedNewLeafs)) { + expect(lodash.isEqual(leaf, newLeafs[address])).to.be.equal(true); + } + } else { + testVectors[i].blobOuters[n].batches[k].expectedNewLeafs = newLeafs; + } + + // Check the circuit input + const circuitInput = await batch.getStarkInput(); + + // Check the encode transaction match with the vector test + if (!update) { + expect(batchL2Data).to.be.equal(batch.getBatchL2Data()); + // Check the batchHashData and the input hash + expect(batchHashData).to.be.equal(circuitInput.batchHashData); + expect(inputHash).to.be.equal(circuitInput.inputHash); + expect(newLocalExitRoot).to.be.equal(circuitInput.newLocalExitRoot); + expect(newL1InfoTreeRoot).to.be.equal(batch.currentL1InfoTreeRoot); + expect(newL1InfoTreeIndex).to.be.equal(batch.currentL1InfoTreeIndex); + } else { + testVectors[i].blobOuters[n].batches[k].batchL2Data = batch.getBatchL2Data(); + testVectors[i].blobOuters[n].batches[k].batchHashData = circuitInput.batchHashData; + testVectors[i].blobOuters[n].batches[k].inputHash = circuitInput.inputHash; + testVectors[i].blobOuters[n].batches[k].newLocalExitRoot = circuitInput.newLocalExitRoot; + testVectors[i].blobOuters[n].batches[k].newL1InfoTreeRoot = batch.currentL1InfoTreeRoot; + testVectors[i].blobOuters[n].batches[k].newL1InfoTreeIndex = batch.currentL1InfoTreeIndex; + } + + // update vars for the next batch + lastBatchInput = circuitInput; + initL1InfoTreeRoot = circuitInput.newL1InfoTreeRoot; + initL1InfoTreeIndex = circuitInput.newL1InfoTreeIndex; + initBatchAccInputHash = circuitInput.newBatchAccInputHash; + + if (update && geninput) { + const dstFile = path.join(pathInputs, `${path.basename(pathTests, '.json')}-BATCH-${i}-${n}-${k}-input.json`); + const folfer = path.dirname(dstFile); + + if (!fs.existsSync(folfer)) { + fs.mkdirSync(folfer); + } + + await fs.writeFileSync(dstFile, JSON.stringify(circuitInput, null, 2)); + } + } + + // aggregate batches + const aggrBatchesData = await zkEVMDB.aggregateBatches(initBatchNum, zkEVMDB.lastBatch); + + // build blobOuter + const { inputBlobInner, inputBlobOuter } = await zkEVMDB.buildBlobInner( + initBatchNum, + zkEVMDB.lastBatch, + lastBatchInput.newL1InfoTreeRoot, + lastBatchInput.newL1InfoTreeIndex, + lastBatchInput.newLastTimestamp, + zkGasLimit, + blobType, + lastBatchInput.forcedHashData, + ); + + // check expected result for batch aggregation + const { + batchAggregation, + blobInner, + blobOuter, + } = expected; + + // batch aggregation + if (!update) { + expect(aggrBatchesData.aggBatchData.newStateRoot).to.be.equal(batchAggregation.newStateRoot); + expect(aggrBatchesData.aggBatchData.newBatchAccInputHash).to.be.equal(batchAggregation.newBatchAccInputHash); + expect(aggrBatchesData.aggBatchData.newLastTimestamp).to.be.equal(batchAggregation.newLastTimestamp); + expect(aggrBatchesData.aggBatchData.currentL1InfoTreeRoot).to.be.equal(batchAggregation.currentL1InfoTreeRoot); + expect(aggrBatchesData.aggBatchData.currentL1InfoTreeIndex).to.be.equal(batchAggregation.currentL1InfoTreeIndex); + } else { + testVectors[i].blobOuters[n].expected.batchAggregation = { + newStateRoot: aggrBatchesData.aggBatchData.newStateRoot, + newBatchAccInputHash: aggrBatchesData.aggBatchData.newBatchAccInputHash, + newLastTimestamp: aggrBatchesData.aggBatchData.newLastTimestamp, + currentL1InfoTreeRoot: aggrBatchesData.aggBatchData.currentL1InfoTreeRoot, + currentL1InfoTreeIndex: aggrBatchesData.aggBatchData.currentL1InfoTreeIndex, + }; + } + + // blob inner + if (!update) { + expect(inputBlobInner.newBlobStateRoot).to.be.equal(blobInner.newBlobStateRoot); + expect(inputBlobInner.newBlobAccInputHash).to.be.equal(blobInner.newBlobAccInputHash); + expect(inputBlobInner.newNumBlob).to.be.equal(blobInner.newNumBlob); + expect(inputBlobInner.finalAccBatchHashData).to.be.equal(blobInner.finalAccBatchHashData); + expect(inputBlobInner.localExitRootFromBlob).to.be.equal(blobInner.localExitRootFromBlob); + expect(inputBlobInner.isInvalid).to.be.equal(blobInner.isInvalid); + } else { + testVectors[i].blobOuters[n].expected.blobInner = { + newBlobStateRoot: inputBlobInner.newBlobStateRoot, + newBlobAccInputHash: inputBlobInner.newBlobAccInputHash, + newNumBlob: inputBlobInner.newNumBlob, + finalAccBatchHashData: inputBlobInner.finalAccBatchHashData, + localExitRootFromBlob: inputBlobInner.localExitRootFromBlob, + isInvalid: inputBlobInner.isInvalid, + }; + } + + // blob outer + if (!update) { + expect(inputBlobOuter.newStateRoot).to.be.equal(blobOuter.newStateRoot); + expect(inputBlobOuter.newBlobStateRoot).to.be.equal(blobOuter.newBlobStateRoot); + expect(inputBlobOuter.newBlobAccInputHash).to.be.equal(blobOuter.newBlobAccInputHash); + expect(inputBlobOuter.newNumBlob).to.be.equal(blobOuter.newNumBlob); + expect(inputBlobOuter.newLocalExitRoot).to.be.equal(blobOuter.newLocalExitRoot); + } else { + testVectors[i].blobOuters[n].expected.blobOuter = { + newStateRoot: inputBlobOuter.newStateRoot, + newBlobStateRoot: inputBlobOuter.newBlobStateRoot, + newBlobAccInputHash: inputBlobOuter.newBlobAccInputHash, + newNumBlob: inputBlobOuter.newNumBlob, + newLocalExitRoot: inputBlobOuter.newLocalExitRoot, + }; + } + + if (update && geninput) { + const dstFileAggBatches = path.join(pathInputs, `${path.basename(pathTests, '.json')}-AGGBATCHES-${i}-${n}-input.json`); + const dstFileInner = path.join(pathInputs, `${path.basename(pathTests, '.json')}-INNER-${i}-${n}-input.json`); + const dstFileOuter = path.join(pathInputs, `${path.basename(pathTests, '.json')}-OUTER-${i}-${n}-input.json`); + const folderAggBatches = path.dirname(dstFileAggBatches); + const folderInner = path.dirname(dstFileInner); + const folderOuter = path.dirname(dstFileOuter); + + if (!fs.existsSync(folderAggBatches)) { + fs.mkdirSync(folderAggBatches); + } + + if (!fs.existsSync(folderInner)) { + fs.mkdirSync(folderInner); + } + + if (!fs.existsSync(folderOuter)) { + fs.mkdirSync(folderOuter); + } + + await fs.writeFileSync(dstFileAggBatches, JSON.stringify(aggrBatchesData, null, 2)); + await fs.writeFileSync(dstFileInner, JSON.stringify(inputBlobInner, null, 2)); + await fs.writeFileSync(dstFileOuter, JSON.stringify(inputBlobOuter, null, 2)); + } + } + + // aggregate blob outers + const aggBlobOuters = await zkEVMDB.aggregateBlobOuters(1, zkEVMDB.lastBlob, aggregatorAddress); + + // check expected result for blob outers aggregation + if (!update) { + expect(aggBlobOuters.aggData.newStateRoot).to.be.equal(expectedFinal.newStateRoot); + expect(aggBlobOuters.aggData.newBlobStateRoot).to.be.equal(expectedFinal.newBlobStateRoot); + expect(aggBlobOuters.aggData.newBlobAccInputHash).to.be.equal(expectedFinal.newBlobAccInputHash); + expect(aggBlobOuters.aggData.newNumBlob).to.be.equal(expectedFinal.newNumBlob); + expect(aggBlobOuters.aggData.newLocalExitRoot).to.be.equal(expectedFinal.newLocalExitRoot); + expect(aggBlobOuters.aggData.aggregatorAddress).to.be.equal(expectedFinal.aggregatorAddress); + expect(aggBlobOuters.aggData.inputSnark).to.be.equal(expectedFinal.inputSnark); + } else { + testVectors[i].expectedFinal = { + newStateRoot: aggBlobOuters.aggData.newStateRoot, + newBlobStateRoot: aggBlobOuters.aggData.newBlobStateRoot, + newBlobAccInputHash: aggBlobOuters.aggData.newBlobAccInputHash, + newNumBlob: aggBlobOuters.aggData.newNumBlob, + newLocalExitRoot: aggBlobOuters.aggData.newLocalExitRoot, + aggregatorAddress: aggBlobOuters.aggData.aggregatorAddress, + inputSnark: aggBlobOuters.aggData.inputSnark, + }; + } + + if (update && geninput) { + const dstFileFinal = path.join(pathInputs, `${path.basename(pathTests, '.json')}-FINAL-${i}-input.json`); + const folderFinal = path.dirname(dstFileFinal); + + if (!fs.existsSync(folderFinal)) { + fs.mkdirSync(folderFinal); + } + + await fs.writeFileSync(dstFileFinal, JSON.stringify(aggBlobOuters, null, 2)); + } + + console.log(` Completed test ${i + 1}/${testVectors.length}: ${description}`); + } + if (update) { + await fs.writeFileSync(pathTests, JSON.stringify(testVectors, null, 2)); + } + }); +}); diff --git a/test/helpers/test-vectors/blob-inner/blob-inner-data.json b/test/helpers/test-vectors/blob-inner/blob-inner-data.json index f8b83150..82c87808 100644 --- a/test/helpers/test-vectors/blob-inner/blob-inner-data.json +++ b/test/helpers/test-vectors/blob-inner/blob-inner-data.json @@ -10,7 +10,7 @@ "oldBlobStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "oldBlobAccInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "oldNumBlob": 0, - "forkID": 9, + "forkID": 10, "oldStateRoot": "0x799c98013da3f7a43b6e8086d0cedd89bd6a9bfef7179ce30755b27f7e9be302" }, "private": { @@ -46,7 +46,7 @@ "oldBlobStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "oldBlobAccInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "oldNumBlob": 0, - "forkID": 9, + "forkID": 10, "oldStateRoot": "0x799c98013da3f7a43b6e8086d0cedd89bd6a9bfef7179ce30755b27f7e9be302" }, "private": { @@ -82,7 +82,7 @@ "oldBlobStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "oldBlobAccInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", "oldNumBlob": 0, - "forkID": 9, + "forkID": 10, "oldStateRoot": "0x799c98013da3f7a43b6e8086d0cedd89bd6a9bfef7179ce30755b27f7e9be302" }, "private": { @@ -102,7 +102,7 @@ "newBlobStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "newBlobAccInputHash": "0x16a732fdf8b663112fa30baa38f484ca298e87d563601eace4a3d9e1620960ee", "newNumBlob": 1, - "finalAccBatchHashData": "0xa78cd7278eb8b48a40e791486985ad6290af374ca45ad962ed08cc83b2e184ba", + "finalAccBatchHashData": "0x0000000000000000000000000000000000000000000000000000000000000000", "localExitRootFromBlob": "0x0000000000000000000000000000000000000000000000000000000000000001", "isInvalid": true } diff --git a/test/helpers/test-vectors/block-info/block-info-batches.json b/test/helpers/test-vectors/block-info/block-info-batches.json index 68f591ac..f852bb76 100644 --- a/test/helpers/test-vectors/block-info/block-info-batches.json +++ b/test/helpers/test-vectors/block-info/block-info-batches.json @@ -3,7 +3,7 @@ "id": 0, "description": "Get timestamp", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "sequencerPvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", "genesis": [ @@ -540,7 +540,7 @@ "id": 1, "description": "Verify skip flags", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "sequencerPvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", "genesis": [ @@ -836,7 +836,7 @@ "id": 2, "description": "Previous batch partition in just one batch", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "sequencerPvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", "genesis": [ diff --git a/test/helpers/test-vectors/block-info/block-info.json b/test/helpers/test-vectors/block-info/block-info.json index 46d9847f..c9d7ba26 100644 --- a/test/helpers/test-vectors/block-info/block-info.json +++ b/test/helpers/test-vectors/block-info/block-info.json @@ -3,7 +3,7 @@ "id": 0, "description": "Get timestamp", "chainID": 1000, - "forkID": 8, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "sequencerPvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", "genesis": [ diff --git a/test/helpers/test-vectors/end-to-end/e2e-circuits.json b/test/helpers/test-vectors/end-to-end/e2e-circuits.json new file mode 100644 index 00000000..93c08421 --- /dev/null +++ b/test/helpers/test-vectors/end-to-end/e2e-circuits.json @@ -0,0 +1,490 @@ +[ + { + "id": 0, + "description": "e2e all circuits", + "chainID": 1000, + "forkID": 10, + "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "aggregatorAddress": "0x64E968003c934F8d7Ad9a4e30F48EE8e2409baE6", + "sequencerPvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", + "genesis": [ + { + "address": "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d", + "balance": "100000000000000000000", + "nonce": "0", + "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e" + }, + { + "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "balance": "200000000000000000000", + "nonce": "0", + "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23" + } + ], + "oldStateRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "oldLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "oldBatchAccInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "blobOuters": [ + { + "zkGasLimit": "10000000", + "blobType": 0, + "forcedHashData": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousL1InfoTreeRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousL1InfoTreeIndex": 0, + "oldBatchAccInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "batches": [ + { + "txs": [ + { + "type": 11, + "deltaTimestamp": "1", + "l1InfoTree": { + "globalExitRoot": "0x16994edfddddb9480667b64174fc00d3b6da7290d37b8db3a16571b4ddf0789f", + "blockHash": "0x24a5871d68723340d9eadc674aa8ad75f3e33b61d5a9db7db92af856a19270bb", + "minTimestamp": "42" + }, + "indexL1InfoTree": 0, + "reason": "", + "customRawTx": "0x0b0000000100000000" + }, + { + "from": "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d", + "to": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": 0, + "value": "22000000000000000000", + "gasLimit": 100000, + "gasPrice": "1000000000", + "chainId": 1000, + "rawTx": "0xf86f80843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff8901314fb37062980000808207f3a0f9ea8e90ae323e360a22bd0b1a972d15cb33df6ccbfbada4a0d49792d1164ea5a06029d84d5093a7186fb5bf2f1b7258d57e9c09ac89c4cb8eb44a3c961c4dd89b", + "customRawTx": "0xef80843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff8901314fb37062980000808203e88080f9ea8e90ae323e360a22bd0b1a972d15cb33df6ccbfbada4a0d49792d1164ea56029d84d5093a7186fb5bf2f1b7258d57e9c09ac89c4cb8eb44a3c961c4dd89b1bff" + } + ], + "newStateRoot": "0xc66ec2e1ba7fafd9b2224602ce059091e7c77598d94d247d54cf3e46e45c6f73", + "expectedNewLeafs": { + "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d": { + "balance": "78000000000000000000", + "nonce": "1" + }, + "0x4d5cf5032b2a844602278b01199ed191a86c93ff": { + "balance": "222000000000000000000", + "nonce": "0" + }, + "0x000000000000000000000000000000005ca1ab1e": { + "balance": "0", + "nonce": "0", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x01", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x01", + "0xa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0xeb81067ca2f0b5f4fb41f17901e949892f9adb48ef41c0b04656fc0207582df8" + } + } + }, + "batchL2Data": "0x0b0000000100000000ef80843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff8901314fb37062980000808203e88080f9ea8e90ae323e360a22bd0b1a972d15cb33df6ccbfbada4a0d49792d1164ea56029d84d5093a7186fb5bf2f1b7258d57e9c09ac89c4cb8eb44a3c961c4dd89b1bff", + "newLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "batchHashData": "0x3e0ef8cd3a369bbd4f8d261b5d5622ad5879ec564230673a9fa8fc40e1e02f45", + "skipFirstChangeL2Block": false, + "skipWriteBlockInfoRoot": false, + "newL1InfoTreeRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newL1InfoTreeIndex": 0 + }, + { + "txs": [ + { + "type": 11, + "deltaTimestamp": "1944498031", + "l1InfoTree": { + "globalExitRoot": "0x16994edfddddb9480667b64174fc00d3b6da7290d37b8db3a16571b4ddf0789f", + "blockHash": "0x24a5871d68723340d9eadc674aa8ad75f3e33b61d5a9db7db92af856a19270bb", + "minTimestamp": "42" + }, + "indexL1InfoTree": 0, + "reason": "", + "customRawTx": "0x0b73e6af6f00000000" + }, + { + "from": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "to": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", + "nonce": 0, + "value": "2000000000000000000", + "gasLimit": 100000, + "gasPrice": "1000000000", + "chainId": 1000, + "rawTx": "0xf86e80843b9aca00830186a094617b3a3528f9cdd6630fd3301b9c8911f7bf063d881bc16d674ec80000808207f3a04902102bdd9b91ae389102098dd7d8cb6e732410851223a1153cbe78b0c54d1ea063bd7740451f2efcf88bbebdcc334ff3b3e3c332fbbf5703e4699124454663ba", + "customRawTx": "0xee80843b9aca00830186a094617b3a3528f9cdd6630fd3301b9c8911f7bf063d881bc16d674ec80000808203e880804902102bdd9b91ae389102098dd7d8cb6e732410851223a1153cbe78b0c54d1e63bd7740451f2efcf88bbebdcc334ff3b3e3c332fbbf5703e4699124454663ba1bff" + } + ], + "newStateRoot": "0x885edbf5a857b3879aed0d5deff7e8a3b62113d03c01b3a00082f0f81da1593b", + "expectedNewLeafs": { + "0x000000000000000000000000000000005ca1ab1e": { + "balance": "0", + "nonce": "0", + "storage": { + "0xa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "0xcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f": "0xc66ec2e1ba7fafd9b2224602ce059091e7c77598d94d247d54cf3e46e45c6f73", + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x02", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x73e6af70", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0xb49b443045c345747e9188750579ae3ff56ddcb47bf8f8c2bed3c11fab6f9fa7" + } + }, + "0x4d5cf5032b2a844602278b01199ed191a86c93ff": { + "balance": "219999979000000000000", + "nonce": "1" + }, + "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d": { + "balance": "80000021000000000000", + "nonce": "1" + } + }, + "batchL2Data": "0x0b73e6af6f00000000ee80843b9aca00830186a094617b3a3528f9cdd6630fd3301b9c8911f7bf063d881bc16d674ec80000808203e880804902102bdd9b91ae389102098dd7d8cb6e732410851223a1153cbe78b0c54d1e63bd7740451f2efcf88bbebdcc334ff3b3e3c332fbbf5703e4699124454663ba1bff", + "newLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "batchHashData": "0x404cb9de715588844f034466dcb656ab1fdf909180f6ec397ada12dc72d7f4c0", + "newL1InfoTreeRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newL1InfoTreeIndex": 0 + }, + { + "txs": [ + { + "type": 11, + "deltaTimestamp": "1", + "l1InfoTree": { + "globalExitRoot": "0x16994edfddddb9480667b64174fc00d3b6da7290d37b8db3a16571b4ddf0789f", + "blockHash": "0x24a5871d68723340d9eadc674aa8ad75f3e33b61d5a9db7db92af856a19270bb", + "minTimestamp": "42" + }, + "indexL1InfoTree": 0, + "reason": "", + "customRawTx": "0x0b0000000100000000" + }, + { + "type": 11, + "deltaTimestamp": "1", + "l1InfoTree": { + "globalExitRoot": "0x16994edfddddb9480667b64174fc00d3b6da7290d37b8db3a16571b4ddf0789f", + "blockHash": "0x24a5871d68723340d9eadc674aa8ad75f3e33b61d5a9db7db92af856a19270bb", + "minTimestamp": "42" + }, + "indexL1InfoTree": 0, + "reason": "", + "customRawTx": "0x0b0000000100000000" + } + ], + "newStateRoot": "0x94e2694f541e98b6b8cfb2828bda65ea24c230d81e0935cacebcb8bc27dd864d", + "expectedNewLeafs": { + "0x000000000000000000000000000000005ca1ab1e": { + "balance": "0", + "nonce": "0", + "storage": { + "0xa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "0xcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f": "0xc66ec2e1ba7fafd9b2224602ce059091e7c77598d94d247d54cf3e46e45c6f73", + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x04", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x73e6af72", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0xe8909ebfade647bdb30e38fcb3b316d263943a8e7f84a3106a0ae46e72b9366e", + "0xd9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330f": "0x885edbf5a857b3879aed0d5deff7e8a3b62113d03c01b3a00082f0f81da1593b", + "0x7dfe757ecd65cbd7922a9c0161e935dd7fdbcc0e999689c7d31633896b1fc60b": "0x139f3f425e1ea1e50e46299a16aaee17f8a2d29097dda14b72dd759675c12290" + } + } + }, + "batchL2Data": "0x0b00000001000000000b0000000100000000", + "newLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "batchHashData": "0xcef25df9487d86d4e936af7dfd545b1b18be2fbf947552955cfa033d74a7f8a7", + "newL1InfoTreeRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newL1InfoTreeIndex": 0 + } + ], + "expected": { + "batchAggregation": { + "newStateRoot": "0x94e2694f541e98b6b8cfb2828bda65ea24c230d81e0935cacebcb8bc27dd864d", + "newBatchAccInputHash": "0xb97f392b0cafa501ec60aba6981ea2db79f7d335b4f1d1c62ed199442b3f16c2", + "newLastTimestamp": "1944498034", + "currentL1InfoTreeRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "currentL1InfoTreeIndex": 0 + }, + "blobInner": { + "newBlobStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newBlobAccInputHash": "0xcaafa97ea390e76e27c80a36e6ea1514338481a5b0db6a1a9f76af3f63995c75", + "newNumBlob": 1, + "finalAccBatchHashData": "0xb97f392b0cafa501ec60aba6981ea2db79f7d335b4f1d1c62ed199442b3f16c2", + "localExitRootFromBlob": "0x0000000000000000000000000000000000000000000000000000000000000000", + "isInvalid": false + }, + "blobOuter": { + "newStateRoot": "0x94e2694f541e98b6b8cfb2828bda65ea24c230d81e0935cacebcb8bc27dd864d", + "newBlobStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newBlobAccInputHash": "0xcaafa97ea390e76e27c80a36e6ea1514338481a5b0db6a1a9f76af3f63995c75", + "newNumBlob": 1, + "newLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + } + }, + { + "zkGasLimit": "10000000", + "blobType": 0, + "forcedHashData": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousL1InfoTreeRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousL1InfoTreeIndex": 0, + "oldBatchAccInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "batches": [ + { + "txs": [ + { + "type": 11, + "deltaTimestamp": "1", + "l1InfoTree": { + "globalExitRoot": "0x16994edfddddb9480667b64174fc00d3b6da7290d37b8db3a16571b4ddf0789f", + "blockHash": "0x24a5871d68723340d9eadc674aa8ad75f3e33b61d5a9db7db92af856a19270bb", + "minTimestamp": "42" + }, + "indexL1InfoTree": 0, + "reason": "", + "customRawTx": "0x0b0000000100000000" + }, + { + "from": "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d", + "to": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": 1, + "value": "22000000000000000000", + "gasLimit": 100000, + "gasPrice": "1000000000", + "chainId": 1000, + "rawTx": "0xf86f01843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff8901314fb37062980000808207f3a0b3efa7a5ca86fda596287bd82f6bbc0188acb0aacf0864162bfbf7444d7c7b9ba06f1c2307ba1e83bf212cb473e33c122ee3d9c29fed945bbd0a78e4995a6837be", + "customRawTx": "0xef01843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff8901314fb37062980000808203e88080b3efa7a5ca86fda596287bd82f6bbc0188acb0aacf0864162bfbf7444d7c7b9b6f1c2307ba1e83bf212cb473e33c122ee3d9c29fed945bbd0a78e4995a6837be1bff" + } + ], + "newStateRoot": "0xbf1ed0f89abad42f63fa698fdcdbc980aed90bc73b2166d5d6838feef8443558", + "expectedNewLeafs": { + "0x000000000000000000000000000000005ca1ab1e": { + "balance": "0", + "nonce": "0", + "storage": { + "0x7dfe757ecd65cbd7922a9c0161e935dd7fdbcc0e999689c7d31633896b1fc60b": "0x139f3f425e1ea1e50e46299a16aaee17f8a2d29097dda14b72dd759675c12290", + "0xa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "0xcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f": "0xc66ec2e1ba7fafd9b2224602ce059091e7c77598d94d247d54cf3e46e45c6f73", + "0xd9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330f": "0x885edbf5a857b3879aed0d5deff7e8a3b62113d03c01b3a00082f0f81da1593b", + "0xedc95719e9a3b28dd8e80877cb5880a9be7de1a13fc8b05e7999683b6b567643": "0x94e2694f541e98b6b8cfb2828bda65ea24c230d81e0935cacebcb8bc27dd864d", + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x05", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x73e6af73", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0xb2991ab296a16b1cdb1b97d531ab942fe7cbd71de7712d43a33adc47b98b7a71" + } + }, + "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d": { + "balance": "58000021000000000000", + "nonce": "2" + }, + "0x4d5cf5032b2a844602278b01199ed191a86c93ff": { + "balance": "241999979000000000000", + "nonce": "1" + } + }, + "batchL2Data": "0x0b0000000100000000ef01843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff8901314fb37062980000808203e88080b3efa7a5ca86fda596287bd82f6bbc0188acb0aacf0864162bfbf7444d7c7b9b6f1c2307ba1e83bf212cb473e33c122ee3d9c29fed945bbd0a78e4995a6837be1bff", + "newLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "batchHashData": "0xa7ab456957aaff9d7a2efeff1cdf905f0efc54856804a5f1917d3c46e816d7ed", + "skipFirstChangeL2Block": false, + "skipWriteBlockInfoRoot": false, + "newL1InfoTreeRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newL1InfoTreeIndex": 0 + } + ], + "expected": { + "batchAggregation": { + "newStateRoot": "0xbf1ed0f89abad42f63fa698fdcdbc980aed90bc73b2166d5d6838feef8443558", + "newBatchAccInputHash": "0xaf98377e881f17d3081ba3adb743800be8968639610f0efd1f0ba293ba9c45bd", + "newLastTimestamp": "1944498035", + "currentL1InfoTreeRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "currentL1InfoTreeIndex": 0 + }, + "blobInner": { + "newBlobStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newBlobAccInputHash": "0xa7b3498984c422939844fbe62337e219c2ac4a70e20bc1a31282cb038f118ee2", + "newNumBlob": 2, + "finalAccBatchHashData": "0xaf98377e881f17d3081ba3adb743800be8968639610f0efd1f0ba293ba9c45bd", + "localExitRootFromBlob": "0x0000000000000000000000000000000000000000000000000000000000000000", + "isInvalid": false + }, + "blobOuter": { + "newStateRoot": "0xbf1ed0f89abad42f63fa698fdcdbc980aed90bc73b2166d5d6838feef8443558", + "newBlobStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newBlobAccInputHash": "0xa7b3498984c422939844fbe62337e219c2ac4a70e20bc1a31282cb038f118ee2", + "newNumBlob": 2, + "newLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + } + }, + { + "zkGasLimit": "10000000", + "blobType": 0, + "forcedHashData": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousL1InfoTreeRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "previousL1InfoTreeIndex": 0, + "oldBatchAccInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "batches": [ + { + "txs": [ + { + "type": 11, + "deltaTimestamp": "1", + "l1InfoTree": { + "globalExitRoot": "0x16994edfddddb9480667b64174fc00d3b6da7290d37b8db3a16571b4ddf0789f", + "blockHash": "0x24a5871d68723340d9eadc674aa8ad75f3e33b61d5a9db7db92af856a19270bb", + "minTimestamp": "42" + }, + "indexL1InfoTree": 0, + "reason": "", + "customRawTx": "0x0b0000000100000000" + }, + { + "from": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "to": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": 1, + "value": "22000000000000000000", + "gasLimit": 100000, + "gasPrice": "1000000000", + "chainId": 1000, + "rawTx": "0xf86f01843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff8901314fb37062980000808207f3a0f04954c6b456af5a7950e251637dd461c371baa97b8899ef6e06bd661043af1ea051752adb5d6fcb206635dc4eb1965091e10eda834eb610581ec3f0192ac942cb", + "customRawTx": "0xef01843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff8901314fb37062980000808203e88080f04954c6b456af5a7950e251637dd461c371baa97b8899ef6e06bd661043af1e51752adb5d6fcb206635dc4eb1965091e10eda834eb610581ec3f0192ac942cb1bff" + } + ], + "newStateRoot": "0xc48a6f0a00228c8a0da8ed232cbb8c9d5da77f929931498e9a23120a62d02558", + "expectedNewLeafs": { + "0x000000000000000000000000000000005ca1ab1e": { + "balance": "0", + "nonce": "0", + "storage": { + "0x7dfe757ecd65cbd7922a9c0161e935dd7fdbcc0e999689c7d31633896b1fc60b": "0x139f3f425e1ea1e50e46299a16aaee17f8a2d29097dda14b72dd759675c12290", + "0xa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "0xcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f": "0xc66ec2e1ba7fafd9b2224602ce059091e7c77598d94d247d54cf3e46e45c6f73", + "0xd9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330f": "0x885edbf5a857b3879aed0d5deff7e8a3b62113d03c01b3a00082f0f81da1593b", + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x06", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x73e6af74", + "0xe2689cd4a84e23ad2f564004f1c9013e9589d260bde6380aba3ca7e09e4df40c": "0xbf1ed0f89abad42f63fa698fdcdbc980aed90bc73b2166d5d6838feef8443558", + "0xedc95719e9a3b28dd8e80877cb5880a9be7de1a13fc8b05e7999683b6b567643": "0x94e2694f541e98b6b8cfb2828bda65ea24c230d81e0935cacebcb8bc27dd864d", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0xeb15cbb91a66ec33eec8855b42cf9dc083aeb0630fe6781eeac71c5bd97c244c" + } + }, + "0x4d5cf5032b2a844602278b01199ed191a86c93ff": { + "balance": "241999958000000000000", + "nonce": "2" + }, + "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d": { + "balance": "58000042000000000000", + "nonce": "2" + } + }, + "batchL2Data": "0x0b0000000100000000ef01843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff8901314fb37062980000808203e88080f04954c6b456af5a7950e251637dd461c371baa97b8899ef6e06bd661043af1e51752adb5d6fcb206635dc4eb1965091e10eda834eb610581ec3f0192ac942cb1bff", + "newLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "batchHashData": "0x447b02a69c9db656005276c2b8d476fa466a6007fa0b3e3f36d7c5903e953dba", + "skipFirstChangeL2Block": false, + "skipWriteBlockInfoRoot": false, + "newL1InfoTreeRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newL1InfoTreeIndex": 0 + }, + { + "txs": [ + { + "type": 11, + "deltaTimestamp": "1", + "l1InfoTree": { + "globalExitRoot": "0x16994edfddddb9480667b64174fc00d3b6da7290d37b8db3a16571b4ddf0789f", + "blockHash": "0x24a5871d68723340d9eadc674aa8ad75f3e33b61d5a9db7db92af856a19270bb", + "minTimestamp": "42" + }, + "indexL1InfoTree": 0, + "reason": "", + "customRawTx": "0x0b0000000100000000" + }, + { + "from": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "to": "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d", + "nonce": 2, + "value": "22000000000000000000", + "gasLimit": 100000, + "gasPrice": "1000000000", + "chainId": 1000, + "rawTx": "0xf86f02843b9aca00830186a094617b3a3528f9cdd6630fd3301b9c8911f7bf063d8901314fb37062980000808207f3a03a8de3ca4e2d3ae7e6b25e26848b838172333a08fa3e6f1e4d3f0606f1b9d063a03576cc42b79b1e614d43ad338a320a828bbeb4bdd06e63101fd189a4ffaf9cb4", + "customRawTx": "0xef02843b9aca00830186a094617b3a3528f9cdd6630fd3301b9c8911f7bf063d8901314fb37062980000808203e880803a8de3ca4e2d3ae7e6b25e26848b838172333a08fa3e6f1e4d3f0606f1b9d0633576cc42b79b1e614d43ad338a320a828bbeb4bdd06e63101fd189a4ffaf9cb41bff" + }, + { + "from": "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d", + "to": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", + "nonce": 2, + "value": "22000000000000000000", + "gasLimit": 100000, + "gasPrice": "1000000000", + "chainId": 1000, + "rawTx": "0xf86f02843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff8901314fb37062980000808207f4a077e1a9edc020ae7ae247b20232af6be41200d14b0225ac687be0b8b986f801b9a041e657efb582eb091fe7d901b7697aa7635bf892e0bc828fea05916b7f2f6e60", + "customRawTx": "0xef02843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff8901314fb37062980000808203e8808077e1a9edc020ae7ae247b20232af6be41200d14b0225ac687be0b8b986f801b941e657efb582eb091fe7d901b7697aa7635bf892e0bc828fea05916b7f2f6e601cff" + } + ], + "newStateRoot": "0xdcd43410d7b738d63e88feb0bef716f5176750fa3bc974b509c0a1ea5f123d43", + "expectedNewLeafs": { + "0x000000000000000000000000000000005ca1ab1e": { + "balance": "0", + "nonce": "0", + "storage": { + "0x7dfe757ecd65cbd7922a9c0161e935dd7fdbcc0e999689c7d31633896b1fc60b": "0x139f3f425e1ea1e50e46299a16aaee17f8a2d29097dda14b72dd759675c12290", + "0x8f331abe73332f95a25873e8b430885974c0409691f89d643119a11623a7924a": "0xc48a6f0a00228c8a0da8ed232cbb8c9d5da77f929931498e9a23120a62d02558", + "0xa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", + "0xcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f": "0xc66ec2e1ba7fafd9b2224602ce059091e7c77598d94d247d54cf3e46e45c6f73", + "0xd9d16d34ffb15ba3a3d852f0d403e2ce1d691fb54de27ac87cd2f993f3ec330f": "0x885edbf5a857b3879aed0d5deff7e8a3b62113d03c01b3a00082f0f81da1593b", + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x07", + "0x0000000000000000000000000000000000000000000000000000000000000002": "0x73e6af75", + "0xe2689cd4a84e23ad2f564004f1c9013e9589d260bde6380aba3ca7e09e4df40c": "0xbf1ed0f89abad42f63fa698fdcdbc980aed90bc73b2166d5d6838feef8443558", + "0xedc95719e9a3b28dd8e80877cb5880a9be7de1a13fc8b05e7999683b6b567643": "0x94e2694f541e98b6b8cfb2828bda65ea24c230d81e0935cacebcb8bc27dd864d", + "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0d31526a02059db0de0debbdc395580c3e9c219e3932c057c6638856c8ed8e7e" + } + }, + "0x4d5cf5032b2a844602278b01199ed191a86c93ff": { + "balance": "241999937000000000000", + "nonce": "3" + }, + "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d": { + "balance": "58000063000000000000", + "nonce": "3" + } + }, + "batchL2Data": "0x0b0000000100000000ef02843b9aca00830186a094617b3a3528f9cdd6630fd3301b9c8911f7bf063d8901314fb37062980000808203e880803a8de3ca4e2d3ae7e6b25e26848b838172333a08fa3e6f1e4d3f0606f1b9d0633576cc42b79b1e614d43ad338a320a828bbeb4bdd06e63101fd189a4ffaf9cb41bffef02843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff8901314fb37062980000808203e8808077e1a9edc020ae7ae247b20232af6be41200d14b0225ac687be0b8b986f801b941e657efb582eb091fe7d901b7697aa7635bf892e0bc828fea05916b7f2f6e601cff", + "newLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "batchHashData": "0xbb87fbdd657d39c0894f9c55ead9c07116ed921e20707c6dc1a3c579fc1e4922", + "skipFirstChangeL2Block": false, + "skipWriteBlockInfoRoot": false, + "newL1InfoTreeRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newL1InfoTreeIndex": 0 + } + ], + "expected": { + "batchAggregation": { + "newStateRoot": "0xdcd43410d7b738d63e88feb0bef716f5176750fa3bc974b509c0a1ea5f123d43", + "newBatchAccInputHash": "0x287d430f52f249bc67f146b4e73552e0c69899bcc411f8bd0cf86996109f2ca0", + "newLastTimestamp": "1944498037", + "currentL1InfoTreeRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "currentL1InfoTreeIndex": 0 + }, + "blobInner": { + "newBlobStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newBlobAccInputHash": "0x9070a522e33fd52f9ac8221ab5c5e77c8c7b5378d553835574d931ce2a51f79e", + "newNumBlob": 3, + "finalAccBatchHashData": "0x287d430f52f249bc67f146b4e73552e0c69899bcc411f8bd0cf86996109f2ca0", + "localExitRootFromBlob": "0x0000000000000000000000000000000000000000000000000000000000000000", + "isInvalid": false + }, + "blobOuter": { + "newStateRoot": "0xdcd43410d7b738d63e88feb0bef716f5176750fa3bc974b509c0a1ea5f123d43", + "newBlobStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newBlobAccInputHash": "0x9070a522e33fd52f9ac8221ab5c5e77c8c7b5378d553835574d931ce2a51f79e", + "newNumBlob": 3, + "newLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000" + } + } + } + ], + "expectedFinal": { + "newStateRoot": "0xdcd43410d7b738d63e88feb0bef716f5176750fa3bc974b509c0a1ea5f123d43", + "newBlobStateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "newBlobAccInputHash": "0x9070a522e33fd52f9ac8221ab5c5e77c8c7b5378d553835574d931ce2a51f79e", + "newNumBlob": 3, + "newLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", + "aggregatorAddress": "0x64E968003c934F8d7Ad9a4e30F48EE8e2409baE6", + "inputSnark": "0x00d6ec4e53cf5125f27039348cab112b46603fa02dccae62c26b71b249bf0a84" + } + } +] \ No newline at end of file diff --git a/test/helpers/test-vectors/end-to-end/state-transition-e2e.json b/test/helpers/test-vectors/end-to-end/state-transition-e2e.json index 77c1cc60..ed374b2c 100644 --- a/test/helpers/test-vectors/end-to-end/state-transition-e2e.json +++ b/test/helpers/test-vectors/end-to-end/state-transition-e2e.json @@ -4,7 +4,7 @@ "description": "Test end to end", "bridgeDeployed": true, "chainID": 1000, - "forkID": 8, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "sequencerPvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", "genesis": [ diff --git a/test/helpers/test-vectors/inputs-executor/input_executor.json b/test/helpers/test-vectors/inputs-executor/input_executor.json index 004ef09e..6f6db568 100644 --- a/test/helpers/test-vectors/inputs-executor/input_executor.json +++ b/test/helpers/test-vectors/inputs-executor/input_executor.json @@ -7,7 +7,7 @@ "oldNumBatch": 0, "newNumBatch": 1, "chainID": 1000, - "forkID": 9, + "forkID": 10, "batchL2Data": "0x0b73e6af6e00000001ee80843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff88016345785d8a0000808203e880801cee7e01dc62f69a12c3510c6d64de04ee6346d84b6a017f3e786c7d87f963e75d8cc91fa983cd6d9cf55fff80d73bd26cd333b0f098acc1e58edb1fd484ad731bff0b0000000100000002", "sequencerAddr": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "batchHashData": "0x32b53865e6e076378b62b6c02beabba42ba63289796dda21df27bb766439ec2b", diff --git a/test/helpers/test-vectors/processor/state-transition-etrog.json b/test/helpers/test-vectors/processor/state-transition-etrog.json index 5439c1e4..de50592f 100644 --- a/test/helpers/test-vectors/processor/state-transition-etrog.json +++ b/test/helpers/test-vectors/processor/state-transition-etrog.json @@ -3,7 +3,7 @@ "id": 0, "description": "2 accounts and 1 valid transaction.", "chainID": 1000, - "forkID": 8, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "timestampLimit": 1944498031, "forcedBlockHashL1": "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -181,7 +181,7 @@ "id": 1, "description": "Forced batch: 2 accounts and 1 valid transaction", "chainID": 1000, - "forkID": 8, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "timestampLimit": 1944498031, "forcedBlockHashL1": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", @@ -265,7 +265,7 @@ "id": 2, "description": "Forced batch: starts with changeL2Block --> invalid batch", "chainID": 1000, - "forkID": 8, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "timestampLimit": 1944498031, "forcedBlockHashL1": "0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3", diff --git a/test/helpers/test-vectors/processor/state-transition-feijoa.json b/test/helpers/test-vectors/processor/state-transition-feijoa.json index 04693f54..ccc8beb3 100644 --- a/test/helpers/test-vectors/processor/state-transition-feijoa.json +++ b/test/helpers/test-vectors/processor/state-transition-feijoa.json @@ -3,7 +3,7 @@ "id": 0, "description": "Batch with two blocks with new blockInfoTree index", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "genesis": [ { @@ -175,7 +175,7 @@ "batchHashData": "0xd701021881711af19cce8045e02a565da5f1c117e79b015ad8bf2fac06cb3a88", "oldLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "oldBatchAccInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "newBatchAccInputHash": "0xa21050d2dbc0f9ddc66a2b61e4d6fb7c70a78d2fb8ea0305e4bd9948e897dd83", + "newBatchAccInputHash": "0x9ac9dbbbbff66d093c4b68a93dedde622cb3a468d6bb6301e2dc692a1912d743", "newL1InfoTreeRoot": "0xe6101bc39e53988f6af5f2269394b8a988b8560216eaba87ac8ef44d586d85bb", "newL1InfoTreeIndex": 3 }, @@ -183,7 +183,7 @@ "id": 1, "description": "Batch with two blocks with new blockInfoTree index, previousL1InfoTreeIndex is zero", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "genesis": [ { @@ -356,7 +356,7 @@ "batchHashData": "0xd701021881711af19cce8045e02a565da5f1c117e79b015ad8bf2fac06cb3a88", "oldLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "oldBatchAccInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "newBatchAccInputHash": "0xa21050d2dbc0f9ddc66a2b61e4d6fb7c70a78d2fb8ea0305e4bd9948e897dd83", + "newBatchAccInputHash": "0x9ac9dbbbbff66d093c4b68a93dedde622cb3a468d6bb6301e2dc692a1912d743", "newL1InfoTreeRoot": "0xc1092bc3b2def186d9b4c80b20093c05352ee2b8f248dc80b569cef4a4aac44e", "newL1InfoTreeIndex": 3 }, @@ -364,7 +364,7 @@ "id": 2, "description": "Forced batch: 2 accounts and 1 valid transaction", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "genesis": [ { @@ -447,7 +447,7 @@ "batchHashData": "0x8b8b9af0fafef950a10fb0ebc624afa77e8038b7a8fa0e879b14fbfe96971ba4", "oldLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "oldBatchAccInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "newBatchAccInputHash": "0xd0fe57f8649fd013b8c9ef279272003f2ed3eee7a0380a6c0ae0140100c0570c", + "newBatchAccInputHash": "0xc75f9545a7dd317221a528c176cb3326799722f80f3edb30da641e792a5b8458", "newL1InfoTreeRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "newL1InfoTreeIndex": 0 }, @@ -455,7 +455,7 @@ "id": 3, "description": "Forced batch: starts with changeL2Block --> invalid batch", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "genesis": [ { @@ -605,7 +605,7 @@ "batchHashData": "0x32b53865e6e076378b62b6c02beabba42ba63289796dda21df27bb766439ec2b", "oldLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "oldBatchAccInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "newBatchAccInputHash": "0x5b24bd4eb18a304f1ec227df8757e3a9a511bd4f913dad895ce53f91f3762d10", + "newBatchAccInputHash": "0xac4a7dad5dd827d8bb9fc160caf3727c140eb3db0dcc5d61afe3a37d954a7d1b", "newL1InfoTreeRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "newL1InfoTreeIndex": 0 } diff --git a/test/helpers/test-vectors/processor/state-transition.json b/test/helpers/test-vectors/processor/state-transition.json index 2b1f83fb..ba3c2394 100644 --- a/test/helpers/test-vectors/processor/state-transition.json +++ b/test/helpers/test-vectors/processor/state-transition.json @@ -3,7 +3,7 @@ "id": 0, "description": "2 accounts and 1 valid transaction.", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "genesis": [ { @@ -92,7 +92,7 @@ "id": 1, "description": "5 accounts. 2 valid tx, 3 invalid tx (same amount as balance, invalid nonce, invalid chain id 1)", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "genesis": [ { @@ -272,7 +272,7 @@ "id": 2, "description": "2 accounts and 1 invalid tx (tx with more value than balance). Old root equals new root.", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "genesis": [ { @@ -357,7 +357,7 @@ "id": 3, "description": "2 accounts and 4 invalid transactions. Two of the transactions have invalid from and to address so no rawTx is provided for them, can be ignored.Tx with same amount than balance and tx with invalid chain id (different chain id than sequencer). Old root equals new root", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "genesis": [ { @@ -477,7 +477,7 @@ "id": 4, "description": "2 accounts and 1 invalid transaction. Wrong encode of the tx (invalid signature). Old root equals new root", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "genesis": [ { @@ -551,7 +551,7 @@ "id": 5, "description": "2 accounts and 1 valid transaction, from and to are the same", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", "genesis": [ { @@ -640,7 +640,7 @@ "id": 6, "description": "2 accounts. 1 valid tx, 3 invalid tx (same amount as balance, invalid nonce, invalid chain id", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", "genesis": [ { @@ -768,7 +768,7 @@ "id": 7, "description": "2 accounts and 1 valid transaction, from, to and sequencer are the same", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "genesis": [ { @@ -857,7 +857,7 @@ "id": 8, "description": "2 accounts and 2 valid transaction, sequencer is able to do the transaction because the fees are payed at the end of every tx", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "genesis": [ { @@ -959,7 +959,7 @@ "id": 9, "description": "2 accounts and 4 valid transaction, 4 transactions from the same account", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", "genesis": [ { @@ -1087,7 +1087,7 @@ "id": 10, "description": "2 accounts + 1 contract + and 2 valid transaction.", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "sequencerPvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", "genesis": [ @@ -1217,7 +1217,7 @@ "id": 11, "description": "2 accounts + 2 contract + and 1 tx to contract + contract call ", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "sequencerPvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", "genesis": [ @@ -1342,7 +1342,7 @@ "id": 12, "description": "2 accounts + 2 contract with constructor + and 1 tx to contract + 1 contract call", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "sequencerPvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", "genesis": [ @@ -1478,7 +1478,7 @@ "id": 13, "description": "2 accounts + and 1 tx to contract deploy + 1 call to deplyed contract", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "sequencerPvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", "genesis": [ @@ -1614,7 +1614,7 @@ "id": 14, "description": "2 accounts and 3 valid transactions", "chainID": 1000, - "forkID": 9, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "genesis": [ { diff --git a/test/helpers/test-vectors/selfdestruct/selfdestruct.json b/test/helpers/test-vectors/selfdestruct/selfdestruct.json index 81e4bf7a..97174dbb 100644 --- a/test/helpers/test-vectors/selfdestruct/selfdestruct.json +++ b/test/helpers/test-vectors/selfdestruct/selfdestruct.json @@ -3,7 +3,7 @@ "id": 0, "description": "Selfdestruct", "chainID": 1000, - "forkID": 8, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "sequencerPvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", "genesis": [ diff --git a/test/helpers/test-vectors/zkevm-db/recursive.json b/test/helpers/test-vectors/zkevm-db/recursive.json deleted file mode 100644 index 0cec2718..00000000 --- a/test/helpers/test-vectors/zkevm-db/recursive.json +++ /dev/null @@ -1,166 +0,0 @@ -[ - { - "id": 0, - "description": "2 accounts and 1 valid transaction.", - "chainID": 1000, - "forkID": 9, - "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", - "oldBatchAccInputHash": "0x0000000000000000000000000000000000000000000000000000000000000000", - "aggregatorAddress": "0x0123456789012345678901234567890123456789", - "genesis": [ - { - "address": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", - "pvtKey": "0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e", - "balance": "100000000000000000000", - "nonce": "0" - }, - { - "address": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", - "pvtKey": "0x4d27a600dce8c29b7bd080e29a26972377dbb04d7a27d919adbb602bf13cfd23", - "balance": "200000000000000000000", - "nonce": "0" - } - ], - "oldStateRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", - "batches": [ - { - "txs": [ - { - "type": 11, - "deltaTimestamp": "1944498031", - "l1InfoTree": { - "globalExitRoot": "0x16994edfddddb9480667b64174fc00d3b6da7290d37b8db3a16571b4ddf0789f", - "blockHash": "0x24a5871d68723340d9eadc674aa8ad75f3e33b61d5a9db7db92af856a19270bb", - "minTimestamp": "42" - }, - "indexL1InfoTree": 0, - "reason": "", - "customRawTx": "0x0b73e6af6f00000000" - }, - { - "id": 0, - "from": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", - "to": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", - "nonce": 0, - "value": "1000000000000000000", - "gasLimit": 100000, - "gasPrice": "1000000000", - "chainId": 1000, - "rawTx": "0xf86d80843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff88016345785d8a0000808207f5a01186622d03b6b8da7cf111d1ccba5bb185c56deae6a322cebc6dda0556f3cb979f910c26408b64b51c5da36ba2f38ef55ba1cee719d5a6c01225968799907432", - "reason": "", - "customRawTx": "0xee80843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff880de0b6b3a7640000808203e880803317280d96c3ed303a42d9da2638805301351c96cad135380ffa544d3c2bc96a6a55cef2d3827323f134976dd99a33bebef27b5e99c454fb1f8d4a4861ac4e0f1cff" - } - ], - "newStateRoot": "0xdce3cbabb38e22f9b4faa7f146e03234f770efd5e034f0ea34c428378653981d", - "newBatchAccInputHash": "0x1e5c2a35311592bced4f999fbec973b9509491ff4efadf3dc371fd459dd3575b", - "newLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", - "newNumBatch": 1, - "batchL2Data": "0x0b73e6af6f00000000ee80843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff880de0b6b3a7640000808203e880803317280d96c3ed303a42d9da2638805301351c96cad135380ffa544d3c2bc96a6a55cef2d3827323f134976dd99a33bebef27b5e99c454fb1f8d4a4861ac4e0f1cff", - "expectedNewLeafs": { - "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d": { - "balance": "99000000000000000000", - "nonce": "1", - "storage": null, - "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", - "bytecodeLength": 0 - }, - "0x4d5cf5032b2a844602278b01199ed191a86c93ff": { - "balance": "201000000000000000000", - "nonce": "0", - "storage": null, - "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", - "bytecodeLength": 0 - }, - "0x000000000000000000000000000000005ca1ab1e": { - "balance": "0", - "nonce": "0", - "storage": { - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x01", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x73e6af6f", - "0xa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x0627f99dd3b4b9410a7c6e9de8140a3a3a43501c5017e0942db84cb9cc0590d3" - }, - "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", - "bytecodeLength": 0 - } - }, - "newL1InfoTreeRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", - "newL1InfoTreeIndex": 1 - }, - { - "txs": [ - { - "type": 11, - "deltaTimestamp": "1", - "l1InfoTree": { - "globalExitRoot": "0x16994edfddddb9480667b64174fc00d3b6da7290d37b8db3a16571b4ddf0789f", - "blockHash": "0x24a5871d68723340d9eadc674aa8ad75f3e33b61d5a9db7db92af856a19270bb", - "minTimestamp": "42" - }, - "indexL1InfoTree": 0, - "reason": "", - "customRawTx": "0x0b0000000100000000" - }, - { - "id": 0, - "from": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", - "to": "0x4d5Cf5032B2a844602278b01199ED191A86c93ff", - "nonce": 1, - "value": "2000000000000000000", - "gasLimit": 100000, - "gasPrice": "1000000000", - "chainId": 1000, - "rawTx": "0xf86d80843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff88016345785d8a0000808207f5a01186622d03b6b8da7cf111d1ccba5bb185c56deae6a322cebc6dda0556f3cb979f910c26408b64b51c5da36ba2f38ef55ba1cee719d5a6c01225968799907432", - "reason": "", - "customRawTx": "0xee01843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff881bc16d674ec80000808203e88080bf1d7a420018877e3b781282465de4f3d6f2a5e678ce36fb694832a59ec437504c2dd20a8be59f26a3a84739512cafef34449d4008340ecebc9aea69dff382c31cff" - } - ], - "newStateRoot": "0x980788a678a534114fc2946998687ba7cbba11c91bc0809f8bdf0e63c04cbac0", - "newBatchAccInputHash": "0xbf4f8e2bff723ef661a13192bd68009342db11d9ed9b8ae7d1196cbca69fb866", - "newLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", - "newNumBatch": 2, - "batchL2Data": "0x0b0000000100000000ee01843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff881bc16d674ec80000808203e88080bf1d7a420018877e3b781282465de4f3d6f2a5e678ce36fb694832a59ec437504c2dd20a8be59f26a3a84739512cafef34449d4008340ecebc9aea69dff382c31cff", - "expectedNewLeafs": { - "0x000000000000000000000000000000005ca1ab1e": { - "balance": "0", - "nonce": "0", - "storage": { - "0xa6eef7e35abe7026729641147f7915573c7e97b47efa546f5f6e3230263bcb49": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", - "0xcc69885fda6bcc1a4ace058b4a62bf5e179ea78fd58a1ccd71c22cc9b688792f": "0xdce3cbabb38e22f9b4faa7f146e03234f770efd5e034f0ea34c428378653981d", - "0x0000000000000000000000000000000000000000000000000000000000000000": "0x02", - "0x0000000000000000000000000000000000000000000000000000000000000002": "0x73e6af70", - "0x0000000000000000000000000000000000000000000000000000000000000003": "0x900056265820a6a724fd7dcb9758bdd0f663ce83341ee9d06ec77189a90b969e" - }, - "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", - "bytecodeLength": 0 - }, - "0x617b3a3528f9cdd6630fd3301b9c8911f7bf063d": { - "balance": "97000000000000000000", - "nonce": "2", - "storage": null, - "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", - "bytecodeLength": 0 - }, - "0x4d5cf5032b2a844602278b01199ed191a86c93ff": { - "balance": "203000000000000000000", - "nonce": "0", - "storage": null, - "hashBytecode": "0x0000000000000000000000000000000000000000000000000000000000000000", - "bytecodeLength": 0 - } - }, - "newL1InfoTreeRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", - "newL1InfoTreeIndex": 1 - } - ], - "forcedHashData": "0x0000000000000000000000000000000000000000000000000000000000000000", - "previousL1InfoTreeRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d", - "previousL1InfoTreeIndex": 1, - "newStateRoot": "0x980788a678a534114fc2946998687ba7cbba11c91bc0809f8bdf0e63c04cbac0", - "newLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", - "newBatchAccInputHash": "0xbf4f8e2bff723ef661a13192bd68009342db11d9ed9b8ae7d1196cbca69fb866", - "newNumBatch": 2, - "inputSnark": "0x120e6250d03ecf8ec07041b0668c6ca2a8089e87cdc3e13f1573e89a915a2b66", - "expectedOldRoot": "0x4a9bfcb163ec91c5beb22e6aca41592433092c8c7821b01d37fd0de483f9265d" - } -] \ No newline at end of file diff --git a/test/helpers/test-vectors/zkevm-db/state-transition.json b/test/helpers/test-vectors/zkevm-db/state-transition.json index 2b114554..e94348e7 100644 --- a/test/helpers/test-vectors/zkevm-db/state-transition.json +++ b/test/helpers/test-vectors/zkevm-db/state-transition.json @@ -3,7 +3,7 @@ "id": 0, "description": "2 accounts and 1 valid transaction.", "chainID": 1000, - "forkID": 8, + "forkID": 10, "sequencerAddress": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D", "genesis": [ { diff --git a/test/processor.test.js b/test/processor.test.js index f91665b8..55984c2e 100644 --- a/test/processor.test.js +++ b/test/processor.test.js @@ -97,7 +97,6 @@ describe('Processor', async function () { db, poseidon, [F.zero, F.zero, F.zero, F.zero], - smtUtils.stringToH4(oldBatchAccInputHash), genesis, null, null, @@ -158,6 +157,7 @@ describe('Processor', async function () { const batch = await zkEVMDB.buildBatch( sequencerAddress, forcedHashData, + oldBatchAccInputHash, previousL1InfoTreeRoot, previousL1InfoTreeIndex, Constants.DEFAULT_MAX_TX, diff --git a/test/zkevm-db.test.js b/test/zkevm-db.test.js index b501a11b..7781159b 100644 --- a/test/zkevm-db.test.js +++ b/test/zkevm-db.test.js @@ -2,7 +2,6 @@ /* eslint-disable no-await-in-loop */ const fs = require('fs'); const path = require('path'); -const lodash = require('lodash'); const { Scalar } = require('ffjavascript'); const ethers = require('ethers'); @@ -19,20 +18,17 @@ const { serializeChangeL2Block } = require('../index').processorUtils; describe('ZkEVMDB', function () { this.timeout(100000); const pathZkevmDbTest = path.join(pathTestVectors, 'zkevm-db/state-transition.json'); - const pathZkevmDbTestRecursive = path.join(pathTestVectors, 'zkevm-db/recursive.json'); let update; let poseidon; let F; let testVectors; - let testVectorsRecursive; before(async () => { poseidon = await getPoseidon(); F = poseidon.F; testVectors = JSON.parse(fs.readFileSync(pathZkevmDbTest)); - testVectorsRecursive = JSON.parse(fs.readFileSync(pathZkevmDbTestRecursive)); update = argv.update === true; }); @@ -40,11 +36,11 @@ describe('ZkEVMDB', function () { it('Check zkEVMDB basic functions', async () => { const sequencerAddress = '0x0000000000000000000000000000000000000000'; const genesisRoot = [F.zero, F.zero, F.zero, F.zero]; - const oldBatchAccInputHash = [F.zero, F.zero, F.zero, F.zero]; + const oldBatchAccInputHash = '0x0000000000000000000000000000000000000000000000000000000000000000'; const genesis = []; const db = new MemDB(F); const chainID = 1000; - const forkID = 9; + const forkID = 10; const forcedHashData = Constants.ZERO_BYTES32; const previousL1InfoTreeRoot = Constants.ZERO_BYTES32; const previousL1InfoTreeIndex = 0; @@ -53,7 +49,6 @@ describe('ZkEVMDB', function () { db, poseidon, genesisRoot, - oldBatchAccInputHash, genesis, null, null, @@ -65,6 +60,7 @@ describe('ZkEVMDB', function () { const batch = await zkEVMDB.buildBatch( sequencerAddress, forcedHashData, + oldBatchAccInputHash, previousL1InfoTreeRoot, previousL1InfoTreeIndex, null, @@ -99,7 +95,6 @@ describe('ZkEVMDB', function () { null, null, null, - null, chainID, forkID, ); @@ -257,7 +252,6 @@ describe('ZkEVMDB', function () { db, poseidon, genesisRoot, - smtUtils.stringToH4(oldBatchAccInputHash), genesis, null, null, @@ -268,6 +262,7 @@ describe('ZkEVMDB', function () { const batch = await zkEVMDB.buildBatch( sequencerAddress, forcedHashData, + oldBatchAccInputHash, previousL1InfoTreeRoot, previousL1InfoTreeIndex, Constants.DEFAULT_MAX_TX, @@ -330,290 +325,4 @@ describe('ZkEVMDB', function () { await fs.writeFileSync(pathZkevmDbTest, JSON.stringify(testVectors, null, 2)); } }); - - it('Check zkEVMDB recursive functions', async () => { - const { - genesis, - oldStateRoot, - batches, - sequencerAddress, - previousL1InfoTreeRoot, - previousL1InfoTreeIndex, - oldBatchAccInputHash, - chainID, - forkID, - newStateRoot, - newLocalExitRoot, - newBatchAccInputHash, - newNumBatch, - aggregatorAddress, - inputSnark, - } = testVectorsRecursive[0]; - - const db = new MemDB(F); - const smt = new SMT(db, poseidon, poseidon.F); - - const walletMap = {}; - const addressArray = []; - const amountArray = []; - const nonceArray = []; - - // create genesis block - for (let j = 0; j < genesis.length; j++) { - const { - address, pvtKey, balance, nonce, - } = genesis[j]; - - const newWallet = new ethers.Wallet(pvtKey); - expect(address).to.be.equal(newWallet.address); - - walletMap[address] = newWallet; - addressArray.push(address); - amountArray.push(Scalar.e(balance)); - nonceArray.push(Scalar.e(nonce)); - } - - // set genesis block - const genesisRoot = await stateUtils.setGenesisBlock(addressArray, amountArray, nonceArray, smt); - for (let j = 0; j < addressArray.length; j++) { - const currentState = await stateUtils.getState(addressArray[j], smt, genesisRoot); - - expect(currentState.balance).to.be.equal(amountArray[j]); - expect(currentState.nonce).to.be.equal(nonceArray[j]); - } - - if (update) { - testVectorsRecursive[0].expectedOldRoot = smtUtils.h4toString(genesisRoot); - } else { - expect(smtUtils.h4toString(genesisRoot)).to.be.equal(oldStateRoot); - } - - /* - * build, sign transaction and generate rawTxs - * rawTxs would be the calldata inserted in the contract - */ - const extraData = { l1Info: {} }; - const rawBatches = []; - - for (let m = 0; m < batches.length; m++) { - const { txs } = batches[m]; - const rawTxs = []; - - for (let j = 0; j < txs.length; j++) { - const txData = txs[j]; - - if (txData.type === Constants.TX_CHANGE_L2_BLOCK) { - const rawChangeL2BlockTx = serializeChangeL2Block(txData); - - // Append l1Info to l1Info object - extraData.l1Info[txData.indexL1InfoTree] = txData.l1Info; - - const customRawTx = `0x${rawChangeL2BlockTx}`; - rawTxs.push(customRawTx); - - if (!update) { - expect(customRawTx).to.equal(txData.customRawTx); - } else { - txData.customRawTx = customRawTx; - } - // eslint-disable-next-line no-continue - continue; - } - - const tx = { - to: txData.to, - nonce: txData.nonce, - value: ethers.utils.parseUnits(txData.value, 'wei'), - gasLimit: txData.gasLimit, - gasPrice: ethers.utils.parseUnits(txData.gasPrice, 'wei'), - chainId: txData.chainId, - data: txData.data || '0x', - }; - if (!ethers.utils.isAddress(tx.to) || !ethers.utils.isAddress(txData.from)) { - expect(txData.customRawTx).to.equal(undefined); - // eslint-disable-next-line no-continue - continue; - } - - try { - let customRawTx; - - if (tx.chainId === 0) { - const signData = ethers.utils.RLP.encode([ - processorUtils.toHexStringRlp(Scalar.e(tx.nonce)), - processorUtils.toHexStringRlp(tx.gasPrice), - processorUtils.toHexStringRlp(tx.gasLimit), - processorUtils.toHexStringRlp(tx.to), - processorUtils.toHexStringRlp(tx.value), - processorUtils.toHexStringRlp(tx.data), - processorUtils.toHexStringRlp(tx.chainId), - '0x', - '0x', - ]); - const digest = ethers.utils.keccak256(signData); - const signingKey = new ethers.utils.SigningKey(walletMap[txData.from].privateKey); - const signature = signingKey.signDigest(digest); - const r = signature.r.slice(2).padStart(64, '0'); // 32 bytes - const s = signature.s.slice(2).padStart(64, '0'); // 32 bytes - const v = (signature.v).toString(16).padStart(2, '0'); // 1 bytes - customRawTx = signData.concat(r).concat(s).concat(v); - } else { - const rawTxEthers = await walletMap[txData.from].signTransaction(tx); - customRawTx = processorUtils.rawTxToCustomRawTx(rawTxEthers); - } - - if (update) { - testVectorsRecursive[0].batches[m].txs[j].customRawTx = customRawTx; - } else { - expect(customRawTx).to.equal(txData.customRawTx); - } - - if (txData.encodeInvalidData) { - customRawTx = customRawTx.slice(0, -6); - } - rawTxs.push(customRawTx); - } catch (error) { - expect(txData.customRawTx).to.equal(undefined); - } - } - rawBatches.push(rawTxs); - } - - // create a zkEVMDB and build a batch - const zkEVMDB = await ZkEVMDB.newZkEVM( - db, - poseidon, - genesisRoot, - smtUtils.stringToH4(oldBatchAccInputHash), - genesis, - null, - null, - chainID, - forkID, - ); - - // create batches - for (let m = 0; m < rawBatches.length; m++) { - const rawTxs = rawBatches[m]; - const batch = await zkEVMDB.buildBatch( - sequencerAddress, - Constants.ZERO_BYTES32, // forcedHashData - previousL1InfoTreeRoot, - previousL1InfoTreeIndex, - Constants.DEFAULT_MAX_TX, - { - skipVerifyL1InfoRoot: false, - }, - extraData, - ); - - for (let j = 0; j < rawTxs.length; j++) { - batch.addRawTx(rawTxs[j]); - } - - await batch.executeTxs(); - await zkEVMDB.consolidate(batch); - - const batchL2Data = await batch.getBatchL2Data(); - - if (update) { - testVectorsRecursive[0].batches[m].newStateRoot = smtUtils.h4toString(batch.currentStateRoot); - testVectorsRecursive[0].batches[m].newBatchAccInputHash = smtUtils.h4toString(batch.newBatchAccInputHash); - testVectorsRecursive[0].batches[m].newNumBatch = batch.newNumBatch; - testVectorsRecursive[0].batches[m].newLocalExitRoot = smtUtils.h4toString(batch.newLocalExitRoot); - testVectorsRecursive[0].batches[m].batchL2Data = batchL2Data; - testVectorsRecursive[0].batches[m].newL1InfoTreeRoot = batch.currentL1InfoTreeRoot; - testVectorsRecursive[0].batches[m].newL1InfoTreeIndex = batch.currentL1InfoTreeIndex; - } else { - expect(smtUtils.h4toString(batch.currentStateRoot)).to.be.equal(batches[m].newStateRoot); - expect(smtUtils.h4toString(batch.newBatchAccInputHash)).to.be.equal(batches[m].newBatchAccInputHash); - expect(batch.newNumBatch).to.be.equal(batches[m].newNumBatch); - expect(smtUtils.h4toString(batch.newLocalExitRoot)).to.be.equal(batches[m].newLocalExitRoot); - expect(batchL2Data).to.be.equal(batches[m].batchL2Data); - expect(batches[m].newL1InfoTreeRoot).to.be.equal(batch.currentL1InfoTreeRoot); - expect(batches[m].newL1InfoTreeIndex).to.be.equal(batch.currentL1InfoTreeIndex); - } - - // Check balances and nonces - const updatedAccounts = batch.getUpdatedAccountsBatch(); - - const newLeafs = {}; - // eslint-disable-next-line no-restricted-syntax, guard-for-in - for (const item in updatedAccounts) { - const address = item; - const account = updatedAccounts[address]; - newLeafs[address] = {}; - - const newLeaf = await zkEVMDB.getCurrentAccountState(address); - expect(newLeaf.balance.toString()).to.equal(account.balance.toString()); - expect(newLeaf.nonce.toString()).to.equal(account.nonce.toString()); - - const smtNewLeaf = await zkEVMDB.getCurrentAccountState(address); - expect(smtNewLeaf.balance.toString()).to.equal(account.balance.toString()); - expect(smtNewLeaf.nonce.toString()).to.equal(account.nonce.toString()); - - newLeafs[address].balance = account.balance.toString(); - newLeafs[address].nonce = account.nonce.toString(); - - const storage = await zkEVMDB.dumpStorage(address); - const hashBytecode = await zkEVMDB.getHashBytecode(address); - const bytecodeLength = await zkEVMDB.getLength(address); - newLeafs[address].storage = storage; - newLeafs[address].hashBytecode = hashBytecode; - newLeafs[address].bytecodeLength = bytecodeLength; - } - - for (const leaf of genesis) { - if (!newLeafs[leaf.address.toLowerCase()]) { - newLeafs[leaf.address] = { ...leaf }; - delete newLeafs[leaf.address].address; - delete newLeafs[leaf.address].bytecode; - delete newLeafs[leaf.address].contractName; - } - } - - if (!update) { - for (const [address, leaf] of Object.entries(batches[m].expectedNewLeafs)) { - expect(lodash.isEqual(leaf, newLeafs[address])).to.be.equal(true); - } - } else { - testVectorsRecursive[0].batches[m].expectedNewLeafs = newLeafs; - } - } - - // checks after consolidate zkEVMDB - if (!update) { - expect(smtUtils.h4toString(zkEVMDB.getCurrentStateRoot())).to.be.equal(newStateRoot); - expect(smtUtils.h4toString(zkEVMDB.getCurrentLocalExitRoot())).to.be.equal(newLocalExitRoot); - expect(smtUtils.h4toString(zkEVMDB.getCurrentBatchAccInputHash())).to.be.equal(newBatchAccInputHash); - expect(zkEVMDB.getCurrentNumBatch()).to.be.equal(newNumBatch); - } else { - testVectorsRecursive[0].newStateRoot = smtUtils.h4toString(zkEVMDB.getCurrentStateRoot()); - testVectorsRecursive[0].newLocalExitRoot = smtUtils.h4toString(zkEVMDB.getCurrentLocalExitRoot()); - testVectorsRecursive[0].newBatchAccInputHash = smtUtils.h4toString(zkEVMDB.getCurrentBatchAccInputHash()); - testVectorsRecursive[0].newNumBatch = zkEVMDB.getCurrentNumBatch(); - } - - // checks sequence multiple batches - const initBatch = 1; - const finalBatch = 2; - const seqBatches = await zkEVMDB.sequenceMultipleBatches(initBatch, finalBatch); - - for (let i = 0; i < (finalBatch - initBatch); i++) { - expect(seqBatches[i].transactions).to.equal(batches[i].batchL2Data); - } - - // checks snark input for multiple batches - const verifyBatches = await zkEVMDB.verifyMultipleBatches(initBatch, finalBatch, aggregatorAddress); - - if (update) { - testVectorsRecursive[0].inputSnark = verifyBatches.inputSnark; - } else { - expect(inputSnark).to.be.equal(verifyBatches.inputSnark); - } - - if (update) { - await fs.writeFileSync(pathZkevmDbTestRecursive, JSON.stringify(testVectorsRecursive, null, 2)); - } - }); });