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" "strings"
"github.com/DataDog/zstd" "github.com/DataDog/zstd"
"github.com/ipfs/go-cid"
levelds "github.com/ipfs/go-ds-leveldb" levelds "github.com/ipfs/go-ds-leveldb"
metricsprom "github.com/ipfs/go-metrics-prometheus" metricsprom "github.com/ipfs/go-metrics-prometheus"
"github.com/mitchellh/go-homedir" "github.com/mitchellh/go-homedir"
@ -639,11 +638,13 @@ func slashConsensus(a lapi.FullNode, p string, from string) error {
} }
for block := range blocks { for block := range blocks {
log.Infof("deal with block: %d, %v, %s", block.Height, block.Miner, block.Cid()) 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 { otherBlock, extraBlock, fault, err := slashFilterMinedBlock(ctx, sf, a, block)
if otherBlock == nil { if err != nil {
log.Errorf("slash detector errored: %s", err)
continue continue
} }
log.Errorf("<!!> SLASH FILTER ERROR: %s", err) if fault {
log.Errorf("<!!> SLASH FILTER DETECTED FAULT DUE TO BLOCKS %s and %s", otherBlock.Cid(), block.Cid())
bh1, err := cborutil.Dump(otherBlock) bh1, err := cborutil.Dump(otherBlock)
if err != nil { if err != nil {
log.Errorf("could not dump otherblock:%s, err:%s", otherBlock.Cid(), err) 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, Params: enc,
}, nil) }, nil)
if err != nil { if err != nil {
log.Errorf("ReportConsensusFault to messagepool error:%w", err) log.Errorf("ReportConsensusFault to messagepool error:%s", err)
continue continue
} }
log.Infof("ReportConsensusFault message CID:%s", message.Cid()) log.Infof("ReportConsensusFault message CID:%s", message.Cid())
@ -692,24 +693,35 @@ func slashConsensus(a lapi.FullNode, p string, from string) error {
return err 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]) blockC, err := a.ChainGetBlock(ctx, blockB.Parents[0])
if err != nil { 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 { 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 { if !fault {
otherHeader, err := a.ChainGetBlock(ctx, otherCid) return nil, nil, false, nil
return otherHeader, nil, xerrors.Errorf("chain get other block error:%s", err)
} }
blockA, err := a.ChainGetBlock(ctx, otherCid) blockA, err := a.ChainGetBlock(ctx, blockACid)
if 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 // (c) parent-grinding fault
// Here extra is the "witness", a third block that shows the connection between A and B as // 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] // [A, C]
if types.CidArrsEqual(blockA.Parents, blockC.Parents) && blockA.Height == blockC.Height && if types.CidArrsEqual(blockA.Parents, blockC.Parents) && blockA.Height == blockC.Height &&
types.CidArrsContains(blockB.Parents, blockC.Cid()) && !types.CidArrsContains(blockB.Parents, blockA.Cid()) { 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 { 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 continue
} }
} }