feat: improvements to the consensus slasher
This commit is contained in:
parent
a413a53be2
commit
50a86f2161
@ -16,7 +16,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/DataDog/zstd"
|
||||
"github.com/ipfs/go-cid"
|
||||
levelds "github.com/ipfs/go-ds-leveldb"
|
||||
metricsprom "github.com/ipfs/go-metrics-prometheus"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
@ -639,11 +638,13 @@ func slashConsensus(a lapi.FullNode, p string, from string) error {
|
||||
}
|
||||
for block := range blocks {
|
||||
log.Infof("deal with block: %d, %v, %s", block.Height, block.Miner, block.Cid())
|
||||
if otherBlock, extraBlock, err := slashFilterMinedBlock(ctx, sf, a, block); err != nil {
|
||||
if otherBlock == nil {
|
||||
continue
|
||||
}
|
||||
log.Errorf("<!!> SLASH FILTER ERROR: %s", err)
|
||||
otherBlock, extraBlock, fault, err := slashFilterMinedBlock(ctx, sf, a, block)
|
||||
if err != nil {
|
||||
log.Errorf("slash detector errored: %s", err)
|
||||
continue
|
||||
}
|
||||
if fault {
|
||||
log.Errorf("<!!> SLASH FILTER DETECTED FAULT DUE TO BLOCKS %s and %s", otherBlock.Cid(), block.Cid())
|
||||
bh1, err := cborutil.Dump(otherBlock)
|
||||
if err != nil {
|
||||
log.Errorf("could not dump otherblock:%s, err:%s", otherBlock.Cid(), err)
|
||||
@ -682,7 +683,7 @@ func slashConsensus(a lapi.FullNode, p string, from string) error {
|
||||
Params: enc,
|
||||
}, nil)
|
||||
if err != nil {
|
||||
log.Errorf("ReportConsensusFault to messagepool error:%w", err)
|
||||
log.Errorf("ReportConsensusFault to messagepool error:%s", err)
|
||||
continue
|
||||
}
|
||||
log.Infof("ReportConsensusFault message CID:%s", message.Cid())
|
||||
@ -692,24 +693,35 @@ func slashConsensus(a lapi.FullNode, p string, from string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func slashFilterMinedBlock(ctx context.Context, sf *slashfilter.SlashFilter, a lapi.FullNode, blockB *types.BlockHeader) (*types.BlockHeader, *types.BlockHeader, error) {
|
||||
func slashFilterMinedBlock(ctx context.Context, sf *slashfilter.SlashFilter, a lapi.FullNode, blockB *types.BlockHeader) (*types.BlockHeader, *types.BlockHeader, bool, error) {
|
||||
blockC, err := a.ChainGetBlock(ctx, blockB.Parents[0])
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("chain get block error:%s", err)
|
||||
return nil, nil, false, xerrors.Errorf("chain get block error:%s", err)
|
||||
}
|
||||
|
||||
otherCid, err := sf.MinedBlock(ctx, blockB, blockC.Height)
|
||||
blockACid, fault, err := sf.MinedBlock(ctx, blockB, blockC.Height)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("slash filter check block error:%s", err)
|
||||
return nil, nil, false, xerrors.Errorf("slash filter check block error:%s", err)
|
||||
}
|
||||
|
||||
if otherCid != cid.Undef {
|
||||
otherHeader, err := a.ChainGetBlock(ctx, otherCid)
|
||||
return otherHeader, nil, xerrors.Errorf("chain get other block error:%s", err)
|
||||
if !fault {
|
||||
return nil, nil, false, nil
|
||||
}
|
||||
|
||||
blockA, err := a.ChainGetBlock(ctx, otherCid)
|
||||
if
|
||||
blockA, err := a.ChainGetBlock(ctx, blockACid)
|
||||
if err != nil {
|
||||
return nil, nil, false, xerrors.Errorf("failed to get blockA: %w", err)
|
||||
}
|
||||
|
||||
// (a) double-fork mining (2 blocks at one epoch)
|
||||
if blockA.Height == blockB.Height {
|
||||
return blockA, nil, true, nil
|
||||
}
|
||||
|
||||
// (b) time-offset mining faults (2 blocks with the same parents)
|
||||
if types.CidArrsEqual(blockB.Parents, blockA.Parents) {
|
||||
return blockA, nil, true, nil
|
||||
}
|
||||
|
||||
// (c) parent-grinding fault
|
||||
// Here extra is the "witness", a third block that shows the connection between A and B as
|
||||
@ -721,8 +733,9 @@ func slashFilterMinedBlock(ctx context.Context, sf *slashfilter.SlashFilter, a l
|
||||
// [A, C]
|
||||
if types.CidArrsEqual(blockA.Parents, blockC.Parents) && blockA.Height == blockC.Height &&
|
||||
types.CidArrsContains(blockB.Parents, blockC.Cid()) && !types.CidArrsContains(blockB.Parents, blockA.Cid()) {
|
||||
return blockA, blockC, xerrors.Errorf("chain get other block error:%s", err)
|
||||
return blockA, blockC, true, nil
|
||||
}
|
||||
|
||||
return nil, nil, nil
|
||||
log.Error("unexpectedly reached end of slashFilterMinedBlock despite fault being reported!")
|
||||
return nil, nil, false, nil
|
||||
}
|
||||
|
@ -333,7 +333,7 @@ minerLoop:
|
||||
}
|
||||
|
||||
if fault {
|
||||
log.Errorf("<!!> SLASH FILTER DETECTED FAULT due to witness %s", witness)
|
||||
log.Errorf("<!!> SLASH FILTER DETECTED FAULT due to blocks %s and %s", b.Header.Cid(), witness)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user