Skip to content

Commit 9c6283e

Browse files
authored
fix(dot/sync): fix block request and response logic (#1907)
1 parent 8c8f6d0 commit 9c6283e

File tree

11 files changed

+791
-76
lines changed

11 files changed

+791
-76
lines changed

dot/network/notifications.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ func (s *Service) sendData(peer peer.ID, hs Handshake, info *notificationsProtoc
349349

350350
err := s.host.writeToStream(hsData.stream, msg)
351351
if err != nil {
352-
logger.Trace("failed to send message to peer", "peer", peer, "error", err)
352+
logger.Debug("failed to send message to peer", "peer", peer, "error", err)
353353
}
354354
}
355355

dot/state/block.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,16 @@ func (bs *BlockState) AddBlockToBlockTree(header *types.Header) error {
444444
return bs.bt.AddBlock(header, arrivalTime)
445445
}
446446

447+
// GetAllBlocksAtNumber returns all unfinalised blocks with the given number
448+
func (bs *BlockState) GetAllBlocksAtNumber(num *big.Int) ([]common.Hash, error) {
449+
header, err := bs.GetHeaderByNumber(num)
450+
if err != nil {
451+
return nil, err
452+
}
453+
454+
return bs.GetAllBlocksAtDepth(header.ParentHash), nil
455+
}
456+
447457
// GetAllBlocksAtDepth returns all hashes with the depth of the given hash plus one
448458
func (bs *BlockState) GetAllBlocksAtDepth(hash common.Hash) []common.Hash {
449459
return bs.bt.GetAllBlocksAtNumber(hash)

dot/sync/chain_sync.go

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -646,9 +646,7 @@ func (cs *chainSync) doSync(req *network.BlockRequestMessage) *workerError {
646646

647647
if req.Direction == network.Descending {
648648
// reverse blocks before pre-validating and placing in ready queue
649-
for i, j := 0, len(resp.BlockData)-1; i < j; i, j = i+1, j-1 {
650-
resp.BlockData[i], resp.BlockData[j] = resp.BlockData[j], resp.BlockData[i]
651-
}
649+
reverseBlockData(resp.BlockData)
652650
}
653651

654652
// perform some pre-validation of response, error if failure
@@ -897,10 +895,18 @@ func workerToRequests(w *worker) ([]*network.BlockRequestMessage, error) {
897895
} else {
898896
// in tip-syncing mode, we know the hash of the block on the fork we wish to sync
899897
start, _ = variadic.NewUint64OrHash(w.startHash)
898+
899+
// if we're doing descending requests and not at the last (highest starting) request,
900+
// then use number as start block
901+
if w.direction == network.Descending && i != numRequests-1 {
902+
start = variadic.MustNewUint64OrHash(startNumber)
903+
}
900904
}
901905

902906
var end *common.Hash
903-
if !w.targetHash.IsEmpty() {
907+
if !w.targetHash.IsEmpty() && i == numRequests-1 {
908+
// if we're on our last request (which should contain the target hash),
909+
// then add it
904910
end = &w.targetHash
905911
}
906912

@@ -911,7 +917,21 @@ func workerToRequests(w *worker) ([]*network.BlockRequestMessage, error) {
911917
Direction: w.direction,
912918
Max: &max,
913919
}
914-
startNumber += maxResponseSize
920+
921+
switch w.direction {
922+
case network.Ascending:
923+
startNumber += maxResponseSize
924+
case network.Descending:
925+
startNumber -= maxResponseSize
926+
}
927+
}
928+
929+
// if our direction is descending, we want to send out the request with the lowest
930+
// startNumber first
931+
if w.direction == network.Descending {
932+
for i, j := 0, len(reqs)-1; i < j; i, j = i+1, j-1 {
933+
reqs[i], reqs[j] = reqs[j], reqs[i]
934+
}
915935
}
916936

917937
return reqs, nil

dot/sync/chain_sync_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,30 @@ func TestWorkerToRequests(t *testing.T) {
405405
},
406406
},
407407
},
408+
{
409+
w: &worker{
410+
startNumber: big.NewInt(1 + maxResponseSize + (maxResponseSize / 2)),
411+
targetNumber: big.NewInt(1),
412+
direction: network.Descending,
413+
requestData: bootstrapRequestData,
414+
},
415+
expected: []*network.BlockRequestMessage{
416+
{
417+
RequestedData: network.RequestedDataHeader + network.RequestedDataBody + network.RequestedDataJustification,
418+
StartingBlock: *variadic.MustNewUint64OrHash(1 + (maxResponseSize / 2)),
419+
EndBlockHash: nil,
420+
Direction: network.Descending,
421+
Max: &max64,
422+
},
423+
{
424+
RequestedData: bootstrapRequestData,
425+
StartingBlock: *variadic.MustNewUint64OrHash(1 + maxResponseSize + (maxResponseSize / 2)),
426+
EndBlockHash: nil,
427+
Direction: network.Descending,
428+
Max: &max128,
429+
},
430+
},
431+
},
408432
}
409433

410434
for i, tc := range testCases {

dot/sync/errors.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ var (
4040
ErrInvalidBlock = errors.New("could not verify block")
4141

4242
// ErrInvalidBlockRequest is returned when an invalid block request is received
43-
ErrInvalidBlockRequest = errors.New("invalid block request")
43+
ErrInvalidBlockRequest = errors.New("invalid block request")
44+
errInvalidRequestDirection = errors.New("invalid request direction")
45+
errRequestStartTooHigh = errors.New("request start number is higher than our best block")
46+
errFailedToGetEndHashAncestor = errors.New("failed to get ancestor of end block")
4447

4548
// chainSync errors
4649
errEmptyBlockData = errors.New("empty block data")
@@ -57,6 +60,9 @@ var (
5760
errUnknownParent = errors.New("parent of first block in block response is unknown")
5861
errUnknownBlockForJustification = errors.New("received justification for unknown block")
5962
errFailedToGetParent = errors.New("failed to get parent header")
63+
errNilDescendantNumber = errors.New("descendant number is nil")
64+
errStartAndEndMismatch = errors.New("request start and end hash are not on the same chain")
65+
errFailedToGetDescendant = errors.New("failed to find descendant block")
6066
)
6167

6268
// ErrNilChannel is returned if a channel is nil

dot/sync/interface.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ type BlockState interface {
5757
StoreRuntime(common.Hash, runtime.Instance)
5858
GetHighestFinalisedHeader() (*types.Header, error)
5959
GetFinalisedNotifierChannel() chan *types.FinalisationInfo
60+
GetHeaderByNumber(num *big.Int) (*types.Header, error)
61+
GetAllBlocksAtNumber(num *big.Int) ([]common.Hash, error)
62+
IsDescendantOf(parent, child common.Hash) (bool, error)
6063
}
6164

6265
// StorageState is the interface for the storage state

0 commit comments

Comments
 (0)