diff --git a/store/store.go b/store/store.go index 2d7c356e8..8f67fd0c9 100644 --- a/store/store.go +++ b/store/store.go @@ -477,13 +477,18 @@ func (bs *BlockStore) SaveBlock(block *types.Block, blockParts *types.PartSet, s } // Save seen commit (seen +2/3 precommits for block) - // NOTE: we can delete this at a later height pbsc := seenCommit.ToProto() seenCommitBytes := mustEncode(pbsc) if err := batch.Set(seenCommitKey(height), seenCommitBytes); err != nil { panic(err) } + // remove the previous seen commit that we have just replaced with the + // canonical commit + if err := batch.Delete(seenCommitKey(height - 1)); err != nil { + panic(err) + } + if err := batch.WriteSync(); err != nil { panic(err) } diff --git a/store/store_test.go b/store/store_test.go index 58b841335..ba70cd97d 100644 --- a/store/store_test.go +++ b/store/store_test.go @@ -35,8 +35,14 @@ func makeTestCommit(height int64, timestamp time.Time) *types.Commit { Timestamp: timestamp, Signature: []byte("Signature"), }} - return types.NewCommit(height, 0, - types.BlockID{Hash: []byte(""), PartSetHeader: types.PartSetHeader{Hash: []byte(""), Total: 2}}, commitSigs) + return types.NewCommit( + height, + 0, + types.BlockID{ + Hash: crypto.CRandBytes(32), + PartSetHeader: types.PartSetHeader{Hash: crypto.CRandBytes(32), Total: 2}, + }, + commitSigs) } func makeTxs(height int64) (txs []types.Tx) { @@ -504,6 +510,45 @@ func TestBlockFetchAtHeight(t *testing.T) { require.Nil(t, blockAtHeightPlus2, "expecting an unsuccessful load of Height()+2") } +func TestSeenAndCanonicalCommit(t *testing.T) { + bs, _ := freshBlockStore() + height := int64(2) + loadCommit := func() (interface{}, error) { + meta := bs.LoadSeenCommit(height) + return meta, nil + } + + // Initially no contents. + // 1. Requesting for a non-existent blockMeta shouldn't fail + res, _, panicErr := doFn(loadCommit) + require.Nil(t, panicErr, "a non-existent blockMeta shouldn't cause a panic") + require.Nil(t, res, "a non-existent blockMeta should return nil") + + // produce a few blocks and check that the correct seen and cannoncial commits + // are persisted. + for h := int64(3); h <= 5; h++ { + c1 := bs.LoadSeenCommit(h) + require.Nil(t, c1) + c2 := bs.LoadBlockCommit(h - 1) + require.Nil(t, c2) + blockCommit := makeTestCommit(h-1, tmtime.Now()) + block := makeBlock(h, state, blockCommit) + partSet := block.MakePartSet(2) + seenCommit := makeTestCommit(h, tmtime.Now()) + bs.SaveBlock(block, partSet, seenCommit) + c3 := bs.LoadSeenCommit(h) + require.Equal(t, seenCommit.Hash(), c3.Hash()) + // the previous seen commit should be removed + c4 := bs.LoadSeenCommit(h - 1) + require.Nil(t, c4) + c5 := bs.LoadBlockCommit(h) + require.Nil(t, c5) + c6 := bs.LoadBlockCommit(h - 1) + require.Equal(t, blockCommit.Hash(), c6.Hash()) + } + +} + func doFn(fn func() (interface{}, error)) (res interface{}, err error, panicErr error) { defer func() { if r := recover(); r != nil {