Skip to content

Commit e1f9f42

Browse files
authored
feat(dot/network, lib/grandpa): request justification on receiving NeighbourMessage, verify justification on receipt (#1529)
1 parent b18290c commit e1f9f42

28 files changed

+430
-266
lines changed

dot/core/test_helpers.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,10 @@ func (s *mockSyncer) ProcessBlockData(_ []*types.BlockData) (int, error) {
256256
return 0, nil
257257
}
258258

259+
func (s *mockSyncer) ProcessJustification(data []*types.BlockData) (int, error) {
260+
return 0, nil
261+
}
262+
259263
func (s *mockSyncer) IsSynced() bool {
260264
return false
261265
}

dot/network/host.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ func (h *host) bootstrap() {
257257
failed++
258258
}
259259
}
260-
if failed == len(all) {
260+
if failed == len(all) && len(all) != 0 {
261261
logger.Error("failed to bootstrap to any bootnode")
262262
}
263263
}

dot/network/state.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ type Syncer interface {
3838
// CreateBlockResponse is called upon receipt of a BlockRequestMessage to create the response
3939
CreateBlockResponse(*BlockRequestMessage) (*BlockResponseMessage, error)
4040

41+
ProcessJustification(data []*types.BlockData) (int, error)
42+
4143
// ProcessBlockData is called to process BlockData received in a BlockResponseMessage
4244
ProcessBlockData(data []*types.BlockData) (int, error)
4345

dot/network/sync.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ func (q *syncQueue) pushResponse(resp *BlockResponseMessage, pid peer.ID) error
474474
}
475475

476476
if numJustifications == 0 {
477+
logger.Debug("got empty justification data", "start hash", startHash)
477478
return errEmptyJustificationData
478479
}
479480

@@ -484,7 +485,7 @@ func (q *syncQueue) pushResponse(resp *BlockResponseMessage, pid peer.ID) error
484485
from: pid,
485486
})
486487

487-
logger.Info("pushed justification data to queue", "hash", startHash)
488+
logger.Debug("pushed justification data to queue", "hash", startHash)
488489
q.responseCh <- justificationResponses
489490
return nil
490491
}
@@ -668,7 +669,7 @@ func (q *syncQueue) handleBlockJustification(data []*types.BlockData) {
668669
startHash, endHash := data[0].Hash, data[len(data)-1].Hash
669670
logger.Debug("sending justification data to syncer", "start", startHash, "end", endHash)
670671

671-
_, err := q.s.syncer.ProcessBlockData(data)
672+
_, err := q.s.syncer.ProcessJustification(data)
672673
if err != nil {
673674
logger.Warn("failed to handle block justifications", "error", err)
674675
return
@@ -792,6 +793,7 @@ func (q *syncQueue) handleBlockAnnounceHandshake(blockNum uint32, from peer.ID)
792793

793794
func (q *syncQueue) handleBlockAnnounce(msg *BlockAnnounceMessage, from peer.ID) {
794795
q.updatePeerScore(from, 1)
796+
logger.Info("received BlockAnnounce", "number", msg.Number, "from", from)
795797

796798
header, err := types.NewHeader(msg.ParentHash, msg.StateRoot, msg.ExtrinsicsRoot, msg.Number, msg.Digest)
797799
if err != nil {

dot/network/sync_justification.go

Lines changed: 8 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -18,62 +18,19 @@ package network
1818

1919
import (
2020
"math/big"
21-
"time"
22-
)
23-
24-
func (q *syncQueue) finalizeAtHead() {
25-
prev, err := q.s.blockState.GetFinalizedHeader(0, 0)
26-
if err != nil {
27-
logger.Error("failed to get latest finalized block header", "error", err)
28-
return
29-
}
30-
31-
for {
32-
select {
33-
// sleep for average block time TODO: make this configurable from slot duration
34-
case <-time.After(q.slotDuration * 2):
35-
case <-q.ctx.Done():
36-
return
37-
}
38-
39-
head, err := q.s.blockState.BestBlockNumber()
40-
if err != nil {
41-
continue
42-
}
4321

44-
if head.Int64() < q.goal {
45-
continue
46-
}
47-
48-
curr, err := q.s.blockState.GetFinalizedHeader(0, 0)
49-
if err != nil {
50-
continue
51-
}
52-
53-
logger.Debug("checking finalized blocks", "curr", curr.Number, "prev", prev.Number)
54-
55-
if curr.Number.Cmp(prev.Number) > 0 {
56-
prev = curr
57-
continue
58-
}
59-
60-
prev = curr
61-
62-
start := head.Uint64() - uint64(blockRequestSize)
63-
if curr.Number.Uint64() > start {
64-
start = curr.Number.Uint64() + 1
65-
} else if int(start) < int(blockRequestSize) {
66-
start = 1
67-
}
22+
"github.com/libp2p/go-libp2p-core/peer"
23+
)
6824

69-
q.pushJustificationRequest(start)
70-
}
25+
// SendJustificationRequest pushes a justification request to the queue to be sent out to the network
26+
func (s *Service) SendJustificationRequest(to peer.ID, num uint32) {
27+
s.syncQueue.pushJustificationRequest(to, uint64(num))
7128
}
7229

73-
func (q *syncQueue) pushJustificationRequest(start uint64) {
30+
func (q *syncQueue) pushJustificationRequest(to peer.ID, start uint64) {
7431
startHash, err := q.s.blockState.GetHashByNumber(big.NewInt(int64(start)))
7532
if err != nil {
76-
logger.Error("failed to get hash for block w/ number", "number", start, "error", err)
33+
logger.Debug("failed to get hash for block w/ number", "number", start, "error", err)
7734
return
7835
}
7936

@@ -87,6 +44,6 @@ func (q *syncQueue) pushJustificationRequest(start uint64) {
8744

8845
q.requestCh <- &syncRequest{
8946
req: req,
90-
to: "",
47+
to: to,
9148
}
9249
}

dot/network/sync_justification_test.go

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ package network
1818

1919
import (
2020
"context"
21-
"math/big"
2221
"testing"
2322
"time"
2423

@@ -135,34 +134,3 @@ func TestSyncQueue_processBlockResponses_Justification(t *testing.T) {
135134
require.True(t, ok)
136135
require.Equal(t, 2, score)
137136
}
138-
139-
func TestSyncQueue_finalizeAtHead(t *testing.T) {
140-
q := newTestSyncQueue(t)
141-
q.stop()
142-
time.Sleep(time.Second)
143-
q.ctx = context.Background()
144-
q.slotDuration = time.Millisecond * 200
145-
146-
hash, err := q.s.blockState.GetHashByNumber(big.NewInt(1))
147-
require.NoError(t, err)
148-
149-
go q.finalizeAtHead()
150-
time.Sleep(time.Second)
151-
152-
data, has := q.justificationRequestData.Load(hash)
153-
require.True(t, has)
154-
require.Equal(t, requestData{}, data)
155-
156-
expected := createBlockRequestWithHash(hash, blockRequestSize)
157-
expected.RequestedData = RequestedDataJustification
158-
159-
select {
160-
case req := <-q.requestCh:
161-
require.Equal(t, &syncRequest{
162-
req: expected,
163-
to: "",
164-
}, req)
165-
case <-time.After(time.Second):
166-
t.Fatal("did not receive request")
167-
}
168-
}

dot/network/test_helpers.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ func (s *mockSyncer) ProcessBlockData(data []*types.BlockData) (int, error) {
6161
return 0, nil
6262
}
6363

64+
func (s *mockSyncer) ProcessJustification(data []*types.BlockData) (int, error) {
65+
return 0, nil
66+
}
67+
6468
func (s *mockSyncer) IsSynced() bool {
6569
return s.synced
6670
}

dot/node.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ func NodeInitialized(basepath string, expected bool) bool {
125125
_, err := os.Stat(registry)
126126
if os.IsNotExist(err) {
127127
if expected {
128-
logger.Warn(
128+
logger.Debug(
129129
"node has not been initialized",
130130
"basepath", basepath,
131131
"error", "failed to locate KEYREGISTRY file in data directory",
@@ -242,12 +242,6 @@ func NewNode(cfg *Config, ks *keystore.GlobalKeystore, stopFunc func()) (*Node,
242242
return nil, err
243243
}
244244

245-
// Syncer
246-
syncer, err := createSyncService(cfg, stateSrvc, bp, dh, ver, rt)
247-
if err != nil {
248-
return nil, err
249-
}
250-
251245
// create GRANDPA service
252246
fg, err := createGRANDPAService(cfg, rt, stateSrvc, dh, ks.Gran, networkSrvc)
253247
if err != nil {
@@ -256,6 +250,12 @@ func NewNode(cfg *Config, ks *keystore.GlobalKeystore, stopFunc func()) (*Node,
256250
nodeSrvcs = append(nodeSrvcs, fg)
257251
dh.SetFinalityGadget(fg) // TODO: this should be cleaned up
258252

253+
// Syncer
254+
syncer, err := createSyncService(cfg, stateSrvc, bp, fg, dh, ver, rt)
255+
if err != nil {
256+
return nil, err
257+
}
258+
259259
// Core Service
260260

261261
// create core service and append core service to node services

dot/rpc/modules/system_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ func (s *mockSyncer) ProcessBlockData(_ []*types.BlockData) (int, error) {
5151
return 0, nil
5252
}
5353

54+
func (s *mockSyncer) ProcessJustification(_ []*types.BlockData) (int, error) {
55+
return 0, nil
56+
}
57+
5458
func (s *mockSyncer) HandleBlockAnnounce(msg *network.BlockAnnounceMessage) error {
5559
return nil
5660
}

dot/services.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,13 +381,14 @@ func createBlockVerifier(st *state.Service) (*babe.VerificationManager, error) {
381381
return ver, nil
382382
}
383383

384-
func createSyncService(cfg *Config, st *state.Service, bp sync.BlockProducer, dh *core.DigestHandler, verifier *babe.VerificationManager, rt runtime.Instance) (*sync.Service, error) {
384+
func createSyncService(cfg *Config, st *state.Service, bp sync.BlockProducer, fg sync.FinalityGadget, dh *core.DigestHandler, verifier *babe.VerificationManager, rt runtime.Instance) (*sync.Service, error) {
385385
syncCfg := &sync.Config{
386386
LogLvl: cfg.Log.SyncLvl,
387387
BlockState: st.Block,
388388
StorageState: st.Storage,
389389
TransactionState: st.Transaction,
390390
BlockProducer: bp,
391+
FinalityGadget: fg,
391392
Verifier: verifier,
392393
Runtime: rt,
393394
DigestHandler: dh,

0 commit comments

Comments
 (0)