From 46e63e0956e42c63ae5c222964d0a9998dfbe23a Mon Sep 17 00:00:00 2001 From: Mathieu Hofman <86499+mhofman@users.noreply.github.com> Date: Wed, 11 Oct 2023 22:40:20 -0300 Subject: [PATCH] feat(cosmic-swingset): add begin block check and transaction (#8432) * feat(cosmic-swingset): add being block check and transaction * fixup! feat(cosmic-swingset): add being block check and transaction --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- packages/cosmic-swingset/src/launch-chain.js | 31 +++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/packages/cosmic-swingset/src/launch-chain.js b/packages/cosmic-swingset/src/launch-chain.js index f7e1531525f4..bc10c58c7cfe 100644 --- a/packages/cosmic-swingset/src/launch-chain.js +++ b/packages/cosmic-swingset/src/launch-chain.js @@ -427,6 +427,9 @@ export async function launch({ } let savedHeight = Number(kvStore.get(getHostKey('height')) || 0); + let savedBeginHeight = Number( + kvStore.get(getHostKey('beginHeight')) || savedHeight, + ); let runTime = 0; let chainTime; let saveTime = 0; @@ -658,6 +661,11 @@ export async function launch({ throw decohered; } + function saveBeginHeight(blockHeight) { + savedBeginHeight = blockHeight; + kvStore.set(getHostKey('beginHeight'), `${savedBeginHeight}`); + } + async function afterCommit(blockHeight, blockTime) { await waitUntilQuiescent() .then(afterCommitCallback) @@ -688,7 +696,7 @@ export async function launch({ // This only runs for the very first block on the chain. if (isBootstrap) { verboseBlocks && blockManagerConsole.info('block bootstrap'); - savedHeight === 0 || + (savedHeight === 0 && savedBeginHeight === 0) || Fail`Cannot run a bootstrap block at height ${savedHeight}`; const blockHeight = 0; const runNum = 0; @@ -701,6 +709,9 @@ export async function launch({ blockHeight, runNum, }); + // Start a block transaction, but without changing state + // for the upcoming begin block check + saveBeginHeight(savedBeginHeight); await processAction(action.type, async () => bootstrapBlock(blockHeight, blockTime), ); @@ -790,6 +801,17 @@ export async function launch({ blockManagerConsole.info('block', blockHeight, 'begin'); runTime = 0; + if (blockNeedsExecution(blockHeight)) { + if (savedBeginHeight === blockHeight) { + decohered = Error( + `Inconsistent committed state. Block ${blockHeight} had already began execution`, + ); + throw decohered; + } + // Start a block transaction, recording which block height is executed + saveBeginHeight(blockHeight); + } + controller.writeSlogObject({ type: 'cosmic-swingset-begin-block', blockHeight, @@ -827,6 +849,13 @@ export async function launch({ throw e; } } else { + if (blockHeight !== savedBeginHeight) { + decohered = Error( + `Inconsistent committed state. Trying to end block ${blockHeight}, expected began block ${savedBeginHeight}`, + ); + throw decohered; + } + // And now we actually process the queued actions down here, during // END_BLOCK, but still reentrancy-protected.