mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-08 23:18:15 -05:00
Add feature flag to blacklist blocks (#15030)
* Add feature flag to blacklist blocks * review and add tests * add test * review * Kasey's review --------- Co-authored-by: Radosław Kapka <rkapka@wp.pl>
This commit is contained in:
@@ -32,6 +32,8 @@ var (
|
||||
ErrNilHead = errors.New("nil head")
|
||||
// errNotGenesisRoot is returned when the root is not the genesis block root.
|
||||
errNotGenesisRoot = errors.New("root is not the genesis block root")
|
||||
// errBlacklistedBlock is returned when a block is blacklisted as invalid.
|
||||
errBlacklistedRoot = errors.New("block root is blacklisted")
|
||||
)
|
||||
|
||||
var errMaxBlobsExceeded = errors.New("Expected commitments in block exceeds MAX_BLOBS_PER_BLOCK")
|
||||
|
||||
@@ -175,6 +175,9 @@ func (s *Service) onBlockBatch(ctx context.Context, blks []consensusblocks.ROBlo
|
||||
var set *bls.SignatureBatch
|
||||
boundaries := make(map[[32]byte]state.BeaconState)
|
||||
for i, b := range blks {
|
||||
if features.BlacklistedBlock(b.Root()) {
|
||||
return errBlacklistedRoot
|
||||
}
|
||||
v, h, err := getStateVersionAndPayload(preState)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/das"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/slasher/types"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/features"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
@@ -64,6 +65,10 @@ type SlashingReceiver interface {
|
||||
func (s *Service) ReceiveBlock(ctx context.Context, block interfaces.ReadOnlySignedBeaconBlock, blockRoot [32]byte, avs das.AvailabilityStore) error {
|
||||
ctx, span := trace.StartSpan(ctx, "blockChain.ReceiveBlock")
|
||||
defer span.End()
|
||||
// Return early if the block is blacklisted
|
||||
if features.BlacklistedBlock(blockRoot) {
|
||||
return errBlacklistedRoot
|
||||
}
|
||||
// Return early if the block has been synced
|
||||
if s.InForkchoice(blockRoot) {
|
||||
log.WithField("blockRoot", fmt.Sprintf("%#x", blockRoot)).Debug("Ignoring already synced block")
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
statefeed "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/feed/state"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/das"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/voluntaryexits"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/features"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
@@ -41,6 +42,16 @@ func TestService_ReceiveBlock(t *testing.T) {
|
||||
bc.ShardCommitteePeriod = 0 // Required for voluntary exits test in reasonable time.
|
||||
params.OverrideBeaconConfig(bc)
|
||||
|
||||
badBlock := genFullBlock(t, util.DefaultBlockGenConfig(), 101)
|
||||
badRoot, err := badBlock.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
badRoots := make(map[[32]byte]struct{})
|
||||
badRoots[badRoot] = struct{}{}
|
||||
resetCfg := features.InitWithReset(&features.Flags{
|
||||
BlacklistedRoots: badRoots,
|
||||
})
|
||||
defer resetCfg()
|
||||
|
||||
type args struct {
|
||||
block *ethpb.SignedBeaconBlock
|
||||
}
|
||||
@@ -124,8 +135,14 @@ func TestService_ReceiveBlock(t *testing.T) {
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "The block is blacklisted",
|
||||
args: args{
|
||||
block: badBlock,
|
||||
},
|
||||
wantedErr: errBlacklistedRoot.Error(),
|
||||
},
|
||||
}
|
||||
|
||||
wg := new(sync.WaitGroup)
|
||||
for _, tt := range tests {
|
||||
wg.Add(1)
|
||||
|
||||
@@ -32,6 +32,7 @@ go_library(
|
||||
"//beacon-chain/sync/verify:go_default_library",
|
||||
"//beacon-chain/verification:go_default_library",
|
||||
"//cmd/beacon-chain/flags:go_default_library",
|
||||
"//config/features:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
prysmsync "github.com/prysmaticlabs/prysm/v5/beacon-chain/sync"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/sync/verify"
|
||||
"github.com/prysmaticlabs/prysm/v5/cmd/beacon-chain/flags"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/features"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
@@ -357,6 +358,13 @@ func (f *blocksFetcher) fetchBlocksFromPeer(
|
||||
log.WithField("peer", p).WithError(err).Debug("invalid BeaconBlocksByRange response")
|
||||
continue
|
||||
}
|
||||
if len(features.Get().BlacklistedRoots) > 0 {
|
||||
for _, b := range robs {
|
||||
if features.BlacklistedBlock(b.Block.Root()) {
|
||||
return nil, p, prysmsync.ErrInvalidFetchedData
|
||||
}
|
||||
}
|
||||
}
|
||||
return robs, p, err
|
||||
}
|
||||
return nil, "", errNoPeersAvailable
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/transition"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/features"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
consensusblocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
@@ -409,6 +410,9 @@ func (s *Service) setSeenBlockIndexSlot(slot primitives.Slot, proposerIdx primit
|
||||
|
||||
// Returns true if the block is marked as a bad block.
|
||||
func (s *Service) hasBadBlock(root [32]byte) bool {
|
||||
if features.BlacklistedBlock(root) {
|
||||
return true
|
||||
}
|
||||
s.badBlockLock.RLock()
|
||||
defer s.badBlockLock.RUnlock()
|
||||
_, seen := s.badBlockCache.Get(string(root[:]))
|
||||
|
||||
3
changelog/potuz_blacklist.md
Normal file
3
changelog/potuz_blacklist.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Added
|
||||
|
||||
- Add a feature flag `--blacklist-roots` to allow the node to specify blocks that will be treated as invalid.
|
||||
@@ -14,6 +14,7 @@ go_library(
|
||||
"//cmd:go_default_library",
|
||||
"//cmd/beacon-chain/sync/backfill/flags:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
],
|
||||
@@ -30,6 +31,7 @@ go_test(
|
||||
deps = [
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/cmd"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
@@ -88,7 +89,8 @@ type Flags struct {
|
||||
AggregateIntervals [3]time.Duration
|
||||
|
||||
// Feature related flags (alignment forced in the end)
|
||||
ForceHead string // ForceHead forces the head block to be a specific block root, the last head block, or the last finalized block.
|
||||
ForceHead string // ForceHead forces the head block to be a specific block root, the last head block, or the last finalized block.
|
||||
BlacklistedRoots map[[32]byte]struct{} // BlacklistedRoots is a list of roots that are blacklisted from processing.
|
||||
}
|
||||
|
||||
var featureConfig *Flags
|
||||
@@ -282,11 +284,29 @@ func ConfigureBeaconChain(ctx *cli.Context) error {
|
||||
cfg.ForceHead = ctx.String(forceHeadFlag.Name)
|
||||
}
|
||||
|
||||
if ctx.IsSet(blacklistRoots.Name) {
|
||||
logEnabled(blacklistRoots)
|
||||
cfg.BlacklistedRoots = parseBlacklistedRoots(ctx.StringSlice(blacklistRoots.Name))
|
||||
}
|
||||
|
||||
cfg.AggregateIntervals = [3]time.Duration{aggregateFirstInterval.Value, aggregateSecondInterval.Value, aggregateThirdInterval.Value}
|
||||
Init(cfg)
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseBlacklistedRoots(blacklistedRoots []string) map[[32]byte]struct{} {
|
||||
roots := make(map[[32]byte]struct{})
|
||||
for _, root := range blacklistedRoots {
|
||||
r, err := bytesutil.DecodeHexWithLength(root, 32)
|
||||
if err != nil {
|
||||
log.WithError(err).WithField("root", root).Warn("Failed to parse blacklisted root")
|
||||
continue
|
||||
}
|
||||
roots[[32]byte(r)] = struct{}{}
|
||||
}
|
||||
return roots
|
||||
}
|
||||
|
||||
// ConfigureValidator sets the global config based
|
||||
// on what flags are enabled for the validator client.
|
||||
func ConfigureValidator(ctx *cli.Context) error {
|
||||
@@ -398,3 +418,10 @@ func ValidateNetworkFlags(ctx *cli.Context) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// BlacklistedBlock returns weather the given block root belongs to the list of blacklisted roots.
|
||||
func BlacklistedBlock(r [32]byte) bool {
|
||||
blacklisted := Get().BlacklistedRoots
|
||||
_, ok := blacklisted[r]
|
||||
return ok
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/sirupsen/logrus/hooks/test"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
@@ -93,3 +94,26 @@ func TestValidateNetworkFlags(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_parseBlacklistedRoots(t *testing.T) {
|
||||
strings := []string{"0xf98e27558ac9ba27ab7d0d3b97d5742a4a68b5e3d7f33c520eda14c39df6368c",
|
||||
"0x31604da144e1047b250ee87c5049774870e4a140e8eb0087f38ebc4584c2e7",
|
||||
"0x4fcf04e7e4075962360a91be0c54c1d3f67237aa2ce07d83b0479971af3f7e78",
|
||||
}
|
||||
hook := test.NewGlobal()
|
||||
resCfg := InitWithReset(&Flags{
|
||||
BlacklistedRoots: parseBlacklistedRoots(strings),
|
||||
})
|
||||
defer resCfg()
|
||||
|
||||
expected := [][32]byte{
|
||||
{0xf9, 0x8e, 0x27, 0x55, 0x8a, 0xc9, 0xba, 0x27, 0xab, 0x7d, 0x0d, 0x3b, 0x97, 0xd5, 0x74, 0x2a, 0x4a, 0x68, 0xb5, 0xe3, 0xd7, 0xf3, 0x3c, 0x52, 0x0e, 0xda, 0x14, 0xc3, 0x9d, 0xf6, 0x36, 0x8c},
|
||||
{0x4f, 0xcf, 0x04, 0xe7, 0xe4, 0x07, 0x59, 0x62, 0x36, 0x0a, 0x91, 0xbe, 0x0c, 0x54, 0xc1, 0xd3, 0xf6, 0x72, 0x37, 0xaa, 0x2c, 0xe0, 0x7d, 0x83, 0xb0, 0x47, 0x99, 0x71, 0xaf, 0x3f, 0x7e, 0x78},
|
||||
}
|
||||
require.LogsContain(t, hook, "Failed to parse blacklisted root")
|
||||
require.LogsContain(t, hook, strings[1])
|
||||
require.Equal(t, len(expected), len(Get().BlacklistedRoots))
|
||||
for _, root := range expected {
|
||||
require.Equal(t, true, BlacklistedBlock(root))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,6 +185,12 @@ var (
|
||||
Usage: "Forces the head of the beacon chain to a specific block root. Values can be 'head' or a block root." +
|
||||
" The block root has to be known to the beacon node and correspond to a block newer than the current finalized checkpoint.",
|
||||
}
|
||||
// blacklistRoots is a flag for blacklisting block roots from gossip and
|
||||
// downscore peers that send them.
|
||||
blacklistRoots = &cli.StringSliceFlag{
|
||||
Name: "blacklist-roots",
|
||||
Usage: "A comma-separatted list of 0x-prefixed hexstrings. Declares blocks with the given blockroots to be invalid. It downscores peers that send these blocks.",
|
||||
}
|
||||
)
|
||||
|
||||
// devModeFlags holds list of flags that are set when development mode is on.
|
||||
@@ -244,6 +250,7 @@ var BeaconChainFlags = combinedFlags([]cli.Flag{
|
||||
EnableDiscoveryReboot,
|
||||
enableExperimentalAttestationPool,
|
||||
forceHeadFlag,
|
||||
blacklistRoots,
|
||||
}, deprecatedBeaconFlags, deprecatedFlags, upcomingDeprecation)
|
||||
|
||||
func combinedFlags(flags ...[]cli.Flag) []cli.Flag {
|
||||
|
||||
Reference in New Issue
Block a user