Skip to content

Commit

Permalink
fix(cosmic-swingset): use BOOTSTRAP_BLOCK to avoid slog confusion
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelfig committed Jul 20, 2021
1 parent fbc512d commit 9c8725b
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 48 deletions.
28 changes: 24 additions & 4 deletions golang/cosmos/x/swingset/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package swingset

import (
// "fmt"
"encoding/json"
stdlog "log"

"github.com/Agoric/agoric-sdk/golang/cosmos/vm"
"github.com/Agoric/agoric-sdk/golang/cosmos/x/swingset/types"
sdk "github.com/cosmos/cosmos-sdk/types"
abci "github.com/tendermint/tendermint/abci/types"
Expand All @@ -24,6 +26,12 @@ func DefaultGenesisState() *types.GenesisState {
return gs
}

type bootstrapBlockAction struct {
Type string `json:"type"`
BlockTime int64 `json:"blockTime"`
StoragePort int `json:"storagePort"`
}

func InitGenesis(ctx sdk.Context, keeper Keeper, data *types.GenesisState) []abci.ValidatorUpdate {
var storage types.Storage
for key, value := range data.Storage {
Expand All @@ -34,13 +42,25 @@ func InitGenesis(ctx sdk.Context, keeper Keeper, data *types.GenesisState) []abc
// Just run the SwingSet kernel to finish bootstrap and get ready to open for
// business.
stdlog.Println("Running SwingSet until bootstrap is ready")
bootstrapBlock := abci.RequestEndBlock{Height: ctx.BlockHeight()}
valUpdate, err := EndBlock(ctx, bootstrapBlock, keeper)
action := &bootstrapBlockAction{
Type: "BOOTSTRAP_BLOCK",
BlockTime: ctx.BlockTime().Unix(),
StoragePort: vm.GetPort("storage"),
}
b, err := json.Marshal(action)
if err != nil {
// Errors here are fatal.
panic(err)
}
return valUpdate

_, err = keeper.CallToController(ctx, string(b))

if err != nil {
// NOTE: A failed BOOTSTRAP_BLOCK means that the SwingSet state is inconsistent.
// Panic here, in the hopes that a replay from scratch will fix the problem.
panic(err)
}

return []abci.ValidatorUpdate{}
}

func ExportGenesis(ctx sdk.Context, k Keeper) *types.GenesisState {
Expand Down
1 change: 0 additions & 1 deletion packages/agoric-cli/lib/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,6 @@ export default async function startMain(progname, rawArgs, powers, opts) {
]);
const newGenesisJson = finishCosmosGenesis({
genesisJson,
bootstrapAddress: addrs.provision,
});
const newConfigToml = finishTendermintConfig({
configToml,
Expand Down
37 changes: 19 additions & 18 deletions packages/cosmic-swingset/src/block-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { assert, details as X } from '@agoric/assert';

const console = anylogger('block-manager');

const BOOTSTRAP_BLOCK = 'BOOTSTRAP_BLOCK';
const BEGIN_BLOCK = 'BEGIN_BLOCK';
const DELIVER_INBOUND = 'DELIVER_INBOUND';
const END_BLOCK = 'END_BLOCK';
Expand All @@ -15,17 +16,17 @@ const VBANK_BALANCE_UPDATE = 'VBANK_BALANCE_UPDATE';
export default function makeBlockManager({
deliverInbound,
doBridgeInbound,
bootstrapBlock,
beginBlock,
endBlock,
flushChainSends,
saveChainState,
saveOutsideState,
savedActions,
savedHeight,
bootstrapBlock,
verboseBlocks = false,
}) {
let computedHeight = bootstrapBlock ? undefined : savedHeight;
let computedHeight = savedHeight;
let runTime = 0;
let chainTime;

Expand Down Expand Up @@ -99,12 +100,21 @@ export default function makeBlockManager({

// console.warn('FIGME: blockHeight', action.blockHeight, 'received', action.type)
switch (action.type) {
case BOOTSTRAP_BLOCK: {
// This only runs for the very first block on the chain.
verboseBlocks && console.info('block bootstrap');
if (computedHeight !== 0) {
throw Error(
`Cannot run a bootstrap block at height ${action.blockHeight}`,
);
}
await bootstrapBlock(action.blockTime);
break;
}

case COMMIT_BLOCK: {
verboseBlocks && console.info('block', action.blockHeight, 'commit');
if (
computedHeight !== undefined &&
action.blockHeight !== computedHeight
) {
if (action.blockHeight !== computedHeight) {
throw Error(
`Committed height ${action.blockHeight} does not match computed height ${computedHeight}`,
);
Expand Down Expand Up @@ -150,15 +160,12 @@ export default function makeBlockManager({
currentActions.push(action);

// eslint-disable-next-line no-use-before-define
if (!deepEquals(currentActions, savedActions)) {
if (computedHeight > 0 && !deepEquals(currentActions, savedActions)) {
// We only handle the trivial case.
const restoreHeight = action.blockHeight - 1;
// We can reset from -1 or 0 to anything, since that's what happens
// when genesis.initial_height !== "1".
if (
computedHeight !== undefined &&
restoreHeight !== computedHeight
) {
if (restoreHeight !== computedHeight) {
// Keep throwing forever.
decohered = Error(
// TODO unimplemented
Expand Down Expand Up @@ -200,13 +207,7 @@ export default function makeBlockManager({

// Advance our saved state variables.
savedActions = currentActions;
if (computedHeight === undefined && action.blockHeight > 1) {
// Genesis height is the same as the first block, so we
// need to adjust.
computedHeight = action.blockHeight - 1;
} else {
computedHeight = action.blockHeight;
}
computedHeight = action.blockHeight;
}

currentActions = [];
Expand Down
31 changes: 18 additions & 13 deletions packages/cosmic-swingset/src/launch-chain.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ async function buildSwingset(
);

// We DON'T want to run the kernel yet, only when the application decides
// (either on bootstrap block (-1) or in endBlock).
// (either on bootstrap block (0) or in endBlock).

return { controller, mb, bridgeInbound, timer };
}
Expand Down Expand Up @@ -175,21 +175,27 @@ export async function launch(
schedulerBlockTimeHistogram.record((now - blockStart) / 1000);
}

let bootstrapBlock;
async function bootstrapBlock(blockTime) {
controller.writeSlogObject({
type: 'cosmic-swingset-bootstrap-block-start',
blockTime,
});
// This is before the initial block, we need to finish processing the
// entire bootstrap before opening for business.
await crankScheduler(Infinity);
controller.writeSlogObject({
type: 'cosmic-swingset-bootstrap-block-end',
blockTime,
});
}

async function endBlock(blockHeight, blockTime) {
controller.writeSlogObject({
type: 'cosmic-swingset-end-block-start',
blockHeight,
blockTime,
});
let numCranks = FIXME_MAX_CRANKS_PER_BLOCK;
if (bootstrapBlock) {
// This is the initial block, we need to finish processing the entire
// bootstrap before opening for business.
numCranks = Infinity;
bootstrapBlock = false;
}
await crankScheduler(numCranks);
await crankScheduler(FIXME_MAX_CRANKS_PER_BLOCK);
controller.writeSlogObject({
type: 'cosmic-swingset-end-block-finish',
blockHeight,
Expand Down Expand Up @@ -248,20 +254,19 @@ export async function launch(
}

const [savedHeight, savedActions, savedChainSends] = JSON.parse(
kvStore.get(SWING_STORE_META_KEY) || '[-1, [], []]',
kvStore.get(SWING_STORE_META_KEY) || '[0, [], []]',
);
bootstrapBlock = savedHeight < 0;

return {
deliverInbound,
doBridgeInbound,
// bridgeOutbound,
bootstrapBlock,
beginBlock,
endBlock,
saveChainState,
saveOutsideState,
savedHeight,
bootstrapBlock,
savedActions,
savedChainSends,
};
Expand Down
21 changes: 9 additions & 12 deletions packages/cosmic-swingset/src/sim-chain.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ async function makeMapStorage(file) {
}

export async function connectToFakeChain(basedir, GCI, delay, inbound) {
const initialHeight = 1;
const initialHeight = 0;
const mailboxFile = path.join(basedir, `fake-chain-${GCI}-mailbox.json`);
const bootAddress = `${GCI}-client`;

Expand All @@ -58,9 +58,7 @@ export async function connectToFakeChain(basedir, GCI, delay, inbound) {
hardcodedClientAddresses: [bootAddress],
noFakeCurrencies: process.env.NO_FAKE_CURRENCIES,
bootMsg: {
bootstrapAddress: 'agoric1simboot',
bootstrapValue: `${50000n * 10n ** 6n}`,
donationValue: `${5n * 10n ** 6n}`,
supplyCoins: [{ denom: 'ubld', amount: `${50000n * 10n ** 6n}` }],
},
};
const stateDBdir = path.join(basedir, `fake-chain-${GCI}-state`);
Expand Down Expand Up @@ -149,7 +147,8 @@ export async function connectToFakeChain(basedir, GCI, delay, inbound) {
);

const simulateBlock = () =>
unhandledSimulateBlock().catch(_ => {
unhandledSimulateBlock().catch(e => {
console.error(e);
process.exit(1);
});

Expand All @@ -166,16 +165,14 @@ export async function connectToFakeChain(basedir, GCI, delay, inbound) {
}

let genesisBlockP;
if (blockHeight < 0) {
if (!blockHeight) {
// The before-first-block is special... do it now.
// This emulates what x/swingset does to run an END_BLOCK
// with block 1 and genesis transactions before continuing with the real
// block 1.
blockHeight = initialHeight;
// This emulates what x/swingset does to run a BOOTSTRAP_BLOCK
// before continuing with the real initialHeight.
genesisBlockP = blockManager(
{ type: 'END_BLOCK', blockHeight, blockTime },
{ type: 'BOOTSTRAP_BLOCK', blockTime },
savedChainSends,
);
).then(() => (blockHeight = initialHeight));
}
await genesisBlockP;

Expand Down

0 comments on commit 9c8725b

Please sign in to comment.