diff --git a/deploy/OneStepProverHostIoCreator.js b/deploy/OneStepProverHostIoCreator.js index 8174c09c..f3df423d 100644 --- a/deploy/OneStepProverHostIoCreator.js +++ b/deploy/OneStepProverHostIoCreator.js @@ -5,9 +5,12 @@ module.exports = async hre => { await deploy('OneStepProverHostIo', { from: deployer, - args: [ethers.constants.AddressZero], + args: [ + ethers.constants.AddressZero, + (await deployments.get('HashProofHelper')).address, + ], }) } module.exports.tags = ['OneStepProverHostIo'] -module.exports.dependencies = [] +module.exports.dependencies = ['HashProofHelper'] diff --git a/src/osp/OneStepProofEntry.sol b/src/osp/OneStepProofEntry.sol index 19253698..561c2aec 100644 --- a/src/osp/OneStepProofEntry.sol +++ b/src/osp/OneStepProofEntry.sol @@ -106,22 +106,28 @@ contract OneStepProofEntry is IOneStepProofEntry { (globalState, offset) = Deserialize.globalState(proof, offset); require(globalState.hash() == mach.globalStateHash, "BAD_GLOBAL_STATE"); - MELState memory melState; - (melState, offset) = Deserialize.melState(proof, offset); - require(melState.hash() == globalState.getMELStateHash(), "BAD_MEL_STATE"); - - // The machine has finished processing a message and we're at the start of the next execution segment (machineStep == 0). - // If the MELState is not at its target (meaning that it hasn't finished extracting messages, which should only happen before the extraction process is started), - // or if all messages were extracted, but there are still messages to be executed in MEL, we kickstart the machine. - if ( - mach.status == MachineStatus.FINISHED && machineStep == 0 - && ( - melState.parentChainBlockHash != execCtx.targetParentChainBlockHash - || globalState.getMELExecutedMsgCount() < melState.msgCount - ) - ) { - // Kickstart the machine - return getStartMachineHash(mach.globalStateHash, execCtx.initialWasmModuleRoot); + // Only MEL-enhanced proofs carry a MELState. For non-MEL halted + // machines (MELStateHash == 0) the prover serializes the global + // state and reads no further, so we must not attempt to read a + // MELState here either. + if (globalState.getMELStateHash() != bytes32(0)) { + MELState memory melState; + (melState, offset) = Deserialize.melState(proof, offset); + require(melState.hash() == globalState.getMELStateHash(), "BAD_MEL_STATE"); + + // The machine has finished processing a message and we're at the start of the next execution segment (machineStep == 0). + // If the MELState is not at its target (meaning that it hasn't finished extracting messages, which should only happen before the extraction process is started), + // or if all messages were extracted, but there are still messages to be executed in MEL, we kickstart the machine. + if ( + mach.status == MachineStatus.FINISHED && machineStep == 0 + && ( + melState.parentChainBlockHash != execCtx.targetParentChainBlockHash + || globalState.getMELExecutedMsgCount() < melState.msgCount + ) + ) { + // Kickstart the machine + return getStartMachineHash(mach.globalStateHash, execCtx.initialWasmModuleRoot); + } } return mach.hash(); } diff --git a/test/prover/one-step-proof.ts b/test/prover/one-step-proof.ts index 3ff5238d..14911e2d 100644 --- a/test/prover/one-step-proof.ts +++ b/test/prover/one-step-proof.ts @@ -74,12 +74,6 @@ describe('OneStepProof', function () { await deployments.get('OneStepProofEntry') ).address ) - const bridge = await ethers.getContractAt( - 'BridgeStub', - ( - await deployments.get('BridgeStub') - ).address - ) const promises = [] const isdone = [] @@ -89,10 +83,9 @@ describe('OneStepProof', function () { ) const proof = proofs[i] isdone.push(false) - const inboxLimit = 1000000 const promise = osp .proveOneStep( - [inboxLimit, bridge.address], + [ethers.constants.HashZero, ethers.constants.HashZero], i, [...Buffer.from(proof.before, 'hex')], [...Buffer.from(proof.proof, 'hex')]