Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(dot/sync): Revert verify justification before importing blocks #3615

Merged
merged 6 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dot/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type ServiceRegisterer interface {

// BlockJustificationVerifier has a verification method for block justifications.
type BlockJustificationVerifier interface {
VerifyBlockJustification(common.Hash, []byte) (round uint64, setID uint64, err error)
VerifyBlockJustification(common.Hash, []byte) error
}

// Telemetry is the telemetry client to send telemetry messages.
Expand Down
15 changes: 0 additions & 15 deletions dot/state/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -492,21 +492,6 @@ func (bs *BlockState) AddBlockWithArrivalTime(block *types.Block, arrivalTime ti
return nil
}

// AddBlockToBlockTree adds the given block to the blocktree. It does not write it to the database.
// TODO: remove this func and usage from sync (after sync refactor?)
func (bs *BlockState) AddBlockToBlockTree(block *types.Block) error {
bs.Lock()
defer bs.Unlock()

arrivalTime, err := bs.GetArrivalTime(block.Header.Hash())
if err != nil {
arrivalTime = time.Now()
}

bs.unfinalisedBlocks.store(block)
return bs.bt.AddBlock(&block.Header, arrivalTime)
}

// GetAllBlocksAtNumber returns all unfinalised blocks with the given number
func (bs *BlockState) GetAllBlocksAtNumber(num uint) ([]common.Hash, error) {
header, err := bs.GetHeaderByNumber(num)
Expand Down
20 changes: 0 additions & 20 deletions dot/state/block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -635,26 +635,6 @@ func TestAddBlock_WithReOrg(t *testing.T) {
require.Equal(t, header3a.Hash(), block3hash)
}

func TestAddBlockToBlockTree(t *testing.T) {
bs := newTestBlockState(t, newTriesEmpty())

header := &types.Header{
Number: 1,
Digest: createPrimaryBABEDigest(t),
ParentHash: testGenesisHeader.Hash(),
}

err := bs.setArrivalTime(header.Hash(), time.Now())
require.NoError(t, err)

err = bs.AddBlockToBlockTree(&types.Block{
Header: *header,
Body: types.Body{},
})
require.NoError(t, err)
require.Equal(t, bs.BestBlockHash(), header.Hash())
}

func TestNumberIsFinalised(t *testing.T) {
tries := newTriesEmpty()

Expand Down
62 changes: 19 additions & 43 deletions dot/sync/chain_sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -816,33 +816,25 @@ func (cs *chainSync) handleReadyBlock(bd *types.BlockData, origin blockOrigin) e
// processBlockData processes the BlockData from a BlockResponse and
// returns the index of the last BlockData it handled on success,
// or the index of the block data that errored on failure.
// TODO: https://github.com/ChainSafe/gossamer/issues/3468
func (cs *chainSync) processBlockData(blockData types.BlockData, origin blockOrigin) error {
// while in bootstrap mode we don't need to broadcast block announcements
announceImportedBlock := cs.getSyncMode() == tip
var blockDataJustification []byte
if blockData.Justification != nil {
blockDataJustification = *blockData.Justification
}

if blockData.Header != nil {
round, setID, err := cs.verifyJustification(blockData.Header.Hash(), blockDataJustification)
if err != nil {
return err
}

if blockData.Body != nil {
err = cs.processBlockDataWithHeaderAndBody(blockData, origin, announceImportedBlock)
err := cs.processBlockDataWithHeaderAndBody(blockData, origin, announceImportedBlock)
if err != nil {
return fmt.Errorf("processing block data with header and body: %w", err)
}
}

err = cs.finalizeAndSetJustification(
blockData.Header,
round, setID,
blockDataJustification)
if err != nil {
return fmt.Errorf("while setting justification: %w", err)
if blockData.Justification != nil && len(*blockData.Justification) > 0 {
logger.Infof("handling justification for block %s (#%d)", blockData.Hash.Short(), blockData.Number())
err := cs.handleJustification(blockData.Header, *blockData.Justification)
if err != nil {
return fmt.Errorf("handling justification: %w", err)
}
}
}

Expand All @@ -854,16 +846,6 @@ func (cs *chainSync) processBlockData(blockData types.BlockData, origin blockOri
return nil
}

func (cs *chainSync) verifyJustification(headerHash common.Hash, justification []byte) (
round uint64, setID uint64, err error) {
if len(justification) > 0 {
round, setID, err = cs.finalityGadget.VerifyBlockJustification(headerHash, justification)
return round, setID, err
}

return 0, 0, nil
}

func (cs *chainSync) processBlockDataWithHeaderAndBody(blockData types.BlockData,
origin blockOrigin, announceImportedBlock bool) (err error) {

Expand Down Expand Up @@ -900,27 +882,21 @@ func (cs *chainSync) handleBody(body *types.Body) {
blockSizeGauge.Set(float64(acc))
}

func (cs *chainSync) finalizeAndSetJustification(header *types.Header,
round, setID uint64, justification []byte) (err error) {
if len(justification) > 0 {
err = cs.blockState.SetFinalisedHash(header.Hash(), round, setID)
if err != nil {
return fmt.Errorf("setting finalised hash: %w", err)
}

logger.Debugf(
"finalised block with hash #%d (%s), round %d and set id %d",
header.Number, header.Hash(), round, setID)
func (cs *chainSync) handleJustification(header *types.Header, justification []byte) (err error) {
logger.Debugf("handling justification for block %d...", header.Number)

err = cs.blockState.SetJustification(header.Hash(), justification)
if err != nil {
return fmt.Errorf("setting justification for block number %d: %w",
header.Number, err)
}
headerHash := header.Hash()
err = cs.finalityGadget.VerifyBlockJustification(headerHash, justification)
if err != nil {
return fmt.Errorf("verifying block number %d justification: %w", header.Number, err)
}

logger.Infof("🔨 finalised block number #%d (%s)", header.Number, header.Hash())
err = cs.blockState.SetJustification(headerHash, justification)
if err != nil {
return fmt.Errorf("setting justification for block number %d: %w", header.Number, err)
}

logger.Infof("🔨 finalised block number %d with hash %s", header.Number, headerHash)
return nil
}

Expand Down
3 changes: 2 additions & 1 deletion dot/sync/chain_sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1676,8 +1676,9 @@ func TestChainSync_getHighestBlock(t *testing.T) {
})
}
}

func TestChainSync_BootstrapSync_SuccessfulSync_WithInvalidJusticationBlock(t *testing.T) {
// TODO: https://github.com/ChainSafe/gossamer/issues/3468
t.Skip()
t.Parallel()

ctrl := gomock.NewController(t)
Expand Down
4 changes: 1 addition & 3 deletions dot/sync/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ type BlockState interface {
GetMessageQueue(common.Hash) ([]byte, error)
GetJustification(common.Hash) ([]byte, error)
SetJustification(hash common.Hash, data []byte) error
AddBlockToBlockTree(block *types.Block) error
GetHashByNumber(blockNumber uint) (common.Hash, error)
GetBlockByHash(common.Hash) (*types.Block, error)
GetRuntime(blockHash common.Hash) (runtime runtime.Instance, err error)
Expand All @@ -39,7 +38,6 @@ type BlockState interface {
GetHeaderByNumber(num uint) (*types.Header, error)
GetAllBlocksAtNumber(num uint) ([]common.Hash, error)
IsDescendantOf(parent, child common.Hash) (bool, error)
SetFinalisedHash(common.Hash, uint64, uint64) error
}

// StorageState is the interface for the storage state
Expand All @@ -60,7 +58,7 @@ type BabeVerifier interface {

// FinalityGadget implements justification verification functionality
type FinalityGadget interface {
VerifyBlockJustification(common.Hash, []byte) (round uint64, setID uint64, err error)
VerifyBlockJustification(common.Hash, []byte) error
}

// BlockImportHandler is the interface for the handler of newly imported blocks
Expand Down
36 changes: 3 additions & 33 deletions dot/sync/mocks_test.go

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

7 changes: 3 additions & 4 deletions dot/sync/syncer_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,9 @@ func newTestSyncer(t *testing.T) *Service {
cfg.LogLvl = log.Trace
mockFinalityGadget := NewMockFinalityGadget(ctrl)
mockFinalityGadget.EXPECT().VerifyBlockJustification(gomock.AssignableToTypeOf(common.Hash{}),
gomock.AssignableToTypeOf([]byte{})).DoAndReturn(
func(hash common.Hash, justification []byte) (uint64, uint64, error) {
return 1, 1, nil
}).AnyTimes()
gomock.AssignableToTypeOf([]byte{})).DoAndReturn(func(hash common.Hash, justification []byte) error {
return nil
}).AnyTimes()

cfg.FinalityGadget = mockFinalityGadget
cfg.Network = NewMockNetwork(ctrl)
Expand Down
Loading
Loading