Skip to content

Commit 7b69497

Browse files
authored
move double signing detaction to post block process hook (#1281)
1 parent a1545d9 commit 7b69497

4 files changed

Lines changed: 49 additions & 41 deletions

File tree

chain/repository.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -255,17 +255,17 @@ func (r *Repository) ScanConflicts(blockNum uint32) (uint32, error) {
255255
}
256256

257257
// GetConflicts returns an array of found conflicts
258-
func (r *Repository) GetConflicts(blockNum uint32) ([][]byte, error) {
258+
func (r *Repository) GetConflicts(blockNum uint32) ([]thor.Bytes32, error) {
259259
prefix := binary.BigEndian.AppendUint32(nil, blockNum)
260260

261261
iter := r.hdrStore.Iterate(kv.Range(*util.BytesPrefix(prefix)))
262262
defer iter.Release()
263263

264-
conflicts := make([][]byte, 0, 1)
264+
conflicts := make([]thor.Bytes32, 0, 1)
265265
for iter.Next() {
266266
key := make([]byte, 32)
267267
copy(key, iter.Key())
268-
conflicts = append(conflicts, key)
268+
conflicts = append(conflicts, thor.BytesToBytes32(key))
269269
}
270270
return conflicts, iter.Error()
271271
}

chain/repository_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,17 +110,17 @@ func TestConflicts(t *testing.T) {
110110

111111
assert.Equal(t, []any{uint32(1), nil}, M(repo.GetMaxBlockNum()))
112112
assert.Equal(t, []any{uint32(1), nil}, M(repo.ScanConflicts(1)))
113-
assert.Equal(t, []any{[][]byte{b1.Header().ID().Bytes()}, nil}, M(repo.GetConflicts(1)))
113+
assert.Equal(t, []any{[]thor.Bytes32{b1.Header().ID()}, nil}, M(repo.GetConflicts(1)))
114114

115115
b1x := newBlock(b0, 20)
116116
repo.AddBlock(b1x, nil, 1, false)
117117
assert.Equal(t, []any{uint32(1), nil}, M(repo.GetMaxBlockNum()))
118118
assert.Equal(t, []any{uint32(2), nil}, M(repo.ScanConflicts(1)))
119119
switch bytes.Compare(b1.Header().ID().Bytes(), b1x.Header().ID().Bytes()) {
120120
case -1:
121-
assert.Equal(t, []any{[][]byte{b1.Header().ID().Bytes(), b1x.Header().ID().Bytes()}, nil}, M(repo.GetConflicts(1)))
121+
assert.Equal(t, []any{[]thor.Bytes32{b1.Header().ID(), b1x.Header().ID()}, nil}, M(repo.GetConflicts(1)))
122122
case 1:
123-
assert.Equal(t, []any{[][]byte{b1x.Header().ID().Bytes(), b1.Header().ID().Bytes()}, nil}, M(repo.GetConflicts(1)))
123+
assert.Equal(t, []any{[]thor.Bytes32{b1x.Header().ID(), b1.Header().ID()}, nil}, M(repo.GetConflicts(1)))
124124
}
125125
}
126126

cmd/thor/node/node.go

Lines changed: 40 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -282,13 +282,14 @@ func (n *Node) txStashLoop(ctx context.Context) {
282282
}
283283

284284
// guardBlockProcessing adds lock on block processing and maintains block conflicts.
285-
func (n *Node) guardBlockProcessing(blockNum uint32, process func(conflicts [][]byte) (thor.Bytes32, error)) error {
285+
func (n *Node) guardBlockProcessing(blockNum uint32, process func(conflicts uint32) (thor.Bytes32, error)) error {
286286
n.processLock.Lock()
287287
defer n.processLock.Unlock()
288288

289289
var (
290-
err error
291-
blockID thor.Bytes32
290+
err error
291+
blockID thor.Bytes32
292+
conflicts []thor.Bytes32
292293
)
293294

294295
if blockNum > n.maxBlockNum {
@@ -298,19 +299,19 @@ func (n *Node) guardBlockProcessing(blockNum uint32, process func(conflicts [][]
298299
}
299300

300301
// don't increase maxBlockNum if the block is unprocessable
301-
if blockID, err = process(make([][]byte, 0)); err != nil {
302+
if blockID, err = process(0); err != nil {
302303
return err
303304
}
304305

305306
n.maxBlockNum = blockNum
306307
return nil
307308
}
308309

309-
conflicts, err := n.repo.GetConflicts(blockNum)
310+
conflicts, err = n.repo.GetConflicts(blockNum)
310311
if err != nil {
311312
return err
312313
}
313-
blockID, err = process(conflicts)
314+
blockID, err = process(uint32(len(conflicts)))
314315
if err != nil {
315316
return err
316317
}
@@ -336,45 +337,52 @@ func (n *Node) guardBlockProcessing(blockNum uint32, process func(conflicts [][]
336337
}
337338
}
338339
}
339-
return nil
340-
}(); err != nil {
341-
logger.Warn("failed to run post process hook", "err", err)
342-
}
343340

344-
return nil
345-
}
346-
347-
func (n *Node) processBlock(newBlock *block.Block, stats *blockStats) (bool, error) {
348-
var isTrunk *bool
349-
350-
if err := n.guardBlockProcessing(newBlock.Header().Number(), func(conflicts [][]byte) (thor.Bytes32, error) {
351-
// Check whether the block was already there.
352-
// It can be skipped if no conflicts.
353341
if len(conflicts) > 0 {
342+
newBlock, err := n.repo.GetBlock(blockID)
343+
if err != nil {
344+
return err
345+
}
346+
354347
newSigner, err := newBlock.Header().Signer()
355348
if err != nil {
356-
return thor.Bytes32{}, err
349+
return err
357350
}
358351
// iter over conflicting blocks
359352
for _, conflict := range conflicts {
360-
conflictBlock, err := n.repo.GetBlock(thor.BytesToBytes32(conflict))
353+
conflictBlock, err := n.repo.GetBlock(conflict)
361354
if err != nil {
362-
return thor.Bytes32{}, err
355+
return err
363356
}
364357
// logic to verify that the blocks are different and from the same signer
365-
signer, err := conflictBlock.Header().Signer()
358+
existingSigner, err := conflictBlock.Header().Signer()
366359
if err != nil {
367-
return thor.Bytes32{}, err
360+
return err
368361
}
369-
if signer == newSigner &&
370-
conflictBlock.Header().ID() != newBlock.Header().ID() &&
371-
conflictBlock.Header().StateRoot() != newBlock.Header().StateRoot() {
372-
log.Warn("Double signing", "block", shortID(newBlock.Header().ID()), "previous", shortID(thor.BytesToBytes32(conflict)))
373-
metricDoubleSignedBlocks().AddWithLabel(1, map[string]string{"signer": signer.String()})
362+
if existingSigner == newSigner &&
363+
conflictBlock.Header().ID() != newBlock.Header().ID() {
364+
log.Warn("Double signing", "block", shortID(newBlock.Header().ID()), "previous", shortID(conflict), "signer", existingSigner)
365+
metricDoubleSignedBlocks().AddWithLabel(1, map[string]string{"signer": existingSigner.String()})
374366
}
375367
}
368+
}
369+
370+
return nil
371+
}(); err != nil {
372+
logger.Warn("failed to run post process hook", "err", err)
373+
}
376374

377-
_, err = n.repo.GetBlockSummary(newBlock.Header().ID())
375+
return nil
376+
}
377+
378+
func (n *Node) processBlock(newBlock *block.Block, stats *blockStats) (bool, error) {
379+
var isTrunk *bool
380+
381+
if err := n.guardBlockProcessing(newBlock.Header().Number(), func(conflicts uint32) (thor.Bytes32, error) {
382+
// Check whether the block was already there.
383+
// It can be skipped if no conflicts.
384+
if conflicts > 0 {
385+
_, err := n.repo.GetBlockSummary(newBlock.Header().ID())
378386
if err != nil {
379387
if !n.repo.IsNotFound(err) {
380388
return thor.Bytes32{}, err
@@ -403,7 +411,7 @@ func (n *Node) processBlock(newBlock *block.Block, stats *blockStats) (bool, err
403411
}
404412

405413
// process the new block
406-
stage, receipts, err := n.cons.Process(parentSummary, newBlock, uint64(time.Now().Unix()), uint32(len(conflicts)))
414+
stage, receipts, err := n.cons.Process(parentSummary, newBlock, uint64(time.Now().Unix()), conflicts)
407415
if err != nil {
408416
return thor.Bytes32{}, err
409417
}
@@ -444,7 +452,7 @@ func (n *Node) processBlock(newBlock *block.Block, stats *blockStats) (bool, err
444452
}
445453

446454
// add the new block into repository
447-
if err := n.repo.AddBlock(newBlock, receipts, uint32(len(conflicts)), becomeNewBest); err != nil {
455+
if err := n.repo.AddBlock(newBlock, receipts, conflicts, becomeNewBest); err != nil {
448456
return thor.Bytes32{}, errors.Wrap(err, "add block")
449457
}
450458

cmd/thor/node/packer_loop.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ func (n *Node) pack(flow *packer.Flow) (err error) {
120120
}
121121
}()
122122

123-
return n.guardBlockProcessing(flow.Number(), func(conflicts [][]byte) (thor.Bytes32, error) {
123+
return n.guardBlockProcessing(flow.Number(), func(conflicts uint32) (thor.Bytes32, error) {
124124
var (
125125
startTime = mclock.Now()
126126
logEnabled = !n.options.SkipLogs && !n.logDBFailed
@@ -150,7 +150,7 @@ func (n *Node) pack(flow *packer.Flow) (err error) {
150150
}
151151

152152
// pack the new block
153-
newBlock, stage, receipts, err := flow.Pack(n.master.PrivateKey, uint32(len(conflicts)), shouldVote)
153+
newBlock, stage, receipts, err := flow.Pack(n.master.PrivateKey, conflicts, shouldVote)
154154
if err != nil {
155155
return thor.Bytes32{}, errors.Wrap(err, "failed to pack block")
156156
}
@@ -177,7 +177,7 @@ func (n *Node) pack(flow *packer.Flow) (err error) {
177177
}
178178

179179
// add the new block into repository
180-
if err := n.repo.AddBlock(newBlock, receipts, uint32(len(conflicts)), true); err != nil {
180+
if err := n.repo.AddBlock(newBlock, receipts, conflicts, true); err != nil {
181181
return thor.Bytes32{}, errors.Wrap(err, "add block")
182182
}
183183

0 commit comments

Comments
 (0)