Skip to content

Commit

Permalink
fix(dot/state, lib/grandpa): update justification and SignedVote hand…
Browse files Browse the repository at this point in the history
…ling in database (ChainSafe#1682)
  • Loading branch information
noot authored and timwu20 committed Dec 6, 2021
1 parent 13380af commit 9dda6b5
Show file tree
Hide file tree
Showing 44 changed files with 669 additions and 525 deletions.
6 changes: 3 additions & 3 deletions dot/core/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ type BlockState interface {
GetBlockByHash(common.Hash) (*types.Block, error)
GenesisHash() common.Hash
GetSlotForBlock(common.Hash) (uint64, error)
GetFinalizedHeader(uint64, uint64) (*types.Header, error)
GetFinalizedHash(uint64, uint64) (common.Hash, error)
SetFinalizedHash(common.Hash, uint64, uint64) error
GetFinalisedHeader(uint64, uint64) (*types.Header, error)
GetFinalisedHash(uint64, uint64) (common.Hash, error)
SetFinalisedHash(common.Hash, uint64, uint64) error
RegisterImportedChannel(ch chan<- *types.Block) (byte, error)
UnregisterImportedChannel(id byte)
RegisterFinalizedChannel(ch chan<- *types.FinalisationInfo) (byte, error)
Expand Down
6 changes: 3 additions & 3 deletions dot/digest/digest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,13 @@ func TestHandler_GrandpaScheduledChange(t *testing.T) {

headers := addTestBlocksToState(t, 2, handler.blockState)
for i, h := range headers {
handler.blockState.(*state.BlockState).SetFinalizedHash(h.Hash(), uint64(i), 0)
handler.blockState.(*state.BlockState).SetFinalisedHash(h.Hash(), uint64(i), 0)
}

// authorities should change on start of block 3 from start
headers = addTestBlocksToState(t, 1, handler.blockState)
for _, h := range headers {
handler.blockState.(*state.BlockState).SetFinalizedHash(h.Hash(), 3, 0)
handler.blockState.(*state.BlockState).SetFinalisedHash(h.Hash(), 3, 0)
}

time.Sleep(time.Millisecond * 500)
Expand Down Expand Up @@ -232,7 +232,7 @@ func TestHandler_GrandpaPauseAndResume(t *testing.T) {

headers := addTestBlocksToState(t, 3, handler.blockState)
for i, h := range headers {
handler.blockState.(*state.BlockState).SetFinalizedHash(h.Hash(), uint64(i), 0)
handler.blockState.(*state.BlockState).SetFinalisedHash(h.Hash(), uint64(i), 0)
}

time.Sleep(time.Millisecond * 100)
Expand Down
4 changes: 2 additions & 2 deletions dot/network/mock_block_state.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dot/network/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ func (s *Service) sentBlockIntervalTelemetry() {
}
bestHash := best.Hash()

finalized, err := s.blockState.GetFinalizedHeader(0, 0) //nolint
finalized, err := s.blockState.GetFinalisedHeader(0, 0) //nolint
if err != nil {
continue
}
Expand Down
2 changes: 1 addition & 1 deletion dot/network/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type BlockState interface {
BestBlockNumber() (*big.Int, error)
GenesisHash() common.Hash
HasBlockBody(common.Hash) (bool, error)
GetFinalizedHeader(round, setID uint64) (*types.Header, error)
GetFinalisedHeader(round, setID uint64) (*types.Header, error)
GetHashByNumber(num *big.Int) (common.Hash, error)
}

Expand Down
6 changes: 3 additions & 3 deletions dot/network/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ func (q *syncQueue) benchmark() {
}

if before.Number.Int64() >= q.goal {
finalised, err := q.s.blockState.GetFinalizedHeader(0, 0) //nolint
finalised, err := q.s.blockState.GetFinalisedHeader(0, 0) //nolint
if err != nil {
continue
}
Expand Down Expand Up @@ -742,7 +742,7 @@ func (q *syncQueue) handleBlockJustification(data []*types.BlockData) {
}

func (q *syncQueue) handleBlockData(data []*types.BlockData) {
finalised, err := q.s.blockState.GetFinalizedHeader(0, 0)
finalised, err := q.s.blockState.GetFinalisedHeader(0, 0)
if err != nil {
panic(err) // this should never happen
}
Expand Down Expand Up @@ -790,7 +790,7 @@ func (q *syncQueue) handleBlockDataFailure(idx int, err error, data []*types.Blo
logger.Warn("failed to handle block data", "failed on block", q.currStart+int64(idx), "error", err)

if errors.Is(err, chaindb.ErrKeyNotFound) || errors.Is(err, blocktree.ErrParentNotFound) {
finalised, err := q.s.blockState.GetFinalizedHeader(0, 0)
finalised, err := q.s.blockState.GetFinalisedHeader(0, 0)
if err != nil {
panic(err)
}
Expand Down
2 changes: 1 addition & 1 deletion dot/network/test_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func NewMockBlockState(n *big.Int) *MockBlockState {
m.On("GenesisHash").Return(common.NewHash([]byte{}))
m.On("BestBlockNumber").Return(big.NewInt(1), nil)
m.On("HasBlockBody", mock.AnythingOfType("common.Hash")).Return(false, nil)
m.On("GetFinalizedHeader", mock.AnythingOfType("uint64"), mock.AnythingOfType("uint64")).Return(header, nil)
m.On("GetFinalisedHeader", mock.AnythingOfType("uint64"), mock.AnythingOfType("uint64")).Return(header, nil)
m.On("GetHashByNumber", mock.AnythingOfType("*big.Int")).Return(common.Hash{}, nil)

return m
Expand Down
2 changes: 1 addition & 1 deletion dot/rpc/modules/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ type BlockAPI interface {
BestBlockHash() common.Hash
GetBlockByHash(hash common.Hash) (*types.Block, error)
GetBlockHash(blockNumber *big.Int) (*common.Hash, error)
GetFinalizedHash(uint64, uint64) (common.Hash, error)
GetFinalisedHash(uint64, uint64) (common.Hash, error)
HasJustification(hash common.Hash) (bool, error)
GetJustification(hash common.Hash) ([]byte, error)
RegisterImportedChannel(ch chan<- *types.Block) (byte, error)
Expand Down
2 changes: 1 addition & 1 deletion dot/rpc/modules/api_mocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func NewMockBlockAPI() *modulesmocks.MockBlockAPI {
m.On("BestBlockHash").Return(common.Hash{})
m.On("GetBlockByHash", mock.AnythingOfType("common.Hash")).Return(nil, nil)
m.On("GetBlockHash", mock.AnythingOfType("*big.Int")).Return(nil, nil)
m.On("GetFinalizedHash", mock.AnythingOfType("uint64"), mock.AnythingOfType("uint64")).Return(common.Hash{}, nil)
m.On("GetFinalisedHash", mock.AnythingOfType("uint64"), mock.AnythingOfType("uint64")).Return(common.Hash{}, nil)
m.On("RegisterImportedChannel", mock.AnythingOfType("chan<- *types.Block")).Return(byte(0), nil)
m.On("UnregisterImportedChannel", mock.AnythingOfType("uint8"))
m.On("RegisterFinalizedChannel", mock.AnythingOfType("chan<- *types.FinalisationInfo")).Return(byte(0), nil)
Expand Down
4 changes: 2 additions & 2 deletions dot/rpc/modules/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ func (cm *ChainModule) GetHead(r *http.Request, req *ChainBlockNumberRequest, re

// GetFinalizedHead returns the most recently finalised block hash
func (cm *ChainModule) GetFinalizedHead(r *http.Request, req *EmptyRequest, res *ChainHashResponse) error {
h, err := cm.blockAPI.GetFinalizedHash(0, 0)
h, err := cm.blockAPI.GetFinalisedHash(0, 0)
if err != nil {
return err
}
Expand All @@ -146,7 +146,7 @@ func (cm *ChainModule) GetFinalizedHead(r *http.Request, req *EmptyRequest, res

// GetFinalizedHeadByRound returns the hash of the block finalised at the given round and setID
func (cm *ChainModule) GetFinalizedHeadByRound(r *http.Request, req *ChainFinalizedHeadRequest, res *ChainHashResponse) error {
h, err := cm.blockAPI.GetFinalizedHash(req.Round, req.SetID)
h, err := cm.blockAPI.GetFinalisedHash(req.Round, req.SetID)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion dot/rpc/modules/chain_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ func TestChainGetFinalizedHeadByRound(t *testing.T) {
require.NoError(t, err)

testhash := header.Hash()
err = state.Block.SetFinalizedHash(testhash, 77, 1)
err = state.Block.SetFinalisedHash(testhash, 77, 1)
require.NoError(t, err)

req = ChainFinalizedHeadRequest{77, 1}
Expand Down
4 changes: 2 additions & 2 deletions dot/rpc/modules/mocks/block_api.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

140 changes: 2 additions & 138 deletions dot/state/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func NewBlockState(db chaindb.Database, bt *blocktree.BlockTree) (*BlockState, e
}

bs.genesisHash = genesisBlock.Header.Hash()
bs.lastFinalised, err = bs.GetFinalizedHash(0, 0)
bs.lastFinalised, err = bs.GetFinalisedHash(0, 0)
if err != nil {
return nil, fmt.Errorf("failed to get last finalised hash: %w", err)
}
Expand Down Expand Up @@ -117,12 +117,7 @@ func NewBlockStateFromGenesis(db chaindb.Database, header *types.Header) (*Block
bs.genesisHash = header.Hash()

// set the latest finalised head to the genesis header
err = bs.SetFinalizedHash(bs.genesisHash, 0, 0)
if err != nil {
return nil, err
}

err = bs.SetRound(0)
err = bs.SetFinalisedHash(bs.genesisHash, 0, 0)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -168,16 +163,6 @@ func arrivalTimeKey(hash common.Hash) []byte {
return append(arrivalTimePrefix, hash.ToBytes()...)
}

// finalizedHashKey = hashkey + round + setID (LE encoded)
func finalizedHashKey(round, setID uint64) []byte {
buf := make([]byte, 8)
binary.LittleEndian.PutUint64(buf, round)
key := append(common.FinalizedBlockHashKey, buf...)
buf2 := make([]byte, 8)
binary.LittleEndian.PutUint64(buf2, setID)
return append(key, buf2...)
}

// GenesisHash returns the hash of the genesis block
func (bs *BlockState) GenesisHash() common.Hash {
return bs.genesisHash
Expand Down Expand Up @@ -373,127 +358,6 @@ func (bs *BlockState) SetBlockBody(hash common.Hash, body *types.Body) error {
return bs.db.Put(blockBodyKey(hash), body.AsOptional().Value())
}

// HasFinalizedBlock returns true if there is a finalised block for a given round and setID, false otherwise
func (bs *BlockState) HasFinalizedBlock(round, setID uint64) (bool, error) {
return bs.db.Has(finalizedHashKey(round, setID))
}

// NumberIsFinalised checks if a block number is finalised or not
func (bs *BlockState) NumberIsFinalised(num *big.Int) (bool, error) {
header, err := bs.GetFinalizedHeader(0, 0)
if err != nil {
return false, err
}

return num.Cmp(header.Number) <= 0, nil
}

// GetFinalizedHeader returns the latest finalised block header
func (bs *BlockState) GetFinalizedHeader(round, setID uint64) (*types.Header, error) {
h, err := bs.GetFinalizedHash(round, setID)
if err != nil {
return nil, err
}

header, err := bs.GetHeader(h)
if err != nil {
return nil, err
}

return header, nil
}

// GetFinalizedHash gets the latest finalised block header
func (bs *BlockState) GetFinalizedHash(round, setID uint64) (common.Hash, error) {
h, err := bs.db.Get(finalizedHashKey(round, setID))
if err != nil {
return common.Hash{}, err
}

return common.NewHash(h), nil
}

// SetFinalizedHash sets the latest finalised block header
func (bs *BlockState) SetFinalizedHash(hash common.Hash, round, setID uint64) error {
bs.Lock()
defer bs.Unlock()

has, _ := bs.HasHeader(hash)
if !has {
return fmt.Errorf("cannot finalise unknown block %s", hash)
}

// if nothing was previously finalised, set the first slot of the network to the
// slot number of block 1, which is now being set as final
if bs.lastFinalised.Equal(bs.genesisHash) && !hash.Equal(bs.genesisHash) {
err := bs.setFirstSlotOnFinalisation()
if err != nil {
return err
}
}

if round > 0 {
go bs.notifyFinalized(hash, round, setID)

err := bs.SetRound(round)
if err != nil {
return err
}
}

pruned := bs.bt.Prune(hash)
for _, rem := range pruned {
header, err := bs.GetHeader(rem)
if err != nil {
return err
}

err = bs.DeleteBlock(rem)
if err != nil {
return err
}

logger.Trace("pruned block", "hash", rem, "number", header.Number)
bs.pruneKeyCh <- header
}

bs.lastFinalised = hash
return bs.db.Put(finalizedHashKey(round, setID), hash[:])
}

func (bs *BlockState) setFirstSlotOnFinalisation() error {
header, err := bs.GetHeaderByNumber(big.NewInt(1))
if err != nil {
return err
}

slot, err := types.GetSlotFromHeader(header)
if err != nil {
return err
}

return bs.baseState.storeFirstSlot(slot)
}

// SetRound sets the latest finalised GRANDPA round in the db
// TODO: this needs to use both setID and round
func (bs *BlockState) SetRound(round uint64) error {
buf := make([]byte, 8)
binary.LittleEndian.PutUint64(buf, round)
return bs.db.Put(common.LatestFinalizedRoundKey, buf)
}

// GetRound gets the latest finalised GRANDPA round from the db
func (bs *BlockState) GetRound() (uint64, error) {
r, err := bs.db.Get(common.LatestFinalizedRoundKey)
if err != nil {
return 0, err
}

round := binary.LittleEndian.Uint64(r)
return round, nil
}

// CompareAndSetBlockData will compare empty fields and set all elements in a block data to db
func (bs *BlockState) CompareAndSetBlockData(bd *types.BlockData) error {
hasReceipt, _ := bs.HasReceipt(bd.Hash)
Expand Down
9 changes: 0 additions & 9 deletions dot/state/block_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ func (bs *BlockState) HasReceipt(hash common.Hash) (bool, error) {

// SetReceipt sets a Receipt in the database
func (bs *BlockState) SetReceipt(hash common.Hash, data []byte) error {
bs.Lock()
defer bs.Unlock()

err := bs.db.Put(prefixKey(hash, receiptPrefix), data)
if err != nil {
return err
Expand All @@ -60,9 +57,6 @@ func (bs *BlockState) HasMessageQueue(hash common.Hash) (bool, error) {

// SetMessageQueue sets a MessageQueue in the database
func (bs *BlockState) SetMessageQueue(hash common.Hash, data []byte) error {
bs.Lock()
defer bs.Unlock()

err := bs.db.Put(prefixKey(hash, messageQueuePrefix), data)
if err != nil {
return err
Expand All @@ -88,9 +82,6 @@ func (bs *BlockState) HasJustification(hash common.Hash) (bool, error) {

// SetJustification sets a Justification in the database
func (bs *BlockState) SetJustification(hash common.Hash, data []byte) error {
bs.Lock()
defer bs.Unlock()

err := bs.db.Put(prefixKey(hash, justificationPrefix), data)
if err != nil {
return err
Expand Down
Loading

0 comments on commit 9dda6b5

Please sign in to comment.