feat: improvements to the consensus slasher

This commit is contained in:
Aayush 2023-06-13 10:51:03 -04:00
parent a413a53be2
commit 50a86f2161
2 changed files with 32 additions and 19 deletions

View File

@ -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
}

View File

@ -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
}
}