diff --git a/core/kernel.go b/core/kernel.go index 7abbaeeb2..dd04ecefd 100644 --- a/core/kernel.go +++ b/core/kernel.go @@ -109,7 +109,7 @@ func NewKernel(ctx context.Context, keyClient keys.KeyClient, privValidator tmTy // These should be in sync unless we are at the genesis block if kern.Blockchain.LastBlockHeight() > 0 { kern.Logger.InfoMsg("Loading application state") - kern.State, err = execution.LoadState(stateDB, int64(kern.Blockchain.LastBlockHeight())) + kern.State, err = execution.LoadState(stateDB, int64(kern.Blockchain.LastBlockHeight()+execution.VersionOffset)) if err != nil { return nil, fmt.Errorf("could not load persisted execution state at hash 0x%X: %v", kern.Blockchain.AppHashAfterLastBlock(), err) diff --git a/execution/execution.go b/execution/execution.go index c42038451..fbe55e350 100644 --- a/execution/execution.go +++ b/execution/execution.go @@ -343,8 +343,9 @@ func (exe *executor) Commit(blockHash []byte, blockTime time.Time, header *abciT "total_validator_power", exe.blockchain.CurrentValidators().TotalPower(), "total_validator_power_change", totalPowerChange, "total_validator_flow", totalFlow) - if uint64(version) != exe.blockchain.LastBlockHeight() { - return nil, fmt.Errorf("state tree version %d does not equal blockchain height %d but their equality "+ + // TODO: revert this to straight equality by removing the initial write on MakeGenesisState + if uint64(version) != exe.blockchain.LastBlockHeight()+VersionOffset { + return nil, fmt.Errorf("state tree version %d does not equal blockchain height %d + 1 but that "+ "is meant to be a guaranteed invariant", version, exe.blockchain.LastBlockHeight()) } diff --git a/execution/execution_test.go b/execution/execution_test.go index c00efd9b6..bd4af0c22 100644 --- a/execution/execution_test.go +++ b/execution/execution_test.go @@ -1560,7 +1560,7 @@ type testExecutor struct { func makeExecutor(state *State) *testExecutor { blockchain := newBlockchain(testGenesisDoc) - blockchain.CommitBlockAtHeight(time.Now(), []byte("hashily"), state.Hash(), uint64(state.Version())) + blockchain.CommitBlockAtHeight(time.Now(), []byte("hashily"), state.Hash(), uint64(state.Version())-VersionOffset) return &testExecutor{ executor: newExecutor("makeExecutorCache", true, state, blockchain, event.NewNoOpPublisher(), logger), diff --git a/execution/state.go b/execution/state.go index ff6379ee8..35cd412a4 100644 --- a/execution/state.go +++ b/execution/state.go @@ -38,8 +38,9 @@ import ( ) const ( - defaultCacheCapacity = 1024 - uint64Length = 8 + VersionOffset uint64 = 1 + defaultCacheCapacity = 1024 + uint64Length = 8 // Prefix under which the versioned merkle state tree resides - tracking previous versions of history treePrefix = "m" @@ -164,6 +165,12 @@ func MakeGenesisState(db dbm.DB, genesisDoc *genesis.GenesisDoc) (*State, error) return nil, err } + // TODO: remove this in order to synchronise version and height + // We need to save at least once so that readTree points at a non-working-state tree + _, _, err = s.writeState.commit() + if err != nil { + return nil, err + } return s, nil }