From b57cbdcff7bc276ce586d30560d27fa491a62e4c Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Thu, 4 Jan 2024 10:44:57 +0100 Subject: [PATCH 01/92] polygon/sync: canonical chain builder (#9117) --- cmd/devnet/networks/devnet_bor.go | 7 +- cmd/devnet/services/polygon/heimdall.go | 9 +- cmd/rpcdaemon/cli/config.go | 22 +- consensus/bor/bor.go | 136 ++-------- consensus/bor/bor_test.go | 26 +- consensus/bor/borcfg/bor_config.go | 196 ++++++++++++++ consensus/bor/borcfg/bor_config_test.go | 47 ++++ consensus/bor/heimdall/span/span_id.go | 8 +- consensus/bor/heimdall/span/span_id_test.go | 4 +- consensus/bor/heimdall/span/spanner.go | 11 +- consensus/bor/snapshot.go | 30 +-- consensus/bor/valset/validator_set.go | 28 +- consensus/misc/eip1559.go | 5 +- core/forkid/forkid.go | 4 +- core/rawdb/accessors_metadata.go | 21 ++ core/system_contract_lookup.go | 4 +- erigon-lib/chain/chain_config.go | 176 +------------ erigon-lib/common/collections.go | 15 ++ .../txpool/txpooluitl/all_components.go | 2 +- eth/ethconfig/config.go | 4 +- eth/ethconsensusconfig/config.go | 7 +- eth/stagedsync/stage_bor_heimdall.go | 50 ++-- eth/stagedsync/stage_bor_heimdall_test.go | 2 +- eth/stagedsync/stage_txlookup.go | 15 +- .../stagedsynctest/chain_configs.go | 3 +- eth/stagedsync/stagedsynctest/harness.go | 15 +- params/config.go | 12 + polygon/sync/canonical_chain_builder.go | 244 ++++++++++++++++++ polygon/sync/canonical_chain_builder_test.go | 23 ++ polygon/sync/difficulty.go | 60 +++++ polygon/sync/difficulty_test.go | 21 ++ polygon/sync/heimdall.go | 13 +- .../sync/mock/canonical_chain_builder_mock.go | 118 +++++++++ tests/bor/helper/miner.go | 16 +- turbo/jsonrpc/bor_helper.go | 8 +- turbo/jsonrpc/bor_snapshot.go | 13 +- turbo/jsonrpc/eth_block.go | 12 +- turbo/snapshotsync/freezeblocks/dump_test.go | 5 +- 38 files changed, 1000 insertions(+), 392 deletions(-) create mode 100644 consensus/bor/borcfg/bor_config.go create mode 100644 consensus/bor/borcfg/bor_config_test.go create mode 100644 erigon-lib/common/collections.go create mode 100644 polygon/sync/canonical_chain_builder.go create mode 100644 polygon/sync/canonical_chain_builder_test.go create mode 100644 polygon/sync/difficulty.go create mode 100644 polygon/sync/difficulty_test.go create mode 100644 polygon/sync/mock/canonical_chain_builder_mock.go diff --git a/cmd/devnet/networks/devnet_bor.go b/cmd/devnet/networks/devnet_bor.go index af9b1f218ec..9fccc438dd8 100644 --- a/cmd/devnet/networks/devnet_bor.go +++ b/cmd/devnet/networks/devnet_bor.go @@ -3,6 +3,8 @@ package networks import ( "time" + "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/chain/networkname" "github.com/ledgerwatch/erigon/cmd/devnet/accounts" "github.com/ledgerwatch/erigon/cmd/devnet/args" @@ -10,9 +12,9 @@ import ( account_services "github.com/ledgerwatch/erigon/cmd/devnet/services/accounts" "github.com/ledgerwatch/erigon/cmd/devnet/services/polygon" "github.com/ledgerwatch/erigon/cmd/utils" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/params" - "github.com/ledgerwatch/log/v3" ) func NewBorDevnetWithoutHeimdall( @@ -190,8 +192,9 @@ func NewBorDevnetWithLocalHeimdall( logger log.Logger, ) devnet.Devnet { config := *params.BorDevnetChainConfig + borConfig := config.Bor.(*borcfg.BorConfig) if sprintSize > 0 { - config.Bor.Sprint = map[string]uint64{"0": sprintSize} + borConfig.Sprint = map[string]uint64{"0": sprintSize} } checkpointOwner := accounts.NewAccount("checkpoint-owner") diff --git a/cmd/devnet/services/polygon/heimdall.go b/cmd/devnet/services/polygon/heimdall.go index 69da6aae841..b3748cad48f 100644 --- a/cmd/devnet/services/polygon/heimdall.go +++ b/cmd/devnet/services/polygon/heimdall.go @@ -18,6 +18,7 @@ import ( "github.com/ledgerwatch/erigon/cmd/devnet/blocks" "github.com/ledgerwatch/erigon/cmd/devnet/contracts" "github.com/ledgerwatch/erigon/cmd/devnet/devnet" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "github.com/ledgerwatch/erigon/consensus/bor/heimdall/checkpoint" "github.com/ledgerwatch/erigon/consensus/bor/heimdall/milestone" "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" @@ -68,6 +69,7 @@ type CheckpointConfig struct { type Heimdall struct { sync.Mutex chainConfig *chain.Config + borConfig *borcfg.BorConfig grpcAddr string validatorSet *valset.ValidatorSet pendingCheckpoint *checkpoint.Checkpoint @@ -97,6 +99,7 @@ func NewHeimdall( ) *Heimdall { heimdall := &Heimdall{ chainConfig: chainConfig, + borConfig: chainConfig.Bor.(*borcfg.BorConfig), grpcAddr: grpcAddr, checkpointConfig: *checkpointConfig, spans: map[uint64]*span.HeimdallSpan{}, @@ -159,7 +162,7 @@ func (h *Heimdall) Span(ctx context.Context, spanID uint64) (*span.HeimdallSpan, nextSpan.StartBlock = h.currentSpan.EndBlock + 1 } - nextSpan.EndBlock = nextSpan.StartBlock + (100 * h.chainConfig.Bor.CalculateSprint(nextSpan.StartBlock)) - 1 + nextSpan.EndBlock = nextSpan.StartBlock + (100 * h.borConfig.CalculateSprintLength(nextSpan.StartBlock)) - 1 // TODO we should use a subset here - see: https://wiki.polygon.technology/docs/pos/bor/ @@ -183,10 +186,10 @@ func (h *Heimdall) Span(ctx context.Context, spanID uint64) (*span.HeimdallSpan, func (h *Heimdall) currentSprintLength() int { if h.currentSpan != nil { - return int(h.chainConfig.Bor.CalculateSprint(h.currentSpan.StartBlock)) + return int(h.borConfig.CalculateSprintLength(h.currentSpan.StartBlock)) } - return int(h.chainConfig.Bor.CalculateSprint(256)) + return int(h.borConfig.CalculateSprintLength(256)) } func (h *Heimdall) getSpanOverrideHeight() uint64 { diff --git a/cmd/rpcdaemon/cli/config.go b/cmd/rpcdaemon/cli/config.go index 18127a88e02..ed29b8a4d49 100644 --- a/cmd/rpcdaemon/cli/config.go +++ b/cmd/rpcdaemon/cli/config.go @@ -24,6 +24,7 @@ import ( libstate "github.com/ledgerwatch/erigon-lib/state" "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/consensus/bor" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "github.com/ledgerwatch/erigon/consensus/bor/contract" "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" "github.com/ledgerwatch/erigon/consensus/ethash" @@ -37,6 +38,13 @@ import ( "github.com/ledgerwatch/erigon/turbo/snapshotsync/freezeblocks" "github.com/ledgerwatch/erigon/turbo/snapshotsync/snap" + "github.com/ledgerwatch/log/v3" + "github.com/spf13/cobra" + "golang.org/x/sync/semaphore" + "google.golang.org/grpc" + grpcHealth "google.golang.org/grpc/health" + "google.golang.org/grpc/health/grpc_health_v1" + "github.com/ledgerwatch/erigon-lib/direct" "github.com/ledgerwatch/erigon-lib/gointerfaces" "github.com/ledgerwatch/erigon-lib/gointerfaces/grpcutil" @@ -47,12 +55,6 @@ import ( kv2 "github.com/ledgerwatch/erigon-lib/kv/mdbx" "github.com/ledgerwatch/erigon-lib/kv/remotedb" "github.com/ledgerwatch/erigon-lib/kv/remotedbserver" - "github.com/ledgerwatch/log/v3" - "github.com/spf13/cobra" - "golang.org/x/sync/semaphore" - "google.golang.org/grpc" - grpcHealth "google.golang.org/grpc/health" - "google.golang.org/grpc/health/grpc_health_v1" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/cli/httpcfg" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/graphql" @@ -502,9 +504,11 @@ func RemoteServices(ctx context.Context, cfg *httpcfg.HttpCfg, logger log.Logger } // Skip the compatibility check, until we have a schema in erigon-lib + borConfig := cc.Bor.(*borcfg.BorConfig) + engine = bor.NewRo(cc, borKv, blockReader, span.NewChainSpanner(contract.ValidatorSet(), cc, true, logger), - contract.NewGenesisContractsClient(cc, cc.Bor.ValidatorContract, cc.Bor.StateReceiverContract, logger), logger) + contract.NewGenesisContractsClient(cc, borConfig.ValidatorContract, borConfig.StateReceiverContract, logger), logger) default: engine = ethash.NewFaker() @@ -910,9 +914,11 @@ func (e *remoteConsensusEngine) init(db kv.RoDB, blockReader services.FullBlockR return false } + borConfig := cc.Bor.(*borcfg.BorConfig) + e.engine = bor.NewRo(cc, borKv, blockReader, span.NewChainSpanner(contract.ValidatorSet(), cc, true, logger), - contract.NewGenesisContractsClient(cc, cc.Bor.ValidatorContract, cc.Bor.StateReceiverContract, logger), logger) + contract.NewGenesisContractsClient(cc, borConfig.ValidatorContract, borConfig.StateReceiverContract, logger), logger) } else { e.engine = ethash.NewFaker() } diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index ed49c131b6d..aa62d4fffa0 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -28,6 +28,7 @@ import ( "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon/common" "github.com/ledgerwatch/erigon/consensus" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "github.com/ledgerwatch/erigon/consensus/bor/finality" "github.com/ledgerwatch/erigon/consensus/bor/finality/flags" "github.com/ledgerwatch/erigon/consensus/bor/finality/whitelist" @@ -141,7 +142,7 @@ var ( type SignerFn func(signer libcommon.Address, mimeType string, message []byte) ([]byte, error) // ecrecover extracts the Ethereum account address from a signed header. -func Ecrecover(header *types.Header, sigcache *lru.ARCCache[libcommon.Hash, libcommon.Address], c *chain.BorConfig) (libcommon.Address, error) { +func Ecrecover(header *types.Header, sigcache *lru.ARCCache[libcommon.Hash, libcommon.Address], c *borcfg.BorConfig) (libcommon.Address, error) { // If the signature's already cached, return that hash := header.Hash() if address, known := sigcache.Get(hash); known { @@ -168,7 +169,7 @@ func Ecrecover(header *types.Header, sigcache *lru.ARCCache[libcommon.Hash, libc } // SealHash returns the hash of a block prior to it being sealed. -func SealHash(header *types.Header, c *chain.BorConfig) (hash libcommon.Hash) { +func SealHash(header *types.Header, c *borcfg.BorConfig) (hash libcommon.Hash) { hasher := cryptopool.NewLegacyKeccak256() defer cryptopool.ReturnToPoolKeccak256(hasher) @@ -178,7 +179,7 @@ func SealHash(header *types.Header, c *chain.BorConfig) (hash libcommon.Hash) { return hash } -func encodeSigHeader(w io.Writer, header *types.Header, c *chain.BorConfig) { +func encodeSigHeader(w io.Writer, header *types.Header, c *borcfg.BorConfig) { enc := []interface{}{ header.ParentHash, header.UncleHash, @@ -209,11 +210,11 @@ func encodeSigHeader(w io.Writer, header *types.Header, c *chain.BorConfig) { } // CalcProducerDelay is the block delay algorithm based on block time, period, producerDelay and turn-ness of a signer -func CalcProducerDelay(number uint64, succession int, c *chain.BorConfig) uint64 { +func CalcProducerDelay(number uint64, succession int, c *borcfg.BorConfig) uint64 { // When the block is the first block of the sprint, it is expected to be delayed by `producerDelay`. // That is to allow time for block propagation in the last sprint delay := c.CalculatePeriod(number) - if number%c.CalculateSprint(number) == 0 { + if number%c.CalculateSprintLength(number) == 0 { delay = c.CalculateProducerDelay(number) } @@ -231,7 +232,7 @@ func CalcProducerDelay(number uint64, succession int, c *chain.BorConfig) uint64 // Note, the method requires the extra data to be at least 65 bytes, otherwise it // panics. This is done to avoid accidentally using both forms (signature present // or not), which could be abused to produce different hashes for the same header. -func BorRLP(header *types.Header, c *chain.BorConfig) []byte { +func BorRLP(header *types.Header, c *borcfg.BorConfig) []byte { b := new(bytes.Buffer) encodeSigHeader(b, header, c) @@ -240,9 +241,9 @@ func BorRLP(header *types.Header, c *chain.BorConfig) []byte { // Bor is the matic-bor consensus engine type Bor struct { - chainConfig *chain.Config // Chain config - config *chain.BorConfig // Consensus engine configuration parameters for bor consensus - DB kv.RwDB // Database to store and retrieve snapshot checkpoints + chainConfig *chain.Config // Chain config + config *borcfg.BorConfig // Consensus engine configuration parameters for bor consensus + DB kv.RwDB // Database to store and retrieve snapshot checkpoints blockReader services.FullBlockReader Recents *lru.ARCCache[libcommon.Hash, *Snapshot] // Snapshots for recent block to speed up reorgs @@ -273,95 +274,6 @@ type signer struct { signFn SignerFn // Signer function to authorize hashes with } -type sprint struct { - from, size uint64 -} - -type sprints []sprint - -func (s sprints) Len() int { - return len(s) -} - -func (s sprints) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -func (s sprints) Less(i, j int) bool { - return s[i].from < s[j].from -} - -func asSprints(configSprints map[string]uint64) sprints { - sprints := make(sprints, len(configSprints)) - - i := 0 - for key, value := range configSprints { - sprints[i].from, _ = strconv.ParseUint(key, 10, 64) - sprints[i].size = value - i++ - } - - sort.Sort(sprints) - - return sprints -} - -func CalculateSprintCount(config *chain.BorConfig, from, to uint64) int { - - switch { - case from > to: - return 0 - case from < to: - to-- - } - - sprints := asSprints(config.Sprint) - - count := uint64(0) - startCalc := from - - zeroth := func(boundary uint64, size uint64) uint64 { - if boundary%size == 0 { - return 1 - } - - return 0 - } - - for i := 0; i < len(sprints)-1; i++ { - if startCalc >= sprints[i].from && startCalc < sprints[i+1].from { - if to >= sprints[i].from && to < sprints[i+1].from { - if startCalc == to { - return int(count + zeroth(startCalc, sprints[i].size)) - } - return int(count + zeroth(startCalc, sprints[i].size) + (to-startCalc)/sprints[i].size) - } else { - endCalc := sprints[i+1].from - 1 - count += zeroth(startCalc, sprints[i].size) + (endCalc-startCalc)/sprints[i].size - startCalc = endCalc + 1 - } - } - } - - if startCalc == to { - return int(count + zeroth(startCalc, sprints[len(sprints)-1].size)) - } - - return int(count + zeroth(startCalc, sprints[len(sprints)-1].size) + (to-startCalc)/sprints[len(sprints)-1].size) -} - -func CalculateSprint(config *chain.BorConfig, number uint64) uint64 { - sprints := asSprints(config.Sprint) - - for i := 0; i < len(sprints)-1; i++ { - if number >= sprints[i].from && number < sprints[i+1].from { - return sprints[i].size - } - } - - return sprints[len(sprints)-1].size -} - // New creates a Matic Bor consensus engine. func New( chainConfig *chain.Config, @@ -373,10 +285,10 @@ func New( logger log.Logger, ) *Bor { // get bor config - borConfig := chainConfig.Bor + borConfig := chainConfig.Bor.(*borcfg.BorConfig) // Set any missing consensus parameters to their defaults - if borConfig != nil && borConfig.CalculateSprint(0) == 0 { + if borConfig != nil && borConfig.CalculateSprintLength(0) == 0 { borConfig.Sprint = defaultSprintLength } @@ -441,10 +353,10 @@ func (w rwWrapper) BeginRwNosync(ctx context.Context) (kv.RwTx, error) { func NewRo(chainConfig *chain.Config, db kv.RoDB, blockReader services.FullBlockReader, spanner Spanner, genesisContracts GenesisContract, logger log.Logger) *Bor { // get bor config - borConfig := chainConfig.Bor + borConfig := chainConfig.Bor.(*borcfg.BorConfig) // Set any missing consensus parameters to their defaults - if borConfig != nil && borConfig.CalculateSprint(0) == 0 { + if borConfig != nil && borConfig.CalculateSprintLength(0) == 0 { borConfig.Sprint = defaultSprintLength } @@ -469,6 +381,10 @@ func (c *Bor) Type() chain.ConsensusName { return chain.BorConsensus } +func (c *Bor) Config() *borcfg.BorConfig { + return c.config +} + type HeaderProgress interface { Progress() uint64 } @@ -533,7 +449,7 @@ func (c *Bor) verifyHeader(chain consensus.ChainHeaderReader, header *types.Head } // check extr adata - isSprintEnd := isSprintStart(number+1, c.config.CalculateSprint(number)) + isSprintEnd := isSprintStart(number+1, c.config.CalculateSprintLength(number)) // Ensure that the extra-data contains a signer list on checkpoint, but none otherwise signersBytes := len(GetValidatorBytes(header, c.config)) @@ -889,7 +805,7 @@ func (c *Bor) verifySeal(chain consensus.ChainHeaderReader, header *types.Header return nil } -func IsBlockOnTime(parent *types.Header, header *types.Header, number uint64, succession int, cfg *chain.BorConfig) bool { +func IsBlockOnTime(parent *types.Header, header *types.Header, number uint64, succession int, cfg *borcfg.BorConfig) bool { return parent != nil && header.Time < parent.Time+CalcProducerDelay(number, succession, cfg) } @@ -922,7 +838,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header, s // client calls `GetCurrentValidators` because it makes a contract call // where it fetches producers internally. As we fetch data from span // in Erigon, use directly the `GetCurrentProducers` function. - if isSprintStart(number+1, c.config.CalculateSprint(number)) { + if isSprintStart(number+1, c.config.CalculateSprintLength(number)) { spanID := span.IDAt(number + 1) newValidators, err := c.spanner.GetCurrentProducers(spanID, c.authorizedSigner.Load().signer, chain) if err != nil { @@ -1017,7 +933,7 @@ func (c *Bor) Finalize(config *chain.Config, header *types.Header, state *state. return nil, nil, consensus.ErrUnexpectedWithdrawals } - if isSprintStart(headerNumber, c.config.CalculateSprint(headerNumber)) { + if isSprintStart(headerNumber, c.config.CalculateSprintLength(headerNumber)) { cx := statefull.ChainContext{Chain: chain, Bor: c} if c.blockReader != nil { @@ -1083,7 +999,7 @@ func (c *Bor) FinalizeAndAssemble(chainConfig *chain.Config, header *types.Heade return nil, nil, nil, consensus.ErrUnexpectedWithdrawals } - if isSprintStart(headerNumber, c.config.CalculateSprint(headerNumber)) { + if isSprintStart(headerNumber, c.config.CalculateSprintLength(headerNumber)) { cx := statefull.ChainContext{Chain: chain, Bor: c} if c.blockReader != nil { @@ -1378,7 +1294,7 @@ func (c *Bor) needToCommitSpan(currentSpan *span.Span, headerNumber uint64) bool if currentSpan.EndBlock == 0 { return true } - sprintLength := c.config.CalculateSprint(headerNumber) + sprintLength := c.config.CalculateSprintLength(headerNumber) // if current block is first block of last sprint in current span if currentSpan.EndBlock > sprintLength && currentSpan.EndBlock-sprintLength+1 == headerNumber { @@ -1542,7 +1458,7 @@ func (c *Bor) getNextHeimdallSpanForTest( spanBor.StartBlock = spanBor.EndBlock + 1 } - spanBor.EndBlock = spanBor.StartBlock + (100 * c.config.CalculateSprint(headerNumber)) - 1 + spanBor.EndBlock = spanBor.StartBlock + (100 * c.config.CalculateSprintLength(headerNumber)) - 1 selectedProducers := make([]valset.Validator, len(snap.ValidatorSet.Validators)) for i, v := range snap.ValidatorSet.Validators { @@ -1632,7 +1548,7 @@ func GetTxDependency(b *types.Block) [][]uint64 { return blockExtraData.TxDependency } -func GetValidatorBytes(h *types.Header, config *chain.BorConfig) []byte { +func GetValidatorBytes(h *types.Header, config *borcfg.BorConfig) []byte { tempExtra := h.Extra if !config.IsParallelUniverse(h.Number.Uint64()) { diff --git a/consensus/bor/bor_test.go b/consensus/bor/bor_test.go index 373b3bd10d5..54744a7301f 100644 --- a/consensus/bor/bor_test.go +++ b/consensus/bor/bor_test.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "math/big" "testing" @@ -34,12 +35,23 @@ import ( type test_heimdall struct { currentSpan *span.HeimdallSpan chainConfig *chain.Config + borConfig *borcfg.BorConfig validatorSet *valset.ValidatorSet spans map[uint64]*span.HeimdallSpan } func newTestHeimdall(chainConfig *chain.Config) *test_heimdall { - return &test_heimdall{nil, chainConfig, nil, map[uint64]*span.HeimdallSpan{}} + return &test_heimdall{ + currentSpan: nil, + chainConfig: chainConfig, + borConfig: chainConfig.Bor.(*borcfg.BorConfig), + validatorSet: nil, + spans: map[uint64]*span.HeimdallSpan{}, + } +} + +func (h *test_heimdall) BorConfig() *borcfg.BorConfig { + return h.borConfig } func (h test_heimdall) StateSyncEvents(ctx context.Context, fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error) { @@ -67,7 +79,7 @@ func (h *test_heimdall) Span(ctx context.Context, spanID uint64) (*span.Heimdall nextSpan.StartBlock = h.currentSpan.EndBlock + 1 } - nextSpan.EndBlock = nextSpan.StartBlock + (100 * h.chainConfig.Bor.CalculateSprint(nextSpan.StartBlock)) - 1 + nextSpan.EndBlock = nextSpan.StartBlock + (100 * h.borConfig.CalculateSprintLength(nextSpan.StartBlock)) - 1 // TODO we should use a subset here - see: https://wiki.polygon.technology/docs/pos/bor/ @@ -91,10 +103,10 @@ func (h *test_heimdall) Span(ctx context.Context, spanID uint64) (*span.Heimdall func (h test_heimdall) currentSprintLength() int { if h.currentSpan != nil { - return int(h.chainConfig.Bor.CalculateSprint(h.currentSpan.StartBlock)) + return int(h.borConfig.CalculateSprintLength(h.currentSpan.StartBlock)) } - return int(h.chainConfig.Bor.CalculateSprint(256)) + return int(h.borConfig.CalculateSprintLength(256)) } func (h test_heimdall) FetchCheckpoint(ctx context.Context, number int64) (*checkpoint.Checkpoint, error) { @@ -346,11 +358,11 @@ func TestVerifyRun(t *testing.T) { } func TestVerifySprint(t *testing.T) { - //testVerify(t, 10, 4, int(params.BorDevnetChainConfig.Bor.CalculateSprint(256))) + //testVerify(t, 10, 4, int(params.BorDevnetChainConfig.Bor.CalculateSprintLength(256))) } func TestVerifySpan(t *testing.T) { - //testVerify(t, 10, 4 /*100**/ *int(params.BorDevnetChainConfig.Bor.CalculateSprint(256))) + //testVerify(t, 10, 4 /*100**/ *int(params.BorDevnetChainConfig.Bor.CalculateSprintLength(256))) } func testVerify(t *testing.T, noValidators int, chainLength int) { @@ -392,7 +404,7 @@ func testVerify(t *testing.T, noValidators int, chainLength int) { if isProposer { if vi != lastProposerIndex { - sprintLen := params.BorDevnetChainConfig.Bor.CalculateSprint(block.NumberU64()) + sprintLen := heimdall.BorConfig().CalculateSprintLength(block.NumberU64()) if block.NumberU64() > 1 && block.NumberU64()%sprintLen != 0 { t.Fatalf("Unexpected sprint boundary at %d for: %d", bi, block.NumberU64()) } diff --git a/consensus/bor/borcfg/bor_config.go b/consensus/bor/borcfg/bor_config.go new file mode 100644 index 00000000000..d73f20a830a --- /dev/null +++ b/consensus/bor/borcfg/bor_config.go @@ -0,0 +1,196 @@ +package borcfg + +import ( + "math/big" + "sort" + "strconv" + + "github.com/ledgerwatch/erigon-lib/common" +) + +// BorConfig is the consensus engine configs for Matic bor based sealing. +type BorConfig struct { + Period map[string]uint64 `json:"period"` // Number of seconds between blocks to enforce + ProducerDelay map[string]uint64 `json:"producerDelay"` // Number of seconds delay between two producer interval + Sprint map[string]uint64 `json:"sprint"` // Epoch length to proposer + BackupMultiplier map[string]uint64 `json:"backupMultiplier"` // Backup multiplier to determine the wiggle time + ValidatorContract string `json:"validatorContract"` // Validator set contract + StateReceiverContract string `json:"stateReceiverContract"` // State receiver contract + + OverrideStateSyncRecords map[string]int `json:"overrideStateSyncRecords"` // override state records count + BlockAlloc map[string]interface{} `json:"blockAlloc"` + + JaipurBlock *big.Int `json:"jaipurBlock"` // Jaipur switch block (nil = no fork, 0 = already on jaipur) + DelhiBlock *big.Int `json:"delhiBlock"` // Delhi switch block (nil = no fork, 0 = already on delhi) + IndoreBlock *big.Int `json:"indoreBlock"` // Indore switch block (nil = no fork, 0 = already on indore) + AgraBlock *big.Int `json:"agraBlock"` // Agra switch block (nil = no fork, 0 = already in agra) + StateSyncConfirmationDelay map[string]uint64 `json:"stateSyncConfirmationDelay"` // StateSync Confirmation Delay, in seconds, to calculate `to` + + ParallelUniverseBlock *big.Int `json:"parallelUniverseBlock"` // TODO: update all occurrence, change name and finalize number (hardfork for block-stm related changes) + + sprints sprints +} + +// String implements the stringer interface, returning the consensus engine details. +func (c *BorConfig) String() string { + return "bor" +} + +func (c *BorConfig) CalculateProducerDelay(number uint64) uint64 { + return borKeyValueConfigHelper(c.ProducerDelay, number) +} + +func (c *BorConfig) CalculateSprintLength(number uint64) uint64 { + if c.sprints == nil { + c.sprints = asSprints(c.Sprint) + } + + for i := 0; i < len(c.sprints)-1; i++ { + if number >= c.sprints[i].from && number < c.sprints[i+1].from { + return c.sprints[i].size + } + } + + return c.sprints[len(c.sprints)-1].size +} + +func (c *BorConfig) CalculateSprintNumber(number uint64) uint64 { + if c.sprints == nil { + c.sprints = asSprints(c.Sprint) + } + + // unknown sprint size + if (len(c.sprints) == 0) || (number < c.sprints[0].from) { + return 0 + } + + // remove sprint configs that are not in effect yet + sprints := c.sprints + for number < sprints[len(sprints)-1].from { + sprints = sprints[:len(sprints)-1] + } + + var count uint64 + end := number + for len(sprints) > 0 { + sprint := sprints[len(sprints)-1] + count += (end - sprint.from) / sprint.size + + sprints = sprints[:len(sprints)-1] + end = sprint.from + } + + if c.sprints[0].from > 0 { + count++ + } + return count +} + +func (c *BorConfig) CalculateBackupMultiplier(number uint64) uint64 { + return borKeyValueConfigHelper(c.BackupMultiplier, number) +} + +func (c *BorConfig) CalculatePeriod(number uint64) uint64 { + return borKeyValueConfigHelper(c.Period, number) +} + +// isForked returns whether a fork scheduled at block s is active at the given head block. +func isForked(s *big.Int, head uint64) bool { + if s == nil { + return false + } + return s.Uint64() <= head +} + +func (c *BorConfig) IsJaipur(number uint64) bool { + return isForked(c.JaipurBlock, number) +} + +func (c *BorConfig) IsDelhi(number uint64) bool { + return isForked(c.DelhiBlock, number) +} + +func (c *BorConfig) IsIndore(number uint64) bool { + return isForked(c.IndoreBlock, number) +} + +// IsAgra returns whether num is either equal to the Agra fork block or greater. +// The Agra hard fork is based on the Shanghai hard fork, but it doesn't include withdrawals. +// Also Agra is activated based on the block number rather than the timestamp. +// Refer to https://forum.polygon.technology/t/pip-28-agra-hardfork +func (c *BorConfig) IsAgra(num uint64) bool { + return isForked(c.AgraBlock, num) +} + +func (c *BorConfig) GetAgraBlock() *big.Int { + return c.AgraBlock +} + +// TODO: modify this function once the block number is finalized +func (c *BorConfig) IsParallelUniverse(number uint64) bool { + if c.ParallelUniverseBlock != nil { + if c.ParallelUniverseBlock.Cmp(big.NewInt(0)) == 0 { + return false + } + } + + return isForked(c.ParallelUniverseBlock, number) +} + +func (c *BorConfig) CalculateStateSyncDelay(number uint64) uint64 { + return borKeyValueConfigHelper(c.StateSyncConfirmationDelay, number) +} + +func borKeyValueConfigHelper[T uint64 | common.Address](field map[string]T, number uint64) T { + fieldUint := make(map[uint64]T) + for k, v := range field { + keyUint, err := strconv.ParseUint(k, 10, 64) + if err != nil { + panic(err) + } + fieldUint[keyUint] = v + } + + keys := common.SortedKeys(fieldUint) + + for i := 0; i < len(keys)-1; i++ { + if number >= keys[i] && number < keys[i+1] { + return fieldUint[keys[i]] + } + } + + return fieldUint[keys[len(keys)-1]] +} + +type sprint struct { + from, size uint64 +} + +type sprints []sprint + +func (s sprints) Len() int { + return len(s) +} + +func (s sprints) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +func (s sprints) Less(i, j int) bool { + return s[i].from < s[j].from +} + +func asSprints(configSprints map[string]uint64) sprints { + sprints := make(sprints, len(configSprints)) + + i := 0 + for key, value := range configSprints { + sprints[i].from, _ = strconv.ParseUint(key, 10, 64) + sprints[i].size = value + i++ + } + + sort.Sort(sprints) + + return sprints +} diff --git a/consensus/bor/borcfg/bor_config_test.go b/consensus/bor/borcfg/bor_config_test.go new file mode 100644 index 00000000000..26109597b27 --- /dev/null +++ b/consensus/bor/borcfg/bor_config_test.go @@ -0,0 +1,47 @@ +package borcfg + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestCalculateSprintNumber(t *testing.T) { + cfg := BorConfig{ + Sprint: map[string]uint64{ + "0": 64, + "256": 16, + }, + } + + examples := map[uint64]uint64{ + 0: 0, + 1: 0, + 2: 0, + 63: 0, + 64: 1, + 65: 1, + 66: 1, + 127: 1, + 128: 2, + 191: 2, + 192: 3, + 255: 3, + 256: 4, + 257: 4, + 258: 4, + 271: 4, + 272: 5, + 273: 5, + 274: 5, + 287: 5, + 288: 6, + 303: 6, + 304: 7, + 319: 7, + 320: 8, + } + + for blockNumber, expectedSprintNumber := range examples { + assert.Equal(t, expectedSprintNumber, cfg.CalculateSprintNumber(blockNumber), blockNumber) + } +} diff --git a/consensus/bor/heimdall/span/span_id.go b/consensus/bor/heimdall/span/span_id.go index 7c4113bf848..50955212867 100644 --- a/consensus/bor/heimdall/span/span_id.go +++ b/consensus/bor/heimdall/span/span_id.go @@ -1,6 +1,8 @@ package span -import "github.com/ledgerwatch/erigon-lib/chain" +import ( + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" +) const ( spanLength = 6400 // Number of blocks in a span @@ -24,10 +26,10 @@ func EndBlockNum(spanID uint64) uint64 { } // BlockInLastSprintOfSpan returns true if a block num is within the last sprint of a span and false otherwise. -func BlockInLastSprintOfSpan(blockNum uint64, config *chain.BorConfig) bool { +func BlockInLastSprintOfSpan(blockNum uint64, config *borcfg.BorConfig) bool { spanNum := IDAt(blockNum) endBlockNum := EndBlockNum(spanNum) - sprintLen := config.CalculateSprint(blockNum) + sprintLen := config.CalculateSprintLength(blockNum) startBlockNum := endBlockNum - sprintLen + 1 return startBlockNum <= blockNum && blockNum <= endBlockNum } diff --git a/consensus/bor/heimdall/span/span_id_test.go b/consensus/bor/heimdall/span/span_id_test.go index 8ab45ed425d..a7c80891c7c 100644 --- a/consensus/bor/heimdall/span/span_id_test.go +++ b/consensus/bor/heimdall/span/span_id_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/ledgerwatch/erigon-lib/chain" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" ) func TestSpanIDAt(t *testing.T) { @@ -31,7 +31,7 @@ func TestSpanEndBlockNum(t *testing.T) { } func TestBlockInLastSprintOfSpan(t *testing.T) { - config := &chain.BorConfig{ + config := &borcfg.BorConfig{ Sprint: map[string]uint64{ "0": 16, }, diff --git a/consensus/bor/heimdall/span/spanner.go b/consensus/bor/heimdall/span/spanner.go index b3738c4774c..9af95abf718 100644 --- a/consensus/bor/heimdall/span/spanner.go +++ b/consensus/bor/heimdall/span/spanner.go @@ -5,26 +5,31 @@ import ( "encoding/json" "math/big" + "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/consensus/bor/abi" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "github.com/ledgerwatch/erigon/consensus/bor/valset" "github.com/ledgerwatch/erigon/rlp" - "github.com/ledgerwatch/log/v3" ) type ChainSpanner struct { validatorSet abi.ABI chainConfig *chain.Config + borConfig *borcfg.BorConfig logger log.Logger withoutHeimdall bool } func NewChainSpanner(validatorSet abi.ABI, chainConfig *chain.Config, withoutHeimdall bool, logger log.Logger) *ChainSpanner { + borConfig := chainConfig.Bor.(*borcfg.BorConfig) return &ChainSpanner{ validatorSet: validatorSet, chainConfig: chainConfig, + borConfig: borConfig, logger: logger, withoutHeimdall: withoutHeimdall, } @@ -42,7 +47,7 @@ func (c *ChainSpanner) GetCurrentSpan(syscall consensus.SystemCall) (*Span, erro return nil, err } - result, err := syscall(libcommon.HexToAddress(c.chainConfig.Bor.ValidatorContract), data) + result, err := syscall(libcommon.HexToAddress(c.borConfig.ValidatorContract), data) if err != nil { return nil, err } @@ -149,7 +154,7 @@ func (c *ChainSpanner) CommitSpan(heimdallSpan HeimdallSpan, syscall consensus.S return err } - _, err = syscall(libcommon.HexToAddress(c.chainConfig.Bor.ValidatorContract), data) + _, err = syscall(libcommon.HexToAddress(c.borConfig.ValidatorContract), data) return err } diff --git a/consensus/bor/snapshot.go b/consensus/bor/snapshot.go index 836acf36343..8eabd324172 100644 --- a/consensus/bor/snapshot.go +++ b/consensus/bor/snapshot.go @@ -6,17 +6,18 @@ import ( "encoding/json" lru "github.com/hashicorp/golang-lru/arc/v2" - "github.com/ledgerwatch/erigon-lib/chain" + "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "github.com/ledgerwatch/erigon/consensus/bor/valset" "github.com/ledgerwatch/erigon/core/types" - "github.com/ledgerwatch/log/v3" ) // Snapshot is the state of the authorization voting at a given point in time. type Snapshot struct { - config *chain.BorConfig // Consensus engine parameters to fine tune behavior + config *borcfg.BorConfig // Consensus engine parameters to fine tune behavior sigcache *lru.ARCCache[common.Hash, common.Address] // Cache of recent block signatures to speed up ecrecover Number uint64 `json:"number"` // Block number where the snapshot was created @@ -38,7 +39,7 @@ const BorSeparate = "BorSeparate" // method does not initialize the set of recent signers, so only ever use if for // the genesis block. func NewSnapshot( - config *chain.BorConfig, + config *borcfg.BorConfig, sigcache *lru.ARCCache[common.Hash, common.Address], number uint64, hash common.Hash, @@ -57,7 +58,7 @@ func NewSnapshot( } // loadSnapshot loads an existing snapshot from the database. -func LoadSnapshot(config *chain.BorConfig, sigcache *lru.ARCCache[common.Hash, common.Address], db kv.RwDB, hash common.Hash) (*Snapshot, error) { +func LoadSnapshot(config *borcfg.BorConfig, sigcache *lru.ARCCache[common.Hash, common.Address], db kv.RwDB, hash common.Hash) (*Snapshot, error) { tx, err := db.BeginRo(context.Background()) if err != nil { return nil, err @@ -139,7 +140,7 @@ func (s *Snapshot) Apply(parent *types.Header, headers []*types.Header, logger l for _, header := range headers { // Remove any votes on checkpoint blocks number := header.Number.Uint64() - sprintLen := s.config.CalculateSprint(number) + sprintLen := s.config.CalculateSprintLength(number) // Delete the oldest signer from the recent list to allow it signing again if number >= sprintLen { @@ -244,18 +245,9 @@ func (s *Snapshot) Difficulty(signer common.Address) uint64 { return 1 } - validators := s.ValidatorSet.Validators - proposer := s.ValidatorSet.GetProposer().Address - totalValidators := len(validators) - - proposerIndex, _ := s.ValidatorSet.GetByAddress(proposer) - signerIndex, _ := s.ValidatorSet.GetByAddress(signer) - - // temp index - tempIndex := signerIndex - if tempIndex < proposerIndex { - tempIndex = tempIndex + totalValidators + if d, err := s.ValidatorSet.Difficulty(signer); err == nil { + return d + } else { + return 0 } - - return uint64(totalValidators - (tempIndex - proposerIndex)) } diff --git a/consensus/bor/valset/validator_set.go b/consensus/bor/valset/validator_set.go index de2792d5285..4f540dc8e1e 100644 --- a/consensus/bor/valset/validator_set.go +++ b/consensus/bor/valset/validator_set.go @@ -4,14 +4,16 @@ package valset import ( "bytes" + "errors" "fmt" "math" "math/big" "sort" "strings" - libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/log/v3" + + libcommon "github.com/ledgerwatch/erigon-lib/common" ) // MaxTotalVotingPower - the maximum allowed total voting power. @@ -656,6 +658,30 @@ func (vals *ValidatorSet) UpdateWithChangeSet(changes []*Validator, logger log.L return vals.updateWithChangeSet(changes, true, logger) } +// Difficulty returns the difficulty for a particular signer at the current snapshot number +func (vals *ValidatorSet) Difficulty(signer libcommon.Address) (uint64, error) { + proposer := vals.GetProposer() + if proposer == nil { + return 0, errors.New("ValidatorSet.Difficulty: proposer not found") + } + + proposerIndex, _ := vals.GetByAddress(proposer.Address) + if proposerIndex < 0 { + return 0, errors.New("ValidatorSet.Difficulty: proposer index not found") + } + + signerIndex, _ := vals.GetByAddress(signer) + if signerIndex < 0 { + return 0, errors.New("ValidatorSet.Difficulty: signer index not found") + } + + indexDiff := signerIndex - proposerIndex + if indexDiff < 0 { + indexDiff += len(vals.Validators) + } + return uint64(len(vals.Validators) - indexDiff), nil +} + //----------------- // ErrTooMuchChange diff --git a/consensus/misc/eip1559.go b/consensus/misc/eip1559.go index 8cd278b253b..e7729a4bef9 100644 --- a/consensus/misc/eip1559.go +++ b/consensus/misc/eip1559.go @@ -22,6 +22,7 @@ import ( "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "github.com/ledgerwatch/erigon/common/math" "github.com/ledgerwatch/erigon/core/types" @@ -96,9 +97,9 @@ func CalcBaseFee(config *chain.Config, parent *types.Header) *big.Int { } } -func getBaseFeeChangeDenominator(borConfig *chain.BorConfig, number uint64) uint64 { +func getBaseFeeChangeDenominator(borConfig chain.BorConfig, number uint64) uint64 { // If we're running bor based chain post delhi hardfork, return the new value - if borConfig != nil && borConfig.IsDelhi(number) { + if borConfig, ok := borConfig.(*borcfg.BorConfig); ok && borConfig.IsDelhi(number) { return params.BaseFeeChangeDenominatorPostDelhi } diff --git a/core/forkid/forkid.go b/core/forkid/forkid.go index 433c9221b18..f5c51cb3c1e 100644 --- a/core/forkid/forkid.go +++ b/core/forkid/forkid.go @@ -244,8 +244,8 @@ func GatherForks(config *chain.Config, genesisTime uint64) (heightForks []uint64 heightForks = append(heightForks, *config.Aura.PosdaoTransition) } - if config.Bor != nil && config.Bor.AgraBlock != nil { - heightForks = append(heightForks, config.Bor.AgraBlock.Uint64()) + if config.Bor != nil && config.Bor.GetAgraBlock() != nil { + heightForks = append(heightForks, config.Bor.GetAgraBlock().Uint64()) } // Sort the fork block numbers & times to permit chronological XOR diff --git a/core/rawdb/accessors_metadata.go b/core/rawdb/accessors_metadata.go index d93691c723d..c2ee9218bca 100644 --- a/core/rawdb/accessors_metadata.go +++ b/core/rawdb/accessors_metadata.go @@ -19,6 +19,7 @@ package rawdb import ( "encoding/json" "fmt" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" @@ -34,10 +35,20 @@ func ReadChainConfig(db kv.Getter, hash libcommon.Hash) (*chain.Config, error) { if len(data) == 0 { return nil, nil } + var config chain.Config if err := json.Unmarshal(data, &config); err != nil { return nil, fmt.Errorf("invalid chain config JSON: %x, %w", hash, err) } + + if config.BorJSON != nil { + borConfig := &borcfg.BorConfig{} + if err := json.Unmarshal(config.BorJSON, borConfig); err != nil { + return nil, fmt.Errorf("invalid chain config 'bor' JSON: %x, %w", hash, err) + } + config.Bor = borConfig + } + return &config, nil } @@ -46,10 +57,20 @@ func WriteChainConfig(db kv.Putter, hash libcommon.Hash, cfg *chain.Config) erro if cfg == nil { return nil } + + if cfg.Bor != nil { + borJSON, err := json.Marshal(cfg.Bor) + if err != nil { + return fmt.Errorf("failed to JSON encode chain config 'bor': %w", err) + } + cfg.BorJSON = borJSON + } + data, err := json.Marshal(cfg) if err != nil { return fmt.Errorf("failed to JSON encode chain config: %w", err) } + if err := db.Put(kv.ConfigTable, hash[:], data); err != nil { return fmt.Errorf("failed to store chain config: %w", err) } diff --git a/core/system_contract_lookup.go b/core/system_contract_lookup.go index 2905904a2d3..6b6908dda69 100644 --- a/core/system_contract_lookup.go +++ b/core/system_contract_lookup.go @@ -7,6 +7,7 @@ import ( "github.com/ledgerwatch/erigon-lib/chain/networkname" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/hexutility" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "github.com/ledgerwatch/erigon/core/systemcontracts" "github.com/ledgerwatch/erigon/core/types" @@ -23,7 +24,8 @@ func init() { allocToCodeRecords(genesisBlock.Alloc, byChain, 0) // Process upgrades chainConfig := params.ChainConfigByChainName(chainName) - for blockNumStr, genesisAlloc := range chainConfig.Bor.BlockAlloc { + borConfig := chainConfig.Bor.(*borcfg.BorConfig) + for blockNumStr, genesisAlloc := range borConfig.BlockAlloc { blockNum, err := strconv.ParseUint(blockNumStr, 10, 64) if err != nil { panic(fmt.Errorf("failed to parse block number in BlockAlloc: %s", err.Error())) diff --git a/erigon-lib/chain/chain_config.go b/erigon-lib/chain/chain_config.go index cecba46e21c..cc8fe6d9468 100644 --- a/erigon-lib/chain/chain_config.go +++ b/erigon-lib/chain/chain_config.go @@ -17,9 +17,9 @@ package chain import ( + "encoding/json" "fmt" "math/big" - "sort" "strconv" "github.com/ledgerwatch/erigon-lib/common" @@ -81,7 +81,15 @@ type Config struct { Ethash *EthashConfig `json:"ethash,omitempty"` Clique *CliqueConfig `json:"clique,omitempty"` Aura *AuRaConfig `json:"aura,omitempty"` - Bor *BorConfig `json:"bor,omitempty"` + + Bor BorConfig `json:"-"` + BorJSON json.RawMessage `json:"bor,omitempty"` +} + +type BorConfig interface { + fmt.Stringer + IsAgra(num uint64) bool + GetAgraBlock() *big.Int } func (c *Config) String() string { @@ -203,10 +211,7 @@ func (c *Config) IsShanghai(time uint64) bool { // Also Agra is activated based on the block number rather than the timestamp. // Refer to https://forum.polygon.technology/t/pip-28-agra-hardfork func (c *Config) IsAgra(num uint64) bool { - if c == nil || c.Bor == nil { - return false - } - return isForked(c.Bor.AgraBlock, num) + return (c != nil) && (c.Bor != nil) && c.Bor.IsAgra(num) } // IsCancun returns whether time is either equal to the Cancun fork time or greater. @@ -452,132 +457,6 @@ func (c *CliqueConfig) String() string { return "clique" } -// BorConfig is the consensus engine configs for Matic bor based sealing. -type BorConfig struct { - Period map[string]uint64 `json:"period"` // Number of seconds between blocks to enforce - ProducerDelay map[string]uint64 `json:"producerDelay"` // Number of seconds delay between two producer interval - Sprint map[string]uint64 `json:"sprint"` // Epoch length to proposer - BackupMultiplier map[string]uint64 `json:"backupMultiplier"` // Backup multiplier to determine the wiggle time - ValidatorContract string `json:"validatorContract"` // Validator set contract - StateReceiverContract string `json:"stateReceiverContract"` // State receiver contract - - OverrideStateSyncRecords map[string]int `json:"overrideStateSyncRecords"` // override state records count - BlockAlloc map[string]interface{} `json:"blockAlloc"` - - JaipurBlock *big.Int `json:"jaipurBlock"` // Jaipur switch block (nil = no fork, 0 = already on jaipur) - DelhiBlock *big.Int `json:"delhiBlock"` // Delhi switch block (nil = no fork, 0 = already on delhi) - IndoreBlock *big.Int `json:"indoreBlock"` // Indore switch block (nil = no fork, 0 = already on indore) - AgraBlock *big.Int `json:"agraBlock"` // Agra switch block (nil = no fork, 0 = already in agra) - StateSyncConfirmationDelay map[string]uint64 `json:"stateSyncConfirmationDelay"` // StateSync Confirmation Delay, in seconds, to calculate `to` - - ParallelUniverseBlock *big.Int `json:"parallelUniverseBlock"` // TODO: update all occurrence, change name and finalize number (hardfork for block-stm related changes) - - sprints sprints -} - -// String implements the stringer interface, returning the consensus engine details. -func (c *BorConfig) String() string { - return "bor" -} - -func (c *BorConfig) CalculateProducerDelay(number uint64) uint64 { - return borKeyValueConfigHelper(c.ProducerDelay, number) -} - -func (c *BorConfig) CalculateSprint(number uint64) uint64 { - if c.sprints == nil { - c.sprints = asSprints(c.Sprint) - } - - for i := 0; i < len(c.sprints)-1; i++ { - if number >= c.sprints[i].from && number < c.sprints[i+1].from { - return c.sprints[i].size - } - } - - return c.sprints[len(c.sprints)-1].size -} - -func (c *BorConfig) CalculateSprintCount(from, to uint64) int { - switch { - case from > to: - return 0 - case from < to: - to-- - } - - if c.sprints == nil { - c.sprints = asSprints(c.Sprint) - } - - count := uint64(0) - startCalc := from - - zeroth := func(boundary uint64, size uint64) uint64 { - if boundary%size == 0 { - return 1 - } - - return 0 - } - - for i := 0; i < len(c.sprints)-1; i++ { - if startCalc >= c.sprints[i].from && startCalc < c.sprints[i+1].from { - if to >= c.sprints[i].from && to < c.sprints[i+1].from { - if startCalc == to { - return int(count + zeroth(startCalc, c.sprints[i].size)) - } - return int(count + zeroth(startCalc, c.sprints[i].size) + (to-startCalc)/c.sprints[i].size) - } else { - endCalc := c.sprints[i+1].from - 1 - count += zeroth(startCalc, c.sprints[i].size) + (endCalc-startCalc)/c.sprints[i].size - startCalc = endCalc + 1 - } - } - } - - if startCalc == to { - return int(count + zeroth(startCalc, c.sprints[len(c.sprints)-1].size)) - } - - return int(count + zeroth(startCalc, c.sprints[len(c.sprints)-1].size) + (to-startCalc)/c.sprints[len(c.sprints)-1].size) -} - -func (c *BorConfig) CalculateBackupMultiplier(number uint64) uint64 { - return borKeyValueConfigHelper(c.BackupMultiplier, number) -} - -func (c *BorConfig) CalculatePeriod(number uint64) uint64 { - return borKeyValueConfigHelper(c.Period, number) -} - -func (c *BorConfig) IsJaipur(number uint64) bool { - return isForked(c.JaipurBlock, number) -} - -func (c *BorConfig) IsDelhi(number uint64) bool { - return isForked(c.DelhiBlock, number) -} - -func (c *BorConfig) IsIndore(number uint64) bool { - return isForked(c.IndoreBlock, number) -} - -// TODO: modify this function once the block number is finalized -func (c *BorConfig) IsParallelUniverse(number uint64) bool { - if c.ParallelUniverseBlock != nil { - if c.ParallelUniverseBlock.Cmp(big.NewInt(0)) == 0 { - return false - } - } - - return isForked(c.ParallelUniverseBlock, number) -} - -func (c *BorConfig) CalculateStateSyncDelay(number uint64) uint64 { - return borKeyValueConfigHelper(c.StateSyncConfirmationDelay, number) -} - func borKeyValueConfigHelper[T uint64 | common.Address](field map[string]T, number uint64) T { fieldUint := make(map[uint64]T) for k, v := range field { @@ -599,39 +478,6 @@ func borKeyValueConfigHelper[T uint64 | common.Address](field map[string]T, numb return fieldUint[keys[len(keys)-1]] } -type sprint struct { - from, size uint64 -} - -type sprints []sprint - -func (s sprints) Len() int { - return len(s) -} - -func (s sprints) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -func (s sprints) Less(i, j int) bool { - return s[i].from < s[j].from -} - -func asSprints(configSprints map[string]uint64) sprints { - sprints := make(sprints, len(configSprints)) - - i := 0 - for key, value := range configSprints { - sprints[i].from, _ = strconv.ParseUint(key, 10, 64) - sprints[i].size = value - i++ - } - - sort.Sort(sprints) - - return sprints -} - // Rules is syntactic sugar over Config. It can be used for functions // that do not have or require information about the block. // diff --git a/erigon-lib/common/collections.go b/erigon-lib/common/collections.go new file mode 100644 index 00000000000..1e5a13856d2 --- /dev/null +++ b/erigon-lib/common/collections.go @@ -0,0 +1,15 @@ +package common + +func SliceReverse[T any](s []T) { + for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { + s[i], s[j] = s[j], s[i] + } +} + +func SliceMap[T any, U any](s []T, mapFunc func(T) U) []U { + out := make([]U, 0, len(s)) + for _, x := range s { + out = append(out, mapFunc(x)) + } + return out +} diff --git a/erigon-lib/txpool/txpooluitl/all_components.go b/erigon-lib/txpool/txpooluitl/all_components.go index ffa6fdf0310..156a5771c2b 100644 --- a/erigon-lib/txpool/txpooluitl/all_components.go +++ b/erigon-lib/txpool/txpooluitl/all_components.go @@ -137,7 +137,7 @@ func AllComponents(ctx context.Context, cfg txpoolcfg.Config, cache kvcache.Cach shanghaiTime := chainConfig.ShanghaiTime var agraBlock *big.Int if chainConfig.Bor != nil { - agraBlock = chainConfig.Bor.AgraBlock + agraBlock = chainConfig.Bor.GetAgraBlock() } cancunTime := chainConfig.CancunTime if cfg.OverrideCancunTime != nil { diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 61274a41939..47ee3501560 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -27,12 +27,14 @@ import ( "time" "github.com/c2h5oh/datasize" + "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon-lib/chain/networkname" "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/datadir" "github.com/ledgerwatch/erigon-lib/downloader/downloadercfg" "github.com/ledgerwatch/erigon-lib/txpool/txpoolcfg" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "github.com/ledgerwatch/erigon/cl/beacon/beacon_router_configuration" "github.com/ledgerwatch/erigon/cl/clparams" @@ -209,7 +211,7 @@ type Config struct { Clique params.ConsensusSnapshotConfig Aura chain.AuRaConfig - Bor chain.BorConfig + Bor borcfg.BorConfig // Transaction pool options DeprecatedTxPool DeprecatedTxPoolConfig diff --git a/eth/ethconsensusconfig/config.go b/eth/ethconsensusconfig/config.go index 72ff681393e..04bf7cc08c1 100644 --- a/eth/ethconsensusconfig/config.go +++ b/eth/ethconsensusconfig/config.go @@ -8,6 +8,7 @@ import ( "github.com/ledgerwatch/log/v3" "github.com/ledgerwatch/erigon-lib/chain" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon/consensus" @@ -95,12 +96,12 @@ func CreateConsensusEngine(ctx context.Context, nodeConfig *nodecfg.Config, chai panic(err) } } - case *chain.BorConfig: + case *borcfg.BorConfig: // If Matic bor consensus is requested, set it up // In order to pass the ethereum transaction tests, we need to set the burn contract which is in the bor config // Then, bor != nil will also be enabled for ethash and clique. Only enable Bor for real if there is a validator contract present. - if chainConfig.Bor != nil && chainConfig.Bor.ValidatorContract != "" { - genesisContractsClient := contract.NewGenesisContractsClient(chainConfig, chainConfig.Bor.ValidatorContract, chainConfig.Bor.StateReceiverContract, logger) + if chainConfig.Bor != nil && consensusCfg.ValidatorContract != "" { + genesisContractsClient := contract.NewGenesisContractsClient(chainConfig, consensusCfg.ValidatorContract, consensusCfg.StateReceiverContract, logger) spanner := span.NewChainSpanner(contract.ValidatorSet(), chainConfig, withoutHeimdall, logger) diff --git a/eth/stagedsync/stage_bor_heimdall.go b/eth/stagedsync/stage_bor_heimdall.go index 6a36a553059..1fb367156d5 100644 --- a/eth/stagedsync/stage_bor_heimdall.go +++ b/eth/stagedsync/stage_bor_heimdall.go @@ -23,6 +23,7 @@ import ( "github.com/ledgerwatch/erigon/accounts/abi" "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/consensus/bor" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "github.com/ledgerwatch/erigon/consensus/bor/contract" "github.com/ledgerwatch/erigon/consensus/bor/finality/generics" "github.com/ledgerwatch/erigon/consensus/bor/finality/whitelist" @@ -40,7 +41,7 @@ import ( const ( inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory - inmemorySignatures = 4096 // Number of recent block signatures to keep in memory + InMemorySignatures = 4096 // Number of recent block signatures to keep in memory snapshotPersistInterval = 1024 // Number of blocks after which to persist the vote snapshot to the database extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal @@ -56,6 +57,7 @@ type BorHeimdallCfg struct { snapDb kv.RwDB // Database to store and retrieve snapshot checkpoints miningState MiningState chainConfig chain.Config + borConfig *borcfg.BorConfig heimdallClient heimdall.IHeimdallClient blockReader services.FullBlockReader hd *headerdownload.HeaderDownload @@ -79,11 +81,17 @@ func StageBorHeimdallCfg( recents *lru.ARCCache[libcommon.Hash, *bor.Snapshot], signatures *lru.ARCCache[libcommon.Hash, libcommon.Address], ) BorHeimdallCfg { + var borConfig *borcfg.BorConfig + if chainConfig.Bor != nil { + borConfig = chainConfig.Bor.(*borcfg.BorConfig) + } + return BorHeimdallCfg{ db: db, snapDb: snapDb, miningState: miningState, chainConfig: chainConfig, + borConfig: borConfig, heimdallClient: heimdallClient, blockReader: blockReader, hd: hd, @@ -106,7 +114,7 @@ func BorHeimdallForward( ) (err error) { processStart := time.Now() - if cfg.chainConfig.Bor == nil { + if cfg.borConfig == nil { return } if cfg.heimdallClient == nil { @@ -226,7 +234,7 @@ func BorHeimdallForward( endSpanID = span.IDAt(headNumber + 1) } - if span.BlockInLastSprintOfSpan(headNumber, cfg.chainConfig.Bor) { + if span.BlockInLastSprintOfSpan(headNumber, cfg.borConfig) { endSpanID++ } @@ -238,7 +246,7 @@ func BorHeimdallForward( if err != nil { return err } - signatures, err := lru.NewARC[libcommon.Hash, libcommon.Address](inmemorySignatures) + signatures, err := lru.NewARC[libcommon.Hash, libcommon.Address](InMemorySignatures) if err != nil { return err } @@ -291,19 +299,19 @@ func BorHeimdallForward( } } - sprintLength := cfg.chainConfig.Bor.CalculateSprint(blockNum) + sprintLength := cfg.borConfig.CalculateSprintLength(blockNum) spanID := span.IDAt(blockNum) if (spanID > 0) && ((blockNum+1)%sprintLength == 0) { - if err = checkHeaderExtraData(u, ctx, chain, blockNum, header, cfg.chainConfig.Bor); err != nil { + if err = checkHeaderExtraData(u, ctx, chain, blockNum, header, cfg.borConfig); err != nil { return err } } } - if blockNum > 0 && blockNum%cfg.chainConfig.Bor.CalculateSprint(blockNum) == 0 { + if blockNum > 0 && blockNum%cfg.borConfig.CalculateSprintLength(blockNum) == 0 { var callTime time.Duration var records int - if lastEventId, records, callTime, err = fetchAndWriteBorEvents(ctx, cfg.blockReader, cfg.chainConfig.Bor, header, lastEventId, cfg.chainConfig.ChainID.String(), tx, cfg.heimdallClient, cfg.stateReceiverABI, s.LogPrefix(), logger); err != nil { + if lastEventId, records, callTime, err = fetchAndWriteBorEvents(ctx, cfg.blockReader, cfg.borConfig, header, lastEventId, cfg.chainConfig.ChainID.String(), tx, cfg.heimdallClient, cfg.stateReceiverABI, s.LogPrefix(), logger); err != nil { return err } @@ -315,10 +323,10 @@ func BorHeimdallForward( if header != nil { if cfg.blockReader.BorSnapshots().SegmentsMin() == 0 { - snap = loadSnapshot(blockNum, header.Hash(), cfg.chainConfig.Bor, recents, signatures, cfg.snapDb, logger) + snap = loadSnapshot(blockNum, header.Hash(), cfg.borConfig, recents, signatures, cfg.snapDb, logger) if snap == nil { - snap, err = initValidatorSets(ctx, tx, cfg.blockReader, cfg.chainConfig.Bor, + snap, err = initValidatorSets(ctx, tx, cfg.blockReader, cfg.borConfig, cfg.heimdallClient, chain, blockNum, recents, signatures, cfg.snapDb, logger, s.LogPrefix()) if err != nil { @@ -326,7 +334,7 @@ func BorHeimdallForward( } } - if err = persistValidatorSets(ctx, snap, u, tx, cfg.blockReader, cfg.chainConfig.Bor, chain, blockNum, header.Hash(), recents, signatures, cfg.snapDb, logger, s.LogPrefix()); err != nil { + if err = persistValidatorSets(ctx, snap, u, tx, cfg.blockReader, cfg.borConfig, chain, blockNum, header.Hash(), recents, signatures, cfg.snapDb, logger, s.LogPrefix()); err != nil { return fmt.Errorf("can't persist validator sets: %w", err) } } @@ -359,7 +367,7 @@ func checkHeaderExtraData( chain consensus.ChainHeaderReader, blockNum uint64, header *types.Header, - config *chain.BorConfig, + config *borcfg.BorConfig, ) error { spanID := span.IDAt(blockNum + 1) spanBytes := chain.BorSpan(spanID) @@ -394,7 +402,7 @@ func checkHeaderExtraData( func fetchAndWriteBorEvents( ctx context.Context, blockReader services.FullBlockReader, - config *chain.BorConfig, + config *borcfg.BorConfig, header *types.Header, lastEventId uint64, chainID string, @@ -422,7 +430,7 @@ func fetchAndWriteBorEvents( stateSyncDelay := config.CalculateStateSyncDelay(blockNum) to = time.Unix(int64(header.Time-stateSyncDelay), 0) } else { - pHeader, err := blockReader.HeaderByNumber(ctx, tx, blockNum-config.CalculateSprint(blockNum)) + pHeader, err := blockReader.HeaderByNumber(ctx, tx, blockNum-config.CalculateSprintLength(blockNum)) if err != nil { return lastEventId, 0, time.Since(fetchStart), err } @@ -523,7 +531,7 @@ func fetchAndWriteSpans( return spanId, nil } -func loadSnapshot(blockNum uint64, hash libcommon.Hash, config *chain.BorConfig, recents *lru.ARCCache[libcommon.Hash, *bor.Snapshot], +func loadSnapshot(blockNum uint64, hash libcommon.Hash, config *borcfg.BorConfig, recents *lru.ARCCache[libcommon.Hash, *bor.Snapshot], signatures *lru.ARCCache[libcommon.Hash, libcommon.Address], snapDb kv.RwDB, logger log.Logger) *bor.Snapshot { @@ -548,7 +556,7 @@ func persistValidatorSets( u Unwinder, tx kv.Tx, blockReader services.FullBlockReader, - config *chain.BorConfig, + config *borcfg.BorConfig, chain consensus.ChainHeaderReader, blockNum uint64, hash libcommon.Hash, @@ -665,7 +673,7 @@ func initValidatorSets( ctx context.Context, tx kv.RwTx, blockReader services.FullBlockReader, - config *chain.BorConfig, + config *borcfg.BorConfig, heimdallClient heimdall.IHeimdallClient, chain consensus.ChainHeaderReader, blockNum uint64, @@ -724,7 +732,7 @@ func initValidatorSets( g.SetLimit(estimate.AlmostAllCPUs()) defer g.Wait() - batchSize := 128 // must be < inmemorySignatures + batchSize := 128 // must be < InMemorySignatures initialHeaders := make([]*types.Header, 0, batchSize) parentHeader := zeroHeader for i := uint64(1); i <= blockNum; i++ { @@ -732,7 +740,7 @@ func initValidatorSets( { // `snap.apply` bottleneck - is recover of signer. // to speedup: recover signer in background goroutines and save in `sigcache` - // `batchSize` < `inmemorySignatures`: means all current batch will fit in cache - and `snap.apply` will find it there. + // `batchSize` < `InMemorySignatures`: means all current batch will fit in cache - and `snap.apply` will find it there. g.Go(func() error { if header == nil { return nil @@ -767,7 +775,7 @@ func initValidatorSets( } func BorHeimdallUnwind(u *UnwindState, ctx context.Context, s *StageState, tx kv.RwTx, cfg BorHeimdallCfg) (err error) { - if cfg.chainConfig.Bor == nil { + if cfg.borConfig == nil { return } useExternalTx := tx != nil @@ -840,7 +848,7 @@ func BorHeimdallUnwind(u *UnwindState, ctx context.Context, s *StageState, tx kv } func BorHeimdallPrune(s *PruneState, ctx context.Context, tx kv.RwTx, cfg BorHeimdallCfg) (err error) { - if cfg.chainConfig.Bor == nil { + if cfg.borConfig == nil { return } return diff --git a/eth/stagedsync/stage_bor_heimdall_test.go b/eth/stagedsync/stage_bor_heimdall_test.go index 45a27311905..8a11c7173ca 100644 --- a/eth/stagedsync/stage_bor_heimdall_test.go +++ b/eth/stagedsync/stage_bor_heimdall_test.go @@ -188,7 +188,7 @@ func TestBorHeimdallForwardDetectsUnauthorizedSignerError(t *testing.T) { invalidHeader.Extra = bytes.Repeat([]byte{0x00}, types.ExtraVanityLength+types.ExtraSealLength) validatorKey1, err := crypto.GenerateKey() require.NoError(t, err) - sighash, err := crypto.Sign(crypto.Keccak256(bor.BorRLP(invalidHeader, chainConfig.Bor)), validatorKey1) + sighash, err := crypto.Sign(crypto.Keccak256(bor.BorRLP(invalidHeader, testHarness.BorConfig())), validatorKey1) require.NoError(t, err) copy(invalidHeader.Extra[len(invalidHeader.Extra)-types.ExtraSealLength:], sighash) testHarness.SaveHeader(ctx, t, invalidHeader) diff --git a/eth/stagedsync/stage_txlookup.go b/eth/stagedsync/stage_txlookup.go index 3c0223e3393..197a319099a 100644 --- a/eth/stagedsync/stage_txlookup.go +++ b/eth/stagedsync/stage_txlookup.go @@ -6,14 +6,16 @@ import ( "fmt" "math/big" + "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/cmp" "github.com/ledgerwatch/erigon-lib/common/hexutility" "github.com/ledgerwatch/erigon-lib/etl" "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "github.com/ledgerwatch/erigon/turbo/services" - "github.com/ledgerwatch/log/v3" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/types" @@ -24,7 +26,7 @@ type TxLookupCfg struct { db kv.RwDB prune prune.Mode tmpdir string - borConfig *chain.BorConfig + borConfig *borcfg.BorConfig blockReader services.FullBlockReader } @@ -32,9 +34,14 @@ func StageTxLookupCfg( db kv.RwDB, prune prune.Mode, tmpdir string, - borConfig *chain.BorConfig, + borConfigInterface chain.BorConfig, blockReader services.FullBlockReader, ) TxLookupCfg { + var borConfig *borcfg.BorConfig + if borConfigInterface != nil { + borConfig = borConfigInterface.(*borcfg.BorConfig) + } + return TxLookupCfg{ db: db, prune: prune, @@ -152,7 +159,7 @@ func borTxnLookupTransform(logPrefix string, tx kv.RwTx, blockFrom, blockTo uint blockNumBytes := bigNum.SetUint64(blocknum).Bytes() // we add state sync transactions every bor Sprint amount of blocks - if blocknum%cfg.borConfig.CalculateSprint(blocknum) == 0 && rawdb.HasBorReceipts(tx, blocknum) { + if blocknum%cfg.borConfig.CalculateSprintLength(blocknum) == 0 && rawdb.HasBorReceipts(tx, blocknum) { txnHash := types.ComputeBorTxHash(blocknum, blockHash) if err := next(k, txnHash.Bytes(), blockNumBytes); err != nil { return err diff --git a/eth/stagedsync/stagedsynctest/chain_configs.go b/eth/stagedsync/stagedsynctest/chain_configs.go index 99b81e24442..7be90935113 100644 --- a/eth/stagedsync/stagedsynctest/chain_configs.go +++ b/eth/stagedsync/stagedsynctest/chain_configs.go @@ -2,13 +2,14 @@ package stagedsynctest import ( "github.com/ledgerwatch/erigon-lib/chain" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "github.com/ledgerwatch/erigon/params" ) func BorDevnetChainConfigWithNoBlockSealDelays() *chain.Config { // take care not to mutate global var (shallow copy) chainConfigCopy := *params.BorDevnetChainConfig - borConfigCopy := *chainConfigCopy.Bor + borConfigCopy := *chainConfigCopy.Bor.(*borcfg.BorConfig) borConfigCopy.Period = map[string]uint64{ "0": 0, } diff --git a/eth/stagedsync/stagedsynctest/harness.go b/eth/stagedsync/stagedsynctest/harness.go index 0b3100d8022..78e481f94b9 100644 --- a/eth/stagedsync/stagedsynctest/harness.go +++ b/eth/stagedsync/stagedsynctest/harness.go @@ -7,6 +7,7 @@ import ( "encoding/json" "errors" "fmt" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "math/big" "testing" "time" @@ -90,6 +91,7 @@ func InitHarness(ctx context.Context, t *testing.T, cfg HarnessCfg) Harness { chainDataDB: chainDataDB, borConsensusDB: borConsensusDB, chainConfig: cfg.ChainConfig, + borConfig: cfg.ChainConfig.Bor.(*borcfg.BorConfig), blockReader: blockReader, stateSyncStages: stateSyncStages, stateSync: stateSync, @@ -141,6 +143,7 @@ type Harness struct { chainDataDB kv.RwDB borConsensusDB kv.RwDB chainConfig *chain.Config + borConfig *borcfg.BorConfig blockReader services.BlockReader stateSyncStages []*stagedsync.Stage stateSync *stagedsync.Sync @@ -161,6 +164,10 @@ func (h *Harness) Logger() log.Logger { return h.logger } +func (h *Harness) BorConfig() *borcfg.BorConfig { + return h.borConfig +} + func (h *Harness) SaveStageProgress(ctx context.Context, t *testing.T, stageID stages.SyncStage, progress uint64) { rwTx, err := h.chainDataDB.BeginRw(ctx) require.NoError(t, err) @@ -417,8 +424,8 @@ func (h *Harness) consensusEngine(t *testing.T, cfg HarnessCfg) consensus.Engine if h.chainConfig.Bor != nil { genesisContracts := contract.NewGenesisContractsClient( h.chainConfig, - h.chainConfig.Bor.ValidatorContract, - h.chainConfig.Bor.StateReceiverContract, + h.borConfig.ValidatorContract, + h.borConfig.StateReceiverContract, h.logger, ) @@ -568,8 +575,8 @@ func (h *Harness) mockHeimdallClient() { StateSyncEvents(gomock.Any(), gomock.Any(), gomock.Any()). DoAndReturn(func(_ context.Context, _ uint64, _ int64) ([]*clerk.EventRecordWithTime, error) { h.heimdallLastEventID++ - h.heimdallLastEventHeaderNum += h.chainConfig.Bor.CalculateSprint(h.heimdallLastEventHeaderNum) - stateSyncDelay := h.chainConfig.Bor.CalculateStateSyncDelay(h.heimdallLastEventHeaderNum) + h.heimdallLastEventHeaderNum += h.borConfig.CalculateSprintLength(h.heimdallLastEventHeaderNum) + stateSyncDelay := h.borConfig.CalculateStateSyncDelay(h.heimdallLastEventHeaderNum) newEvent := clerk.EventRecordWithTime{ EventRecord: clerk.EventRecord{ ID: h.heimdallLastEventID, diff --git a/params/config.go b/params/config.go index 5f6c4160008..23761442a19 100644 --- a/params/config.go +++ b/params/config.go @@ -26,6 +26,7 @@ import ( "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon-lib/chain/networkname" libcommon "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "github.com/ledgerwatch/erigon/common/paths" ) @@ -39,12 +40,23 @@ func readChainSpec(filename string) *chain.Config { panic(fmt.Sprintf("Could not open chainspec for %s: %v", filename, err)) } defer f.Close() + decoder := json.NewDecoder(f) spec := &chain.Config{} err = decoder.Decode(&spec) if err != nil { panic(fmt.Sprintf("Could not parse chainspec for %s: %v", filename, err)) } + + if spec.BorJSON != nil { + borConfig := &borcfg.BorConfig{} + err = json.Unmarshal(spec.BorJSON, borConfig) + if err != nil { + panic(fmt.Sprintf("Could not parse 'bor' chainspec for %s: %v", filename, err)) + } + spec.Bor = borConfig + } + return spec } diff --git a/polygon/sync/canonical_chain_builder.go b/polygon/sync/canonical_chain_builder.go new file mode 100644 index 00000000000..9acd3cf07d3 --- /dev/null +++ b/polygon/sync/canonical_chain_builder.go @@ -0,0 +1,244 @@ +package sync + +import ( + "errors" + "fmt" + + libcommon "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon/consensus/bor" + "github.com/ledgerwatch/erigon/core/types" +) + +//go:generate mockgen -destination=./mock/canonical_chain_builder_mock.go -package=mock . CanonicalChainBuilder +type CanonicalChainBuilder interface { + Reset(root *types.Header) + ContainsHash(hash libcommon.Hash) bool + Tip() *types.Header + HeadersInRange(start uint64, count uint64) []*types.Header + Prune(newRootNum uint64) error + Connect(headers []*types.Header) error +} + +type producerSlotIndex uint64 + +type forkTreeNode struct { + parent *forkTreeNode + children map[producerSlotIndex]*forkTreeNode + + header *types.Header + headerHash libcommon.Hash + + totalDifficulty uint64 +} + +type canonicalChainBuilderImpl struct { + root *forkTreeNode + tip *forkTreeNode + + difficultyCalc DifficultyCalculator +} + +func NewCanonicalChainBuilder( + root *types.Header, + difficultyCalc DifficultyCalculator, +) CanonicalChainBuilder { + impl := &canonicalChainBuilderImpl{ + difficultyCalc: difficultyCalc, + } + impl.Reset(root) + return impl +} + +func (impl *canonicalChainBuilderImpl) Reset(root *types.Header) { + impl.root = &forkTreeNode{ + children: make(map[producerSlotIndex]*forkTreeNode), + header: root, + headerHash: root.Hash(), + } + impl.tip = impl.root +} + +// depth-first search +func (impl *canonicalChainBuilderImpl) enumerate(visitFunc func(*forkTreeNode) bool) { + stack := []*forkTreeNode{impl.root} + for len(stack) > 0 { + // pop + node := stack[len(stack)-1] + stack = stack[:len(stack)-1] + + if !visitFunc(node) { + break + } + + for _, child := range node.children { + stack = append(stack, child) + } + } +} + +func (impl *canonicalChainBuilderImpl) nodeByHash(hash libcommon.Hash) *forkTreeNode { + var result *forkTreeNode + impl.enumerate(func(node *forkTreeNode) bool { + if node.headerHash == hash { + result = node + } + return result == nil + }) + return result +} + +func (impl *canonicalChainBuilderImpl) ContainsHash(hash libcommon.Hash) bool { + return impl.nodeByHash(hash) != nil +} + +func (impl *canonicalChainBuilderImpl) Tip() *types.Header { + return impl.tip.header +} + +func (impl *canonicalChainBuilderImpl) Headers() []*types.Header { + var headers []*types.Header + node := impl.tip + for node != nil { + headers = append(headers, node.header) + node = node.parent + } + libcommon.SliceReverse(headers) + return headers +} + +func (impl *canonicalChainBuilderImpl) HeadersInRange(start uint64, count uint64) []*types.Header { + headers := impl.Headers() + if len(headers) == 0 { + return nil + } + if headers[0].Number.Uint64() > start { + return nil + } + if headers[len(headers)-1].Number.Uint64() < start+count-1 { + return nil + } + + offset := start - headers[0].Number.Uint64() + return headers[offset : offset+count] +} + +func (impl *canonicalChainBuilderImpl) Prune(newRootNum uint64) error { + if (newRootNum < impl.root.header.Number.Uint64()) || (newRootNum > impl.Tip().Number.Uint64()) { + return errors.New("canonicalChainBuilderImpl.Prune: newRootNum outside of the canonical chain") + } + + newRoot := impl.tip + for newRoot.header.Number.Uint64() > newRootNum { + newRoot = newRoot.parent + } + + impl.root = newRoot + return nil +} + +func (impl *canonicalChainBuilderImpl) updateTipIfNeeded(tipCandidate *forkTreeNode) { + if tipCandidate.totalDifficulty > impl.tip.totalDifficulty { + impl.tip = tipCandidate + } + // else if tipCandidate.totalDifficulty == impl.tip.totalDifficulty { + // TODO: is it possible? which one is selected? + // } +} + +func (impl *canonicalChainBuilderImpl) Connect(headers []*types.Header) error { + if (len(headers) > 0) && (headers[0].Number != nil) && (headers[0].Number.Cmp(impl.root.header.Number) == 0) { + headers = headers[1:] + } + if len(headers) == 0 { + return nil + } + + parent := impl.nodeByHash(headers[0].ParentHash) + if parent == nil { + return errors.New("canonicalChainBuilderImpl.Connect: can't connect headers") + } + + headersHashes := libcommon.SliceMap(headers, func(header *types.Header) libcommon.Hash { + return header.Hash() + }) + + // check if headers are linked by ParentHash + for i, header := range headers[1:] { + if header.ParentHash != headersHashes[i] { + return errors.New("canonicalChainBuilderImpl.Connect: invalid headers slice ParentHash") + } + } + + // skip existing matching nodes until a new header is found + for len(headers) > 0 { + var matchingNode *forkTreeNode + for _, c := range parent.children { + if c.headerHash == headersHashes[0] { + matchingNode = c + break + } + } + if matchingNode != nil { + parent = matchingNode + headers = headers[1:] + headersHashes = headersHashes[1:] + } else { + break + } + } + + // if all headers are already inserted + if len(headers) == 0 { + return nil + } + + // attach nodes for the new headers + for i, header := range headers { + if (header.Number == nil) && (header.Number.Uint64() != parent.header.Number.Uint64()+1) { + return errors.New("canonicalChainBuilderImpl.Connect: invalid header.Number") + } + + // TODO: validate using CalcProducerDelay + if header.Time <= parent.header.Time { + return errors.New("canonicalChainBuilderImpl.Connect: invalid header.Time") + } + + if err := bor.ValidateHeaderExtraField(header.Extra); err != nil { + return fmt.Errorf("canonicalChainBuilderImpl.Connect: invalid header.Extra %w", err) + } + + difficulty, err := impl.difficultyCalc.HeaderDifficulty(header) + if err != nil { + return fmt.Errorf("canonicalChainBuilderImpl.Connect: header difficulty error %w", err) + } + if (header.Difficulty == nil) || (header.Difficulty.Uint64() != difficulty) { + return &bor.WrongDifficultyError{ + Number: header.Number.Uint64(), + Expected: difficulty, + Actual: header.Difficulty.Uint64(), + Signer: []byte{}, + } + } + + slot := producerSlotIndex(difficulty) + if _, ok := parent.children[slot]; ok { + return errors.New("canonicalChainBuilderImpl.Connect: producer slot is already filled by a different header") + } + + node := &forkTreeNode{ + parent: parent, + children: make(map[producerSlotIndex]*forkTreeNode), + + header: header, + headerHash: headersHashes[i], + + totalDifficulty: parent.totalDifficulty + difficulty, + } + + parent.children[slot] = node + parent = node + impl.updateTipIfNeeded(node) + } + + return nil +} diff --git a/polygon/sync/canonical_chain_builder_test.go b/polygon/sync/canonical_chain_builder_test.go new file mode 100644 index 00000000000..aa640f3c479 --- /dev/null +++ b/polygon/sync/canonical_chain_builder_test.go @@ -0,0 +1,23 @@ +package sync + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/ledgerwatch/erigon/core/types" +) + +type testDifficultyCalculator struct { +} + +func (*testDifficultyCalculator) HeaderDifficulty(*types.Header) (uint64, error) { + return 0, nil +} + +func TestCanonicalChainBuilderConnectEmpty(t *testing.T) { + difficultyCalc := testDifficultyCalculator{} + builder := NewCanonicalChainBuilder(new(types.Header), &difficultyCalc) + err := builder.Connect([]*types.Header{}) + require.Nil(t, err) +} diff --git a/polygon/sync/difficulty.go b/polygon/sync/difficulty.go new file mode 100644 index 00000000000..7a6895c506c --- /dev/null +++ b/polygon/sync/difficulty.go @@ -0,0 +1,60 @@ +package sync + +import ( + lru "github.com/hashicorp/golang-lru/arc/v2" + "github.com/ledgerwatch/erigon/eth/stagedsync" + "github.com/ledgerwatch/log/v3" + + libcommon "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon/consensus/bor" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" + heimdallspan "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" + "github.com/ledgerwatch/erigon/consensus/bor/valset" + "github.com/ledgerwatch/erigon/core/types" +) + +type DifficultyCalculator interface { + HeaderDifficulty(header *types.Header) (uint64, error) +} + +type difficultyCalculatorImpl struct { + borConfig *borcfg.BorConfig + span *heimdallspan.HeimdallSpan + signaturesCache *lru.ARCCache[libcommon.Hash, libcommon.Address] + + log log.Logger +} + +func NewDifficultyCalculator( + borConfig *borcfg.BorConfig, + span *heimdallspan.HeimdallSpan, + log log.Logger, +) DifficultyCalculator { + signaturesCache, err := lru.NewARC[libcommon.Hash, libcommon.Address](stagedsync.InMemorySignatures) + if err != nil { + panic(err) + } + return &difficultyCalculatorImpl{ + borConfig: borConfig, + span: span, + signaturesCache: signaturesCache, + + log: log, + } +} + +func (impl *difficultyCalculatorImpl) HeaderDifficulty(header *types.Header) (uint64, error) { + signer, err := bor.Ecrecover(header, impl.signaturesCache, impl.borConfig) + if err != nil { + return 0, err + } + + validatorSet := valset.NewValidatorSet(impl.span.ValidatorSet.Validators, log.New()) + + sprintCount := impl.borConfig.CalculateSprintNumber(header.Number.Uint64()) + if sprintCount > 0 { + validatorSet.IncrementProposerPriority(int(sprintCount), impl.log) + } + + return validatorSet.Difficulty(signer) +} diff --git a/polygon/sync/difficulty_test.go b/polygon/sync/difficulty_test.go new file mode 100644 index 00000000000..69d684149ed --- /dev/null +++ b/polygon/sync/difficulty_test.go @@ -0,0 +1,21 @@ +package sync + +import ( + "github.com/ledgerwatch/log/v3" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" + heimdallspan "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" + "github.com/ledgerwatch/erigon/core/types" +) + +func TestHeaderDifficultyNoSignature(t *testing.T) { + borConfig := borcfg.BorConfig{} + span := heimdallspan.HeimdallSpan{} + logger := log.New() + calc := NewDifficultyCalculator(&borConfig, &span, logger) + _, err := calc.HeaderDifficulty(new(types.Header)) + require.ErrorContains(t, err, "signature suffix missing") +} diff --git a/polygon/sync/heimdall.go b/polygon/sync/heimdall.go index f1addfad9e5..cdf8077b9ac 100644 --- a/polygon/sync/heimdall.go +++ b/polygon/sync/heimdall.go @@ -8,6 +8,7 @@ import ( "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/consensus/bor/heimdall" "github.com/ledgerwatch/erigon/consensus/bor/heimdall/checkpoint" "github.com/ledgerwatch/erigon/consensus/bor/heimdall/milestone" @@ -61,12 +62,6 @@ func cmpBlockNumToMilestoneRange(n uint64, m *milestone.Milestone) int { return cmpNumToRange(n, m.StartBlock, m.EndBlock) } -func reverse[T any](s []T) { - for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { - s[i], s[j] = s[j], s[i] - } -} - func (impl *HeimdallImpl) FetchCheckpoints(ctx context.Context, start uint64) ([]*checkpoint.Checkpoint, error) { count, err := impl.client.FetchCheckpointCount(ctx) if err != nil { @@ -95,7 +90,7 @@ func (impl *HeimdallImpl) FetchCheckpoints(ctx context.Context, start uint64) ([ } } - reverse(checkpoints) + common.SliceReverse(checkpoints) return checkpoints, nil } @@ -111,7 +106,7 @@ func (impl *HeimdallImpl) FetchMilestones(ctx context.Context, start uint64) ([] m, err := impl.client.FetchMilestone(ctx, i) if err != nil { if errors.Is(err, heimdall.ErrNotInMilestoneList) { - reverse(milestones) + common.SliceReverse(milestones) return milestones, ErrIncompleteMilestoneRange } return nil, err @@ -131,7 +126,7 @@ func (impl *HeimdallImpl) FetchMilestones(ctx context.Context, start uint64) ([] } } - reverse(milestones) + common.SliceReverse(milestones) return milestones, nil } diff --git a/polygon/sync/mock/canonical_chain_builder_mock.go b/polygon/sync/mock/canonical_chain_builder_mock.go new file mode 100644 index 00000000000..2985c446798 --- /dev/null +++ b/polygon/sync/mock/canonical_chain_builder_mock.go @@ -0,0 +1,118 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/ledgerwatch/erigon/polygon/sync (interfaces: CanonicalChainBuilder) + +// Package mock is a generated GoMock package. +package mock + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + common "github.com/ledgerwatch/erigon-lib/common" + types "github.com/ledgerwatch/erigon/core/types" +) + +// MockCanonicalChainBuilder is a mock of CanonicalChainBuilder interface. +type MockCanonicalChainBuilder struct { + ctrl *gomock.Controller + recorder *MockCanonicalChainBuilderMockRecorder +} + +// MockCanonicalChainBuilderMockRecorder is the mock recorder for MockCanonicalChainBuilder. +type MockCanonicalChainBuilderMockRecorder struct { + mock *MockCanonicalChainBuilder +} + +// NewMockCanonicalChainBuilder creates a new mock instance. +func NewMockCanonicalChainBuilder(ctrl *gomock.Controller) *MockCanonicalChainBuilder { + mock := &MockCanonicalChainBuilder{ctrl: ctrl} + mock.recorder = &MockCanonicalChainBuilderMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockCanonicalChainBuilder) EXPECT() *MockCanonicalChainBuilderMockRecorder { + return m.recorder +} + +// Connect mocks base method. +func (m *MockCanonicalChainBuilder) Connect(arg0 []*types.Header) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Connect", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// Connect indicates an expected call of Connect. +func (mr *MockCanonicalChainBuilderMockRecorder) Connect(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Connect", reflect.TypeOf((*MockCanonicalChainBuilder)(nil).Connect), arg0) +} + +// ContainsHash mocks base method. +func (m *MockCanonicalChainBuilder) ContainsHash(arg0 common.Hash) bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ContainsHash", arg0) + ret0, _ := ret[0].(bool) + return ret0 +} + +// ContainsHash indicates an expected call of ContainsHash. +func (mr *MockCanonicalChainBuilderMockRecorder) ContainsHash(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ContainsHash", reflect.TypeOf((*MockCanonicalChainBuilder)(nil).ContainsHash), arg0) +} + +// HeadersInRange mocks base method. +func (m *MockCanonicalChainBuilder) HeadersInRange(arg0, arg1 uint64) []*types.Header { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "HeadersInRange", arg0, arg1) + ret0, _ := ret[0].([]*types.Header) + return ret0 +} + +// HeadersInRange indicates an expected call of HeadersInRange. +func (mr *MockCanonicalChainBuilderMockRecorder) HeadersInRange(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HeadersInRange", reflect.TypeOf((*MockCanonicalChainBuilder)(nil).HeadersInRange), arg0, arg1) +} + +// Prune mocks base method. +func (m *MockCanonicalChainBuilder) Prune(arg0 uint64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Prune", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// Prune indicates an expected call of Prune. +func (mr *MockCanonicalChainBuilderMockRecorder) Prune(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Prune", reflect.TypeOf((*MockCanonicalChainBuilder)(nil).Prune), arg0) +} + +// Reset mocks base method. +func (m *MockCanonicalChainBuilder) Reset(arg0 *types.Header) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Reset", arg0) +} + +// Reset indicates an expected call of Reset. +func (mr *MockCanonicalChainBuilderMockRecorder) Reset(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Reset", reflect.TypeOf((*MockCanonicalChainBuilder)(nil).Reset), arg0) +} + +// Tip mocks base method. +func (m *MockCanonicalChainBuilder) Tip() *types.Header { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Tip") + ret0, _ := ret[0].(*types.Header) + return ret0 +} + +// Tip indicates an expected call of Tip. +func (mr *MockCanonicalChainBuilderMockRecorder) Tip() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Tip", reflect.TypeOf((*MockCanonicalChainBuilder)(nil).Tip)) +} diff --git a/tests/bor/helper/miner.go b/tests/bor/helper/miner.go index fc420100a16..970116db606 100644 --- a/tests/bor/helper/miner.go +++ b/tests/bor/helper/miner.go @@ -4,6 +4,8 @@ import ( "context" "crypto/ecdsa" "encoding/json" + "fmt" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "math/big" "os" "time" @@ -28,7 +30,6 @@ import ( // InitGenesis initializes genesis file from json with sprint size and chain name as configurable inputs func InitGenesis(fileLocation string, sprintSize uint64, chainName string) types.Genesis { - // sprint size = 8 in genesis genesisData, err := os.ReadFile(fileLocation) if err != nil { @@ -36,14 +37,23 @@ func InitGenesis(fileLocation string, sprintSize uint64, chainName string) types } genesis := &types.Genesis{} - if err := json.Unmarshal(genesisData, genesis); err != nil { panic(err) } - genesis.Config.Bor.Sprint["0"] = sprintSize genesis.Config.ChainName = chainName + if genesis.Config.BorJSON != nil { + borConfig := &borcfg.BorConfig{} + err = json.Unmarshal(genesis.Config.BorJSON, borConfig) + if err != nil { + panic(fmt.Sprintf("Could not parse 'bor' config for %s: %v", fileLocation, err)) + } + + borConfig.Sprint["0"] = sprintSize + genesis.Config.Bor = borConfig + } + return *genesis } diff --git a/turbo/jsonrpc/bor_helper.go b/turbo/jsonrpc/bor_helper.go index c4a14e1b119..34a5ec35f5d 100644 --- a/turbo/jsonrpc/bor_helper.go +++ b/turbo/jsonrpc/bor_helper.go @@ -7,9 +7,9 @@ import ( "fmt" "sort" - "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "github.com/ledgerwatch/erigon/consensus/bor" "github.com/ledgerwatch/erigon/consensus/bor/valset" @@ -89,7 +89,7 @@ func getHeaderByHash(ctx context.Context, api *BorImpl, tx kv.Tx, hash common.Ha } // ecrecover extracts the Ethereum account address from a signed header. -func ecrecover(header *types.Header, c *chain.BorConfig) (common.Address, error) { +func ecrecover(header *types.Header, c *borcfg.BorConfig) (common.Address, error) { // Retrieve the signature from the header extra-data if len(header.Extra) < extraSeal { return common.Address{}, errMissingSignature @@ -146,8 +146,8 @@ func getUpdatedValidatorSet(oldValidatorSet *ValidatorSet, newVals []*valset.Val // author returns the Ethereum address recovered // from the signature in the header's extra-data section. func author(api *BorImpl, tx kv.Tx, header *types.Header) (common.Address, error) { - config, _ := api.chainConfig(tx) - return ecrecover(header, config.Bor) + borEngine, _ := api.bor() + return ecrecover(header, borEngine.Config()) } func rankMapDifficulties(values map[common.Address]uint64) []difficultiesKV { diff --git a/turbo/jsonrpc/bor_snapshot.go b/turbo/jsonrpc/bor_snapshot.go index 7a6ef67f4c8..0fb6389c3c2 100644 --- a/turbo/jsonrpc/bor_snapshot.go +++ b/turbo/jsonrpc/bor_snapshot.go @@ -6,10 +6,11 @@ import ( "errors" "fmt" - "github.com/ledgerwatch/erigon-lib/chain" + "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/consensus/bor" @@ -21,7 +22,7 @@ import ( ) type Snapshot struct { - config *chain.BorConfig // Consensus engine parameters to fine tune behavior + config *borcfg.BorConfig // Consensus engine parameters to fine tune behavior Number uint64 `json:"number"` // Block number where the snapshot was created Hash common.Hash `json:"hash"` // Block hash where the snapshot was created @@ -526,7 +527,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) { number := header.Number.Uint64() // Delete the oldest signer from the recent list to allow it signing again - currentSprint := s.config.CalculateSprint(number) + currentSprint := s.config.CalculateSprintLength(number) if number >= currentSprint { delete(snap.Recents, number-currentSprint) } @@ -628,8 +629,8 @@ func loadSnapshot(api *BorImpl, db kv.Tx, borDb kv.Tx, hash common.Hash) (*Snaps if err := json.Unmarshal(blob, snap); err != nil { return nil, err } - config, _ := api.chainConfig(db) - snap.config = config.Bor + borEngine, _ := api.bor() + snap.config = borEngine.Config() // update total voting power if err := snap.ValidatorSet.UpdateTotalVotingPower(); err != nil { diff --git a/turbo/jsonrpc/eth_block.go b/turbo/jsonrpc/eth_block.go index 25ba7f9505d..50cfca6e271 100644 --- a/turbo/jsonrpc/eth_block.go +++ b/turbo/jsonrpc/eth_block.go @@ -3,15 +3,18 @@ package jsonrpc import ( "context" "fmt" - "github.com/ledgerwatch/erigon-lib/common/hexutil" - "github.com/ledgerwatch/erigon/cl/clparams" "math/big" "time" + "github.com/ledgerwatch/erigon-lib/common/hexutil" + "github.com/ledgerwatch/erigon/cl/clparams" + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" + + "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/hexutility" "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/log/v3" "github.com/ledgerwatch/erigon/common/math" "github.com/ledgerwatch/erigon/core" @@ -292,7 +295,8 @@ func (api *APIImpl) GetBlockByHash(ctx context.Context, numberOrHash rpc.BlockNu response, err := ethapi.RPCMarshalBlockEx(block, true, fullTx, borTx, borTxHash, additionalFields) if chainConfig.Bor != nil { - response["miner"], _ = ecrecover(block.Header(), chainConfig.Bor) + borConfig := chainConfig.Bor.(*borcfg.BorConfig) + response["miner"], _ = ecrecover(block.Header(), borConfig) } if err == nil && int64(number) == rpc.PendingBlockNumber.Int64() { diff --git a/turbo/snapshotsync/freezeblocks/dump_test.go b/turbo/snapshotsync/freezeblocks/dump_test.go index cedfb5f27ec..a3de0bad293 100644 --- a/turbo/snapshotsync/freezeblocks/dump_test.go +++ b/turbo/snapshotsync/freezeblocks/dump_test.go @@ -1,6 +1,7 @@ package freezeblocks_test import ( + "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "math/big" "testing" @@ -51,9 +52,9 @@ func TestDump(t *testing.T) { } withConfig := func(config chain.Config, sprints map[string]uint64) *chain.Config { - bor := *config.Bor + bor := *config.Bor.(*borcfg.BorConfig) + bor.Sprint = sprints config.Bor = &bor - config.Bor.Sprint = sprints return &config } From 9cd5f5837f1da397504f9482b44fcad70897ff16 Mon Sep 17 00:00:00 2001 From: a Date: Thu, 4 Jan 2024 10:56:14 -0600 Subject: [PATCH 02/92] data (#9126) --- cl/beacon/validatorapi/get.go | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/cl/beacon/validatorapi/get.go b/cl/beacon/validatorapi/get.go index e72e4502119..00cbbf1e374 100644 --- a/cl/beacon/validatorapi/get.go +++ b/cl/beacon/validatorapi/get.go @@ -42,13 +42,14 @@ func (v *ValidatorApiHandler) GetEthV1NodeSyncing(w http.ResponseWriter, r *http } return map[string]any{ - "head_slot": strconv.FormatUint(slot, 10), - "sync_distance": syncDistance, - "is_syncing": isSyncing, - "el_offline": elOffline, - // TODO: figure out how to populat this field - "is_optimistic": true, - }, nil + "data": map[string]any{ + "head_slot": strconv.FormatUint(slot, 10), + "sync_distance": syncDistance, + "is_syncing": isSyncing, + "el_offline": elOffline, + // TODO: figure out how to populat this field + "is_optimistic": true, + }}, nil } func (v *ValidatorApiHandler) GetEthV1ConfigSpec(w http.ResponseWriter, r *http.Request) (*clparams.BeaconChainConfig, error) { @@ -67,10 +68,11 @@ func (v *ValidatorApiHandler) GetEthV1BeaconGenesis(w http.ResponseWriter, r *ht return nil, beaconhttp.NewEndpointError(http.StatusInternalServerError, err.Error()) } return map[string]any{ - "genesis_time": v.GenesisCfg.GenesisTime, - "genesis_validator_root": v.GenesisCfg.GenesisValidatorRoot, - "genesis_fork_version": hexutility.Bytes(digest[:]), - }, nil + "data": map[string]any{ + "genesis_time": v.GenesisCfg.GenesisTime, + "genesis_validator_root": v.GenesisCfg.GenesisValidatorRoot, + "genesis_fork_version": hexutility.Bytes(digest[:]), + }}, nil } func (v *ValidatorApiHandler) GetEthV1BeaconStatesStateIdFork(w http.ResponseWriter, r *http.Request) (any, error) { From 3eeb57218f13f9e755c132b2003c826551b8e560 Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Fri, 5 Jan 2024 13:03:36 +0100 Subject: [PATCH 03/92] params: begin 2.57 release cycle (#9144) --- params/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/params/version.go b/params/version.go index cb2d12d5bb1..a1b0c0ae15b 100644 --- a/params/version.go +++ b/params/version.go @@ -32,7 +32,7 @@ var ( // see https://calver.org const ( VersionMajor = 2 // Major version component of the current release - VersionMinor = 56 // Minor version component of the current release + VersionMinor = 57 // Minor version component of the current release VersionMicro = 0 // Patch version component of the current release VersionModifier = "dev" // Modifier component of the current release VersionKeyCreated = "ErigonVersionCreated" From ebe16d8360cb42067be9e558f816cf107bfad208 Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Fri, 5 Jan 2024 14:03:19 +0100 Subject: [PATCH 04/92] bor: BorConfig setup fix (#9145) A crash on startup happens on --chain=mumbai , because I've confused chainConfig.Bor (from type chain.Config) and config.Bor (from type ethconfig.Config) in the setup code. ethconfig.Config.Bor property contained bogus values, and was used only to check its type in CreateConsensusEngine(). Its value was never read (before PR #9117). This change removes the property to avoid confusion and fix the crash. Devnet network.BorStateSyncDelay was implemented using ethconfig.Config.Bor, but it wasn't taking any effect. It should be fixed separately in a different way. --- cmd/devnet/devnet/node.go | 8 +++++--- cmd/integration/commands/stages.go | 11 ++++++----- cmd/state/commands/check_change_sets.go | 2 +- eth/backend.go | 3 ++- eth/ethconfig/config.go | 3 --- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/cmd/devnet/devnet/node.go b/cmd/devnet/devnet/node.go index 4c372721a03..30f46633615 100644 --- a/cmd/devnet/devnet/node.go +++ b/cmd/devnet/devnet/node.go @@ -8,6 +8,9 @@ import ( "sync" "github.com/c2h5oh/datasize" + "github.com/ledgerwatch/log/v3" + "github.com/urfave/cli/v2" + "github.com/ledgerwatch/erigon/cmd/devnet/accounts" "github.com/ledgerwatch/erigon/cmd/devnet/args" "github.com/ledgerwatch/erigon/cmd/devnet/requests" @@ -17,8 +20,6 @@ import ( "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/turbo/debug" enode "github.com/ledgerwatch/erigon/turbo/node" - "github.com/ledgerwatch/log/v3" - "github.com/urfave/cli/v2" ) type Node interface { @@ -171,7 +172,8 @@ func (n *devnetNode) run(ctx *cli.Context) error { } if n.network.BorStateSyncDelay > 0 { - n.ethCfg.Bor.StateSyncConfirmationDelay = map[string]uint64{"0": uint64(n.network.BorStateSyncDelay.Seconds())} + stateSyncConfirmationDelay := map[string]uint64{"0": uint64(n.network.BorStateSyncDelay.Seconds())} + logger.Warn("TODO: custom BorStateSyncDelay is not applied to BorConfig.StateSyncConfirmationDelay", "delay", stateSyncConfirmationDelay) } n.ethNode, err = enode.New(ctx.Context, n.nodeCfg, n.ethCfg, logger) diff --git a/cmd/integration/commands/stages.go b/cmd/integration/commands/stages.go index fdfa42c44a2..b084cc3a7f5 100644 --- a/cmd/integration/commands/stages.go +++ b/cmd/integration/commands/stages.go @@ -13,6 +13,11 @@ import ( "github.com/c2h5oh/datasize" "github.com/erigontech/mdbx-go/mdbx" lru "github.com/hashicorp/golang-lru/arc/v2" + "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/secp256k1" + "github.com/spf13/cobra" + "golang.org/x/exp/slices" + "github.com/ledgerwatch/erigon/consensus/bor" "github.com/ledgerwatch/erigon/consensus/bor/heimdall" "github.com/ledgerwatch/erigon/consensus/bor/heimdallgrpc" @@ -21,10 +26,6 @@ import ( "github.com/ledgerwatch/erigon/p2p/sentry/sentry_multi_client" "github.com/ledgerwatch/erigon/turbo/builder" "github.com/ledgerwatch/erigon/turbo/snapshotsync/freezeblocks" - "github.com/ledgerwatch/log/v3" - "github.com/ledgerwatch/secp256k1" - "github.com/spf13/cobra" - "golang.org/x/exp/slices" chain2 "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon-lib/commitment" @@ -1674,7 +1675,7 @@ func initConsensusEngine(ctx context.Context, cc *chain2.Config, dir string, db } else if cc.Aura != nil { consensusConfig = &config.Aura } else if cc.Bor != nil { - consensusConfig = &config.Bor + consensusConfig = cc.Bor config.HeimdallURL = HeimdallURL if !config.WithoutHeimdall { if config.HeimdallgRPCAddress != "" { diff --git a/cmd/state/commands/check_change_sets.go b/cmd/state/commands/check_change_sets.go index 19eceebb5ca..3b844f1e5d7 100644 --- a/cmd/state/commands/check_change_sets.go +++ b/cmd/state/commands/check_change_sets.go @@ -288,7 +288,7 @@ func initConsensusEngine(ctx context.Context, cc *chain2.Config, snapshots *free } else if cc.Aura != nil { consensusConfig = &config.Aura } else if cc.Bor != nil { - consensusConfig = &config.Bor + consensusConfig = cc.Bor } else { consensusConfig = &config.Ethash } diff --git a/eth/backend.go b/eth/backend.go index f389a9463c4..04436895754 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -32,6 +32,7 @@ import ( "time" lru "github.com/hashicorp/golang-lru/arc/v2" + "github.com/ledgerwatch/erigon-lib/chain/networkname" "github.com/ledgerwatch/erigon-lib/chain/snapcfg" "github.com/ledgerwatch/erigon-lib/diagnostics" @@ -509,7 +510,7 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger } else if chainConfig.Aura != nil { consensusConfig = &config.Aura } else if chainConfig.Bor != nil { - consensusConfig = &config.Bor + consensusConfig = chainConfig.Bor } else { consensusConfig = &config.Ethash } diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 47ee3501560..a75b5783ac6 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -34,8 +34,6 @@ import ( "github.com/ledgerwatch/erigon-lib/common/datadir" "github.com/ledgerwatch/erigon-lib/downloader/downloadercfg" "github.com/ledgerwatch/erigon-lib/txpool/txpoolcfg" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" - "github.com/ledgerwatch/erigon/cl/beacon/beacon_router_configuration" "github.com/ledgerwatch/erigon/cl/clparams" "github.com/ledgerwatch/erigon/consensus/ethash/ethashcfg" @@ -211,7 +209,6 @@ type Config struct { Clique params.ConsensusSnapshotConfig Aura chain.AuRaConfig - Bor borcfg.BorConfig // Transaction pool options DeprecatedTxPool DeprecatedTxPoolConfig From 98cc1ee808fc71eaf97eb0b9d18906aa05021958 Mon Sep 17 00:00:00 2001 From: milen <94537774+taratorio@users.noreply.github.com> Date: Fri, 5 Jan 2024 14:20:21 +0000 Subject: [PATCH 05/92] stagedsync: implement bor span for chain reader and fix loggers (#9146) While working on fixing the bor mining loop I stumbled across an error in `ChainReader.BorSpan` - not implemented panic. Also hit a few other panics due to missed logger in `ChainReaderImpl` struct initialisations. This PR fixes both. --- consensus/clique/snapshot_test.go | 13 ++++++-- core/block_validator_test.go | 34 ++++++++++++++++----- eth/stagedsync/chain_reader.go | 23 +++++++++----- eth/stagedsync/stage_bodies.go | 6 ++-- eth/stagedsync/stage_headers.go | 17 +++++++---- eth/stagedsync/stage_mining_create_block.go | 8 ++--- eth/stagedsync/stage_mining_exec.go | 7 ++--- eth/stagedsync/stage_mining_finish.go | 10 +++--- 8 files changed, 78 insertions(+), 40 deletions(-) diff --git a/consensus/clique/snapshot_test.go b/consensus/clique/snapshot_test.go index 0f487177bfc..de00f536d79 100644 --- a/consensus/clique/snapshot_test.go +++ b/consensus/clique/snapshot_test.go @@ -23,6 +23,8 @@ import ( "sort" "testing" + "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/length" @@ -35,7 +37,7 @@ import ( "github.com/ledgerwatch/erigon/eth/stagedsync" "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/turbo/stages/mock" - "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon/turbo/testlog" ) // testerAccountPool is a pool to maintain currently active tester accounts, @@ -392,6 +394,7 @@ func TestClique(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { + logger := testlog.Logger(t, log.LvlInfo) // Create the account pool and generate the initial set of signers accounts := newTesterAccountPool() @@ -509,7 +512,13 @@ func TestClique(t *testing.T) { var snap *clique.Snapshot if err := m.DB.View(context.Background(), func(tx kv.Tx) error { - snap, err = engine.Snapshot(stagedsync.ChainReader{Cfg: config, Db: tx, BlockReader: m.BlockReader}, head.NumberU64(), head.Hash(), nil) + chainReader := stagedsync.ChainReader{ + Cfg: config, + Db: tx, + BlockReader: m.BlockReader, + Logger: logger, + } + snap, err = engine.Snapshot(chainReader, head.NumberU64(), head.Hash(), nil) if err != nil { return err } diff --git a/core/block_validator_test.go b/core/block_validator_test.go index 34ab7a2c21d..e57d40d3477 100644 --- a/core/block_validator_test.go +++ b/core/block_validator_test.go @@ -20,13 +20,17 @@ import ( "context" "testing" + "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/consensus/ethash" "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/eth/stagedsync" "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/turbo/stages/mock" + "github.com/ledgerwatch/erigon/turbo/testlog" ) // Tests that simple header verification works, for both good and bad blocks. @@ -37,6 +41,7 @@ func TestHeaderVerification(t *testing.T) { gspec = &types.Genesis{Config: params.TestChainConfig} engine = ethash.NewFaker() ) + logger := testlog.Logger(t, log.LvlInfo) checkStateRoot := true m := mock.MockWithGenesisEngine(t, gspec, engine, false, checkStateRoot) @@ -48,13 +53,19 @@ func TestHeaderVerification(t *testing.T) { for i := 0; i < chain.Length(); i++ { if err := m.DB.View(context.Background(), func(tx kv.Tx) error { for j, valid := range []bool{true, false} { + chainReader := stagedsync.ChainReader{ + Cfg: *params.TestChainConfig, + Db: tx, + BlockReader: m.BlockReader, + Logger: logger, + } + var engine consensus.Engine if valid { - engine := ethash.NewFaker() - err = engine.VerifyHeader(stagedsync.ChainReader{Cfg: *params.TestChainConfig, Db: tx, BlockReader: m.BlockReader}, chain.Headers[i], true) + engine = ethash.NewFaker() } else { - engine := ethash.NewFakeFailer(chain.Headers[i].Number.Uint64()) - err = engine.VerifyHeader(stagedsync.ChainReader{Cfg: *params.TestChainConfig, Db: tx, BlockReader: m.BlockReader}, chain.Headers[i], true) + engine = ethash.NewFakeFailer(chain.Headers[i].Number.Uint64()) } + err = engine.VerifyHeader(chainReader, chain.Headers[i], true) if (err == nil) != valid { t.Errorf("test %d.%d: validity mismatch: have %v, want %v", i, j, err, valid) } @@ -79,6 +90,7 @@ func TestHeaderWithSealVerification(t *testing.T) { gspec = &types.Genesis{Config: params.TestChainAuraConfig} engine = ethash.NewFaker() ) + logger := testlog.Logger(t, log.LvlInfo) checkStateRoot := true m := mock.MockWithGenesisEngine(t, gspec, engine, false, checkStateRoot) @@ -91,13 +103,19 @@ func TestHeaderWithSealVerification(t *testing.T) { for i := 0; i < chain.Length(); i++ { if err := m.DB.View(context.Background(), func(tx kv.Tx) error { for j, valid := range []bool{true, false} { + chainReader := stagedsync.ChainReader{ + Cfg: *params.TestChainAuraConfig, + Db: tx, + BlockReader: m.BlockReader, + Logger: logger, + } + var engine consensus.Engine if valid { - engine := ethash.NewFaker() - err = engine.VerifyHeader(stagedsync.ChainReader{Cfg: *params.TestChainAuraConfig, Db: tx, BlockReader: m.BlockReader}, chain.Headers[i], true) + engine = ethash.NewFaker() } else { - engine := ethash.NewFakeFailer(chain.Headers[i].Number.Uint64()) - err = engine.VerifyHeader(stagedsync.ChainReader{Cfg: *params.TestChainAuraConfig, Db: tx, BlockReader: m.BlockReader}, chain.Headers[i], true) + engine = ethash.NewFakeFailer(chain.Headers[i].Number.Uint64()) } + err = engine.VerifyHeader(chainReader, chain.Headers[i], true) if (err == nil) != valid { t.Errorf("test %d.%d: validity mismatch: have %v, want %v", i, j, err, valid) } diff --git a/eth/stagedsync/chain_reader.go b/eth/stagedsync/chain_reader.go index 862cae5710a..f1d0e52057e 100644 --- a/eth/stagedsync/chain_reader.go +++ b/eth/stagedsync/chain_reader.go @@ -4,23 +4,24 @@ import ( "context" "math/big" + "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon/rlp" - "github.com/ledgerwatch/erigon/turbo/services" - "github.com/ledgerwatch/log/v3" - "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/rlp" + "github.com/ledgerwatch/erigon/turbo/services" ) -// Implements consensus.ChainReader +// ChainReader implements consensus.ChainReader type ChainReader struct { Cfg chain.Config Db kv.Getter BlockReader services.FullBlockReader + Logger log.Logger } // Config retrieves the blockchain's chain configuration. @@ -81,10 +82,16 @@ func (cr ChainReader) FrozenBlocks() uint64 { return cr.BlockReader.FrozenBlocks() } -func (cr ChainReader) BorEventsByBlock(hash libcommon.Hash, number uint64) []rlp.RawValue { - panic("") +func (cr ChainReader) BorEventsByBlock(_ libcommon.Hash, _ uint64) []rlp.RawValue { + panic("bor events by block not implemented") } func (cr ChainReader) BorSpan(spanId uint64) []byte { - panic("") + span, err := cr.BlockReader.Span(context.Background(), cr.Db, spanId) + if err != nil { + cr.Logger.Error("BorSpan failed", "err", err) + return nil + } + + return span } diff --git a/eth/stagedsync/stage_bodies.go b/eth/stagedsync/stage_bodies.go index 62811264323..c10aaae4438 100644 --- a/eth/stagedsync/stage_bodies.go +++ b/eth/stagedsync/stage_bodies.go @@ -6,14 +6,14 @@ import ( "runtime" "time" + "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/dbg" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/rawdb/blockio" - "github.com/ledgerwatch/log/v3" - "github.com/ledgerwatch/erigon/dataflow" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" "github.com/ledgerwatch/erigon/turbo/adapter" @@ -134,7 +134,7 @@ func BodiesForward( prevProgress := bodyProgress var noProgressCount uint = 0 // How many time the progress was printed without actual progress var totalDelivered uint64 = 0 - cr := ChainReader{Cfg: cfg.chanConfig, Db: tx, BlockReader: cfg.blockReader} + cr := ChainReader{Cfg: cfg.chanConfig, Db: tx, BlockReader: cfg.blockReader, Logger: logger} loopBody := func() (bool, error) { // loopCount is used here to ensure we don't get caught in a constant loop of making requests diff --git a/eth/stagedsync/stage_headers.go b/eth/stagedsync/stage_headers.go index aa60d348ae7..839d7842468 100644 --- a/eth/stagedsync/stage_headers.go +++ b/eth/stagedsync/stage_headers.go @@ -9,19 +9,19 @@ import ( "time" "github.com/c2h5oh/datasize" + "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/dbg" "github.com/ledgerwatch/erigon-lib/common/hexutility" "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon/core/rawdb/blockio" - "github.com/ledgerwatch/erigon/eth/ethconfig" - "github.com/ledgerwatch/erigon/eth/stagedsync/stages" - "github.com/ledgerwatch/log/v3" - "github.com/ledgerwatch/erigon/common" "github.com/ledgerwatch/erigon/core/rawdb" + "github.com/ledgerwatch/erigon/core/rawdb/blockio" "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/eth/ethconfig" + "github.com/ledgerwatch/erigon/eth/stagedsync/stages" "github.com/ledgerwatch/erigon/rlp" "github.com/ledgerwatch/erigon/turbo/engineapi/engine_helpers" "github.com/ledgerwatch/erigon/turbo/services" @@ -183,7 +183,12 @@ func HeadersPOW( } TEMP TESTING */ headerInserter := headerdownload.NewHeaderInserter(logPrefix, localTd, startProgress, cfg.blockReader) - cfg.hd.SetHeaderReader(&ChainReaderImpl{config: &cfg.chainConfig, tx: tx, blockReader: cfg.blockReader}) + cfg.hd.SetHeaderReader(&ChainReaderImpl{ + config: &cfg.chainConfig, + tx: tx, + blockReader: cfg.blockReader, + logger: logger, + }) stopped := false var noProgressCounter uint = 0 diff --git a/eth/stagedsync/stage_mining_create_block.go b/eth/stagedsync/stage_mining_create_block.go index 5016d4afa02..40b63680e16 100644 --- a/eth/stagedsync/stage_mining_create_block.go +++ b/eth/stagedsync/stage_mining_create_block.go @@ -8,11 +8,10 @@ import ( "time" mapset "github.com/deckarep/golang-set/v2" - "github.com/ledgerwatch/erigon-lib/chain" - libcommon "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon/turbo/services" "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/chain" + libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon/common/debug" "github.com/ledgerwatch/erigon/consensus" @@ -22,6 +21,7 @@ import ( "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/eth/ethutils" "github.com/ledgerwatch/erigon/params" + "github.com/ledgerwatch/erigon/turbo/services" ) type MiningBlock struct { @@ -127,7 +127,7 @@ func SpawnMiningCreateBlockStage(s *StageState, tx kv.RwTx, cfg MiningCreateBloc if err != nil { return err } - chain := ChainReader{Cfg: cfg.chainConfig, Db: tx, BlockReader: cfg.blockReader} + chain := ChainReader{Cfg: cfg.chainConfig, Db: tx, BlockReader: cfg.blockReader, Logger: logger} var GetBlocksFromHash = func(hash libcommon.Hash, n int) (blocks []*types.Block) { number := rawdb.ReadHeaderNumber(tx, hash) if number == nil { diff --git a/eth/stagedsync/stage_mining_exec.go b/eth/stagedsync/stage_mining_exec.go index d2ad47f6fb0..abc94326dc0 100644 --- a/eth/stagedsync/stage_mining_exec.go +++ b/eth/stagedsync/stage_mining_exec.go @@ -10,15 +10,14 @@ import ( mapset "github.com/deckarep/golang-set/v2" "github.com/holiman/uint256" - "github.com/ledgerwatch/erigon-lib/kv/membatch" "github.com/ledgerwatch/log/v3" "golang.org/x/net/context" "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon-lib/kv/membatch" types2 "github.com/ledgerwatch/erigon-lib/types" - "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/core/rawdb" @@ -89,7 +88,7 @@ func SpawnMiningExecStage(s *StageState, tx kv.RwTx, cfg MiningExecCfg, quit <-c ibs := state.New(stateReader) stateWriter := state.NewPlainStateWriter(tx, tx, current.Header.Number.Uint64()) - chainReader := ChainReader{Cfg: cfg.chainConfig, Db: tx, BlockReader: cfg.blockReader} + chainReader := ChainReader{Cfg: cfg.chainConfig, Db: tx, BlockReader: cfg.blockReader, Logger: logger} core.InitializeBlockExecution(cfg.engine, chainReader, current.Header, &cfg.chainConfig, ibs, logger) // Create an empty block based on temporary copied state for @@ -163,7 +162,7 @@ func SpawnMiningExecStage(s *StageState, tx kv.RwTx, cfg MiningExecCfg, quit <-c } var err error - _, current.Txs, current.Receipts, err = core.FinalizeBlockExecution(cfg.engine, stateReader, current.Header, current.Txs, current.Uncles, stateWriter, &cfg.chainConfig, ibs, current.Receipts, current.Withdrawals, ChainReaderImpl{config: &cfg.chainConfig, tx: tx, blockReader: cfg.blockReader}, true, logger) + _, current.Txs, current.Receipts, err = core.FinalizeBlockExecution(cfg.engine, stateReader, current.Header, current.Txs, current.Uncles, stateWriter, &cfg.chainConfig, ibs, current.Receipts, current.Withdrawals, ChainReaderImpl{config: &cfg.chainConfig, tx: tx, blockReader: cfg.blockReader, logger: logger}, true, logger) if err != nil { return err } diff --git a/eth/stagedsync/stage_mining_finish.go b/eth/stagedsync/stage_mining_finish.go index 16d90e00667..81cc486e57c 100644 --- a/eth/stagedsync/stage_mining_finish.go +++ b/eth/stagedsync/stage_mining_finish.go @@ -3,14 +3,14 @@ package stagedsync import ( "fmt" - "github.com/ledgerwatch/erigon-lib/chain" - "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon/turbo/builder" - "github.com/ledgerwatch/erigon/turbo/services" "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/chain" + "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/turbo/builder" + "github.com/ledgerwatch/erigon/turbo/services" ) type MiningFinishCfg struct { @@ -95,7 +95,7 @@ func SpawnMiningFinishStage(s *StageState, tx kv.RwTx, cfg MiningFinishCfg, quit default: logger.Trace("No in-flight sealing task.") } - chain := ChainReader{Cfg: cfg.chainConfig, Db: tx, BlockReader: cfg.blockReader} + chain := ChainReader{Cfg: cfg.chainConfig, Db: tx, BlockReader: cfg.blockReader, Logger: logger} if err := cfg.engine.Seal(chain, block, cfg.miningState.MiningResultCh, cfg.sealCancel); err != nil { logger.Warn("Block sealing failed", "err", err) } From e958d3584d0812c985a4158d1f51c3863c4b2695 Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Sat, 6 Jan 2024 21:49:23 +0100 Subject: [PATCH 06/92] Added Heads method to Beacon API (#9135) --- cl/beacon/handler/forkchoice.go | 39 +++++++++ cl/beacon/handler/forkchoice_test.go | 80 +++++++++++++++++ cl/beacon/handler/handler.go | 6 +- cl/beacon/handler/node.go | 20 +++++ cl/beacon/handler/node_test.go | 49 +++++++++++ cl/beacon/synced_data/synced_data.go | 5 +- .../historical_states_reader_test.go | 6 +- cl/phase1/forkchoice/forkchoice.go | 86 +++++++++++++++++-- cl/phase1/forkchoice/forkchoice_mock.go | 5 ++ cl/phase1/forkchoice/get_head.go | 54 ++++++++++-- cl/phase1/forkchoice/interface.go | 1 + cl/phase1/forkchoice/on_attestation.go | 51 ++++++++++- cl/phase1/forkchoice/on_attester_slashing.go | 2 +- cl/phase1/forkchoice/on_block.go | 3 + cl/phase1/forkchoice/utils.go | 1 + cl/phase1/stages/clstages.go | 19 ++-- 16 files changed, 392 insertions(+), 35 deletions(-) create mode 100644 cl/beacon/handler/forkchoice.go create mode 100644 cl/beacon/handler/forkchoice_test.go create mode 100644 cl/beacon/handler/node.go create mode 100644 cl/beacon/handler/node_test.go diff --git a/cl/beacon/handler/forkchoice.go b/cl/beacon/handler/forkchoice.go new file mode 100644 index 00000000000..4f7f845b707 --- /dev/null +++ b/cl/beacon/handler/forkchoice.go @@ -0,0 +1,39 @@ +package handler + +import ( + "encoding/json" + "net/http" + + "github.com/ledgerwatch/erigon/cl/beacon/beaconhttp" +) + +func (a *ApiHandler) GetEthV2DebugBeaconHeads(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { + if a.syncedData.Syncing() { + return nil, beaconhttp.NewEndpointError(http.StatusServiceUnavailable, "beacon node is syncing") + } + hash, slotNumber, err := a.forkchoiceStore.GetHead() + if err != nil { + return nil, err + } + return newBeaconResponse( + []interface{}{ + map[string]interface{}{ + "slot": slotNumber, + "root": hash, + "execution_optimistic": false, + }, + }), nil +} + +func (a *ApiHandler) GetEthV1DebugBeaconForkChoice(w http.ResponseWriter, r *http.Request) { + justifiedCheckpoint := a.forkchoiceStore.JustifiedCheckpoint() + finalizedCheckpoint := a.forkchoiceStore.FinalizedCheckpoint() + forkNodes := a.forkchoiceStore.ForkNodes() + if err := json.NewEncoder(w).Encode(map[string]interface{}{ + "justified_checkpoint": justifiedCheckpoint, + "finalized_checkpoint": finalizedCheckpoint, + "fork_choice_nodes": forkNodes, + }); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } +} diff --git a/cl/beacon/handler/forkchoice_test.go b/cl/beacon/handler/forkchoice_test.go new file mode 100644 index 00000000000..8b98997f815 --- /dev/null +++ b/cl/beacon/handler/forkchoice_test.go @@ -0,0 +1,80 @@ +package handler + +import ( + "io" + "net/http/httptest" + "testing" + + libcommon "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon/cl/clparams" + "github.com/ledgerwatch/erigon/cl/cltypes/solid" + "github.com/ledgerwatch/erigon/cl/phase1/forkchoice" + "github.com/stretchr/testify/require" +) + +func TestGetHeads(t *testing.T) { + // find server + _, _, _, _, p, handler, _, sm, fcu := setupTestingHandler(t, clparams.Phase0Version) + sm.OnHeadState(p) + s, cancel := sm.HeadState() + s.SetSlot(789274827847783) + cancel() + + fcu.HeadSlotVal = 128 + fcu.HeadVal = libcommon.Hash{1, 2, 3} + server := httptest.NewServer(handler.mux) + defer server.Close() + + // get heads + resp, err := server.Client().Get(server.URL + "/eth/v2/debug/beacon/heads") + require.NoError(t, err) + defer resp.Body.Close() + + require.Equal(t, 200, resp.StatusCode) + out, err := io.ReadAll(resp.Body) + require.NoError(t, err) + + require.Equal(t, `{"data":[{"execution_optimistic":false,"root":"0x0102030000000000000000000000000000000000000000000000000000000000","slot":128}]}`+"\n", string(out)) +} + +func TestGetForkchoice(t *testing.T) { + // find server + _, _, _, _, p, handler, _, sm, fcu := setupTestingHandler(t, clparams.Phase0Version) + sm.OnHeadState(p) + s, cancel := sm.HeadState() + s.SetSlot(789274827847783) + cancel() + + fcu.HeadSlotVal = 128 + fcu.HeadVal = libcommon.Hash{1, 2, 3} + server := httptest.NewServer(handler.mux) + defer server.Close() + + fcu.WeightsMock = []forkchoice.ForkNode{ + { + BlockRoot: libcommon.Hash{1, 2, 3}, + ParentRoot: libcommon.Hash{1, 2, 3}, + Slot: 128, + Weight: 1, + }, + { + BlockRoot: libcommon.Hash{1, 2, 2, 4, 5, 3}, + ParentRoot: libcommon.Hash{1, 2, 5}, + Slot: 128, + Weight: 2, + }, + } + + fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(libcommon.Hash{1, 2, 3}, 1) + fcu.JustifiedCheckpointVal = solid.NewCheckpointFromParameters(libcommon.Hash{1, 2, 3}, 2) + + // get heads + resp, err := server.Client().Get(server.URL + "/eth/v1/debug/fork_choice") + require.NoError(t, err) + defer resp.Body.Close() + + require.Equal(t, 200, resp.StatusCode) + out, err := io.ReadAll(resp.Body) + require.NoError(t, err) + require.Equal(t, `{"finalized_checkpoint":{"epoch":"1","root":"0x0102030000000000000000000000000000000000000000000000000000000000"},"fork_choice_nodes":[{"slot":"128","block_root":"0x0102030000000000000000000000000000000000000000000000000000000000","parent_root":"0x0102030000000000000000000000000000000000000000000000000000000000","justified_epoch":"0","finalized_epoch":"0","weight":"1","validity":"","execution_block_hash":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"slot":"128","block_root":"0x0102020405030000000000000000000000000000000000000000000000000000","parent_root":"0x0102050000000000000000000000000000000000000000000000000000000000","justified_epoch":"0","finalized_epoch":"0","weight":"2","validity":"","execution_block_hash":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"justified_checkpoint":{"epoch":"2","root":"0x0102030000000000000000000000000000000000000000000000000000000000"}}`+"\n", string(out)) +} diff --git a/cl/beacon/handler/handler.go b/cl/beacon/handler/handler.go index fb4e5aa63f6..eb2fc2e90f6 100644 --- a/cl/beacon/handler/handler.go +++ b/cl/beacon/handler/handler.go @@ -49,8 +49,11 @@ func (a *ApiHandler) init() { // otterscn specific ones are commented as such r.Route("/eth", func(r chi.Router) { r.Route("/v1", func(r chi.Router) { - r.Get("/events", http.NotFound) + r.Route("/node", func(r chi.Router) { + r.Get("/health", a.GetEthV1NodeHealth) + }) + r.Get("/debug/fork_choice", a.GetEthV1DebugBeaconForkChoice) r.Route("/config", func(r chi.Router) { r.Get("/spec", beaconhttp.HandleEndpointFunc(a.getSpec)) r.Get("/deposit_contract", beaconhttp.HandleEndpointFunc(a.getDepositContract)) @@ -125,6 +128,7 @@ func (a *ApiHandler) init() { r.Route("/debug", func(r chi.Router) { r.Route("/beacon", func(r chi.Router) { r.Get("/states/{state_id}", beaconhttp.HandleEndpointFunc(a.getFullState)) + r.Get("/heads", beaconhttp.HandleEndpointFunc(a.GetEthV2DebugBeaconHeads)) }) }) r.Route("/beacon", func(r chi.Router) { diff --git a/cl/beacon/handler/node.go b/cl/beacon/handler/node.go new file mode 100644 index 00000000000..26f4fc46f0d --- /dev/null +++ b/cl/beacon/handler/node.go @@ -0,0 +1,20 @@ +package handler + +import "net/http" + +func (a *ApiHandler) GetEthV1NodeHealth(w http.ResponseWriter, r *http.Request) { + syncingStatus, err := uint64FromQueryParams(r, "syncing_status") + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + syncingCode := http.StatusOK + if syncingStatus != nil { + syncingCode = int(*syncingStatus) + } + if a.syncedData.Syncing() { + w.WriteHeader(syncingCode) + return + } + w.WriteHeader(http.StatusOK) +} diff --git a/cl/beacon/handler/node_test.go b/cl/beacon/handler/node_test.go new file mode 100644 index 00000000000..094412ddd7e --- /dev/null +++ b/cl/beacon/handler/node_test.go @@ -0,0 +1,49 @@ +package handler + +import ( + "net/http" + "net/http/httptest" + "testing" + + "github.com/ledgerwatch/erigon/cl/clparams" + "github.com/stretchr/testify/require" +) + +func TestNodeSyncing(t *testing.T) { + // i just want the correct schema to be generated + _, _, _, _, _, handler, _, _, _ := setupTestingHandler(t, clparams.Phase0Version) + + // Call GET /eth/v1/node/health + server := httptest.NewServer(handler.mux) + defer server.Close() + + req, err := http.NewRequest("GET", server.URL+"/eth/v1/node/health?syncing_status=666", nil) + require.NoError(t, err) + + resp, err := http.DefaultClient.Do(req) + require.NoError(t, err) + defer resp.Body.Close() + require.Equal(t, 666, resp.StatusCode) +} + +func TestNodeSyncingTip(t *testing.T) { + // i just want the correct schema to be generated + _, _, _, _, post, handler, _, sm, _ := setupTestingHandler(t, clparams.Phase0Version) + + // Call GET /eth/v1/node/health + server := httptest.NewServer(handler.mux) + defer server.Close() + + req, err := http.NewRequest("GET", server.URL+"/eth/v1/node/health?syncing_status=666", nil) + require.NoError(t, err) + + require.NoError(t, sm.OnHeadState(post)) + s, cancel := sm.HeadState() + s.SetSlot(999999999999999) + cancel() + + resp, err := http.DefaultClient.Do(req) + require.NoError(t, err) + defer resp.Body.Close() + require.Equal(t, 200, resp.StatusCode) +} diff --git a/cl/beacon/synced_data/synced_data.go b/cl/beacon/synced_data/synced_data.go index c8de023f888..0d6f7e0789f 100644 --- a/cl/beacon/synced_data/synced_data.go +++ b/cl/beacon/synced_data/synced_data.go @@ -32,6 +32,9 @@ func (s *SyncedDataManager) OnHeadState(newState *state.CachingBeaconState) (err defer s.mu.Unlock() if s.headState == nil { s.headState, err = newState.Copy() + if err != nil { + return err + } } err = newState.CopyInto(s.headState) if err != nil { @@ -56,7 +59,7 @@ func (s *SyncedDataManager) Syncing() bool { s.mu.RLock() defer s.mu.RUnlock() if s.headState == nil { - return false + return true } headEpoch := utils.GetCurrentEpoch(s.headState.GenesisTime(), s.cfg.SecondsPerSlot, s.cfg.SlotsPerEpoch) diff --git a/cl/persistence/state/historical_states_reader/historical_states_reader_test.go b/cl/persistence/state/historical_states_reader/historical_states_reader_test.go index cc98f2ac304..cec53451589 100644 --- a/cl/persistence/state/historical_states_reader/historical_states_reader_test.go +++ b/cl/persistence/state/historical_states_reader/historical_states_reader_test.go @@ -47,19 +47,19 @@ func runTest(t *testing.T, blocks []*cltypes.SignedBeaconBlock, preState, postSt } func TestStateAntiquaryCapella(t *testing.T) { - //t.Skip() + t.Skip() blocks, preState, postState := tests.GetCapellaRandom() runTest(t, blocks, preState, postState) } func TestStateAntiquaryPhase0(t *testing.T) { - //t.Skip() + t.Skip() blocks, preState, postState := tests.GetPhase0Random() runTest(t, blocks, preState, postState) } func TestStateAntiquaryBellatrix(t *testing.T) { - //t.Skip() + t.Skip() blocks, preState, postState := tests.GetBellatrixRandom() runTest(t, blocks, preState, postState) } diff --git a/cl/phase1/forkchoice/forkchoice.go b/cl/phase1/forkchoice/forkchoice.go index f6533b96ebb..bde4d322f37 100644 --- a/cl/phase1/forkchoice/forkchoice.go +++ b/cl/phase1/forkchoice/forkchoice.go @@ -2,6 +2,7 @@ package forkchoice import ( "context" + "sort" "sync" "github.com/ledgerwatch/erigon/cl/clparams" @@ -20,6 +21,31 @@ import ( "github.com/ledgerwatch/erigon-lib/common/length" ) +// Schema +/* +{ + "slot": "1", + "block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "parent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "justified_epoch": "1", + "finalized_epoch": "1", + "weight": "1", + "validity": "valid", + "execution_block_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "extra_data": {} + } +*/ +type ForkNode struct { + Slot uint64 `json:"slot,string"` + BlockRoot libcommon.Hash `json:"block_root"` + ParentRoot libcommon.Hash `json:"parent_root"` + JustifiedEpoch uint64 `json:"justified_epoch,string"` + FinalizedEpoch uint64 `json:"finalized_epoch,string"` + Weight uint64 `json:"weight,string"` + Validity string `json:"validity"` + ExecutionBlock libcommon.Hash `json:"execution_block_hash"` +} + type checkpointComparable string const ( @@ -53,17 +79,21 @@ type ForkChoiceStore struct { unrealizedJustifiedCheckpoint solid.Checkpoint unrealizedFinalizedCheckpoint solid.Checkpoint proposerBoostRoot libcommon.Hash - headHash libcommon.Hash - headSlot uint64 - genesisTime uint64 - childrens map[libcommon.Hash]childrens + // head data + headHash libcommon.Hash + headSlot uint64 + genesisTime uint64 + weights map[libcommon.Hash]uint64 + headSet map[libcommon.Hash]struct{} + // childrens + childrens map[libcommon.Hash]childrens // Use go map because this is actually an unordered set - equivocatingIndicies map[uint64]struct{} + equivocatingIndicies []byte forkGraph fork_graph.ForkGraph // I use the cache due to the convenient auto-cleanup feauture. checkpointStates map[checkpointComparable]*checkpointState // We keep ssz snappy of it as the full beacon state is full of rendundant data. - latestMessages map[uint64]*LatestMessage + latestMessages []LatestMessage anchorPublicKeys []byte // We keep track of them so that we can forkchoice with EL. eth2Roots *lru.Cache[libcommon.Hash, libcommon.Hash] // ETH2 root -> ETH1 hash @@ -163,6 +193,8 @@ func NewForkChoiceStore(ctx context.Context, anchorState *state2.CachingBeaconSt r := solid.NewHashVector(int(anchorState.BeaconConfig().EpochsPerHistoricalVector)) anchorState.RandaoMixes().CopyTo(r) randaoMixesLists.Add(anchorRoot, r) + headSet := make(map[libcommon.Hash]struct{}) + headSet[anchorRoot] = struct{}{} return &ForkChoiceStore{ ctx: ctx, highestSeen: anchorState.Slot(), @@ -172,8 +204,8 @@ func NewForkChoiceStore(ctx context.Context, anchorState *state2.CachingBeaconSt unrealizedJustifiedCheckpoint: anchorCheckpoint.Copy(), unrealizedFinalizedCheckpoint: anchorCheckpoint.Copy(), forkGraph: forkGraph, - equivocatingIndicies: map[uint64]struct{}{}, - latestMessages: map[uint64]*LatestMessage{}, + equivocatingIndicies: make([]byte, anchorState.ValidatorLength(), anchorState.ValidatorLength()*2), + latestMessages: make([]LatestMessage, anchorState.ValidatorLength(), anchorState.ValidatorLength()*2), checkpointStates: make(map[checkpointComparable]*checkpointState), eth2Roots: eth2Roots, engine: engine, @@ -188,6 +220,8 @@ func NewForkChoiceStore(ctx context.Context, anchorState *state2.CachingBeaconSt totalActiveBalances: totalActiveBalances, randaoMixesLists: randaoMixesLists, randaoDeltas: randaoDeltas, + headSet: headSet, + weights: make(map[libcommon.Hash]uint64), participation: participation, }, nil } @@ -399,3 +433,39 @@ func (f *ForkChoiceStore) RandaoMixes(blockRoot libcommon.Hash, out solid.HashLi func (f *ForkChoiceStore) Partecipation(epoch uint64) (*solid.BitList, bool) { return f.participation.Get(epoch) } + +func (f *ForkChoiceStore) ForkNodes() []ForkNode { + f.mu.Lock() + defer f.mu.Unlock() + forkNodes := make([]ForkNode, 0, len(f.weights)) + for blockRoot, weight := range f.weights { + header, has := f.forkGraph.GetHeader(blockRoot) + if !has { + continue + } + justifiedCheckpoint, has := f.forkGraph.GetCurrentJustifiedCheckpoint(blockRoot) + if !has { + continue + } + finalizedCheckpoint, has := f.forkGraph.GetFinalizedCheckpoint(blockRoot) + if !has { + continue + } + blockHash, _ := f.eth2Roots.Get(blockRoot) + + forkNodes = append(forkNodes, ForkNode{ + Weight: weight, + BlockRoot: blockRoot, + ParentRoot: header.ParentRoot, + JustifiedEpoch: justifiedCheckpoint.Epoch(), + FinalizedEpoch: finalizedCheckpoint.Epoch(), + Slot: header.Slot, + Validity: "valid", + ExecutionBlock: blockHash, + }) + } + sort.Slice(forkNodes, func(i, j int) bool { + return forkNodes[i].Slot < forkNodes[j].Slot + }) + return forkNodes +} diff --git a/cl/phase1/forkchoice/forkchoice_mock.go b/cl/phase1/forkchoice/forkchoice_mock.go index 16f8ee6b0af..6ae413d4f96 100644 --- a/cl/phase1/forkchoice/forkchoice_mock.go +++ b/cl/phase1/forkchoice/forkchoice_mock.go @@ -66,6 +66,7 @@ type ForkChoiceStorageMock struct { StateAtSlotVal map[uint64]*state.CachingBeaconState GetSyncCommitteesVal map[common.Hash][2]*solid.SyncCommittee GetFinalityCheckpointsVal map[common.Hash][3]solid.Checkpoint + WeightsMock []ForkNode Pool pool.OperationsPool } @@ -215,3 +216,7 @@ func (f *ForkChoiceStorageMock) OnBlsToExecutionChange(signedChange *cltypes.Sig f.Pool.BLSToExecutionChangesPool.Insert(signedChange.Signature, signedChange) return nil } + +func (f *ForkChoiceStorageMock) ForkNodes() []ForkNode { + return f.WeightsMock +} diff --git a/cl/phase1/forkchoice/get_head.go b/cl/phase1/forkchoice/get_head.go index e1300c2c022..56165f4a2bc 100644 --- a/cl/phase1/forkchoice/get_head.go +++ b/cl/phase1/forkchoice/get_head.go @@ -16,6 +16,23 @@ func (f *ForkChoiceStore) GetHead() (libcommon.Hash, uint64, error) { return f.getHead() } +// accountWeights updates the weights of the validators, given the vote and given an head leaf. +func (f *ForkChoiceStore) accountWeights(votes, weights map[libcommon.Hash]uint64, justifedRoot, leaf libcommon.Hash) { + curr := leaf + accumulated := uint64(0) + for curr != justifedRoot { + accumulated += votes[curr] + votes[curr] = 0 // make sure we don't double count + weights[curr] += accumulated + header, has := f.forkGraph.GetHeader(curr) + if !has { + return + } + curr = header.ParentRoot + } + return +} + func (f *ForkChoiceStore) getHead() (libcommon.Hash, uint64, error) { if f.headHash != (libcommon.Hash{}) { return f.headHash, f.headSlot, nil @@ -28,8 +45,33 @@ func (f *ForkChoiceStore) getHead() (libcommon.Hash, uint64, error) { if err != nil { return libcommon.Hash{}, 0, err } - // Filter all validators deemed as bad - filteredIndicies := f.filterValidatorSetForAttestationScores(justificationState, justificationState.epoch) + // Do a simple scan to determine the fork votes. + votes := make(map[libcommon.Hash]uint64) + for validatorIndex, message := range f.latestMessages { + if message == (LatestMessage{}) { + continue + } + if !readFromBitset(justificationState.actives, validatorIndex) || readFromBitset(justificationState.slasheds, validatorIndex) { + continue + } + if _, hasLatestMessage := f.getLatestMessage(uint64(validatorIndex)); !hasLatestMessage { + continue + } + if f.isUnequivocating(uint64(validatorIndex)) { + continue + } + votes[message.Root] += justificationState.balances[validatorIndex] + } + if f.proposerBoostRoot != (libcommon.Hash{}) { + boost := justificationState.activeBalance / justificationState.beaconConfig.SlotsPerEpoch + votes[f.proposerBoostRoot] += (boost * justificationState.beaconConfig.ProposerScoreBoost) / 100 + } + // Account for weights on each head fork + f.weights = make(map[libcommon.Hash]uint64) + for head := range f.headSet { + f.accountWeights(votes, f.weights, f.justifiedCheckpoint.BlockRoot(), head) + } + for { // Filter out current head children. unfilteredChildren := f.children(f.headHash) @@ -62,9 +104,9 @@ func (f *ForkChoiceStore) getHead() (libcommon.Hash, uint64, error) { // After sorting is done determine best fit. f.headHash = children[0] - maxWeight := f.getWeight(children[0], filteredIndicies, justificationState) + maxWeight := f.weights[children[0]] for i := 1; i < len(children); i++ { - weight := f.getWeight(children[i], filteredIndicies, justificationState) + weight := f.weights[children[i]] // Lexicographical order is king. if weight >= maxWeight { f.headHash = children[i] @@ -81,10 +123,10 @@ func (f *ForkChoiceStore) filterValidatorSetForAttestationScores(c *checkpointSt if !readFromBitset(c.actives, validatorIndex) || readFromBitset(c.slasheds, validatorIndex) { continue } - if _, hasLatestMessage := f.latestMessages[uint64(validatorIndex)]; !hasLatestMessage { + if _, hasLatestMessage := f.getLatestMessage(uint64(validatorIndex)); !hasLatestMessage { continue } - if _, isUnequivocating := f.equivocatingIndicies[uint64(validatorIndex)]; isUnequivocating { + if f.isUnequivocating(uint64(validatorIndex)) { continue } filtered = append(filtered, uint64(validatorIndex)) diff --git a/cl/phase1/forkchoice/interface.go b/cl/phase1/forkchoice/interface.go index 438db97f32c..7da33e5acbf 100644 --- a/cl/phase1/forkchoice/interface.go +++ b/cl/phase1/forkchoice/interface.go @@ -40,6 +40,7 @@ type ForkChoiceStorageReader interface { GetStateAtSlot(slot uint64, alwaysCopy bool) (*state.CachingBeaconState, error) GetStateAtStateRoot(root libcommon.Hash, alwaysCopy bool) (*state.CachingBeaconState, error) + ForkNodes() []ForkNode } type ForkChoiceStorageWriter interface { diff --git a/cl/phase1/forkchoice/on_attestation.go b/cl/phase1/forkchoice/on_attestation.go index ed4b0ce674c..ed734b4b8a7 100644 --- a/cl/phase1/forkchoice/on_attestation.go +++ b/cl/phase1/forkchoice/on_attestation.go @@ -85,20 +85,63 @@ func (f *ForkChoiceStore) scheduleAttestationForLaterProcessing(attestation *sol }() } +func (f *ForkChoiceStore) setLatestMessage(index uint64, message LatestMessage) { + if index >= uint64(len(f.latestMessages)) { + if index >= uint64(cap(f.latestMessages)) { + tmp := make([]LatestMessage, index+1, index*2) + copy(tmp, f.latestMessages) + f.latestMessages = tmp + } + f.latestMessages = f.latestMessages[:index+1] + } + f.latestMessages[index] = message +} + +func (f *ForkChoiceStore) getLatestMessage(validatorIndex uint64) (LatestMessage, bool) { + if validatorIndex >= uint64(len(f.latestMessages)) || f.latestMessages[validatorIndex] == (LatestMessage{}) { + return LatestMessage{}, false + } + return f.latestMessages[validatorIndex], true +} + +func (f *ForkChoiceStore) isUnequivocating(validatorIndex uint64) bool { + // f.equivocatingIndicies is a bitlist + index := int(validatorIndex) / 8 + if index >= len(f.equivocatingIndicies) { + return false + } + subIndex := int(validatorIndex) % 8 + return f.equivocatingIndicies[index]&(1<= len(f.equivocatingIndicies) { + if index >= cap(f.equivocatingIndicies) { + tmp := make([]byte, index+1, index*2) + copy(tmp, f.equivocatingIndicies) + f.equivocatingIndicies = tmp + } + f.equivocatingIndicies = f.equivocatingIndicies[:index+1] + } + subIndex := int(validatorIndex) % 8 + f.equivocatingIndicies[index] |= 1 << uint(subIndex) +} + func (f *ForkChoiceStore) processAttestingIndicies(attestation *solid.Attestation, indicies []uint64) { beaconBlockRoot := attestation.AttestantionData().BeaconBlockRoot() target := attestation.AttestantionData().Target() for _, index := range indicies { - if _, ok := f.equivocatingIndicies[index]; ok { + if f.isUnequivocating(index) { continue } - validatorMessage, has := f.latestMessages[index] + validatorMessage, has := f.getLatestMessage(index) if !has || target.Epoch() > validatorMessage.Epoch { - f.latestMessages[index] = &LatestMessage{ + f.setLatestMessage(index, LatestMessage{ Epoch: target.Epoch(), Root: beaconBlockRoot, - } + }) } } } diff --git a/cl/phase1/forkchoice/on_attester_slashing.go b/cl/phase1/forkchoice/on_attester_slashing.go index 1c4ea9d5dc3..4305ed58d08 100644 --- a/cl/phase1/forkchoice/on_attester_slashing.go +++ b/cl/phase1/forkchoice/on_attester_slashing.go @@ -86,7 +86,7 @@ func (f *ForkChoiceStore) OnAttesterSlashing(attesterSlashing *cltypes.AttesterS defer f.mu.Unlock() var anySlashed bool for _, index := range solid.IntersectionOfSortedSets(attestation1.AttestingIndices, attestation2.AttestingIndices) { - f.equivocatingIndicies[index] = struct{}{} + f.setUnequivocating(index) if !anySlashed { v, err := s.ValidatorForValidatorIndex(int(index)) if err != nil { diff --git a/cl/phase1/forkchoice/on_block.go b/cl/phase1/forkchoice/on_block.go index 06b28c5e772..627e16ac26f 100644 --- a/cl/phase1/forkchoice/on_block.go +++ b/cl/phase1/forkchoice/on_block.go @@ -66,6 +66,9 @@ func (f *ForkChoiceStore) OnBlock(block *cltypes.SignedBeaconBlock, newPayload, if block.Block.Slot > f.highestSeen { f.highestSeen = block.Block.Slot } + // Remove the parent from the head set + delete(f.headSet, block.Block.ParentRoot) + f.headSet[blockRoot] = struct{}{} // Add proposer score boost if the block is timely timeIntoSlot := (f.time - f.genesisTime) % lastProcessedState.BeaconConfig().SecondsPerSlot isBeforeAttestingInterval := timeIntoSlot < f.beaconCfg.SecondsPerSlot/f.beaconCfg.IntervalsPerSlot diff --git a/cl/phase1/forkchoice/utils.go b/cl/phase1/forkchoice/utils.go index b3eaca58da7..f13aee3dac4 100644 --- a/cl/phase1/forkchoice/utils.go +++ b/cl/phase1/forkchoice/utils.go @@ -41,6 +41,7 @@ func (f *ForkChoiceStore) onNewFinalized(newFinalized solid.Checkpoint) { for k, children := range f.childrens { if children.parentSlot <= newFinalized.Epoch()*f.beaconCfg.SlotsPerEpoch { delete(f.childrens, k) + delete(f.headSet, k) continue } } diff --git a/cl/phase1/stages/clstages.go b/cl/phase1/stages/clstages.go index 58cd687bd98..b2d57dd01a7 100644 --- a/cl/phase1/stages/clstages.go +++ b/cl/phase1/stages/clstages.go @@ -14,6 +14,7 @@ import ( "github.com/ledgerwatch/erigon/cl/clparams" "github.com/ledgerwatch/erigon/cl/clstages" "github.com/ledgerwatch/erigon/cl/cltypes" + "github.com/ledgerwatch/erigon/cl/cltypes/solid" "github.com/ledgerwatch/erigon/cl/persistence" "github.com/ledgerwatch/erigon/cl/persistence/beacon_indicies" "github.com/ledgerwatch/erigon/cl/persistence/db_config" @@ -403,6 +404,13 @@ func ConsensusClStages(ctx context.Context, cfg.rpc.BanPeer(blocks.Peer) continue MainLoop } + block.Block.Body.Attestations.Range(func(idx int, a *solid.Attestation, total int) bool { + if err = cfg.forkChoice.OnAttestation(a, true); err != nil { + log.Debug("bad attestation received", "err", err) + } + return true + }) + if block.Block.Slot >= args.targetSlot { break MainLoop } @@ -425,17 +433,6 @@ func ConsensusClStages(ctx context.Context, }, ActionFunc: func(ctx context.Context, logger log.Logger, cfg *Cfg, args Args) error { - // TODO: we need to get the last run block in order to process attestations here - ////////block.Block.Body.Attestations.Range(func(idx int, a *solid.Attestation, total int) bool { - //////// if err = g.forkChoice.OnAttestation(a, true); err != nil { - //////// return false - //////// } - //////// return true - ////////}) - ////////if err != nil { - //////// return err - ////////} - // Now check the head headRoot, headSlot, err := cfg.forkChoice.GetHead() if err != nil { From 235af8a321448a105d8c3442fc38521c0bc122e0 Mon Sep 17 00:00:00 2001 From: a Date: Sun, 7 Jan 2024 12:03:17 -0600 Subject: [PATCH 07/92] glob filter (#9148) --- cl/phase1/network/gossip_manager.go | 2 +- cl/sentinel/service/service.go | 19 +- erigon-lib/direct/sentinel_client.go | 2 +- erigon-lib/go.mod | 2 +- erigon-lib/go.sum | 4 +- .../gointerfaces/sentinel/sentinel.pb.go | 237 +++++++++++------- .../gointerfaces/sentinel/sentinel_grpc.pb.go | 10 +- 7 files changed, 179 insertions(+), 97 deletions(-) diff --git a/cl/phase1/network/gossip_manager.go b/cl/phase1/network/gossip_manager.go index d7a0543b3cc..1207c1e924b 100644 --- a/cl/phase1/network/gossip_manager.go +++ b/cl/phase1/network/gossip_manager.go @@ -165,7 +165,7 @@ func (g *GossipManager) onRecv(ctx context.Context, data *sentinel.GossipData, l } func (g *GossipManager) Start(ctx context.Context) { - subscription, err := g.sentinel.SubscribeGossip(ctx, &sentinel.EmptyMessage{}) + subscription, err := g.sentinel.SubscribeGossip(ctx, &sentinel.SubscriptionData{}) if err != nil { return } diff --git a/cl/sentinel/service/service.go b/cl/sentinel/service/service.go index d43b40cb6b5..218c54f1848 100644 --- a/cl/sentinel/service/service.go +++ b/cl/sentinel/service/service.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "net/http" + "path" "strconv" "strings" "sync" @@ -24,6 +25,8 @@ import ( "github.com/libp2p/go-libp2p/core/peer" ) +var _ sentinelrpc.SentinelServer = (*SentinelServer)(nil) + type SentinelServer struct { sentinelrpc.UnimplementedSentinelServer @@ -108,7 +111,7 @@ func (s *SentinelServer) PublishGossip(_ context.Context, msg *sentinelrpc.Gossi return &sentinelrpc.EmptyMessage{}, subscription.Publish(compressedData) } -func (s *SentinelServer) SubscribeGossip(_ *sentinelrpc.EmptyMessage, stream sentinelrpc.Sentinel_SubscribeGossipServer) error { +func (s *SentinelServer) SubscribeGossip(data *sentinelrpc.SubscriptionData, stream sentinelrpc.Sentinel_SubscribeGossipServer) error { // first of all subscribe ch, subId, err := s.gossipNotifier.addSubscriber() if err != nil { @@ -122,6 +125,9 @@ func (s *SentinelServer) SubscribeGossip(_ *sentinelrpc.EmptyMessage, stream sen case <-stream.Context().Done(): return nil case packet := <-ch: + if !s.gossipMatchSubscription(packet, data) { + continue + } if err := stream.Send(&sentinelrpc.GossipData{ Data: packet.data, Name: packet.t, @@ -135,6 +141,17 @@ func (s *SentinelServer) SubscribeGossip(_ *sentinelrpc.EmptyMessage, stream sen } } +func (s *SentinelServer) gossipMatchSubscription(obj gossipObject, data *sentinelrpc.SubscriptionData) bool { + if data.Filter != nil { + filter := data.GetFilter() + matched, err := path.Match(obj.t, filter) + if err != nil || !matched { + return false + } + } + return true +} + func (s *SentinelServer) withTimeoutCtx(pctx context.Context, dur time.Duration) (ctx context.Context, cn func()) { if dur > 0 { ctx, cn = context.WithTimeout(pctx, 8*time.Second) diff --git a/erigon-lib/direct/sentinel_client.go b/erigon-lib/direct/sentinel_client.go index f421f4332bf..4a196bddb33 100644 --- a/erigon-lib/direct/sentinel_client.go +++ b/erigon-lib/direct/sentinel_client.go @@ -64,7 +64,7 @@ func (s *SentinelClientDirect) PublishGossip(ctx context.Context, in *sentinel.G // Subscribe gossip part. the only complex section of this bullshit -func (s *SentinelClientDirect) SubscribeGossip(ctx context.Context, in *sentinel.EmptyMessage, opts ...grpc.CallOption) (sentinel.Sentinel_SubscribeGossipClient, error) { +func (s *SentinelClientDirect) SubscribeGossip(ctx context.Context, in *sentinel.SubscriptionData, opts ...grpc.CallOption) (sentinel.Sentinel_SubscribeGossipClient, error) { ch := make(chan *gossipReply, 16384) streamServer := &SentinelSubscribeGossipS{ch: ch, ctx: ctx} go func() { diff --git a/erigon-lib/go.mod b/erigon-lib/go.mod index 95e0dd8f5ec..acb9a2e6eb0 100644 --- a/erigon-lib/go.mod +++ b/erigon-lib/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( github.com/erigontech/mdbx-go v0.27.21 github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240101230756-23fbc6c56a1d - github.com/ledgerwatch/interfaces v0.0.0-20231209102305-b17e86fbe07d + github.com/ledgerwatch/interfaces v0.0.0-20240105165407-ac2eea9d3c55 github.com/ledgerwatch/log/v3 v3.9.0 github.com/ledgerwatch/secp256k1 v1.0.0 ) diff --git a/erigon-lib/go.sum b/erigon-lib/go.sum index 005ce3b3ce1..8d874b682fc 100644 --- a/erigon-lib/go.sum +++ b/erigon-lib/go.sum @@ -293,8 +293,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240101230756-23fbc6c56a1d h1:rMqDEGLdmVgGdpDmaNp4Do1vc9BtUQ3rjFD9gQBRSx0= github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240101230756-23fbc6c56a1d/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo= -github.com/ledgerwatch/interfaces v0.0.0-20231209102305-b17e86fbe07d h1:7aB9lKmUGAaWt4TzXnGLzJSZkhyuqREMmaao+Gn5Ky0= -github.com/ledgerwatch/interfaces v0.0.0-20231209102305-b17e86fbe07d/go.mod h1:ugQv1QllJzBny3cKZKxUrSnykkjkBgm27eQM6dnGAcc= +github.com/ledgerwatch/interfaces v0.0.0-20240105165407-ac2eea9d3c55 h1:Avbyef7Fyz5O9TkN/AoPy4NRXiRiFoYrG6Zp8CyRcrM= +github.com/ledgerwatch/interfaces v0.0.0-20240105165407-ac2eea9d3c55/go.mod h1:ugQv1QllJzBny3cKZKxUrSnykkjkBgm27eQM6dnGAcc= github.com/ledgerwatch/log/v3 v3.9.0 h1:iDwrXe0PVwBC68Dd94YSsHbMgQ3ufsgjzXtFNFVZFRk= github.com/ledgerwatch/log/v3 v3.9.0/go.mod h1:EiAY6upmI/6LkNhOVxb4eVsmsP11HZCnZ3PlJMjYiqE= github.com/ledgerwatch/secp256k1 v1.0.0 h1:Usvz87YoTG0uePIV8woOof5cQnLXGYa162rFf3YnwaQ= diff --git a/erigon-lib/gointerfaces/sentinel/sentinel.pb.go b/erigon-lib/gointerfaces/sentinel/sentinel.pb.go index 35477c388e4..0e4aec4df7a 100644 --- a/erigon-lib/gointerfaces/sentinel/sentinel.pb.go +++ b/erigon-lib/gointerfaces/sentinel/sentinel.pb.go @@ -59,6 +59,53 @@ func (*EmptyMessage) Descriptor() ([]byte, []int) { return file_p2psentinel_sentinel_proto_rawDescGZIP(), []int{0} } +type SubscriptionData struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Filter *string `protobuf:"bytes,1,opt,name=filter,proto3,oneof" json:"filter,omitempty"` +} + +func (x *SubscriptionData) Reset() { + *x = SubscriptionData{} + if protoimpl.UnsafeEnabled { + mi := &file_p2psentinel_sentinel_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SubscriptionData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SubscriptionData) ProtoMessage() {} + +func (x *SubscriptionData) ProtoReflect() protoreflect.Message { + mi := &file_p2psentinel_sentinel_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SubscriptionData.ProtoReflect.Descriptor instead. +func (*SubscriptionData) Descriptor() ([]byte, []int) { + return file_p2psentinel_sentinel_proto_rawDescGZIP(), []int{1} +} + +func (x *SubscriptionData) GetFilter() string { + if x != nil && x.Filter != nil { + return *x.Filter + } + return "" +} + type Peer struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -70,7 +117,7 @@ type Peer struct { func (x *Peer) Reset() { *x = Peer{} if protoimpl.UnsafeEnabled { - mi := &file_p2psentinel_sentinel_proto_msgTypes[1] + mi := &file_p2psentinel_sentinel_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -83,7 +130,7 @@ func (x *Peer) String() string { func (*Peer) ProtoMessage() {} func (x *Peer) ProtoReflect() protoreflect.Message { - mi := &file_p2psentinel_sentinel_proto_msgTypes[1] + mi := &file_p2psentinel_sentinel_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -96,7 +143,7 @@ func (x *Peer) ProtoReflect() protoreflect.Message { // Deprecated: Use Peer.ProtoReflect.Descriptor instead. func (*Peer) Descriptor() ([]byte, []int) { - return file_p2psentinel_sentinel_proto_rawDescGZIP(), []int{1} + return file_p2psentinel_sentinel_proto_rawDescGZIP(), []int{2} } func (x *Peer) GetPid() string { @@ -119,7 +166,7 @@ type GossipData struct { func (x *GossipData) Reset() { *x = GossipData{} if protoimpl.UnsafeEnabled { - mi := &file_p2psentinel_sentinel_proto_msgTypes[2] + mi := &file_p2psentinel_sentinel_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -132,7 +179,7 @@ func (x *GossipData) String() string { func (*GossipData) ProtoMessage() {} func (x *GossipData) ProtoReflect() protoreflect.Message { - mi := &file_p2psentinel_sentinel_proto_msgTypes[2] + mi := &file_p2psentinel_sentinel_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -145,7 +192,7 @@ func (x *GossipData) ProtoReflect() protoreflect.Message { // Deprecated: Use GossipData.ProtoReflect.Descriptor instead. func (*GossipData) Descriptor() ([]byte, []int) { - return file_p2psentinel_sentinel_proto_rawDescGZIP(), []int{2} + return file_p2psentinel_sentinel_proto_rawDescGZIP(), []int{3} } func (x *GossipData) GetData() []byte { @@ -184,7 +231,7 @@ type Status struct { func (x *Status) Reset() { *x = Status{} if protoimpl.UnsafeEnabled { - mi := &file_p2psentinel_sentinel_proto_msgTypes[3] + mi := &file_p2psentinel_sentinel_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -197,7 +244,7 @@ func (x *Status) String() string { func (*Status) ProtoMessage() {} func (x *Status) ProtoReflect() protoreflect.Message { - mi := &file_p2psentinel_sentinel_proto_msgTypes[3] + mi := &file_p2psentinel_sentinel_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -210,7 +257,7 @@ func (x *Status) ProtoReflect() protoreflect.Message { // Deprecated: Use Status.ProtoReflect.Descriptor instead. func (*Status) Descriptor() ([]byte, []int) { - return file_p2psentinel_sentinel_proto_rawDescGZIP(), []int{3} + return file_p2psentinel_sentinel_proto_rawDescGZIP(), []int{4} } func (x *Status) GetForkDigest() uint32 { @@ -259,7 +306,7 @@ type PeerCount struct { func (x *PeerCount) Reset() { *x = PeerCount{} if protoimpl.UnsafeEnabled { - mi := &file_p2psentinel_sentinel_proto_msgTypes[4] + mi := &file_p2psentinel_sentinel_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -272,7 +319,7 @@ func (x *PeerCount) String() string { func (*PeerCount) ProtoMessage() {} func (x *PeerCount) ProtoReflect() protoreflect.Message { - mi := &file_p2psentinel_sentinel_proto_msgTypes[4] + mi := &file_p2psentinel_sentinel_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -285,7 +332,7 @@ func (x *PeerCount) ProtoReflect() protoreflect.Message { // Deprecated: Use PeerCount.ProtoReflect.Descriptor instead. func (*PeerCount) Descriptor() ([]byte, []int) { - return file_p2psentinel_sentinel_proto_rawDescGZIP(), []int{4} + return file_p2psentinel_sentinel_proto_rawDescGZIP(), []int{5} } func (x *PeerCount) GetAmount() uint64 { @@ -307,7 +354,7 @@ type RequestData struct { func (x *RequestData) Reset() { *x = RequestData{} if protoimpl.UnsafeEnabled { - mi := &file_p2psentinel_sentinel_proto_msgTypes[5] + mi := &file_p2psentinel_sentinel_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -320,7 +367,7 @@ func (x *RequestData) String() string { func (*RequestData) ProtoMessage() {} func (x *RequestData) ProtoReflect() protoreflect.Message { - mi := &file_p2psentinel_sentinel_proto_msgTypes[5] + mi := &file_p2psentinel_sentinel_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -333,7 +380,7 @@ func (x *RequestData) ProtoReflect() protoreflect.Message { // Deprecated: Use RequestData.ProtoReflect.Descriptor instead. func (*RequestData) Descriptor() ([]byte, []int) { - return file_p2psentinel_sentinel_proto_rawDescGZIP(), []int{5} + return file_p2psentinel_sentinel_proto_rawDescGZIP(), []int{6} } func (x *RequestData) GetData() []byte { @@ -363,7 +410,7 @@ type ResponseData struct { func (x *ResponseData) Reset() { *x = ResponseData{} if protoimpl.UnsafeEnabled { - mi := &file_p2psentinel_sentinel_proto_msgTypes[6] + mi := &file_p2psentinel_sentinel_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -376,7 +423,7 @@ func (x *ResponseData) String() string { func (*ResponseData) ProtoMessage() {} func (x *ResponseData) ProtoReflect() protoreflect.Message { - mi := &file_p2psentinel_sentinel_proto_msgTypes[6] + mi := &file_p2psentinel_sentinel_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -389,7 +436,7 @@ func (x *ResponseData) ProtoReflect() protoreflect.Message { // Deprecated: Use ResponseData.ProtoReflect.Descriptor instead. func (*ResponseData) Descriptor() ([]byte, []int) { - return file_p2psentinel_sentinel_proto_rawDescGZIP(), []int{6} + return file_p2psentinel_sentinel_proto_rawDescGZIP(), []int{7} } func (x *ResponseData) GetData() []byte { @@ -420,43 +467,47 @@ var file_p2psentinel_sentinel_proto_rawDesc = []byte{ 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x08, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x1a, 0x11, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x0e, 0x0a, 0x0c, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x18, 0x0a, 0x04, 0x50, 0x65, 0x65, - 0x72, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, - 0x70, 0x69, 0x64, 0x22, 0x66, 0x0a, 0x0a, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x44, 0x61, 0x74, - 0x61, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x04, 0x70, 0x65, 0x65, - 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, - 0x65, 0x6c, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x48, 0x00, 0x52, 0x04, 0x70, 0x65, 0x65, 0x72, 0x88, - 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x22, 0xcd, 0x01, 0x0a, 0x06, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x64, - 0x69, 0x67, 0x65, 0x73, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x66, 0x6f, 0x72, - 0x6b, 0x44, 0x69, 0x67, 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x0e, 0x66, 0x69, 0x6e, 0x61, 0x6c, - 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x48, 0x32, 0x35, 0x36, 0x52, 0x0d, 0x66, 0x69, - 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x66, - 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, - 0x70, 0x6f, 0x63, 0x68, 0x12, 0x28, 0x0a, 0x09, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x72, 0x6f, 0x6f, - 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, - 0x48, 0x32, 0x35, 0x36, 0x52, 0x08, 0x68, 0x65, 0x61, 0x64, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1b, - 0x0a, 0x09, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x08, 0x68, 0x65, 0x61, 0x64, 0x53, 0x6c, 0x6f, 0x74, 0x22, 0x23, 0x0a, 0x09, 0x50, - 0x65, 0x65, 0x72, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, - 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, - 0x22, 0x37, 0x0a, 0x0b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, - 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, - 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x22, 0x5c, 0x0a, 0x0c, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, - 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, - 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x12, 0x22, 0x0a, 0x04, 0x70, 0x65, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x0e, 0x2e, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x2e, 0x50, 0x65, 0x65, - 0x72, 0x52, 0x04, 0x70, 0x65, 0x65, 0x72, 0x32, 0x90, 0x04, 0x0a, 0x08, 0x53, 0x65, 0x6e, 0x74, - 0x69, 0x6e, 0x65, 0x6c, 0x12, 0x41, 0x0a, 0x0f, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, - 0x65, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x12, 0x16, 0x2e, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, - 0x65, 0x6c, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, + 0x74, 0x79, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x3a, 0x0a, 0x10, 0x53, 0x75, 0x62, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1b, 0x0a, + 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, + 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x66, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x18, 0x0a, 0x04, 0x50, 0x65, 0x65, 0x72, 0x12, 0x10, 0x0a, + 0x03, 0x70, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x64, 0x22, + 0x66, 0x0a, 0x0a, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x44, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, + 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, + 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x04, 0x70, 0x65, 0x65, 0x72, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x2e, 0x50, + 0x65, 0x65, 0x72, 0x48, 0x00, 0x52, 0x04, 0x70, 0x65, 0x65, 0x72, 0x88, 0x01, 0x01, 0x42, 0x07, + 0x0a, 0x05, 0x5f, 0x70, 0x65, 0x65, 0x72, 0x22, 0xcd, 0x01, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x64, 0x69, 0x67, 0x65, 0x73, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x66, 0x6f, 0x72, 0x6b, 0x44, 0x69, 0x67, + 0x65, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x0e, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, + 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2e, 0x48, 0x32, 0x35, 0x36, 0x52, 0x0d, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, + 0x7a, 0x65, 0x64, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x66, 0x69, 0x6e, 0x61, 0x6c, + 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x65, 0x70, 0x6f, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, + 0x52, 0x0e, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x64, 0x45, 0x70, 0x6f, 0x63, 0x68, + 0x12, 0x28, 0x0a, 0x09, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x48, 0x32, 0x35, 0x36, + 0x52, 0x08, 0x68, 0x65, 0x61, 0x64, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x68, 0x65, + 0x61, 0x64, 0x5f, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x68, + 0x65, 0x61, 0x64, 0x53, 0x6c, 0x6f, 0x74, 0x22, 0x23, 0x0a, 0x09, 0x50, 0x65, 0x65, 0x72, 0x43, + 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x37, 0x0a, 0x0b, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x64, + 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, + 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x74, 0x6f, 0x70, 0x69, 0x63, 0x22, 0x5c, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, + 0x22, 0x0a, 0x04, 0x70, 0x65, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, + 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x52, 0x04, 0x70, + 0x65, 0x65, 0x72, 0x32, 0x94, 0x04, 0x0a, 0x08, 0x53, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, + 0x12, 0x45, 0x0a, 0x0f, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x47, 0x6f, 0x73, + 0x73, 0x69, 0x70, 0x12, 0x1a, 0x2e, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x2e, 0x53, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x61, 0x1a, 0x14, 0x2e, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, 0x6c, 0x2e, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x44, 0x61, 0x74, 0x61, 0x30, 0x01, 0x12, 0x3c, 0x0a, 0x0b, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x2e, 0x73, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x65, @@ -503,35 +554,36 @@ func file_p2psentinel_sentinel_proto_rawDescGZIP() []byte { return file_p2psentinel_sentinel_proto_rawDescData } -var file_p2psentinel_sentinel_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_p2psentinel_sentinel_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_p2psentinel_sentinel_proto_goTypes = []interface{}{ - (*EmptyMessage)(nil), // 0: sentinel.EmptyMessage - (*Peer)(nil), // 1: sentinel.Peer - (*GossipData)(nil), // 2: sentinel.GossipData - (*Status)(nil), // 3: sentinel.Status - (*PeerCount)(nil), // 4: sentinel.PeerCount - (*RequestData)(nil), // 5: sentinel.RequestData - (*ResponseData)(nil), // 6: sentinel.ResponseData - (*types.H256)(nil), // 7: types.H256 + (*EmptyMessage)(nil), // 0: sentinel.EmptyMessage + (*SubscriptionData)(nil), // 1: sentinel.SubscriptionData + (*Peer)(nil), // 2: sentinel.Peer + (*GossipData)(nil), // 3: sentinel.GossipData + (*Status)(nil), // 4: sentinel.Status + (*PeerCount)(nil), // 5: sentinel.PeerCount + (*RequestData)(nil), // 6: sentinel.RequestData + (*ResponseData)(nil), // 7: sentinel.ResponseData + (*types.H256)(nil), // 8: types.H256 } var file_p2psentinel_sentinel_proto_depIdxs = []int32{ - 1, // 0: sentinel.GossipData.peer:type_name -> sentinel.Peer - 7, // 1: sentinel.Status.finalized_root:type_name -> types.H256 - 7, // 2: sentinel.Status.head_root:type_name -> types.H256 - 1, // 3: sentinel.ResponseData.peer:type_name -> sentinel.Peer - 0, // 4: sentinel.Sentinel.SubscribeGossip:input_type -> sentinel.EmptyMessage - 5, // 5: sentinel.Sentinel.SendRequest:input_type -> sentinel.RequestData - 3, // 6: sentinel.Sentinel.SetStatus:input_type -> sentinel.Status + 2, // 0: sentinel.GossipData.peer:type_name -> sentinel.Peer + 8, // 1: sentinel.Status.finalized_root:type_name -> types.H256 + 8, // 2: sentinel.Status.head_root:type_name -> types.H256 + 2, // 3: sentinel.ResponseData.peer:type_name -> sentinel.Peer + 1, // 4: sentinel.Sentinel.SubscribeGossip:input_type -> sentinel.SubscriptionData + 6, // 5: sentinel.Sentinel.SendRequest:input_type -> sentinel.RequestData + 4, // 6: sentinel.Sentinel.SetStatus:input_type -> sentinel.Status 0, // 7: sentinel.Sentinel.GetPeers:input_type -> sentinel.EmptyMessage - 1, // 8: sentinel.Sentinel.BanPeer:input_type -> sentinel.Peer - 1, // 9: sentinel.Sentinel.UnbanPeer:input_type -> sentinel.Peer - 1, // 10: sentinel.Sentinel.PenalizePeer:input_type -> sentinel.Peer - 1, // 11: sentinel.Sentinel.RewardPeer:input_type -> sentinel.Peer - 2, // 12: sentinel.Sentinel.PublishGossip:input_type -> sentinel.GossipData - 2, // 13: sentinel.Sentinel.SubscribeGossip:output_type -> sentinel.GossipData - 6, // 14: sentinel.Sentinel.SendRequest:output_type -> sentinel.ResponseData + 2, // 8: sentinel.Sentinel.BanPeer:input_type -> sentinel.Peer + 2, // 9: sentinel.Sentinel.UnbanPeer:input_type -> sentinel.Peer + 2, // 10: sentinel.Sentinel.PenalizePeer:input_type -> sentinel.Peer + 2, // 11: sentinel.Sentinel.RewardPeer:input_type -> sentinel.Peer + 3, // 12: sentinel.Sentinel.PublishGossip:input_type -> sentinel.GossipData + 3, // 13: sentinel.Sentinel.SubscribeGossip:output_type -> sentinel.GossipData + 7, // 14: sentinel.Sentinel.SendRequest:output_type -> sentinel.ResponseData 0, // 15: sentinel.Sentinel.SetStatus:output_type -> sentinel.EmptyMessage - 4, // 16: sentinel.Sentinel.GetPeers:output_type -> sentinel.PeerCount + 5, // 16: sentinel.Sentinel.GetPeers:output_type -> sentinel.PeerCount 0, // 17: sentinel.Sentinel.BanPeer:output_type -> sentinel.EmptyMessage 0, // 18: sentinel.Sentinel.UnbanPeer:output_type -> sentinel.EmptyMessage 0, // 19: sentinel.Sentinel.PenalizePeer:output_type -> sentinel.EmptyMessage @@ -563,7 +615,7 @@ func file_p2psentinel_sentinel_proto_init() { } } file_p2psentinel_sentinel_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Peer); i { + switch v := v.(*SubscriptionData); i { case 0: return &v.state case 1: @@ -575,7 +627,7 @@ func file_p2psentinel_sentinel_proto_init() { } } file_p2psentinel_sentinel_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GossipData); i { + switch v := v.(*Peer); i { case 0: return &v.state case 1: @@ -587,7 +639,7 @@ func file_p2psentinel_sentinel_proto_init() { } } file_p2psentinel_sentinel_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Status); i { + switch v := v.(*GossipData); i { case 0: return &v.state case 1: @@ -599,7 +651,7 @@ func file_p2psentinel_sentinel_proto_init() { } } file_p2psentinel_sentinel_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PeerCount); i { + switch v := v.(*Status); i { case 0: return &v.state case 1: @@ -611,7 +663,7 @@ func file_p2psentinel_sentinel_proto_init() { } } file_p2psentinel_sentinel_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RequestData); i { + switch v := v.(*PeerCount); i { case 0: return &v.state case 1: @@ -623,6 +675,18 @@ func file_p2psentinel_sentinel_proto_init() { } } file_p2psentinel_sentinel_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RequestData); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_p2psentinel_sentinel_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ResponseData); i { case 0: return &v.state @@ -635,14 +699,15 @@ func file_p2psentinel_sentinel_proto_init() { } } } - file_p2psentinel_sentinel_proto_msgTypes[2].OneofWrappers = []interface{}{} + file_p2psentinel_sentinel_proto_msgTypes[1].OneofWrappers = []interface{}{} + file_p2psentinel_sentinel_proto_msgTypes[3].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_p2psentinel_sentinel_proto_rawDesc, NumEnums: 0, - NumMessages: 7, + NumMessages: 8, NumExtensions: 0, NumServices: 1, }, diff --git a/erigon-lib/gointerfaces/sentinel/sentinel_grpc.pb.go b/erigon-lib/gointerfaces/sentinel/sentinel_grpc.pb.go index a62786b600f..34a47f5e43e 100644 --- a/erigon-lib/gointerfaces/sentinel/sentinel_grpc.pb.go +++ b/erigon-lib/gointerfaces/sentinel/sentinel_grpc.pb.go @@ -34,7 +34,7 @@ const ( // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type SentinelClient interface { - SubscribeGossip(ctx context.Context, in *EmptyMessage, opts ...grpc.CallOption) (Sentinel_SubscribeGossipClient, error) + SubscribeGossip(ctx context.Context, in *SubscriptionData, opts ...grpc.CallOption) (Sentinel_SubscribeGossipClient, error) SendRequest(ctx context.Context, in *RequestData, opts ...grpc.CallOption) (*ResponseData, error) SetStatus(ctx context.Context, in *Status, opts ...grpc.CallOption) (*EmptyMessage, error) GetPeers(ctx context.Context, in *EmptyMessage, opts ...grpc.CallOption) (*PeerCount, error) @@ -53,7 +53,7 @@ func NewSentinelClient(cc grpc.ClientConnInterface) SentinelClient { return &sentinelClient{cc} } -func (c *sentinelClient) SubscribeGossip(ctx context.Context, in *EmptyMessage, opts ...grpc.CallOption) (Sentinel_SubscribeGossipClient, error) { +func (c *sentinelClient) SubscribeGossip(ctx context.Context, in *SubscriptionData, opts ...grpc.CallOption) (Sentinel_SubscribeGossipClient, error) { stream, err := c.cc.NewStream(ctx, &Sentinel_ServiceDesc.Streams[0], Sentinel_SubscribeGossip_FullMethodName, opts...) if err != nil { return nil, err @@ -161,7 +161,7 @@ func (c *sentinelClient) PublishGossip(ctx context.Context, in *GossipData, opts // All implementations must embed UnimplementedSentinelServer // for forward compatibility type SentinelServer interface { - SubscribeGossip(*EmptyMessage, Sentinel_SubscribeGossipServer) error + SubscribeGossip(*SubscriptionData, Sentinel_SubscribeGossipServer) error SendRequest(context.Context, *RequestData) (*ResponseData, error) SetStatus(context.Context, *Status) (*EmptyMessage, error) GetPeers(context.Context, *EmptyMessage) (*PeerCount, error) @@ -177,7 +177,7 @@ type SentinelServer interface { type UnimplementedSentinelServer struct { } -func (UnimplementedSentinelServer) SubscribeGossip(*EmptyMessage, Sentinel_SubscribeGossipServer) error { +func (UnimplementedSentinelServer) SubscribeGossip(*SubscriptionData, Sentinel_SubscribeGossipServer) error { return status.Errorf(codes.Unimplemented, "method SubscribeGossip not implemented") } func (UnimplementedSentinelServer) SendRequest(context.Context, *RequestData) (*ResponseData, error) { @@ -218,7 +218,7 @@ func RegisterSentinelServer(s grpc.ServiceRegistrar, srv SentinelServer) { } func _Sentinel_SubscribeGossip_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(EmptyMessage) + m := new(SubscriptionData) if err := stream.RecvMsg(m); err != nil { return err } From 15ff41876c5c000b7b5bdcdeca0dbfe8bff5a5b9 Mon Sep 17 00:00:00 2001 From: Mark Holt <135143369+mh0lt@users.noreply.github.com> Date: Mon, 8 Jan 2024 00:10:45 +0000 Subject: [PATCH 08/92] Change retire progress log level to debug (#9153) This moved the log level of retire progress messaging to debug, to avoid log nose on qa and test runs --- eth/stagedsync/stage_snapshots.go | 2 +- turbo/snapshotsync/freezeblocks/bor_snapshots.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/eth/stagedsync/stage_snapshots.go b/eth/stagedsync/stage_snapshots.go index 7be716c40b5..7ef851ff0b4 100644 --- a/eth/stagedsync/stage_snapshots.go +++ b/eth/stagedsync/stage_snapshots.go @@ -434,7 +434,7 @@ func SnapshotsPrune(s *PruneState, initialCycle bool, cfg SnapshotsCfg, ctx cont minBlockNumber = cfg.snapshotUploader.minBlockNumber() } - cfg.blockRetire.RetireBlocksInBackground(ctx, minBlockNumber, s.ForwardProgress, log.LvlInfo, func(downloadRequest []services.DownloadRequest) error { + cfg.blockRetire.RetireBlocksInBackground(ctx, minBlockNumber, s.ForwardProgress, log.LvlDebug, func(downloadRequest []services.DownloadRequest) error { if cfg.snapshotDownloader != nil && !reflect.ValueOf(cfg.snapshotDownloader).IsNil() { if err := snapshotsync.RequestSnapshotsDownload(ctx, downloadRequest, cfg.snapshotDownloader); err != nil { return err diff --git a/turbo/snapshotsync/freezeblocks/bor_snapshots.go b/turbo/snapshotsync/freezeblocks/bor_snapshots.go index 91d181ba960..62ff94ec83a 100644 --- a/turbo/snapshotsync/freezeblocks/bor_snapshots.go +++ b/turbo/snapshotsync/freezeblocks/bor_snapshots.go @@ -194,7 +194,7 @@ func (br *BlockRetire) retireBorBlocks(ctx context.Context, minBlockNum uint64, merger := NewBorMerger(tmpDir, workers, lvl, db, chainConfig, notifier, logger) rangesToMerge := merger.FindMergeRanges(snapshots.Ranges()) - logger.Warn("[bor snapshots] Retire Bor Blocks", "rangesToMerge", fmt.Sprintf("%s", Ranges(rangesToMerge))) + logger.Log(lvl, "[bor snapshots] Retire Bor Blocks", "rangesToMerge", fmt.Sprintf("%s", Ranges(rangesToMerge))) if len(rangesToMerge) == 0 { return ok, nil } From 134dc8573e712d41f130c4c74bb0446e3d9a8a27 Mon Sep 17 00:00:00 2001 From: Arpit Temani Date: Mon, 8 Jan 2024 12:26:08 +0530 Subject: [PATCH 09/92] add amoy bootnodes (#9158) this PR adds amoy bootnodes to the configuration --- core/allocs/amoy.json | 2 +- params/bootnodes.go | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/core/allocs/amoy.json b/core/allocs/amoy.json index df3d74e4526..5cdc8e52465 100644 --- a/core/allocs/amoy.json +++ b/core/allocs/amoy.json @@ -14,4 +14,4 @@ "6aB3d36C46ecFb9B9c0bD51CB1c3da5A2C81cea6": { "balance": "0x3635c9adc5dea00000" } -} \ No newline at end of file +} diff --git a/params/bootnodes.go b/params/bootnodes.go index 5b250aa7791..5e7734c7484 100644 --- a/params/bootnodes.go +++ b/params/bootnodes.go @@ -109,7 +109,10 @@ var V5Bootnodes = []string{ "enr:-Ku4QEWzdnVtXc2Q0ZVigfCGggOVB2Vc1ZCPEc6j21NIFLODSJbvNaef1g4PxhPwl_3kax86YPheFUSLXPRs98vvYsoBh2F0dG5ldHOIAAAAAAAAAACEZXRoMpC1MD8qAAAAAP__________gmlkgnY0gmlwhDZBrP2Jc2VjcDI1NmsxoQM6jr8Rb1ktLEsVcKAPa08wCsKUmvoQ8khiOl_SLozf9IN1ZHCCIyg", } -var AmoyBootnodes = []string{} // Todo: Add BorAmoy bootnodes +var AmoyBootnodes = []string{ + "enode://bce861be777e91b0a5a49d58a51e14f32f201b4c6c2d1fbea6c7a1f14756cbb3f931f3188d6b65de8b07b53ff28d03b6e366d09e56360d2124a9fc5a15a0913d@54.217.171.196:30303", + "enode://4a3dc0081a346d26a73d79dd88216a9402d2292318e2db9947dbc97ea9c4afb2498dc519c0af04420dc13a238c279062da0320181e7c1461216ce4513bfd40bf@13.251.184.185:30303", +} var BorMainnetBootnodes = []string{ "enode://b8f1cc9c5d4403703fbf377116469667d2b1823c0daf16b7250aa576bacf399e42c3930ccfcb02c5df6879565a2b8931335565f0e8d3f8e72385ecf4a4bf160a@3.36.224.80:30303", From fe9bc35e1e3c52dcb8d41e320aad473799a430fc Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Mon, 8 Jan 2024 09:42:47 +0100 Subject: [PATCH 10/92] Added GetEth1V1BuilderStatesExpectedWithdrawals (#9152) --- cl/beacon/handler/builder.go | 69 ++++++++++++++++++++++++++++++++++++ cl/beacon/handler/format.go | 2 +- cl/beacon/handler/handler.go | 1 + 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 cl/beacon/handler/builder.go diff --git a/cl/beacon/handler/builder.go b/cl/beacon/handler/builder.go new file mode 100644 index 00000000000..d7174008681 --- /dev/null +++ b/cl/beacon/handler/builder.go @@ -0,0 +1,69 @@ +package handler + +import ( + "net/http" + + libcommon "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon/cl/beacon/beaconhttp" + "github.com/ledgerwatch/erigon/cl/clparams" + "github.com/ledgerwatch/erigon/cl/persistence/beacon_indicies" + "github.com/ledgerwatch/erigon/cl/phase1/core/state" +) + +func (a *ApiHandler) GetEth1V1BuilderStatesExpectedWit(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { + ctx := r.Context() + + tx, err := a.indiciesDB.BeginRo(ctx) + if err != nil { + return nil, err + } + defer tx.Rollback() + + blockId, err := stateIdFromRequest(r) + if err != nil { + return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) + } + root, httpStatus, err := a.blockRootFromStateId(ctx, tx, blockId) + if err != nil { + return nil, beaconhttp.NewEndpointError(httpStatus, err.Error()) + } + slot, err := beacon_indicies.ReadBlockSlotByBlockRoot(tx, root) + if err != nil { + return nil, err + } + if slot == nil { + return nil, beaconhttp.NewEndpointError(http.StatusNotFound, "state not found") + } + if a.beaconChainCfg.GetCurrentStateVersion(*slot/a.beaconChainCfg.SlotsPerEpoch) < clparams.CapellaVersion { + return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, "the specified state is not a capella state") + } + headRoot, _, err := a.forkchoiceStore.GetHead() + if err != nil { + return nil, err + } + if root == headRoot { + s, cn := a.syncedData.HeadState() + defer cn() + return newBeaconResponse(state.ExpectedWithdrawals(s)).withFinalized(false), nil + } + lookAhead := 1024 + for currSlot := *slot + 1; currSlot < *slot+uint64(lookAhead); currSlot++ { + if currSlot > a.syncedData.HeadSlot() { + return nil, beaconhttp.NewEndpointError(http.StatusNotFound, "state not found") + } + blockRoot, err := beacon_indicies.ReadCanonicalBlockRoot(tx, currSlot) + if err != nil { + return nil, err + } + if blockRoot == (libcommon.Hash{}) { + continue + } + blk, err := a.blockReader.ReadBlockByRoot(ctx, tx, blockRoot) + if err != nil { + return nil, err + } + return newBeaconResponse(blk.Block.Body.ExecutionPayload.Withdrawals).withFinalized(false), nil + } + + return nil, beaconhttp.NewEndpointError(http.StatusNotFound, "state not found") +} diff --git a/cl/beacon/handler/format.go b/cl/beacon/handler/format.go index 7baa88b42f2..3a96cf6e8c0 100644 --- a/cl/beacon/handler/format.go +++ b/cl/beacon/handler/format.go @@ -170,7 +170,7 @@ func stateIdFromRequest(r *http.Request) (*segmentID, error) { stateId := chi.URLParam(r, "state_id") if !regex.MatchString(stateId) { - return nil, fmt.Errorf("invalid path variable: {block_id}") + return nil, fmt.Errorf("invalid path variable: {state_id}") } if stateId == "head" { diff --git a/cl/beacon/handler/handler.go b/cl/beacon/handler/handler.go index eb2fc2e90f6..9ead9cb0b2f 100644 --- a/cl/beacon/handler/handler.go +++ b/cl/beacon/handler/handler.go @@ -49,6 +49,7 @@ func (a *ApiHandler) init() { // otterscn specific ones are commented as such r.Route("/eth", func(r chi.Router) { r.Route("/v1", func(r chi.Router) { + r.Get("/builder/states/{state_id}/expected_withdrawals", beaconhttp.HandleEndpointFunc(a.GetEth1V1BuilderStatesExpectedWit)) r.Get("/events", http.NotFound) r.Route("/node", func(r chi.Router) { r.Get("/health", a.GetEthV1NodeHealth) From 2cbe8b7fe7ab089ee4ef6d673b295f2343514256 Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Mon, 8 Jan 2024 16:01:02 +0700 Subject: [PATCH 11/92] downloader: `--verify --verify.files --verify.failfast` support (#9156) --- cmd/downloader/main.go | 64 ++++++------- erigon-lib/downloader/downloader.go | 82 ++++++++--------- .../downloader/downloader_grpc_server.go | 8 +- erigon-lib/downloader/torrent_files.go | 12 ++- erigon-lib/downloader/util.go | 90 ++++++++++++++++++- erigon-lib/downloader/webseed.go | 2 +- 6 files changed, 167 insertions(+), 91 deletions(-) diff --git a/cmd/downloader/main.go b/cmd/downloader/main.go index 7db4324abb6..18e7c0d6fa9 100644 --- a/cmd/downloader/main.go +++ b/cmd/downloader/main.go @@ -7,7 +7,6 @@ import ( "net" "os" "path/filepath" - "runtime" "strings" "time" @@ -60,8 +59,10 @@ var ( datadirCli, chain string filePath string forceRebuild bool - forceVerify bool - forceVerifyFiles []string + verify bool + verifyFailfast bool + _verifyFiles string + verifyFiles []string downloaderApiAddr string natSetting string torrentVerbosity int @@ -96,8 +97,9 @@ func init() { rootCmd.Flags().BoolVar(&disableIPV6, "downloader.disable.ipv6", utils.DisableIPV6.Value, utils.DisableIPV6.Usage) rootCmd.Flags().BoolVar(&disableIPV4, "downloader.disable.ipv4", utils.DisableIPV4.Value, utils.DisableIPV6.Usage) rootCmd.Flags().BoolVar(&seedbox, "seedbox", false, "Turns downloader into independent (doesn't need Erigon) software which discover/download/seed new files - useful for Erigon network, and can work on very cheap hardware. It will: 1) download .torrent from webseed 2) download new files after upgrade 3) we planing add discovery of new files soon") - rootCmd.PersistentFlags().BoolVar(&forceVerify, "verify", false, "Verify files. All by default, or passed by --verify.files") - rootCmd.PersistentFlags().StringArrayVar(&forceVerifyFiles, "verify.files", nil, "Limit list of files to verify") + rootCmd.PersistentFlags().BoolVar(&verify, "verify", false, utils.DownloaderVerifyFlag.Usage) + rootCmd.PersistentFlags().StringVar(&_verifyFiles, "verify.files", "", "Limit list of files to verify") + rootCmd.PersistentFlags().BoolVar(&verifyFailfast, "verify.failfast", false, "Stop on first found error. Report it and exit") withDataDir(createTorrent) withFile(createTorrent) @@ -191,7 +193,7 @@ func Downloader(ctx context.Context, logger log.Logger) error { return err } - cfg.ClientConfig.PieceHashersPerTorrent = 32 * runtime.NumCPU() + cfg.ClientConfig.PieceHashersPerTorrent = 32 cfg.ClientConfig.DisableIPv6 = disableIPV6 cfg.ClientConfig.DisableIPv4 = disableIPV4 @@ -210,20 +212,12 @@ func Downloader(ctx context.Context, logger log.Logger) error { defer d.Close() logger.Info("[snapshots] Start bittorrent server", "my_peer_id", fmt.Sprintf("%x", d.TorrentClient().PeerID())) - if forceVerify { // remove and create .torrent files (will re-read all snapshots) - if err = d.VerifyData(ctx, forceVerifyFiles); err != nil { - return err - } - logger.Info("[snapshots] Verify done") - return nil - } - - d.MainLoopInBackground(false) - if err := addPreConfiguredHashes(ctx, d); err != nil { return err } + d.MainLoopInBackground(false) + bittorrentServer, err := downloader.NewGrpcServer(d) if err != nil { return fmt.Errorf("new server: %w", err) @@ -235,6 +229,13 @@ func Downloader(ctx context.Context, logger log.Logger) error { } defer grpcServer.GracefulStop() + verifyFiles = strings.Split(_verifyFiles, ",") + if verify || verifyFailfast || len(verifyFiles) > 0 { // remove and create .torrent files (will re-read all snapshots) + if err = d.VerifyData(ctx, verifyFiles, verifyFailfast); err != nil { + return err + } + } + <-ctx.Done() return nil } @@ -277,23 +278,6 @@ var manifestCmd = &cobra.Command{ }, } -var torrentVerify = &cobra.Command{ - Use: "torrent_verify", - Example: "go run ./cmd/downloader torrent_verify ", - RunE: func(cmd *cobra.Command, args []string) error { - if len(args) == 0 { - return fmt.Errorf("please pass .torrent file path by first argument") - } - fPath := args[0] - mi, err := metainfo.LoadFromFile(fPath) - if err != nil { - return fmt.Errorf("LoadFromFile: %w, file=%s", err, fPath) - } - - fmt.Printf("%s\n", mi.HashInfoBytes()) - return nil - }, -} var torrentCat = &cobra.Command{ Use: "torrent_cat", Example: "go run ./cmd/downloader torrent_cat ", @@ -306,8 +290,13 @@ var torrentCat = &cobra.Command{ if err != nil { return fmt.Errorf("LoadFromFile: %w, file=%s", err, fPath) } - - fmt.Printf("%s\n", mi.HashInfoBytes()) + fmt.Printf("InfoHash = '%x'\n", mi.HashInfoBytes()) + mi.InfoBytes = nil + bytes, err := toml.Marshal(mi) + if err != nil { + return err + } + fmt.Printf("%s\n", string(bytes)) return nil }, } @@ -407,7 +396,10 @@ func doPrintTorrentHashes(ctx context.Context, logger log.Logger) error { for _, t := range torrents { // we don't release commitment history in this time. let's skip it here. - if strings.HasPrefix(t.DisplayName, "history/v1-commitment") || strings.HasPrefix(t.DisplayName, "idx/v1-commitment") { + if strings.Contains(t.DisplayName, "history") && strings.Contains(t.DisplayName, "commitment") { + continue + } + if strings.Contains(t.DisplayName, "idx") && strings.Contains(t.DisplayName, "commitment") { continue } res[t.DisplayName] = t.InfoHash.String() diff --git a/erigon-lib/downloader/downloader.go b/erigon-lib/downloader/downloader.go index 6f7d87a8d60..8a42ed2c21f 100644 --- a/erigon-lib/downloader/downloader.go +++ b/erigon-lib/downloader/downloader.go @@ -33,6 +33,11 @@ import ( "github.com/anacrolix/torrent/metainfo" "github.com/anacrolix/torrent/storage" "github.com/c2h5oh/datasize" + "github.com/ledgerwatch/log/v3" + "golang.org/x/exp/slices" + "golang.org/x/sync/errgroup" + "golang.org/x/sync/semaphore" + "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/datadir" "github.com/ledgerwatch/erigon-lib/common/dbg" @@ -42,10 +47,6 @@ import ( "github.com/ledgerwatch/erigon-lib/downloader/snaptype" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/mdbx" - "github.com/ledgerwatch/log/v3" - "golang.org/x/exp/slices" - "golang.org/x/sync/errgroup" - "golang.org/x/sync/semaphore" ) // Downloader - component which downloading historical files. Can use BitTorrent, or other protocols @@ -487,54 +488,35 @@ func getPeersRatesForlogs(peersOfThisFile []*torrent.PeerConn, fName string) ([] return rates, averageRate } -func VerifyFile(ctx context.Context, t *torrent.Torrent, completePieces *atomic.Uint64) error { - select { - case <-ctx.Done(): - return ctx.Err() - case <-t.GotInfo(): - } - - g := &errgroup.Group{} - for i := 0; i < t.NumPieces(); i++ { - i := i - g.Go(func() error { - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - - t.Piece(i).VerifyData() - completePieces.Add(1) - return nil - }) - //<-t.Complete.On() - } - return g.Wait() -} - -func (d *Downloader) VerifyData(ctx context.Context, onlyFiles []string) error { +func (d *Downloader) VerifyData(ctx context.Context, whiteList []string, failFast bool) error { total := 0 - _torrents := d.torrentClient.Torrents() - torrents := make([]*torrent.Torrent, 0, len(_torrents)) - for _, t := range torrents { + allTorrents := d.torrentClient.Torrents() + toVerify := make([]*torrent.Torrent, 0, len(allTorrents)) + for _, t := range allTorrents { select { case <-t.GotInfo(): - if len(onlyFiles) > 0 && !slices.Contains(onlyFiles, t.Name()) { - continue - } - torrents = append(torrents, t) - total += t.NumPieces() case <-ctx.Done(): return ctx.Err() } + + if len(whiteList) > 0 { + name := t.Name() + exactOrPartialMatch := slices.ContainsFunc(whiteList, func(s string) bool { + return name == s || strings.HasSuffix(name, s) || strings.HasPrefix(name, s) + }) + if !exactOrPartialMatch { + continue + } + } + toVerify = append(toVerify, t) + total += t.NumPieces() } + d.logger.Info("[snapshots] Verify start") + defer d.logger.Info("[snapshots] Verify done", "files", len(toVerify), "whiteList", whiteList) completedPieces := &atomic.Uint64{} { - d.logger.Info("[snapshots] Verify start") - defer d.logger.Info("[snapshots] Verify done") logEvery := time.NewTicker(20 * time.Second) defer logEvery.Stop() d.wg.Add(1) @@ -555,11 +537,13 @@ func (d *Downloader) VerifyData(ctx context.Context, onlyFiles []string) error { // torrent lib internally limiting amount of hashers per file // set limit here just to make load predictable, not to control Disk/CPU consumption g.SetLimit(runtime.GOMAXPROCS(-1) * 4) - - for _, t := range torrents { + for _, t := range toVerify { t := t g.Go(func() error { - return VerifyFile(ctx, t, completedPieces) + if failFast { + return VerifyFileFailFast(ctx, t, d.SnapDir(), completedPieces) + } + return ScheduleVerifyFile(ctx, t, completedPieces) }) } @@ -666,15 +650,19 @@ func seedableFiles(dirs datadir.Dirs) ([]string, error) { if err != nil { return nil, fmt.Errorf("seedableSegmentFiles: %w", err) } - l, err := seedableSnapshotsBySubDir(dirs.Snap, "history") + l1, err := seedableSnapshotsBySubDir(dirs.Snap, "idx") + if err != nil { + return nil, err + } + l2, err := seedableSnapshotsBySubDir(dirs.Snap, "history") if err != nil { return nil, err } - l2, err := seedableSnapshotsBySubDir(dirs.Snap, "warm") + l3, err := seedableSnapshotsBySubDir(dirs.Snap, "domain") if err != nil { return nil, err } - files = append(append(files, l...), l2...) + files = append(append(append(files, l1...), l2...), l3...) return files, nil } func (d *Downloader) addTorrentFilesFromDisk(quiet bool) error { diff --git a/erigon-lib/downloader/downloader_grpc_server.go b/erigon-lib/downloader/downloader_grpc_server.go index 5d4e763e8fe..33410793475 100644 --- a/erigon-lib/downloader/downloader_grpc_server.go +++ b/erigon-lib/downloader/downloader_grpc_server.go @@ -24,11 +24,12 @@ import ( "time" "github.com/anacrolix/torrent/metainfo" + "github.com/ledgerwatch/log/v3" + "google.golang.org/protobuf/types/known/emptypb" + "github.com/ledgerwatch/erigon-lib/gointerfaces" proto_downloader "github.com/ledgerwatch/erigon-lib/gointerfaces/downloader" prototypes "github.com/ledgerwatch/erigon-lib/gointerfaces/types" - "github.com/ledgerwatch/log/v3" - "google.golang.org/protobuf/types/known/emptypb" ) var ( @@ -83,6 +84,7 @@ func (s *GrpcServer) Add(ctx context.Context, request *proto_downloader.AddReque return nil, err } } + return &emptypb.Empty{}, nil } @@ -114,7 +116,7 @@ func (s *GrpcServer) Delete(ctx context.Context, request *proto_downloader.Delet } func (s *GrpcServer) Verify(ctx context.Context, request *proto_downloader.VerifyRequest) (*emptypb.Empty, error) { - err := s.d.VerifyData(ctx, nil) + err := s.d.VerifyData(ctx, nil, false) if err != nil { return nil, err } diff --git a/erigon-lib/downloader/torrent_files.go b/erigon-lib/downloader/torrent_files.go index 1e27c8e0e40..51d1c8ddd1a 100644 --- a/erigon-lib/downloader/torrent_files.go +++ b/erigon-lib/downloader/torrent_files.go @@ -71,7 +71,7 @@ func (tf *TorrentFiles) CreateTorrentFromMetaInfo(fPath string, mi *metainfo.Met return tf.createTorrentFromMetaInfo(fPath, mi) } func (tf *TorrentFiles) createTorrentFromMetaInfo(fPath string, mi *metainfo.MetaInfo) error { - file, err := os.Create(fPath) + file, err := os.Create(fPath + ".tmp") if err != nil { return err } @@ -79,7 +79,15 @@ func (tf *TorrentFiles) createTorrentFromMetaInfo(fPath string, mi *metainfo.Met if err := mi.Write(file); err != nil { return err } - file.Sync() + if err := file.Sync(); err != nil { + return err + } + if err := file.Close(); err != nil { + return err + } + if err := os.Rename(fPath+".tmp", fPath); err != nil { + return err + } return nil } diff --git a/erigon-lib/downloader/util.go b/erigon-lib/downloader/util.go index 02437c38e5f..f169064e86a 100644 --- a/erigon-lib/downloader/util.go +++ b/erigon-lib/downloader/util.go @@ -17,8 +17,12 @@ package downloader import ( + "bytes" "context" + "crypto/sha1" "fmt" + "io" + "os" "path/filepath" "regexp" "runtime" @@ -29,14 +33,18 @@ import ( "github.com/anacrolix/torrent" "github.com/anacrolix/torrent/bencode" "github.com/anacrolix/torrent/metainfo" + "github.com/anacrolix/torrent/mmap_span" + "github.com/anacrolix/torrent/storage" + "github.com/edsrzf/mmap-go" + "github.com/ledgerwatch/log/v3" + "golang.org/x/sync/errgroup" + common2 "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/datadir" dir2 "github.com/ledgerwatch/erigon-lib/common/dir" "github.com/ledgerwatch/erigon-lib/downloader/downloadercfg" "github.com/ledgerwatch/erigon-lib/downloader/snaptype" "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/log/v3" - "golang.org/x/sync/errgroup" ) // udpOrHttpTrackers - torrent library spawning several goroutines and producing many requests for each tracker. So we limit amout of trackers by 7 @@ -360,3 +368,81 @@ func readPeerID(db kv.RoDB) (peerID []byte, err error) { func IsLocal(path string) bool { return isLocal(path) } + +func ScheduleVerifyFile(ctx context.Context, t *torrent.Torrent, completePieces *atomic.Uint64) error { + for i := 0; i < t.NumPieces(); i++ { + t.Piece(i).VerifyData() + + completePieces.Add(1) + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + } + return nil +} + +func VerifyFileFailFast(ctx context.Context, t *torrent.Torrent, root string, completePieces *atomic.Uint64) error { + span := new(mmap_span.MMapSpan) + defer span.Close() + info := t.Info() + for _, file := range info.UpvertedFiles() { + filename := filepath.Join(append([]string{root, info.Name}, file.Path...)...) + mm, err := mmapFile(filename) + if err != nil { + return err + } + if int64(len(mm.Bytes())) != file.Length { + return fmt.Errorf("file %q has wrong length", filename) + } + span.Append(mm) + } + span.InitIndex() + + hasher := sha1.New() + for i := 0; i < info.NumPieces(); i++ { + p := info.Piece(i) + hasher.Reset() + _, err := io.Copy(hasher, io.NewSectionReader(span, p.Offset(), p.Length())) + if err != nil { + return err + } + good := bytes.Equal(hasher.Sum(nil), p.Hash().Bytes()) + if !good { + return fmt.Errorf("hash mismatch at piece %d, file: %s", i, t.Name()) + } + + completePieces.Add(1) + select { + case <-ctx.Done(): + return ctx.Err() + default: + } + } + return nil +} + +func mmapFile(name string) (mm storage.FileMapping, err error) { + f, err := os.Open(name) + if err != nil { + return + } + defer func() { + if err != nil { + f.Close() + } + }() + fi, err := f.Stat() + if err != nil { + return + } + if fi.Size() == 0 { + return + } + reg, err := mmap.MapRegion(f, -1, mmap.RDONLY, mmap.COPY, 0) + if err != nil { + return + } + return storage.WrapFileMapping(reg, f), nil +} diff --git a/erigon-lib/downloader/webseed.go b/erigon-lib/downloader/webseed.go index 2c42b29b62b..f6433103356 100644 --- a/erigon-lib/downloader/webseed.go +++ b/erigon-lib/downloader/webseed.go @@ -169,7 +169,7 @@ func (d *WebSeeds) callS3Provider(ctx context.Context, token string) (snaptype.W //v1:bucketName:accID:accessKeyID:accessKeySecret l := strings.Split(token, ":") if len(l) != 5 { - return nil, fmt.Errorf("token has invalid format, exepcing 'v1:tokenInBase64'") + return nil, fmt.Errorf("[snapshots] webseed token has invalid format. expeting 5 parts, found %d", len(l)) } version, bucketName, accountId, accessKeyId, accessKeySecret := strings.TrimSpace(l[0]), strings.TrimSpace(l[1]), strings.TrimSpace(l[2]), strings.TrimSpace(l[3]), strings.TrimSpace(l[4]) if version != "v1" { From 7490e7dd63c413865b1f8e8dda10516524ac5936 Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Mon, 8 Jan 2024 16:01:36 +0700 Subject: [PATCH 12/92] up `x` and `cli` deps (#9154) --- erigon-lib/go.mod | 22 +++++++++---------- erigon-lib/go.sum | 44 ++++++++++++++++++------------------- go.mod | 28 ++++++++++++------------ go.sum | 56 ++++++++++++++++++++++++----------------------- 4 files changed, 76 insertions(+), 74 deletions(-) diff --git a/erigon-lib/go.mod b/erigon-lib/go.mod index acb9a2e6eb0..b5c718c5d16 100644 --- a/erigon-lib/go.mod +++ b/erigon-lib/go.mod @@ -5,7 +5,7 @@ go 1.20 require ( github.com/erigontech/mdbx-go v0.27.21 github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240101230756-23fbc6c56a1d - github.com/ledgerwatch/interfaces v0.0.0-20240105165407-ac2eea9d3c55 + github.com/ledgerwatch/interfaces v0.0.0-20240105174738-fe57049f198c github.com/ledgerwatch/log/v3 v3.9.0 github.com/ledgerwatch/secp256k1 v1.0.0 ) @@ -34,20 +34,20 @@ require ( github.com/matryer/moq v0.3.3 github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 github.com/pelletier/go-toml/v2 v2.1.0 - github.com/prometheus/client_golang v1.17.0 + github.com/prometheus/client_golang v1.18.0 github.com/prometheus/client_model v0.5.0 github.com/quasilyte/go-ruleguard/dsl v0.3.22 github.com/spaolacci/murmur3 v1.1.0 github.com/stretchr/testify v1.8.4 github.com/tidwall/btree v1.6.0 - golang.org/x/crypto v0.16.0 + golang.org/x/crypto v0.17.0 golang.org/x/exp v0.0.0-20230905200255-921286631fa9 - golang.org/x/sync v0.5.0 - golang.org/x/sys v0.15.0 + golang.org/x/sync v0.6.0 + golang.org/x/sys v0.16.0 golang.org/x/time v0.5.0 - google.golang.org/grpc v1.59.0 + google.golang.org/grpc v1.60.1 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 - google.golang.org/protobuf v1.31.0 + google.golang.org/protobuf v1.32.0 ) require ( @@ -103,7 +103,7 @@ require ( github.com/huandu/xstrings v1.4.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/mschoch/smat v0.2.0 // indirect github.com/opencontainers/runtime-spec v1.0.2 // indirect @@ -127,8 +127,8 @@ require ( github.com/pion/webrtc/v3 v3.1.42 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.11.1 // indirect + github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417 // indirect github.com/sirupsen/logrus v1.9.0 // indirect @@ -139,7 +139,7 @@ require ( golang.org/x/net v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.16.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect modernc.org/libc v1.24.1 // indirect modernc.org/mathutil v1.6.0 // indirect diff --git a/erigon-lib/go.sum b/erigon-lib/go.sum index 8d874b682fc..19f1ddb7b28 100644 --- a/erigon-lib/go.sum +++ b/erigon-lib/go.sum @@ -293,8 +293,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240101230756-23fbc6c56a1d h1:rMqDEGLdmVgGdpDmaNp4Do1vc9BtUQ3rjFD9gQBRSx0= github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240101230756-23fbc6c56a1d/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo= -github.com/ledgerwatch/interfaces v0.0.0-20240105165407-ac2eea9d3c55 h1:Avbyef7Fyz5O9TkN/AoPy4NRXiRiFoYrG6Zp8CyRcrM= -github.com/ledgerwatch/interfaces v0.0.0-20240105165407-ac2eea9d3c55/go.mod h1:ugQv1QllJzBny3cKZKxUrSnykkjkBgm27eQM6dnGAcc= +github.com/ledgerwatch/interfaces v0.0.0-20240105174738-fe57049f198c h1:j9IrDNf6oTtc9R+1rra3Umf7xIYvTgJWXsCavGcqv7k= +github.com/ledgerwatch/interfaces v0.0.0-20240105174738-fe57049f198c/go.mod h1:ugQv1QllJzBny3cKZKxUrSnykkjkBgm27eQM6dnGAcc= github.com/ledgerwatch/log/v3 v3.9.0 h1:iDwrXe0PVwBC68Dd94YSsHbMgQ3ufsgjzXtFNFVZFRk= github.com/ledgerwatch/log/v3 v3.9.0/go.mod h1:EiAY6upmI/6LkNhOVxb4eVsmsP11HZCnZ3PlJMjYiqE= github.com/ledgerwatch/secp256k1 v1.0.0 h1:Usvz87YoTG0uePIV8woOof5cQnLXGYa162rFf3YnwaQ= @@ -307,8 +307,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= @@ -395,8 +395,8 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= -github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= +github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -407,15 +407,15 @@ github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= -github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -488,8 +488,8 @@ golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220516162934-403b01795ae8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= -golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= @@ -543,8 +543,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -580,8 +580,8 @@ golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -626,8 +626,8 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -635,8 +635,8 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -647,8 +647,8 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/go.mod b/go.mod index a18844cc939..1119355e12e 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/99designs/gqlgen v0.17.40 github.com/Giulio2002/bls v0.0.0-20230906201036-c2330c97dc7d github.com/RoaringBitmap/roaring v1.2.3 - github.com/VictoriaMetrics/fastcache v1.12.1 + github.com/VictoriaMetrics/fastcache v1.12.2 github.com/alecthomas/kong v0.8.0 github.com/anacrolix/log v0.14.3-0.20230823030427-4b296d71a6b4 github.com/anacrolix/sync v0.4.0 @@ -37,7 +37,7 @@ require ( github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c github.com/gballet/go-verkle v0.0.0-20221121182333-31427a1f2d35 github.com/gfx-labs/sse v0.0.0-20231226060816-f747e26a9baa - github.com/go-chi/chi/v5 v5.0.10 + github.com/go-chi/chi/v5 v5.0.11 github.com/go-chi/cors v1.2.1 github.com/goccy/go-json v0.9.11 github.com/gofrs/flock v0.8.1 @@ -46,7 +46,7 @@ require ( github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb github.com/google/btree v1.1.2 github.com/google/gofuzz v1.2.0 - github.com/gorilla/websocket v1.5.0 + github.com/gorilla/websocket v1.5.1 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/hashicorp/golang-lru/arc/v2 v2.0.6 github.com/hashicorp/golang-lru/v2 v2.0.6 @@ -83,7 +83,7 @@ require ( github.com/tidwall/btree v1.6.0 github.com/ugorji/go/codec v1.1.13 github.com/ugorji/go/codec/codecgen v1.1.13 - github.com/urfave/cli/v2 v2.25.7 + github.com/urfave/cli/v2 v2.27.1 github.com/valyala/fastjson v1.6.4 github.com/vektah/gqlparser/v2 v2.5.10 github.com/xsleonard/go-merkle v1.1.0 @@ -91,17 +91,17 @@ require ( golang.org/x/crypto v0.17.0 golang.org/x/exp v0.0.0-20230905200255-921286631fa9 golang.org/x/net v0.19.0 - golang.org/x/sync v0.5.0 - golang.org/x/sys v0.15.0 + golang.org/x/sync v0.6.0 + golang.org/x/sys v0.16.0 golang.org/x/time v0.5.0 - google.golang.org/grpc v1.59.0 + google.golang.org/grpc v1.60.1 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 - google.golang.org/protobuf v1.31.0 + google.golang.org/protobuf v1.32.0 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 - modernc.org/sqlite v1.27.0 + modernc.org/sqlite v1.28.0 pgregory.net/rapid v1.1.0 ) @@ -202,7 +202,7 @@ require ( github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-runewidth v0.0.13 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/miekg/dns v1.1.55 // indirect github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect @@ -242,10 +242,10 @@ require ( github.com/pion/webrtc/v3 v3.1.42 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.17.0 // indirect + github.com/prometheus/client_golang v1.18.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.11.1 // indirect + github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qtls-go1-20 v0.3.3 // indirect github.com/quic-go/quic-go v0.38.1 // indirect @@ -270,7 +270,7 @@ require ( golang.org/x/mod v0.14.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.16.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect lukechampine.com/blake3 v1.2.1 // indirect diff --git a/go.sum b/go.sum index fcabad51499..90a5e4fe9d1 100644 --- a/go.sum +++ b/go.sum @@ -62,8 +62,8 @@ github.com/RoaringBitmap/roaring v1.2.3 h1:yqreLINqIrX22ErkKI0vY47/ivtJr6n+kMhVO github.com/RoaringBitmap/roaring v1.2.3/go.mod h1:plvDsJQpxOC5bw8LRteu/MLWHsHez/3y6cubLI4/1yE= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= -github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= +github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= +github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8= github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= github.com/ajwerner/btree v0.0.0-20211221152037-f427b3e689c0 h1:byYvvbfSo3+9efR4IeReh77gVs4PnNDR3AMOE9NJ7a0= @@ -319,8 +319,8 @@ github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a/go.mod github.com/glycerine/goconvey v0.0.0-20180728074245-46e3a41ad493/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= github.com/glycerine/goconvey v0.0.0-20190315024820-982ee783a72e/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= -github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= -github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/chi/v5 v5.0.11 h1:BnpYbFZ3T3S1WMpD79r7R5ThWX40TaFB7L31Y8xqSwA= +github.com/go-chi/chi/v5 v5.0.11/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= @@ -458,8 +458,8 @@ github.com/gopherjs/gopherjs v0.0.0-20190309154008-847fc94819f9/go.mod h1:wJfORR github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= @@ -595,8 +595,8 @@ github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4 github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo= @@ -743,8 +743,8 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= -github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= +github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -756,16 +756,16 @@ github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7q github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= -github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/protolambda/ztyp v0.2.2 h1:rVcL3vBu9W/aV646zF6caLS/dyn9BN8NYiuJzicLNyY= github.com/protolambda/ztyp v0.2.2/go.mod h1:9bYgKGqg3wJqT9ac1gI2hnVb0STQq7p/1lapqrqY1dU= github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7 h1:0tVE4tdWQK9ZpYygoV7+vS6QkDvQVySboMVEIxBJmXw= @@ -885,8 +885,8 @@ github.com/ugorji/go/codec v1.1.13/go.mod h1:oNVt3Dq+FO91WNQ/9JnHKQP2QJxTzoN7wCB github.com/ugorji/go/codec/codecgen v1.1.13 h1:rGpZ4Q63VcWA3DMBbIHvg+SQweUkfXBBa/f9X0W+tFg= github.com/ugorji/go/codec/codecgen v1.1.13/go.mod h1:EhCxlc7Crov+HLygD4+hBCitXNrrGKRrRWj+pRsyJGg= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= -github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= +github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho= +github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ= github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= github.com/vektah/gqlparser/v2 v2.5.10 h1:6zSM4azXC9u4Nxy5YmdmGu4uKamfwsdKTwp5zsEealU= @@ -1082,8 +1082,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= -golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1156,8 +1156,10 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -1319,8 +1321,8 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -1340,8 +1342,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -1356,8 +1358,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y= gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UDAkHu8BrjI= @@ -1412,8 +1414,8 @@ modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= -modernc.org/sqlite v1.27.0 h1:MpKAHoyYB7xqcwnUwkuD+npwEa0fojF0B5QRbN+auJ8= -modernc.org/sqlite v1.27.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0= +modernc.org/sqlite v1.28.0 h1:Zx+LyDDmXczNnEQdvPuEfcFVA2ZPyaD7UCZDjef3BHQ= +modernc.org/sqlite v1.28.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY= From b4fd278533fd9ca38b60f985c75e74afde54e150 Mon Sep 17 00:00:00 2001 From: Michelangelo Riccobene Date: Mon, 8 Jan 2024 10:18:00 +0100 Subject: [PATCH 13/92] clean-exit test: bump golang version to 1.21 (#9160) --- .github/workflows/qa-clean-exit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/qa-clean-exit.yml b/.github/workflows/qa-clean-exit.yml index 1e6c9f2767f..51198fcc606 100644 --- a/.github/workflows/qa-clean-exit.yml +++ b/.github/workflows/qa-clean-exit.yml @@ -35,7 +35,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v4 with: - go-version: '1.20' + go-version: '1.21' - name: Set up Python uses: actions/setup-python@v4 From ff92b701c36595ca5daa010dd90620628893d2d7 Mon Sep 17 00:00:00 2001 From: Dmytro Date: Mon, 8 Jan 2024 10:43:04 +0100 Subject: [PATCH 14/92] dvovk/updsync (#9134) refactored data structure for sync statistics --- cmd/capcli/cli.go | 2 +- diagnostics/diagnostic.go | 111 ++++++++++++++++++++--------- diagnostics/snapshot_sync.go | 2 +- erigon-lib/diagnostics/entities.go | 29 +++++++- eth/stagedsync/stage_snapshots.go | 2 +- eth/stagedsync/sync.go | 51 +++++++++---- turbo/snapshotsync/snapshotsync.go | 5 +- 7 files changed, 147 insertions(+), 55 deletions(-) diff --git a/cmd/capcli/cli.go b/cmd/capcli/cli.go index 4a5be83f9ba..f012add350d 100644 --- a/cmd/capcli/cli.go +++ b/cmd/capcli/cli.go @@ -796,7 +796,7 @@ func (d *DownloadSnapshots) Run(ctx *Context) error { freezeblocks.NewBlockReader( freezeblocks.NewRoSnapshots(ethconfig.NewSnapCfg(false, false, false), dirs.Snap, snapshotVersion, log.Root()), freezeblocks.NewBorRoSnapshots(ethconfig.NewSnapCfg(false, false, false), dirs.Snap, snapshotVersion, log.Root())), - params.ChainConfigByChainName(d.Chain), direct.NewDownloaderClient(bittorrentServer)) + params.ChainConfigByChainName(d.Chain), direct.NewDownloaderClient(bittorrentServer), []string{}) } type RetrieveHistoricalState struct { diff --git a/diagnostics/diagnostic.go b/diagnostics/diagnostic.go index 2f3ef2af48a..dcd332d9929 100644 --- a/diagnostics/diagnostic.go +++ b/diagnostics/diagnostic.go @@ -16,11 +16,11 @@ type DiagnosticClient struct { metricsMux *http.ServeMux node *node.ErigonNode - snapshotDownload diaglib.SnapshotDownloadStatistics + syncStats diaglib.SyncStatistics } func NewDiagnosticClient(ctx *cli.Context, metricsMux *http.ServeMux, node *node.ErigonNode) *DiagnosticClient { - return &DiagnosticClient{ctx: ctx, metricsMux: metricsMux, node: node, snapshotDownload: diaglib.SnapshotDownloadStatistics{}} + return &DiagnosticClient{ctx: ctx, metricsMux: metricsMux, node: node, syncStats: diaglib.SyncStatistics{}} } func (d *DiagnosticClient) Setup() { @@ -28,6 +28,8 @@ func (d *DiagnosticClient) Setup() { d.runSegmentDownloadingListener() d.runSegmentIndexingListener() d.runSegmentIndexingFinishedListener() + d.runCurrentSyncStageListener() + d.runSyncStagesListListener() } func (d *DiagnosticClient) runSnapshotListener() { @@ -44,19 +46,18 @@ func (d *DiagnosticClient) runSnapshotListener() { cancel() return case info := <-ch: - d.snapshotDownload.Downloaded = info.Downloaded - d.snapshotDownload.Total = info.Total - d.snapshotDownload.TotalTime = info.TotalTime - d.snapshotDownload.DownloadRate = info.DownloadRate - d.snapshotDownload.UploadRate = info.UploadRate - d.snapshotDownload.Peers = info.Peers - d.snapshotDownload.Files = info.Files - d.snapshotDownload.Connections = info.Connections - d.snapshotDownload.Alloc = info.Alloc - d.snapshotDownload.Sys = info.Sys - d.snapshotDownload.DownloadFinished = info.DownloadFinished - d.snapshotDownload.TorrentMetadataReady = info.TorrentMetadataReady - d.snapshotDownload.LogPrefix = info.LogPrefix + d.syncStats.SnapshotDownload.Downloaded = info.Downloaded + d.syncStats.SnapshotDownload.Total = info.Total + d.syncStats.SnapshotDownload.TotalTime = info.TotalTime + d.syncStats.SnapshotDownload.DownloadRate = info.DownloadRate + d.syncStats.SnapshotDownload.UploadRate = info.UploadRate + d.syncStats.SnapshotDownload.Peers = info.Peers + d.syncStats.SnapshotDownload.Files = info.Files + d.syncStats.SnapshotDownload.Connections = info.Connections + d.syncStats.SnapshotDownload.Alloc = info.Alloc + d.syncStats.SnapshotDownload.Sys = info.Sys + d.syncStats.SnapshotDownload.DownloadFinished = info.DownloadFinished + d.syncStats.SnapshotDownload.TorrentMetadataReady = info.TorrentMetadataReady if info.DownloadFinished { return @@ -67,8 +68,8 @@ func (d *DiagnosticClient) runSnapshotListener() { }() } -func (d *DiagnosticClient) SnapshotDownload() diaglib.SnapshotDownloadStatistics { - return d.snapshotDownload +func (d *DiagnosticClient) SyncStatistics() diaglib.SyncStatistics { + return d.syncStats } func (d *DiagnosticClient) runSegmentDownloadingListener() { @@ -85,11 +86,11 @@ func (d *DiagnosticClient) runSegmentDownloadingListener() { cancel() return case info := <-ch: - if d.snapshotDownload.SegmentsDownloading == nil { - d.snapshotDownload.SegmentsDownloading = map[string]diaglib.SegmentDownloadStatistics{} + if d.syncStats.SnapshotDownload.SegmentsDownloading == nil { + d.syncStats.SnapshotDownload.SegmentsDownloading = map[string]diaglib.SegmentDownloadStatistics{} } - d.snapshotDownload.SegmentsDownloading[info.Name] = info + d.syncStats.SnapshotDownload.SegmentsDownloading[info.Name] = info } } }() @@ -130,15 +131,15 @@ func (d *DiagnosticClient) runSegmentIndexingFinishedListener() { return case info := <-ch: found := false - for i := range d.snapshotDownload.SegmentIndexing.Segments { - if d.snapshotDownload.SegmentIndexing.Segments[i].SegmentName == info.SegmentName { + for i := range d.syncStats.SnapshotIndexing.Segments { + if d.syncStats.SnapshotIndexing.Segments[i].SegmentName == info.SegmentName { found = true - d.snapshotDownload.SegmentIndexing.Segments[i].Percent = 100 + d.syncStats.SnapshotIndexing.Segments[i].Percent = 100 } } if !found { - d.snapshotDownload.SegmentIndexing.Segments = append(d.snapshotDownload.SegmentIndexing.Segments, diaglib.SnapshotSegmentIndexingStatistics{ + d.syncStats.SnapshotIndexing.Segments = append(d.syncStats.SnapshotIndexing.Segments, diaglib.SnapshotSegmentIndexingStatistics{ SegmentName: info.SegmentName, Percent: 100, Alloc: 0, @@ -151,26 +152,70 @@ func (d *DiagnosticClient) runSegmentIndexingFinishedListener() { } func (d *DiagnosticClient) addOrUpdateSegmentIndexingState(upd diaglib.SnapshotIndexingStatistics) { - if d.snapshotDownload.SegmentIndexing.Segments == nil { - d.snapshotDownload.SegmentIndexing.Segments = []diaglib.SnapshotSegmentIndexingStatistics{} + if d.syncStats.SnapshotIndexing.Segments == nil { + d.syncStats.SnapshotIndexing.Segments = []diaglib.SnapshotSegmentIndexingStatistics{} } for i := range upd.Segments { found := false - for j := range d.snapshotDownload.SegmentIndexing.Segments { - if d.snapshotDownload.SegmentIndexing.Segments[j].SegmentName == upd.Segments[i].SegmentName { - d.snapshotDownload.SegmentIndexing.Segments[j].Percent = upd.Segments[i].Percent - d.snapshotDownload.SegmentIndexing.Segments[j].Alloc = upd.Segments[i].Alloc - d.snapshotDownload.SegmentIndexing.Segments[j].Sys = upd.Segments[i].Sys + for j := range d.syncStats.SnapshotIndexing.Segments { + if d.syncStats.SnapshotIndexing.Segments[j].SegmentName == upd.Segments[i].SegmentName { + d.syncStats.SnapshotIndexing.Segments[j].Percent = upd.Segments[i].Percent + d.syncStats.SnapshotIndexing.Segments[j].Alloc = upd.Segments[i].Alloc + d.syncStats.SnapshotIndexing.Segments[j].Sys = upd.Segments[i].Sys found = true break } } if !found { - d.snapshotDownload.SegmentIndexing.Segments = append(d.snapshotDownload.SegmentIndexing.Segments, upd.Segments[i]) + d.syncStats.SnapshotIndexing.Segments = append(d.syncStats.SnapshotIndexing.Segments, upd.Segments[i]) } } - d.snapshotDownload.SegmentIndexing.TimeElapsed = upd.TimeElapsed + d.syncStats.SnapshotIndexing.TimeElapsed = upd.TimeElapsed +} + +func (d *DiagnosticClient) runSyncStagesListListener() { + go func() { + ctx, ch, cancel := diaglib.Context[diaglib.SyncStagesList](context.Background(), 1) + defer cancel() + + rootCtx, _ := common.RootContext() + + diaglib.StartProviders(ctx, diaglib.TypeOf(diaglib.SyncStagesList{}), log.Root()) + for { + select { + case <-rootCtx.Done(): + cancel() + return + case info := <-ch: + d.syncStats.SyncStages.StagesList = info.Stages + return + } + } + }() +} + +func (d *DiagnosticClient) runCurrentSyncStageListener() { + go func() { + ctx, ch, cancel := diaglib.Context[diaglib.CurrentSyncStage](context.Background(), 1) + defer cancel() + + rootCtx, _ := common.RootContext() + + diaglib.StartProviders(ctx, diaglib.TypeOf(diaglib.CurrentSyncStage{}), log.Root()) + for { + select { + case <-rootCtx.Done(): + cancel() + return + case info := <-ch: + d.syncStats.SyncStages.CurrentStage = info.Stage + if int(d.syncStats.SyncStages.CurrentStage) >= len(d.syncStats.SyncStages.StagesList) { + return + } + } + } + }() } diff --git a/diagnostics/snapshot_sync.go b/diagnostics/snapshot_sync.go index 66bb2a8a392..6e99b8ba4c1 100644 --- a/diagnostics/snapshot_sync.go +++ b/diagnostics/snapshot_sync.go @@ -14,5 +14,5 @@ func SetupStagesAccess(metricsMux *http.ServeMux, diag *DiagnosticClient) { } func writeStages(w http.ResponseWriter, diag *DiagnosticClient) { - json.NewEncoder(w).Encode(diag.SnapshotDownload()) + json.NewEncoder(w).Encode(diag.SyncStatistics()) } diff --git a/erigon-lib/diagnostics/entities.go b/erigon-lib/diagnostics/entities.go index f91ab9cea6e..fe8656249de 100644 --- a/erigon-lib/diagnostics/entities.go +++ b/erigon-lib/diagnostics/entities.go @@ -29,6 +29,12 @@ type PeerStatistics struct { TypeBytesOut map[string]uint64 } +type SyncStatistics struct { + SyncStages SyncStages `json:"syncStages"` + SnapshotDownload SnapshotDownloadStatistics `json:"snapshotDownload"` + SnapshotIndexing SnapshotIndexingStatistics `json:"snapshotIndexing"` +} + type SnapshotDownloadStatistics struct { Downloaded uint64 `json:"downloaded"` Total uint64 `json:"total"` @@ -42,9 +48,7 @@ type SnapshotDownloadStatistics struct { Sys uint64 `json:"sys"` DownloadFinished bool `json:"downloadFinished"` SegmentsDownloading map[string]SegmentDownloadStatistics `json:"segmentsDownloading"` - SegmentIndexing SnapshotIndexingStatistics `json:"segmentsIndexing"` TorrentMetadataReady int32 `json:"torrentMetadataReady"` - LogPrefix string `json:"logPrefix"` } type SegmentDownloadStatistics struct { @@ -73,6 +77,19 @@ type SnapshotSegmentIndexingFinishedUpdate struct { SegmentName string `json:"segmentName"` } +type SyncStagesList struct { + Stages []string `json:"stages"` +} + +type CurrentSyncStage struct { + Stage uint `json:"stage"` +} + +type SyncStages struct { + StagesList []string `json:"stagesList"` + CurrentStage uint `json:"currentStage"` +} + func (ti SnapshotDownloadStatistics) Type() Type { return TypeOf(ti) } @@ -88,3 +105,11 @@ func (ti SnapshotIndexingStatistics) Type() Type { func (ti SnapshotSegmentIndexingFinishedUpdate) Type() Type { return TypeOf(ti) } + +func (ti SyncStagesList) Type() Type { + return TypeOf(ti) +} + +func (ti CurrentSyncStage) Type() Type { + return TypeOf(ti) +} diff --git a/eth/stagedsync/stage_snapshots.go b/eth/stagedsync/stage_snapshots.go index 7ef851ff0b4..4b9cbc37064 100644 --- a/eth/stagedsync/stage_snapshots.go +++ b/eth/stagedsync/stage_snapshots.go @@ -231,7 +231,7 @@ func DownloadAndIndexSnapshotsIfNeed(s *StageState, ctx context.Context, tx kv.R cfg.notifier.Events.OnNewSnapshot() } } else { - if err := snapshotsync.WaitForDownloader(ctx, s.LogPrefix(), cfg.historyV3, cstate, cfg.agg, tx, cfg.blockReader, &cfg.chainConfig, cfg.snapshotDownloader); err != nil { + if err := snapshotsync.WaitForDownloader(ctx, s.LogPrefix(), cfg.historyV3, cstate, cfg.agg, tx, cfg.blockReader, &cfg.chainConfig, cfg.snapshotDownloader, s.state.StagesIdsList()); err != nil { return err } } diff --git a/eth/stagedsync/sync.go b/eth/stagedsync/sync.go index cf1cd273fac..df75def7ccc 100644 --- a/eth/stagedsync/sync.go +++ b/eth/stagedsync/sync.go @@ -9,6 +9,7 @@ import ( libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/dbg" + "github.com/ledgerwatch/erigon-lib/diagnostics" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon/eth/ethconfig" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" @@ -21,13 +22,14 @@ type Sync struct { unwindReason UnwindReason posTransition *uint64 - stages []*Stage - unwindOrder []*Stage - pruningOrder []*Stage - currentStage uint - timings []Timing - logPrefixes []string - logger log.Logger + stages []*Stage + unwindOrder []*Stage + pruningOrder []*Stage + currentStage uint + timings []Timing + logPrefixes []string + logger log.Logger + stagesIdsList []string } type Timing struct { @@ -86,6 +88,11 @@ func (s *Sync) NextStage() { return } s.currentStage++ + + isDiagEnabled := diagnostics.TypeOf(diagnostics.CurrentSyncStage{}).Enabled() + if isDiagEnabled { + diagnostics.Send(diagnostics.CurrentSyncStage{Stage: s.currentStage}) + } } // IsBefore returns true if stage1 goes before stage2 in staged sync @@ -144,10 +151,22 @@ func (s *Sync) LogPrefix() string { return s.logPrefixes[s.currentStage] } +func (s *Sync) StagesIdsList() []string { + if s == nil { + return []string{} + } + return s.stagesIdsList +} + func (s *Sync) SetCurrentStage(id stages.SyncStage) error { for i, stage := range s.stages { if stage.ID == id { s.currentStage = uint(i) + isDiagEnabled := diagnostics.TypeOf(diagnostics.CurrentSyncStage{}).Enabled() + if isDiagEnabled { + diagnostics.Send(diagnostics.CurrentSyncStage{Stage: s.currentStage}) + } + return nil } } @@ -173,19 +192,23 @@ func New(cfg ethconfig.Sync, stagesList []*Stage, unwindOrder UnwindOrder, prune } } } + logPrefixes := make([]string, len(stagesList)) + stagesIdsList := make([]string, len(stagesList)) for i := range stagesList { logPrefixes[i] = fmt.Sprintf("%d/%d %s", i+1, len(stagesList), stagesList[i].ID) + stagesIdsList[i] = string(stagesList[i].ID) } return &Sync{ - cfg: cfg, - stages: stagesList, - currentStage: 0, - unwindOrder: unwindStages, - pruningOrder: pruneStages, - logPrefixes: logPrefixes, - logger: logger, + cfg: cfg, + stages: stagesList, + currentStage: 0, + unwindOrder: unwindStages, + pruningOrder: pruneStages, + logPrefixes: logPrefixes, + logger: logger, + stagesIdsList: stagesIdsList, } } diff --git a/turbo/snapshotsync/snapshotsync.go b/turbo/snapshotsync/snapshotsync.go index a33b5e2efa1..7197fc68384 100644 --- a/turbo/snapshotsync/snapshotsync.go +++ b/turbo/snapshotsync/snapshotsync.go @@ -67,7 +67,7 @@ func RequestSnapshotsDownload(ctx context.Context, downloadRequest []services.Do // WaitForDownloader - wait for Downloader service to download all expected snapshots // for MVP we sync with Downloader only once, in future will send new snapshots also -func WaitForDownloader(ctx context.Context, logPrefix string, histV3 bool, caplin CaplinMode, agg *state.AggregatorV3, tx kv.RwTx, blockReader services.FullBlockReader, cc *chain.Config, snapshotDownloader proto_downloader.DownloaderClient) error { +func WaitForDownloader(ctx context.Context, logPrefix string, histV3 bool, caplin CaplinMode, agg *state.AggregatorV3, tx kv.RwTx, blockReader services.FullBlockReader, cc *chain.Config, snapshotDownloader proto_downloader.DownloaderClient, stagesIdsList []string) error { snapshots := blockReader.Snapshots() borSnapshots := blockReader.BorSnapshots() if blockReader.FreezingCfg().NoDownloader { @@ -157,12 +157,12 @@ Loop: Alloc: m.Alloc, Sys: m.Sys, DownloadFinished: stats.Completed, - LogPrefix: logPrefix, }) log.Info(fmt.Sprintf("[%s] download finished", logPrefix), "time", time.Since(downloadStartTime).String()) break Loop } else { + diagnostics.Send(diagnostics.SyncStagesList{Stages: stagesIdsList}) diagnostics.Send(diagnostics.SnapshotDownloadStatistics{ Downloaded: stats.BytesCompleted, Total: stats.BytesTotal, @@ -176,7 +176,6 @@ Loop: Sys: m.Sys, DownloadFinished: stats.Completed, TorrentMetadataReady: stats.MetadataReady, - LogPrefix: logPrefix, }) if stats.MetadataReady < stats.FilesTotal { From de6c1593e44151161d86788b530018dc5fa4c5ad Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Mon, 8 Jan 2024 18:30:51 +0700 Subject: [PATCH 15/92] "erigon snapshots retire" - doesn't see any files because version is 0 - fix (#9163) --- turbo/app/snapshots_cmd.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/turbo/app/snapshots_cmd.go b/turbo/app/snapshots_cmd.go index 79d234ec572..ad17210b399 100644 --- a/turbo/app/snapshots_cmd.go +++ b/turbo/app/snapshots_cmd.go @@ -87,6 +87,7 @@ var snapshotCommand = cli.Command{ &SnapshotFromFlag, &SnapshotToFlag, &SnapshotEveryFlag, + &SnapshotVersionFlag, }), }, { @@ -510,6 +511,9 @@ func doRetireCommand(cliCtx *cli.Context) error { to := cliCtx.Uint64(SnapshotToFlag.Name) every := cliCtx.Uint64(SnapshotEveryFlag.Name) version := uint8(cliCtx.Int(SnapshotVersionFlag.Name)) + if version != 0 { + snapcfg.SnapshotVersion(version) + } db := dbCfg(kv.ChainDB, dirs.Chaindata).MustOpen() defer db.Close() From 2521f47e7b848a5a01a6bf1774aac56a041e0438 Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Mon, 8 Jan 2024 15:55:43 +0100 Subject: [PATCH 16/92] polygon/sync: canonical chain builder unit tests (#9137) --- polygon/sync/canonical_chain_builder_test.go | 233 ++++++++++++++++++- polygon/sync/difficulty.go | 52 ++++- polygon/sync/difficulty_test.go | 109 ++++++++- 3 files changed, 375 insertions(+), 19 deletions(-) diff --git a/polygon/sync/canonical_chain_builder_test.go b/polygon/sync/canonical_chain_builder_test.go index aa640f3c479..802009e2c4d 100644 --- a/polygon/sync/canonical_chain_builder_test.go +++ b/polygon/sync/canonical_chain_builder_test.go @@ -1,23 +1,246 @@ package sync import ( + "bytes" + "errors" + "math/big" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + heimdallspan "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" "github.com/ledgerwatch/erigon/core/types" ) type testDifficultyCalculator struct { } -func (*testDifficultyCalculator) HeaderDifficulty(*types.Header) (uint64, error) { - return 0, nil +func (*testDifficultyCalculator) HeaderDifficulty(header *types.Header) (uint64, error) { + if header.Difficulty == nil { + return 0, errors.New("unset header.Difficulty") + } + return header.Difficulty.Uint64(), nil } -func TestCanonicalChainBuilderConnectEmpty(t *testing.T) { +func (*testDifficultyCalculator) SetSpan(*heimdallspan.HeimdallSpan) {} + +func makeRoot() *types.Header { + return &types.Header{ + Number: big.NewInt(0), + } +} + +func makeCCB(root *types.Header) CanonicalChainBuilder { difficultyCalc := testDifficultyCalculator{} - builder := NewCanonicalChainBuilder(new(types.Header), &difficultyCalc) - err := builder.Connect([]*types.Header{}) + builder := NewCanonicalChainBuilder(root, &difficultyCalc) + return builder +} + +type connectCCBTest struct { + t *testing.T + root *types.Header + builder CanonicalChainBuilder + + currentHeaderTime uint64 +} + +func newConnectCCBTest(t *testing.T) (*connectCCBTest, *types.Header) { + root := makeRoot() + builder := makeCCB(root) + test := &connectCCBTest{ + t: t, + root: root, + builder: builder, + } + return test, root +} + +func (test *connectCCBTest) makeHeader(parent *types.Header, difficulty uint64) *types.Header { + test.currentHeaderTime++ + return &types.Header{ + ParentHash: parent.Hash(), + Difficulty: big.NewInt(int64(difficulty)), + Number: big.NewInt(parent.Number.Int64() + 1), + Time: test.currentHeaderTime, + Extra: bytes.Repeat([]byte{0x00}, types.ExtraVanityLength+types.ExtraSealLength), + } +} + +func (test *connectCCBTest) makeHeaders(parent *types.Header, difficulties []uint64) []*types.Header { + count := len(difficulties) + headers := make([]*types.Header, 0, count) + for i := 0; i < count; i++ { + header := test.makeHeader(parent, difficulties[i]) + headers = append(headers, header) + parent = header + } + return headers +} + +func (test *connectCCBTest) testConnect( + headers []*types.Header, + expectedTip *types.Header, + expectedHeaders []*types.Header, +) { + t := test.t + builder := test.builder + + err := builder.Connect(headers) require.Nil(t, err) + + newTip := builder.Tip() + assert.Equal(t, expectedTip.Hash(), newTip.Hash()) + + require.NotNil(t, newTip.Number) + count := uint64(len(expectedHeaders)) + start := newTip.Number.Uint64() - (count - 1) + + actualHeaders := builder.HeadersInRange(start, count) + require.Equal(t, len(expectedHeaders), len(actualHeaders)) + for i, h := range actualHeaders { + assert.Equal(t, expectedHeaders[i].Hash(), h.Hash()) + } +} + +func TestCCBEmptyState(t *testing.T) { + test, root := newConnectCCBTest(t) + + tip := test.builder.Tip() + assert.Equal(t, root.Hash(), tip.Hash()) + + headers := test.builder.HeadersInRange(0, 1) + require.Equal(t, 1, len(headers)) + assert.Equal(t, root.Hash(), headers[0].Hash()) +} + +func TestCCBConnectEmpty(t *testing.T) { + test, root := newConnectCCBTest(t) + test.testConnect([]*types.Header{}, root, []*types.Header{root}) +} + +// connect 0 to 0 +func TestCCBConnectRoot(t *testing.T) { + test, root := newConnectCCBTest(t) + test.testConnect([]*types.Header{root}, root, []*types.Header{root}) +} + +// connect 1 to 0 +func TestCCBConnectOneToRoot(t *testing.T) { + test, root := newConnectCCBTest(t) + newTip := test.makeHeader(root, 1) + test.testConnect([]*types.Header{newTip}, newTip, []*types.Header{root, newTip}) +} + +// connect 1-2-3 to 0 +func TestCCBConnectSomeToRoot(t *testing.T) { + test, root := newConnectCCBTest(t) + headers := test.makeHeaders(root, []uint64{1, 2, 3}) + test.testConnect(headers, headers[len(headers)-1], append([]*types.Header{root}, headers...)) +} + +// connect any subset of 0-1-2-3 to 0-1-2-3 +func TestCCBConnectOverlapsFull(t *testing.T) { + test, root := newConnectCCBTest(t) + headers := test.makeHeaders(root, []uint64{1, 2, 3}) + require.Nil(t, test.builder.Connect(headers)) + + expectedTip := headers[len(headers)-1] + expectedHeaders := append([]*types.Header{root}, headers...) + + for subsetLen := 1; subsetLen <= len(headers); subsetLen++ { + for i := 0; i+subsetLen-1 < len(expectedHeaders); i++ { + headers := expectedHeaders[i : i+subsetLen] + test.testConnect(headers, expectedTip, expectedHeaders) + } + } +} + +// connect 0-1 to 0 +func TestCCBConnectOverlapPartialOne(t *testing.T) { + test, root := newConnectCCBTest(t) + newTip := test.makeHeader(root, 1) + test.testConnect([]*types.Header{root, newTip}, newTip, []*types.Header{root, newTip}) +} + +// connect 2-3-4-5 to 0-1-2-3 +func TestCCBConnectOverlapPartialSome(t *testing.T) { + test, root := newConnectCCBTest(t) + headers := test.makeHeaders(root, []uint64{1, 2, 3}) + require.Nil(t, test.builder.Connect(headers)) + + overlapHeaders := append(headers[1:], test.makeHeaders(headers[len(headers)-1], []uint64{4, 5})...) + expectedTip := overlapHeaders[len(overlapHeaders)-1] + expectedHeaders := append([]*types.Header{root, headers[0]}, overlapHeaders...) + test.testConnect(overlapHeaders, expectedTip, expectedHeaders) +} + +// connect 2 to 0-1 at 0, then connect 10 to 0-1 +func TestCCBConnectAltMainBecomesFork(t *testing.T) { + test, root := newConnectCCBTest(t) + header1 := test.makeHeader(root, 1) + header2 := test.makeHeader(root, 2) + require.Nil(t, test.builder.Connect([]*types.Header{header1})) + + // the tip changes to header2 + test.testConnect([]*types.Header{header2}, header2, []*types.Header{root, header2}) + + header10 := test.makeHeader(header1, 10) + test.testConnect([]*types.Header{header10}, header10, []*types.Header{root, header1, header10}) +} + +// connect 1 to 0-2 at 0, then connect 10 to 0-1 +func TestCCBConnectAltForkBecomesMain(t *testing.T) { + test, root := newConnectCCBTest(t) + header1 := test.makeHeader(root, 1) + header2 := test.makeHeader(root, 2) + require.Nil(t, test.builder.Connect([]*types.Header{header2})) + + // the tip stays at header2 + test.testConnect([]*types.Header{header1}, header2, []*types.Header{root, header2}) + + header10 := test.makeHeader(header1, 10) + test.testConnect([]*types.Header{header10}, header10, []*types.Header{root, header1, header10}) +} + +// connect 10 and 11 to 1, then 20 and 22 to 2 one by one starting from a [0-1, 0-2] tree +func TestCCBConnectAltForksAtLevel2(t *testing.T) { + test, root := newConnectCCBTest(t) + header1 := test.makeHeader(root, 1) + header10 := test.makeHeader(header1, 10) + header11 := test.makeHeader(header1, 11) + header2 := test.makeHeader(root, 2) + header20 := test.makeHeader(header2, 20) + header22 := test.makeHeader(header2, 22) + require.Nil(t, test.builder.Connect([]*types.Header{header1})) + require.Nil(t, test.builder.Connect([]*types.Header{header2})) + + test.testConnect([]*types.Header{header10}, header10, []*types.Header{root, header1, header10}) + test.testConnect([]*types.Header{header11}, header11, []*types.Header{root, header1, header11}) + test.testConnect([]*types.Header{header20}, header20, []*types.Header{root, header2, header20}) + test.testConnect([]*types.Header{header22}, header22, []*types.Header{root, header2, header22}) +} + +// connect 11 and 10 to 1, then 22 and 20 to 2 one by one starting from a [0-1, 0-2] tree +// then connect 100 to 10, and 200 to 20 +func TestCCBConnectAltForksAtLevel2Reverse(t *testing.T) { + test, root := newConnectCCBTest(t) + header1 := test.makeHeader(root, 1) + header10 := test.makeHeader(header1, 10) + header11 := test.makeHeader(header1, 11) + header2 := test.makeHeader(root, 2) + header20 := test.makeHeader(header2, 20) + header22 := test.makeHeader(header2, 22) + header100 := test.makeHeader(header10, 100) + header200 := test.makeHeader(header20, 200) + require.Nil(t, test.builder.Connect([]*types.Header{header1})) + require.Nil(t, test.builder.Connect([]*types.Header{header2})) + + test.testConnect([]*types.Header{header11}, header11, []*types.Header{root, header1, header11}) + test.testConnect([]*types.Header{header10}, header11, []*types.Header{root, header1, header11}) + test.testConnect([]*types.Header{header22}, header22, []*types.Header{root, header2, header22}) + test.testConnect([]*types.Header{header20}, header22, []*types.Header{root, header2, header22}) + + test.testConnect([]*types.Header{header100}, header100, []*types.Header{root, header1, header10, header100}) + test.testConnect([]*types.Header{header200}, header200, []*types.Header{root, header2, header20, header200}) } diff --git a/polygon/sync/difficulty.go b/polygon/sync/difficulty.go index 7a6895c506c..c632050024b 100644 --- a/polygon/sync/difficulty.go +++ b/polygon/sync/difficulty.go @@ -2,9 +2,10 @@ package sync import ( lru "github.com/hashicorp/golang-lru/arc/v2" - "github.com/ledgerwatch/erigon/eth/stagedsync" "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon/eth/stagedsync" + libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/consensus/bor" "github.com/ledgerwatch/erigon/consensus/bor/borcfg" @@ -15,32 +16,56 @@ import ( type DifficultyCalculator interface { HeaderDifficulty(header *types.Header) (uint64, error) + SetSpan(span *heimdallspan.HeimdallSpan) } type difficultyCalculatorImpl struct { - borConfig *borcfg.BorConfig - span *heimdallspan.HeimdallSpan - signaturesCache *lru.ARCCache[libcommon.Hash, libcommon.Address] + borConfig *borcfg.BorConfig + span *heimdallspan.HeimdallSpan + validatorSetFactory func() validatorSetInterface + signaturesCache *lru.ARCCache[libcommon.Hash, libcommon.Address] log log.Logger } +// valset.ValidatorSet abstraction for unit tests +type validatorSetInterface interface { + IncrementProposerPriority(times int, logger log.Logger) + Difficulty(signer libcommon.Address) (uint64, error) +} + func NewDifficultyCalculator( borConfig *borcfg.BorConfig, span *heimdallspan.HeimdallSpan, + validatorSetFactory func() validatorSetInterface, log log.Logger, ) DifficultyCalculator { signaturesCache, err := lru.NewARC[libcommon.Hash, libcommon.Address](stagedsync.InMemorySignatures) if err != nil { panic(err) } - return &difficultyCalculatorImpl{ - borConfig: borConfig, - span: span, - signaturesCache: signaturesCache, + impl := difficultyCalculatorImpl{ + borConfig: borConfig, + span: span, + validatorSetFactory: validatorSetFactory, + signaturesCache: signaturesCache, log: log, } + + if validatorSetFactory == nil { + impl.validatorSetFactory = impl.makeValidatorSet + } + + return &impl +} + +func (impl *difficultyCalculatorImpl) makeValidatorSet() validatorSetInterface { + return valset.NewValidatorSet(impl.span.ValidatorSet.Validators, impl.log) +} + +func (impl *difficultyCalculatorImpl) SetSpan(span *heimdallspan.HeimdallSpan) { + impl.span = span } func (impl *difficultyCalculatorImpl) HeaderDifficulty(header *types.Header) (uint64, error) { @@ -48,12 +73,15 @@ func (impl *difficultyCalculatorImpl) HeaderDifficulty(header *types.Header) (ui if err != nil { return 0, err } + return impl.signerDifficulty(signer, header.Number.Uint64()) +} - validatorSet := valset.NewValidatorSet(impl.span.ValidatorSet.Validators, log.New()) +func (impl *difficultyCalculatorImpl) signerDifficulty(signer libcommon.Address, headerNum uint64) (uint64, error) { + validatorSet := impl.validatorSetFactory() - sprintCount := impl.borConfig.CalculateSprintNumber(header.Number.Uint64()) - if sprintCount > 0 { - validatorSet.IncrementProposerPriority(int(sprintCount), impl.log) + sprintNum := impl.borConfig.CalculateSprintNumber(headerNum) + if sprintNum > 0 { + validatorSet.IncrementProposerPriority(int(sprintNum), impl.log) } return validatorSet.Difficulty(signer) diff --git a/polygon/sync/difficulty_test.go b/polygon/sync/difficulty_test.go index 69d684149ed..77b0711c3b2 100644 --- a/polygon/sync/difficulty_test.go +++ b/polygon/sync/difficulty_test.go @@ -1,21 +1,126 @@ package sync import ( - "github.com/ledgerwatch/log/v3" "testing" + "github.com/ledgerwatch/log/v3" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/consensus/bor/borcfg" heimdallspan "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" "github.com/ledgerwatch/erigon/core/types" ) +type testValidatorSetInterface struct { + signers []libcommon.Address + sprintNum int +} + +func (v *testValidatorSetInterface) IncrementProposerPriority(times int, _ log.Logger) { + v.sprintNum = times +} + +func (v *testValidatorSetInterface) Difficulty(signer libcommon.Address) (uint64, error) { + var i int + for (i < len(v.signers)) && (v.signers[i] != signer) { + i++ + } + + sprintOffset := v.sprintNum % len(v.signers) + var delta int + if i >= sprintOffset { + delta = i - sprintOffset + } else { + delta = i + len(v.signers) - sprintOffset + } + + return uint64(len(v.signers) - delta), nil +} + +func TestSignerDifficulty(t *testing.T) { + borConfig := borcfg.BorConfig{ + Sprint: map[string]uint64{"0": 16}, + } + span := heimdallspan.HeimdallSpan{} + signers := []libcommon.Address{ + libcommon.HexToAddress("00"), + libcommon.HexToAddress("01"), + libcommon.HexToAddress("02"), + } + validatorSetFactory := func() validatorSetInterface { return &testValidatorSetInterface{signers: signers} } + logger := log.New() + calc := NewDifficultyCalculator(&borConfig, &span, validatorSetFactory, logger).(*difficultyCalculatorImpl) + + var d uint64 + + // sprint 0 + d, _ = calc.signerDifficulty(signers[0], 0) + assert.Equal(t, uint64(3), d) + + d, _ = calc.signerDifficulty(signers[0], 1) + assert.Equal(t, uint64(3), d) + + d, _ = calc.signerDifficulty(signers[0], 15) + assert.Equal(t, uint64(3), d) + + d, _ = calc.signerDifficulty(signers[1], 0) + assert.Equal(t, uint64(2), d) + + d, _ = calc.signerDifficulty(signers[1], 1) + assert.Equal(t, uint64(2), d) + + d, _ = calc.signerDifficulty(signers[1], 15) + assert.Equal(t, uint64(2), d) + + d, _ = calc.signerDifficulty(signers[2], 0) + assert.Equal(t, uint64(1), d) + + d, _ = calc.signerDifficulty(signers[2], 1) + assert.Equal(t, uint64(1), d) + + d, _ = calc.signerDifficulty(signers[2], 15) + assert.Equal(t, uint64(1), d) + + // sprint 1 + d, _ = calc.signerDifficulty(signers[1], 16) + assert.Equal(t, uint64(3), d) + + d, _ = calc.signerDifficulty(signers[2], 16) + assert.Equal(t, uint64(2), d) + + d, _ = calc.signerDifficulty(signers[0], 16) + assert.Equal(t, uint64(1), d) + + // sprint 2 + d, _ = calc.signerDifficulty(signers[2], 32) + assert.Equal(t, uint64(3), d) + + d, _ = calc.signerDifficulty(signers[0], 32) + assert.Equal(t, uint64(2), d) + + d, _ = calc.signerDifficulty(signers[1], 32) + assert.Equal(t, uint64(1), d) + + // sprint 3 + d, _ = calc.signerDifficulty(signers[0], 48) + assert.Equal(t, uint64(3), d) + + d, _ = calc.signerDifficulty(signers[1], 48) + assert.Equal(t, uint64(2), d) + + d, _ = calc.signerDifficulty(signers[2], 48) + assert.Equal(t, uint64(1), d) +} + func TestHeaderDifficultyNoSignature(t *testing.T) { borConfig := borcfg.BorConfig{} span := heimdallspan.HeimdallSpan{} logger := log.New() - calc := NewDifficultyCalculator(&borConfig, &span, logger) + calc := NewDifficultyCalculator(&borConfig, &span, nil, logger) + _, err := calc.HeaderDifficulty(new(types.Header)) require.ErrorContains(t, err, "signature suffix missing") } From b2fa618f74fcf6e62ca5127da7182640406f8e85 Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Mon, 8 Jan 2024 17:13:25 +0100 Subject: [PATCH 17/92] Caplin: Fixed crash in OnAttestation (#9159) * Added handling of AggregateAndProof --- cl/beacon/handler/handler.go | 7 ++-- cl/beacon/handler/node.go | 18 +++++++++- cl/beacon/handler/node_test.go | 26 +++++++++++++-- cl/beacon/handler/utils_test.go | 3 +- cl/phase1/core/state/accessors.go | 7 ++++ cl/phase1/core/state/cache.go | 31 +++++++++++------ cl/phase1/forkchoice/fork_choice_test.go | 2 +- cl/phase1/forkchoice/forkchoice_mock.go | 2 +- cl/phase1/forkchoice/interface.go | 2 +- cl/phase1/forkchoice/on_attestation.go | 39 +++++++++++++++++++--- cl/phase1/network/gossip_manager.go | 4 +++ cl/phase1/stages/clstages.go | 2 +- cl/pool/operation_pool.go | 29 ++++++++++++++-- cl/sentinel/service/start.go | 2 +- cl/spectest/consensus_tests/fork_choice.go | 5 +-- cmd/caplin-regression/regression/tester.go | 2 +- cmd/caplin/caplin1/run.go | 3 +- 17 files changed, 153 insertions(+), 31 deletions(-) diff --git a/cl/beacon/handler/handler.go b/cl/beacon/handler/handler.go index 9ead9cb0b2f..47baf6175fd 100644 --- a/cl/beacon/handler/handler.go +++ b/cl/beacon/handler/handler.go @@ -32,14 +32,16 @@ type ApiHandler struct { stateReader *historical_states_reader.HistoricalStatesReader sentinel sentinel.SentinelClient + version string // Node's version + // pools randaoMixesPool sync.Pool } -func NewApiHandler(genesisConfig *clparams.GenesisConfig, beaconChainConfig *clparams.BeaconChainConfig, source persistence.RawBeaconBlockChain, indiciesDB kv.RoDB, forkchoiceStore forkchoice.ForkChoiceStorage, operationsPool pool.OperationsPool, rcsn freezeblocks.BeaconSnapshotReader, syncedData *synced_data.SyncedDataManager, stateReader *historical_states_reader.HistoricalStatesReader, sentinel sentinel.SentinelClient) *ApiHandler { +func NewApiHandler(genesisConfig *clparams.GenesisConfig, beaconChainConfig *clparams.BeaconChainConfig, source persistence.RawBeaconBlockChain, indiciesDB kv.RoDB, forkchoiceStore forkchoice.ForkChoiceStorage, operationsPool pool.OperationsPool, rcsn freezeblocks.BeaconSnapshotReader, syncedData *synced_data.SyncedDataManager, stateReader *historical_states_reader.HistoricalStatesReader, sentinel sentinel.SentinelClient, version string) *ApiHandler { return &ApiHandler{o: sync.Once{}, genesisCfg: genesisConfig, beaconChainCfg: beaconChainConfig, indiciesDB: indiciesDB, forkchoiceStore: forkchoiceStore, operationsPool: operationsPool, blockReader: rcsn, syncedData: syncedData, stateReader: stateReader, randaoMixesPool: sync.Pool{New: func() interface{} { return solid.NewHashVector(int(beaconChainConfig.EpochsPerHistoricalVector)) - }}, sentinel: sentinel} + }}, sentinel: sentinel, version: version} } func (a *ApiHandler) init() { @@ -53,6 +55,7 @@ func (a *ApiHandler) init() { r.Get("/events", http.NotFound) r.Route("/node", func(r chi.Router) { r.Get("/health", a.GetEthV1NodeHealth) + r.Get("/version", a.GetEthV1NodeVersion) }) r.Get("/debug/fork_choice", a.GetEthV1DebugBeaconForkChoice) r.Route("/config", func(r chi.Router) { diff --git a/cl/beacon/handler/node.go b/cl/beacon/handler/node.go index 26f4fc46f0d..72687b2e371 100644 --- a/cl/beacon/handler/node.go +++ b/cl/beacon/handler/node.go @@ -1,6 +1,11 @@ package handler -import "net/http" +import ( + "encoding/json" + "fmt" + "net/http" + "runtime" +) func (a *ApiHandler) GetEthV1NodeHealth(w http.ResponseWriter, r *http.Request) { syncingStatus, err := uint64FromQueryParams(r, "syncing_status") @@ -18,3 +23,14 @@ func (a *ApiHandler) GetEthV1NodeHealth(w http.ResponseWriter, r *http.Request) } w.WriteHeader(http.StatusOK) } + +func (a *ApiHandler) GetEthV1NodeVersion(w http.ResponseWriter, r *http.Request) { + // Get OS and Arch + if err := json.NewEncoder(w).Encode(map[string]interface{}{ + "data": map[string]interface{}{ + "version": fmt.Sprintf("Caplin/%s %s/%s", a.version, runtime.GOOS, runtime.GOARCH), + }, + }); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } +} diff --git a/cl/beacon/handler/node_test.go b/cl/beacon/handler/node_test.go index 094412ddd7e..8572f1430fa 100644 --- a/cl/beacon/handler/node_test.go +++ b/cl/beacon/handler/node_test.go @@ -1,15 +1,17 @@ package handler import ( + "encoding/json" "net/http" "net/http/httptest" + "strings" "testing" "github.com/ledgerwatch/erigon/cl/clparams" "github.com/stretchr/testify/require" ) -func TestNodeSyncing(t *testing.T) { +func TestNodeHealthSyncing(t *testing.T) { // i just want the correct schema to be generated _, _, _, _, _, handler, _, _, _ := setupTestingHandler(t, clparams.Phase0Version) @@ -26,7 +28,7 @@ func TestNodeSyncing(t *testing.T) { require.Equal(t, 666, resp.StatusCode) } -func TestNodeSyncingTip(t *testing.T) { +func TestNodeHealthSyncingTip(t *testing.T) { // i just want the correct schema to be generated _, _, _, _, post, handler, _, sm, _ := setupTestingHandler(t, clparams.Phase0Version) @@ -47,3 +49,23 @@ func TestNodeSyncingTip(t *testing.T) { defer resp.Body.Close() require.Equal(t, 200, resp.StatusCode) } + +func TestNodeVersion(t *testing.T) { + // i just want the correct schema to be generated + _, _, _, _, _, handler, _, _, _ := setupTestingHandler(t, clparams.Phase0Version) + + // Call GET /eth/v1/node/health + server := httptest.NewServer(handler.mux) + defer server.Close() + + req, err := http.NewRequest("GET", server.URL+"/eth/v1/node/version", nil) + require.NoError(t, err) + + resp, err := http.DefaultClient.Do(req) + require.NoError(t, err) + defer resp.Body.Close() + out := map[string]interface{}{} + require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) + v := out["data"].(map[string]interface{})["version"].(string) + require.True(t, strings.Contains(v, "Caplin")) +} diff --git a/cl/beacon/handler/utils_test.go b/cl/beacon/handler/utils_test.go index f4117fa176f..345cd94d7a6 100644 --- a/cl/beacon/handler/utils_test.go +++ b/cl/beacon/handler/utils_test.go @@ -62,7 +62,8 @@ func setupTestingHandler(t *testing.T, v clparams.StateVersion) (db kv.RwDB, blo reader, syncedData, statesReader, - nil) + nil, + "test-version") handler.init() return } diff --git a/cl/phase1/core/state/accessors.go b/cl/phase1/core/state/accessors.go index 14d6d74c03d..90974b2cce8 100644 --- a/cl/phase1/core/state/accessors.go +++ b/cl/phase1/core/state/accessors.go @@ -1,6 +1,7 @@ package state import ( + "encoding/binary" "fmt" "github.com/Giulio2002/bls" @@ -28,6 +29,12 @@ func Epoch(b abstract.BeaconStateBasic) uint64 { return GetEpochAtSlot(b.BeaconConfig(), b.Slot()) } +func IsAggregator(cfg *clparams.BeaconChainConfig, committeeLength, slot, committeeIndex uint64, slotSignature libcommon.Bytes96) bool { + modulo := utils.Max64(1, committeeLength/cfg.TargetAggregatorsPerCommittee) + hashSlotSignatue := utils.Sha256(slotSignature[:]) + return binary.LittleEndian.Uint64(hashSlotSignatue[:8])%modulo == 0 +} + // GetTotalBalance return the sum of all balances within the given validator set. func GetTotalBalance(b abstract.BeaconStateBasic, validatorSet []uint64) (uint64, error) { var ( diff --git a/cl/phase1/core/state/cache.go b/cl/phase1/core/state/cache.go index fcd410f080d..63ada362378 100644 --- a/cl/phase1/core/state/cache.go +++ b/cl/phase1/core/state/cache.go @@ -334,11 +334,16 @@ func readUint64WithBuffer(r io.Reader, buf []byte, out *uint64) error { // internal encoding/decoding algos func (b *CachingBeaconState) encodeActiveValidatorsCache(w io.Writer, num []byte) error { - keys := b.activeValidatorsCache.Keys() - lists := make([][]uint64, len(keys)) - - for i, key := range keys { - lists[i], _ = b.activeValidatorsCache.Get(key) + keysA := b.activeValidatorsCache.Keys() + keys := make([]uint64, 0, len(keysA)) + lists := make([][]uint64, 0, len(keys)) + for _, key := range keysA { + l, ok := b.activeValidatorsCache.Get(key) + if !ok || len(l) == 0 { + continue + } + keys = append(keys, key) + lists = append(lists, l) } // Write the total length if err := writeUint64WithBuffer(w, uint64(len(keys)), num); err != nil { @@ -396,11 +401,17 @@ func (b *CachingBeaconState) decodeActiveValidatorsCache(r io.Reader, num []byte // internal encoding/decoding algos func (b *CachingBeaconState) encodeShuffledSetsCache(w io.Writer, num []byte) error { - keys := b.shuffledSetsCache.Keys() - lists := make([][]uint64, len(keys)) - - for i, key := range keys { - lists[i], _ = b.shuffledSetsCache.Get(key) + keysA := b.shuffledSetsCache.Keys() + keys := make([]common.Hash, 0, len(keysA)) + lists := make([][]uint64, 0, len(keys)) + + for _, key := range keysA { + l, ok := b.shuffledSetsCache.Get(key) + if !ok || len(l) == 0 { + continue + } + keys = append(keys, key) + lists = append(lists, l) } // Write the total length if err := writeUint64WithBuffer(w, uint64(len(keys)), num); err != nil { diff --git a/cl/phase1/forkchoice/fork_choice_test.go b/cl/phase1/forkchoice/fork_choice_test.go index f712a447124..fa3559490d3 100644 --- a/cl/phase1/forkchoice/fork_choice_test.go +++ b/cl/phase1/forkchoice/fork_choice_test.go @@ -92,7 +92,7 @@ func TestForkChoiceBasic(t *testing.T) { require.Equal(t, headSlot, uint64(3)) require.Equal(t, headRoot, libcommon.HexToHash("0x744cc484f6503462f0f3a5981d956bf4fcb3e57ab8687ed006467e05049ee033")) // lastly do attestation - require.NoError(t, store.OnAttestation(testAttestation, false)) + require.NoError(t, store.OnAttestation(testAttestation, false, false)) // Try processing a voluntary exit err = store.OnVoluntaryExit(&cltypes.SignedVoluntaryExit{ VoluntaryExit: &cltypes.VoluntaryExit{ diff --git a/cl/phase1/forkchoice/forkchoice_mock.go b/cl/phase1/forkchoice/forkchoice_mock.go index 6ae413d4f96..691b832f8a8 100644 --- a/cl/phase1/forkchoice/forkchoice_mock.go +++ b/cl/phase1/forkchoice/forkchoice_mock.go @@ -160,7 +160,7 @@ func (f *ForkChoiceStorageMock) Time() uint64 { return f.TimeVal } -func (f *ForkChoiceStorageMock) OnAttestation(attestation *solid.Attestation, fromBlock bool) error { +func (f *ForkChoiceStorageMock) OnAttestation(attestation *solid.Attestation, fromBlock, insert bool) error { f.Pool.AttestationsPool.Insert(attestation.Signature(), attestation) return nil } diff --git a/cl/phase1/forkchoice/interface.go b/cl/phase1/forkchoice/interface.go index 7da33e5acbf..81fa579e2e6 100644 --- a/cl/phase1/forkchoice/interface.go +++ b/cl/phase1/forkchoice/interface.go @@ -44,7 +44,7 @@ type ForkChoiceStorageReader interface { } type ForkChoiceStorageWriter interface { - OnAttestation(attestation *solid.Attestation, fromBlock bool) error + OnAttestation(attestation *solid.Attestation, fromBlock, insert bool) error OnAttesterSlashing(attesterSlashing *cltypes.AttesterSlashing, test bool) error OnVoluntaryExit(signedVoluntaryExit *cltypes.SignedVoluntaryExit, test bool) error OnProposerSlashing(proposerSlashing *cltypes.ProposerSlashing, test bool) error diff --git a/cl/phase1/forkchoice/on_attestation.go b/cl/phase1/forkchoice/on_attestation.go index ed734b4b8a7..5dd9326b0fc 100644 --- a/cl/phase1/forkchoice/on_attestation.go +++ b/cl/phase1/forkchoice/on_attestation.go @@ -4,6 +4,7 @@ import ( "fmt" "time" + "github.com/ledgerwatch/erigon/cl/cltypes" "github.com/ledgerwatch/erigon/cl/cltypes/solid" "github.com/ledgerwatch/erigon/cl/phase1/cache" "github.com/ledgerwatch/erigon/cl/phase1/core/state" @@ -13,7 +14,7 @@ import ( ) // OnAttestation processes incoming attestations. -func (f *ForkChoiceStore) OnAttestation(attestation *solid.Attestation, fromBlock bool) error { +func (f *ForkChoiceStore) OnAttestation(attestation *solid.Attestation, fromBlock bool, insert bool) error { f.mu.Lock() defer f.mu.Unlock() f.headHash = libcommon.Hash{} @@ -61,11 +62,41 @@ func (f *ForkChoiceStore) OnAttestation(attestation *solid.Attestation, fromBloc cache.StoreAttestation(&data, attestation.AggregationBits(), attestationIndicies) // Lastly update latest messages. f.processAttestingIndicies(attestation, attestationIndicies) + if !fromBlock && insert { + // Add to the pool when verified. + f.operationsPool.AttestationsPool.Insert(attestation.Signature(), attestation) + } return nil } +func (f *ForkChoiceStore) OnAggregateAndProof(aggregateAndProof *cltypes.SignedAggregateAndProof, test bool) error { + slot := aggregateAndProof.Message.Aggregate.AttestantionData().Slot() + selectionProof := aggregateAndProof.Message.SelectionProof + committeeIndex := aggregateAndProof.Message.Aggregate.AttestantionData().ValidatorIndex() + epoch := state.GetEpochAtSlot(f.beaconCfg, slot) + + target := aggregateAndProof.Message.Aggregate.AttestantionData().Target() + targetState, err := f.getCheckpointState(target) + if err != nil { + return nil + } + + activeIndicies := targetState.getActiveIndicies(epoch) + activeIndiciesLength := uint64(len(activeIndicies)) + + count := targetState.committeeCount(epoch, activeIndiciesLength) * f.beaconCfg.SlotsPerEpoch + start := (activeIndiciesLength * committeeIndex) / count + end := (activeIndiciesLength * (committeeIndex + 1)) / count + committeeLength := end - start + if !state.IsAggregator(f.beaconCfg, committeeLength, slot, committeeIndex, selectionProof) { + log.Warn("invalid aggregate and proof") + return fmt.Errorf("invalid aggregate and proof") + } + return f.OnAttestation(aggregateAndProof.Message.Aggregate, false, false) +} + // scheduleAttestationForLaterProcessing scheudules an attestation for later processing -func (f *ForkChoiceStore) scheduleAttestationForLaterProcessing(attestation *solid.Attestation, fromBlock bool) { +func (f *ForkChoiceStore) scheduleAttestationForLaterProcessing(attestation *solid.Attestation, insert bool) { go func() { logInterval := time.NewTicker(50 * time.Millisecond) for { @@ -76,8 +107,8 @@ func (f *ForkChoiceStore) scheduleAttestationForLaterProcessing(attestation *sol if f.Slot() < attestation.AttestantionData().Slot()+1 { continue } - if err := f.OnAttestation(attestation, false); err != nil { - log.Trace("could not process scheduled attestation", "reason", err) + if err := f.OnAttestation(attestation, false, insert); err != nil { + log.Debug("could not process scheduled attestation", "reason", err) } return } diff --git a/cl/phase1/network/gossip_manager.go b/cl/phase1/network/gossip_manager.go index 1207c1e924b..88c0841dea8 100644 --- a/cl/phase1/network/gossip_manager.go +++ b/cl/phase1/network/gossip_manager.go @@ -160,6 +160,10 @@ func (g *GossipManager) onRecv(ctx context.Context, data *sentinel.GossipData, l if err := operationsContract[*cltypes.SignedBLSToExecutionChange](ctx, g, l, data, int(version), "bls to execution change", g.forkChoice.OnBlsToExecutionChange); err != nil { return err } + case gossip.TopicNameBeaconAggregateAndProof: + if err := operationsContract[*cltypes.SignedAggregateAndProof](ctx, g, l, data, int(version), "aggregate and proof", g.forkChoice.OnAggregateAndProof); err != nil { + return err + } } return nil } diff --git a/cl/phase1/stages/clstages.go b/cl/phase1/stages/clstages.go index b2d57dd01a7..8c5710bfe50 100644 --- a/cl/phase1/stages/clstages.go +++ b/cl/phase1/stages/clstages.go @@ -405,7 +405,7 @@ func ConsensusClStages(ctx context.Context, continue MainLoop } block.Block.Body.Attestations.Range(func(idx int, a *solid.Attestation, total int) bool { - if err = cfg.forkChoice.OnAttestation(a, true); err != nil { + if err = cfg.forkChoice.OnAttestation(a, true, false); err != nil { log.Debug("bad attestation received", "err", err) } return true diff --git a/cl/pool/operation_pool.go b/cl/pool/operation_pool.go index 44962135584..348680559c5 100644 --- a/cl/pool/operation_pool.go +++ b/cl/pool/operation_pool.go @@ -1,13 +1,19 @@ package pool import ( + "time" + "github.com/ledgerwatch/erigon/cl/phase1/core/state/lru" ) +const lifeSpan = 30 * time.Minute + var operationsMultiplier = 20 // Cap the amount of cached element to max_operations_per_block * operations_multiplier type OperationPool[K comparable, T any] struct { - pool *lru.Cache[K, T] // Map the Signature to the underlying object + pool *lru.Cache[K, T] // Map the Signature to the underlying object + recentlySeen map[K]time.Time + lastPruned time.Time } func NewOperationPool[K comparable, T any](maxOperationsPerBlock int, matricName string) *OperationPool[K, T] { @@ -15,11 +21,30 @@ func NewOperationPool[K comparable, T any](maxOperationsPerBlock int, matricName if err != nil { panic(err) } - return &OperationPool[K, T]{pool: pool} + return &OperationPool[K, T]{ + pool: pool, + recentlySeen: make(map[K]time.Time), + } } func (o *OperationPool[K, T]) Insert(k K, operation T) { + if _, ok := o.recentlySeen[k]; ok { + return + } o.pool.Add(k, operation) + o.recentlySeen[k] = time.Now() + if time.Since(o.lastPruned) > lifeSpan { + deleteList := make([]K, 0, len(o.recentlySeen)) + for k, t := range o.recentlySeen { + if time.Since(t) > lifeSpan { + deleteList = append(deleteList, k) + } + } + for _, k := range deleteList { + delete(o.recentlySeen, k) + } + o.lastPruned = time.Now() + } } func (o *OperationPool[K, T]) DeleteIfExist(k K) (removed bool) { diff --git a/cl/sentinel/service/start.go b/cl/sentinel/service/start.go index 50ad1b38cf1..f84de009455 100644 --- a/cl/sentinel/service/start.go +++ b/cl/sentinel/service/start.go @@ -31,7 +31,7 @@ func createSentinel(cfg *sentinel.SentinelConfig, db persistence.RawBeaconBlockC } gossipTopics := []sentinel.GossipTopic{ sentinel.BeaconBlockSsz, - //sentinel.BeaconAggregateAndProofSsz, + sentinel.BeaconAggregateAndProofSsz, sentinel.VoluntaryExitSsz, sentinel.ProposerSlashingSsz, sentinel.AttesterSlashingSsz, diff --git a/cl/spectest/consensus_tests/fork_choice.go b/cl/spectest/consensus_tests/fork_choice.go index ca39a83c042..ac33534e067 100644 --- a/cl/spectest/consensus_tests/fork_choice.go +++ b/cl/spectest/consensus_tests/fork_choice.go @@ -3,10 +3,11 @@ package consensus_tests import ( "context" "fmt" - "github.com/ledgerwatch/erigon/spectest" "io/fs" "testing" + "github.com/ledgerwatch/erigon/spectest" + "github.com/ledgerwatch/erigon/cl/abstract" "github.com/ledgerwatch/erigon/cl/clparams" "github.com/ledgerwatch/erigon/cl/cltypes/solid" @@ -194,7 +195,7 @@ func (b *ForkChoice) Run(t *testing.T, root fs.FS, c spectest.TestCase) (err err att := &solid.Attestation{} err := spectest.ReadSsz(root, c.Version(), step.GetAttestation()+".ssz_snappy", att) require.NoError(t, err, stepstr) - err = forkStore.OnAttestation(att, false) + err = forkStore.OnAttestation(att, false, false) if step.GetValid() { require.NoError(t, err, stepstr) } else { diff --git a/cmd/caplin-regression/regression/tester.go b/cmd/caplin-regression/regression/tester.go index badaebe5413..9734b21894f 100644 --- a/cmd/caplin-regression/regression/tester.go +++ b/cmd/caplin-regression/regression/tester.go @@ -88,7 +88,7 @@ func TestRegressionWithValidation(store *forkchoice.ForkChoiceStore, block *clty return err } block.Block.Body.Attestations.Range(func(index int, value *solid2.Attestation, length int) bool { - store.OnAttestation(value, true) + store.OnAttestation(value, true, true) return true }) return nil diff --git a/cmd/caplin/caplin1/run.go b/cmd/caplin/caplin1/run.go index 7455d911fe3..6edd4857287 100644 --- a/cmd/caplin/caplin1/run.go +++ b/cmd/caplin/caplin1/run.go @@ -18,6 +18,7 @@ import ( "github.com/ledgerwatch/erigon/cl/freezer" freezer2 "github.com/ledgerwatch/erigon/cl/freezer" "github.com/ledgerwatch/erigon/eth/ethconfig" + "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/turbo/snapshotsync/freezeblocks" "github.com/ledgerwatch/erigon/cl/persistence" @@ -212,7 +213,7 @@ func RunCaplinPhase1(ctx context.Context, sentinel sentinel.SentinelClient, engi statesReader := historical_states_reader.NewHistoricalStatesReader(beaconConfig, rcsn, vTables, af, genesisState) syncedDataManager := synced_data.NewSyncedDataManager(cfg.Active, beaconConfig) if cfg.Active { - apiHandler := handler.NewApiHandler(genesisConfig, beaconConfig, rawDB, indexDB, forkChoice, pool, rcsn, syncedDataManager, statesReader, sentinel) + apiHandler := handler.NewApiHandler(genesisConfig, beaconConfig, rawDB, indexDB, forkChoice, pool, rcsn, syncedDataManager, statesReader, sentinel, params.GitTag) headApiHandler := &validatorapi.ValidatorApiHandler{ FC: forkChoice, BeaconChainCfg: beaconConfig, From b4e6563e4a65454dcd615678d67ed99e2c036f5d Mon Sep 17 00:00:00 2001 From: Dmytro Date: Mon, 8 Jan 2024 18:52:28 +0100 Subject: [PATCH 18/92] fixed sync.loop flags (#9167) --- eth/stagedsync/sync.go | 4 ++-- turbo/cli/default_flags.go | 3 +++ turbo/cli/flags.go | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/eth/stagedsync/sync.go b/eth/stagedsync/sync.go index df75def7ccc..f90e0577b11 100644 --- a/eth/stagedsync/sync.go +++ b/eth/stagedsync/sync.go @@ -310,7 +310,7 @@ func (s *Sync) RunNoInterrupt(db kv.RwDB, tx kv.RwTx, firstCycle bool) error { } if string(stage.ID) == s.cfg.BreakAfterStage { // break process loop - s.logger.Warn("--sync.loop.break caused stage break") + s.logger.Warn("--sync.loop.break.after caused stage break") break } @@ -385,7 +385,7 @@ func (s *Sync) Run(db kv.RwDB, tx kv.RwTx, firstCycle bool) (bool, error) { } if string(stage.ID) == s.cfg.BreakAfterStage { // break process loop - s.logger.Warn("--sync.loop.break caused stage break") + s.logger.Warn("--sync.loop.break.after caused stage break") if s.posTransition != nil { ptx := tx diff --git a/turbo/cli/default_flags.go b/turbo/cli/default_flags.go index 63e138f889b..d5ab5f85a5d 100644 --- a/turbo/cli/default_flags.go +++ b/turbo/cli/default_flags.go @@ -186,4 +186,7 @@ var DefaultFlags = []cli.Flag{ &utils.RPCSlowFlag, &utils.TxPoolGossipDisableFlag, + &SyncLoopBlockLimitFlag, + &SyncLoopBreakAfterFlag, + &SyncLoopPruneLimitFlag, } diff --git a/turbo/cli/flags.go b/turbo/cli/flags.go index 4ab09e4358b..75261f14db3 100644 --- a/turbo/cli/flags.go +++ b/turbo/cli/flags.go @@ -156,7 +156,7 @@ var ( } SyncLoopBreakAfterFlag = cli.StringFlag{ - Name: "sync.loop.break", + Name: "sync.loop.break.after", Usage: "Sets the last stage of the sync loop to run", Value: "", } From 19b9504039b3f388faceb48356538848f34c9f26 Mon Sep 17 00:00:00 2001 From: milen <94537774+taratorio@users.noreply.github.com> Date: Mon, 8 Jan 2024 18:37:22 +0000 Subject: [PATCH 19/92] stagedsync: borheimdall segments min check minor improvement (#9168) --- eth/stagedsync/stage_bor_heimdall.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/eth/stagedsync/stage_bor_heimdall.go b/eth/stagedsync/stage_bor_heimdall.go index 1fb367156d5..02044314fb2 100644 --- a/eth/stagedsync/stage_bor_heimdall.go +++ b/eth/stagedsync/stage_bor_heimdall.go @@ -322,7 +322,10 @@ func BorHeimdallForward( var snap *bor.Snapshot if header != nil { - if cfg.blockReader.BorSnapshots().SegmentsMin() == 0 { + if blockNum > cfg.blockReader.BorSnapshots().SegmentsMin() { + // SegmentsMin is only set if running as an uploader process (check SnapshotsCfg.snapshotUploader and + // UploadLocationFlag) when we remove snapshots based on FrozenBlockLimit and number of uploaded snapshots + // avoid calling this if block for blockNums <= SegmentsMin to avoid reinsertion of snapshots snap = loadSnapshot(blockNum, header.Hash(), cfg.borConfig, recents, signatures, cfg.snapDb, logger) if snap == nil { From 36fefbbee1816b8ea58ccbe15668c92535d8c3c1 Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Tue, 9 Jan 2024 08:25:12 +0700 Subject: [PATCH 20/92] downloader: verify fixempty (#9161) --- cmd/downloader/main.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmd/downloader/main.go b/cmd/downloader/main.go index 18e7c0d6fa9..f7251501bde 100644 --- a/cmd/downloader/main.go +++ b/cmd/downloader/main.go @@ -229,7 +229,9 @@ func Downloader(ctx context.Context, logger log.Logger) error { } defer grpcServer.GracefulStop() - verifyFiles = strings.Split(_verifyFiles, ",") + if len(_verifyFiles) > 0 { + verifyFiles = strings.Split(_verifyFiles, ",") + } if verify || verifyFailfast || len(verifyFiles) > 0 { // remove and create .torrent files (will re-read all snapshots) if err = d.VerifyData(ctx, verifyFiles, verifyFailfast); err != nil { return err From b25d8cc8735e917ce4c9e609d751e3f540d6c2e5 Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Tue, 9 Jan 2024 08:25:27 +0700 Subject: [PATCH 21/92] disable TestGetValidatorsBalances: oom on CI (#9131) https://github.com/ledgerwatch/erigon/issues/9130 --- cl/beacon/handler/validators_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cl/beacon/handler/validators_test.go b/cl/beacon/handler/validators_test.go index 66e53990cc0..116b9155867 100644 --- a/cl/beacon/handler/validators_test.go +++ b/cl/beacon/handler/validators_test.go @@ -79,6 +79,7 @@ func TestGetAllValidators(t *testing.T) { } func TestGetValidatorsBalances(t *testing.T) { + t.Skip("FIXME: oom") // setupTestingHandler(t, clparams.Phase0Version) _, blocks, _, _, postState, handler, _, _, fcu := setupTestingHandler(t, clparams.Phase0Version) From 22f761593f395d5829b537783e2147d512116917 Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Tue, 9 Jan 2024 08:25:39 +0700 Subject: [PATCH 22/92] disable TestStateAntiquaryCapella because of oom on CI (#9129) https://github.com/ledgerwatch/erigon/issues/9128 From 459ccf8de45c62c5180d6e6cbb266422d0a9f3ca Mon Sep 17 00:00:00 2001 From: ledgerwatch Date: Tue, 9 Jan 2024 01:26:26 +0000 Subject: [PATCH 23/92] =?UTF-8?q?[E3]=20Some=20fixes=20for=20the=20in-memo?= =?UTF-8?q?ry=20database=20when=20working=20with=20Caplin=20(=E2=80=A6=20(?= =?UTF-8?q?#9164)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …testing on Sepolia) (#9151) --------- Co-authored-by: Alex Sharp --- cmd/integration/commands/stages.go | 7 +- cmd/integration/commands/state_stages.go | 27 +- core/state/rw_v3.go | 2 +- .../kv/membatchwithdb/memory_mutation.go | 175 +++++++- .../membatchwithdb/memory_mutation_cursor.go | 39 +- erigon-lib/wrap/e3_wrapper.go | 10 + eth/backend.go | 9 +- eth/stagedsync/default_stages.go | 387 +++++++++--------- eth/stagedsync/exec3.go | 4 +- eth/stagedsync/stage.go | 5 +- eth/stagedsync/stage_execute.go | 117 +++--- eth/stagedsync/stage_execute_test.go | 12 +- eth/stagedsync/stagebuilder.go | 59 +-- eth/stagedsync/stagedsynctest/harness.go | 3 +- eth/stagedsync/sync.go | 32 +- eth/stagedsync/sync_test.go | 172 ++++---- turbo/app/import_cmd.go | 3 +- .../engine_helpers/fork_validator.go | 23 +- turbo/execution/eth1/ethereum_execution.go | 3 +- turbo/execution/eth1/forkchoice.go | 5 +- turbo/execution/eth1/inserters.go | 13 +- turbo/jsonrpc/eth_subscribe_test.go | 3 +- turbo/jsonrpc/send_transaction_test.go | 3 +- turbo/stages/mock/mock_sentry.go | 11 +- turbo/stages/mock/sentry_mock_test.go | 17 +- turbo/stages/stageloop.go | 54 +-- 26 files changed, 723 insertions(+), 472 deletions(-) create mode 100644 erigon-lib/wrap/e3_wrapper.go diff --git a/cmd/integration/commands/stages.go b/cmd/integration/commands/stages.go index b084cc3a7f5..f8a824177ac 100644 --- a/cmd/integration/commands/stages.go +++ b/cmd/integration/commands/stages.go @@ -38,6 +38,8 @@ import ( "github.com/ledgerwatch/erigon-lib/kv/kvcfg" "github.com/ledgerwatch/erigon-lib/kv/rawdbv3" libstate "github.com/ledgerwatch/erigon-lib/state" + "github.com/ledgerwatch/erigon-lib/wrap" + "github.com/ledgerwatch/erigon/cmd/hack/tool/fromdb" "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/core" @@ -965,10 +967,11 @@ func stageExec(db kv.RwDB, ctx context.Context, logger log.Logger) error { } defer tx.Rollback() } + txc := wrap.TxContainer{Tx: tx} if unwind > 0 { u := sync.NewUnwindState(stages.Execution, s.BlockNumber-unwind, s.BlockNumber) - err := stagedsync.UnwindExecutionStage(u, s, tx, ctx, cfg, true, logger) + err := stagedsync.UnwindExecutionStage(u, s, txc, ctx, cfg, true, logger) if err != nil { return err } @@ -987,7 +990,7 @@ func stageExec(db kv.RwDB, ctx context.Context, logger log.Logger) error { return nil } - err := stagedsync.SpawnExecuteBlocksStage(s, sync, tx, block, ctx, cfg, true /* initialCycle */, logger) + err := stagedsync.SpawnExecuteBlocksStage(s, sync, txc, block, ctx, cfg, true /* initialCycle */, logger) if err != nil { return err } diff --git a/cmd/integration/commands/state_stages.go b/cmd/integration/commands/state_stages.go index 63733b5fc2f..ab9955dfca2 100644 --- a/cmd/integration/commands/state_stages.go +++ b/cmd/integration/commands/state_stages.go @@ -11,6 +11,7 @@ import ( "time" "github.com/ledgerwatch/erigon-lib/kv/dbutils" + "github.com/ledgerwatch/erigon-lib/wrap" "github.com/c2h5oh/datasize" chain2 "github.com/ledgerwatch/erigon-lib/chain" @@ -228,9 +229,9 @@ func syncBySmallSteps(db kv.RwDB, miningConfig params.MiningConfig, ctx context. execCfg := stagedsync.StageExecuteBlocksCfg(db, pm, batchSize, changeSetHook, chainConfig, engine, vmConfig, changesAcc, false, false, historyV3, dirs, br, nil, genesis, syncCfg, agg, nil) - execUntilFunc := func(execToBlock uint64) func(firstCycle bool, badBlockUnwind bool, stageState *stagedsync.StageState, unwinder stagedsync.Unwinder, tx kv.RwTx, logger log.Logger) error { - return func(firstCycle bool, badBlockUnwind bool, s *stagedsync.StageState, unwinder stagedsync.Unwinder, tx kv.RwTx, logger log.Logger) error { - if err := stagedsync.SpawnExecuteBlocksStage(s, unwinder, tx, execToBlock, ctx, execCfg, firstCycle, logger); err != nil { + execUntilFunc := func(execToBlock uint64) func(firstCycle bool, badBlockUnwind bool, stageState *stagedsync.StageState, unwinder stagedsync.Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return func(firstCycle bool, badBlockUnwind bool, s *stagedsync.StageState, unwinder stagedsync.Unwinder, txc wrap.TxContainer, logger log.Logger) error { + if err := stagedsync.SpawnExecuteBlocksStage(s, unwinder, txc, execToBlock, ctx, execCfg, firstCycle, logger); err != nil { return fmt.Errorf("spawnExecuteBlocksStage: %w", err) } return nil @@ -317,7 +318,7 @@ func syncBySmallSteps(db kv.RwDB, miningConfig params.MiningConfig, ctx context. stateStages.MockExecFunc(stages.Execution, execUntilFunc(execToBlock)) _ = stateStages.SetCurrentStage(stages.Execution) - if _, err := stateStages.Run(db, tx, false /* firstCycle */); err != nil { + if _, err := stateStages.Run(db, wrap.TxContainer{Tx: tx}, false /* firstCycle */); err != nil { return err } @@ -352,8 +353,8 @@ func syncBySmallSteps(db kv.RwDB, miningConfig params.MiningConfig, ctx context. if miner.MiningConfig.Enabled && nextBlock != nil && nextBlock.Coinbase() != (common2.Address{}) { miner.MiningConfig.Etherbase = nextBlock.Coinbase() miner.MiningConfig.ExtraData = nextBlock.Extra() - miningStages.MockExecFunc(stages.MiningCreateBlock, func(firstCycle bool, badBlockUnwind bool, s *stagedsync.StageState, u stagedsync.Unwinder, tx kv.RwTx, logger log.Logger) error { - err = stagedsync.SpawnMiningCreateBlockStage(s, tx, + miningStages.MockExecFunc(stages.MiningCreateBlock, func(firstCycle bool, badBlockUnwind bool, s *stagedsync.StageState, u stagedsync.Unwinder, txc wrap.TxContainer, logger log.Logger) error { + err = stagedsync.SpawnMiningCreateBlockStage(s, txc.Tx, stagedsync.StageMiningCreateBlockCfg(db, miner, *chainConfig, engine, nil, nil, dirs.Tmp, br), quit, logger) if err != nil { @@ -375,7 +376,7 @@ func syncBySmallSteps(db kv.RwDB, miningConfig params.MiningConfig, ctx context. //}) _ = miningStages.SetCurrentStage(stages.MiningCreateBlock) - if _, err := miningStages.Run(db, tx, false /* firstCycle */); err != nil { + if _, err := miningStages.Run(db, wrap.TxContainer{Tx: tx}, false /* firstCycle */); err != nil { return err } tx.Rollback() @@ -468,7 +469,7 @@ func loopIh(db kv.RwDB, ctx context.Context, unwind uint64, logger log.Logger) e } defer tx.Rollback() sync.DisableStages(stages.Snapshots, stages.Headers, stages.BlockHashes, stages.Bodies, stages.Senders, stages.Execution, stages.AccountHistoryIndex, stages.StorageHistoryIndex, stages.TxLookup, stages.Finish) - if _, err = sync.Run(db, tx, false /* firstCycle */); err != nil { + if _, err = sync.Run(db, wrap.TxContainer{Tx: tx}, false /* firstCycle */); err != nil { return err } execStage := stage(sync, tx, nil, stages.HashState) @@ -492,7 +493,7 @@ func loopIh(db kv.RwDB, ctx context.Context, unwind uint64, logger log.Logger) e sync.DisableStages(stages.IntermediateHashes) _ = sync.SetCurrentStage(stages.HashState) - if _, err = sync.Run(db, tx, false /* firstCycle */); err != nil { + if _, err = sync.Run(db, wrap.TxContainer{Tx: tx}, false /* firstCycle */); err != nil { return err } must(tx.Commit()) @@ -512,7 +513,7 @@ func loopIh(db kv.RwDB, ctx context.Context, unwind uint64, logger log.Logger) e _ = sync.SetCurrentStage(stages.IntermediateHashes) t := time.Now() - if _, err = sync.Run(db, tx, false /* firstCycle */); err != nil { + if _, err = sync.Run(db, wrap.TxContainer{Tx: tx}, false /* firstCycle */); err != nil { return err } logger.Warn("loop", "time", time.Since(t).String()) @@ -567,8 +568,8 @@ func loopExec(db kv.RwDB, ctx context.Context, unwind uint64, logger log.Logger) /*badBlockHalt=*/ false, historyV3, dirs, br, nil, genesis, syncCfg, agg, nil) // set block limit of execute stage - sync.MockExecFunc(stages.Execution, func(firstCycle bool, badBlockUnwind bool, stageState *stagedsync.StageState, unwinder stagedsync.Unwinder, tx kv.RwTx, logger log.Logger) error { - if err = stagedsync.SpawnExecuteBlocksStage(stageState, sync, tx, to, ctx, cfg, initialCycle, logger); err != nil { + sync.MockExecFunc(stages.Execution, func(firstCycle bool, badBlockUnwind bool, stageState *stagedsync.StageState, unwinder stagedsync.Unwinder, txc wrap.TxContainer, logger log.Logger) error { + if err = stagedsync.SpawnExecuteBlocksStage(stageState, sync, txc, to, ctx, cfg, initialCycle, logger); err != nil { return fmt.Errorf("spawnExecuteBlocksStage: %w", err) } return nil @@ -583,7 +584,7 @@ func loopExec(db kv.RwDB, ctx context.Context, unwind uint64, logger log.Logger) _ = sync.SetCurrentStage(stages.Execution) t := time.Now() - if _, err = sync.Run(db, tx, initialCycle); err != nil { + if _, err = sync.Run(db, wrap.TxContainer{Tx: tx}, initialCycle); err != nil { return err } logger.Info("[Integration] ", "loop time", time.Since(t)) diff --git a/core/state/rw_v3.go b/core/state/rw_v3.go index 6ed8f08400c..b8bb03c664e 100644 --- a/core/state/rw_v3.go +++ b/core/state/rw_v3.go @@ -521,7 +521,7 @@ func recoverCodeHashPlain(acc *accounts.Account, db kv.Tx, key []byte) { } } -func (rs *StateV3) Unwind(ctx context.Context, tx kv.RwTx, txUnwindTo uint64, agg *libstate.AggregatorV3, accumulator *shards.Accumulator) error { +func (rs *StateV3) Unwind(ctx context.Context, tx kv.RwTx, blockUnwindTo, txUnwindTo uint64, agg *libstate.AggregatorV3, accumulator *shards.Accumulator) error { agg.SetTx(tx) var currentInc uint64 handle := func(k, v []byte, table etl.CurrentTableReader, next etl.LoadNextFunc) error { diff --git a/erigon-lib/kv/membatchwithdb/memory_mutation.go b/erigon-lib/kv/membatchwithdb/memory_mutation.go index 9e53fec72d7..173e44b232a 100644 --- a/erigon-lib/kv/membatchwithdb/memory_mutation.go +++ b/erigon-lib/kv/membatchwithdb/memory_mutation.go @@ -32,6 +32,7 @@ type MemoryMutation struct { memTx kv.RwTx memDb kv.RwDB deletedEntries map[string]map[string]struct{} + deletedDups map[string]map[string]map[string]struct{} clearedTables map[string]struct{} db kv.Tx statelessCursors map[string]kv.RwCursor @@ -60,6 +61,7 @@ func NewMemoryBatch(tx kv.Tx, tmpDir string, logger log.Logger) *MemoryMutation memDb: tmpDB, memTx: memTx, deletedEntries: make(map[string]map[string]struct{}), + deletedDups: map[string]map[string]map[string]struct{}{}, clearedTables: make(map[string]struct{}), } } @@ -70,6 +72,7 @@ func NewMemoryBatchWithCustomDB(tx kv.Tx, db kv.RwDB, uTx kv.RwTx, tmpDir string memDb: db, memTx: uTx, deletedEntries: make(map[string]map[string]struct{}), + deletedDups: map[string]map[string]map[string]struct{}{}, clearedTables: make(map[string]struct{}), } } @@ -93,6 +96,19 @@ func (m *MemoryMutation) isEntryDeleted(table string, key []byte) bool { return ok } +func (m *MemoryMutation) isDupDeleted(table string, key []byte, val []byte) bool { + t, ok := m.deletedDups[table] + if !ok { + return ok + } + k, ok := t[string(key)] + if !ok { + return ok + } + _, ok = k[string(val)] + return ok +} + func (m *MemoryMutation) DBSize() (uint64, error) { panic("not implemented") } @@ -243,10 +259,141 @@ func (m *MemoryMutation) RangeAscend(table string, fromPrefix, toPrefix []byte, panic("please implement me") } func (m *MemoryMutation) RangeDescend(table string, fromPrefix, toPrefix []byte, limit int) (iter.KV, error) { - panic("please implement me") + s := &rangeIter{orderAscend: false, limit: int64(limit)} + var err error + if s.iterDb, err = m.db.RangeDescend(table, fromPrefix, toPrefix, limit); err != nil { + return s, err + } + if s.iterMem, err = m.memTx.RangeDescend(table, fromPrefix, toPrefix, limit); err != nil { + return s, err + } + return s.init() +} + +type rangeIter struct { + iterDb, iterMem iter.KV + hasNextDb, hasNextMem bool + nextKdb, nextVdb, nextKmem, nextVmem []byte + orderAscend bool + limit int64 +} + +func (s *rangeIter) init() (*rangeIter, error) { + s.hasNextDb = s.iterDb.HasNext() + s.hasNextMem = s.iterMem.HasNext() + var err error + if s.hasNextDb { + if s.nextKdb, s.nextVdb, err = s.iterDb.Next(); err != nil { + return s, err + } + } + if s.hasNextMem { + if s.nextKmem, s.nextVmem, err = s.iterMem.Next(); err != nil { + return s, err + } + } + return s, nil +} + +func (s *rangeIter) HasNext() bool { + if s.limit == 0 { + return false + } + return s.hasNextDb || s.hasNextMem +} +func (s *rangeIter) Next() (k, v []byte, err error) { + s.limit-- + c := bytes.Compare(s.nextKdb, s.nextKmem) + if !s.hasNextMem || c == -1 && s.orderAscend || c == 1 && !s.orderAscend || c == 0 { + if s.hasNextDb { + k = s.nextKdb + v = s.nextVdb + s.hasNextDb = s.iterDb.HasNext() + if s.nextKdb, s.nextVdb, err = s.iterDb.Next(); err != nil { + return nil, nil, err + } + } + } + if !s.hasNextDb || c == 1 && s.orderAscend || c == -1 && !s.orderAscend || c == 0 { + if s.hasNextMem { + k = s.nextKmem + v = s.nextVmem + s.hasNextMem = s.iterMem.HasNext() + if s.nextKmem, s.nextVmem, err = s.iterMem.Next(); err != nil { + return nil, nil, err + } + } + } + return } + func (m *MemoryMutation) RangeDupSort(table string, key []byte, fromPrefix, toPrefix []byte, asc order.By, limit int) (iter.KV, error) { - panic("please implement me") + s := &rangeDupSortIter{key: key, orderAscend: bool(asc), limit: int64(limit)} + var err error + if s.iterDb, err = m.db.RangeDupSort(table, key, fromPrefix, toPrefix, asc, limit); err != nil { + return s, err + } + if s.iterMem, err = m.memTx.RangeDupSort(table, key, fromPrefix, toPrefix, asc, limit); err != nil { + return s, err + } + return s.init() +} + +type rangeDupSortIter struct { + iterDb, iterMem iter.KV + hasNextDb, hasNextMem bool + key []byte + nextVdb, nextVmem []byte + orderAscend bool + limit int64 +} + +func (s *rangeDupSortIter) init() (*rangeDupSortIter, error) { + s.hasNextDb = s.iterDb.HasNext() + s.hasNextMem = s.iterMem.HasNext() + var err error + if s.hasNextDb { + if _, s.nextVdb, err = s.iterDb.Next(); err != nil { + return s, err + } + } + if s.hasNextMem { + if _, s.nextVmem, err = s.iterMem.Next(); err != nil { + return s, err + } + } + return s, nil +} + +func (s *rangeDupSortIter) HasNext() bool { + if s.limit == 0 { + return false + } + return s.hasNextDb || s.hasNextMem +} +func (s *rangeDupSortIter) Next() (k, v []byte, err error) { + s.limit-- + k = s.key + c := bytes.Compare(s.nextVdb, s.nextVmem) + if !s.hasNextMem || c == -1 && s.orderAscend || c == 1 && !s.orderAscend || c == 0 { + if s.hasNextDb { + v = s.nextVdb + s.hasNextDb = s.iterDb.HasNext() + if _, s.nextVdb, err = s.iterDb.Next(); err != nil { + return nil, nil, err + } + } + } + if !s.hasNextDb || c == 1 && s.orderAscend || c == -1 && !s.orderAscend || c == 0 { + if s.hasNextMem { + v = s.nextVmem + s.hasNextMem = s.iterMem.HasNext() + if _, s.nextVmem, err = s.iterMem.Next(); err != nil { + return nil, nil, err + } + } + } + return } func (m *MemoryMutation) ForPrefix(bucket string, prefix []byte, walker func(k, v []byte) error) error { @@ -271,13 +418,29 @@ func (m *MemoryMutation) ForPrefix(bucket string, prefix []byte, walker func(k, } func (m *MemoryMutation) Delete(table string, k []byte) error { - if _, ok := m.deletedEntries[table]; !ok { - m.deletedEntries[table] = make(map[string]struct{}) + t, ok := m.deletedEntries[table] + if !ok { + t = make(map[string]struct{}) + m.deletedEntries[table] = t } - m.deletedEntries[table][string(k)] = struct{}{} + t[string(k)] = struct{}{} return m.memTx.Delete(table, k) } +func (m *MemoryMutation) deleteDup(table string, k, v []byte) { + t, ok := m.deletedDups[table] + if !ok { + t = map[string]map[string]struct{}{} + m.deletedDups[table] = t + } + km, ok := t[string(k)] + if !ok { + km = map[string]struct{}{} + t[string(k)] = km + } + km[string(v)] = struct{}{} +} + func (m *MemoryMutation) Commit() error { m.statelessCursors = nil return nil @@ -467,7 +630,7 @@ func (m *MemoryMutation) MemTx() kv.RwTx { // Cursor creates a new cursor (the real fun begins here) func (m *MemoryMutation) makeCursor(bucket string) (kv.RwCursorDupSort, error) { - c := &memoryMutationCursor{} + c := &memoryMutationCursor{pureDupSort: isTablePurelyDupsort(bucket)} // We can filter duplicates in dup sorted table c.table = bucket diff --git a/erigon-lib/kv/membatchwithdb/memory_mutation_cursor.go b/erigon-lib/kv/membatchwithdb/memory_mutation_cursor.go index c21b9e4015b..0fefa48dac3 100644 --- a/erigon-lib/kv/membatchwithdb/memory_mutation_cursor.go +++ b/erigon-lib/kv/membatchwithdb/memory_mutation_cursor.go @@ -47,6 +47,7 @@ type memoryMutationCursor struct { currentDbEntry cursorEntry currentMemEntry cursorEntry isPrevFromDb bool + pureDupSort bool } func (m *memoryMutationCursor) isTableCleared() bool { @@ -337,8 +338,13 @@ func (m *memoryMutationCursor) Delete(k []byte) error { } func (m *memoryMutationCursor) DeleteCurrent() error { - panic("DeleteCurrent Not implemented") + if !m.pureDupSort { + return m.mutation.Delete(m.table, m.currentPair.key) + } + m.mutation.deleteDup(m.table, m.currentPair.key, m.currentPair.value) + return nil } + func (m *memoryMutationCursor) DeleteExact(_, _ []byte) error { panic("DeleteExact Not implemented") } @@ -502,5 +508,34 @@ func (m *memoryMutationCursor) CountDuplicates() (uint64, error) { } func (m *memoryMutationCursor) SeekBothExact(key, value []byte) ([]byte, []byte, error) { - panic("SeekBothExact Not implemented") + memKey, memValue, err := m.memCursor.SeekBothExact(key, value) + if err != nil || m.isTableCleared() { + return memKey, memValue, err + } + + if memKey != nil { + m.currentMemEntry.key = memKey + m.currentMemEntry.value = memValue + m.currentDbEntry.key = key + m.currentDbEntry.value, err = m.cursor.SeekBothRange(key, value) + m.isPrevFromDb = false + m.currentPair = cursorEntry{memKey, memValue} + return memKey, memValue, err + } + + dbKey, dbValue, err := m.cursor.SeekBothExact(key, value) + if err != nil { + return nil, nil, err + } + + if dbKey != nil && !m.mutation.isDupDeleted(m.table, key, value) { + m.currentDbEntry.key = dbKey + m.currentDbEntry.value = dbValue + m.currentMemEntry.key = key + m.currentMemEntry.value, err = m.memCursor.SeekBothRange(key, value) + m.isPrevFromDb = true + m.currentPair = cursorEntry{dbKey, dbValue} + return dbKey, dbValue, err + } + return nil, nil, nil } diff --git a/erigon-lib/wrap/e3_wrapper.go b/erigon-lib/wrap/e3_wrapper.go new file mode 100644 index 00000000000..71f7f0e5f16 --- /dev/null +++ b/erigon-lib/wrap/e3_wrapper.go @@ -0,0 +1,10 @@ +package wrap + +import ( + "github.com/ledgerwatch/erigon-lib/kv" +) + +type TxContainer struct { + Tx kv.RwTx + Ttx kv.TemporalTx +} diff --git a/eth/backend.go b/eth/backend.go index 04436895754..bfc1fce3dad 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -38,6 +38,7 @@ import ( "github.com/ledgerwatch/erigon-lib/diagnostics" "github.com/ledgerwatch/erigon-lib/downloader/downloadergrpc" "github.com/ledgerwatch/erigon-lib/kv/kvcfg" + "github.com/ledgerwatch/erigon-lib/wrap" "github.com/ledgerwatch/erigon/cl/clparams" "github.com/ledgerwatch/erigon/cl/cltypes" "github.com/ledgerwatch/erigon/cl/fork" @@ -529,20 +530,20 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger backend.engine = ethconsensusconfig.CreateConsensusEngine(ctx, stack.Config(), chainConfig, consensusConfig, config.Miner.Notify, config.Miner.Noverify, heimdallClient, config.WithoutHeimdall, blockReader, false /* readonly */, logger) - inMemoryExecution := func(batch kv.RwTx, header *types.Header, body *types.RawBody, unwindPoint uint64, headersChain []*types.Header, bodiesChain []*types.RawBody, + inMemoryExecution := func(txc wrap.TxContainer, header *types.Header, body *types.RawBody, unwindPoint uint64, headersChain []*types.Header, bodiesChain []*types.RawBody, notifications *shards.Notifications) error { terseLogger := log.New() terseLogger.SetHandler(log.LvlFilterHandler(log.LvlWarn, log.StderrHandler)) // Needs its own notifications to not update RPC daemon and txpool about pending blocks stateSync := stages2.NewInMemoryExecution(backend.sentryCtx, backend.chainDB, config, backend.sentriesClient, dirs, notifications, blockReader, blockWriter, backend.agg, backend.silkworm, terseLogger) - chainReader := stagedsync.NewChainReaderImpl(chainConfig, batch, blockReader, logger) + chainReader := stagedsync.NewChainReaderImpl(chainConfig, txc.Tx, blockReader, logger) // We start the mining step - if err := stages2.StateStep(ctx, chainReader, backend.engine, batch, backend.blockWriter, stateSync, backend.sentriesClient.Bd, header, body, unwindPoint, headersChain, bodiesChain, config.HistoryV3); err != nil { + if err := stages2.StateStep(ctx, chainReader, backend.engine, txc, backend.blockWriter, stateSync, backend.sentriesClient.Bd, header, body, unwindPoint, headersChain, bodiesChain, config.HistoryV3); err != nil { logger.Warn("Could not validate block", "err", err) return err } - progress, err := stages.GetStageProgress(batch, stages.IntermediateHashes) + progress, err := stages.GetStageProgress(txc.Tx, stages.IntermediateHashes) if err != nil { return err } diff --git a/eth/stagedsync/default_stages.go b/eth/stagedsync/default_stages.go index a882729abdc..d24c39ea97f 100644 --- a/eth/stagedsync/default_stages.go +++ b/eth/stagedsync/default_stages.go @@ -5,6 +5,7 @@ import ( "github.com/ledgerwatch/erigon-lib/common/dbg" "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon-lib/wrap" "github.com/ledgerwatch/erigon/eth/ethconfig" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" "github.com/ledgerwatch/log/v3" @@ -30,13 +31,13 @@ func DefaultStages(ctx context.Context, { ID: stages.Snapshots, Description: "Download snapshots", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { if badBlockUnwind { return nil } - return SpawnStageSnapshots(s, ctx, tx, snapshots, firstCycle, logger) + return SpawnStageSnapshots(s, ctx, txc.Tx, snapshots, firstCycle, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { return nil }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { @@ -46,14 +47,14 @@ func DefaultStages(ctx context.Context, { ID: stages.Headers, Description: "Download headers", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { if badBlockUnwind { return nil } - return SpawnStageHeaders(s, u, ctx, tx, headers, firstCycle, test, logger) + return SpawnStageHeaders(s, u, ctx, txc.Tx, headers, firstCycle, test, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return HeadersUnwind(u, s, tx, headers, test) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return HeadersUnwind(u, s, txc.Tx, headers, test) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return nil @@ -62,14 +63,14 @@ func DefaultStages(ctx context.Context, { ID: stages.BorHeimdall, Description: "Download Bor-specific data from Heimdall", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { if badBlockUnwind { return nil } - return BorHeimdallForward(s, u, ctx, tx, borHeimdallCfg, false, logger) + return BorHeimdallForward(s, u, ctx, txc.Tx, borHeimdallCfg, false, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return BorHeimdallUnwind(u, ctx, s, tx, borHeimdallCfg) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return BorHeimdallUnwind(u, ctx, s, txc.Tx, borHeimdallCfg) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return BorHeimdallPrune(p, ctx, tx, borHeimdallCfg) @@ -78,11 +79,11 @@ func DefaultStages(ctx context.Context, { ID: stages.BlockHashes, Description: "Write block hashes", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnBlockHashStage(s, tx, blockHashCfg, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnBlockHashStage(s, txc.Tx, blockHashCfg, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindBlockHashStage(u, tx, blockHashCfg, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindBlockHashStage(u, txc.Tx, blockHashCfg, ctx) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneBlockHashStage(p, tx, blockHashCfg, ctx) @@ -91,11 +92,11 @@ func DefaultStages(ctx context.Context, { ID: stages.Bodies, Description: "Download block bodies", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return BodiesForward(s, u, ctx, tx, bodies, test, firstCycle, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return BodiesForward(s, u, ctx, txc.Tx, bodies, test, firstCycle, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindBodiesStage(u, tx, bodies, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindBodiesStage(u, txc.Tx, bodies, ctx) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return nil @@ -104,11 +105,11 @@ func DefaultStages(ctx context.Context, { ID: stages.Senders, Description: "Recover senders from tx signatures", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnRecoverSendersStage(senders, s, u, tx, 0, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnRecoverSendersStage(senders, s, u, txc.Tx, 0, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindSendersStage(u, tx, senders, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindSendersStage(u, txc.Tx, senders, ctx) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneSendersStage(p, tx, senders, ctx) @@ -118,11 +119,11 @@ func DefaultStages(ctx context.Context, ID: stages.Execution, Description: "Execute blocks w/o hash checks", Disabled: dbg.StagesOnlyBlocks, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnExecuteBlocksStage(s, u, tx, 0, ctx, exec, firstCycle, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnExecuteBlocksStage(s, u, txc, 0, ctx, exec, firstCycle, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindExecutionStage(u, s, tx, ctx, exec, firstCycle, logger) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindExecutionStage(u, s, txc, ctx, exec, firstCycle, logger) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneExecutionStage(p, tx, exec, ctx, firstCycle) @@ -132,11 +133,11 @@ func DefaultStages(ctx context.Context, ID: stages.HashState, Description: "Hash the key in the state", Disabled: bodies.historyV3 || ethconfig.EnableHistoryV4InTest || dbg.StagesOnlyBlocks, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnHashStateStage(s, tx, hashState, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnHashStateStage(s, txc.Tx, hashState, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindHashStateStage(u, s, tx, hashState, ctx, logger) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindHashStateStage(u, s, txc.Tx, hashState, ctx, logger) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneHashStateStage(p, tx, hashState, ctx) @@ -146,19 +147,19 @@ func DefaultStages(ctx context.Context, ID: stages.IntermediateHashes, Description: "Generate intermediate hashes and computing state root", Disabled: bodies.historyV3 || ethconfig.EnableHistoryV4InTest || dbg.StagesOnlyBlocks, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { if exec.chainConfig.IsPrague(0) { - _, err := SpawnVerkleTrie(s, u, tx, trieCfg, ctx, logger) + _, err := SpawnVerkleTrie(s, u, txc.Tx, trieCfg, ctx, logger) return err } - _, err := SpawnIntermediateHashesStage(s, u, tx, trieCfg, ctx, logger) + _, err := SpawnIntermediateHashesStage(s, u, txc.Tx, trieCfg, ctx, logger) return err }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { if exec.chainConfig.IsPrague(0) { - return UnwindVerkleTrie(u, s, tx, trieCfg, ctx, logger) + return UnwindVerkleTrie(u, s, txc.Tx, trieCfg, ctx, logger) } - return UnwindIntermediateHashesStage(u, s, tx, trieCfg, ctx, logger) + return UnwindIntermediateHashesStage(u, s, txc.Tx, trieCfg, ctx, logger) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneIntermediateHashesStage(p, tx, trieCfg, ctx) @@ -169,11 +170,11 @@ func DefaultStages(ctx context.Context, Description: "Generate call traces index", DisabledDescription: "Work In Progress", Disabled: bodies.historyV3 || dbg.StagesOnlyBlocks, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnCallTraces(s, tx, callTraces, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnCallTraces(s, txc.Tx, callTraces, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindCallTraces(u, s, tx, callTraces, ctx, logger) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindCallTraces(u, s, txc.Tx, callTraces, ctx, logger) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneCallTraces(p, tx, callTraces, ctx, logger) @@ -183,11 +184,11 @@ func DefaultStages(ctx context.Context, ID: stages.AccountHistoryIndex, Description: "Generate account history index", Disabled: bodies.historyV3 || dbg.StagesOnlyBlocks, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnAccountHistoryIndex(s, tx, history, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnAccountHistoryIndex(s, txc.Tx, history, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindAccountHistoryIndex(u, s, tx, history, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindAccountHistoryIndex(u, s, txc.Tx, history, ctx) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneAccountHistoryIndex(p, tx, history, ctx, logger) @@ -197,11 +198,11 @@ func DefaultStages(ctx context.Context, ID: stages.StorageHistoryIndex, Description: "Generate storage history index", Disabled: bodies.historyV3 || dbg.StagesOnlyBlocks, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnStorageHistoryIndex(s, tx, history, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnStorageHistoryIndex(s, txc.Tx, history, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindStorageHistoryIndex(u, s, tx, history, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindStorageHistoryIndex(u, s, txc.Tx, history, ctx) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneStorageHistoryIndex(p, tx, history, ctx, logger) @@ -211,11 +212,11 @@ func DefaultStages(ctx context.Context, ID: stages.LogIndex, Description: "Generate receipt logs index", Disabled: bodies.historyV3 || dbg.StagesOnlyBlocks, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnLogIndex(s, tx, logIndex, ctx, 0, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnLogIndex(s, txc.Tx, logIndex, ctx, 0, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindLogIndex(u, s, tx, logIndex, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindLogIndex(u, s, txc.Tx, logIndex, ctx) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneLogIndex(p, tx, logIndex, ctx, logger) @@ -225,11 +226,11 @@ func DefaultStages(ctx context.Context, ID: stages.TxLookup, Description: "Generate tx lookup index", Disabled: dbg.StagesOnlyBlocks, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnTxLookup(s, tx, 0 /* toBlock */, txLookup, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnTxLookup(s, txc.Tx, 0 /* toBlock */, txLookup, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindTxLookup(u, s, tx, txLookup, ctx, logger) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindTxLookup(u, s, txc.Tx, txLookup, ctx, logger) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneTxLookup(p, tx, txLookup, ctx, firstCycle, logger) @@ -238,11 +239,11 @@ func DefaultStages(ctx context.Context, { ID: stages.Finish, Description: "Final: update current block for the RPC API", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, _ Unwinder, tx kv.RwTx, logger log.Logger) error { - return FinishForward(s, tx, finish, firstCycle) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, _ Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return FinishForward(s, txc.Tx, finish, firstCycle) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindFinish(u, tx, finish, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindFinish(u, txc.Tx, finish, ctx) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneFinish(p, tx, finish, ctx) @@ -256,13 +257,13 @@ func PipelineStages(ctx context.Context, snapshots SnapshotsCfg, blockHashCfg Bl { ID: stages.Snapshots, Description: "Download snapshots", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { if badBlockUnwind { return nil } - return SpawnStageSnapshots(s, ctx, tx, snapshots, firstCycle, logger) + return SpawnStageSnapshots(s, ctx, txc.Tx, snapshots, firstCycle, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { return nil }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { @@ -272,11 +273,11 @@ func PipelineStages(ctx context.Context, snapshots SnapshotsCfg, blockHashCfg Bl { ID: stages.BlockHashes, Description: "Write block hashes", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnBlockHashStage(s, tx, blockHashCfg, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnBlockHashStage(s, txc.Tx, blockHashCfg, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindBlockHashStage(u, tx, blockHashCfg, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindBlockHashStage(u, txc.Tx, blockHashCfg, ctx) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneBlockHashStage(p, tx, blockHashCfg, ctx) @@ -285,11 +286,11 @@ func PipelineStages(ctx context.Context, snapshots SnapshotsCfg, blockHashCfg Bl { ID: stages.Senders, Description: "Recover senders from tx signatures", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnRecoverSendersStage(senders, s, u, tx, 0, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnRecoverSendersStage(senders, s, u, txc.Tx, 0, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindSendersStage(u, tx, senders, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindSendersStage(u, txc.Tx, senders, ctx) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneSendersStage(p, tx, senders, ctx) @@ -298,11 +299,11 @@ func PipelineStages(ctx context.Context, snapshots SnapshotsCfg, blockHashCfg Bl { ID: stages.Execution, Description: "Execute blocks w/o hash checks", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnExecuteBlocksStage(s, u, tx, 0, ctx, exec, firstCycle, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnExecuteBlocksStage(s, u, txc, 0, ctx, exec, firstCycle, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindExecutionStage(u, s, tx, ctx, exec, firstCycle, logger) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindExecutionStage(u, s, txc, ctx, exec, firstCycle, logger) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneExecutionStage(p, tx, exec, ctx, firstCycle) @@ -312,11 +313,11 @@ func PipelineStages(ctx context.Context, snapshots SnapshotsCfg, blockHashCfg Bl ID: stages.HashState, Description: "Hash the key in the state", Disabled: exec.historyV3 && ethconfig.EnableHistoryV4InTest, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnHashStateStage(s, tx, hashState, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnHashStateStage(s, txc.Tx, hashState, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindHashStateStage(u, s, tx, hashState, ctx, logger) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindHashStateStage(u, s, txc.Tx, hashState, ctx, logger) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneHashStateStage(p, tx, hashState, ctx) @@ -326,19 +327,19 @@ func PipelineStages(ctx context.Context, snapshots SnapshotsCfg, blockHashCfg Bl ID: stages.IntermediateHashes, Description: "Generate intermediate hashes and computing state root", Disabled: exec.historyV3 && ethconfig.EnableHistoryV4InTest, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { if exec.chainConfig.IsPrague(0) { - _, err := SpawnVerkleTrie(s, u, tx, trieCfg, ctx, logger) + _, err := SpawnVerkleTrie(s, u, txc.Tx, trieCfg, ctx, logger) return err } - _, err := SpawnIntermediateHashesStage(s, u, tx, trieCfg, ctx, logger) + _, err := SpawnIntermediateHashesStage(s, u, txc.Tx, trieCfg, ctx, logger) return err }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { if exec.chainConfig.IsPrague(0) { - return UnwindVerkleTrie(u, s, tx, trieCfg, ctx, logger) + return UnwindVerkleTrie(u, s, txc.Tx, trieCfg, ctx, logger) } - return UnwindIntermediateHashesStage(u, s, tx, trieCfg, ctx, logger) + return UnwindIntermediateHashesStage(u, s, txc.Tx, trieCfg, ctx, logger) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneIntermediateHashesStage(p, tx, trieCfg, ctx) @@ -349,11 +350,11 @@ func PipelineStages(ctx context.Context, snapshots SnapshotsCfg, blockHashCfg Bl Description: "Generate call traces index", DisabledDescription: "Work In Progress", Disabled: exec.historyV3, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnCallTraces(s, tx, callTraces, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnCallTraces(s, txc.Tx, callTraces, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindCallTraces(u, s, tx, callTraces, ctx, logger) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindCallTraces(u, s, txc.Tx, callTraces, ctx, logger) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneCallTraces(p, tx, callTraces, ctx, logger) @@ -363,11 +364,11 @@ func PipelineStages(ctx context.Context, snapshots SnapshotsCfg, blockHashCfg Bl ID: stages.AccountHistoryIndex, Description: "Generate account history index", Disabled: exec.historyV3, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnAccountHistoryIndex(s, tx, history, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnAccountHistoryIndex(s, txc.Tx, history, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindAccountHistoryIndex(u, s, tx, history, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindAccountHistoryIndex(u, s, txc.Tx, history, ctx) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneAccountHistoryIndex(p, tx, history, ctx, logger) @@ -377,11 +378,11 @@ func PipelineStages(ctx context.Context, snapshots SnapshotsCfg, blockHashCfg Bl ID: stages.StorageHistoryIndex, Description: "Generate storage history index", Disabled: exec.historyV3, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnStorageHistoryIndex(s, tx, history, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnStorageHistoryIndex(s, txc.Tx, history, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindStorageHistoryIndex(u, s, tx, history, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindStorageHistoryIndex(u, s, txc.Tx, history, ctx) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneStorageHistoryIndex(p, tx, history, ctx, logger) @@ -391,11 +392,11 @@ func PipelineStages(ctx context.Context, snapshots SnapshotsCfg, blockHashCfg Bl ID: stages.LogIndex, Description: "Generate receipt logs index", Disabled: exec.historyV3, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnLogIndex(s, tx, logIndex, ctx, 0, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnLogIndex(s, txc.Tx, logIndex, ctx, 0, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindLogIndex(u, s, tx, logIndex, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindLogIndex(u, s, txc.Tx, logIndex, ctx) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneLogIndex(p, tx, logIndex, ctx, logger) @@ -404,11 +405,11 @@ func PipelineStages(ctx context.Context, snapshots SnapshotsCfg, blockHashCfg Bl { ID: stages.TxLookup, Description: "Generate tx lookup index", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnTxLookup(s, tx, 0 /* toBlock */, txLookup, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnTxLookup(s, txc.Tx, 0 /* toBlock */, txLookup, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindTxLookup(u, s, tx, txLookup, ctx, logger) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindTxLookup(u, s, txc.Tx, txLookup, ctx, logger) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneTxLookup(p, tx, txLookup, ctx, firstCycle, logger) @@ -417,11 +418,11 @@ func PipelineStages(ctx context.Context, snapshots SnapshotsCfg, blockHashCfg Bl { ID: stages.Finish, Description: "Final: update current block for the RPC API", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, _ Unwinder, tx kv.RwTx, logger log.Logger) error { - return FinishForward(s, tx, finish, firstCycle) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, _ Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return FinishForward(s, txc.Tx, finish, firstCycle) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindFinish(u, tx, finish, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindFinish(u, txc.Tx, finish, ctx) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneFinish(p, tx, finish, ctx) @@ -436,13 +437,13 @@ func UploaderPipelineStages(ctx context.Context, snapshots SnapshotsCfg, headers { ID: stages.Snapshots, Description: "Download snapshots", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { if badBlockUnwind { return nil } - return SpawnStageSnapshots(s, ctx, tx, snapshots, firstCycle, logger) + return SpawnStageSnapshots(s, ctx, txc.Tx, snapshots, firstCycle, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { return nil }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { @@ -452,14 +453,14 @@ func UploaderPipelineStages(ctx context.Context, snapshots SnapshotsCfg, headers { ID: stages.Headers, Description: "Download headers", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { if badBlockUnwind { return nil } - return SpawnStageHeaders(s, u, ctx, tx, headers, firstCycle, test, logger) + return SpawnStageHeaders(s, u, ctx, txc.Tx, headers, firstCycle, test, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return HeadersUnwind(u, s, tx, headers, test) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return HeadersUnwind(u, s, txc.Tx, headers, test) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return nil @@ -468,11 +469,11 @@ func UploaderPipelineStages(ctx context.Context, snapshots SnapshotsCfg, headers { ID: stages.BlockHashes, Description: "Write block hashes", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnBlockHashStage(s, tx, blockHashCfg, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnBlockHashStage(s, txc.Tx, blockHashCfg, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindBlockHashStage(u, tx, blockHashCfg, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindBlockHashStage(u, txc.Tx, blockHashCfg, ctx) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneBlockHashStage(p, tx, blockHashCfg, ctx) @@ -481,11 +482,11 @@ func UploaderPipelineStages(ctx context.Context, snapshots SnapshotsCfg, headers { ID: stages.Bodies, Description: "Download block bodies", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return BodiesForward(s, u, ctx, tx, bodies, test, firstCycle, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return BodiesForward(s, u, ctx, txc.Tx, bodies, test, firstCycle, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindBodiesStage(u, tx, bodies, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindBodiesStage(u, txc.Tx, bodies, ctx) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return nil @@ -494,11 +495,11 @@ func UploaderPipelineStages(ctx context.Context, snapshots SnapshotsCfg, headers { ID: stages.Senders, Description: "Recover senders from tx signatures", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnRecoverSendersStage(senders, s, u, tx, 0, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnRecoverSendersStage(senders, s, u, txc.Tx, 0, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindSendersStage(u, tx, senders, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindSendersStage(u, txc.Tx, senders, ctx) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneSendersStage(p, tx, senders, ctx) @@ -507,11 +508,11 @@ func UploaderPipelineStages(ctx context.Context, snapshots SnapshotsCfg, headers { ID: stages.Execution, Description: "Execute blocks w/o hash checks", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnExecuteBlocksStage(s, u, tx, 0, ctx, exec, firstCycle, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnExecuteBlocksStage(s, u, txc, 0, ctx, exec, firstCycle, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindExecutionStage(u, s, tx, ctx, exec, firstCycle, logger) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindExecutionStage(u, s, txc, ctx, exec, firstCycle, logger) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneExecutionStage(p, tx, exec, ctx, firstCycle) @@ -521,11 +522,11 @@ func UploaderPipelineStages(ctx context.Context, snapshots SnapshotsCfg, headers ID: stages.HashState, Description: "Hash the key in the state", Disabled: exec.historyV3 && ethconfig.EnableHistoryV4InTest, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnHashStateStage(s, tx, hashState, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnHashStateStage(s, txc.Tx, hashState, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindHashStateStage(u, s, tx, hashState, ctx, logger) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindHashStateStage(u, s, txc.Tx, hashState, ctx, logger) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneHashStateStage(p, tx, hashState, ctx) @@ -535,19 +536,19 @@ func UploaderPipelineStages(ctx context.Context, snapshots SnapshotsCfg, headers ID: stages.IntermediateHashes, Description: "Generate intermediate hashes and computing state root", Disabled: exec.historyV3 && ethconfig.EnableHistoryV4InTest, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { if exec.chainConfig.IsPrague(0) { - _, err := SpawnVerkleTrie(s, u, tx, trieCfg, ctx, logger) + _, err := SpawnVerkleTrie(s, u, txc.Tx, trieCfg, ctx, logger) return err } - _, err := SpawnIntermediateHashesStage(s, u, tx, trieCfg, ctx, logger) + _, err := SpawnIntermediateHashesStage(s, u, txc.Tx, trieCfg, ctx, logger) return err }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { if exec.chainConfig.IsPrague(0) { - return UnwindVerkleTrie(u, s, tx, trieCfg, ctx, logger) + return UnwindVerkleTrie(u, s, txc.Tx, trieCfg, ctx, logger) } - return UnwindIntermediateHashesStage(u, s, tx, trieCfg, ctx, logger) + return UnwindIntermediateHashesStage(u, s, txc.Tx, trieCfg, ctx, logger) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneIntermediateHashesStage(p, tx, trieCfg, ctx) @@ -558,11 +559,11 @@ func UploaderPipelineStages(ctx context.Context, snapshots SnapshotsCfg, headers Description: "Generate call traces index", DisabledDescription: "Work In Progress", Disabled: exec.historyV3, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnCallTraces(s, tx, callTraces, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnCallTraces(s, txc.Tx, callTraces, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindCallTraces(u, s, tx, callTraces, ctx, logger) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindCallTraces(u, s, txc.Tx, callTraces, ctx, logger) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneCallTraces(p, tx, callTraces, ctx, logger) @@ -572,11 +573,11 @@ func UploaderPipelineStages(ctx context.Context, snapshots SnapshotsCfg, headers ID: stages.AccountHistoryIndex, Description: "Generate account history index", Disabled: exec.historyV3, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnAccountHistoryIndex(s, tx, history, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnAccountHistoryIndex(s, txc.Tx, history, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindAccountHistoryIndex(u, s, tx, history, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindAccountHistoryIndex(u, s, txc.Tx, history, ctx) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneAccountHistoryIndex(p, tx, history, ctx, logger) @@ -586,11 +587,11 @@ func UploaderPipelineStages(ctx context.Context, snapshots SnapshotsCfg, headers ID: stages.StorageHistoryIndex, Description: "Generate storage history index", Disabled: exec.historyV3, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnStorageHistoryIndex(s, tx, history, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnStorageHistoryIndex(s, txc.Tx, history, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindStorageHistoryIndex(u, s, tx, history, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindStorageHistoryIndex(u, s, txc.Tx, history, ctx) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneStorageHistoryIndex(p, tx, history, ctx, logger) @@ -600,11 +601,11 @@ func UploaderPipelineStages(ctx context.Context, snapshots SnapshotsCfg, headers ID: stages.LogIndex, Description: "Generate receipt logs index", Disabled: exec.historyV3, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnLogIndex(s, tx, logIndex, ctx, 0, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnLogIndex(s, txc.Tx, logIndex, ctx, 0, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindLogIndex(u, s, tx, logIndex, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindLogIndex(u, s, txc.Tx, logIndex, ctx) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneLogIndex(p, tx, logIndex, ctx, logger) @@ -613,11 +614,11 @@ func UploaderPipelineStages(ctx context.Context, snapshots SnapshotsCfg, headers { ID: stages.TxLookup, Description: "Generate tx lookup index", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnTxLookup(s, tx, 0 /* toBlock */, txLookup, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnTxLookup(s, txc.Tx, 0 /* toBlock */, txLookup, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindTxLookup(u, s, tx, txLookup, ctx, logger) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindTxLookup(u, s, txc.Tx, txLookup, ctx, logger) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneTxLookup(p, tx, txLookup, ctx, firstCycle, logger) @@ -626,11 +627,11 @@ func UploaderPipelineStages(ctx context.Context, snapshots SnapshotsCfg, headers { ID: stages.Finish, Description: "Final: update current block for the RPC API", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, _ Unwinder, tx kv.RwTx, logger log.Logger) error { - return FinishForward(s, tx, finish, firstCycle) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, _ Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return FinishForward(s, txc.Tx, finish, firstCycle) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindFinish(u, tx, finish, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindFinish(u, txc.Tx, finish, ctx) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return PruneFinish(p, tx, finish, ctx) @@ -645,72 +646,72 @@ func StateStages(ctx context.Context, headers HeadersCfg, bodies BodiesCfg, bloc { ID: stages.Headers, Description: "Download headers", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { return nil }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return HeadersUnwind(u, s, tx, headers, false) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return HeadersUnwind(u, s, txc.Tx, headers, false) }, }, { ID: stages.Bodies, Description: "Download block bodies", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { return nil }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindBodiesStage(u, tx, bodies, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindBodiesStage(u, txc.Tx, bodies, ctx) }, }, { ID: stages.BlockHashes, Description: "Write block hashes", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnBlockHashStage(s, tx, blockHashCfg, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnBlockHashStage(s, txc.Tx, blockHashCfg, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindBlockHashStage(u, tx, blockHashCfg, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindBlockHashStage(u, txc.Tx, blockHashCfg, ctx) }, }, { ID: stages.Senders, Description: "Recover senders from tx signatures", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnRecoverSendersStage(senders, s, u, tx, 0, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnRecoverSendersStage(senders, s, u, txc.Tx, 0, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindSendersStage(u, tx, senders, ctx) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindSendersStage(u, txc.Tx, senders, ctx) }, }, { ID: stages.Execution, Description: "Execute blocks w/o hash checks", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnExecuteBlocksStage(s, u, tx, 0, ctx, exec, firstCycle, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnExecuteBlocksStage(s, u, txc, 0, ctx, exec, firstCycle, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindExecutionStage(u, s, tx, ctx, exec, firstCycle, logger) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindExecutionStage(u, s, txc, ctx, exec, firstCycle, logger) }, }, { ID: stages.HashState, Description: "Hash the key in the state", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnHashStateStage(s, tx, hashState, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnHashStateStage(s, txc.Tx, hashState, ctx, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindHashStateStage(u, s, tx, hashState, ctx, logger) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindHashStateStage(u, s, txc.Tx, hashState, ctx, logger) }, }, { ID: stages.IntermediateHashes, Description: "Generate intermediate hashes and computing state root", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - _, err := SpawnIntermediateHashesStage(s, u, tx, trieCfg, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + _, err := SpawnIntermediateHashesStage(s, u, txc.Tx, trieCfg, ctx, logger) return err }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return UnwindIntermediateHashesStage(u, s, tx, trieCfg, ctx, logger) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return UnwindIntermediateHashesStage(u, s, txc.Tx, trieCfg, ctx, logger) }, }, } diff --git a/eth/stagedsync/exec3.go b/eth/stagedsync/exec3.go index 41513721d95..f10435198c4 100644 --- a/eth/stagedsync/exec3.go +++ b/eth/stagedsync/exec3.go @@ -29,6 +29,7 @@ import ( "github.com/ledgerwatch/erigon-lib/kv/rawdbv3" "github.com/ledgerwatch/erigon-lib/metrics" libstate "github.com/ledgerwatch/erigon-lib/state" + "github.com/ledgerwatch/erigon-lib/wrap" "github.com/ledgerwatch/erigon/cmd/state/exec22" "github.com/ledgerwatch/erigon/cmd/state/exec3" "github.com/ledgerwatch/erigon/common/math" @@ -144,7 +145,7 @@ rwloop does: When rwLoop has nothing to do - it does Prune, or flush of WAL to RwTx (agg.rotate+agg.Flush) */ func ExecV3(ctx context.Context, - execStage *StageState, u Unwinder, workerCount int, cfg ExecuteBlockCfg, applyTx kv.RwTx, + execStage *StageState, u Unwinder, workerCount int, cfg ExecuteBlockCfg, txc wrap.TxContainer, parallel bool, logPrefix string, maxBlockNum uint64, logger log.Logger, @@ -156,6 +157,7 @@ func ExecV3(ctx context.Context, agg, engine := cfg.agg, cfg.engine chainConfig, genesis := cfg.chainConfig, cfg.genesis + applyTx := txc.Tx useExternalTx := applyTx != nil if !useExternalTx && !parallel { var err error diff --git a/eth/stagedsync/stage.go b/eth/stagedsync/stage.go index 17607787155..43b248ecdd9 100644 --- a/eth/stagedsync/stage.go +++ b/eth/stagedsync/stage.go @@ -5,18 +5,19 @@ import ( libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon-lib/wrap" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" ) // ExecFunc is the execution function for the stage to move forward. // * state - is the current state of the stage and contains stage data. // * unwinder - if the stage needs to cause unwinding, `unwinder` methods can be used. -type ExecFunc func(firstCycle bool, badBlockUnwind bool, s *StageState, unwinder Unwinder, tx kv.RwTx, logger log.Logger) error +type ExecFunc func(firstCycle bool, badBlockUnwind bool, s *StageState, unwinder Unwinder, txc wrap.TxContainer, logger log.Logger) error // UnwindFunc is the unwinding logic of the stage. // * unwindState - contains information about the unwind itself. // * stageState - represents the state of this stage at the beginning of unwind. -type UnwindFunc func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error +type UnwindFunc func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error // PruneFunc is the execution function for the stage to prune old data. // * state - is the current state of the stage and contains stage data. diff --git a/eth/stagedsync/stage_execute.go b/eth/stagedsync/stage_execute.go index 8a512eba3e2..c53e1995d93 100644 --- a/eth/stagedsync/stage_execute.go +++ b/eth/stagedsync/stage_execute.go @@ -28,6 +28,7 @@ import ( "github.com/ledgerwatch/erigon-lib/kv/rawdbv3" "github.com/ledgerwatch/erigon-lib/kv/temporal/historyv2" libstate "github.com/ledgerwatch/erigon-lib/state" + "github.com/ledgerwatch/erigon-lib/wrap" "github.com/ledgerwatch/erigon/common/changeset" "github.com/ledgerwatch/erigon/common/math" "github.com/ledgerwatch/erigon/consensus" @@ -239,7 +240,7 @@ func newStateReaderWriter( // ================ Erigon3 ================ -func ExecBlockV3(s *StageState, u Unwinder, tx kv.RwTx, toBlock uint64, ctx context.Context, cfg ExecuteBlockCfg, initialCycle bool, logger log.Logger) (err error) { +func ExecBlockV3(s *StageState, u Unwinder, txc wrap.TxContainer, toBlock uint64, ctx context.Context, cfg ExecuteBlockCfg, initialCycle bool, logger log.Logger) (err error) { workersCount := cfg.syncCfg.ExecWorkerCount //workersCount := 2 if !initialCycle { @@ -248,7 +249,7 @@ func ExecBlockV3(s *StageState, u Unwinder, tx kv.RwTx, toBlock uint64, ctx cont cfg.agg.SetWorkers(estimate.CompressSnapshot.WorkersQuarter()) if initialCycle { - reconstituteToBlock, found, err := reconstituteBlock(cfg.agg, cfg.db, tx) + reconstituteToBlock, found, err := reconstituteBlock(cfg.agg, cfg.db, txc.Tx) if err != nil { return err } @@ -264,7 +265,7 @@ func ExecBlockV3(s *StageState, u Unwinder, tx kv.RwTx, toBlock uint64, ctx cont } } - prevStageProgress, err := senderStageProgress(tx, cfg.db) + prevStageProgress, err := senderStageProgress(txc.Tx, cfg.db) if err != nil { return err } @@ -280,8 +281,8 @@ func ExecBlockV3(s *StageState, u Unwinder, tx kv.RwTx, toBlock uint64, ctx cont if to > s.BlockNumber+16 { logger.Info(fmt.Sprintf("[%s] Blocks execution", logPrefix), "from", s.BlockNumber, "to", to) } - parallel := tx == nil - if err := ExecV3(ctx, s, u, workersCount, cfg, tx, parallel, logPrefix, + parallel := txc.Tx == nil + if err := ExecV3(ctx, s, u, workersCount, cfg, txc, parallel, logPrefix, to, logger, initialCycle); err != nil { return fmt.Errorf("ExecV3: %w", err) } @@ -308,28 +309,28 @@ func reconstituteBlock(agg *libstate.AggregatorV3, db kv.RoDB, tx kv.Tx) (n uint return } -func unwindExec3(u *UnwindState, s *StageState, tx kv.RwTx, ctx context.Context, cfg ExecuteBlockCfg, accumulator *shards.Accumulator, logger log.Logger) (err error) { +func unwindExec3(u *UnwindState, s *StageState, txc wrap.TxContainer, ctx context.Context, cfg ExecuteBlockCfg, accumulator *shards.Accumulator, logger log.Logger) (err error) { cfg.agg.SetLogPrefix(s.LogPrefix()) rs := state.NewStateV3(cfg.dirs.Tmp, logger) // unwind all txs of u.UnwindPoint block. 1 txn in begin/end of block - system txs - txNum, err := rawdbv3.TxNums.Min(tx, u.UnwindPoint+1) + txNum, err := rawdbv3.TxNums.Min(txc.Tx, u.UnwindPoint+1) if err != nil { return err } - if err := rs.Unwind(ctx, tx, txNum, cfg.agg, accumulator); err != nil { + if err := rs.Unwind(ctx, txc.Tx, u.UnwindPoint, txNum, cfg.agg, accumulator); err != nil { return fmt.Errorf("StateV3.Unwind: %w", err) } - if err := rs.Flush(ctx, tx, s.LogPrefix(), time.NewTicker(30*time.Second)); err != nil { + if err := rs.Flush(ctx, txc.Tx, s.LogPrefix(), time.NewTicker(30*time.Second)); err != nil { return fmt.Errorf("StateV3.Flush: %w", err) } - if err := rawdb.TruncateReceipts(tx, u.UnwindPoint+1); err != nil { + if err := rawdb.TruncateReceipts(txc.Tx, u.UnwindPoint+1); err != nil { return fmt.Errorf("truncate receipts: %w", err) } - if err := rawdb.TruncateBorReceipts(tx, u.UnwindPoint+1); err != nil { + if err := rawdb.TruncateBorReceipts(txc.Tx, u.UnwindPoint+1); err != nil { return fmt.Errorf("truncate bor receipts: %w", err) } - if err := rawdb.DeleteNewerEpochs(tx, u.UnwindPoint+1); err != nil { + if err := rawdb.DeleteNewerEpochs(txc.Tx, u.UnwindPoint+1); err != nil { return fmt.Errorf("delete newer epochs: %w", err) } @@ -358,29 +359,29 @@ func senderStageProgress(tx kv.Tx, db kv.RoDB) (prevStageProgress uint64, err er // ================ Erigon3 End ================ -func SpawnExecuteBlocksStage(s *StageState, u Unwinder, tx kv.RwTx, toBlock uint64, ctx context.Context, cfg ExecuteBlockCfg, initialCycle bool, logger log.Logger) (err error) { +func SpawnExecuteBlocksStage(s *StageState, u Unwinder, txc wrap.TxContainer, toBlock uint64, ctx context.Context, cfg ExecuteBlockCfg, initialCycle bool, logger log.Logger) (err error) { if cfg.historyV3 { - if err = ExecBlockV3(s, u, tx, toBlock, ctx, cfg, initialCycle, logger); err != nil { + if err = ExecBlockV3(s, u, txc, toBlock, ctx, cfg, initialCycle, logger); err != nil { return err } return nil } quit := ctx.Done() - useExternalTx := tx != nil + useExternalTx := txc.Tx != nil if !useExternalTx { - tx, err = cfg.db.BeginRw(context.Background()) + txc.Tx, err = cfg.db.BeginRw(context.Background()) if err != nil { return err } - defer tx.Rollback() + defer txc.Tx.Rollback() } - prevStageProgress, errStart := stages.GetStageProgress(tx, stages.Senders) + prevStageProgress, errStart := stages.GetStageProgress(txc.Tx, stages.Senders) if errStart != nil { return errStart } - nextStageProgress, err := stages.GetStageProgress(tx, stages.HashState) + nextStageProgress, err := stages.GetStageProgress(txc.Tx, stages.HashState) if err != nil { return err } @@ -415,7 +416,7 @@ func SpawnExecuteBlocksStage(s *StageState, u Unwinder, tx kv.RwTx, toBlock uint var batch kv.PendingMutations // state is stored through ethdb batches - batch = membatch.NewHashBatch(tx, quit, cfg.dirs.Tmp, logger) + batch = membatch.NewHashBatch(txc.Tx, quit, cfg.dirs.Tmp, logger) // avoids stacking defers within the loop defer func() { batch.Close() @@ -443,11 +444,11 @@ Loop: } } - blockHash, err := cfg.blockReader.CanonicalHash(ctx, tx, blockNum) + blockHash, err := cfg.blockReader.CanonicalHash(ctx, txc.Tx, blockNum) if err != nil { return err } - block, _, err := cfg.blockReader.BlockWithSenders(ctx, tx, blockHash, blockNum) + block, _, err := cfg.blockReader.BlockWithSenders(ctx, txc.Tx, blockHash, blockNum) if err != nil { return err } @@ -463,11 +464,11 @@ Loop: writeReceipts := nextStagesExpectData || blockNum > cfg.prune.Receipts.PruneTo(to) writeCallTraces := nextStagesExpectData || blockNum > cfg.prune.CallTraces.PruneTo(to) - _, isMemoryMutation := tx.(*membatchwithdb.MemoryMutation) + _, isMemoryMutation := txc.Tx.(*membatchwithdb.MemoryMutation) if cfg.silkworm != nil && !isMemoryMutation { - blockNum, err = silkworm.ExecuteBlocks(cfg.silkworm, tx, cfg.chainConfig.ChainID, blockNum, to, uint64(cfg.batchSize), writeChangeSets, writeReceipts, writeCallTraces) + blockNum, err = silkworm.ExecuteBlocks(cfg.silkworm, txc.Tx, cfg.chainConfig.ChainID, blockNum, to, uint64(cfg.batchSize), writeChangeSets, writeReceipts, writeCallTraces) } else { - err = executeBlock(block, tx, batch, cfg, *cfg.vmConfig, writeChangeSets, writeReceipts, writeCallTraces, initialCycle, stateStream, logger) + err = executeBlock(block, txc.Tx, batch, cfg, *cfg.vmConfig, writeChangeSets, writeReceipts, writeCallTraces, initialCycle, stateStream, logger) } if err != nil { @@ -507,24 +508,24 @@ Loop: if shouldUpdateProgress { logger.Info("Committed State", "gas reached", currentStateGas, "gasTarget", gasState) currentStateGas = 0 - if err = batch.Flush(ctx, tx); err != nil { + if err = batch.Flush(ctx, txc.Tx); err != nil { return err } - if err = s.Update(tx, stageProgress); err != nil { + if err = s.Update(txc.Tx, stageProgress); err != nil { return err } if !useExternalTx { - if err = tx.Commit(); err != nil { + if err = txc.Tx.Commit(); err != nil { return err } - tx, err = cfg.db.BeginRw(context.Background()) + txc.Tx, err = cfg.db.BeginRw(context.Background()) if err != nil { return err } // TODO: This creates stacked up deferrals - defer tx.Rollback() + defer txc.Tx.Rollback() } - batch = membatch.NewHashBatch(tx, quit, cfg.dirs.Tmp, logger) + batch = membatch.NewHashBatch(txc.Tx, quit, cfg.dirs.Tmp, logger) } gas = gas + block.GasUsed() @@ -534,25 +535,25 @@ Loop: case <-logEvery.C: logBlock, logTx, logTime = logProgress(logPrefix, logBlock, logTime, blockNum, logTx, lastLogTx, gas, float64(currentStateGas)/float64(gasState), batch, logger) gas = 0 - tx.CollectMetrics() + txc.Tx.CollectMetrics() syncMetrics[stages.Execution].SetUint64(blockNum) } } - if err = s.Update(batch, stageProgress); err != nil { + if err = s.Update(txc.Tx, stageProgress); err != nil { return err } - if err = batch.Flush(ctx, tx); err != nil { + if err = batch.Flush(ctx, txc.Tx); err != nil { return fmt.Errorf("batch commit: %w", err) } - _, err = rawdb.IncrementStateVersion(tx) + _, err = rawdb.IncrementStateVersion(txc.Tx) if err != nil { return fmt.Errorf("writing plain state version: %w", err) } if !useExternalTx { - if err = tx.Commit(); err != nil { + if err = txc.Tx.Commit(); err != nil { return err } } @@ -673,37 +674,37 @@ func logProgress(logPrefix string, prevBlock uint64, prevTime time.Time, current return currentBlock, currentTx, currentTime } -func UnwindExecutionStage(u *UnwindState, s *StageState, tx kv.RwTx, ctx context.Context, cfg ExecuteBlockCfg, initialCycle bool, logger log.Logger) (err error) { +func UnwindExecutionStage(u *UnwindState, s *StageState, txc wrap.TxContainer, ctx context.Context, cfg ExecuteBlockCfg, initialCycle bool, logger log.Logger) (err error) { if u.UnwindPoint >= s.BlockNumber { return nil } - useExternalTx := tx != nil + useExternalTx := txc.Tx != nil if !useExternalTx { - tx, err = cfg.db.BeginRw(context.Background()) + txc.Tx, err = cfg.db.BeginRw(context.Background()) if err != nil { return err } - defer tx.Rollback() + defer txc.Tx.Rollback() } logPrefix := u.LogPrefix() logger.Info(fmt.Sprintf("[%s] Unwind Execution", logPrefix), "from", s.BlockNumber, "to", u.UnwindPoint) - if err = unwindExecutionStage(u, s, tx, ctx, cfg, initialCycle, logger); err != nil { + if err = unwindExecutionStage(u, s, txc, ctx, cfg, initialCycle, logger); err != nil { return err } - if err = u.Done(tx); err != nil { + if err = u.Done(txc.Tx); err != nil { return err } if !useExternalTx { - if err = tx.Commit(); err != nil { + if err = txc.Tx.Commit(); err != nil { return err } } return nil } -func unwindExecutionStage(u *UnwindState, s *StageState, tx kv.RwTx, ctx context.Context, cfg ExecuteBlockCfg, initialCycle bool, logger log.Logger) error { +func unwindExecutionStage(u *UnwindState, s *StageState, txc wrap.TxContainer, ctx context.Context, cfg ExecuteBlockCfg, initialCycle bool, logger log.Logger) error { logPrefix := s.LogPrefix() stateBucket := kv.PlainState storageKeyLength := length.Addr + length.Incarnation + length.Hash @@ -712,11 +713,11 @@ func unwindExecutionStage(u *UnwindState, s *StageState, tx kv.RwTx, ctx context if !initialCycle && cfg.stateStream && s.BlockNumber-u.UnwindPoint < stateStreamLimit { accumulator = cfg.accumulator - hash, err := cfg.blockReader.CanonicalHash(ctx, tx, u.UnwindPoint) + hash, err := cfg.blockReader.CanonicalHash(ctx, txc.Tx, u.UnwindPoint) if err != nil { return fmt.Errorf("read canonical hash of unwind point: %w", err) } - txs, err := cfg.blockReader.RawTransactions(ctx, tx, u.UnwindPoint, s.BlockNumber) + txs, err := cfg.blockReader.RawTransactions(ctx, txc.Tx, u.UnwindPoint, s.BlockNumber) if err != nil { return err } @@ -724,17 +725,17 @@ func unwindExecutionStage(u *UnwindState, s *StageState, tx kv.RwTx, ctx context } if cfg.historyV3 { - return unwindExec3(u, s, tx, ctx, cfg, accumulator, logger) + return unwindExec3(u, s, txc, ctx, cfg, accumulator, logger) } changes := etl.NewCollector(logPrefix, cfg.dirs.Tmp, etl.NewOldestEntryBuffer(etl.BufferOptimalSize), logger) defer changes.Close() - errRewind := changeset.RewindData(tx, s.BlockNumber, u.UnwindPoint, changes, ctx.Done()) + errRewind := changeset.RewindData(txc.Tx, s.BlockNumber, u.UnwindPoint, changes, ctx.Done()) if errRewind != nil { return fmt.Errorf("getting rewind data: %w", errRewind) } - if err := changes.Load(tx, stateBucket, func(k, v []byte, table etl.CurrentTableReader, next etl.LoadNextFunc) error { + if err := changes.Load(txc.Tx, stateBucket, func(k, v []byte, table etl.CurrentTableReader, next etl.LoadNextFunc) error { if len(k) == 20 { if len(v) > 0 { var acc accounts.Account @@ -743,19 +744,19 @@ func unwindExecutionStage(u *UnwindState, s *StageState, tx kv.RwTx, ctx context } // Fetch the code hash - recoverCodeHashPlain(&acc, tx, k) + recoverCodeHashPlain(&acc, txc.Tx, k) var address common.Address copy(address[:], k) // cleanup contract code bucket - original, err := state.NewPlainStateReader(tx).ReadAccountData(address) + original, err := state.NewPlainStateReader(txc.Tx).ReadAccountData(address) if err != nil { return fmt.Errorf("read account for %x: %w", address, err) } if original != nil { // clean up all the code incarnations original incarnation and the new one for incarnation := original.Incarnation; incarnation > acc.Incarnation && incarnation > 0; incarnation-- { - err = tx.Delete(kv.PlainContractCode, dbutils.PlainGenerateStoragePrefix(address[:], incarnation)) + err = txc.Tx.Delete(kv.PlainContractCode, dbutils.PlainGenerateStoragePrefix(address[:], incarnation)) if err != nil { return fmt.Errorf("writeAccountPlain for %x: %w", address, err) } @@ -807,23 +808,23 @@ func unwindExecutionStage(u *UnwindState, s *StageState, tx kv.RwTx, ctx context return err } - if err := historyv2.Truncate(tx, u.UnwindPoint+1); err != nil { + if err := historyv2.Truncate(txc.Tx, u.UnwindPoint+1); err != nil { return err } - if err := rawdb.TruncateReceipts(tx, u.UnwindPoint+1); err != nil { + if err := rawdb.TruncateReceipts(txc.Tx, u.UnwindPoint+1); err != nil { return fmt.Errorf("truncate receipts: %w", err) } - if err := rawdb.TruncateBorReceipts(tx, u.UnwindPoint+1); err != nil { + if err := rawdb.TruncateBorReceipts(txc.Tx, u.UnwindPoint+1); err != nil { return fmt.Errorf("truncate bor receipts: %w", err) } - if err := rawdb.DeleteNewerEpochs(tx, u.UnwindPoint+1); err != nil { + if err := rawdb.DeleteNewerEpochs(txc.Tx, u.UnwindPoint+1); err != nil { return fmt.Errorf("delete newer epochs: %w", err) } // Truncate CallTraceSet keyStart := hexutility.EncodeTs(u.UnwindPoint + 1) - c, err := tx.RwCursorDupSort(kv.CallTraceSet) + c, err := txc.Tx.RwCursorDupSort(kv.CallTraceSet) if err != nil { return err } @@ -832,7 +833,7 @@ func unwindExecutionStage(u *UnwindState, s *StageState, tx kv.RwTx, ctx context if err != nil { return err } - if err = tx.Delete(kv.CallTraceSet, k); err != nil { + if err = txc.Tx.Delete(kv.CallTraceSet, k); err != nil { return err } } diff --git a/eth/stagedsync/stage_execute_test.go b/eth/stagedsync/stage_execute_test.go index 7ef922a112a..a34f6010b14 100644 --- a/eth/stagedsync/stage_execute_test.go +++ b/eth/stagedsync/stage_execute_test.go @@ -11,6 +11,8 @@ import ( "github.com/ledgerwatch/log/v3" "github.com/stretchr/testify/require" + "github.com/ledgerwatch/erigon-lib/wrap" + "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/memdb" "github.com/ledgerwatch/erigon-lib/kv/rawdbv3" @@ -42,7 +44,7 @@ func TestExec(t *testing.T) { u := &UnwindState{ID: stages.Execution, UnwindPoint: 25} s := &StageState{ID: stages.Execution, BlockNumber: 50} - err = UnwindExecutionStage(u, s, tx2, ctx, cfg, false, logger) + err = UnwindExecutionStage(u, s, wrap.TxContainer{Tx: tx2}, ctx, cfg, false, logger) require.NoError(err) compareCurrentState(t, newAgg(t, logger), tx1, tx2, kv.PlainState, kv.PlainContractCode, kv.ContractTEVMCode) @@ -58,7 +60,7 @@ func TestExec(t *testing.T) { u := &UnwindState{ID: stages.Execution, UnwindPoint: 25} s := &StageState{ID: stages.Execution, BlockNumber: 50} - err = UnwindExecutionStage(u, s, tx2, ctx, cfg, false, logger) + err = UnwindExecutionStage(u, s, wrap.TxContainer{Tx: tx2}, ctx, cfg, false, logger) require.NoError(err) compareCurrentState(t, newAgg(t, logger), tx1, tx2, kv.PlainState, kv.PlainContractCode) @@ -76,7 +78,7 @@ func TestExec(t *testing.T) { } u := &UnwindState{ID: stages.Execution, UnwindPoint: 25} s := &StageState{ID: stages.Execution, BlockNumber: 50} - err = UnwindExecutionStage(u, s, tx2, ctx, cfg, false, logger) + err = UnwindExecutionStage(u, s, wrap.TxContainer{Tx: tx2}, ctx, cfg, false, logger) require.NoError(err) compareCurrentState(t, newAgg(t, logger), tx1, tx2, kv.PlainState, kv.PlainContractCode) @@ -204,7 +206,7 @@ func TestExec22(t *testing.T) { u := &UnwindState{ID: stages.Execution, UnwindPoint: 25} s := &StageState{ID: stages.Execution, BlockNumber: 50} - err = UnwindExecutionStage(u, s, tx2, ctx, cfg, false, logger) + err = UnwindExecutionStage(u, s, wrap.TxContainer{Tx: tx2}, ctx, cfg, false, logger) require.NoError(err) compareCurrentState(t, agg, tx1, tx2, kv.PlainState, kv.PlainContractCode) @@ -228,7 +230,7 @@ func TestExec22(t *testing.T) { u := &UnwindState{ID: stages.Execution, UnwindPoint: 25} s := &StageState{ID: stages.Execution, BlockNumber: 50} - err = UnwindExecutionStage(u, s, tx2, ctx, cfg, false, logger) + err = UnwindExecutionStage(u, s, wrap.TxContainer{Tx: tx2}, ctx, cfg, false, logger) require.NoError(err) tx1.ForEach(kv.PlainState, nil, func(k, v []byte) error { diff --git a/eth/stagedsync/stagebuilder.go b/eth/stagedsync/stagebuilder.go index 05ed4183ca6..26200a9e3a8 100644 --- a/eth/stagedsync/stagebuilder.go +++ b/eth/stagedsync/stagebuilder.go @@ -5,6 +5,7 @@ import ( "github.com/ledgerwatch/erigon-lib/gointerfaces/remote" "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon-lib/wrap" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" "github.com/ledgerwatch/log/v3" @@ -30,23 +31,25 @@ func MiningStages( { ID: stages.MiningCreateBlock, Description: "Mining: construct new block from tx pool", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnMiningCreateBlockStage(s, tx, createBlockCfg, ctx.Done(), logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnMiningCreateBlockStage(s, txc.Tx, createBlockCfg, ctx.Done(), logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { return nil }, - Prune: func(firstCycle bool, u *PruneState, tx kv.RwTx, logger log.Logger) error { return nil }, + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return nil + }, + Prune: func(firstCycle bool, u *PruneState, tx kv.RwTx, logger log.Logger) error { return nil }, }, { ID: stages.BorHeimdall, Description: "Download Bor-specific data from Heimdall", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { if badBlockUnwind { return nil } - return BorHeimdallForward(s, u, ctx, tx, borHeimdallCfg, true, logger) + return BorHeimdallForward(s, u, ctx, txc.Tx, borHeimdallCfg, true, logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { - return BorHeimdallUnwind(u, ctx, s, tx, borHeimdallCfg) + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return BorHeimdallUnwind(u, ctx, s, txc.Tx, borHeimdallCfg) }, Prune: func(firstCycle bool, p *PruneState, tx kv.RwTx, logger log.Logger) error { return BorHeimdallPrune(p, ctx, tx, borHeimdallCfg) @@ -55,45 +58,53 @@ func MiningStages( { ID: stages.MiningExecution, Description: "Mining: execute new block from tx pool", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { //fmt.Println("SpawnMiningExecStage") //defer fmt.Println("SpawnMiningExecStage", "DONE") - return SpawnMiningExecStage(s, tx, execCfg, ctx.Done(), logger) + return SpawnMiningExecStage(s, txc.Tx, execCfg, ctx.Done(), logger) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { return nil }, - Prune: func(firstCycle bool, u *PruneState, tx kv.RwTx, logger log.Logger) error { return nil }, + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return nil + }, + Prune: func(firstCycle bool, u *PruneState, tx kv.RwTx, logger log.Logger) error { return nil }, }, { ID: stages.HashState, Description: "Hash the key in the state", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnHashStateStage(s, tx, hashStateCfg, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnHashStateStage(s, txc.Tx, hashStateCfg, ctx, logger) + }, + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return nil }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { return nil }, - Prune: func(firstCycle bool, u *PruneState, tx kv.RwTx, logger log.Logger) error { return nil }, + Prune: func(firstCycle bool, u *PruneState, tx kv.RwTx, logger log.Logger) error { return nil }, }, { ID: stages.IntermediateHashes, Description: "Generate intermediate hashes and computing state root", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - stateRoot, err := SpawnIntermediateHashesStage(s, u, tx, trieCfg, ctx, logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + stateRoot, err := SpawnIntermediateHashesStage(s, u, txc.Tx, trieCfg, ctx, logger) if err != nil { return err } createBlockCfg.miner.MiningBlock.Header.Root = stateRoot return nil }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { return nil }, - Prune: func(firstCycle bool, u *PruneState, tx kv.RwTx, logger log.Logger) error { return nil }, + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return nil + }, + Prune: func(firstCycle bool, u *PruneState, tx kv.RwTx, logger log.Logger) error { return nil }, }, { ID: stages.MiningFinish, Description: "Mining: create and propagate valid block", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnMiningFinishStage(s, tx, finish, ctx.Done(), logger) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnMiningFinishStage(s, txc.Tx, finish, ctx.Done(), logger) + }, + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return nil }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { return nil }, - Prune: func(firstCycle bool, u *PruneState, tx kv.RwTx, logger log.Logger) error { return nil }, + Prune: func(firstCycle bool, u *PruneState, tx kv.RwTx, logger log.Logger) error { return nil }, }, } } diff --git a/eth/stagedsync/stagedsynctest/harness.go b/eth/stagedsync/stagedsynctest/harness.go index 78e481f94b9..bba47ad402d 100644 --- a/eth/stagedsync/stagedsynctest/harness.go +++ b/eth/stagedsync/stagedsynctest/harness.go @@ -21,6 +21,7 @@ import ( libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/memdb" + "github.com/ledgerwatch/erigon-lib/wrap" "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/consensus/bor" "github.com/ledgerwatch/erigon/consensus/bor/clerk" @@ -216,7 +217,7 @@ func (h *Harness) RunStageForwardWithReturnError(t *testing.T, id stages.SyncSta stageState, err := h.stateSync.StageState(id, nil, h.chainDataDB) require.NoError(t, err) - return stage.Forward(true, false, stageState, h.stateSync, nil, h.logger) + return stage.Forward(true, false, stageState, h.stateSync, wrap.TxContainer{}, h.logger) } func (h *Harness) ReadSpansFromDB(ctx context.Context) (spans []*span.HeimdallSpan, err error) { diff --git a/eth/stagedsync/sync.go b/eth/stagedsync/sync.go index f90e0577b11..20b067844de 100644 --- a/eth/stagedsync/sync.go +++ b/eth/stagedsync/sync.go @@ -11,6 +11,8 @@ import ( "github.com/ledgerwatch/erigon-lib/common/dbg" "github.com/ledgerwatch/erigon-lib/diagnostics" "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon-lib/wrap" + "github.com/ledgerwatch/erigon/eth/ethconfig" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" ) @@ -236,7 +238,7 @@ func (s *Sync) StageState(stage stages.SyncStage, tx kv.Tx, db kv.RoDB) (*StageS return &StageState{s, stage, blockNum}, nil } -func (s *Sync) RunUnwind(db kv.RwDB, tx kv.RwTx) error { +func (s *Sync) RunUnwind(db kv.RwDB, txc wrap.TxContainer) error { if s.unwindPoint == nil { return nil } @@ -244,7 +246,7 @@ func (s *Sync) RunUnwind(db kv.RwDB, tx kv.RwTx) error { if s.unwindOrder[j] == nil || s.unwindOrder[j].Disabled || s.unwindOrder[j].Unwind == nil { continue } - if err := s.unwindStage(false, s.unwindOrder[j], db, tx); err != nil { + if err := s.unwindStage(false, s.unwindOrder[j], db, txc); err != nil { return err } } @@ -257,7 +259,7 @@ func (s *Sync) RunUnwind(db kv.RwDB, tx kv.RwTx) error { return nil } -func (s *Sync) RunNoInterrupt(db kv.RwDB, tx kv.RwTx, firstCycle bool) error { +func (s *Sync) RunNoInterrupt(db kv.RwDB, txc wrap.TxContainer, firstCycle bool) error { s.prevUnwindPoint = nil s.timings = s.timings[:0] @@ -268,7 +270,7 @@ func (s *Sync) RunNoInterrupt(db kv.RwDB, tx kv.RwTx, firstCycle bool) error { if s.unwindOrder[j] == nil || s.unwindOrder[j].Disabled || s.unwindOrder[j].Unwind == nil { continue } - if err := s.unwindStage(firstCycle, s.unwindOrder[j], db, tx); err != nil { + if err := s.unwindStage(firstCycle, s.unwindOrder[j], db, txc); err != nil { return err } } @@ -300,7 +302,7 @@ func (s *Sync) RunNoInterrupt(db kv.RwDB, tx kv.RwTx, firstCycle bool) error { continue } - if err := s.runStage(stage, db, tx, firstCycle, badBlockUnwind); err != nil { + if err := s.runStage(stage, db, txc, firstCycle, badBlockUnwind); err != nil { return err } @@ -325,7 +327,7 @@ func (s *Sync) RunNoInterrupt(db kv.RwDB, tx kv.RwTx, firstCycle bool) error { return nil } -func (s *Sync) Run(db kv.RwDB, tx kv.RwTx, firstCycle bool) (bool, error) { +func (s *Sync) Run(db kv.RwDB, txc wrap.TxContainer, firstCycle bool) (bool, error) { s.prevUnwindPoint = nil s.timings = s.timings[:0] @@ -338,7 +340,7 @@ func (s *Sync) Run(db kv.RwDB, tx kv.RwTx, firstCycle bool) (bool, error) { if s.unwindOrder[j] == nil || s.unwindOrder[j].Disabled || s.unwindOrder[j].Unwind == nil { continue } - if err := s.unwindStage(firstCycle, s.unwindOrder[j], db, tx); err != nil { + if err := s.unwindStage(firstCycle, s.unwindOrder[j], db, txc); err != nil { return false, err } } @@ -375,7 +377,7 @@ func (s *Sync) Run(db kv.RwDB, tx kv.RwTx, firstCycle bool) (bool, error) { continue } - if err := s.runStage(stage, db, tx, firstCycle, badBlockUnwind); err != nil { + if err := s.runStage(stage, db, txc, firstCycle, badBlockUnwind); err != nil { return false, err } @@ -387,7 +389,7 @@ func (s *Sync) Run(db kv.RwDB, tx kv.RwTx, firstCycle bool) (bool, error) { if string(stage.ID) == s.cfg.BreakAfterStage { // break process loop s.logger.Warn("--sync.loop.break.after caused stage break") if s.posTransition != nil { - ptx := tx + ptx := txc.Tx if ptx == nil { if tx, err := db.BeginRw(context.Background()); err == nil { @@ -490,14 +492,14 @@ func PrintTables(db kv.RoDB, tx kv.RwTx) []interface{} { return bucketSizes } -func (s *Sync) runStage(stage *Stage, db kv.RwDB, tx kv.RwTx, firstCycle bool, badBlockUnwind bool) (err error) { +func (s *Sync) runStage(stage *Stage, db kv.RwDB, txc wrap.TxContainer, firstCycle bool, badBlockUnwind bool) (err error) { start := time.Now() - stageState, err := s.StageState(stage.ID, tx, db) + stageState, err := s.StageState(stage.ID, txc.Tx, db) if err != nil { return err } - if err = stage.Forward(firstCycle, badBlockUnwind, stageState, s, tx, s.logger); err != nil { + if err = stage.Forward(firstCycle, badBlockUnwind, stageState, s, txc, s.logger); err != nil { wrappedError := fmt.Errorf("[%s] %w", s.LogPrefix(), err) s.logger.Debug("Error while executing stage", "err", wrappedError) return wrappedError @@ -514,10 +516,10 @@ func (s *Sync) runStage(stage *Stage, db kv.RwDB, tx kv.RwTx, firstCycle bool, b return nil } -func (s *Sync) unwindStage(firstCycle bool, stage *Stage, db kv.RwDB, tx kv.RwTx) error { +func (s *Sync) unwindStage(firstCycle bool, stage *Stage, db kv.RwDB, txc wrap.TxContainer) error { start := time.Now() s.logger.Trace("Unwind...", "stage", stage.ID) - stageState, err := s.StageState(stage.ID, tx, db) + stageState, err := s.StageState(stage.ID, txc.Tx, db) if err != nil { return err } @@ -533,7 +535,7 @@ func (s *Sync) unwindStage(firstCycle bool, stage *Stage, db kv.RwDB, tx kv.RwTx return err } - err = stage.Unwind(firstCycle, unwind, stageState, tx, s.logger) + err = stage.Unwind(firstCycle, unwind, stageState, txc, s.logger) if err != nil { return fmt.Errorf("[%s] %w", s.LogPrefix(), err) } diff --git a/eth/stagedsync/sync_test.go b/eth/stagedsync/sync_test.go index 48a6c475478..6324d72e060 100644 --- a/eth/stagedsync/sync_test.go +++ b/eth/stagedsync/sync_test.go @@ -5,8 +5,8 @@ import ( "fmt" "testing" - "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/memdb" + "github.com/ledgerwatch/erigon-lib/wrap" "github.com/ledgerwatch/log/v3" "github.com/stretchr/testify/assert" @@ -20,7 +20,7 @@ func TestStagesSuccess(t *testing.T) { { ID: stages.Headers, Description: "Downloading headers", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Headers) return nil }, @@ -28,7 +28,7 @@ func TestStagesSuccess(t *testing.T) { { ID: stages.Bodies, Description: "Downloading block bodiess", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Bodies) return nil }, @@ -36,7 +36,7 @@ func TestStagesSuccess(t *testing.T) { { ID: stages.Senders, Description: "Recovering senders from tx signatures", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Senders) return nil }, @@ -44,7 +44,7 @@ func TestStagesSuccess(t *testing.T) { } state := New(ethconfig.Defaults.Sync, s, nil, nil, log.New()) db, tx := memdb.NewTestTx(t) - _, err := state.Run(db, tx, true /* initialCycle */) + _, err := state.Run(db, wrap.TxContainer{Tx: tx}, true /* initialCycle */) assert.NoError(t, err) expectedFlow := []stages.SyncStage{ @@ -59,7 +59,7 @@ func TestDisabledStages(t *testing.T) { { ID: stages.Headers, Description: "Downloading headers", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Headers) return nil }, @@ -67,7 +67,7 @@ func TestDisabledStages(t *testing.T) { { ID: stages.Bodies, Description: "Downloading block bodiess", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Bodies) return nil }, @@ -76,7 +76,7 @@ func TestDisabledStages(t *testing.T) { { ID: stages.Senders, Description: "Recovering senders from tx signatures", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Senders) return nil }, @@ -84,7 +84,7 @@ func TestDisabledStages(t *testing.T) { } state := New(ethconfig.Defaults.Sync, s, nil, nil, log.New()) db, tx := memdb.NewTestTx(t) - _, err := state.Run(db, tx, true /* initialCycle */) + _, err := state.Run(db, wrap.TxContainer{Tx: tx}, true /* initialCycle */) assert.NoError(t, err) expectedFlow := []stages.SyncStage{ @@ -100,7 +100,7 @@ func TestErroredStage(t *testing.T) { { ID: stages.Headers, Description: "Downloading headers", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Headers) return nil }, @@ -108,7 +108,7 @@ func TestErroredStage(t *testing.T) { { ID: stages.Bodies, Description: "Downloading block bodiess", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Bodies) return expectedErr }, @@ -116,7 +116,7 @@ func TestErroredStage(t *testing.T) { { ID: stages.Senders, Description: "Recovering senders from tx signatures", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Senders) return nil }, @@ -124,7 +124,7 @@ func TestErroredStage(t *testing.T) { } state := New(ethconfig.Defaults.Sync, s, []stages.SyncStage{s[2].ID, s[1].ID, s[0].ID}, nil, log.New()) db, tx := memdb.NewTestTx(t) - _, err := state.Run(db, tx, true /* initialCycle */) + _, err := state.Run(db, wrap.TxContainer{Tx: tx}, true /* initialCycle */) assert.Equal(t, fmt.Errorf("[2/3 Bodies] %w", expectedErr), err) expectedFlow := []stages.SyncStage{ @@ -140,39 +140,39 @@ func TestUnwindSomeStagesBehindUnwindPoint(t *testing.T) { { ID: stages.Headers, Description: "Downloading headers", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Headers) if s.BlockNumber == 0 { - return s.Update(tx, 2000) + return s.Update(txc.Tx, 2000) } return nil }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, unwindOf(stages.Headers)) - return u.Done(tx) + return u.Done(txc.Tx) }, }, { ID: stages.Bodies, Description: "Downloading block bodiess", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Bodies) if s.BlockNumber == 0 { - return s.Update(tx, 1000) + return s.Update(txc.Tx, 1000) } return nil }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, unwindOf(stages.Bodies)) - return u.Done(tx) + return u.Done(txc.Tx) }, }, { ID: stages.Senders, Description: "Recovering senders from tx signatures", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { if s.BlockNumber == 0 { - if err := s.Update(tx, 1700); err != nil { + if err := s.Update(txc.Tx, 1700); err != nil { return err } } @@ -184,30 +184,30 @@ func TestUnwindSomeStagesBehindUnwindPoint(t *testing.T) { } return nil }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, unwindOf(stages.Senders)) - return u.Done(tx) + return u.Done(txc.Tx) }, }, { ID: stages.IntermediateHashes, Disabled: true, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.IntermediateHashes) if s.BlockNumber == 0 { - return s.Update(tx, 2000) + return s.Update(txc.Tx, 2000) } return nil }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, unwindOf(stages.IntermediateHashes)) - return u.Done(tx) + return u.Done(txc.Tx) }, }, } state := New(ethconfig.Defaults.Sync, s, []stages.SyncStage{s[3].ID, s[2].ID, s[1].ID, s[0].ID}, nil, log.New()) db, tx := memdb.NewTestTx(t) - _, err := state.Run(db, tx, true /* initialCycle */) + _, err := state.Run(db, wrap.TxContainer{Tx: tx}, true /* initialCycle */) assert.NoError(t, err) expectedFlow := []stages.SyncStage{ @@ -238,69 +238,69 @@ func TestUnwind(t *testing.T) { { ID: stages.Headers, Description: "Downloading headers", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Headers) if s.BlockNumber == 0 { - return s.Update(tx, 2000) + return s.Update(txc.Tx, 2000) } return nil }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, unwindOf(stages.Headers)) - return u.Done(tx) + return u.Done(txc.Tx) }, }, { ID: stages.Bodies, Description: "Downloading block bodiess", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Bodies) if s.BlockNumber == 0 { - return s.Update(tx, 2000) + return s.Update(txc.Tx, 2000) } return nil }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, unwindOf(stages.Bodies)) - return u.Done(tx) + return u.Done(txc.Tx) }, }, { ID: stages.Senders, Description: "Recovering senders from tx signatures", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Senders) if !unwound { unwound = true u.UnwindTo(500, UnwindReason{}) - return s.Update(tx, 3000) + return s.Update(txc.Tx, 3000) } return nil }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, unwindOf(stages.Senders)) - return u.Done(tx) + return u.Done(txc.Tx) }, }, { ID: stages.IntermediateHashes, Disabled: true, - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.IntermediateHashes) if s.BlockNumber == 0 { - return s.Update(tx, 2000) + return s.Update(txc.Tx, 2000) } return nil }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, unwindOf(stages.IntermediateHashes)) - return u.Done(tx) + return u.Done(txc.Tx) }, }, } state := New(ethconfig.Defaults.Sync, s, []stages.SyncStage{s[3].ID, s[2].ID, s[1].ID, s[0].ID}, nil, log.New()) db, tx := memdb.NewTestTx(t) - _, err := state.Run(db, tx, true /* initialCycle */) + _, err := state.Run(db, wrap.TxContainer{Tx: tx}, true /* initialCycle */) assert.NoError(t, err) expectedFlow := []stages.SyncStage{ @@ -327,7 +327,7 @@ func TestUnwind(t *testing.T) { flow = flow[:0] state.unwindOrder = []*Stage{s[3], s[2], s[1], s[0]} state.UnwindTo(100, UnwindReason{}) - _, err = state.Run(db, tx, true /* initialCycle */) + _, err = state.Run(db, wrap.TxContainer{Tx: tx}, true /* initialCycle */) assert.NoError(t, err) expectedFlow = []stages.SyncStage{ @@ -346,25 +346,25 @@ func TestUnwindEmptyUnwinder(t *testing.T) { { ID: stages.Headers, Description: "Downloading headers", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Headers) if s.BlockNumber == 0 { - return s.Update(tx, 2000) + return s.Update(txc.Tx, 2000) } return nil }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, unwindOf(stages.Headers)) - return u.Done(tx) + return u.Done(txc.Tx) }, }, { ID: stages.Bodies, Description: "Downloading block bodiess", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Bodies) if s.BlockNumber == 0 { - return s.Update(tx, 2000) + return s.Update(txc.Tx, 2000) } return nil }, @@ -372,24 +372,24 @@ func TestUnwindEmptyUnwinder(t *testing.T) { { ID: stages.Senders, Description: "Recovering senders from tx signatures", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Senders) if !unwound { unwound = true u.UnwindTo(500, UnwindReason{}) - return s.Update(tx, 3000) + return s.Update(txc.Tx, 3000) } return nil }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, unwindOf(stages.Senders)) - return u.Done(tx) + return u.Done(txc.Tx) }, }, } state := New(ethconfig.Defaults.Sync, s, []stages.SyncStage{s[2].ID, s[1].ID, s[0].ID}, nil, log.New()) db, tx := memdb.NewTestTx(t) - _, err := state.Run(db, tx, true /* initialCycle */) + _, err := state.Run(db, wrap.TxContainer{Tx: tx}, true /* initialCycle */) assert.NoError(t, err) expectedFlow := []stages.SyncStage{ @@ -420,36 +420,36 @@ func TestSyncDoTwice(t *testing.T) { { ID: stages.Headers, Description: "Downloading headers", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Headers) - return s.Update(tx, s.BlockNumber+100) + return s.Update(txc.Tx, s.BlockNumber+100) }, }, { ID: stages.Bodies, Description: "Downloading block bodiess", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Bodies) - return s.Update(tx, s.BlockNumber+200) + return s.Update(txc.Tx, s.BlockNumber+200) }, }, { ID: stages.Senders, Description: "Recovering senders from tx signatures", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Senders) - return s.Update(tx, s.BlockNumber+300) + return s.Update(txc.Tx, s.BlockNumber+300) }, }, } state := New(ethconfig.Defaults.Sync, s, nil, nil, log.New()) db, tx := memdb.NewTestTx(t) - _, err := state.Run(db, tx, true /* initialCycle */) + _, err := state.Run(db, wrap.TxContainer{Tx: tx}, true /* initialCycle */) assert.NoError(t, err) state = New(ethconfig.Defaults.Sync, s, nil, nil, log.New()) - _, err = state.Run(db, tx, true /* initialCycle */) + _, err = state.Run(db, wrap.TxContainer{Tx: tx}, true /* initialCycle */) assert.NoError(t, err) expectedFlow := []stages.SyncStage{ @@ -478,7 +478,7 @@ func TestStateSyncInterruptRestart(t *testing.T) { { ID: stages.Headers, Description: "Downloading headers", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Headers) return nil }, @@ -486,7 +486,7 @@ func TestStateSyncInterruptRestart(t *testing.T) { { ID: stages.Bodies, Description: "Downloading block bodiess", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Bodies) return expectedErr }, @@ -494,7 +494,7 @@ func TestStateSyncInterruptRestart(t *testing.T) { { ID: stages.Senders, Description: "Recovering senders from tx signatures", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Senders) return nil }, @@ -503,13 +503,13 @@ func TestStateSyncInterruptRestart(t *testing.T) { state := New(ethconfig.Defaults.Sync, s, nil, nil, log.New()) db, tx := memdb.NewTestTx(t) - _, err := state.Run(db, tx, true /* initialCycle */) + _, err := state.Run(db, wrap.TxContainer{Tx: tx}, true /* initialCycle */) assert.Equal(t, fmt.Errorf("[2/3 Bodies] %w", expectedErr), err) expectedErr = nil state = New(ethconfig.Defaults.Sync, s, nil, nil, log.New()) - _, err = state.Run(db, tx, true /* initialCycle */) + _, err = state.Run(db, wrap.TxContainer{Tx: tx}, true /* initialCycle */) assert.NoError(t, err) expectedFlow := []stages.SyncStage{ @@ -530,59 +530,59 @@ func TestSyncInterruptLongUnwind(t *testing.T) { { ID: stages.Headers, Description: "Downloading headers", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Headers) if s.BlockNumber == 0 { - return s.Update(tx, 2000) + return s.Update(txc.Tx, 2000) } return nil }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, unwindOf(stages.Headers)) - return u.Done(tx) + return u.Done(txc.Tx) }, }, { ID: stages.Bodies, Description: "Downloading block bodiess", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Bodies) if s.BlockNumber == 0 { - return s.Update(tx, 2000) + return s.Update(txc.Tx, 2000) } return nil }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, unwindOf(stages.Bodies)) - return u.Done(tx) + return u.Done(txc.Tx) }, }, { ID: stages.Senders, Description: "Recovering senders from tx signatures", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, stages.Senders) if !unwound { unwound = true u.UnwindTo(500, UnwindReason{}) - return s.Update(tx, 3000) + return s.Update(txc.Tx, 3000) } return nil }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { flow = append(flow, unwindOf(stages.Senders)) if !interrupted { interrupted = true return errInterrupted } assert.Equal(t, 500, int(u.UnwindPoint)) - return u.Done(tx) + return u.Done(txc.Tx) }, }, } state := New(ethconfig.Defaults.Sync, s, []stages.SyncStage{s[2].ID, s[1].ID, s[0].ID}, nil, log.New()) db, tx := memdb.NewTestTx(t) - _, err := state.Run(db, tx, true /* initialCycle */) + _, err := state.Run(db, wrap.TxContainer{Tx: tx}, true /* initialCycle */) assert.Error(t, errInterrupted, err) //state = NewState(s) @@ -590,7 +590,7 @@ func TestSyncInterruptLongUnwind(t *testing.T) { //err = state.LoadUnwindInfo(tx) //assert.NoError(t, err) //state.UnwindTo(500, libcommon.Hash{}) - _, err = state.Run(db, tx, true /* initialCycle */) + _, err = state.Run(db, wrap.TxContainer{Tx: tx}, true /* initialCycle */) assert.NoError(t, err) expectedFlow := []stages.SyncStage{ diff --git a/turbo/app/import_cmd.go b/turbo/app/import_cmd.go index 4b23fcf4e76..085b2dbb53c 100644 --- a/turbo/app/import_cmd.go +++ b/turbo/app/import_cmd.go @@ -12,6 +12,7 @@ import ( "syscall" "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon-lib/wrap" "github.com/ledgerwatch/erigon/turbo/services" "github.com/ledgerwatch/log/v3" "github.com/urfave/cli/v2" @@ -221,7 +222,7 @@ func InsertChain(ethereum *eth.Ethereum, chain *core.ChainPack, logger log.Logge blockReader, _ := ethereum.BlockIO() hook := stages.NewHook(ethereum.SentryCtx(), ethereum.ChainDB(), ethereum.Notifications(), ethereum.StagedSync(), blockReader, ethereum.ChainConfig(), logger, sentryControlServer.UpdateHead) - err := stages.StageLoopIteration(ethereum.SentryCtx(), ethereum.ChainDB(), nil, ethereum.StagedSync(), initialCycle, logger, blockReader, hook, false) + err := stages.StageLoopIteration(ethereum.SentryCtx(), ethereum.ChainDB(), wrap.TxContainer{}, ethereum.StagedSync(), initialCycle, logger, blockReader, hook, false) if err != nil { return err } diff --git a/turbo/engineapi/engine_helpers/fork_validator.go b/turbo/engineapi/engine_helpers/fork_validator.go index b0b12de0fdf..76902dcb0f4 100644 --- a/turbo/engineapi/engine_helpers/fork_validator.go +++ b/turbo/engineapi/engine_helpers/fork_validator.go @@ -24,13 +24,14 @@ import ( libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/membatchwithdb" + "github.com/ledgerwatch/erigon-lib/wrap" + "github.com/ledgerwatch/erigon/common/math" "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" "github.com/ledgerwatch/erigon/turbo/engineapi/engine_types" "github.com/ledgerwatch/erigon/turbo/services" "github.com/ledgerwatch/log/v3" - "github.com/ledgerwatch/erigon/common/math" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/turbo/shards" @@ -39,7 +40,7 @@ import ( // the maximum point from the current head, past which side forks are not validated anymore. const maxForkDepth = 32 // 32 slots is the duration of an epoch thus there cannot be side forks in PoS deeper than 32 blocks from head. -type validatePayloadFunc func(kv.RwTx, *types.Header, *types.RawBody, uint64, []*types.Header, []*types.RawBody, *shards.Notifications) error +type validatePayloadFunc func(wrap.TxContainer, *types.Header, *types.RawBody, uint64, []*types.Header, []*types.RawBody, *shards.Notifications) error type ForkValidator struct { // current memory batch containing chain head that extend canonical fork. @@ -152,6 +153,8 @@ func (fv *ForkValidator) ValidatePayload(tx kv.Tx, header *types.Header, body *t if extendCanonical { extendingFork := membatchwithdb.NewMemoryBatch(tx, fv.tmpDir, logger) defer extendingFork.Close() + var txc wrap.TxContainer + txc.Tx = extendingFork fv.extendingForkNotifications = &shards.Notifications{ Events: shards.NewEvents(), @@ -160,7 +163,7 @@ func (fv *ForkValidator) ValidatePayload(tx kv.Tx, header *types.Header, body *t // Update fork head hash. fv.extendingForkHeadHash = header.Hash() fv.extendingForkNumber = header.Number.Uint64() - status, latestValidHash, validationError, criticalError = fv.validateAndStorePayload(extendingFork, header, body, 0, nil, nil, fv.extendingForkNotifications) + status, latestValidHash, validationError, criticalError = fv.validateAndStorePayload(txc, header, body, 0, nil, nil, fv.extendingForkNotifications) if criticalError != nil { return } @@ -231,11 +234,13 @@ func (fv *ForkValidator) ValidatePayload(tx kv.Tx, header *types.Header, body *t } batch := membatchwithdb.NewMemoryBatch(tx, fv.tmpDir, logger) defer batch.Rollback() + var txc wrap.TxContainer + txc.Tx = batch notifications := &shards.Notifications{ Events: shards.NewEvents(), Accumulator: shards.NewAccumulator(), } - return fv.validateAndStorePayload(batch, header, body, unwindPoint, headersChain, bodiesChain, notifications) + return fv.validateAndStorePayload(txc, header, body, unwindPoint, headersChain, bodiesChain, notifications) } // Clear wipes out current extending fork data, this method is called after fcu is called, @@ -255,9 +260,9 @@ func (fv *ForkValidator) ClearWithUnwind(accumulator *shards.Accumulator, c shar } // validateAndStorePayload validate and store a payload fork chain if such chain results valid. -func (fv *ForkValidator) validateAndStorePayload(tx kv.RwTx, header *types.Header, body *types.RawBody, unwindPoint uint64, headersChain []*types.Header, bodiesChain []*types.RawBody, +func (fv *ForkValidator) validateAndStorePayload(txc wrap.TxContainer, header *types.Header, body *types.RawBody, unwindPoint uint64, headersChain []*types.Header, bodiesChain []*types.RawBody, notifications *shards.Notifications) (status engine_types.EngineStatus, latestValidHash libcommon.Hash, validationError error, criticalError error) { - if err := fv.validatePayload(tx, header, body, unwindPoint, headersChain, bodiesChain, notifications); err != nil { + if err := fv.validatePayload(txc, header, body, unwindPoint, headersChain, bodiesChain, notifications); err != nil { if errors.Is(err, consensus.ErrInvalidBlock) { validationError = err } else { @@ -269,11 +274,11 @@ func (fv *ForkValidator) validateAndStorePayload(tx kv.RwTx, header *types.Heade latestValidHash = header.Hash() if validationError != nil { var latestValidNumber uint64 - latestValidNumber, criticalError = stages.GetStageProgress(tx, stages.IntermediateHashes) + latestValidNumber, criticalError = stages.GetStageProgress(txc.Tx, stages.IntermediateHashes) if criticalError != nil { return } - latestValidHash, criticalError = rawdb.ReadCanonicalHash(tx, latestValidNumber) + latestValidHash, criticalError = rawdb.ReadCanonicalHash(txc.Tx, latestValidNumber) if criticalError != nil { return } @@ -287,7 +292,7 @@ func (fv *ForkValidator) validateAndStorePayload(tx kv.RwTx, header *types.Heade // If we do not have the body we can recover it from the batch. if body != nil { - if _, criticalError = rawdb.WriteRawBodyIfNotExists(tx, header.Hash(), header.Number.Uint64(), body); criticalError != nil { + if _, criticalError = rawdb.WriteRawBodyIfNotExists(txc.Tx, header.Hash(), header.Number.Uint64(), body); criticalError != nil { return } } diff --git a/turbo/execution/eth1/ethereum_execution.go b/turbo/execution/eth1/ethereum_execution.go index c8a6f6a2a04..1a367602192 100644 --- a/turbo/execution/eth1/ethereum_execution.go +++ b/turbo/execution/eth1/ethereum_execution.go @@ -9,6 +9,7 @@ import ( libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/gointerfaces" "github.com/ledgerwatch/erigon-lib/gointerfaces/execution" + "github.com/ledgerwatch/erigon-lib/wrap" "github.com/ledgerwatch/log/v3" "golang.org/x/sync/semaphore" "google.golang.org/protobuf/types/known/emptypb" @@ -235,7 +236,7 @@ func (e *EthereumExecutionModule) Start(ctx context.Context) { for more { var err error - if more, err = e.executionPipeline.Run(e.db, nil, true); err != nil { + if more, err = e.executionPipeline.Run(e.db, wrap.TxContainer{}, true); err != nil { if !errors.Is(err, context.Canceled) { e.logger.Error("Could not start execution service", "err", err) } diff --git a/turbo/execution/eth1/forkchoice.go b/turbo/execution/eth1/forkchoice.go index 574735846c6..baaaf065b36 100644 --- a/turbo/execution/eth1/forkchoice.go +++ b/turbo/execution/eth1/forkchoice.go @@ -10,6 +10,7 @@ import ( "github.com/ledgerwatch/erigon-lib/gointerfaces/execution" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/rawdbv3" + "github.com/ledgerwatch/erigon-lib/wrap" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/eth/stagedsync" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" @@ -234,7 +235,7 @@ func (e *EthereumExecutionModule) updateForkChoice(ctx context.Context, blockHas } // Run the unwind - if err := e.executionPipeline.RunUnwind(e.db, tx); err != nil { + if err := e.executionPipeline.RunUnwind(e.db, wrap.TxContainer{Tx: tx}); err != nil { err = fmt.Errorf("updateForkChoice: %w", err) sendForkchoiceErrorWithoutWaiting(outcomeCh, err) return @@ -305,7 +306,7 @@ func (e *EthereumExecutionModule) updateForkChoice(ctx context.Context, blockHas } } // Run the forkchoice - if _, err := e.executionPipeline.Run(e.db, tx, false); err != nil { + if _, err := e.executionPipeline.Run(e.db, wrap.TxContainer{Tx: tx}, false); err != nil { err = fmt.Errorf("updateForkChoice: %w", err) sendForkchoiceErrorWithoutWaiting(outcomeCh, err) return diff --git a/turbo/execution/eth1/inserters.go b/turbo/execution/eth1/inserters.go index 368a75a3f07..c49a34de86a 100644 --- a/turbo/execution/eth1/inserters.go +++ b/turbo/execution/eth1/inserters.go @@ -29,8 +29,9 @@ func (e *EthereumExecutionModule) InsertBlocks(ctx context.Context, req *executi return nil, fmt.Errorf("ethereumExecutionModule.InsertBlocks: cannot convert headers: %s", err) } body := eth1_utils.ConvertRawBlockBodyFromRpc(block.Body) + height := header.Number.Uint64() // Parent's total difficulty - parentTd, err := rawdb.ReadTd(tx, header.ParentHash, header.Number.Uint64()-1) + parentTd, err := rawdb.ReadTd(tx, header.ParentHash, height-1) if err != nil || parentTd == nil { return nil, fmt.Errorf("parent's total difficulty not found with hash %x and height %d: %v", header.ParentHash, header.Number.Uint64()-1, err) } @@ -38,13 +39,13 @@ func (e *EthereumExecutionModule) InsertBlocks(ctx context.Context, req *executi // Sum TDs. td := parentTd.Add(parentTd, header.Difficulty) if err := rawdb.WriteHeader(tx, header); err != nil { - return nil, fmt.Errorf("ethereumExecutionModule.InsertHeaders: could not insert: %s", err) + return nil, fmt.Errorf("ethereumExecutionModule.InsertHeaders: writeHeader: %s", err) } - if err := rawdb.WriteTd(tx, header.Hash(), header.Number.Uint64(), td); err != nil { - return nil, fmt.Errorf("ethereumExecutionModule.InsertHeaders: could not insert: %s", err) + if err := rawdb.WriteTd(tx, header.Hash(), height, td); err != nil { + return nil, fmt.Errorf("ethereumExecutionModule.InsertHeaders: writeTd: %s", err) } - if _, err := rawdb.WriteRawBodyIfNotExists(tx, header.Hash(), header.Number.Uint64(), body); err != nil { - return nil, fmt.Errorf("ethereumExecutionModule.InsertBlocks: could not insert: %s", err) + if _, err := rawdb.WriteRawBodyIfNotExists(tx, header.Hash(), height, body); err != nil { + return nil, fmt.Errorf("ethereumExecutionModule.InsertBlocks: writeBody: %s", err) } } if err := tx.Commit(); err != nil { diff --git a/turbo/jsonrpc/eth_subscribe_test.go b/turbo/jsonrpc/eth_subscribe_test.go index 26e67192516..25b252ef67e 100644 --- a/turbo/jsonrpc/eth_subscribe_test.go +++ b/turbo/jsonrpc/eth_subscribe_test.go @@ -8,6 +8,7 @@ import ( libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/direct" "github.com/ledgerwatch/erigon-lib/gointerfaces/sentry" + "github.com/ledgerwatch/erigon-lib/wrap" "github.com/stretchr/testify/require" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/rpcservices" @@ -55,7 +56,7 @@ func TestEthSubscribe(t *testing.T) { highestSeenHeader := chain.TopBlock.NumberU64() hook := stages.NewHook(m.Ctx, m.DB, m.Notifications, m.Sync, m.BlockReader, m.ChainConfig, m.Log, m.UpdateHead) - if err := stages.StageLoopIteration(m.Ctx, m.DB, nil, m.Sync, initialCycle, logger, m.BlockReader, hook, false); err != nil { + if err := stages.StageLoopIteration(m.Ctx, m.DB, wrap.TxContainer{}, m.Sync, initialCycle, logger, m.BlockReader, hook, false); err != nil { t.Fatal(err) } diff --git a/turbo/jsonrpc/send_transaction_test.go b/turbo/jsonrpc/send_transaction_test.go index f4b4c2a3efb..b0e1f736ae6 100644 --- a/turbo/jsonrpc/send_transaction_test.go +++ b/turbo/jsonrpc/send_transaction_test.go @@ -10,6 +10,7 @@ import ( "github.com/holiman/uint256" "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/txpool/txpoolcfg" + "github.com/ledgerwatch/erigon-lib/wrap" "github.com/ledgerwatch/erigon-lib/gointerfaces/sentry" "github.com/ledgerwatch/erigon-lib/gointerfaces/txpool" @@ -70,7 +71,7 @@ func oneBlockStep(mockSentry *mock.MockSentry, require *require.Assertions, t *t mockSentry.ReceiveWg.Wait() // Wait for all messages to be processed before we proceed initialCycle := mock.MockInsertAsInitialCycle - if err := stages.StageLoopIteration(mockSentry.Ctx, mockSentry.DB, nil, mockSentry.Sync, initialCycle, log.New(), mockSentry.BlockReader, nil, false); err != nil { + if err := stages.StageLoopIteration(mockSentry.Ctx, mockSentry.DB, wrap.TxContainer{}, mockSentry.Sync, initialCycle, log.New(), mockSentry.BlockReader, nil, false); err != nil { t.Fatal(err) } } diff --git a/turbo/stages/mock/mock_sentry.go b/turbo/stages/mock/mock_sentry.go index c65625117a8..f6da6c474ae 100644 --- a/turbo/stages/mock/mock_sentry.go +++ b/turbo/stages/mock/mock_sentry.go @@ -33,6 +33,7 @@ import ( "github.com/ledgerwatch/erigon-lib/txpool" "github.com/ledgerwatch/erigon-lib/txpool/txpoolcfg" types2 "github.com/ledgerwatch/erigon-lib/types" + "github.com/ledgerwatch/erigon-lib/wrap" "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/consensus/bor" @@ -343,20 +344,20 @@ func MockWithEverything(tb testing.TB, gspec *types.Genesis, key *ecdsa.PrivateK } latestBlockBuiltStore := builder.NewLatestBlockBuiltStore() - inMemoryExecution := func(batch kv.RwTx, header *types.Header, body *types.RawBody, unwindPoint uint64, headersChain []*types.Header, bodiesChain []*types.RawBody, + inMemoryExecution := func(txc wrap.TxContainer, header *types.Header, body *types.RawBody, unwindPoint uint64, headersChain []*types.Header, bodiesChain []*types.RawBody, notifications *shards.Notifications) error { terseLogger := log.New() terseLogger.SetHandler(log.LvlFilterHandler(log.LvlWarn, log.StderrHandler)) // Needs its own notifications to not update RPC daemon and txpool about pending blocks stateSync := stages2.NewInMemoryExecution(mock.Ctx, mock.DB, &cfg, mock.sentriesClient, dirs, notifications, mock.BlockReader, blockWriter, mock.agg, nil, terseLogger) - chainReader := stagedsync.NewChainReaderImpl(mock.ChainConfig, batch, mock.BlockReader, logger) + chainReader := stagedsync.NewChainReaderImpl(mock.ChainConfig, txc.Tx, mock.BlockReader, logger) // We start the mining step - if err := stages2.StateStep(ctx, chainReader, mock.Engine, batch, blockWriter, stateSync, mock.sentriesClient.Bd, header, body, unwindPoint, headersChain, bodiesChain, histV3); err != nil { + if err := stages2.StateStep(ctx, chainReader, mock.Engine, txc, blockWriter, stateSync, mock.sentriesClient.Bd, header, body, unwindPoint, headersChain, bodiesChain, histV3); err != nil { logger.Warn("Could not validate block", "err", err) return err } - progress, err := stages.GetStageProgress(batch, stages.IntermediateHashes) + progress, err := stages.GetStageProgress(txc.Tx, stages.IntermediateHashes) if err != nil { return err } @@ -664,7 +665,7 @@ func (ms *MockSentry) insertPoWBlocks(chain *core.ChainPack) error { initialCycle := MockInsertAsInitialCycle hook := stages2.NewHook(ms.Ctx, ms.DB, ms.Notifications, ms.Sync, ms.BlockReader, ms.ChainConfig, ms.Log, ms.UpdateHead) - if err = stages2.StageLoopIteration(ms.Ctx, ms.DB, nil, ms.Sync, initialCycle, ms.Log, ms.BlockReader, hook, false); err != nil { + if err = stages2.StageLoopIteration(ms.Ctx, ms.DB, wrap.TxContainer{}, ms.Sync, initialCycle, ms.Log, ms.BlockReader, hook, false); err != nil { return err } if ms.TxPool != nil { diff --git a/turbo/stages/mock/sentry_mock_test.go b/turbo/stages/mock/sentry_mock_test.go index e8d95a4256c..c03baff9086 100644 --- a/turbo/stages/mock/sentry_mock_test.go +++ b/turbo/stages/mock/sentry_mock_test.go @@ -7,6 +7,7 @@ import ( "github.com/holiman/uint256" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/gointerfaces/sentry" + "github.com/ledgerwatch/erigon-lib/wrap" "github.com/ledgerwatch/log/v3" "github.com/stretchr/testify/require" @@ -58,7 +59,7 @@ func TestHeaderStep(t *testing.T) { m.ReceiveWg.Wait() // Wait for all messages to be processed before we proceed initialCycle := mock.MockInsertAsInitialCycle - if err := stages.StageLoopIteration(m.Ctx, m.DB, nil, m.Sync, initialCycle, m.Log, m.BlockReader, nil, false); err != nil { + if err := stages.StageLoopIteration(m.Ctx, m.DB, wrap.TxContainer{}, m.Sync, initialCycle, m.Log, m.BlockReader, nil, false); err != nil { t.Fatal(err) } } @@ -97,7 +98,7 @@ func TestMineBlockWith1Tx(t *testing.T) { m.ReceiveWg.Wait() // Wait for all messages to be processed before we proceeed initialCycle := mock.MockInsertAsInitialCycle - if err := stages.StageLoopIteration(m.Ctx, m.DB, nil, m.Sync, initialCycle, log.New(), m.BlockReader, nil, false); err != nil { + if err := stages.StageLoopIteration(m.Ctx, m.DB, wrap.TxContainer{}, m.Sync, initialCycle, log.New(), m.BlockReader, nil, false); err != nil { t.Fatal(err) } } @@ -166,7 +167,7 @@ func TestReorg(t *testing.T) { m.ReceiveWg.Wait() // Wait for all messages to be processed before we proceeed initialCycle := mock.MockInsertAsInitialCycle - if err := stages.StageLoopIteration(m.Ctx, m.DB, nil, m.Sync, initialCycle, m.Log, m.BlockReader, nil, false); err != nil { + if err := stages.StageLoopIteration(m.Ctx, m.DB, wrap.TxContainer{}, m.Sync, initialCycle, m.Log, m.BlockReader, nil, false); err != nil { t.Fatal(err) } @@ -219,7 +220,7 @@ func TestReorg(t *testing.T) { m.ReceiveWg.Wait() // Wait for all messages to be processed before we proceeed initialCycle = false - if err := stages.StageLoopIteration(m.Ctx, m.DB, nil, m.Sync, initialCycle, m.Log, m.BlockReader, nil, false); err != nil { + if err := stages.StageLoopIteration(m.Ctx, m.DB, wrap.TxContainer{}, m.Sync, initialCycle, m.Log, m.BlockReader, nil, false); err != nil { t.Fatal(err) } @@ -262,7 +263,7 @@ func TestReorg(t *testing.T) { m.ReceiveWg.Wait() // Wait for all messages to be processed before we proceeed // This is unwind step - if err := stages.StageLoopIteration(m.Ctx, m.DB, nil, m.Sync, initialCycle, m.Log, m.BlockReader, nil, false); err != nil { + if err := stages.StageLoopIteration(m.Ctx, m.DB, wrap.TxContainer{}, m.Sync, initialCycle, m.Log, m.BlockReader, nil, false); err != nil { t.Fatal(err) } @@ -299,7 +300,7 @@ func TestReorg(t *testing.T) { m.ReceiveWg.Wait() // Wait for all messages to be processed before we proceeed initialCycle = mock.MockInsertAsInitialCycle - if err := stages.StageLoopIteration(m.Ctx, m.DB, nil, m.Sync, initialCycle, m.Log, m.BlockReader, nil, false); err != nil { + if err := stages.StageLoopIteration(m.Ctx, m.DB, wrap.TxContainer{}, m.Sync, initialCycle, m.Log, m.BlockReader, nil, false); err != nil { t.Fatal(err) } } @@ -396,7 +397,7 @@ func TestAnchorReplace(t *testing.T) { m.ReceiveWg.Wait() // Wait for all messages to be processed before we proceeed initialCycle := mock.MockInsertAsInitialCycle - if err := stages.StageLoopIteration(m.Ctx, m.DB, nil, m.Sync, initialCycle, m.Log, m.BlockReader, nil, false); err != nil { + if err := stages.StageLoopIteration(m.Ctx, m.DB, wrap.TxContainer{}, m.Sync, initialCycle, m.Log, m.BlockReader, nil, false); err != nil { t.Fatal(err) } } @@ -502,7 +503,7 @@ func TestAnchorReplace2(t *testing.T) { initialCycle := mock.MockInsertAsInitialCycle hook := stages.NewHook(m.Ctx, m.DB, m.Notifications, m.Sync, m.BlockReader, m.ChainConfig, m.Log, m.UpdateHead) - if err := stages.StageLoopIteration(m.Ctx, m.DB, nil, m.Sync, initialCycle, m.Log, m.BlockReader, hook, false); err != nil { + if err := stages.StageLoopIteration(m.Ctx, m.DB, wrap.TxContainer{}, m.Sync, initialCycle, m.Log, m.BlockReader, hook, false); err != nil { t.Fatal(err) } } diff --git a/turbo/stages/stageloop.go b/turbo/stages/stageloop.go index ae2453afd60..18537dc68fd 100644 --- a/turbo/stages/stageloop.go +++ b/turbo/stages/stageloop.go @@ -19,6 +19,7 @@ import ( "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/membatchwithdb" "github.com/ledgerwatch/erigon-lib/state" + "github.com/ledgerwatch/erigon-lib/wrap" "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/consensus/bor" @@ -68,7 +69,7 @@ func StageLoop(ctx context.Context, } // Estimate the current top height seen from the peer - err := StageLoopIteration(ctx, db, nil, sync, initialCycle, logger, blockReader, hook, forcePartialCommit) + err := StageLoopIteration(ctx, db, wrap.TxContainer{}, sync, initialCycle, logger, blockReader, hook, forcePartialCommit) if err != nil { if errors.Is(err, libcommon.ErrStopped) || errors.Is(err, context.Canceled) { @@ -99,15 +100,15 @@ func StageLoop(ctx context.Context, } } -func StageLoopIteration(ctx context.Context, db kv.RwDB, tx kv.RwTx, sync *stagedsync.Sync, initialCycle bool, logger log.Logger, blockReader services.FullBlockReader, hook *Hook, forcePartialCommit bool) (err error) { +func StageLoopIteration(ctx context.Context, db kv.RwDB, txc wrap.TxContainer, sync *stagedsync.Sync, initialCycle bool, logger log.Logger, blockReader services.FullBlockReader, hook *Hook, forcePartialCommit bool) (err error) { defer func() { if rec := recover(); rec != nil { err = fmt.Errorf("%+v, trace: %s", rec, dbg.Stack()) } }() // avoid crash because Erigon's core does many things - externalTx := tx != nil - finishProgressBefore, borProgressBefore, headersProgressBefore, err := stagesHeadersAndFinish(db, tx) + externalTx := txc.Tx != nil + finishProgressBefore, borProgressBefore, headersProgressBefore, err := stagesHeadersAndFinish(db, txc.Tx) if err != nil { return err } @@ -134,19 +135,19 @@ func StageLoopIteration(ctx context.Context, db kv.RwDB, tx kv.RwTx, sync *stage // - Prune(limited time)+Commit(sync). Write to disk happening here. if canRunCycleInOneTransaction && !externalTx { - tx, err = db.BeginRwNosync(ctx) + txc.Tx, err = db.BeginRwNosync(ctx) if err != nil { return err } - defer tx.Rollback() + defer txc.Tx.Rollback() } if hook != nil { - if err = hook.BeforeRun(tx, isSynced); err != nil { + if err = hook.BeforeRun(txc.Tx, isSynced); err != nil { return err } } - _, err = sync.Run(db, tx, initialCycle) + _, err = sync.Run(db, txc, initialCycle) if err != nil { return err } @@ -154,10 +155,10 @@ func StageLoopIteration(ctx context.Context, db kv.RwDB, tx kv.RwTx, sync *stage var tableSizes []interface{} var commitTime time.Duration if canRunCycleInOneTransaction && !externalTx { - tableSizes = stagedsync.PrintTables(db, tx) // Need to do this before commit to access tx + tableSizes = stagedsync.PrintTables(db, txc.Tx) // Need to do this before commit to access tx commitStart := time.Now() - errTx := tx.Commit() - tx = nil + errTx := txc.Tx.Commit() + txc.Tx = nil if errTx != nil { return errTx } @@ -166,7 +167,7 @@ func StageLoopIteration(ctx context.Context, db kv.RwDB, tx kv.RwTx, sync *stage // -- send notifications START if hook != nil { - if err = hook.AfterRun(tx, finishProgressBefore); err != nil { + if err = hook.AfterRun(txc.Tx, finishProgressBefore); err != nil { return err } } @@ -182,7 +183,7 @@ func StageLoopIteration(ctx context.Context, db kv.RwDB, tx kv.RwTx, sync *stage // -- send notifications END // -- Prune+commit(sync) - if err := stageLoopStepPrune(ctx, db, tx, sync, initialCycle); err != nil { + if err := stageLoopStepPrune(ctx, db, txc.Tx, sync, initialCycle); err != nil { return err } @@ -348,8 +349,9 @@ func MiningStep(ctx context.Context, kv kv.RwDB, mining *stagedsync.Sync, tmpDir miningBatch := membatchwithdb.NewMemoryBatch(tx, tmpDir, logger) defer miningBatch.Rollback() + txc := wrap.TxContainer{Tx: miningBatch} - if _, err = mining.Run(nil, miningBatch, false /* firstCycle */); err != nil { + if _, err = mining.Run(nil, txc, false /* firstCycle */); err != nil { return err } tx.Rollback() @@ -373,18 +375,20 @@ func addAndVerifyBlockStep(batch kv.RwTx, engine consensus.Engine, chainReader c if err := rawdb.WriteHeader(batch, currentHeader); err != nil { return err } + prevHash, err := rawdb.ReadCanonicalHash(batch, currentHeight) + if err != nil { + return err + } if err := rawdb.WriteCanonicalHash(batch, currentHash, currentHeight); err != nil { return err } if err := rawdb.WriteHeadHeaderHash(batch, currentHash); err != nil { return err } - var ok bool - var err error - if ok, err = rawdb.WriteRawBodyIfNotExists(batch, currentHash, currentHeight, currentBody); err != nil { + if _, err := rawdb.WriteRawBodyIfNotExists(batch, currentHash, currentHeight, currentBody); err != nil { return err } - if histV3 && ok { + if histV3 && prevHash != currentHash { if err := rawdb.AppendCanonicalTxNums(batch, currentHeight); err != nil { return err } @@ -398,7 +402,7 @@ func addAndVerifyBlockStep(batch kv.RwTx, engine consensus.Engine, chainReader c return nil } -func StateStep(ctx context.Context, chainReader consensus.ChainReader, engine consensus.Engine, batch kv.RwTx, blockWriter *blockio.BlockWriter, stateSync *stagedsync.Sync, Bd *bodydownload.BodyDownload, header *types.Header, body *types.RawBody, unwindPoint uint64, headersChain []*types.Header, bodiesChain []*types.RawBody, histV3 bool) (err error) { +func StateStep(ctx context.Context, chainReader consensus.ChainReader, engine consensus.Engine, txc wrap.TxContainer, blockWriter *blockio.BlockWriter, stateSync *stagedsync.Sync, Bd *bodydownload.BodyDownload, header *types.Header, body *types.RawBody, unwindPoint uint64, headersChain []*types.Header, bodiesChain []*types.RawBody, histV3 bool) (err error) { defer func() { if rec := recover(); rec != nil { err = fmt.Errorf("%+v, trace: %s", rec, dbg.Stack()) @@ -409,11 +413,11 @@ func StateStep(ctx context.Context, chainReader consensus.ChainReader, engine co if unwindPoint > 0 { // Run it through the unwind stateSync.UnwindTo(unwindPoint, stagedsync.StagedUnwind) - if err = stateSync.RunUnwind(nil, batch); err != nil { + if err = stateSync.RunUnwind(nil, txc); err != nil { return err } } - if err := rawdb.TruncateCanonicalChain(ctx, batch, header.Number.Uint64()+1); err != nil { + if err := rawdb.TruncateCanonicalChain(ctx, txc.Tx, header.Number.Uint64()+1); err != nil { return err } // Once we unwound we can start constructing the chain (assumption: len(headersChain) == len(bodiesChain)) @@ -421,11 +425,11 @@ func StateStep(ctx context.Context, chainReader consensus.ChainReader, engine co currentHeader := headersChain[i] currentBody := bodiesChain[i] - if err := addAndVerifyBlockStep(batch, engine, chainReader, currentHeader, currentBody, histV3); err != nil { + if err := addAndVerifyBlockStep(txc.Tx, engine, chainReader, currentHeader, currentBody, histV3); err != nil { return err } // Run state sync - if err = stateSync.RunNoInterrupt(nil, batch, false /* firstCycle */); err != nil { + if err = stateSync.RunNoInterrupt(nil, txc, false /* firstCycle */); err != nil { return err } } @@ -435,11 +439,11 @@ func StateStep(ctx context.Context, chainReader consensus.ChainReader, engine co return nil } // Prepare memory state for block execution - if err := addAndVerifyBlockStep(batch, engine, chainReader, header, body, histV3); err != nil { + if err := addAndVerifyBlockStep(txc.Tx, engine, chainReader, header, body, histV3); err != nil { return err } // Run state sync - if err = stateSync.RunNoInterrupt(nil, batch, false /* firstCycle */); err != nil { + if err = stateSync.RunNoInterrupt(nil, txc, false /* firstCycle */); err != nil { return err } return nil From 302f1f772ddb24718f5b8462d292dc3a7d9ed4f8 Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Tue, 9 Jan 2024 11:49:04 +0100 Subject: [PATCH 24/92] ci: run macOS jobs on macos-13 instead of macos-13-xlarge (#9177) macos-13-xlarge was needed to use M1 CPU, because previously silkworm-go didn't have macOS Intel support --- .github/workflows/ci.yml | 5 ++++- .github/workflows/qa-clean-exit.yml | 5 ----- .github/workflows/test-integration.yml | 5 ++++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 82267c6fc31..85bac657092 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,10 @@ jobs: if: ${{ github.event_name == 'push' || !github.event.pull_request.draft }} strategy: matrix: - os: [ ubuntu-22.04, macos-13-xlarge ] # list of os: https://github.com/actions/virtual-environments + # list of os: https://github.com/actions/virtual-environments + os: + - ubuntu-22.04 + - macos-13 runs-on: ${{ matrix.os }} steps: diff --git a/.github/workflows/qa-clean-exit.yml b/.github/workflows/qa-clean-exit.yml index 51198fcc606..ace204be27e 100644 --- a/.github/workflows/qa-clean-exit.yml +++ b/.github/workflows/qa-clean-exit.yml @@ -19,11 +19,6 @@ on: jobs: long-running-test: - #if: ${{ github.event_name == 'push' || !github.event.pull_request.draft }} - #strategy: - # matrix: - # os: [ ubuntu-22.04, macos-13-xlarge ] - #runs-on: ${{ matrix.os }} runs-on: self-hosted env: ERIGON_DATA_DIR: ${{ github.workspace }}/erigon_data diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml index 22e68e3fa0f..40564d2af16 100644 --- a/.github/workflows/test-integration.yml +++ b/.github/workflows/test-integration.yml @@ -13,7 +13,10 @@ jobs: tests: strategy: matrix: - os: [ ubuntu-22.04, macos-13-xlarge ] # list of os: https://github.com/actions/virtual-environments + # list of os: https://github.com/actions/virtual-environments + os: + - ubuntu-22.04 + - macos-13 runs-on: ${{ matrix.os }} steps: From 74ec3a9db7422cace2e949870f028e7e9a3b2fc5 Mon Sep 17 00:00:00 2001 From: milen <94537774+taratorio@users.noreply.github.com> Date: Tue, 9 Jan 2024 11:37:39 +0000 Subject: [PATCH 25/92] stagedsync: fix bor heimdall mining flow (#9149) Currently the mining loop is broken for the polygon chain. This PR fixes this. High level changes: - Introduces new Bor<->Heimdall stage specifically for the needs of the mining flow - Extracts out common logic from Bor<->Heimdall sync and mining stages into shared functions - Removes `mine` flag for the Bor<->Heimdall sync stage - Extends the current `StartMining` function to prefetch span zero if needed before the mining loop is started - Fixes Bor to read span zero (instead of span 1) from heimdall when the span is not initially set in the local smart contract that the Spanner uses Test with devnet "state-sync" scenario: ![Screenshot 2024-01-05 at 17 41 23](https://github.com/ledgerwatch/erigon/assets/94537774/34ca903a-69b8-416a-900f-a32f2d4417fa) --- consensus/bor/bor.go | 24 +- eth/backend.go | 74 +-- eth/stagedsync/bor_heimdall_shared.go | 313 +++++++++++++ eth/stagedsync/default_stages.go | 5 +- eth/stagedsync/stage_bor_heimdall.go | 480 ++++++-------------- eth/stagedsync/stage_mining_bor_heimdall.go | 89 ++++ eth/stagedsync/stagebuilder.go | 9 +- eth/stagedsync/stages/stages.go | 1 + 8 files changed, 587 insertions(+), 408 deletions(-) create mode 100644 eth/stagedsync/bor_heimdall_shared.go create mode 100644 eth/stagedsync/stage_mining_bor_heimdall.go diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index aa62d4fffa0..e20f172087e 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -1271,37 +1271,23 @@ func (c *Bor) checkAndCommitSpan( ) error { headerNumber := header.Number.Uint64() - span, err := c.spanner.GetCurrentSpan(syscall) + currentSpan, err := c.spanner.GetCurrentSpan(syscall) if err != nil { return err } - if c.needToCommitSpan(span, headerNumber) { - err := c.fetchAndCommitSpan(span.ID+1, state, header, chain, syscall) - return err - } - - return nil -} - -func (c *Bor) needToCommitSpan(currentSpan *span.Span, headerNumber uint64) bool { - // if span is nil - if currentSpan == nil { - return false - } - // check span is not set initially if currentSpan.EndBlock == 0 { - return true + return c.fetchAndCommitSpan(currentSpan.ID, state, header, chain, syscall) } - sprintLength := c.config.CalculateSprintLength(headerNumber) // if current block is first block of last sprint in current span + sprintLength := c.config.CalculateSprintLength(headerNumber) if currentSpan.EndBlock > sprintLength && currentSpan.EndBlock-sprintLength+1 == headerNumber { - return true + return c.fetchAndCommitSpan(currentSpan.ID+1, state, header, chain, syscall) } - return false + return nil } func (c *Bor) fetchAndCommitSpan( diff --git a/eth/backend.go b/eth/backend.go index bfc1fce3dad..dbfca093cb1 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -32,39 +32,6 @@ import ( "time" lru "github.com/hashicorp/golang-lru/arc/v2" - - "github.com/ledgerwatch/erigon-lib/chain/networkname" - "github.com/ledgerwatch/erigon-lib/chain/snapcfg" - "github.com/ledgerwatch/erigon-lib/diagnostics" - "github.com/ledgerwatch/erigon-lib/downloader/downloadergrpc" - "github.com/ledgerwatch/erigon-lib/kv/kvcfg" - "github.com/ledgerwatch/erigon-lib/wrap" - "github.com/ledgerwatch/erigon/cl/clparams" - "github.com/ledgerwatch/erigon/cl/cltypes" - "github.com/ledgerwatch/erigon/cl/fork" - "github.com/ledgerwatch/erigon/cl/persistence" - "github.com/ledgerwatch/erigon/cl/persistence/db_config" - "github.com/ledgerwatch/erigon/cl/persistence/format/snapshot_format/getters" - clcore "github.com/ledgerwatch/erigon/cl/phase1/core" - "github.com/ledgerwatch/erigon/cl/phase1/execution_client" - "github.com/ledgerwatch/erigon/cl/sentinel" - "github.com/ledgerwatch/erigon/cl/sentinel/service" - - "github.com/ledgerwatch/erigon/core/rawdb/blockio" - "github.com/ledgerwatch/erigon/ethdb/prune" - "github.com/ledgerwatch/erigon/p2p/sentry" - "github.com/ledgerwatch/erigon/p2p/sentry/sentry_multi_client" - "github.com/ledgerwatch/erigon/turbo/builder" - "github.com/ledgerwatch/erigon/turbo/engineapi" - "github.com/ledgerwatch/erigon/turbo/engineapi/engine_block_downloader" - "github.com/ledgerwatch/erigon/turbo/engineapi/engine_helpers" - "github.com/ledgerwatch/erigon/turbo/execution/eth1" - "github.com/ledgerwatch/erigon/turbo/execution/eth1/eth1_chain_reader.go" - "github.com/ledgerwatch/erigon/turbo/jsonrpc" - "github.com/ledgerwatch/erigon/turbo/silkworm" - "github.com/ledgerwatch/erigon/turbo/snapshotsync/freezeblocks" - "github.com/ledgerwatch/erigon/turbo/snapshotsync/snap" - "github.com/holiman/uint256" "github.com/ledgerwatch/log/v3" "golang.org/x/exp/slices" @@ -73,30 +40,44 @@ import ( "google.golang.org/protobuf/types/known/emptypb" "github.com/ledgerwatch/erigon-lib/chain" + "github.com/ledgerwatch/erigon-lib/chain/networkname" + "github.com/ledgerwatch/erigon-lib/chain/snapcfg" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/datadir" + "github.com/ledgerwatch/erigon-lib/diagnostics" "github.com/ledgerwatch/erigon-lib/direct" - downloader "github.com/ledgerwatch/erigon-lib/downloader" + "github.com/ledgerwatch/erigon-lib/downloader" "github.com/ledgerwatch/erigon-lib/downloader/downloadercfg" + "github.com/ledgerwatch/erigon-lib/downloader/downloadergrpc" proto_downloader "github.com/ledgerwatch/erigon-lib/gointerfaces/downloader" "github.com/ledgerwatch/erigon-lib/gointerfaces/grpcutil" "github.com/ledgerwatch/erigon-lib/gointerfaces/remote" + rpcsentinel "github.com/ledgerwatch/erigon-lib/gointerfaces/sentinel" proto_sentry "github.com/ledgerwatch/erigon-lib/gointerfaces/sentry" txpool_proto "github.com/ledgerwatch/erigon-lib/gointerfaces/txpool" prototypes "github.com/ledgerwatch/erigon-lib/gointerfaces/types" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/kvcache" + "github.com/ledgerwatch/erigon-lib/kv/kvcfg" "github.com/ledgerwatch/erigon-lib/kv/remotedbserver" libstate "github.com/ledgerwatch/erigon-lib/state" "github.com/ledgerwatch/erigon-lib/txpool" "github.com/ledgerwatch/erigon-lib/txpool/txpooluitl" types2 "github.com/ledgerwatch/erigon-lib/types" - + "github.com/ledgerwatch/erigon-lib/wrap" + "github.com/ledgerwatch/erigon/cl/clparams" + "github.com/ledgerwatch/erigon/cl/cltypes" + "github.com/ledgerwatch/erigon/cl/fork" + "github.com/ledgerwatch/erigon/cl/persistence" + "github.com/ledgerwatch/erigon/cl/persistence/db_config" + "github.com/ledgerwatch/erigon/cl/persistence/format/snapshot_format/getters" + clcore "github.com/ledgerwatch/erigon/cl/phase1/core" + "github.com/ledgerwatch/erigon/cl/phase1/execution_client" + "github.com/ledgerwatch/erigon/cl/sentinel" + "github.com/ledgerwatch/erigon/cl/sentinel/service" "github.com/ledgerwatch/erigon/cmd/caplin/caplin1" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/cli" "github.com/ledgerwatch/erigon/common/debug" - - rpcsentinel "github.com/ledgerwatch/erigon-lib/gointerfaces/sentinel" "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/consensus/bor" "github.com/ledgerwatch/erigon/consensus/bor/finality/flags" @@ -108,6 +89,7 @@ import ( "github.com/ledgerwatch/erigon/consensus/misc" "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/core/rawdb" + "github.com/ledgerwatch/erigon/core/rawdb/blockio" "github.com/ledgerwatch/erigon/core/state/temporal" "github.com/ledgerwatch/erigon/core/systemcontracts" "github.com/ledgerwatch/erigon/core/types" @@ -120,14 +102,27 @@ import ( "github.com/ledgerwatch/erigon/eth/stagedsync" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" "github.com/ledgerwatch/erigon/ethdb/privateapi" + "github.com/ledgerwatch/erigon/ethdb/prune" "github.com/ledgerwatch/erigon/ethstats" "github.com/ledgerwatch/erigon/node" "github.com/ledgerwatch/erigon/p2p" "github.com/ledgerwatch/erigon/p2p/enode" + "github.com/ledgerwatch/erigon/p2p/sentry" + "github.com/ledgerwatch/erigon/p2p/sentry/sentry_multi_client" "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/rpc" + "github.com/ledgerwatch/erigon/turbo/builder" + "github.com/ledgerwatch/erigon/turbo/engineapi" + "github.com/ledgerwatch/erigon/turbo/engineapi/engine_block_downloader" + "github.com/ledgerwatch/erigon/turbo/engineapi/engine_helpers" + "github.com/ledgerwatch/erigon/turbo/execution/eth1" + "github.com/ledgerwatch/erigon/turbo/execution/eth1/eth1_chain_reader.go" + "github.com/ledgerwatch/erigon/turbo/jsonrpc" "github.com/ledgerwatch/erigon/turbo/services" "github.com/ledgerwatch/erigon/turbo/shards" + "github.com/ledgerwatch/erigon/turbo/silkworm" + "github.com/ledgerwatch/erigon/turbo/snapshotsync/freezeblocks" + "github.com/ledgerwatch/erigon/turbo/snapshotsync/snap" stages2 "github.com/ledgerwatch/erigon/turbo/stages" "github.com/ledgerwatch/erigon/turbo/stages/headerdownload" ) @@ -1051,6 +1046,11 @@ func (s *Ethereum) StartMining(ctx context.Context, db kv.RwDB, mining *stagedsy borcfg.Authorize(eb, func(_ libcommon.Address, mimeType string, message []byte) ([]byte, error) { return crypto.Sign(crypto.Keccak256(message), cfg.SigKey) }) + + err := stagedsync.FetchSpanZeroForMiningIfNeeded(ctx, s.chainDB, s.blockReader, borcfg.HeimdallClient, logger) + if err != nil { + return err + } } else { // for the bor dev network without heimdall we need the authorizer to be set otherwise there is no // validator defined in the bor validator set and non mining nodes will reject all blocks diff --git a/eth/stagedsync/bor_heimdall_shared.go b/eth/stagedsync/bor_heimdall_shared.go new file mode 100644 index 00000000000..281774c5d16 --- /dev/null +++ b/eth/stagedsync/bor_heimdall_shared.go @@ -0,0 +1,313 @@ +package stagedsync + +import ( + "context" + "encoding/binary" + "encoding/json" + "errors" + "fmt" + "math/big" + "strconv" + "strings" + "time" + + "github.com/ledgerwatch/log/v3" + + "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon/consensus/bor/heimdall" + "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" + "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/rlp" + "github.com/ledgerwatch/erigon/turbo/services" +) + +var ( + ErrHeaderValidatorsLengthMismatch = errors.New("header validators length mismatch") + ErrHeaderValidatorsBytesMismatch = errors.New("header validators bytes mismatch") +) + +// LastSpanID TODO - move to block reader +func LastSpanID(tx kv.RwTx, blockReader services.FullBlockReader) (uint64, bool, error) { + sCursor, err := tx.Cursor(kv.BorSpans) + if err != nil { + return 0, false, err + } + + defer sCursor.Close() + k, _, err := sCursor.Last() + if err != nil { + return 0, false, err + } + + var lastSpanId uint64 + if k != nil { + lastSpanId = binary.BigEndian.Uint64(k) + } + + // TODO tidy this out when moving to block reader + type LastFrozen interface { + LastFrozenSpanID() uint64 + } + + snapshotLastSpanId := blockReader.(LastFrozen).LastFrozenSpanID() + if snapshotLastSpanId > lastSpanId { + return snapshotLastSpanId, true, nil + } + + return lastSpanId, k != nil, nil +} + +// LastStateSyncEventID TODO - move to block reader +func LastStateSyncEventID(tx kv.RwTx, blockReader services.FullBlockReader) (uint64, error) { + cursor, err := tx.Cursor(kv.BorEvents) + if err != nil { + return 0, err + } + + defer cursor.Close() + k, _, err := cursor.Last() + if err != nil { + return 0, err + } + + var lastEventId uint64 + if k != nil { + lastEventId = binary.BigEndian.Uint64(k) + } + + // TODO tidy this out when moving to block reader + type LastFrozen interface { + LastFrozenEventID() uint64 + } + + snapshotLastEventId := blockReader.(LastFrozen).LastFrozenEventID() + if snapshotLastEventId > lastEventId { + return snapshotLastEventId, nil + } + + return lastEventId, nil +} + +func FetchSpanZeroForMiningIfNeeded( + ctx context.Context, + db kv.RwDB, + blockReader services.FullBlockReader, + heimdallClient heimdall.IHeimdallClient, + logger log.Logger, +) error { + return db.Update(ctx, func(tx kv.RwTx) error { + _, err := blockReader.Span(ctx, tx, 0) + if err == nil { + return err + } + + // TODO refactor to use errors.Is + if !strings.Contains(err.Error(), "not found") { + // span exists, no need to fetch + return nil + } + + _, err = fetchAndWriteHeimdallSpan(ctx, 0, tx, heimdallClient, "FetchSpanZeroForMiningIfNeeded", logger) + return err + }) +} + +func fetchRequiredHeimdallSpansIfNeeded( + ctx context.Context, + toBlockNum uint64, + tx kv.RwTx, + cfg BorHeimdallCfg, + logPrefix string, + logger log.Logger, +) (uint64, error) { + requiredSpanID := span.IDAt(toBlockNum) + if span.BlockInLastSprintOfSpan(toBlockNum, cfg.borConfig) { + requiredSpanID++ + } + + lastSpanID, exists, err := LastSpanID(tx, cfg.blockReader) + if err != nil { + return 0, err + } + + if exists && requiredSpanID <= lastSpanID { + return lastSpanID, nil + } + + var from uint64 + if lastSpanID > 0 { + from = lastSpanID + 1 + } // else fetch from span 0 + + logger.Info(fmt.Sprintf("[%s] Processing spans...", logPrefix), "from", from, "to", requiredSpanID) + for spanID := from; spanID <= requiredSpanID; spanID++ { + if _, err = fetchAndWriteHeimdallSpan(ctx, spanID, tx, cfg.heimdallClient, logPrefix, logger); err != nil { + return 0, err + } + } + + return requiredSpanID, err +} + +func fetchAndWriteHeimdallSpan( + ctx context.Context, + spanID uint64, + tx kv.RwTx, + heimdallClient heimdall.IHeimdallClient, + logPrefix string, + logger log.Logger, +) (uint64, error) { + response, err := heimdallClient.Span(ctx, spanID) + if err != nil { + return 0, err + } + + spanBytes, err := json.Marshal(response) + if err != nil { + return 0, err + } + + var spanIDBytes [8]byte + binary.BigEndian.PutUint64(spanIDBytes[:], spanID) + if err = tx.Put(kv.BorSpans, spanIDBytes[:], spanBytes); err != nil { + return 0, err + } + + logger.Debug(fmt.Sprintf("[%s] Wrote span", logPrefix), "id", spanID) + return spanID, nil +} + +func fetchRequiredHeimdallStateSyncEventsIfNeeded( + ctx context.Context, + header *types.Header, + tx kv.RwTx, + cfg BorHeimdallCfg, + logPrefix string, + logger log.Logger, + lastStateSyncEventIDGetter func() (uint64, error), +) (uint64, int, time.Duration, error) { + lastStateSyncEventID, err := lastStateSyncEventIDGetter() + if err != nil { + return 0, 0, 0, err + } + + headerNum := header.Number.Uint64() + if headerNum%cfg.borConfig.CalculateSprintLength(headerNum) != 0 || headerNum == 0 { + // we fetch events only at beginning of each sprint + return lastStateSyncEventID, 0, 0, nil + } + + return fetchAndWriteHeimdallStateSyncEvents(ctx, header, lastStateSyncEventID, tx, cfg, logPrefix, logger) +} + +func fetchAndWriteHeimdallStateSyncEvents( + ctx context.Context, + header *types.Header, + lastStateSyncEventID uint64, + tx kv.RwTx, + cfg BorHeimdallCfg, + logPrefix string, + logger log.Logger, +) (uint64, int, time.Duration, error) { + fetchStart := time.Now() + config := cfg.borConfig + blockReader := cfg.blockReader + heimdallClient := cfg.heimdallClient + chainID := cfg.chainConfig.ChainID.String() + stateReceiverABI := cfg.stateReceiverABI + // Find out the latest eventId + var ( + from uint64 + to time.Time + ) + + blockNum := header.Number.Uint64() + + if config.IsIndore(blockNum) { + stateSyncDelay := config.CalculateStateSyncDelay(blockNum) + to = time.Unix(int64(header.Time-stateSyncDelay), 0) + } else { + pHeader, err := blockReader.HeaderByNumber(ctx, tx, blockNum-config.CalculateSprintLength(blockNum)) + if err != nil { + return lastStateSyncEventID, 0, time.Since(fetchStart), err + } + to = time.Unix(int64(pHeader.Time), 0) + } + + from = lastStateSyncEventID + 1 + + logger.Debug( + fmt.Sprintf("[%s] Fetching state updates from Heimdall", logPrefix), + "fromID", from, + "to", to.Format(time.RFC3339), + ) + + eventRecords, err := heimdallClient.StateSyncEvents(ctx, from, to.Unix()) + if err != nil { + return lastStateSyncEventID, 0, time.Since(fetchStart), err + } + + if config.OverrideStateSyncRecords != nil { + if val, ok := config.OverrideStateSyncRecords[strconv.FormatUint(blockNum, 10)]; ok { + eventRecords = eventRecords[0:val] + } + } + + if len(eventRecords) > 0 { + var key, val [8]byte + binary.BigEndian.PutUint64(key[:], blockNum) + binary.BigEndian.PutUint64(val[:], lastStateSyncEventID+1) + } + + const method = "commitState" + wroteIndex := false + for i, eventRecord := range eventRecords { + if eventRecord.ID <= lastStateSyncEventID { + continue + } + + if lastStateSyncEventID+1 != eventRecord.ID || eventRecord.ChainID != chainID || !eventRecord.Time.Before(to) { + return lastStateSyncEventID, i, time.Since(fetchStart), fmt.Errorf(fmt.Sprintf( + "invalid event record received %s, %s, %s, %s", + fmt.Sprintf("blockNum=%d", blockNum), + fmt.Sprintf("eventId=%d (exp %d)", eventRecord.ID, lastStateSyncEventID+1), + fmt.Sprintf("chainId=%s (exp %s)", eventRecord.ChainID, chainID), + fmt.Sprintf("time=%s (exp to %s)", eventRecord.Time, to), + )) + } + + eventRecordWithoutTime := eventRecord.BuildEventRecord() + + recordBytes, err := rlp.EncodeToBytes(eventRecordWithoutTime) + if err != nil { + return lastStateSyncEventID, i, time.Since(fetchStart), err + } + + data, err := stateReceiverABI.Pack(method, big.NewInt(eventRecord.Time.Unix()), recordBytes) + if err != nil { + logger.Error(fmt.Sprintf("[%s] Unable to pack tx for commitState", logPrefix), "err", err) + return lastStateSyncEventID, i, time.Since(fetchStart), err + } + + var eventIdBuf [8]byte + binary.BigEndian.PutUint64(eventIdBuf[:], eventRecord.ID) + if err = tx.Put(kv.BorEvents, eventIdBuf[:], data); err != nil { + return lastStateSyncEventID, i, time.Since(fetchStart), err + } + + if !wroteIndex { + var blockNumBuf [8]byte + binary.BigEndian.PutUint64(blockNumBuf[:], blockNum) + binary.BigEndian.PutUint64(eventIdBuf[:], eventRecord.ID) + if err = tx.Put(kv.BorEventNums, blockNumBuf[:], eventIdBuf[:]); err != nil { + return lastStateSyncEventID, i, time.Since(fetchStart), err + } + + wroteIndex = true + } + + lastStateSyncEventID++ + } + + return lastStateSyncEventID, len(eventRecords), time.Since(fetchStart), nil +} diff --git a/eth/stagedsync/default_stages.go b/eth/stagedsync/default_stages.go index d24c39ea97f..ca5570ba797 100644 --- a/eth/stagedsync/default_stages.go +++ b/eth/stagedsync/default_stages.go @@ -3,12 +3,13 @@ package stagedsync import ( "context" + "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/common/dbg" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/wrap" "github.com/ledgerwatch/erigon/eth/ethconfig" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" - "github.com/ledgerwatch/log/v3" ) func DefaultStages(ctx context.Context, @@ -67,7 +68,7 @@ func DefaultStages(ctx context.Context, if badBlockUnwind { return nil } - return BorHeimdallForward(s, u, ctx, txc.Tx, borHeimdallCfg, false, logger) + return BorHeimdallForward(s, u, ctx, txc.Tx, borHeimdallCfg, logger) }, Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { return BorHeimdallUnwind(u, ctx, s, txc.Tx, borHeimdallCfg) diff --git a/eth/stagedsync/stage_bor_heimdall.go b/eth/stagedsync/stage_bor_heimdall.go index 02044314fb2..9eebb6c50e0 100644 --- a/eth/stagedsync/stage_bor_heimdall.go +++ b/eth/stagedsync/stage_bor_heimdall.go @@ -5,11 +5,8 @@ import ( "context" "encoding/binary" "encoding/json" - "errors" "fmt" - "math/big" "sort" - "strconv" "time" lru "github.com/hashicorp/golang-lru/arc/v2" @@ -34,7 +31,6 @@ import ( "github.com/ledgerwatch/erigon/dataflow" "github.com/ledgerwatch/erigon/eth/ethconfig/estimate" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" - "github.com/ledgerwatch/erigon/rlp" "github.com/ledgerwatch/erigon/turbo/services" "github.com/ledgerwatch/erigon/turbo/stages/headerdownload" ) @@ -47,11 +43,6 @@ const ( extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal ) -var ( - ErrHeaderValidatorsLengthMismatch = errors.New("header validators length mismatch") - ErrHeaderValidatorsBytesMismatch = errors.New("header validators bytes mismatch") -) - type BorHeimdallCfg struct { db kv.RwDB snapDb kv.RwDB // Database to store and retrieve snapshot checkpoints @@ -109,7 +100,6 @@ func BorHeimdallForward( ctx context.Context, tx kv.RwTx, cfg BorHeimdallCfg, - mine bool, logger log.Logger, ) (err error) { processStart := time.Now() @@ -130,114 +120,42 @@ func BorHeimdallForward( defer tx.Rollback() } - var header *types.Header - var headNumber uint64 - - headNumber, err = stages.GetStageProgress(tx, stages.Headers) - + headNumber, err := stages.GetStageProgress(tx, stages.Headers) if err != nil { return err } - service := whitelist.GetWhitelistingService() - - if generics.BorMilestoneRewind.Load() != nil && *generics.BorMilestoneRewind.Load() != 0 { - unwindPoint := *generics.BorMilestoneRewind.Load() - var reset uint64 = 0 - generics.BorMilestoneRewind.Store(&reset) - - if service != nil && unwindPoint < headNumber { - header, err = cfg.blockReader.HeaderByNumber(ctx, tx, headNumber) - logger.Debug("[BorHeimdall] Verification failed for header", "hash", header.Hash(), "height", headNumber, "err", err) - cfg.penalize(ctx, []headerdownload.PenaltyItem{ - {Penalty: headerdownload.BadBlockPenalty, PeerID: cfg.hd.SourcePeerId(header.Hash())}}) + whitelistService := whitelist.GetWhitelistingService() + if unwindPointPtr := generics.BorMilestoneRewind.Load(); unwindPointPtr != nil && *unwindPointPtr != 0 { + unwindPoint := *unwindPointPtr + if whitelistService != nil && unwindPoint < headNumber { + header, err := cfg.blockReader.HeaderByNumber(ctx, tx, headNumber) + if err != nil { + return err + } + hash := header.Hash() + logger.Debug( + fmt.Sprintf("[%s] Verification failed for header due to milestone rewind", s.LogPrefix()), + "hash", hash, + "height", headNumber, + ) + cfg.penalize(ctx, []headerdownload.PenaltyItem{{ + Penalty: headerdownload.BadBlockPenalty, + PeerID: cfg.hd.SourcePeerId(hash), + }}) dataflow.HeaderDownloadStates.AddChange(headNumber, dataflow.HeaderInvalidated) - s.state.UnwindTo(unwindPoint, ForkReset(header.Hash())) + s.state.UnwindTo(unwindPoint, ForkReset(hash)) + var reset uint64 = 0 + generics.BorMilestoneRewind.Store(&reset) return fmt.Errorf("verification failed for header %d: %x", headNumber, header.Hash()) } } - if mine { - minedHeader := cfg.miningState.MiningBlock.Header - - if minedHeadNumber := minedHeader.Number.Uint64(); minedHeadNumber > headNumber { - // Whitelist service is called to check if the bor chain is - // on the cannonical chain according to milestones - if service != nil { - if !service.IsValidChain(minedHeadNumber, []*types.Header{minedHeader}) { - logger.Debug("[BorHeimdall] Verification failed for mined header", "hash", minedHeader.Hash(), "height", minedHeadNumber, "err", err) - dataflow.HeaderDownloadStates.AddChange(minedHeadNumber, dataflow.HeaderInvalidated) - s.state.UnwindTo(minedHeadNumber-1, ForkReset(minedHeader.Hash())) - return fmt.Errorf("mining on a wrong fork %d:%x", minedHeadNumber, minedHeader.Hash()) - } - } - } else { - return fmt.Errorf("attempting to mine %d, which is behind current head: %d", minedHeadNumber, headNumber) - } - } - - if err != nil { - return fmt.Errorf("getting headers progress: %w", err) - } - if s.BlockNumber == headNumber { return nil } - // Find out the latest event Id - cursor, err := tx.Cursor(kv.BorEvents) - if err != nil { - return err - } - defer cursor.Close() - k, _, err := cursor.Last() - if err != nil { - return err - } - - var lastEventId uint64 - if k != nil { - lastEventId = binary.BigEndian.Uint64(k) - } - type LastFrozen interface { - LastFrozenEventID() uint64 - LastFrozenSpanID() uint64 - } - snapshotLastEventId := cfg.blockReader.(LastFrozen).LastFrozenEventID() - if snapshotLastEventId > lastEventId { - lastEventId = snapshotLastEventId - } - sCursor, err := tx.Cursor(kv.BorSpans) - if err != nil { - return err - } - defer sCursor.Close() - k, _, err = sCursor.Last() - if err != nil { - return err - } - var lastSpanId uint64 - if k != nil { - lastSpanId = binary.BigEndian.Uint64(k) - } - snapshotLastSpanId := cfg.blockReader.(LastFrozen).LastFrozenSpanID() - if snapshotLastSpanId > lastSpanId { - lastSpanId = snapshotLastSpanId - } - var nextSpanId uint64 - if lastSpanId > 0 { - nextSpanId = lastSpanId + 1 - } - var endSpanID uint64 - if span.IDAt(headNumber) > 0 { - endSpanID = span.IDAt(headNumber + 1) - } - - if span.BlockInLastSprintOfSpan(headNumber, cfg.borConfig) { - endSpanID++ - } - lastBlockNum := s.BlockNumber if cfg.blockReader.FrozenBorBlocks() > lastBlockNum { lastBlockNum = cfg.blockReader.FrozenBorBlocks() @@ -256,97 +174,95 @@ func BorHeimdallForward( var fetchTime time.Duration var eventRecords int + lastSpanID, err := fetchRequiredHeimdallSpansIfNeeded(ctx, headNumber, tx, cfg, s.LogPrefix(), logger) + if err != nil { + return err + } + + lastStateSyncEventID, err := LastStateSyncEventID(tx, cfg.blockReader) + if err != nil { + return err + } + logTimer := time.NewTicker(logInterval) defer logTimer.Stop() - if endSpanID >= nextSpanId { - logger.Info("["+s.LogPrefix()+"] Processing spans...", "from", nextSpanId, "to", endSpanID) - } - for spanID := nextSpanId; spanID <= endSpanID; spanID++ { - if lastSpanId, err = fetchAndWriteSpans(ctx, spanID, tx, cfg.heimdallClient, s.LogPrefix(), logger); err != nil { - return err - } - } - if !mine { - logger.Info("["+s.LogPrefix()+"] Processing sync events...", "from", lastBlockNum+1, "to", headNumber) - } + logger.Info("["+s.LogPrefix()+"] Processing sync events...", "from", lastBlockNum+1, "to", headNumber) for blockNum = lastBlockNum + 1; blockNum <= headNumber; blockNum++ { select { default: case <-logTimer.C: - logger.Info("["+s.LogPrefix()+"] StateSync Progress", "progress", blockNum, "lastSpanId", lastSpanId, "lastEventId", lastEventId, "total records", eventRecords, "fetch time", fetchTime, "process time", time.Since(processStart)) + logger.Info("["+s.LogPrefix()+"] StateSync Progress", "progress", blockNum, "lastSpanID", lastSpanID, "lastStateSyncEventID", lastStateSyncEventID, "total records", eventRecords, "fetch time", fetchTime, "process time", time.Since(processStart)) } - if !mine { - header, err = cfg.blockReader.HeaderByNumber(ctx, tx, blockNum) - if err != nil { - return err - } - if header == nil { - return fmt.Errorf("header not found: %d", blockNum) - } - - // Whitelist service is called to check if the bor chain is - // on the cannonical chain according to milestones - if service != nil { - if !service.IsValidChain(blockNum, []*types.Header{header}) { - logger.Debug("["+s.LogPrefix()+"] Verification failed for header", "height", blockNum, "hash", header.Hash()) - cfg.penalize(ctx, []headerdownload.PenaltyItem{ - {Penalty: headerdownload.BadBlockPenalty, PeerID: cfg.hd.SourcePeerId(header.Hash())}}) - dataflow.HeaderDownloadStates.AddChange(blockNum, dataflow.HeaderInvalidated) - s.state.UnwindTo(blockNum-1, ForkReset(header.Hash())) - return fmt.Errorf("verification failed for header %d: %x", blockNum, header.Hash()) + header, err := cfg.blockReader.HeaderByNumber(ctx, tx, blockNum) + if err != nil { + return err + } + if header == nil { + return fmt.Errorf("header not found: %d", blockNum) + } + + // Whitelist whitelistService is called to check if the bor chain is + // on the cannonical chain according to milestones + if whitelistService != nil && !whitelistService.IsValidChain(blockNum, []*types.Header{header}) { + logger.Debug("["+s.LogPrefix()+"] Verification failed for header", "height", blockNum, "hash", header.Hash()) + cfg.penalize(ctx, []headerdownload.PenaltyItem{{ + Penalty: headerdownload.BadBlockPenalty, + PeerID: cfg.hd.SourcePeerId(header.Hash()), + }}) + dataflow.HeaderDownloadStates.AddChange(blockNum, dataflow.HeaderInvalidated) + s.state.UnwindTo(blockNum-1, ForkReset(header.Hash())) + return fmt.Errorf("verification failed for header %d: %x", blockNum, header.Hash()) + } + + if blockNum > cfg.blockReader.BorSnapshots().SegmentsMin() { + // SegmentsMin is only set if running as an uploader process (check SnapshotsCfg.snapshotUploader and + // UploadLocationFlag) when we remove snapshots based on FrozenBlockLimit and number of uploaded snapshots + // avoid calling this if block for blockNums <= SegmentsMin to avoid reinsertion of snapshots + snap := loadSnapshot(blockNum, header.Hash(), cfg.borConfig, recents, signatures, cfg.snapDb, logger) + + if snap == nil { + snap, err = initValidatorSets(ctx, tx, cfg.blockReader, cfg.borConfig, + cfg.heimdallClient, chain, blockNum, recents, signatures, cfg.snapDb, logger, s.LogPrefix()) + + if err != nil { + return fmt.Errorf("can't initialise validator sets: %w", err) } } - sprintLength := cfg.borConfig.CalculateSprintLength(blockNum) - spanID := span.IDAt(blockNum) - if (spanID > 0) && ((blockNum+1)%sprintLength == 0) { - if err = checkHeaderExtraData(u, ctx, chain, blockNum, header, cfg.borConfig); err != nil { - return err - } + if err = persistValidatorSets(ctx, snap, u, tx, cfg.blockReader, cfg.borConfig, chain, blockNum, header.Hash(), recents, signatures, cfg.snapDb, logger, s.LogPrefix()); err != nil { + return fmt.Errorf("can't persist validator sets: %w", err) } } - if blockNum > 0 && blockNum%cfg.borConfig.CalculateSprintLength(blockNum) == 0 { - var callTime time.Duration - var records int - if lastEventId, records, callTime, err = fetchAndWriteBorEvents(ctx, cfg.blockReader, cfg.borConfig, header, lastEventId, cfg.chainConfig.ChainID.String(), tx, cfg.heimdallClient, cfg.stateReceiverABI, s.LogPrefix(), logger); err != nil { - return err - } - - eventRecords += records - fetchTime += callTime + if err := checkBorHeaderExtraDataIfRequired(chain, header, cfg.borConfig); err != nil { + return err } - var snap *bor.Snapshot - - if header != nil { - if blockNum > cfg.blockReader.BorSnapshots().SegmentsMin() { - // SegmentsMin is only set if running as an uploader process (check SnapshotsCfg.snapshotUploader and - // UploadLocationFlag) when we remove snapshots based on FrozenBlockLimit and number of uploaded snapshots - // avoid calling this if block for blockNums <= SegmentsMin to avoid reinsertion of snapshots - snap = loadSnapshot(blockNum, header.Hash(), cfg.borConfig, recents, signatures, cfg.snapDb, logger) - - if snap == nil { - snap, err = initValidatorSets(ctx, tx, cfg.blockReader, cfg.borConfig, - cfg.heimdallClient, chain, blockNum, recents, signatures, cfg.snapDb, logger, s.LogPrefix()) - - if err != nil { - return fmt.Errorf("can't initialise validator sets: %w", err) - } - } - - if err = persistValidatorSets(ctx, snap, u, tx, cfg.blockReader, cfg.borConfig, chain, blockNum, header.Hash(), recents, signatures, cfg.snapDb, logger, s.LogPrefix()); err != nil { - return fmt.Errorf("can't persist validator sets: %w", err) - } - } + var callTime time.Duration + var records int + lastStateSyncEventID, records, callTime, err = fetchRequiredHeimdallStateSyncEventsIfNeeded( + ctx, + header, + tx, + cfg, + s.LogPrefix(), + logger, + func() (uint64, error) { + return lastStateSyncEventID, nil + }, + ) + if err != nil { + return err } + eventRecords += records + fetchTime += callTime + if cfg.loopBreakCheck != nil && cfg.loopBreakCheck(int(blockNum-lastBlockNum)) { break } - } if err = s.Update(tx, headNumber); err != nil { @@ -359,181 +275,11 @@ func BorHeimdallForward( } } - logger.Info("["+s.LogPrefix()+"] Sync events processed", "progress", blockNum-1, "lastSpanId", lastSpanId, "lastEventId", lastEventId, "total records", eventRecords, "fetch time", fetchTime, "process time", time.Since(processStart)) + logger.Info("["+s.LogPrefix()+"] Sync events processed", "progress", blockNum-1, "lastSpanID", lastSpanID, "lastStateSyncEventID", lastStateSyncEventID, "total records", eventRecords, "fetch time", fetchTime, "process time", time.Since(processStart)) return } -func checkHeaderExtraData( - u Unwinder, - ctx context.Context, - chain consensus.ChainHeaderReader, - blockNum uint64, - header *types.Header, - config *borcfg.BorConfig, -) error { - spanID := span.IDAt(blockNum + 1) - spanBytes := chain.BorSpan(spanID) - var sp span.HeimdallSpan - if err := json.Unmarshal(spanBytes, &sp); err != nil { - return err - } - producerSet := make([]*valset.Validator, len(sp.SelectedProducers)) - for i := range sp.SelectedProducers { - producerSet[i] = &sp.SelectedProducers[i] - } - - sort.Sort(valset.ValidatorsByAddress(producerSet)) - - headerVals, err := valset.ParseValidators(bor.GetValidatorBytes(header, config)) - if err != nil { - return err - } - - if len(producerSet) != len(headerVals) { - return ErrHeaderValidatorsLengthMismatch - } - - for i, val := range producerSet { - if !bytes.Equal(val.HeaderBytes(), headerVals[i].HeaderBytes()) { - return ErrHeaderValidatorsBytesMismatch - } - } - return nil -} - -func fetchAndWriteBorEvents( - ctx context.Context, - blockReader services.FullBlockReader, - config *borcfg.BorConfig, - header *types.Header, - lastEventId uint64, - chainID string, - tx kv.RwTx, - heimdallClient heimdall.IHeimdallClient, - stateReceiverABI abi.ABI, - logPrefix string, - logger log.Logger, -) (uint64, int, time.Duration, error) { - fetchStart := time.Now() - - // Find out the latest eventId - var ( - from uint64 - to time.Time - ) - - if header == nil { - return 0, 0, 0, fmt.Errorf("can't fetch events for nil header") - } - - blockNum := header.Number.Uint64() - - if config.IsIndore(blockNum) { - stateSyncDelay := config.CalculateStateSyncDelay(blockNum) - to = time.Unix(int64(header.Time-stateSyncDelay), 0) - } else { - pHeader, err := blockReader.HeaderByNumber(ctx, tx, blockNum-config.CalculateSprintLength(blockNum)) - if err != nil { - return lastEventId, 0, time.Since(fetchStart), err - } - to = time.Unix(int64(pHeader.Time), 0) - } - - from = lastEventId + 1 - - logger.Debug( - fmt.Sprintf("[%s] Fetching state updates from Heimdall", logPrefix), - "fromID", from, - "to", to.Format(time.RFC3339), - ) - - eventRecords, err := heimdallClient.StateSyncEvents(ctx, from, to.Unix()) - - if err != nil { - return lastEventId, 0, time.Since(fetchStart), err - } - - if config.OverrideStateSyncRecords != nil { - if val, ok := config.OverrideStateSyncRecords[strconv.FormatUint(blockNum, 10)]; ok { - eventRecords = eventRecords[0:val] - } - } - - if len(eventRecords) > 0 { - var key, val [8]byte - binary.BigEndian.PutUint64(key[:], blockNum) - binary.BigEndian.PutUint64(val[:], lastEventId+1) - } - const method = "commitState" - - wroteIndex := false - for i, eventRecord := range eventRecords { - if eventRecord.ID <= lastEventId { - continue - } - if lastEventId+1 != eventRecord.ID || eventRecord.ChainID != chainID || !eventRecord.Time.Before(to) { - return lastEventId, i, time.Since(fetchStart), fmt.Errorf("invalid event record received blockNum=%d, eventId=%d (exp %d), chainId=%s (exp %s), time=%s (exp to %s)", blockNum, eventRecord.ID, lastEventId+1, eventRecord.ChainID, chainID, eventRecord.Time, to) - } - - eventRecordWithoutTime := eventRecord.BuildEventRecord() - - recordBytes, err := rlp.EncodeToBytes(eventRecordWithoutTime) - if err != nil { - return lastEventId, i, time.Since(fetchStart), err - } - - data, err := stateReceiverABI.Pack(method, big.NewInt(eventRecord.Time.Unix()), recordBytes) - if err != nil { - logger.Error(fmt.Sprintf("[%s] Unable to pack tx for commitState", logPrefix), "err", err) - return lastEventId, i, time.Since(fetchStart), err - } - var eventIdBuf [8]byte - binary.BigEndian.PutUint64(eventIdBuf[:], eventRecord.ID) - if err = tx.Put(kv.BorEvents, eventIdBuf[:], data); err != nil { - return lastEventId, i, time.Since(fetchStart), err - } - if !wroteIndex { - var blockNumBuf [8]byte - binary.BigEndian.PutUint64(blockNumBuf[:], blockNum) - binary.BigEndian.PutUint64(eventIdBuf[:], eventRecord.ID) - if err = tx.Put(kv.BorEventNums, blockNumBuf[:], eventIdBuf[:]); err != nil { - return lastEventId, i, time.Since(fetchStart), err - } - wroteIndex = true - } - - lastEventId++ - } - - return lastEventId, len(eventRecords), time.Since(fetchStart), nil -} - -func fetchAndWriteSpans( - ctx context.Context, - spanId uint64, - tx kv.RwTx, - heimdallClient heimdall.IHeimdallClient, - logPrefix string, - logger log.Logger, -) (uint64, error) { - response, err := heimdallClient.Span(ctx, spanId) - if err != nil { - return 0, err - } - spanBytes, err := json.Marshal(response) - if err != nil { - return 0, err - } - var spanIDBytes [8]byte - binary.BigEndian.PutUint64(spanIDBytes[:], spanId) - if err = tx.Put(kv.BorSpans, spanIDBytes[:], spanBytes); err != nil { - return 0, err - } - logger.Debug(fmt.Sprintf("[%s] Wrote span", logPrefix), "id", spanId) - return spanId, nil -} - func loadSnapshot(blockNum uint64, hash libcommon.Hash, config *borcfg.BorConfig, recents *lru.ARCCache[libcommon.Hash, *bor.Snapshot], signatures *lru.ARCCache[libcommon.Hash, libcommon.Address], snapDb kv.RwDB, @@ -705,7 +451,7 @@ func initValidatorSets( zeroSpanBytes, err := blockReader.Span(ctx, tx, 0) if err != nil { - if _, err := fetchAndWriteSpans(ctx, 0, tx, heimdallClient, logPrefix, logger); err != nil { + if _, err := fetchAndWriteHeimdallSpan(ctx, 0, tx, heimdallClient, logPrefix, logger); err != nil { return nil, err } @@ -777,6 +523,50 @@ func initValidatorSets( return snap, nil } +func checkBorHeaderExtraDataIfRequired(chr consensus.ChainHeaderReader, header *types.Header, cfg *borcfg.BorConfig) error { + blockNum := header.Number.Uint64() + sprintLength := cfg.CalculateSprintLength(blockNum) + if (blockNum+1)%sprintLength != 0 { + // not last block of a sprint in a span, so no check needed (we only check last block of a sprint) + return nil + } + + return checkBorHeaderExtraData(chr, header, cfg) +} + +func checkBorHeaderExtraData(chr consensus.ChainHeaderReader, header *types.Header, cfg *borcfg.BorConfig) error { + spanID := span.IDAt(header.Number.Uint64() + 1) + spanBytes := chr.BorSpan(spanID) + var sp span.HeimdallSpan + if err := json.Unmarshal(spanBytes, &sp); err != nil { + return err + } + + producerSet := make([]*valset.Validator, len(sp.SelectedProducers)) + for i := range sp.SelectedProducers { + producerSet[i] = &sp.SelectedProducers[i] + } + + sort.Sort(valset.ValidatorsByAddress(producerSet)) + + headerVals, err := valset.ParseValidators(bor.GetValidatorBytes(header, cfg)) + if err != nil { + return err + } + + if len(producerSet) != len(headerVals) { + return ErrHeaderValidatorsLengthMismatch + } + + for i, val := range producerSet { + if !bytes.Equal(val.HeaderBytes(), headerVals[i].HeaderBytes()) { + return ErrHeaderValidatorsBytesMismatch + } + } + + return nil +} + func BorHeimdallUnwind(u *UnwindState, ctx context.Context, s *StageState, tx kv.RwTx, cfg BorHeimdallCfg) (err error) { if cfg.borConfig == nil { return diff --git a/eth/stagedsync/stage_mining_bor_heimdall.go b/eth/stagedsync/stage_mining_bor_heimdall.go new file mode 100644 index 00000000000..0befc9f1bc6 --- /dev/null +++ b/eth/stagedsync/stage_mining_bor_heimdall.go @@ -0,0 +1,89 @@ +package stagedsync + +import ( + "context" + "fmt" + + "github.com/ledgerwatch/log/v3" + + "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon/consensus/bor/finality/whitelist" + "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/dataflow" + "github.com/ledgerwatch/erigon/eth/stagedsync/stages" +) + +func MiningBorHeimdallForward( + ctx context.Context, + cfg BorHeimdallCfg, + stageStage *StageState, + unwinder Unwinder, + tx kv.RwTx, + logger log.Logger, +) error { + if cfg.borConfig == nil || cfg.heimdallClient == nil { + return nil + } + + logPrefix := stageStage.LogPrefix() + headerStageProgress, err := stages.GetStageProgress(tx, stages.Headers) + if err != nil { + return err + } + + header := cfg.miningState.MiningBlock.Header + headerNum := header.Number.Uint64() + if headerNum <= headerStageProgress { + return fmt.Errorf("attempting to mine %d, which is behind current head: %d", headerNum, headerStageProgress) + } + + // Whitelist service is called to check if the bor chain is on the canonical chain according to milestones + whitelistService := whitelist.GetWhitelistingService() + if whitelistService != nil && !whitelistService.IsValidChain(headerNum, []*types.Header{header}) { + hash := header.Hash() + logger.Debug( + fmt.Sprintf("[%s] Verification failed for mined header", logPrefix), + "hash", hash, + "height", headerNum, + "err", err, + ) + dataflow.HeaderDownloadStates.AddChange(headerNum, dataflow.HeaderInvalidated) + unwinder.UnwindTo(headerNum-1, ForkReset(hash)) + return fmt.Errorf("mining on a wrong fork %d:%x", headerNum, hash) + } + + lastSpanID, err := fetchRequiredHeimdallSpansIfNeeded(ctx, headerNum, tx, cfg, logPrefix, logger) + if err != nil { + return err + } + + lastStateSyncEventID, records, fetchTime, err := fetchRequiredHeimdallStateSyncEventsIfNeeded( + ctx, + header, + tx, + cfg, + logPrefix, + logger, + func() (uint64, error) { + return LastStateSyncEventID(tx, cfg.blockReader) + }, + ) + if err != nil { + return err + } + + if err = stageStage.Update(tx, headerNum); err != nil { + return err + } + + logger.Info( + "[%s] Finished processing", logPrefix, + "progress", headerNum, + "lastSpanID", lastSpanID, + "lastStateSyncEventID", lastStateSyncEventID, + "stateSyncEventTotalRecords", records, + "stateSyncEventFetchTime", fetchTime, + ) + + return nil +} diff --git a/eth/stagedsync/stagebuilder.go b/eth/stagedsync/stagebuilder.go index 26200a9e3a8..edd2e90049e 100644 --- a/eth/stagedsync/stagebuilder.go +++ b/eth/stagedsync/stagebuilder.go @@ -3,12 +3,13 @@ package stagedsync import ( "context" + "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/gointerfaces/remote" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/wrap" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" - "github.com/ledgerwatch/log/v3" ) type ChainEventNotifier interface { @@ -40,13 +41,13 @@ func MiningStages( Prune: func(firstCycle bool, u *PruneState, tx kv.RwTx, logger log.Logger) error { return nil }, }, { - ID: stages.BorHeimdall, + ID: stages.MiningBorHeimdall, Description: "Download Bor-specific data from Heimdall", Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { if badBlockUnwind { return nil } - return BorHeimdallForward(s, u, ctx, txc.Tx, borHeimdallCfg, true, logger) + return MiningBorHeimdallForward(ctx, borHeimdallCfg, s, u, txc.Tx, logger) }, Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { return BorHeimdallUnwind(u, ctx, s, txc.Tx, borHeimdallCfg) @@ -59,8 +60,6 @@ func MiningStages( ID: stages.MiningExecution, Description: "Mining: execute new block from tx pool", Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { - //fmt.Println("SpawnMiningExecStage") - //defer fmt.Println("SpawnMiningExecStage", "DONE") return SpawnMiningExecStage(s, txc.Tx, execCfg, ctx.Done(), logger) }, Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { diff --git a/eth/stagedsync/stages/stages.go b/eth/stagedsync/stages/stages.go index bf3c9fba6ae..c6734f3923e 100644 --- a/eth/stagedsync/stages/stages.go +++ b/eth/stagedsync/stages/stages.go @@ -49,6 +49,7 @@ var ( Finish SyncStage = "Finish" // Nominal stage after all other stages MiningCreateBlock SyncStage = "MiningCreateBlock" + MiningBorHeimdall SyncStage = "MiningBorHeimdall" MiningExecution SyncStage = "MiningExecution" MiningFinish SyncStage = "MiningFinish" // Beacon chain stages From e25b15b00e6572f87f515077c03275a5f89807f9 Mon Sep 17 00:00:00 2001 From: milen <94537774+taratorio@users.noreply.github.com> Date: Tue, 9 Jan 2024 14:48:01 +0000 Subject: [PATCH 26/92] remotedbserver: add support for bor snapshots (#9180) --- erigon-lib/go.mod | 1 + erigon-lib/go.sum | 9 ++++ erigon-lib/kv/mdbx/kv_abstract_test.go | 17 ++++--- .../kv/remotedbserver/mock/snapshots_mock.go | 48 +++++++++++++++++ .../kv/remotedbserver/remotedbserver.go | 51 ++++++++++++------- ...{server_test.go => remotedbserver_test.go} | 51 +++++++++++++++++-- erigon-lib/tools.go | 1 + eth/backend.go | 12 ++--- turbo/stages/mock/mock_sentry.go | 3 +- 9 files changed, 156 insertions(+), 37 deletions(-) create mode 100644 erigon-lib/kv/remotedbserver/mock/snapshots_mock.go rename erigon-lib/kv/remotedbserver/{server_test.go => remotedbserver_test.go} (54%) diff --git a/erigon-lib/go.mod b/erigon-lib/go.mod index b5c718c5d16..8ca0787b1a3 100644 --- a/erigon-lib/go.mod +++ b/erigon-lib/go.mod @@ -27,6 +27,7 @@ require ( github.com/edsrzf/mmap-go v1.1.0 github.com/go-stack/stack v1.8.1 github.com/gofrs/flock v0.8.1 + github.com/golang/mock v1.6.0 github.com/google/btree v1.1.2 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/hashicorp/golang-lru/v2 v2.0.6 diff --git a/erigon-lib/go.sum b/erigon-lib/go.sum index 19f1ddb7b28..f91070155b8 100644 --- a/erigon-lib/go.sum +++ b/erigon-lib/go.sum @@ -215,6 +215,8 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -464,6 +466,7 @@ github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPyS github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= @@ -500,6 +503,7 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= @@ -520,6 +524,7 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211201190559-0a0e4e1bb54c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -542,6 +547,7 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= @@ -565,7 +571,9 @@ golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -611,6 +619,7 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= diff --git a/erigon-lib/kv/mdbx/kv_abstract_test.go b/erigon-lib/kv/mdbx/kv_abstract_test.go index a504eac6407..70befa9e513 100644 --- a/erigon-lib/kv/mdbx/kv_abstract_test.go +++ b/erigon-lib/kv/mdbx/kv_abstract_test.go @@ -23,6 +23,12 @@ import ( "runtime" "testing" + "github.com/ledgerwatch/log/v3" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" + "google.golang.org/grpc/test/bufconn" + "github.com/ledgerwatch/erigon-lib/gointerfaces" "github.com/ledgerwatch/erigon-lib/gointerfaces/remote" "github.com/ledgerwatch/erigon-lib/kv" @@ -30,11 +36,6 @@ import ( "github.com/ledgerwatch/erigon-lib/kv/memdb" "github.com/ledgerwatch/erigon-lib/kv/remotedb" "github.com/ledgerwatch/erigon-lib/kv/remotedbserver" - "github.com/ledgerwatch/log/v3" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "google.golang.org/grpc" - "google.golang.org/grpc/test/bufconn" ) func TestSequence(t *testing.T) { @@ -169,7 +170,7 @@ func TestRemoteKvVersion(t *testing.T) { conn := bufconn.Listen(1024 * 1024) grpcServer := grpc.NewServer() go func() { - remote.RegisterKVServer(grpcServer, remotedbserver.NewKvServer(ctx, writeDB, nil, nil, logger)) + remote.RegisterKVServer(grpcServer, remotedbserver.NewKvServer(ctx, writeDB, nil, nil, nil, logger)) if err := grpcServer.Serve(conn); err != nil { log.Error("private RPC server fail", "err", err) } @@ -210,7 +211,7 @@ func TestRemoteKvRange(t *testing.T) { ctx, writeDB := context.Background(), memdb.NewTestDB(t) grpcServer, conn := grpc.NewServer(), bufconn.Listen(1024*1024) go func() { - kvServer := remotedbserver.NewKvServer(ctx, writeDB, nil, nil, logger) + kvServer := remotedbserver.NewKvServer(ctx, writeDB, nil, nil, nil, logger) remote.RegisterKVServer(grpcServer, kvServer) if err := grpcServer.Serve(conn); err != nil { log.Error("private RPC server fail", "err", err) @@ -344,7 +345,7 @@ func setupDatabases(t *testing.T, logger log.Logger, f mdbx.TableCfgFunc) (write grpcServer := grpc.NewServer() f2 := func() { - remote.RegisterKVServer(grpcServer, remotedbserver.NewKvServer(ctx, writeDBs[1], nil, nil, logger)) + remote.RegisterKVServer(grpcServer, remotedbserver.NewKvServer(ctx, writeDBs[1], nil, nil, nil, logger)) if err := grpcServer.Serve(conn); err != nil { logger.Error("private RPC server fail", "err", err) } diff --git a/erigon-lib/kv/remotedbserver/mock/snapshots_mock.go b/erigon-lib/kv/remotedbserver/mock/snapshots_mock.go new file mode 100644 index 00000000000..538b5aa4323 --- /dev/null +++ b/erigon-lib/kv/remotedbserver/mock/snapshots_mock.go @@ -0,0 +1,48 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/ledgerwatch/erigon-lib/kv/remotedbserver (interfaces: Snapshots) + +// Package mock is a generated GoMock package. +package mock + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" +) + +// MockSnapshots is a mock of Snapshots interface. +type MockSnapshots struct { + ctrl *gomock.Controller + recorder *MockSnapshotsMockRecorder +} + +// MockSnapshotsMockRecorder is the mock recorder for MockSnapshots. +type MockSnapshotsMockRecorder struct { + mock *MockSnapshots +} + +// NewMockSnapshots creates a new mock instance. +func NewMockSnapshots(ctrl *gomock.Controller) *MockSnapshots { + mock := &MockSnapshots{ctrl: ctrl} + mock.recorder = &MockSnapshotsMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockSnapshots) EXPECT() *MockSnapshotsMockRecorder { + return m.recorder +} + +// Files mocks base method. +func (m *MockSnapshots) Files() []string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Files") + ret0, _ := ret[0].([]string) + return ret0 +} + +// Files indicates an expected call of Files. +func (mr *MockSnapshotsMockRecorder) Files() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Files", reflect.TypeOf((*MockSnapshots)(nil).Files)) +} diff --git a/erigon-lib/kv/remotedbserver/remotedbserver.go b/erigon-lib/kv/remotedbserver/remotedbserver.go index 07191e55fe6..f276674cb78 100644 --- a/erigon-lib/kv/remotedbserver/remotedbserver.go +++ b/erigon-lib/kv/remotedbserver/remotedbserver.go @@ -71,8 +71,9 @@ type KvServer struct { kv kv.RoDB stateChangeStreams *StateChangePubSub - blockSnapshots Snapsthots - historySnapshots Snapsthots + blockSnapshots Snapshots + borSnapshots Snapshots + historySnapshots Snapshots ctx context.Context //v3 fields @@ -90,18 +91,24 @@ type threadSafeTx struct { sync.Mutex } -type Snapsthots interface { +//go:generate mockgen -destination=./mock/snapshots_mock.go -package=mock . Snapshots +type Snapshots interface { Files() []string } -func NewKvServer(ctx context.Context, db kv.RoDB, snapshots Snapsthots, historySnapshots Snapsthots, logger log.Logger) *KvServer { +func NewKvServer(ctx context.Context, db kv.RoDB, snapshots Snapshots, borSnapshots Snapshots, historySnapshots Snapshots, logger log.Logger) *KvServer { return &KvServer{ - trace: false, - rangeStep: 1024, - kv: db, stateChangeStreams: newStateChangeStreams(), ctx: ctx, - blockSnapshots: snapshots, historySnapshots: historySnapshots, - txs: map[uint64]*threadSafeTx{}, txsMapLock: &sync.RWMutex{}, - logger: logger, + trace: false, + rangeStep: 1024, + kv: db, + stateChangeStreams: newStateChangeStreams(), + ctx: ctx, + blockSnapshots: snapshots, + borSnapshots: borSnapshots, + historySnapshots: historySnapshots, + txs: map[uint64]*threadSafeTx{}, + txsMapLock: &sync.RWMutex{}, + logger: logger, } } @@ -430,7 +437,7 @@ func bytesCopy(b []byte) []byte { return copiedBytes } -func (s *KvServer) StateChanges(req *remote.StateChangeRequest, server remote.KV_StateChangesServer) error { +func (s *KvServer) StateChanges(_ *remote.StateChangeRequest, server remote.KV_StateChangesServer) error { ch, remove := s.stateChangeStreams.Sub() defer remove() for { @@ -447,16 +454,21 @@ func (s *KvServer) StateChanges(req *remote.StateChangeRequest, server remote.KV } } -func (s *KvServer) SendStateChanges(ctx context.Context, sc *remote.StateChangeBatch) { +func (s *KvServer) SendStateChanges(_ context.Context, sc *remote.StateChangeBatch) { s.stateChangeStreams.Pub(sc) } -func (s *KvServer) Snapshots(ctx context.Context, _ *remote.SnapshotsRequest) (*remote.SnapshotsReply, error) { +func (s *KvServer) Snapshots(_ context.Context, _ *remote.SnapshotsRequest) (*remote.SnapshotsReply, error) { if s.blockSnapshots == nil || reflect.ValueOf(s.blockSnapshots).IsNil() { // nolint return &remote.SnapshotsReply{BlocksFiles: []string{}, HistoryFiles: []string{}}, nil } - return &remote.SnapshotsReply{BlocksFiles: s.blockSnapshots.Files(), HistoryFiles: s.historySnapshots.Files()}, nil + blockFiles := s.blockSnapshots.Files() + if s.borSnapshots != nil { + blockFiles = append(blockFiles, s.borSnapshots.Files()...) + } + + return &remote.SnapshotsReply{BlocksFiles: blockFiles, HistoryFiles: s.historySnapshots.Files()}, nil } type StateChangePubSub struct { @@ -507,8 +519,11 @@ func (s *StateChangePubSub) remove(id uint) { delete(s.chans, id) } +// // Temporal methods -func (s *KvServer) DomainGet(ctx context.Context, req *remote.DomainGetReq) (reply *remote.DomainGetReply, err error) { +// + +func (s *KvServer) DomainGet(_ context.Context, req *remote.DomainGetReq) (reply *remote.DomainGetReply, err error) { reply = &remote.DomainGetReply{} if err := s.with(req.TxId, func(tx kv.Tx) error { ttx, ok := tx.(kv.TemporalTx) @@ -532,7 +547,7 @@ func (s *KvServer) DomainGet(ctx context.Context, req *remote.DomainGetReq) (rep } return reply, nil } -func (s *KvServer) HistoryGet(ctx context.Context, req *remote.HistoryGetReq) (reply *remote.HistoryGetReply, err error) { +func (s *KvServer) HistoryGet(_ context.Context, req *remote.HistoryGetReq) (reply *remote.HistoryGetReply, err error) { reply = &remote.HistoryGetReply{} if err := s.with(req.TxId, func(tx kv.Tx) error { ttx, ok := tx.(kv.TemporalTx) @@ -552,7 +567,7 @@ func (s *KvServer) HistoryGet(ctx context.Context, req *remote.HistoryGetReq) (r const PageSizeLimit = 4 * 4096 -func (s *KvServer) IndexRange(ctx context.Context, req *remote.IndexRangeReq) (*remote.IndexRangeReply, error) { +func (s *KvServer) IndexRange(_ context.Context, req *remote.IndexRangeReq) (*remote.IndexRangeReply, error) { reply := &remote.IndexRangeReply{} from, limit := int(req.FromTs), int(req.Limit) if req.PageToken != "" { @@ -600,7 +615,7 @@ func (s *KvServer) IndexRange(ctx context.Context, req *remote.IndexRangeReq) (* return reply, nil } -func (s *KvServer) Range(ctx context.Context, req *remote.RangeReq) (*remote.Pairs, error) { +func (s *KvServer) Range(_ context.Context, req *remote.RangeReq) (*remote.Pairs, error) { from, limit := req.FromPrefix, int(req.Limit) if req.PageToken != "" { var pagination remote.ParisPagination diff --git a/erigon-lib/kv/remotedbserver/server_test.go b/erigon-lib/kv/remotedbserver/remotedbserver_test.go similarity index 54% rename from erigon-lib/kv/remotedbserver/server_test.go rename to erigon-lib/kv/remotedbserver/remotedbserver_test.go index fec193f0389..4e233638862 100644 --- a/erigon-lib/kv/remotedbserver/server_test.go +++ b/erigon-lib/kv/remotedbserver/remotedbserver_test.go @@ -21,14 +21,18 @@ import ( "runtime" "testing" - "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon-lib/kv/memdb" + "github.com/golang/mock/gomock" "github.com/ledgerwatch/log/v3" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" + + "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon-lib/kv/memdb" + "github.com/ledgerwatch/erigon-lib/kv/remotedbserver/mock" ) func TestKvServer_renew(t *testing.T) { + //goland:noinspection GoBoolExpressions if runtime.GOOS == "windows" { t.Skip("fix me on win please") } @@ -44,7 +48,7 @@ func TestKvServer_renew(t *testing.T) { return nil })) - s := NewKvServer(ctx, db, nil, nil, log.New()) + s := NewKvServer(ctx, db, nil, nil, nil, log.New()) g, ctx := errgroup.WithContext(ctx) testCase := func() error { id, err := s.begin(ctx) @@ -95,3 +99,44 @@ func TestKvServer_renew(t *testing.T) { } require.NoError(g.Wait()) } + +func TestKVServerSnapshotsReturnsSnapshots(t *testing.T) { + ctx := context.Background() + ctrl := gomock.NewController(t) + blockSnapshots := mock.NewMockSnapshots(ctrl) + blockSnapshots.EXPECT().Files().Return([]string{"headers.seg", "bodies.seg"}).Times(1) + historySnapshots := mock.NewMockSnapshots(ctrl) + historySnapshots.EXPECT().Files().Return([]string{"history"}).Times(1) + + s := NewKvServer(ctx, nil, blockSnapshots, nil, historySnapshots, log.New()) + reply, err := s.Snapshots(ctx, nil) + require.NoError(t, err) + require.Equal(t, []string{"headers.seg", "bodies.seg"}, reply.BlocksFiles) + require.Equal(t, []string{"history"}, reply.HistoryFiles) +} + +func TestKVServerSnapshotsReturnsBorSnapshots(t *testing.T) { + ctx := context.Background() + ctrl := gomock.NewController(t) + blockSnapshots := mock.NewMockSnapshots(ctrl) + blockSnapshots.EXPECT().Files().Return([]string{"headers.seg", "bodies.seg"}).Times(1) + borSnapshots := mock.NewMockSnapshots(ctrl) + borSnapshots.EXPECT().Files().Return([]string{"borevents.seg", "borspans.seg"}).Times(1) + historySnapshots := mock.NewMockSnapshots(ctrl) + historySnapshots.EXPECT().Files().Return([]string{"history"}).Times(1) + + s := NewKvServer(ctx, nil, blockSnapshots, borSnapshots, historySnapshots, log.New()) + reply, err := s.Snapshots(ctx, nil) + require.NoError(t, err) + require.Equal(t, []string{"headers.seg", "bodies.seg", "borevents.seg", "borspans.seg"}, reply.BlocksFiles) + require.Equal(t, []string{"history"}, reply.HistoryFiles) +} + +func TestKVServerSnapshotsReturnsEmptyIfNoBlockSnapshots(t *testing.T) { + ctx := context.Background() + s := NewKvServer(ctx, nil, nil, nil, nil, log.New()) + reply, err := s.Snapshots(ctx, nil) + require.NoError(t, err) + require.Empty(t, reply.BlocksFiles) + require.Empty(t, reply.HistoryFiles) +} diff --git a/erigon-lib/tools.go b/erigon-lib/tools.go index 5188efdc85c..a97764c2cef 100644 --- a/erigon-lib/tools.go +++ b/erigon-lib/tools.go @@ -17,6 +17,7 @@ package tools // build tag 'trick_go_mod_tidy' - is used to hide warnings of IDEA (because we can't import `main` packages in go) import ( + _ "github.com/golang/mock/mockgen/model" _ "github.com/ledgerwatch/interfaces" _ "github.com/ledgerwatch/interfaces/downloader" _ "github.com/ledgerwatch/interfaces/execution" diff --git a/eth/backend.go b/eth/backend.go index dbfca093cb1..03e5e0d9d4c 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -321,7 +321,7 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger // Check if we have an already initialized chain and fall back to // that if so. Otherwise we need to generate a new genesis spec. - blockReader, blockWriter, allSnapshots, agg, err := setUpBlockReader(ctx, chainKv, config.Dirs, snapshotVersion, config.Snapshot, config.HistoryV3, chainConfig.Bor != nil, logger) + blockReader, blockWriter, allSnapshots, allBorSnapshots, agg, err := setUpBlockReader(ctx, chainKv, config.Dirs, snapshotVersion, config.Snapshot, config.HistoryV3, chainConfig.Bor != nil, logger) if err != nil { return nil, err } @@ -339,7 +339,7 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger return nil, err } - kvRPC := remotedbserver.NewKvServer(ctx, backend.chainDB, allSnapshots, agg, logger) + kvRPC := remotedbserver.NewKvServer(ctx, backend.chainDB, allSnapshots, allBorSnapshots, agg, logger) backend.notifications.StateChangesConsumer = kvRPC backend.kvRPC = kvRPC @@ -1242,7 +1242,7 @@ func (s *Ethereum) setUpSnapDownloader(ctx context.Context, downloaderCfg *downl return err } -func setUpBlockReader(ctx context.Context, db kv.RwDB, dirs datadir.Dirs, snashotVersion uint8, snConfig ethconfig.BlocksFreezing, histV3 bool, isBor bool, logger log.Logger) (services.FullBlockReader, *blockio.BlockWriter, *freezeblocks.RoSnapshots, *libstate.AggregatorV3, error) { +func setUpBlockReader(ctx context.Context, db kv.RwDB, dirs datadir.Dirs, snashotVersion uint8, snConfig ethconfig.BlocksFreezing, histV3 bool, isBor bool, logger log.Logger) (services.FullBlockReader, *blockio.BlockWriter, *freezeblocks.RoSnapshots, *freezeblocks.BorRoSnapshots, *libstate.AggregatorV3, error) { allSnapshots := freezeblocks.NewRoSnapshots(snConfig, dirs.Snap, snashotVersion, logger) var allBorSnapshots *freezeblocks.BorRoSnapshots @@ -1267,12 +1267,12 @@ func setUpBlockReader(ctx context.Context, db kv.RwDB, dirs datadir.Dirs, snasho agg, err := libstate.NewAggregatorV3(ctx, dirs.SnapHistory, dirs.Tmp, ethconfig.HistoryV3AggregationStep, db, logger) if err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, err } if err = agg.OpenFolder(); err != nil { - return nil, nil, nil, nil, err + return nil, nil, nil, nil, nil, err } - return blockReader, blockWriter, allSnapshots, agg, nil + return blockReader, blockWriter, allSnapshots, allBorSnapshots, agg, nil } func (s *Ethereum) Peers(ctx context.Context) (*remote.PeersReply, error) { diff --git a/turbo/stages/mock/mock_sentry.go b/turbo/stages/mock/mock_sentry.go index f6da6c474ae..af9bf9241e0 100644 --- a/turbo/stages/mock/mock_sentry.go +++ b/turbo/stages/mock/mock_sentry.go @@ -34,7 +34,6 @@ import ( "github.com/ledgerwatch/erigon-lib/txpool/txpoolcfg" types2 "github.com/ledgerwatch/erigon-lib/types" "github.com/ledgerwatch/erigon-lib/wrap" - "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/consensus/bor" "github.com/ledgerwatch/erigon/consensus/ethash" @@ -260,7 +259,7 @@ func MockWithEverything(tb testing.TB, gspec *types.Genesis, key *ecdsa.PrivateK histV3, db, agg := temporal.NewTestDB(nil, dirs, nil) cfg.HistoryV3 = histV3 - erigonGrpcServeer := remotedbserver.NewKvServer(ctx, db, nil, nil, logger) + erigonGrpcServeer := remotedbserver.NewKvServer(ctx, db, nil, nil, nil, logger) allSnapshots := freezeblocks.NewRoSnapshots(ethconfig.Defaults.Snapshot, dirs.Snap, 1, logger) allBorSnapshots := freezeblocks.NewBorRoSnapshots(ethconfig.Defaults.Snapshot, dirs.Snap, 1, logger) mock := &MockSentry{ From fec0c9eef519fba30a12393301e813e4517dc557 Mon Sep 17 00:00:00 2001 From: vuittont60 <81072379+vuittont60@users.noreply.github.com> Date: Tue, 9 Jan 2024 23:34:47 +0800 Subject: [PATCH 27/92] docs: fix typos (#9173) --- cmd/integration/Readme.md | 2 +- cmd/snapshots/README.md | 4 ++-- docs/programmers_guide/witness_format.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/integration/Readme.md b/cmd/integration/Readme.md index 389248b1e5c..5d97a69368c 100644 --- a/cmd/integration/Readme.md +++ b/cmd/integration/Readme.md @@ -88,7 +88,7 @@ make all 4. Build integration: cd erigon; make integration 5. Run: ./build/bin/integration mdbx_to_mdbx --chaindata /existing/erigon/path/chaindata/ --chaindata.to /path/to/copy-to/chaindata/ 6. cp -R /existing/erigon/path/snapshots /path/to/copy-to/snapshots -7. start erigon in new datadir as usualy +7. start erigon in new datadir as usually ``` ## Clear bad blocks markers table in the case some block was marked as invalid after some error diff --git a/cmd/snapshots/README.md b/cmd/snapshots/README.md index 110f2d20ab4..06544214de4 100644 --- a/cmd/snapshots/README.md +++ b/cmd/snapshots/README.md @@ -16,7 +16,7 @@ Snapshots supports the following sub commands: ## cmp - compare snapshots -This command takes the follwoing form: +This command takes the following form: ```shell snapshots cmp @@ -32,7 +32,7 @@ It is also possible to set the `--types` flag to limit the type of segment file This command can be used to copy segment files from one location to another. -This command takes the follwoing form: +This command takes the following form: ```shell snapshots copy diff --git a/docs/programmers_guide/witness_format.md b/docs/programmers_guide/witness_format.md index 8454e808d66..fe0909f6898 100644 --- a/docs/programmers_guide/witness_format.md +++ b/docs/programmers_guide/witness_format.md @@ -91,6 +91,6 @@ encoded as `[ 0x05 CBOR(key|[]byte)... flags /CBOR(nonce).../ /CBOR(balance).../ *flags* is a bitset encoded in a single bit (see [`witness_operators_test.go`](../../trie/witness_operators_test.go) to see flags in action). * bit 0 defines if **code** is present; if set to 1 it assumes that either `OpCode` or `OpHash` already put something on the stack; -* bit 1 defines if **storage** is present; if set to 1, the operators preceeding `OpAccountLeaf` will reconstruct a storage trie; +* bit 1 defines if **storage** is present; if set to 1, the operators preceding `OpAccountLeaf` will reconstruct a storage trie; * bit 2 defines if **nonce** is not 0; if set to 0, *nonce* field is not encoded; * bit 3 defines if **balance** is not 0; if set to 0, *balance* field is not encoded; From af913fdeeb1a3ae397b31c2afd887dc6a00349eb Mon Sep 17 00:00:00 2001 From: milen <94537774+taratorio@users.noreply.github.com> Date: Tue, 9 Jan 2024 15:41:00 +0000 Subject: [PATCH 28/92] bor: fix for TestMiningBenchmark (#9182) integration test TestMiningBenchmark is failing the CI on devel - this PR aims to fix it --- eth/backend.go | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/eth/backend.go b/eth/backend.go index 03e5e0d9d4c..c15a08f756f 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -780,7 +780,7 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger } }() - if err := backend.StartMining(context.Background(), backend.chainDB, mining, backend.config.Miner, backend.gasPrice, backend.sentriesClient.Hd.QuitPoWMining, tmpdir, logger); err != nil { + if err := backend.StartMining(context.Background(), backend.chainDB, mining, backend.config.Miner, backend.sentriesClient.Hd.QuitPoWMining, tmpdir, logger); err != nil { return nil, err } @@ -1010,8 +1010,7 @@ func (s *Ethereum) shouldPreserve(block *types.Block) bool { //nolint // StartMining starts the miner with the given number of CPU threads. If mining // is already running, this method adjust the number of threads allowed to use // and updates the minimum price required by the transaction pool. -func (s *Ethereum) StartMining(ctx context.Context, db kv.RwDB, mining *stagedsync.Sync, cfg params.MiningConfig, gasPrice *uint256.Int, quitCh chan struct{}, tmpDir string, logger log.Logger) error { - +func (s *Ethereum) StartMining(ctx context.Context, db kv.RwDB, mining *stagedsync.Sync, cfg params.MiningConfig, quitCh chan struct{}, tmpDir string, logger log.Logger) error { var borcfg *bor.Bor if b, ok := s.engine.(*bor.Bor); ok { borcfg = b @@ -1047,9 +1046,17 @@ func (s *Ethereum) StartMining(ctx context.Context, db kv.RwDB, mining *stagedsy return crypto.Sign(crypto.Keccak256(message), cfg.SigKey) }) - err := stagedsync.FetchSpanZeroForMiningIfNeeded(ctx, s.chainDB, s.blockReader, borcfg.HeimdallClient, logger) - if err != nil { - return err + if !s.config.WithoutHeimdall { + err := stagedsync.FetchSpanZeroForMiningIfNeeded( + ctx, + s.chainDB, + s.blockReader, + borcfg.HeimdallClient, + logger, + ) + if err != nil { + return err + } } } else { // for the bor dev network without heimdall we need the authorizer to be set otherwise there is no From 9c47cce62c09ae18ed00187a211223a81a597a39 Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Tue, 9 Jan 2024 19:20:42 +0100 Subject: [PATCH 29/92] bor: move to polygon directory (#9174) --- cmd/devnet/networks/devnet_bor.go | 2 +- cmd/devnet/services/polygon/checkpoint.go | 3 ++- cmd/devnet/services/polygon/heimdall.go | 13 ++++++------ .../services/polygon/proofgenerator_test.go | 14 +++++++------ cmd/devnet/services/polygon/statesync.go | 2 +- cmd/integration/commands/stages.go | 7 ++++--- cmd/rpcdaemon/cli/config.go | 9 ++++---- consensus/misc/eip1559.go | 2 +- core/rawdb/accessors_metadata.go | 2 +- core/system_contract_lookup.go | 2 +- eth/backend.go | 8 +++---- eth/ethconsensusconfig/config.go | 11 +++++----- eth/stagedsync/bor_heimdall_shared.go | 4 ++-- eth/stagedsync/stage_bor_heimdall.go | 16 +++++++------- eth/stagedsync/stage_bor_heimdall_test.go | 4 ++-- eth/stagedsync/stage_mining_bor_heimdall.go | 2 +- eth/stagedsync/stage_txlookup.go | 2 +- .../stagedsynctest/chain_configs.go | 2 +- eth/stagedsync/stagedsynctest/harness.go | 18 +++++++++------- params/config.go | 2 +- {consensus => polygon}/bor/abi/interface.go | 0 {consensus => polygon}/bor/bor.go | 17 ++++++++------- {consensus => polygon}/bor/bor_test.go | 21 +++++++++++-------- .../bor/borcfg/bor_config.go | 0 .../bor/borcfg/bor_config_test.go | 0 {consensus => polygon}/bor/clerk/clerk.go | 0 {consensus => polygon}/bor/contract/client.go | 0 {consensus => polygon}/bor/errors.go | 2 +- {consensus => polygon}/bor/fake.go | 0 {consensus => polygon}/bor/finality/api.go | 2 +- .../bor/finality/bor_verifier.go | 4 ++-- .../bor/finality/flags/flags.go | 0 .../bor/finality/generics/generics.go | 0 .../bor/finality/rawdb/checkpoint.go | 0 .../bor/finality/rawdb/milestone.go | 2 +- .../bor/finality/whitelist.go | 10 +++++---- .../bor/finality/whitelist/checkpoint.go | 2 +- .../bor/finality/whitelist/finality.go | 2 +- .../bor/finality/whitelist/milestone.go | 4 ++-- .../bor/finality/whitelist/service.go | 2 +- .../bor/finality/whitelist/service_test.go | 2 +- .../bor/finality/whitelist_helpers.go | 8 ++++--- .../bor/genesis_contract.go | 0 {consensus => polygon}/bor/merkle.go | 0 .../bor/mock/genesis_contract_mock.go | 2 +- .../bor/mock/spanner_mock.go | 6 +++--- {consensus => polygon}/bor/snapshot.go | 4 ++-- {consensus => polygon}/bor/snapshot_test.go | 4 ++-- {consensus => polygon}/bor/spanner.go | 5 +++-- .../bor/statefull/processor.go | 0 {consensus => polygon}/bor/valset/error.go | 0 .../bor/valset/validator.go | 0 .../bor/valset/validator_set.go | 0 .../heimdall/checkpoint/checkpoint.go | 0 {consensus/bor => polygon}/heimdall/client.go | 9 ++++---- .../bor => polygon}/heimdall/client_test.go | 3 ++- .../bor => polygon}/heimdall/heimdall.go | 11 +++++----- .../heimdall}/heimdallgrpc/checkpoint.go | 2 +- .../heimdall}/heimdallgrpc/client.go | 0 .../heimdall}/heimdallgrpc/milestone.go | 2 +- .../heimdall}/heimdallgrpc/server.go | 6 ++++-- .../heimdall}/heimdallgrpc/span.go | 5 +++-- .../heimdall}/heimdallgrpc/state_sync.go | 2 +- .../bor => polygon}/heimdall/metrics.go | 0 .../heimdall/milestone/milestone.go | 0 .../heimdall/mock/heimdall_client_mock.go | 10 ++++----- .../heimdall/mock/http_client_mock.go | 2 +- .../bor => polygon}/heimdall/span/span.go | 2 +- .../bor => polygon}/heimdall/span/span_id.go | 2 +- .../heimdall/span/span_id_test.go | 2 +- .../bor => polygon}/heimdall/span/spanner.go | 6 +++--- .../heimdall/span/testValidators.go | 2 +- polygon/sync/canonical_chain_builder.go | 2 +- polygon/sync/canonical_chain_builder_test.go | 3 ++- polygon/sync/difficulty.go | 9 ++++---- polygon/sync/difficulty_test.go | 5 +++-- polygon/sync/header_downloader_test.go | 5 +++-- polygon/sync/heimdall.go | 9 ++++---- polygon/sync/heimdall_test.go | 8 +++---- polygon/sync/mock/heimdall_mock.go | 6 +++--- polygon/sync/state_point.go | 5 +++-- polygon/sync/state_points.go | 4 ++-- tests/bor/helper/miner.go | 2 +- turbo/jsonrpc/bor_api.go | 4 ++-- turbo/jsonrpc/bor_helper.go | 6 +++--- turbo/jsonrpc/bor_snapshot.go | 8 +++---- turbo/jsonrpc/daemon.go | 2 +- turbo/jsonrpc/erigon_system.go | 4 ++-- turbo/jsonrpc/eth_block.go | 2 +- turbo/jsonrpc/validator_set.go | 2 +- turbo/rpchelper/helper.go | 4 ++-- .../snapshotsync/freezeblocks/block_reader.go | 6 ++++-- .../freezeblocks/block_snapshots.go | 3 ++- .../freezeblocks/bor_snapshots.go | 3 ++- turbo/snapshotsync/freezeblocks/dump_test.go | 2 +- turbo/stages/mock/mock_sentry.go | 2 +- turbo/stages/stageloop.go | 7 ++++--- turbo/transactions/tracing.go | 2 +- 98 files changed, 220 insertions(+), 185 deletions(-) rename {consensus => polygon}/bor/abi/interface.go (100%) rename {consensus => polygon}/bor/bor.go (99%) rename {consensus => polygon}/bor/bor_test.go (96%) rename {consensus => polygon}/bor/borcfg/bor_config.go (100%) rename {consensus => polygon}/bor/borcfg/bor_config_test.go (100%) rename {consensus => polygon}/bor/clerk/clerk.go (100%) rename {consensus => polygon}/bor/contract/client.go (100%) rename {consensus => polygon}/bor/errors.go (97%) rename {consensus => polygon}/bor/fake.go (100%) rename {consensus => polygon}/bor/finality/api.go (95%) rename {consensus => polygon}/bor/finality/bor_verifier.go (97%) rename {consensus => polygon}/bor/finality/flags/flags.go (100%) rename {consensus => polygon}/bor/finality/generics/generics.go (100%) rename {consensus => polygon}/bor/finality/rawdb/checkpoint.go (100%) rename {consensus => polygon}/bor/finality/rawdb/milestone.go (98%) rename {consensus => polygon}/bor/finality/whitelist.go (97%) rename {consensus => polygon}/bor/finality/whitelist/checkpoint.go (94%) rename {consensus => polygon}/bor/finality/whitelist/finality.go (96%) rename {consensus => polygon}/bor/finality/whitelist/milestone.go (98%) rename {consensus => polygon}/bor/finality/whitelist/service.go (98%) rename {consensus => polygon}/bor/finality/whitelist/service_test.go (99%) rename {consensus => polygon}/bor/finality/whitelist_helpers.go (97%) rename {consensus => polygon}/bor/genesis_contract.go (100%) rename {consensus => polygon}/bor/merkle.go (100%) rename {consensus => polygon}/bor/mock/genesis_contract_mock.go (96%) rename {consensus => polygon}/bor/mock/spanner_mock.go (94%) rename {consensus => polygon}/bor/snapshot.go (98%) rename {consensus => polygon}/bor/snapshot_test.go (97%) rename {consensus => polygon}/bor/spanner.go (84%) rename {consensus => polygon}/bor/statefull/processor.go (100%) rename {consensus => polygon}/bor/valset/error.go (100%) rename {consensus => polygon}/bor/valset/validator.go (100%) rename {consensus => polygon}/bor/valset/validator_set.go (100%) rename {consensus/bor => polygon}/heimdall/checkpoint/checkpoint.go (100%) rename {consensus/bor => polygon}/heimdall/client.go (98%) rename {consensus/bor => polygon}/heimdall/client_test.go (96%) rename {consensus/bor => polygon}/heimdall/heimdall.go (85%) rename {consensus/bor => polygon/heimdall}/heimdallgrpc/checkpoint.go (94%) rename {consensus/bor => polygon/heimdall}/heimdallgrpc/client.go (100%) rename {consensus/bor => polygon/heimdall}/heimdallgrpc/milestone.go (97%) rename {consensus/bor => polygon/heimdall}/heimdallgrpc/server.go (99%) rename {consensus/bor => polygon/heimdall}/heimdallgrpc/span.go (93%) rename {consensus/bor => polygon/heimdall}/heimdallgrpc/state_sync.go (96%) rename {consensus/bor => polygon}/heimdall/metrics.go (100%) rename {consensus/bor => polygon}/heimdall/milestone/milestone.go (100%) rename {consensus/bor => polygon}/heimdall/mock/heimdall_client_mock.go (94%) rename {consensus/bor => polygon}/heimdall/mock/http_client_mock.go (95%) rename {consensus/bor => polygon}/heimdall/span/span.go (94%) rename {consensus/bor => polygon}/heimdall/span/span_id.go (94%) rename {consensus/bor => polygon}/heimdall/span/span_id_test.go (95%) rename {consensus/bor => polygon}/heimdall/span/spanner.go (96%) rename {consensus/bor => polygon}/heimdall/span/testValidators.go (95%) diff --git a/cmd/devnet/networks/devnet_bor.go b/cmd/devnet/networks/devnet_bor.go index 9fccc438dd8..9f8cbd2fad8 100644 --- a/cmd/devnet/networks/devnet_bor.go +++ b/cmd/devnet/networks/devnet_bor.go @@ -12,9 +12,9 @@ import ( account_services "github.com/ledgerwatch/erigon/cmd/devnet/services/accounts" "github.com/ledgerwatch/erigon/cmd/devnet/services/polygon" "github.com/ledgerwatch/erigon/cmd/utils" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/params" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" ) func NewBorDevnetWithoutHeimdall( diff --git a/cmd/devnet/services/polygon/checkpoint.go b/cmd/devnet/services/polygon/checkpoint.go index 5a39652cdf3..5386ab019e9 100644 --- a/cmd/devnet/services/polygon/checkpoint.go +++ b/cmd/devnet/services/polygon/checkpoint.go @@ -10,6 +10,8 @@ import ( "strings" "time" + "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" + "github.com/ledgerwatch/erigon-lib/chain/networkname" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/hexutility" @@ -19,7 +21,6 @@ import ( "github.com/ledgerwatch/erigon/cmd/devnet/contracts" "github.com/ledgerwatch/erigon/cmd/devnet/devnet" "github.com/ledgerwatch/erigon/cmd/devnet/requests" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/checkpoint" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/crypto" ) diff --git a/cmd/devnet/services/polygon/heimdall.go b/cmd/devnet/services/polygon/heimdall.go index b3748cad48f..8e00cecd414 100644 --- a/cmd/devnet/services/polygon/heimdall.go +++ b/cmd/devnet/services/polygon/heimdall.go @@ -10,6 +10,11 @@ import ( "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" + "github.com/ledgerwatch/erigon/polygon/heimdall/heimdallgrpc" + "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" + "github.com/ledgerwatch/erigon/polygon/heimdall/span" + ethereum "github.com/ledgerwatch/erigon" "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" @@ -18,12 +23,8 @@ import ( "github.com/ledgerwatch/erigon/cmd/devnet/blocks" "github.com/ledgerwatch/erigon/cmd/devnet/contracts" "github.com/ledgerwatch/erigon/cmd/devnet/devnet" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/checkpoint" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/milestone" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" - "github.com/ledgerwatch/erigon/consensus/bor/heimdallgrpc" - "github.com/ledgerwatch/erigon/consensus/bor/valset" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/valset" ) type BridgeEvent string diff --git a/cmd/devnet/services/polygon/proofgenerator_test.go b/cmd/devnet/services/polygon/proofgenerator_test.go index f5e53cbd58d..4fc3829d86d 100644 --- a/cmd/devnet/services/polygon/proofgenerator_test.go +++ b/cmd/devnet/services/polygon/proofgenerator_test.go @@ -11,6 +11,11 @@ import ( "testing" "github.com/holiman/uint256" + "github.com/ledgerwatch/log/v3" + "github.com/pion/randutil" + + "github.com/ledgerwatch/erigon/polygon/heimdall/span" + "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon-lib/common" libcommon "github.com/ledgerwatch/erigon-lib/common" @@ -21,10 +26,6 @@ import ( "github.com/ledgerwatch/erigon/cmd/devnet/blocks" "github.com/ledgerwatch/erigon/cmd/devnet/requests" "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/consensus/bor" - "github.com/ledgerwatch/erigon/consensus/bor/contract" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" - "github.com/ledgerwatch/erigon/consensus/bor/valset" "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/state" @@ -32,14 +33,15 @@ import ( "github.com/ledgerwatch/erigon/core/vm" "github.com/ledgerwatch/erigon/crypto" "github.com/ledgerwatch/erigon/params" + "github.com/ledgerwatch/erigon/polygon/bor" + "github.com/ledgerwatch/erigon/polygon/bor/contract" + "github.com/ledgerwatch/erigon/polygon/bor/valset" "github.com/ledgerwatch/erigon/rlp" "github.com/ledgerwatch/erigon/rpc" "github.com/ledgerwatch/erigon/turbo/jsonrpc" "github.com/ledgerwatch/erigon/turbo/services" "github.com/ledgerwatch/erigon/turbo/stages/mock" "github.com/ledgerwatch/erigon/turbo/transactions" - "github.com/ledgerwatch/log/v3" - "github.com/pion/randutil" ) type requestGenerator struct { diff --git a/cmd/devnet/services/polygon/statesync.go b/cmd/devnet/services/polygon/statesync.go index 0429f5085db..ed7232ae59c 100644 --- a/cmd/devnet/services/polygon/statesync.go +++ b/cmd/devnet/services/polygon/statesync.go @@ -9,7 +9,7 @@ import ( "github.com/ledgerwatch/erigon/accounts/abi/bind" "github.com/ledgerwatch/erigon/cmd/devnet/contracts" - "github.com/ledgerwatch/erigon/consensus/bor/clerk" + "github.com/ledgerwatch/erigon/polygon/bor/clerk" ) // Maximum allowed event record data size diff --git a/cmd/integration/commands/stages.go b/cmd/integration/commands/stages.go index f8a824177ac..386fc86f91a 100644 --- a/cmd/integration/commands/stages.go +++ b/cmd/integration/commands/stages.go @@ -18,12 +18,13 @@ import ( "github.com/spf13/cobra" "golang.org/x/exp/slices" - "github.com/ledgerwatch/erigon/consensus/bor" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall" - "github.com/ledgerwatch/erigon/consensus/bor/heimdallgrpc" + "github.com/ledgerwatch/erigon/polygon/heimdall" + "github.com/ledgerwatch/erigon/polygon/heimdall/heimdallgrpc" + "github.com/ledgerwatch/erigon/core/rawdb/blockio" "github.com/ledgerwatch/erigon/node/nodecfg" "github.com/ledgerwatch/erigon/p2p/sentry/sentry_multi_client" + "github.com/ledgerwatch/erigon/polygon/bor" "github.com/ledgerwatch/erigon/turbo/builder" "github.com/ledgerwatch/erigon/turbo/snapshotsync/freezeblocks" diff --git a/cmd/rpcdaemon/cli/config.go b/cmd/rpcdaemon/cli/config.go index ed29b8a4d49..34f8f438c92 100644 --- a/cmd/rpcdaemon/cli/config.go +++ b/cmd/rpcdaemon/cli/config.go @@ -13,6 +13,8 @@ import ( "strings" "time" + "github.com/ledgerwatch/erigon/polygon/heimdall/span" + "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon-lib/chain/snapcfg" libcommon "github.com/ledgerwatch/erigon-lib/common" @@ -23,15 +25,14 @@ import ( "github.com/ledgerwatch/erigon-lib/kv/rawdbv3" libstate "github.com/ledgerwatch/erigon-lib/state" "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/consensus/bor" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" - "github.com/ledgerwatch/erigon/consensus/bor/contract" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" "github.com/ledgerwatch/erigon/consensus/ethash" "github.com/ledgerwatch/erigon/core/state/temporal" "github.com/ledgerwatch/erigon/core/systemcontracts" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/eth/ethconfig" + "github.com/ledgerwatch/erigon/polygon/bor" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/contract" "github.com/ledgerwatch/erigon/rpc/rpccfg" "github.com/ledgerwatch/erigon/turbo/debug" "github.com/ledgerwatch/erigon/turbo/logging" diff --git a/consensus/misc/eip1559.go b/consensus/misc/eip1559.go index e7729a4bef9..de5b4ec0118 100644 --- a/consensus/misc/eip1559.go +++ b/consensus/misc/eip1559.go @@ -22,7 +22,7 @@ import ( "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" "github.com/ledgerwatch/erigon/common/math" "github.com/ledgerwatch/erigon/core/types" diff --git a/core/rawdb/accessors_metadata.go b/core/rawdb/accessors_metadata.go index c2ee9218bca..73292258960 100644 --- a/core/rawdb/accessors_metadata.go +++ b/core/rawdb/accessors_metadata.go @@ -19,7 +19,7 @@ package rawdb import ( "encoding/json" "fmt" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" diff --git a/core/system_contract_lookup.go b/core/system_contract_lookup.go index 6b6908dda69..dc0805a1940 100644 --- a/core/system_contract_lookup.go +++ b/core/system_contract_lookup.go @@ -7,7 +7,7 @@ import ( "github.com/ledgerwatch/erigon-lib/chain/networkname" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/hexutility" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" "github.com/ledgerwatch/erigon/core/systemcontracts" "github.com/ledgerwatch/erigon/core/types" diff --git a/eth/backend.go b/eth/backend.go index c15a08f756f..bbec2e31c8e 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -79,10 +79,6 @@ import ( "github.com/ledgerwatch/erigon/cmd/rpcdaemon/cli" "github.com/ledgerwatch/erigon/common/debug" "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/consensus/bor" - "github.com/ledgerwatch/erigon/consensus/bor/finality/flags" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall" - "github.com/ledgerwatch/erigon/consensus/bor/heimdallgrpc" "github.com/ledgerwatch/erigon/consensus/clique" "github.com/ledgerwatch/erigon/consensus/ethash" "github.com/ledgerwatch/erigon/consensus/merge" @@ -110,6 +106,10 @@ import ( "github.com/ledgerwatch/erigon/p2p/sentry" "github.com/ledgerwatch/erigon/p2p/sentry/sentry_multi_client" "github.com/ledgerwatch/erigon/params" + "github.com/ledgerwatch/erigon/polygon/bor" + "github.com/ledgerwatch/erigon/polygon/bor/finality/flags" + "github.com/ledgerwatch/erigon/polygon/heimdall" + "github.com/ledgerwatch/erigon/polygon/heimdall/heimdallgrpc" "github.com/ledgerwatch/erigon/rpc" "github.com/ledgerwatch/erigon/turbo/builder" "github.com/ledgerwatch/erigon/turbo/engineapi" diff --git a/eth/ethconsensusconfig/config.go b/eth/ethconsensusconfig/config.go index 04bf7cc08c1..5eb4399f3a1 100644 --- a/eth/ethconsensusconfig/config.go +++ b/eth/ethconsensusconfig/config.go @@ -8,15 +8,14 @@ import ( "github.com/ledgerwatch/log/v3" "github.com/ledgerwatch/erigon-lib/chain" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" + + "github.com/ledgerwatch/erigon/polygon/heimdall" + "github.com/ledgerwatch/erigon/polygon/heimdall/span" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/consensus/aura" - "github.com/ledgerwatch/erigon/consensus/bor" - "github.com/ledgerwatch/erigon/consensus/bor/contract" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" "github.com/ledgerwatch/erigon/consensus/clique" "github.com/ledgerwatch/erigon/consensus/ethash" "github.com/ledgerwatch/erigon/consensus/ethash/ethashcfg" @@ -24,6 +23,8 @@ import ( "github.com/ledgerwatch/erigon/node" "github.com/ledgerwatch/erigon/node/nodecfg" "github.com/ledgerwatch/erigon/params" + "github.com/ledgerwatch/erigon/polygon/bor" + "github.com/ledgerwatch/erigon/polygon/bor/contract" "github.com/ledgerwatch/erigon/turbo/services" ) diff --git a/eth/stagedsync/bor_heimdall_shared.go b/eth/stagedsync/bor_heimdall_shared.go index 281774c5d16..323d443eada 100644 --- a/eth/stagedsync/bor_heimdall_shared.go +++ b/eth/stagedsync/bor_heimdall_shared.go @@ -14,9 +14,9 @@ import ( "github.com/ledgerwatch/log/v3" "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/polygon/heimdall" + "github.com/ledgerwatch/erigon/polygon/heimdall/span" "github.com/ledgerwatch/erigon/rlp" "github.com/ledgerwatch/erigon/turbo/services" ) diff --git a/eth/stagedsync/stage_bor_heimdall.go b/eth/stagedsync/stage_bor_heimdall.go index 9eebb6c50e0..a6953b3702c 100644 --- a/eth/stagedsync/stage_bor_heimdall.go +++ b/eth/stagedsync/stage_bor_heimdall.go @@ -19,18 +19,18 @@ import ( "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon/accounts/abi" "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/consensus/bor" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" - "github.com/ledgerwatch/erigon/consensus/bor/contract" - "github.com/ledgerwatch/erigon/consensus/bor/finality/generics" - "github.com/ledgerwatch/erigon/consensus/bor/finality/whitelist" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" - "github.com/ledgerwatch/erigon/consensus/bor/valset" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/dataflow" "github.com/ledgerwatch/erigon/eth/ethconfig/estimate" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" + "github.com/ledgerwatch/erigon/polygon/bor" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/contract" + "github.com/ledgerwatch/erigon/polygon/bor/finality/generics" + "github.com/ledgerwatch/erigon/polygon/bor/finality/whitelist" + "github.com/ledgerwatch/erigon/polygon/bor/valset" + "github.com/ledgerwatch/erigon/polygon/heimdall" + "github.com/ledgerwatch/erigon/polygon/heimdall/span" "github.com/ledgerwatch/erigon/turbo/services" "github.com/ledgerwatch/erigon/turbo/stages/headerdownload" ) diff --git a/eth/stagedsync/stage_bor_heimdall_test.go b/eth/stagedsync/stage_bor_heimdall_test.go index 8a11c7173ca..7da0f8c6988 100644 --- a/eth/stagedsync/stage_bor_heimdall_test.go +++ b/eth/stagedsync/stage_bor_heimdall_test.go @@ -11,14 +11,14 @@ import ( "github.com/ledgerwatch/log/v3" "github.com/stretchr/testify/require" - "github.com/ledgerwatch/erigon/consensus/bor" - "github.com/ledgerwatch/erigon/consensus/bor/valset" "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/crypto" "github.com/ledgerwatch/erigon/eth/stagedsync" "github.com/ledgerwatch/erigon/eth/stagedsync/stagedsynctest" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" + "github.com/ledgerwatch/erigon/polygon/bor" + "github.com/ledgerwatch/erigon/polygon/bor/valset" ) func TestBorHeimdallForwardPersistsSpans(t *testing.T) { diff --git a/eth/stagedsync/stage_mining_bor_heimdall.go b/eth/stagedsync/stage_mining_bor_heimdall.go index 0befc9f1bc6..2dd96a98b85 100644 --- a/eth/stagedsync/stage_mining_bor_heimdall.go +++ b/eth/stagedsync/stage_mining_bor_heimdall.go @@ -7,10 +7,10 @@ import ( "github.com/ledgerwatch/log/v3" "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon/consensus/bor/finality/whitelist" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/dataflow" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" + "github.com/ledgerwatch/erigon/polygon/bor/finality/whitelist" ) func MiningBorHeimdallForward( diff --git a/eth/stagedsync/stage_txlookup.go b/eth/stagedsync/stage_txlookup.go index 197a319099a..67ded81459e 100644 --- a/eth/stagedsync/stage_txlookup.go +++ b/eth/stagedsync/stage_txlookup.go @@ -14,7 +14,7 @@ import ( "github.com/ledgerwatch/erigon-lib/common/hexutility" "github.com/ledgerwatch/erigon-lib/etl" "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" "github.com/ledgerwatch/erigon/turbo/services" "github.com/ledgerwatch/erigon/core/rawdb" diff --git a/eth/stagedsync/stagedsynctest/chain_configs.go b/eth/stagedsync/stagedsynctest/chain_configs.go index 7be90935113..9db9429d327 100644 --- a/eth/stagedsync/stagedsynctest/chain_configs.go +++ b/eth/stagedsync/stagedsynctest/chain_configs.go @@ -2,8 +2,8 @@ package stagedsynctest import ( "github.com/ledgerwatch/erigon-lib/chain" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "github.com/ledgerwatch/erigon/params" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" ) func BorDevnetChainConfigWithNoBlockSealDelays() *chain.Config { diff --git a/eth/stagedsync/stagedsynctest/harness.go b/eth/stagedsync/stagedsynctest/harness.go index bba47ad402d..76fddead0be 100644 --- a/eth/stagedsync/stagedsynctest/harness.go +++ b/eth/stagedsync/stagedsynctest/harness.go @@ -7,29 +7,26 @@ import ( "encoding/json" "errors" "fmt" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "math/big" "testing" "time" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" + "github.com/golang/mock/gomock" "github.com/holiman/uint256" "github.com/ledgerwatch/log/v3" "github.com/stretchr/testify/require" + heimdallmock "github.com/ledgerwatch/erigon/polygon/heimdall/mock" + "github.com/ledgerwatch/erigon/polygon/heimdall/span" + "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/memdb" "github.com/ledgerwatch/erigon-lib/wrap" "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/consensus/bor" - "github.com/ledgerwatch/erigon/consensus/bor/clerk" - "github.com/ledgerwatch/erigon/consensus/bor/contract" - heimdallmock "github.com/ledgerwatch/erigon/consensus/bor/heimdall/mock" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" - bormock "github.com/ledgerwatch/erigon/consensus/bor/mock" - "github.com/ledgerwatch/erigon/consensus/bor/valset" consensusmock "github.com/ledgerwatch/erigon/consensus/mock" "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/core/rawdb" @@ -38,6 +35,11 @@ import ( "github.com/ledgerwatch/erigon/eth/ethconfig" "github.com/ledgerwatch/erigon/eth/stagedsync" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" + "github.com/ledgerwatch/erigon/polygon/bor" + "github.com/ledgerwatch/erigon/polygon/bor/clerk" + "github.com/ledgerwatch/erigon/polygon/bor/contract" + bormock "github.com/ledgerwatch/erigon/polygon/bor/mock" + "github.com/ledgerwatch/erigon/polygon/bor/valset" "github.com/ledgerwatch/erigon/turbo/services" "github.com/ledgerwatch/erigon/turbo/stages/mock" "github.com/ledgerwatch/erigon/turbo/testlog" diff --git a/params/config.go b/params/config.go index 23761442a19..dc0c2c8add6 100644 --- a/params/config.go +++ b/params/config.go @@ -26,7 +26,7 @@ import ( "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon-lib/chain/networkname" libcommon "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" "github.com/ledgerwatch/erigon/common/paths" ) diff --git a/consensus/bor/abi/interface.go b/polygon/bor/abi/interface.go similarity index 100% rename from consensus/bor/abi/interface.go rename to polygon/bor/abi/interface.go diff --git a/consensus/bor/bor.go b/polygon/bor/bor.go similarity index 99% rename from consensus/bor/bor.go rename to polygon/bor/bor.go index e20f172087e..e3c31bdee75 100644 --- a/consensus/bor/bor.go +++ b/polygon/bor/bor.go @@ -22,20 +22,15 @@ import ( "golang.org/x/crypto/sha3" "golang.org/x/sync/errgroup" + "github.com/ledgerwatch/erigon/polygon/heimdall" + "github.com/ledgerwatch/erigon/polygon/heimdall/span" + "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/length" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon/common" "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" - "github.com/ledgerwatch/erigon/consensus/bor/finality" - "github.com/ledgerwatch/erigon/consensus/bor/finality/flags" - "github.com/ledgerwatch/erigon/consensus/bor/finality/whitelist" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" - "github.com/ledgerwatch/erigon/consensus/bor/statefull" - "github.com/ledgerwatch/erigon/consensus/bor/valset" "github.com/ledgerwatch/erigon/consensus/misc" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/state" @@ -45,6 +40,12 @@ import ( "github.com/ledgerwatch/erigon/crypto/cryptopool" "github.com/ledgerwatch/erigon/eth/ethconfig/estimate" "github.com/ledgerwatch/erigon/params" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/finality" + "github.com/ledgerwatch/erigon/polygon/bor/finality/flags" + "github.com/ledgerwatch/erigon/polygon/bor/finality/whitelist" + "github.com/ledgerwatch/erigon/polygon/bor/statefull" + "github.com/ledgerwatch/erigon/polygon/bor/valset" "github.com/ledgerwatch/erigon/rlp" "github.com/ledgerwatch/erigon/rpc" "github.com/ledgerwatch/erigon/turbo/services" diff --git a/consensus/bor/bor_test.go b/polygon/bor/bor_test.go similarity index 96% rename from consensus/bor/bor_test.go rename to polygon/bor/bor_test.go index 54744a7301f..c1341fb0286 100644 --- a/consensus/bor/bor_test.go +++ b/polygon/bor/bor_test.go @@ -4,32 +4,35 @@ import ( "context" "encoding/json" "fmt" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" "math/big" "testing" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" + + "github.com/ledgerwatch/log/v3" + + "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" + "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" + "github.com/ledgerwatch/erigon/polygon/heimdall/span" + "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon-lib/common" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/gointerfaces/sentry" "github.com/ledgerwatch/erigon-lib/kv/memdb" "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/consensus/bor" - "github.com/ledgerwatch/erigon/consensus/bor/clerk" - "github.com/ledgerwatch/erigon/consensus/bor/contract" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/checkpoint" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/milestone" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" - "github.com/ledgerwatch/erigon/consensus/bor/valset" "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/crypto" "github.com/ledgerwatch/erigon/eth/protocols/eth" "github.com/ledgerwatch/erigon/ethdb/prune" "github.com/ledgerwatch/erigon/params" + "github.com/ledgerwatch/erigon/polygon/bor" + "github.com/ledgerwatch/erigon/polygon/bor/clerk" + "github.com/ledgerwatch/erigon/polygon/bor/contract" + "github.com/ledgerwatch/erigon/polygon/bor/valset" "github.com/ledgerwatch/erigon/rlp" "github.com/ledgerwatch/erigon/turbo/stages/mock" - "github.com/ledgerwatch/log/v3" ) type test_heimdall struct { diff --git a/consensus/bor/borcfg/bor_config.go b/polygon/bor/borcfg/bor_config.go similarity index 100% rename from consensus/bor/borcfg/bor_config.go rename to polygon/bor/borcfg/bor_config.go diff --git a/consensus/bor/borcfg/bor_config_test.go b/polygon/bor/borcfg/bor_config_test.go similarity index 100% rename from consensus/bor/borcfg/bor_config_test.go rename to polygon/bor/borcfg/bor_config_test.go diff --git a/consensus/bor/clerk/clerk.go b/polygon/bor/clerk/clerk.go similarity index 100% rename from consensus/bor/clerk/clerk.go rename to polygon/bor/clerk/clerk.go diff --git a/consensus/bor/contract/client.go b/polygon/bor/contract/client.go similarity index 100% rename from consensus/bor/contract/client.go rename to polygon/bor/contract/client.go diff --git a/consensus/bor/errors.go b/polygon/bor/errors.go similarity index 97% rename from consensus/bor/errors.go rename to polygon/bor/errors.go index c70aff344a0..1b33eb634df 100644 --- a/consensus/bor/errors.go +++ b/polygon/bor/errors.go @@ -4,7 +4,7 @@ import ( "fmt" "time" - "github.com/ledgerwatch/erigon/consensus/bor/clerk" + "github.com/ledgerwatch/erigon/polygon/bor/clerk" ) type MaxCheckpointLengthExceededError struct { diff --git a/consensus/bor/fake.go b/polygon/bor/fake.go similarity index 100% rename from consensus/bor/fake.go rename to polygon/bor/fake.go diff --git a/consensus/bor/finality/api.go b/polygon/bor/finality/api.go similarity index 95% rename from consensus/bor/finality/api.go rename to polygon/bor/finality/api.go index 288080e570b..5df9ff2ca22 100644 --- a/consensus/bor/finality/api.go +++ b/polygon/bor/finality/api.go @@ -3,9 +3,9 @@ package finality import ( "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon/consensus/bor/finality/whitelist" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/polygon/bor/finality/whitelist" ) func GetFinalizedBlockNumber(tx kv.Tx) uint64 { diff --git a/consensus/bor/finality/bor_verifier.go b/polygon/bor/finality/bor_verifier.go similarity index 97% rename from consensus/bor/finality/bor_verifier.go rename to polygon/bor/finality/bor_verifier.go index a8dde9dc1ce..1cbb566e0dc 100644 --- a/consensus/bor/finality/bor_verifier.go +++ b/polygon/bor/finality/bor_verifier.go @@ -9,9 +9,9 @@ import ( "github.com/ledgerwatch/log/v3" "github.com/ledgerwatch/erigon-lib/metrics" - "github.com/ledgerwatch/erigon/consensus/bor/finality/generics" - "github.com/ledgerwatch/erigon/consensus/bor/finality/whitelist" "github.com/ledgerwatch/erigon/core/rawdb" + "github.com/ledgerwatch/erigon/polygon/bor/finality/generics" + "github.com/ledgerwatch/erigon/polygon/bor/finality/whitelist" ) var ( diff --git a/consensus/bor/finality/flags/flags.go b/polygon/bor/finality/flags/flags.go similarity index 100% rename from consensus/bor/finality/flags/flags.go rename to polygon/bor/finality/flags/flags.go diff --git a/consensus/bor/finality/generics/generics.go b/polygon/bor/finality/generics/generics.go similarity index 100% rename from consensus/bor/finality/generics/generics.go rename to polygon/bor/finality/generics/generics.go diff --git a/consensus/bor/finality/rawdb/checkpoint.go b/polygon/bor/finality/rawdb/checkpoint.go similarity index 100% rename from consensus/bor/finality/rawdb/checkpoint.go rename to polygon/bor/finality/rawdb/checkpoint.go diff --git a/consensus/bor/finality/rawdb/milestone.go b/polygon/bor/finality/rawdb/milestone.go similarity index 98% rename from consensus/bor/finality/rawdb/milestone.go rename to polygon/bor/finality/rawdb/milestone.go index d5ac8f49621..db748a42f73 100644 --- a/consensus/bor/finality/rawdb/milestone.go +++ b/polygon/bor/finality/rawdb/milestone.go @@ -7,7 +7,7 @@ import ( libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon/consensus/bor/finality/generics" + "github.com/ledgerwatch/erigon/polygon/bor/finality/generics" "github.com/ledgerwatch/log/v3" ) diff --git a/consensus/bor/finality/whitelist.go b/polygon/bor/finality/whitelist.go similarity index 97% rename from consensus/bor/finality/whitelist.go rename to polygon/bor/finality/whitelist.go index 76abfcc0d35..60a2731eb1b 100644 --- a/consensus/bor/finality/whitelist.go +++ b/polygon/bor/finality/whitelist.go @@ -6,12 +6,14 @@ import ( "fmt" "time" + "github.com/ledgerwatch/log/v3" + + "github.com/ledgerwatch/erigon/polygon/heimdall" + "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon/consensus/bor/finality/flags" - "github.com/ledgerwatch/erigon/consensus/bor/finality/whitelist" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall" + "github.com/ledgerwatch/erigon/polygon/bor/finality/flags" + "github.com/ledgerwatch/erigon/polygon/bor/finality/whitelist" "github.com/ledgerwatch/erigon/turbo/services" - "github.com/ledgerwatch/log/v3" ) type config struct { diff --git a/consensus/bor/finality/whitelist/checkpoint.go b/polygon/bor/finality/whitelist/checkpoint.go similarity index 94% rename from consensus/bor/finality/whitelist/checkpoint.go rename to polygon/bor/finality/whitelist/checkpoint.go index fc4a1443610..fd33dd656f0 100644 --- a/consensus/bor/finality/whitelist/checkpoint.go +++ b/polygon/bor/finality/whitelist/checkpoint.go @@ -3,8 +3,8 @@ package whitelist import ( "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/metrics" - "github.com/ledgerwatch/erigon/consensus/bor/finality/rawdb" "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/polygon/bor/finality/rawdb" ) type checkpoint struct { diff --git a/consensus/bor/finality/whitelist/finality.go b/polygon/bor/finality/whitelist/finality.go similarity index 96% rename from consensus/bor/finality/whitelist/finality.go rename to polygon/bor/finality/whitelist/finality.go index f1abbbf3df6..9469a95c91f 100644 --- a/consensus/bor/finality/whitelist/finality.go +++ b/polygon/bor/finality/whitelist/finality.go @@ -5,8 +5,8 @@ import ( "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon/consensus/bor/finality/rawdb" "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/polygon/bor/finality/rawdb" "github.com/ledgerwatch/log/v3" ) diff --git a/consensus/bor/finality/whitelist/milestone.go b/polygon/bor/finality/whitelist/milestone.go similarity index 98% rename from consensus/bor/finality/whitelist/milestone.go rename to polygon/bor/finality/whitelist/milestone.go index 0d80ed4b5a7..b4777c13cae 100644 --- a/consensus/bor/finality/whitelist/milestone.go +++ b/polygon/bor/finality/whitelist/milestone.go @@ -5,9 +5,9 @@ import ( "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/metrics" - "github.com/ledgerwatch/erigon/consensus/bor/finality/flags" - "github.com/ledgerwatch/erigon/consensus/bor/finality/rawdb" "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/polygon/bor/finality/flags" + "github.com/ledgerwatch/erigon/polygon/bor/finality/rawdb" ) type milestone struct { diff --git a/consensus/bor/finality/whitelist/service.go b/polygon/bor/finality/whitelist/service.go similarity index 98% rename from consensus/bor/finality/whitelist/service.go rename to polygon/bor/finality/whitelist/service.go index 7bf7aa89819..14dec13d799 100644 --- a/consensus/bor/finality/whitelist/service.go +++ b/polygon/bor/finality/whitelist/service.go @@ -5,8 +5,8 @@ import ( "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon/consensus/bor/finality/rawdb" "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/polygon/bor/finality/rawdb" ) var ( diff --git a/consensus/bor/finality/whitelist/service_test.go b/polygon/bor/finality/whitelist/service_test.go similarity index 99% rename from consensus/bor/finality/whitelist/service_test.go rename to polygon/bor/finality/whitelist/service_test.go index 0a45e6fe712..62fe3651dea 100644 --- a/consensus/bor/finality/whitelist/service_test.go +++ b/polygon/bor/finality/whitelist/service_test.go @@ -12,8 +12,8 @@ import ( libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/memdb" - "github.com/ledgerwatch/erigon/consensus/bor/finality/rawdb" "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/polygon/bor/finality/rawdb" "github.com/stretchr/testify/require" "pgregory.net/rapid" diff --git a/consensus/bor/finality/whitelist_helpers.go b/polygon/bor/finality/whitelist_helpers.go similarity index 97% rename from consensus/bor/finality/whitelist_helpers.go rename to polygon/bor/finality/whitelist_helpers.go index ddeb1e19dfb..b5d28cad084 100644 --- a/consensus/bor/finality/whitelist_helpers.go +++ b/polygon/bor/finality/whitelist_helpers.go @@ -4,10 +4,12 @@ import ( "context" "errors" - "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon/consensus/bor/finality/whitelist" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall" "github.com/ledgerwatch/log/v3" + + "github.com/ledgerwatch/erigon/polygon/heimdall" + + "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon/polygon/bor/finality/whitelist" ) var ( diff --git a/consensus/bor/genesis_contract.go b/polygon/bor/genesis_contract.go similarity index 100% rename from consensus/bor/genesis_contract.go rename to polygon/bor/genesis_contract.go diff --git a/consensus/bor/merkle.go b/polygon/bor/merkle.go similarity index 100% rename from consensus/bor/merkle.go rename to polygon/bor/merkle.go diff --git a/consensus/bor/mock/genesis_contract_mock.go b/polygon/bor/mock/genesis_contract_mock.go similarity index 96% rename from consensus/bor/mock/genesis_contract_mock.go rename to polygon/bor/mock/genesis_contract_mock.go index 9ad12ae63d4..475ae6ece49 100644 --- a/consensus/bor/mock/genesis_contract_mock.go +++ b/polygon/bor/mock/genesis_contract_mock.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/ledgerwatch/erigon/consensus/bor (interfaces: GenesisContract) +// Source: github.com/ledgerwatch/erigon/polygon/bor (interfaces: GenesisContract) // Package mock is a generated GoMock package. package mock diff --git a/consensus/bor/mock/spanner_mock.go b/polygon/bor/mock/spanner_mock.go similarity index 94% rename from consensus/bor/mock/spanner_mock.go rename to polygon/bor/mock/spanner_mock.go index 70db933edd2..07c9b881bad 100644 --- a/consensus/bor/mock/spanner_mock.go +++ b/polygon/bor/mock/spanner_mock.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/ledgerwatch/erigon/consensus/bor (interfaces: Spanner) +// Source: github.com/ledgerwatch/erigon/polygon/bor (interfaces: Spanner) // Package mock is a generated GoMock package. package mock @@ -10,8 +10,8 @@ import ( gomock "github.com/golang/mock/gomock" common "github.com/ledgerwatch/erigon-lib/common" consensus "github.com/ledgerwatch/erigon/consensus" - span "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" - valset "github.com/ledgerwatch/erigon/consensus/bor/valset" + span "github.com/ledgerwatch/erigon/polygon/heimdall/span" + valset "github.com/ledgerwatch/erigon/polygon/bor/valset" ) // MockSpanner is a mock of Spanner interface. diff --git a/consensus/bor/snapshot.go b/polygon/bor/snapshot.go similarity index 98% rename from consensus/bor/snapshot.go rename to polygon/bor/snapshot.go index 8eabd324172..7d055164807 100644 --- a/consensus/bor/snapshot.go +++ b/polygon/bor/snapshot.go @@ -10,9 +10,9 @@ import ( "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" - "github.com/ledgerwatch/erigon/consensus/bor/valset" "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/valset" ) // Snapshot is the state of the authorization voting at a given point in time. diff --git a/consensus/bor/snapshot_test.go b/polygon/bor/snapshot_test.go similarity index 97% rename from consensus/bor/snapshot_test.go rename to polygon/bor/snapshot_test.go index d3d827ab31b..c5bdb215452 100644 --- a/consensus/bor/snapshot_test.go +++ b/polygon/bor/snapshot_test.go @@ -6,8 +6,8 @@ import ( "testing" libcommon "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon/consensus/bor" - "github.com/ledgerwatch/erigon/consensus/bor/valset" + "github.com/ledgerwatch/erigon/polygon/bor" + "github.com/ledgerwatch/erigon/polygon/bor/valset" "github.com/ledgerwatch/log/v3" "github.com/maticnetwork/crand" "github.com/stretchr/testify/require" diff --git a/consensus/bor/spanner.go b/polygon/bor/spanner.go similarity index 84% rename from consensus/bor/spanner.go rename to polygon/bor/spanner.go index 77769ea835e..ab7710dd558 100644 --- a/consensus/bor/spanner.go +++ b/polygon/bor/spanner.go @@ -1,10 +1,11 @@ package bor import ( + "github.com/ledgerwatch/erigon/polygon/heimdall/span" + libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" - "github.com/ledgerwatch/erigon/consensus/bor/valset" + "github.com/ledgerwatch/erigon/polygon/bor/valset" ) //go:generate mockgen -destination=./mock/spanner_mock.go -package=mock . Spanner diff --git a/consensus/bor/statefull/processor.go b/polygon/bor/statefull/processor.go similarity index 100% rename from consensus/bor/statefull/processor.go rename to polygon/bor/statefull/processor.go diff --git a/consensus/bor/valset/error.go b/polygon/bor/valset/error.go similarity index 100% rename from consensus/bor/valset/error.go rename to polygon/bor/valset/error.go diff --git a/consensus/bor/valset/validator.go b/polygon/bor/valset/validator.go similarity index 100% rename from consensus/bor/valset/validator.go rename to polygon/bor/valset/validator.go diff --git a/consensus/bor/valset/validator_set.go b/polygon/bor/valset/validator_set.go similarity index 100% rename from consensus/bor/valset/validator_set.go rename to polygon/bor/valset/validator_set.go diff --git a/consensus/bor/heimdall/checkpoint/checkpoint.go b/polygon/heimdall/checkpoint/checkpoint.go similarity index 100% rename from consensus/bor/heimdall/checkpoint/checkpoint.go rename to polygon/heimdall/checkpoint/checkpoint.go diff --git a/consensus/bor/heimdall/client.go b/polygon/heimdall/client.go similarity index 98% rename from consensus/bor/heimdall/client.go rename to polygon/heimdall/client.go index 0085a636024..6b2f83c6fc1 100644 --- a/consensus/bor/heimdall/client.go +++ b/polygon/heimdall/client.go @@ -15,11 +15,12 @@ import ( "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" + "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" + "github.com/ledgerwatch/erigon/polygon/heimdall/span" + "github.com/ledgerwatch/erigon-lib/metrics" - "github.com/ledgerwatch/erigon/consensus/bor/clerk" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/checkpoint" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/milestone" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" + "github.com/ledgerwatch/erigon/polygon/bor/clerk" ) var ( diff --git a/consensus/bor/heimdall/client_test.go b/polygon/heimdall/client_test.go similarity index 96% rename from consensus/bor/heimdall/client_test.go rename to polygon/heimdall/client_test.go index 8f3c88e7671..b8804bba64d 100644 --- a/consensus/bor/heimdall/client_test.go +++ b/polygon/heimdall/client_test.go @@ -11,7 +11,8 @@ import ( "github.com/ledgerwatch/log/v3" "github.com/stretchr/testify/require" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/mock" + "github.com/ledgerwatch/erigon/polygon/heimdall/mock" + "github.com/ledgerwatch/erigon/turbo/testlog" ) diff --git a/consensus/bor/heimdall/heimdall.go b/polygon/heimdall/heimdall.go similarity index 85% rename from consensus/bor/heimdall/heimdall.go rename to polygon/heimdall/heimdall.go index 6d81f1aac2b..673a5ff4a77 100644 --- a/consensus/bor/heimdall/heimdall.go +++ b/polygon/heimdall/heimdall.go @@ -3,11 +3,12 @@ package heimdall import ( "context" - "github.com/ledgerwatch/erigon/consensus/bor/clerk" - "github.com/ledgerwatch/erigon/consensus/bor/finality/generics" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/checkpoint" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/milestone" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" + "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" + "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" + "github.com/ledgerwatch/erigon/polygon/heimdall/span" + + "github.com/ledgerwatch/erigon/polygon/bor/clerk" + "github.com/ledgerwatch/erigon/polygon/bor/finality/generics" ) func MilestoneRewindPending() bool { diff --git a/consensus/bor/heimdallgrpc/checkpoint.go b/polygon/heimdall/heimdallgrpc/checkpoint.go similarity index 94% rename from consensus/bor/heimdallgrpc/checkpoint.go rename to polygon/heimdall/heimdallgrpc/checkpoint.go index 17a86ae9e38..f02398a3b37 100644 --- a/consensus/bor/heimdallgrpc/checkpoint.go +++ b/polygon/heimdall/heimdallgrpc/checkpoint.go @@ -4,7 +4,7 @@ import ( "context" "math/big" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/checkpoint" + "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" proto "github.com/maticnetwork/polyproto/heimdall" protoutils "github.com/maticnetwork/polyproto/utils" diff --git a/consensus/bor/heimdallgrpc/client.go b/polygon/heimdall/heimdallgrpc/client.go similarity index 100% rename from consensus/bor/heimdallgrpc/client.go rename to polygon/heimdall/heimdallgrpc/client.go diff --git a/consensus/bor/heimdallgrpc/milestone.go b/polygon/heimdall/heimdallgrpc/milestone.go similarity index 97% rename from consensus/bor/heimdallgrpc/milestone.go rename to polygon/heimdall/heimdallgrpc/milestone.go index a42bab955c5..a20b4d7dc3b 100644 --- a/consensus/bor/heimdallgrpc/milestone.go +++ b/polygon/heimdall/heimdallgrpc/milestone.go @@ -5,7 +5,7 @@ import ( "fmt" "math/big" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/milestone" + "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" proto "github.com/maticnetwork/polyproto/heimdall" protoutils "github.com/maticnetwork/polyproto/utils" diff --git a/consensus/bor/heimdallgrpc/server.go b/polygon/heimdall/heimdallgrpc/server.go similarity index 99% rename from consensus/bor/heimdallgrpc/server.go rename to polygon/heimdall/heimdallgrpc/server.go index 8139c33ddac..ea0ee45ad9e 100644 --- a/consensus/bor/heimdallgrpc/server.go +++ b/polygon/heimdall/heimdallgrpc/server.go @@ -6,8 +6,6 @@ import ( "net" "time" - "github.com/ledgerwatch/erigon-lib/gointerfaces" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall" "github.com/ledgerwatch/log/v3" proto "github.com/maticnetwork/polyproto/heimdall" "google.golang.org/grpc" @@ -15,6 +13,10 @@ import ( "google.golang.org/grpc/status" "google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/ledgerwatch/erigon/polygon/heimdall" + + "github.com/ledgerwatch/erigon-lib/gointerfaces" ) type HeimdallGRPCServer struct { diff --git a/consensus/bor/heimdallgrpc/span.go b/polygon/heimdall/heimdallgrpc/span.go similarity index 93% rename from consensus/bor/heimdallgrpc/span.go rename to polygon/heimdall/heimdallgrpc/span.go index 7bc6ddb8f78..9d9a24b787e 100644 --- a/consensus/bor/heimdallgrpc/span.go +++ b/polygon/heimdall/heimdallgrpc/span.go @@ -3,8 +3,9 @@ package heimdallgrpc import ( "context" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" - "github.com/ledgerwatch/erigon/consensus/bor/valset" + "github.com/ledgerwatch/erigon/polygon/heimdall/span" + + "github.com/ledgerwatch/erigon/polygon/bor/valset" proto "github.com/maticnetwork/polyproto/heimdall" protoutils "github.com/maticnetwork/polyproto/utils" diff --git a/consensus/bor/heimdallgrpc/state_sync.go b/polygon/heimdall/heimdallgrpc/state_sync.go similarity index 96% rename from consensus/bor/heimdallgrpc/state_sync.go rename to polygon/heimdall/heimdallgrpc/state_sync.go index e1b49e67d93..0d32a1908e3 100644 --- a/consensus/bor/heimdallgrpc/state_sync.go +++ b/polygon/heimdall/heimdallgrpc/state_sync.go @@ -6,7 +6,7 @@ import ( "io" libcommon "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon/consensus/bor/clerk" + "github.com/ledgerwatch/erigon/polygon/bor/clerk" proto "github.com/maticnetwork/polyproto/heimdall" ) diff --git a/consensus/bor/heimdall/metrics.go b/polygon/heimdall/metrics.go similarity index 100% rename from consensus/bor/heimdall/metrics.go rename to polygon/heimdall/metrics.go diff --git a/consensus/bor/heimdall/milestone/milestone.go b/polygon/heimdall/milestone/milestone.go similarity index 100% rename from consensus/bor/heimdall/milestone/milestone.go rename to polygon/heimdall/milestone/milestone.go diff --git a/consensus/bor/heimdall/mock/heimdall_client_mock.go b/polygon/heimdall/mock/heimdall_client_mock.go similarity index 94% rename from consensus/bor/heimdall/mock/heimdall_client_mock.go rename to polygon/heimdall/mock/heimdall_client_mock.go index e7d29b17ee6..de176271602 100644 --- a/consensus/bor/heimdall/mock/heimdall_client_mock.go +++ b/polygon/heimdall/mock/heimdall_client_mock.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/ledgerwatch/erigon/consensus/bor/heimdall (interfaces: IHeimdallClient) +// Source: github.com/ledgerwatch/erigon/polygon/heimdall (interfaces: IHeimdallClient) // Package mock is a generated GoMock package. package mock @@ -9,10 +9,10 @@ import ( reflect "reflect" gomock "github.com/golang/mock/gomock" - clerk "github.com/ledgerwatch/erigon/consensus/bor/clerk" - checkpoint "github.com/ledgerwatch/erigon/consensus/bor/heimdall/checkpoint" - milestone "github.com/ledgerwatch/erigon/consensus/bor/heimdall/milestone" - span "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" + clerk "github.com/ledgerwatch/erigon/polygon/bor/clerk" + checkpoint "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" + milestone "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" + span "github.com/ledgerwatch/erigon/polygon/heimdall/span" ) // MockIHeimdallClient is a mock of IHeimdallClient interface. diff --git a/consensus/bor/heimdall/mock/http_client_mock.go b/polygon/heimdall/mock/http_client_mock.go similarity index 95% rename from consensus/bor/heimdall/mock/http_client_mock.go rename to polygon/heimdall/mock/http_client_mock.go index aa6310b1715..b41cfa8f139 100644 --- a/consensus/bor/heimdall/mock/http_client_mock.go +++ b/polygon/heimdall/mock/http_client_mock.go @@ -1,5 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. -// Source: github.com/ledgerwatch/erigon/consensus/bor/heimdall (interfaces: HttpClient) +// Source: github.com/ledgerwatch/erigon/polygon/heimdall (interfaces: HttpClient) // Package mock is a generated GoMock package. package mock diff --git a/consensus/bor/heimdall/span/span.go b/polygon/heimdall/span/span.go similarity index 94% rename from consensus/bor/heimdall/span/span.go rename to polygon/heimdall/span/span.go index 22d3dff2563..7ab715b539e 100644 --- a/consensus/bor/heimdall/span/span.go +++ b/polygon/heimdall/span/span.go @@ -2,7 +2,7 @@ package span import ( "github.com/google/btree" - "github.com/ledgerwatch/erigon/consensus/bor/valset" + "github.com/ledgerwatch/erigon/polygon/bor/valset" ) // Span represents a current bor span diff --git a/consensus/bor/heimdall/span/span_id.go b/polygon/heimdall/span/span_id.go similarity index 94% rename from consensus/bor/heimdall/span/span_id.go rename to polygon/heimdall/span/span_id.go index 50955212867..0485aa6fb30 100644 --- a/consensus/bor/heimdall/span/span_id.go +++ b/polygon/heimdall/span/span_id.go @@ -1,7 +1,7 @@ package span import ( - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" ) const ( diff --git a/consensus/bor/heimdall/span/span_id_test.go b/polygon/heimdall/span/span_id_test.go similarity index 95% rename from consensus/bor/heimdall/span/span_id_test.go rename to polygon/heimdall/span/span_id_test.go index a7c80891c7c..34c2b669f16 100644 --- a/consensus/bor/heimdall/span/span_id_test.go +++ b/polygon/heimdall/span/span_id_test.go @@ -5,7 +5,7 @@ import ( "github.com/stretchr/testify/assert" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" ) func TestSpanIDAt(t *testing.T) { diff --git a/consensus/bor/heimdall/span/spanner.go b/polygon/heimdall/span/spanner.go similarity index 96% rename from consensus/bor/heimdall/span/spanner.go rename to polygon/heimdall/span/spanner.go index 9af95abf718..315617f9eff 100644 --- a/consensus/bor/heimdall/span/spanner.go +++ b/polygon/heimdall/span/spanner.go @@ -10,9 +10,9 @@ import ( "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/consensus/bor/abi" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" - "github.com/ledgerwatch/erigon/consensus/bor/valset" + "github.com/ledgerwatch/erigon/polygon/bor/abi" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/valset" "github.com/ledgerwatch/erigon/rlp" ) diff --git a/consensus/bor/heimdall/span/testValidators.go b/polygon/heimdall/span/testValidators.go similarity index 95% rename from consensus/bor/heimdall/span/testValidators.go rename to polygon/heimdall/span/testValidators.go index 29cf1cc2e6a..1dfaa722e5e 100644 --- a/consensus/bor/heimdall/span/testValidators.go +++ b/polygon/heimdall/span/testValidators.go @@ -3,7 +3,7 @@ package span import ( "github.com/ledgerwatch/erigon-lib/chain/networkname" "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon/consensus/bor/valset" + "github.com/ledgerwatch/erigon/polygon/bor/valset" ) // NetworkNameVals is a map of network name to validator set for tests/devnets diff --git a/polygon/sync/canonical_chain_builder.go b/polygon/sync/canonical_chain_builder.go index 9acd3cf07d3..0ddcf2c325b 100644 --- a/polygon/sync/canonical_chain_builder.go +++ b/polygon/sync/canonical_chain_builder.go @@ -5,8 +5,8 @@ import ( "fmt" libcommon "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon/consensus/bor" "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/polygon/bor" ) //go:generate mockgen -destination=./mock/canonical_chain_builder_mock.go -package=mock . CanonicalChainBuilder diff --git a/polygon/sync/canonical_chain_builder_test.go b/polygon/sync/canonical_chain_builder_test.go index 802009e2c4d..a515738b741 100644 --- a/polygon/sync/canonical_chain_builder_test.go +++ b/polygon/sync/canonical_chain_builder_test.go @@ -9,7 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - heimdallspan "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" + heimdallspan "github.com/ledgerwatch/erigon/polygon/heimdall/span" + "github.com/ledgerwatch/erigon/core/types" ) diff --git a/polygon/sync/difficulty.go b/polygon/sync/difficulty.go index c632050024b..74ec83958ec 100644 --- a/polygon/sync/difficulty.go +++ b/polygon/sync/difficulty.go @@ -6,12 +6,13 @@ import ( "github.com/ledgerwatch/erigon/eth/stagedsync" + heimdallspan "github.com/ledgerwatch/erigon/polygon/heimdall/span" + libcommon "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon/consensus/bor" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" - heimdallspan "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" - "github.com/ledgerwatch/erigon/consensus/bor/valset" "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/polygon/bor" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/valset" ) type DifficultyCalculator interface { diff --git a/polygon/sync/difficulty_test.go b/polygon/sync/difficulty_test.go index 77b0711c3b2..11d4639524d 100644 --- a/polygon/sync/difficulty_test.go +++ b/polygon/sync/difficulty_test.go @@ -8,10 +8,11 @@ import ( "github.com/stretchr/testify/require" + heimdallspan "github.com/ledgerwatch/erigon/polygon/heimdall/span" + libcommon "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" - heimdallspan "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" ) type testValidatorSetInterface struct { diff --git a/polygon/sync/header_downloader_test.go b/polygon/sync/header_downloader_test.go index f60ef0c6557..ae650902ab9 100644 --- a/polygon/sync/header_downloader_test.go +++ b/polygon/sync/header_downloader_test.go @@ -12,9 +12,10 @@ import ( "github.com/ledgerwatch/log/v3" "github.com/stretchr/testify/require" + "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" + "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" + "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/checkpoint" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/milestone" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/polygon/sync/mock" "github.com/ledgerwatch/erigon/polygon/sync/peerinfo" diff --git a/polygon/sync/heimdall.go b/polygon/sync/heimdall.go index cdf8077b9ac..b3e3f1e95af 100644 --- a/polygon/sync/heimdall.go +++ b/polygon/sync/heimdall.go @@ -8,11 +8,12 @@ import ( "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon/polygon/heimdall" + "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" + "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" + "github.com/ledgerwatch/erigon/polygon/heimdall/span" + "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/checkpoint" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/milestone" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" ) // Heimdall is a wrapper of Heimdall HTTP API diff --git a/polygon/sync/heimdall_test.go b/polygon/sync/heimdall_test.go index 2036feb84d5..2d809749d6e 100644 --- a/polygon/sync/heimdall_test.go +++ b/polygon/sync/heimdall_test.go @@ -11,10 +11,10 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - heimdallclient "github.com/ledgerwatch/erigon/consensus/bor/heimdall" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/checkpoint" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/milestone" - heimdallmock "github.com/ledgerwatch/erigon/consensus/bor/heimdall/mock" + heimdallclient "github.com/ledgerwatch/erigon/polygon/heimdall" + "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" + "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" + heimdallmock "github.com/ledgerwatch/erigon/polygon/heimdall/mock" ) func makeCheckpoint(start uint64, len uint) *checkpoint.Checkpoint { diff --git a/polygon/sync/mock/heimdall_mock.go b/polygon/sync/mock/heimdall_mock.go index c38947dc559..fe887f30bad 100644 --- a/polygon/sync/mock/heimdall_mock.go +++ b/polygon/sync/mock/heimdall_mock.go @@ -9,9 +9,9 @@ import ( reflect "reflect" gomock "github.com/golang/mock/gomock" - checkpoint "github.com/ledgerwatch/erigon/consensus/bor/heimdall/checkpoint" - milestone "github.com/ledgerwatch/erigon/consensus/bor/heimdall/milestone" - span "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" + checkpoint "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" + milestone "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" + span "github.com/ledgerwatch/erigon/polygon/heimdall/span" ) // MockHeimdall is a mock of Heimdall interface. diff --git a/polygon/sync/state_point.go b/polygon/sync/state_point.go index dfd61da3858..cad44407de0 100644 --- a/polygon/sync/state_point.go +++ b/polygon/sync/state_point.go @@ -3,9 +3,10 @@ package sync import ( "math/big" + "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" + "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" + "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/checkpoint" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/milestone" ) func statePointFromCheckpoint(checkpoint *checkpoint.Checkpoint) *statePoint { diff --git a/polygon/sync/state_points.go b/polygon/sync/state_points.go index 5577f24d2f4..e88c3160ceb 100644 --- a/polygon/sync/state_points.go +++ b/polygon/sync/state_points.go @@ -1,8 +1,8 @@ package sync import ( - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/checkpoint" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/milestone" + "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" + "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" ) func statePointsFromCheckpoints(checkpoints []*checkpoint.Checkpoint) statePoints { diff --git a/tests/bor/helper/miner.go b/tests/bor/helper/miner.go index 970116db606..ab94206a868 100644 --- a/tests/bor/helper/miner.go +++ b/tests/bor/helper/miner.go @@ -5,7 +5,7 @@ import ( "crypto/ecdsa" "encoding/json" "fmt" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" "math/big" "os" "time" diff --git a/turbo/jsonrpc/bor_api.go b/turbo/jsonrpc/bor_api.go index 41ee908d3e3..835bd8cc170 100644 --- a/turbo/jsonrpc/bor_api.go +++ b/turbo/jsonrpc/bor_api.go @@ -7,8 +7,8 @@ import ( "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/consensus/bor" - "github.com/ledgerwatch/erigon/consensus/bor/valset" + "github.com/ledgerwatch/erigon/polygon/bor" + "github.com/ledgerwatch/erigon/polygon/bor/valset" "github.com/ledgerwatch/erigon/rpc" ) diff --git a/turbo/jsonrpc/bor_helper.go b/turbo/jsonrpc/bor_helper.go index 34a5ec35f5d..dd9ef47d574 100644 --- a/turbo/jsonrpc/bor_helper.go +++ b/turbo/jsonrpc/bor_helper.go @@ -9,12 +9,12 @@ import ( "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" - "github.com/ledgerwatch/erigon/consensus/bor" - "github.com/ledgerwatch/erigon/consensus/bor/valset" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/crypto" + "github.com/ledgerwatch/erigon/polygon/bor" + "github.com/ledgerwatch/erigon/polygon/bor/valset" "github.com/ledgerwatch/erigon/rpc" "github.com/ledgerwatch/erigon/turbo/rpchelper" ) diff --git a/turbo/jsonrpc/bor_snapshot.go b/turbo/jsonrpc/bor_snapshot.go index 0fb6389c3c2..0b41a8117a3 100644 --- a/turbo/jsonrpc/bor_snapshot.go +++ b/turbo/jsonrpc/bor_snapshot.go @@ -10,14 +10,14 @@ import ( "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/consensus/bor" - "github.com/ledgerwatch/erigon/consensus/bor/finality/whitelist" - "github.com/ledgerwatch/erigon/consensus/bor/valset" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/polygon/bor" + "github.com/ledgerwatch/erigon/polygon/bor/finality/whitelist" + "github.com/ledgerwatch/erigon/polygon/bor/valset" "github.com/ledgerwatch/erigon/rpc" ) diff --git a/turbo/jsonrpc/daemon.go b/turbo/jsonrpc/daemon.go index ce98b9bbd0b..ca89bcd0809 100644 --- a/turbo/jsonrpc/daemon.go +++ b/turbo/jsonrpc/daemon.go @@ -7,8 +7,8 @@ import ( libstate "github.com/ledgerwatch/erigon-lib/state" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/cli/httpcfg" "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/consensus/bor" "github.com/ledgerwatch/erigon/consensus/clique" + "github.com/ledgerwatch/erigon/polygon/bor" "github.com/ledgerwatch/erigon/rpc" "github.com/ledgerwatch/erigon/turbo/rpchelper" "github.com/ledgerwatch/erigon/turbo/services" diff --git a/turbo/jsonrpc/erigon_system.go b/turbo/jsonrpc/erigon_system.go index eac0b351554..54bcf65d4ac 100644 --- a/turbo/jsonrpc/erigon_system.go +++ b/turbo/jsonrpc/erigon_system.go @@ -7,9 +7,9 @@ import ( "github.com/ledgerwatch/erigon-lib/common" - borfinality "github.com/ledgerwatch/erigon/consensus/bor/finality" - "github.com/ledgerwatch/erigon/consensus/bor/finality/whitelist" "github.com/ledgerwatch/erigon/core/forkid" + borfinality "github.com/ledgerwatch/erigon/polygon/bor/finality" + "github.com/ledgerwatch/erigon/polygon/bor/finality/whitelist" "github.com/ledgerwatch/erigon/rpc" "github.com/ledgerwatch/erigon/turbo/rpchelper" ) diff --git a/turbo/jsonrpc/eth_block.go b/turbo/jsonrpc/eth_block.go index 50cfca6e271..e40cbff926a 100644 --- a/turbo/jsonrpc/eth_block.go +++ b/turbo/jsonrpc/eth_block.go @@ -8,7 +8,7 @@ import ( "github.com/ledgerwatch/erigon-lib/common/hexutil" "github.com/ledgerwatch/erigon/cl/clparams" - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" "github.com/ledgerwatch/log/v3" diff --git a/turbo/jsonrpc/validator_set.go b/turbo/jsonrpc/validator_set.go index 70c6a5ee5f0..7f4ddf735b8 100644 --- a/turbo/jsonrpc/validator_set.go +++ b/turbo/jsonrpc/validator_set.go @@ -13,7 +13,7 @@ import ( libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/log/v3" - "github.com/ledgerwatch/erigon/consensus/bor/valset" + "github.com/ledgerwatch/erigon/polygon/bor/valset" ) // MaxTotalVotingPower - the maximum allowed total voting power. diff --git a/turbo/rpchelper/helper.go b/turbo/rpchelper/helper.go index 497eaa9523a..2a6ccc0544b 100644 --- a/turbo/rpchelper/helper.go +++ b/turbo/rpchelper/helper.go @@ -9,13 +9,13 @@ import ( "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/kvcache" "github.com/ledgerwatch/erigon-lib/kv/rawdbv3" - borfinality "github.com/ledgerwatch/erigon/consensus/bor/finality" - "github.com/ledgerwatch/erigon/consensus/bor/finality/whitelist" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/state" "github.com/ledgerwatch/erigon/core/systemcontracts" "github.com/ledgerwatch/erigon/eth/ethconfig" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" + borfinality "github.com/ledgerwatch/erigon/polygon/bor/finality" + "github.com/ledgerwatch/erigon/polygon/bor/finality/whitelist" "github.com/ledgerwatch/erigon/rpc" ) diff --git a/turbo/snapshotsync/freezeblocks/block_reader.go b/turbo/snapshotsync/freezeblocks/block_reader.go index 6f20332bf89..84837053147 100644 --- a/turbo/snapshotsync/freezeblocks/block_reader.go +++ b/turbo/snapshotsync/freezeblocks/block_reader.go @@ -8,6 +8,10 @@ import ( "math" "sort" + "github.com/ledgerwatch/log/v3" + + "github.com/ledgerwatch/erigon/polygon/heimdall/span" + "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/dbg" "github.com/ledgerwatch/erigon-lib/common/length" @@ -15,13 +19,11 @@ import ( "github.com/ledgerwatch/erigon-lib/gointerfaces/remote" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/recsplit" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/eth/ethconfig" "github.com/ledgerwatch/erigon/rlp" "github.com/ledgerwatch/erigon/turbo/services" - "github.com/ledgerwatch/log/v3" ) type RemoteBlockReader struct { diff --git a/turbo/snapshotsync/freezeblocks/block_snapshots.go b/turbo/snapshotsync/freezeblocks/block_snapshots.go index 7bd82801192..200d0bee576 100644 --- a/turbo/snapshotsync/freezeblocks/block_snapshots.go +++ b/turbo/snapshotsync/freezeblocks/block_snapshots.go @@ -21,6 +21,8 @@ import ( "golang.org/x/exp/slices" "golang.org/x/sync/errgroup" + "github.com/ledgerwatch/erigon/polygon/heimdall/span" + "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon-lib/chain/snapcfg" common2 "github.com/ledgerwatch/erigon-lib/common" @@ -38,7 +40,6 @@ import ( "github.com/ledgerwatch/erigon-lib/recsplit" types2 "github.com/ledgerwatch/erigon-lib/types" "github.com/ledgerwatch/erigon/cmd/hack/tool/fromdb" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/rawdb/blockio" "github.com/ledgerwatch/erigon/core/types" diff --git a/turbo/snapshotsync/freezeblocks/bor_snapshots.go b/turbo/snapshotsync/freezeblocks/bor_snapshots.go index 62ff94ec83a..39a683bbfb0 100644 --- a/turbo/snapshotsync/freezeblocks/bor_snapshots.go +++ b/turbo/snapshotsync/freezeblocks/bor_snapshots.go @@ -17,6 +17,8 @@ import ( "github.com/ledgerwatch/log/v3" "golang.org/x/exp/slices" + "github.com/ledgerwatch/erigon/polygon/heimdall/span" + "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon-lib/chain/snapcfg" common2 "github.com/ledgerwatch/erigon-lib/common" @@ -30,7 +32,6 @@ import ( "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/recsplit" "github.com/ledgerwatch/erigon/cmd/hack/tool/fromdb" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/eth/ethconfig" diff --git a/turbo/snapshotsync/freezeblocks/dump_test.go b/turbo/snapshotsync/freezeblocks/dump_test.go index a3de0bad293..e056c64d2d7 100644 --- a/turbo/snapshotsync/freezeblocks/dump_test.go +++ b/turbo/snapshotsync/freezeblocks/dump_test.go @@ -1,7 +1,7 @@ package freezeblocks_test import ( - "github.com/ledgerwatch/erigon/consensus/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" "math/big" "testing" diff --git a/turbo/stages/mock/mock_sentry.go b/turbo/stages/mock/mock_sentry.go index af9bf9241e0..eb973d9d70a 100644 --- a/turbo/stages/mock/mock_sentry.go +++ b/turbo/stages/mock/mock_sentry.go @@ -35,7 +35,6 @@ import ( types2 "github.com/ledgerwatch/erigon-lib/types" "github.com/ledgerwatch/erigon-lib/wrap" "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/consensus/bor" "github.com/ledgerwatch/erigon/consensus/ethash" "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/core/rawdb" @@ -54,6 +53,7 @@ import ( "github.com/ledgerwatch/erigon/p2p" "github.com/ledgerwatch/erigon/p2p/sentry/sentry_multi_client" "github.com/ledgerwatch/erigon/params" + "github.com/ledgerwatch/erigon/polygon/bor" "github.com/ledgerwatch/erigon/rlp" "github.com/ledgerwatch/erigon/turbo/builder" "github.com/ledgerwatch/erigon/turbo/engineapi/engine_helpers" diff --git a/turbo/stages/stageloop.go b/turbo/stages/stageloop.go index 18537dc68fd..951dc4b7b83 100644 --- a/turbo/stages/stageloop.go +++ b/turbo/stages/stageloop.go @@ -21,10 +21,9 @@ import ( "github.com/ledgerwatch/erigon-lib/state" "github.com/ledgerwatch/erigon-lib/wrap" + "github.com/ledgerwatch/erigon/polygon/heimdall" + "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/consensus/bor" - "github.com/ledgerwatch/erigon/consensus/bor/finality/flags" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall" "github.com/ledgerwatch/erigon/consensus/misc" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/rawdb/blockio" @@ -35,6 +34,8 @@ import ( "github.com/ledgerwatch/erigon/eth/stagedsync/stages" "github.com/ledgerwatch/erigon/p2p" "github.com/ledgerwatch/erigon/p2p/sentry/sentry_multi_client" + "github.com/ledgerwatch/erigon/polygon/bor" + "github.com/ledgerwatch/erigon/polygon/bor/finality/flags" "github.com/ledgerwatch/erigon/turbo/engineapi/engine_helpers" "github.com/ledgerwatch/erigon/turbo/services" "github.com/ledgerwatch/erigon/turbo/shards" diff --git a/turbo/transactions/tracing.go b/turbo/transactions/tracing.go index 31c85f9c23d..5f56a60714a 100644 --- a/turbo/transactions/tracing.go +++ b/turbo/transactions/tracing.go @@ -17,7 +17,6 @@ import ( ethereum "github.com/ledgerwatch/erigon" "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/consensus/bor/statefull" "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/core/state" "github.com/ledgerwatch/erigon/core/types" @@ -26,6 +25,7 @@ import ( "github.com/ledgerwatch/erigon/eth/stagedsync" "github.com/ledgerwatch/erigon/eth/tracers" "github.com/ledgerwatch/erigon/eth/tracers/logger" + "github.com/ledgerwatch/erigon/polygon/bor/statefull" "github.com/ledgerwatch/erigon/turbo/rpchelper" "github.com/ledgerwatch/erigon/turbo/services" ) From 8db023bea6d40179ea90f7bbea1c90bc09f3b542 Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Tue, 9 Jan 2024 20:57:02 +0100 Subject: [PATCH 30/92] Schedule Dencun for Chiado (#9184) --- cl/clparams/config.go | 6 ++++-- core/forkid/forkid_test.go | 5 ++++- params/chainspecs/chiado.json | 1 + 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/cl/clparams/config.go b/cl/clparams/config.go index 3fd059b8264..4b49f5734ee 100644 --- a/cl/clparams/config.go +++ b/cl/clparams/config.go @@ -881,13 +881,15 @@ func chiadoConfig() BeaconChainConfig { cfg.AltairForkVersion = 0x0100006f cfg.BellatrixForkEpoch = 180 cfg.BellatrixForkVersion = 0x0200006f + cfg.CapellaForkEpoch = 244224 + cfg.CapellaForkVersion = 0x0300006f + cfg.DenebForkEpoch = 8265728 + cfg.DenebForkVersion = 0x0400006f cfg.TerminalTotalDifficulty = "231707791542740786049188744689299064356246512" cfg.DepositContractAddress = "0xb97036A26259B7147018913bD58a774cf91acf25" cfg.BaseRewardFactor = 25 cfg.SlotsPerEpoch = 16 cfg.EpochsPerSyncCommitteePeriod = 512 - cfg.CapellaForkEpoch = math.MaxUint64 - cfg.DenebForkEpoch = math.MaxUint64 cfg.InitializeForkSchedule() return cfg } diff --git a/core/forkid/forkid_test.go b/core/forkid/forkid_test.go index 7b2b7833661..ab631f9e246 100644 --- a/core/forkid/forkid_test.go +++ b/core/forkid/forkid_test.go @@ -141,7 +141,10 @@ func TestCreation(t *testing.T) { []testcase{ {0, 0, ID{Hash: checksumToBytes(0x50d39d7b), Next: 1684934220}}, {4100418, 1684934215, ID{Hash: checksumToBytes(0x50d39d7b), Next: 1684934220}}, // Last pre-Shanghai block - {4100419, 1684934220, ID{Hash: checksumToBytes(0xa15a4252), Next: 0}}, // First Shanghai block + {4100419, 1684934220, ID{Hash: checksumToBytes(0xa15a4252), Next: 1706724940}}, // First Shanghai block + {8102175, 1706724935, ID{Hash: checksumToBytes(0xa15a4252), Next: 1706724940}}, // Last Shanghai block (approx) + {8102176, 1706724940, ID{Hash: checksumToBytes(0x5fbc16bc), Next: 0}}, // First Cancun block (approx) + {10000000, 1800000000, ID{Hash: checksumToBytes(0x5fbc16bc), Next: 0}}, // Future Cancun block (mock) }, }, // Mumbai test cases diff --git a/params/chainspecs/chiado.json b/params/chainspecs/chiado.json index c1f2acf4be8..cc642d266f2 100644 --- a/params/chainspecs/chiado.json +++ b/params/chainspecs/chiado.json @@ -17,6 +17,7 @@ "terminalTotalDifficulty": 231707791542740786049188744689299064356246512, "terminalTotalDifficultyPassed": true, "shanghaiTime": 1684934220, + "cancunTime": 1706724940, "minBlobGasPrice": 1000000000, "maxBlobGasPerBlock": 262144, "targetBlobGasPerBlock": 131072, From 0cfe6617dbbfcc883cc0950b41d2c92135b70d96 Mon Sep 17 00:00:00 2001 From: milen <94537774+taratorio@users.noreply.github.com> Date: Tue, 9 Jan 2024 20:02:14 +0000 Subject: [PATCH 31/92] devnet: fix infinite recursion & enable TestStateSync & TestCallContract integration tests (#9183) This PR fixes an infinite recursion (stack overflow) error in devnet integration tests that surfaced in our integration CI a week or more ago and additionally enables some integration tests that are now fixed - `TestStateSync` & `TestCallContract`. ![Screenshot 2024-01-09 at 17 10 24](https://github.com/ledgerwatch/erigon/assets/94537774/a5a8c9c9-9f68-4084-9e08-1bf3c1601cab) --- cmd/devnet/devnet/context.go | 6 ++---- cmd/devnet/tests/bor/devnet_test.go | 5 ++--- cmd/devnet/tests/generic/devnet_test.go | 5 ++--- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/cmd/devnet/devnet/context.go b/cmd/devnet/devnet/context.go index b26c4b5fde1..7322d054ca3 100644 --- a/cmd/devnet/devnet/context.go +++ b/cmd/devnet/devnet/context.go @@ -139,10 +139,8 @@ func CurrentNetwork(ctx context.Context) *Network { return cn.network } - if current := CurrentNode(ctx); current != nil { - if n, ok := current.(*devnetNode); ok { - return n.network - } + if cn, ok := ctx.Value(ckNode).(*cnode); ok && cn.node != nil { + return cn.node.(*devnetNode).network } if devnet, ok := ctx.Value(ckDevnet).(Devnet); ok { diff --git a/cmd/devnet/tests/bor/devnet_test.go b/cmd/devnet/tests/bor/devnet_test.go index ad43f982c28..fa9d9ecee39 100644 --- a/cmd/devnet/tests/bor/devnet_test.go +++ b/cmd/devnet/tests/bor/devnet_test.go @@ -6,18 +6,17 @@ import ( "context" "testing" + "github.com/stretchr/testify/require" + "github.com/ledgerwatch/erigon-lib/chain/networkname" accounts_steps "github.com/ledgerwatch/erigon/cmd/devnet/accounts/steps" contracts_steps "github.com/ledgerwatch/erigon/cmd/devnet/contracts/steps" "github.com/ledgerwatch/erigon/cmd/devnet/requests" "github.com/ledgerwatch/erigon/cmd/devnet/services" "github.com/ledgerwatch/erigon/cmd/devnet/tests" - "github.com/stretchr/testify/require" ) func TestStateSync(t *testing.T) { - t.Skip("FIXME: hangs in GenerateSyncEvents without any visible progress") - runCtx, err := tests.ContextStart(t, networkname.BorDevnetChainName) require.Nil(t, err) var ctx context.Context = runCtx diff --git a/cmd/devnet/tests/generic/devnet_test.go b/cmd/devnet/tests/generic/devnet_test.go index 8f0f944ab85..9df1b49e871 100644 --- a/cmd/devnet/tests/generic/devnet_test.go +++ b/cmd/devnet/tests/generic/devnet_test.go @@ -7,6 +7,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" + "github.com/ledgerwatch/erigon/cmd/devnet/accounts" "github.com/ledgerwatch/erigon/cmd/devnet/admin" "github.com/ledgerwatch/erigon/cmd/devnet/contracts/steps" @@ -14,7 +16,6 @@ import ( "github.com/ledgerwatch/erigon/cmd/devnet/services" "github.com/ledgerwatch/erigon/cmd/devnet/tests" "github.com/ledgerwatch/erigon/cmd/devnet/transactions" - "github.com/stretchr/testify/require" ) func testDynamicTx(t *testing.T, ctx context.Context) { @@ -51,8 +52,6 @@ func TestDynamicTxAnyNode(t *testing.T) { } func TestCallContract(t *testing.T) { - t.Skip("FIXME: DeployAndCallLogSubscriber step fails: Log result is incorrect expected txIndex: 1, actual txIndex 2") - runCtx, err := tests.ContextStart(t, "") require.Nil(t, err) ctx := runCtx.WithCurrentNetwork(0) From ceeb090f48a859939cde1b151b11634dcd1a695a Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Wed, 10 Jan 2024 15:15:27 +0700 Subject: [PATCH 32/92] mdbx: hard dirtyPages limit (#9178) logic: 1/42 of ram, but not more than 2Gb for chandata and not more than 256mb for other databases. --------- Co-authored-by: battlmonstr --- erigon-lib/kv/mdbx/kv_mdbx.go | 44 +++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/erigon-lib/kv/mdbx/kv_mdbx.go b/erigon-lib/kv/mdbx/kv_mdbx.go index 40068780722..60da7e14ca3 100644 --- a/erigon-lib/kv/mdbx/kv_mdbx.go +++ b/erigon-lib/kv/mdbx/kv_mdbx.go @@ -314,7 +314,7 @@ func (opts MdbxOpts) Open(ctx context.Context) (kv.RwDB, error) { // erigon using big transactions // increase "page measured" options. need do it after env.Open() because default are depend on pageSize known only after env.Open() - if !opts.HasFlag(mdbx.Accede) && !opts.HasFlag(mdbx.Readonly) { + if !opts.HasFlag(mdbx.Readonly) { // 1/8 is good for transactions with a lot of modifications - to reduce invalidation size. // But Erigon app now using Batch and etl.Collectors to avoid writing to DB frequently changing data. // It means most of our writes are: APPEND or "single UPSERT per key during transaction" @@ -326,20 +326,44 @@ func (opts MdbxOpts) Open(ctx context.Context) (kv.RwDB, error) { if err != nil { return nil, err } - if err = env.SetOption(mdbx.OptTxnDpInitial, txnDpInitial*2); err != nil { - return nil, err + if opts.label == kv.ChainDB { + if err = env.SetOption(mdbx.OptTxnDpInitial, txnDpInitial*2); err != nil { + return nil, err + } + dpReserveLimit, err := env.GetOption(mdbx.OptDpReverseLimit) + if err != nil { + return nil, err + } + if err = env.SetOption(mdbx.OptDpReverseLimit, dpReserveLimit*2); err != nil { + return nil, err + } } - dpReserveLimit, err := env.GetOption(mdbx.OptDpReverseLimit) - if err != nil { - return nil, err + + var dirtySpace uint64 + if opts.dirtySpace > 0 { + dirtySpace = opts.dirtySpace + } else { + // the default value is based on the RAM amount + dirtyPagesLimit, err := env.GetOption(mdbx.OptTxnDpLimit) + if err != nil { + return nil, err + } + dirtySpace = dirtyPagesLimit * opts.pageSize + + // clamp to max size + const dirtySpaceMaxChainDB = uint64(2 * datasize.GB) + const dirtySpaceMaxDefault = uint64(256 * datasize.MB) + + if opts.label == kv.ChainDB && dirtySpace > dirtySpaceMaxChainDB { + dirtySpace = dirtySpaceMaxChainDB + } else if opts.label != kv.ChainDB && dirtySpace > dirtySpaceMaxDefault { + dirtySpace = dirtySpaceMaxDefault + } } - if err = env.SetOption(mdbx.OptDpReverseLimit, dpReserveLimit*2); err != nil { + if err = env.SetOption(mdbx.OptTxnDpLimit, dirtySpace/opts.pageSize); err != nil { return nil, err } - if err = env.SetOption(mdbx.OptTxnDpLimit, opts.dirtySpace/opts.pageSize); err != nil { - return nil, err - } // must be in the range from 12.5% (almost empty) to 50% (half empty) // which corresponds to the range from 8192 and to 32768 in units respectively if err = env.SetOption(mdbx.OptMergeThreshold16dot16Percent, opts.mergeThreshold); err != nil { From 95109d980058ddb327e4199eae362184580bf1cb Mon Sep 17 00:00:00 2001 From: milen <94537774+taratorio@users.noreply.github.com> Date: Wed, 10 Jan 2024 12:16:25 +0000 Subject: [PATCH 33/92] erigon-lib: cleanup unnnecessary import in tools.go added in prev PR (#9190) --- erigon-lib/tools.go | 1 - 1 file changed, 1 deletion(-) diff --git a/erigon-lib/tools.go b/erigon-lib/tools.go index a97764c2cef..5188efdc85c 100644 --- a/erigon-lib/tools.go +++ b/erigon-lib/tools.go @@ -17,7 +17,6 @@ package tools // build tag 'trick_go_mod_tidy' - is used to hide warnings of IDEA (because we can't import `main` packages in go) import ( - _ "github.com/golang/mock/mockgen/model" _ "github.com/ledgerwatch/interfaces" _ "github.com/ledgerwatch/interfaces/downloader" _ "github.com/ledgerwatch/interfaces/execution" From 09ec1f160c3efa6205491b6596c4e0ad835b0e30 Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Wed, 10 Jan 2024 16:13:15 +0100 Subject: [PATCH 34/92] Fix DenebForkEpoch for Chiado (#9188) In PR #9184 I confused slot with epoch. Refer to https://github.com/gnosischain/configs/pull/26. --- cl/clparams/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cl/clparams/config.go b/cl/clparams/config.go index 4b49f5734ee..4d51e918dcc 100644 --- a/cl/clparams/config.go +++ b/cl/clparams/config.go @@ -883,7 +883,7 @@ func chiadoConfig() BeaconChainConfig { cfg.BellatrixForkVersion = 0x0200006f cfg.CapellaForkEpoch = 244224 cfg.CapellaForkVersion = 0x0300006f - cfg.DenebForkEpoch = 8265728 + cfg.DenebForkEpoch = 516608 cfg.DenebForkVersion = 0x0400006f cfg.TerminalTotalDifficulty = "231707791542740786049188744689299064356246512" cfg.DepositContractAddress = "0xb97036A26259B7147018913bD58a774cf91acf25" From 284aa1dd0c59bbce126c8f8b07af76700d9272f6 Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Wed, 10 Jan 2024 17:15:58 +0100 Subject: [PATCH 35/92] Added EthV1AggregateAndProofs API (#9192) Added publishing of aggregates and proofs --- cl/beacon/handler/handler.go | 2 +- cl/beacon/handler/pool.go | 32 ++++++++++++++++ cl/beacon/handler/pool_test.go | 49 +++++++++++++++++++++++++ cl/cltypes/solid/attestation.go | 1 + cl/phase1/forkchoice/forkchoice_mock.go | 5 +++ cl/phase1/forkchoice/interface.go | 1 + 6 files changed, 89 insertions(+), 1 deletion(-) diff --git a/cl/beacon/handler/handler.go b/cl/beacon/handler/handler.go index 47baf6175fd..f0fe3bd5ad0 100644 --- a/cl/beacon/handler/handler.go +++ b/cl/beacon/handler/handler.go @@ -119,7 +119,7 @@ func (a *ApiHandler) init() { r.Get("/blinded_blocks/{slot}", http.NotFound) r.Get("/attestation_data", http.NotFound) r.Get("/aggregate_attestation", http.NotFound) - r.Post("/aggregate_and_proofs", http.NotFound) + r.Post("/aggregate_and_proofs", a.PostEthV1ValidatorAggregatesAndProof) r.Post("/beacon_committee_subscriptions", http.NotFound) r.Post("/sync_committee_subscriptions", http.NotFound) r.Get("/sync_committee_contribution", http.NotFound) diff --git a/cl/beacon/handler/pool.go b/cl/beacon/handler/pool.go index a628a958ae7..e96549e6b04 100644 --- a/cl/beacon/handler/pool.go +++ b/cl/beacon/handler/pool.go @@ -191,3 +191,35 @@ func (a *ApiHandler) PostEthV1BeaconPoolBlsToExecutionChanges(w http.ResponseWri // Only write 200 w.WriteHeader(http.StatusOK) } + +func (a *ApiHandler) PostEthV1ValidatorAggregatesAndProof(w http.ResponseWriter, r *http.Request) { + req := []*cltypes.SignedAggregateAndProof{} + + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + failures := []poolingFailure{} + for _, v := range req { + if err := a.forkchoiceStore.OnAggregateAndProof(v, false); err != nil { + failures = append(failures, poolingFailure{Index: len(failures), Message: err.Error()}) + continue + } + // Broadcast to gossip + if a.sentinel != nil { + encodedSSZ, err := v.EncodeSSZ(nil) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + if _, err := a.sentinel.PublishGossip(r.Context(), &sentinel.GossipData{ + Data: encodedSSZ, + Name: gossip.TopicNameBeaconAggregateAndProof, + }); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + } + } +} diff --git a/cl/beacon/handler/pool_test.go b/cl/beacon/handler/pool_test.go index 170f7f564cd..a4349aa1750 100644 --- a/cl/beacon/handler/pool_test.go +++ b/cl/beacon/handler/pool_test.go @@ -195,3 +195,52 @@ func TestPoolBlsToExecutionChainges(t *testing.T) { require.Equal(t, msg[0], out.Data[0]) require.Equal(t, msg[1], out.Data[1]) } + +func TestPoolAggregatesAndProofs(t *testing.T) { + msg := []*cltypes.SignedAggregateAndProof{ + { + Message: &cltypes.AggregateAndProof{ + Aggregate: solid.NewAttestionFromParameters([]byte{1, 2}, solid.NewAttestationData(), libcommon.Bytes96{3, 45, 6}), + }, + Signature: libcommon.Bytes96{2}, + }, + { + Message: &cltypes.AggregateAndProof{ + Aggregate: solid.NewAttestionFromParameters([]byte{1, 2, 5, 6}, solid.NewAttestationData(), libcommon.Bytes96{3, 0, 6}), + }, + Signature: libcommon.Bytes96{2, 3, 5}, + }, + } + // find server + _, _, _, _, _, handler, _, _, _ := setupTestingHandler(t, clparams.Phase0Version) + + server := httptest.NewServer(handler.mux) + defer server.Close() + // json + req, err := json.Marshal(msg) + require.NoError(t, err) + // post attester slashing + resp, err := server.Client().Post(server.URL+"/eth/v1/validator/aggregate_and_proofs", "application/json", bytes.NewBuffer(req)) + require.NoError(t, err) + defer resp.Body.Close() + + require.Equal(t, 200, resp.StatusCode) + // get attester slashings + resp, err = server.Client().Get(server.URL + "/eth/v1/beacon/pool/attestations") + require.NoError(t, err) + defer resp.Body.Close() + + require.Equal(t, 200, resp.StatusCode) + out := struct { + Data []*solid.Attestation `json:"data"` + }{ + Data: []*solid.Attestation{}, + } + + err = json.NewDecoder(resp.Body).Decode(&out) + require.NoError(t, err) + + require.Equal(t, 2, len(out.Data)) + require.Equal(t, msg[0].Message.Aggregate, out.Data[0]) + require.Equal(t, msg[1].Message.Aggregate, out.Data[1]) +} diff --git a/cl/cltypes/solid/attestation.go b/cl/cltypes/solid/attestation.go index 68e9e131e39..42097e11d9f 100644 --- a/cl/cltypes/solid/attestation.go +++ b/cl/cltypes/solid/attestation.go @@ -65,6 +65,7 @@ func (a *Attestation) UnmarshalJSON(buf []byte) error { Signature libcommon.Bytes96 `json:"signature"` Data AttestationData `json:"data"` } + tmp.Data = NewAttestationData() if err := json.Unmarshal(buf, &tmp); err != nil { return err } diff --git a/cl/phase1/forkchoice/forkchoice_mock.go b/cl/phase1/forkchoice/forkchoice_mock.go index 691b832f8a8..3683e5cc3e2 100644 --- a/cl/phase1/forkchoice/forkchoice_mock.go +++ b/cl/phase1/forkchoice/forkchoice_mock.go @@ -220,3 +220,8 @@ func (f *ForkChoiceStorageMock) OnBlsToExecutionChange(signedChange *cltypes.Sig func (f *ForkChoiceStorageMock) ForkNodes() []ForkNode { return f.WeightsMock } + +func (f *ForkChoiceStorageMock) OnAggregateAndProof(aggregateAndProof *cltypes.SignedAggregateAndProof, test bool) error { + f.Pool.AttestationsPool.Insert(aggregateAndProof.Message.Aggregate.Signature(), aggregateAndProof.Message.Aggregate) + return nil +} diff --git a/cl/phase1/forkchoice/interface.go b/cl/phase1/forkchoice/interface.go index 81fa579e2e6..0b62ff8f3e1 100644 --- a/cl/phase1/forkchoice/interface.go +++ b/cl/phase1/forkchoice/interface.go @@ -44,6 +44,7 @@ type ForkChoiceStorageReader interface { } type ForkChoiceStorageWriter interface { + OnAggregateAndProof(aggregateAndProof *cltypes.SignedAggregateAndProof, test bool) error OnAttestation(attestation *solid.Attestation, fromBlock, insert bool) error OnAttesterSlashing(attesterSlashing *cltypes.AttesterSlashing, test bool) error OnVoluntaryExit(signedVoluntaryExit *cltypes.SignedVoluntaryExit, test bool) error From b05ffc909d979e41e1da6f2b949bc4dd562b1bd2 Mon Sep 17 00:00:00 2001 From: Mark Holt <135143369+mh0lt@users.noreply.github.com> Date: Wed, 10 Jan 2024 17:12:15 +0000 Subject: [PATCH 36/92] Fixes for Bor Block Production Synchronization (#9162) This PR contains 3 fixes for interaction between the Bor mining loop and the TX pool which where causing the regular creation of blocks with zero transactions. * Mining/Tx pool block synchronization The synchronization of the tx pool between the sync loop and the mining loop has been changed so that both are triggered by the same event and synchronized via a sync.Cond rather than a polling loop with a hard coded loop limit. This means that mining now waits for the pool to be updated from the previous block before it starts the mining process. * Txpool Startup consolidated into its MainLoop Previously the tx pool start process was dynamically triggered at various points in the code. This has all now been moved to the start of the main loop. This is necessary to avoid a timing hole which can leave the mining loop hanging waiting for a previously block broadcast which it missed due to its delay start. * Mining listens for block broadcast to avoid duplicate mining operations The mining loop for bor has a recommit timer in case blocks re not produced on time. However in the case of sprint transitions where the seal publication is delayed this can lead to duplicate block production. This is suppressed by introducing a `waiting` state which is exited upon the block being broadcast from the sealing operation. --- cmd/devnet/args/node_args.go | 1 + cmd/devnet/devnet/network.go | 12 +- cmd/devnet/devnet/node.go | 10 +- cmd/devnet/main.go | 69 +++++- cmd/devnet/networks/devnet_bor.go | 67 +++-- cmd/devnet/networks/devnet_dev.go | 16 +- cmd/devnet/requests/request_generator.go | 32 ++- cmd/devnet/tests/context.go | 14 +- cmd/devnet/transactions/tx.go | 44 +++- cmd/rpcdaemon/cli/config.go | 2 +- cmd/txpool/main.go | 6 - consensus/chain_reader.go | 2 +- erigon-lib/downloader/path.go | 2 +- erigon-lib/downloader/path_windows.go | 89 ------- erigon-lib/mmap/mmap_windows.go | 2 +- erigon-lib/txpool/pool.go | 228 ++++++++++++------ erigon-lib/txpool/pool_fuzz_test.go | 5 + erigon-lib/txpool/pool_test.go | 5 + eth/backend.go | 108 ++++++--- eth/stagedsync/chain_reader.go | 5 +- eth/stagedsync/stage_bor_heimdall.go | 4 + eth/stagedsync/stage_headers.go | 2 +- eth/stagedsync/stage_mining_bor_heimdall.go | 2 +- eth/stagedsync/stage_mining_exec.go | 43 ++-- eth/stagedsync/stage_mining_finish.go | 6 +- polygon/bor/bor.go | 2 + turbo/cli/flags.go | 2 +- .../snapshotsync/freezeblocks/block_reader.go | 2 +- turbo/stages/stageloop.go | 1 + 29 files changed, 493 insertions(+), 290 deletions(-) diff --git a/cmd/devnet/args/node_args.go b/cmd/devnet/args/node_args.go index 44930fee767..1fba7caaf90 100644 --- a/cmd/devnet/args/node_args.go +++ b/cmd/devnet/args/node_args.go @@ -135,6 +135,7 @@ type BlockProducer struct { NodeArgs Mine bool `arg:"--mine" flag:"true"` Etherbase string `arg:"--miner.etherbase"` + GasLimit int `arg:"--miner.gaslimit"` DevPeriod int `arg:"--dev.period"` BorPeriod int `arg:"--bor.period"` BorMinBlockSize int `arg:"--bor.minblocksize"` diff --git a/cmd/devnet/devnet/network.go b/cmd/devnet/devnet/network.go index 29eee727cdf..372aca838d2 100644 --- a/cmd/devnet/devnet/network.go +++ b/cmd/devnet/devnet/network.go @@ -34,7 +34,7 @@ type Network struct { Snapshots bool Nodes []Node Services []Service - Alloc types.GenesisAlloc + Genesis *types.Genesis BorStateSyncDelay time.Duration BorPeriod time.Duration BorMinBlockSize int @@ -140,12 +140,16 @@ func (nw *Network) createNode(nodeArgs Node) (Node, error) { } if n.IsBlockProducer() { - if nw.Alloc == nil { - nw.Alloc = types.GenesisAlloc{ + if nw.Genesis == nil { + nw.Genesis = &types.Genesis{} + } + + if nw.Genesis.Alloc == nil { + nw.Genesis.Alloc = types.GenesisAlloc{ n.Account().Address: types.GenesisAccount{Balance: blockProducerFunds}, } } else { - nw.Alloc[n.Account().Address] = types.GenesisAccount{Balance: blockProducerFunds} + nw.Genesis.Alloc[n.Account().Address] = types.GenesisAccount{Balance: blockProducerFunds} } } diff --git a/cmd/devnet/devnet/node.go b/cmd/devnet/devnet/node.go index 30f46633615..33f716aa3f3 100644 --- a/cmd/devnet/devnet/node.go +++ b/cmd/devnet/devnet/node.go @@ -167,8 +167,14 @@ func (n *devnetNode) run(ctx *cli.Context) error { n.nodeCfg.MdbxGrowthStep = 32 * datasize.MB n.nodeCfg.MdbxDBSizeLimit = 512 * datasize.MB - for addr, account := range n.network.Alloc { - n.ethCfg.Genesis.Alloc[addr] = account + if n.network.Genesis != nil { + for addr, account := range n.network.Genesis.Alloc { + n.ethCfg.Genesis.Alloc[addr] = account + } + + if n.network.Genesis.GasLimit != 0 { + n.ethCfg.Genesis.GasLimit = n.network.Genesis.GasLimit + } } if n.network.BorStateSyncDelay > 0 { diff --git a/cmd/devnet/main.go b/cmd/devnet/main.go index 655d0d88aff..92a41aca153 100644 --- a/cmd/devnet/main.go +++ b/cmd/devnet/main.go @@ -6,6 +6,7 @@ import ( "os/signal" "path/filepath" dbg "runtime/debug" + "strconv" "strings" "syscall" "time" @@ -131,6 +132,12 @@ var ( Value: 1, } + GasLimitFlag = cli.Uint64Flag{ + Name: "gaslimit", + Usage: "Target gas limit for mined blocks", + Value: 0, + } + WaitFlag = cli.BoolFlag{ Name: "wait", Usage: "Wait until interrupted after all scenarios have run", @@ -173,6 +180,7 @@ func main() { &logging.LogVerbosityFlag, &logging.LogConsoleVerbosityFlag, &logging.LogDirVerbosityFlag, + &GasLimitFlag, } if err := app.Run(os.Args); err != nil { @@ -342,21 +350,74 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { baseRpcHost := ctx.String(BaseRpcHostFlag.Name) baseRpcPort := ctx.Int(BaseRpcPortFlag.Name) producerCount := int(ctx.Uint(BlockProducersFlag.Name)) + gasLimit := ctx.Uint64(GasLimitFlag.Name) + + var dirLogLevel log.Lvl = log.LvlTrace + var consoleLogLevel log.Lvl = log.LvlCrit + + if ctx.IsSet(logging.LogVerbosityFlag.Name) { + lvlVal := ctx.String(logging.LogVerbosityFlag.Name) + + i, err := strconv.Atoi(lvlVal) + + lvl := log.Lvl(i) + + if err != nil { + lvl, err = log.LvlFromString(lvlVal) + } + + if err == nil { + consoleLogLevel = lvl + dirLogLevel = lvl + } + } else { + if ctx.IsSet(logging.LogConsoleVerbosityFlag.Name) { + lvlVal := ctx.String(logging.LogConsoleVerbosityFlag.Name) + + i, err := strconv.Atoi(lvlVal) + + lvl := log.Lvl(i) + + if err != nil { + lvl, err = log.LvlFromString(lvlVal) + } + + if err == nil { + consoleLogLevel = lvl + } + } + + if ctx.IsSet(logging.LogDirVerbosityFlag.Name) { + lvlVal := ctx.String(logging.LogDirVerbosityFlag.Name) + + i, err := strconv.Atoi(lvlVal) + + lvl := log.Lvl(i) + + if err != nil { + lvl, err = log.LvlFromString(lvlVal) + } + + if err == nil { + dirLogLevel = lvl + } + } + } switch chainName { case networkname.BorDevnetChainName: if ctx.Bool(WithoutHeimdallFlag.Name) { - return networks.NewBorDevnetWithoutHeimdall(dataDir, baseRpcHost, baseRpcPort, logger), nil + return networks.NewBorDevnetWithoutHeimdall(dataDir, baseRpcHost, baseRpcPort, gasLimit, logger, consoleLogLevel, dirLogLevel), nil } else if ctx.Bool(LocalHeimdallFlag.Name) { heimdallGrpcAddr := ctx.String(HeimdallGrpcAddressFlag.Name) sprintSize := uint64(ctx.Int(BorSprintSizeFlag.Name)) - return networks.NewBorDevnetWithLocalHeimdall(dataDir, baseRpcHost, baseRpcPort, heimdallGrpcAddr, sprintSize, producerCount, logger), nil + return networks.NewBorDevnetWithLocalHeimdall(dataDir, baseRpcHost, baseRpcPort, heimdallGrpcAddr, sprintSize, producerCount, gasLimit, logger, consoleLogLevel, dirLogLevel), nil } else { - return networks.NewBorDevnetWithRemoteHeimdall(dataDir, baseRpcHost, baseRpcPort, producerCount, logger), nil + return networks.NewBorDevnetWithRemoteHeimdall(dataDir, baseRpcHost, baseRpcPort, producerCount, gasLimit, logger, consoleLogLevel, dirLogLevel), nil } case networkname.DevChainName: - return networks.NewDevDevnet(dataDir, baseRpcHost, baseRpcPort, producerCount, logger), nil + return networks.NewDevDevnet(dataDir, baseRpcHost, baseRpcPort, producerCount, gasLimit, logger, consoleLogLevel, dirLogLevel), nil default: return nil, fmt.Errorf("unknown network: '%s'", chainName) diff --git a/cmd/devnet/networks/devnet_bor.go b/cmd/devnet/networks/devnet_bor.go index 9f8cbd2fad8..41d4993ea18 100644 --- a/cmd/devnet/networks/devnet_bor.go +++ b/cmd/devnet/networks/devnet_bor.go @@ -1,6 +1,7 @@ package networks import ( + "strconv" "time" "github.com/ledgerwatch/log/v3" @@ -21,7 +22,10 @@ func NewBorDevnetWithoutHeimdall( dataDir string, baseRpcHost string, baseRpcPort int, + gasLimit uint64, logger log.Logger, + consoleLogLevel log.Lvl, + dirLogLevel log.Lvl, ) devnet.Devnet { faucetSource := accounts.NewAccount("faucet-source") @@ -34,8 +38,11 @@ func NewBorDevnetWithoutHeimdall( BaseRPCHost: baseRpcHost, BaseRPCPort: baseRpcPort, //Snapshots: true, - Alloc: types.GenesisAlloc{ - faucetSource.Address: {Balance: accounts.EtherAmount(200_000)}, + Genesis: &types.Genesis{ + Alloc: types.GenesisAlloc{ + faucetSource.Address: {Balance: accounts.EtherAmount(200_000)}, + }, + GasLimit: gasLimit, }, Services: []devnet.Service{ account_services.NewFaucet(networkname.BorDevnetChainName, faucetSource), @@ -43,16 +50,16 @@ func NewBorDevnetWithoutHeimdall( Nodes: []devnet.Node{ &args.BlockProducer{ NodeArgs: args.NodeArgs{ - ConsoleVerbosity: "0", - DirVerbosity: "5", + ConsoleVerbosity: strconv.Itoa(int(consoleLogLevel)), + DirVerbosity: strconv.Itoa(int(dirLogLevel)), WithoutHeimdall: true, }, AccountSlots: 200, }, &args.BlockConsumer{ NodeArgs: args.NodeArgs{ - ConsoleVerbosity: "0", - DirVerbosity: "5", + ConsoleVerbosity: strconv.Itoa(int(consoleLogLevel)), + DirVerbosity: strconv.Itoa(int(dirLogLevel)), WithoutHeimdall: true, }, }, @@ -70,8 +77,11 @@ func NewBorDevnetWithHeimdall( heimdallGrpcAddr string, checkpointOwner *accounts.Account, producerCount int, + gasLimit uint64, withMilestones bool, logger log.Logger, + consoleLogLevel log.Lvl, + dirLogLevel log.Lvl, ) devnet.Devnet { faucetSource := accounts.NewAccount("faucet-source") @@ -89,8 +99,8 @@ func NewBorDevnetWithHeimdall( for i := 0; i < producerCount; i++ { nodes = append(nodes, &args.BlockProducer{ NodeArgs: args.NodeArgs{ - ConsoleVerbosity: "0", - DirVerbosity: "5", + ConsoleVerbosity: strconv.Itoa(int(consoleLogLevel)), + DirVerbosity: strconv.Itoa(int(dirLogLevel)), HeimdallGrpcAddr: heimdallGrpcAddr, }, AccountSlots: 20000, @@ -108,14 +118,17 @@ func NewBorDevnetWithHeimdall( BorStateSyncDelay: 5 * time.Second, BorWithMilestones: &withMilestones, Services: append(services, account_services.NewFaucet(networkname.BorDevnetChainName, faucetSource)), - Alloc: types.GenesisAlloc{ - faucetSource.Address: {Balance: accounts.EtherAmount(200_000)}, + Genesis: &types.Genesis{ + Alloc: types.GenesisAlloc{ + faucetSource.Address: {Balance: accounts.EtherAmount(200_000)}, + }, + GasLimit: gasLimit, }, Nodes: append(nodes, &args.BlockConsumer{ NodeArgs: args.NodeArgs{ - ConsoleVerbosity: "0", - DirVerbosity: "5", + ConsoleVerbosity: strconv.Itoa(int(consoleLogLevel)), + DirVerbosity: strconv.Itoa(int(dirLogLevel)), HeimdallGrpcAddr: heimdallGrpcAddr, }, }), @@ -130,15 +143,17 @@ func NewBorDevnetWithHeimdall( BaseRPCHost: baseRpcHost, BaseRPCPort: baseRpcPort + 1000, Services: append(services, account_services.NewFaucet(networkname.DevChainName, faucetSource)), - Alloc: types.GenesisAlloc{ - faucetSource.Address: {Balance: accounts.EtherAmount(200_000)}, - checkpointOwner.Address: {Balance: accounts.EtherAmount(10_000)}, + Genesis: &types.Genesis{ + Alloc: types.GenesisAlloc{ + faucetSource.Address: {Balance: accounts.EtherAmount(200_000)}, + checkpointOwner.Address: {Balance: accounts.EtherAmount(10_000)}, + }, }, Nodes: []devnet.Node{ &args.BlockProducer{ NodeArgs: args.NodeArgs{ - ConsoleVerbosity: "0", - DirVerbosity: "5", + ConsoleVerbosity: strconv.Itoa(int(consoleLogLevel)), + DirVerbosity: strconv.Itoa(int(dirLogLevel)), VMDebug: true, HttpCorsDomain: "*", }, @@ -147,8 +162,8 @@ func NewBorDevnetWithHeimdall( }, &args.BlockConsumer{ NodeArgs: args.NodeArgs{ - ConsoleVerbosity: "0", - DirVerbosity: "3", + ConsoleVerbosity: strconv.Itoa(int(consoleLogLevel)), + DirVerbosity: strconv.Itoa(int(dirLogLevel)), }, }, }, @@ -165,7 +180,10 @@ func NewBorDevnetWithRemoteHeimdall( baseRpcHost string, baseRpcPort int, producerCount int, + gasLimit uint64, logger log.Logger, + consoleLogLevel log.Lvl, + dirLogLevel log.Lvl, ) devnet.Devnet { heimdallGrpcAddr := "" checkpointOwner := accounts.NewAccount("checkpoint-owner") @@ -178,8 +196,11 @@ func NewBorDevnetWithRemoteHeimdall( heimdallGrpcAddr, checkpointOwner, producerCount, + gasLimit, withMilestones, - logger) + logger, + consoleLogLevel, + dirLogLevel) } func NewBorDevnetWithLocalHeimdall( @@ -189,7 +210,10 @@ func NewBorDevnetWithLocalHeimdall( heimdallGrpcAddr string, sprintSize uint64, producerCount int, + gasLimit uint64, logger log.Logger, + consoleLogLevel log.Lvl, + dirLogLevel log.Lvl, ) devnet.Devnet { config := *params.BorDevnetChainConfig borConfig := config.Bor.(*borcfg.BorConfig) @@ -216,7 +240,8 @@ func NewBorDevnetWithLocalHeimdall( heimdallGrpcAddr, checkpointOwner, producerCount, + gasLimit, // milestones are not supported yet on the local heimdall false, - logger) + logger, consoleLogLevel, dirLogLevel) } diff --git a/cmd/devnet/networks/devnet_dev.go b/cmd/devnet/networks/devnet_dev.go index 1429805400d..fa8e399f8bb 100644 --- a/cmd/devnet/networks/devnet_dev.go +++ b/cmd/devnet/networks/devnet_dev.go @@ -1,6 +1,8 @@ package networks import ( + "strconv" + "github.com/ledgerwatch/erigon-lib/chain/networkname" "github.com/ledgerwatch/erigon/cmd/devnet/accounts" "github.com/ledgerwatch/erigon/cmd/devnet/args" @@ -15,7 +17,10 @@ func NewDevDevnet( baseRpcHost string, baseRpcPort int, producerCount int, + gasLimit uint64, logger log.Logger, + consoleLogLevel log.Lvl, + dirLogLevel log.Lvl, ) devnet.Devnet { faucetSource := accounts.NewAccount("faucet-source") @@ -28,8 +33,8 @@ func NewDevDevnet( for i := 0; i < producerCount; i++ { nodes = append(nodes, &args.BlockProducer{ NodeArgs: args.NodeArgs{ - ConsoleVerbosity: "0", - DirVerbosity: "5", + ConsoleVerbosity: strconv.Itoa(int(consoleLogLevel)), + DirVerbosity: strconv.Itoa(int(dirLogLevel)), }, AccountSlots: 200, }) @@ -42,8 +47,11 @@ func NewDevDevnet( BasePrivateApiAddr: "localhost:10090", BaseRPCHost: baseRpcHost, BaseRPCPort: baseRpcPort, - Alloc: types.GenesisAlloc{ - faucetSource.Address: {Balance: accounts.EtherAmount(200_000)}, + Genesis: &types.Genesis{ + Alloc: types.GenesisAlloc{ + faucetSource.Address: {Balance: accounts.EtherAmount(200_000)}, + }, + GasLimit: gasLimit, }, Services: []devnet.Service{ account_services.NewFaucet(networkname.DevChainName, faucetSource), diff --git a/cmd/devnet/requests/request_generator.go b/cmd/devnet/requests/request_generator.go index 1c1e04628d1..1598cba5ce7 100644 --- a/cmd/devnet/requests/request_generator.go +++ b/cmd/devnet/requests/request_generator.go @@ -184,34 +184,50 @@ func (req *requestGenerator) rpcCall(ctx context.Context, result interface{}, me }) } -const connectionTimeout = time.Second * 5 +const requestTimeout = time.Second * 20 +const connectionTimeout = time.Millisecond * 500 func isConnectionError(err error) bool { var opErr *net.OpError - if errors.As(err, &opErr) { + switch { + case errors.As(err, &opErr): return opErr.Op == "dial" + + case errors.Is(err, context.DeadlineExceeded): + return true } + return false } func retryConnects(ctx context.Context, op func(context.Context) error) error { - ctx, cancel := context.WithTimeout(ctx, connectionTimeout) + ctx, cancel := context.WithTimeout(ctx, requestTimeout) defer cancel() - return retry(ctx, op, isConnectionError, time.Millisecond*200, nil) + return retry(ctx, op, isConnectionError, time.Second*1, nil) } func retry(ctx context.Context, op func(context.Context) error, isRecoverableError func(error) bool, delay time.Duration, lastErr error) error { - err := op(ctx) + opctx, cancel := context.WithTimeout(ctx, connectionTimeout) + defer cancel() + + err := op(opctx) + if err == nil { return nil } - if errors.Is(err, context.DeadlineExceeded) && lastErr != nil { - return lastErr - } + if !isRecoverableError(err) { return err } + if errors.Is(err, context.DeadlineExceeded) { + if lastErr != nil { + return lastErr + } + + err = nil + } + delayTimer := time.NewTimer(delay) select { case <-delayTimer.C: diff --git a/cmd/devnet/tests/context.go b/cmd/devnet/tests/context.go index 7f9ead04583..7eb115b0edf 100644 --- a/cmd/devnet/tests/context.go +++ b/cmd/devnet/tests/context.go @@ -16,7 +16,7 @@ import ( "github.com/ledgerwatch/log/v3" ) -func initDevnet(chainName string, dataDir string, producerCount int, logger log.Logger) (devnet.Devnet, error) { +func initDevnet(chainName string, dataDir string, producerCount int, gasLimit uint64, logger log.Logger, consoleLogLevel log.Lvl, dirLogLevel log.Lvl) (devnet.Devnet, error) { const baseRpcHost = "localhost" const baseRpcPort = 8545 @@ -24,17 +24,17 @@ func initDevnet(chainName string, dataDir string, producerCount int, logger log. case networkname.BorDevnetChainName: heimdallGrpcAddr := polygon.HeimdallGrpcAddressDefault const sprintSize uint64 = 0 - return networks.NewBorDevnetWithLocalHeimdall(dataDir, baseRpcHost, baseRpcPort, heimdallGrpcAddr, sprintSize, producerCount, logger), nil + return networks.NewBorDevnetWithLocalHeimdall(dataDir, baseRpcHost, baseRpcPort, heimdallGrpcAddr, sprintSize, producerCount, gasLimit, logger, consoleLogLevel, dirLogLevel), nil case networkname.DevChainName: - return networks.NewDevDevnet(dataDir, baseRpcHost, baseRpcPort, producerCount, logger), nil + return networks.NewDevDevnet(dataDir, baseRpcHost, baseRpcPort, producerCount, gasLimit, logger, consoleLogLevel, dirLogLevel), nil case "": envChainName, _ := os.LookupEnv("DEVNET_CHAIN") if envChainName == "" { envChainName = networkname.DevChainName } - return initDevnet(envChainName, dataDir, producerCount, logger) + return initDevnet(envChainName, dataDir, producerCount, gasLimit, logger, consoleLogLevel, dirLogLevel) default: return nil, fmt.Errorf("unknown network: '%s'", chainName) @@ -57,8 +57,12 @@ func ContextStart(t *testing.T, chainName string) (devnet.Context, error) { producerCount, _ := strconv.ParseUint(envProducerCount, 10, 64) + // TODO get log levels from env + var dirLogLevel log.Lvl = log.LvlTrace + var consoleLogLevel log.Lvl = log.LvlCrit + var network devnet.Devnet - network, err := initDevnet(chainName, dataDir, int(producerCount), logger) + network, err := initDevnet(chainName, dataDir, int(producerCount), 0, logger, consoleLogLevel, dirLogLevel) if err != nil { return nil, fmt.Errorf("ContextStart initDevnet failed: %w", err) } diff --git a/cmd/devnet/transactions/tx.go b/cmd/devnet/transactions/tx.go index dcaafd43865..3a241171f6f 100644 --- a/cmd/devnet/transactions/tx.go +++ b/cmd/devnet/transactions/tx.go @@ -140,27 +140,20 @@ func SendTxLoad(ctx context.Context, to, from string, amount uint64, txPerSec ui for { start := time.Now() - lowtx, hightx, err := CreateManyEIP1559TransactionsRefWithBaseFee2(ctx, to, from, int(batchCount)) + tx, err := CreateManyEIP1559TransactionsHigherThanBaseFee(ctx, to, from, int(batchCount)) if err != nil { logger.Error("failed Create Txs", "error", err) return err } - _, err = SendManyTransactions(ctx, lowtx) + _, err = SendManyTransactions(ctx, tx) if err != nil { logger.Error("failed SendManyTransactions(higherThanBaseFeeTxs)", "error", err) return err } - _, err = SendManyTransactions(ctx, hightx) - - if err != nil { - logger.Error("failed SendManyTransactions(lowerThanBaseFeeTxs)", "error", err) - return err - } - select { case <-ctx.Done(): return nil @@ -249,6 +242,33 @@ func CreateManyEIP1559TransactionsRefWithBaseFee2(ctx context.Context, to, from return lowerBaseFeeTransactions, higherBaseFeeTransactions, nil } +func CreateManyEIP1559TransactionsHigherThanBaseFee(ctx context.Context, to, from string, count int) ([]types.Transaction, error) { + toAddress := libcommon.HexToAddress(to) + fromAddress := libcommon.HexToAddress(from) + + baseFeePerGas, err := blocks.BaseFeeFromBlock(ctx) + + if err != nil { + return nil, fmt.Errorf("failed BaseFeeFromBlock: %v", err) + } + + baseFeePerGas = baseFeePerGas * 2 + + devnet.Logger(ctx).Info("BaseFeePerGas2", "val", baseFeePerGas) + + node := devnet.SelectNode(ctx) + + res, err := node.GetTransactionCount(fromAddress, rpc.PendingBlock) + + if err != nil { + return nil, fmt.Errorf("failed to get transaction count for address 0x%x: %v", fromAddress, err) + } + + nonce := res.Uint64() + + return signEIP1559TxsHigherThanBaseFee(ctx, count, baseFeePerGas, &nonce, toAddress, fromAddress) +} + // createNonContractTx returns a signed transaction and the recipient address func CreateTransaction(node devnet.Node, to, from string, value uint64) (types.Transaction, libcommon.Address, error) { toAccount := accounts.GetAccount(to) @@ -344,7 +364,7 @@ func signEIP1559TxsLowerThanBaseFee(ctx context.Context, n int, baseFeePerGas ui transaction := types.NewEIP1559Transaction(chainId, *nonce, toAddress, uint256.NewInt(value), uint64(210_000), uint256.NewInt(gasPrice), new(uint256.Int), uint256.NewInt(gasFeeCap), nil) - devnet.Logger(ctx).Info("LOWER", "transaction", i, "nonce", transaction.Nonce, "value", transaction.Value, "feecap", transaction.FeeCap) + devnet.Logger(ctx).Trace("LOWER", "transaction", i, "nonce", transaction.Nonce, "value", transaction.Value, "feecap", transaction.FeeCap) signedTransaction, err := types.SignTx(transaction, signer, accounts.SigKey(fromAddress)) @@ -385,7 +405,7 @@ func signEIP1559TxsHigherThanBaseFee(ctx context.Context, n int, baseFeePerGas u transaction := types.NewEIP1559Transaction(chainId, *nonce, toAddress, uint256.NewInt(value), uint64(210_000), uint256.NewInt(gasPrice), new(uint256.Int), uint256.NewInt(gasFeeCap), nil) - devnet.Logger(ctx).Info("HIGHER", "transaction", i, "nonce", transaction.Nonce, "value", transaction.Value, "feecap", transaction.FeeCap) + devnet.Logger(ctx).Trace("HIGHER", "transaction", i, "nonce", transaction.Nonce, "value", transaction.Value, "feecap", transaction.FeeCap) signerKey := accounts.SigKey(fromAddress) if signerKey == nil { @@ -407,7 +427,7 @@ func signEIP1559TxsHigherThanBaseFee(ctx context.Context, n int, baseFeePerGas u func SendManyTransactions(ctx context.Context, signedTransactions []types.Transaction) ([]libcommon.Hash, error) { logger := devnet.Logger(ctx) - logger.Info("Sending multiple transactions to the txpool...") + logger.Info(fmt.Sprintf("Sending %d transactions to the txpool...", len(signedTransactions))) hashes := make([]libcommon.Hash, len(signedTransactions)) for idx, tx := range signedTransactions { diff --git a/cmd/rpcdaemon/cli/config.go b/cmd/rpcdaemon/cli/config.go index 34f8f438c92..5a2f37db806 100644 --- a/cmd/rpcdaemon/cli/config.go +++ b/cmd/rpcdaemon/cli/config.go @@ -208,7 +208,7 @@ func subscribeToStateChangesLoop(ctx context.Context, client StateChangesClient, time.Sleep(3 * time.Second) continue } - log.Warn("[txpool.handleStateChanges]", "err", err) + log.Warn("[rpcdaemon subscribeToStateChanges]", "err", err) } } }() diff --git a/cmd/txpool/main.go b/cmd/txpool/main.go index d915a18b32b..463be539be8 100644 --- a/cmd/txpool/main.go +++ b/cmd/txpool/main.go @@ -170,12 +170,6 @@ func doTxpool(ctx context.Context, logger log.Logger) error { fetch.ConnectCore() fetch.ConnectSentries() - /* - var ethashApi *ethash.API - sif casted, ok := backend.engine.(*ethash.Ethash); ok { - ethashApi = casted.APIs(nil)[1].Service.(*ethash.API) - } - */ miningGrpcServer := privateapi.NewMiningServer(ctx, &rpcdaemontest.IsMiningMock{}, nil, logger) grpcServer, err := txpool.StartGrpc(txpoolGrpcServer, miningGrpcServer, txpoolApiAddr, nil, logger) diff --git a/consensus/chain_reader.go b/consensus/chain_reader.go index f79de40c4cc..c7d81953b7c 100644 --- a/consensus/chain_reader.go +++ b/consensus/chain_reader.go @@ -82,7 +82,7 @@ func (cr ChainReaderImpl) FrozenBlocks() uint64 { func (cr ChainReaderImpl) BorSpan(spanId uint64) []byte { spanBytes, err := cr.BlockReader.Span(context.Background(), cr.Db, spanId) if err != nil { - log.Error("BorSpan failed", "err", err) + log.Error("[consensus] BorSpan failed", "err", err) } return spanBytes } diff --git a/erigon-lib/downloader/path.go b/erigon-lib/downloader/path.go index 06ba51865b4..195c6d05ced 100644 --- a/erigon-lib/downloader/path.go +++ b/erigon-lib/downloader/path.go @@ -171,7 +171,7 @@ func Clean(path string) string { return FromSlash(out.string()) } -func unixIsLocal(path string) bool { +func unixIsLocal(path string) bool { //nolint if IsAbs(path) || path == "" { return false } diff --git a/erigon-lib/downloader/path_windows.go b/erigon-lib/downloader/path_windows.go index f5f4a01d905..687e81429ca 100644 --- a/erigon-lib/downloader/path_windows.go +++ b/erigon-lib/downloader/path_windows.go @@ -175,51 +175,6 @@ func HasPrefix(p, prefix string) bool { return strings.HasPrefix(strings.ToLower(p), strings.ToLower(prefix)) } -func splitList(path string) []string { - // The same implementation is used in LookPath in os/exec; - // consider changing os/exec when changing this. - - if path == "" { - return []string{} - } - - // Split path, respecting but preserving quotes. - list := []string{} - start := 0 - quo := false - for i := 0; i < len(path); i++ { - switch c := path[i]; { - case c == '"': - quo = !quo - case c == ListSeparator && !quo: - list = append(list, path[start:i]) - start = i + 1 - } - } - list = append(list, path[start:]) - - // Remove quotes. - for i, s := range list { - list[i] = strings.ReplaceAll(s, `"`, ``) - } - - return list -} - -func abs(path string) (string, error) { - if path == "" { - // syscall.FullPath returns an error on empty path, because it's not a valid path. - // To implement Abs behavior of returning working directory on empty string input, - // special-case empty path by changing it to "." path. See golang.org/issue/24441. - path = "." - } - fullPath, err := syscall.FullPath(path) - if err != nil { - return "", err - } - return Clean(fullPath), nil -} - func join(elem []string) string { var b strings.Builder var lastChar byte @@ -260,47 +215,3 @@ func join(elem []string) string { } return Clean(b.String()) } - -// joinNonEmpty is like join, but it assumes that the first element is non-empty. -func joinNonEmpty(elem []string) string { - if len(elem[0]) == 2 && elem[0][1] == ':' { - // First element is drive letter without terminating slash. - // Keep path relative to current directory on that drive. - // Skip empty elements. - i := 1 - for ; i < len(elem); i++ { - if elem[i] != "" { - break - } - } - return Clean(elem[0] + strings.Join(elem[i:], string(Separator))) - } - // The following logic prevents Join from inadvertently creating a - // UNC path on Windows. Unless the first element is a UNC path, Join - // shouldn't create a UNC path. See golang.org/issue/9167. - p := Clean(strings.Join(elem, string(Separator))) - if !isUNC(p) { - return p - } - // p == UNC only allowed when the first element is a UNC path. - head := Clean(elem[0]) - if isUNC(head) { - return p - } - // head + tail == UNC, but joining two non-UNC paths should not result - // in a UNC path. Undo creation of UNC path. - tail := Clean(strings.Join(elem[1:], string(Separator))) - if head[len(head)-1] == Separator { - return head + tail - } - return head + string(Separator) + tail -} - -// isUNC reports whether path is a UNC path. -func isUNC(path string) bool { - return len(path) > 1 && isSlash(path[0]) && isSlash(path[1]) -} - -func sameWord(a, b string) bool { - return strings.EqualFold(a, b) -} diff --git a/erigon-lib/mmap/mmap_windows.go b/erigon-lib/mmap/mmap_windows.go index b343ebb4024..0ce85db9ec2 100644 --- a/erigon-lib/mmap/mmap_windows.go +++ b/erigon-lib/mmap/mmap_windows.go @@ -41,7 +41,7 @@ func Mmap(f *os.File, size int) ([]byte, *[MaxMapSize]byte, error) { } // Close mapping handle. - if err := windows.CloseHandle(windows.Handle(h)); err != nil { + if err := windows.CloseHandle(h); err != nil { return nil, nil, os.NewSyscallError("CloseHandle", err) } diff --git a/erigon-lib/txpool/pool.go b/erigon-lib/txpool/pool.go index 69dfb39324f..45dc6f11523 100644 --- a/erigon-lib/txpool/pool.go +++ b/erigon-lib/txpool/pool.go @@ -126,7 +126,6 @@ type metaTx struct { timestamp uint64 // when it was added to pool subPool SubPoolMarker currentSubPool SubPoolType - alreadyYielded bool minedBlockNum uint64 } @@ -211,6 +210,7 @@ type TxPool struct { cfg txpoolcfg.Config chainID uint256.Int lastSeenBlock atomic.Uint64 + lastSeenCond *sync.Cond lastFinalizedBlock atomic.Uint64 started atomic.Bool pendingBaseFee atomic.Uint64 @@ -249,8 +249,11 @@ func New(newTxs chan types.Announcements, coreDB kv.RoDB, cfg txpoolcfg.Config, tracedSenders[common.BytesToAddress([]byte(sender))] = struct{}{} } + lock := &sync.Mutex{} + res := &TxPool{ - lock: &sync.Mutex{}, + lock: lock, + lastSeenCond: sync.NewCond(lock), byHash: map[string]*metaTx{}, isLocalLRU: localsHistory, discardReasonsLRU: discardHistory, @@ -298,42 +301,81 @@ func New(newTxs chan types.Announcements, coreDB kv.RoDB, cfg txpoolcfg.Config, return res, nil } -func (p *TxPool) OnNewBlock(ctx context.Context, stateChanges *remote.StateChangeBatch, unwindTxs, minedTxs types.TxSlots, tx kv.Tx) error { - if err := minedTxs.Valid(); err != nil { - return err +func (p *TxPool) Start(ctx context.Context, db kv.RwDB) error { + if p.started.Load() { + return nil } + return db.View(ctx, func(tx kv.Tx) error { + coreDb, _ := p.coreDBWithCache() + coreTx, err := coreDb.BeginRo(ctx) + + if err != nil { + return err + } + + defer coreTx.Rollback() + + if err := p.fromDB(ctx, tx, coreTx); err != nil { + return fmt.Errorf("loading pool from DB: %w", err) + } + + if p.started.CompareAndSwap(false, true) { + p.logger.Info("[txpool] Started") + } + + return nil + }) +} + +func (p *TxPool) OnNewBlock(ctx context.Context, stateChanges *remote.StateChangeBatch, unwindTxs, minedTxs types.TxSlots, tx kv.Tx) error { + defer newBlockTimer.ObserveDuration(time.Now()) //t := time.Now() coreDB, cache := p.coreDBWithCache() cache.OnNewBlock(stateChanges) coreTx, err := coreDB.BeginRo(ctx) + if err != nil { return err } + defer coreTx.Rollback() - p.lastSeenBlock.Store(stateChanges.ChangeBatch[len(stateChanges.ChangeBatch)-1].BlockHeight) - if !p.started.Load() { - if err := p.fromDBWithLock(ctx, tx, coreTx); err != nil { - return fmt.Errorf("OnNewBlock: loading txs from DB: %w", err) - } + block := stateChanges.ChangeBatch[len(stateChanges.ChangeBatch)-1].BlockHeight + baseFee := stateChanges.PendingBlockBaseFee + available := len(p.pending.best.ms) + + defer func() { + p.logger.Debug("[txpool] New block", "block", block, "unwound", len(unwindTxs.Txs), "mined", len(minedTxs.Txs), "baseFee", baseFee, "pending-pre", available, "pending", p.pending.Len(), "baseFee", p.baseFee.Len(), "queued", p.queued.Len(), "err", err) + }() + + if err = minedTxs.Valid(); err != nil { + return err } + cacheView, err := cache.View(ctx, coreTx) + if err != nil { return err } p.lock.Lock() - defer p.lock.Unlock() + defer func() { + if err == nil { + p.lastSeenBlock.Store(block) + p.lastSeenCond.Broadcast() + } + + p.lock.Unlock() + }() if assert.Enable { if _, err := kvcache.AssertCheckValues(ctx, coreTx, cache); err != nil { p.logger.Error("AssertCheckValues", "err", err, "stack", stack.Trace().String()) } } - baseFee := stateChanges.PendingBlockBaseFee pendingBaseFee, baseFeeChanged := p.setBaseFee(baseFee) // Update pendingBase for all pool queues and slices @@ -350,10 +392,13 @@ func (p *TxPool) OnNewBlock(ctx context.Context, stateChanges *remote.StateChang p.setBlobFee(pendingBlobFee) p.blockGasLimit.Store(stateChanges.BlockGasLimit) - if err := p.senders.onNewBlock(stateChanges, unwindTxs, minedTxs, p.logger); err != nil { + + if err = p.senders.onNewBlock(stateChanges, unwindTxs, minedTxs, p.logger); err != nil { return err } + _, unwindTxs, err = p.validateTxs(&unwindTxs, cacheView) + if err != nil { return err } @@ -371,21 +416,23 @@ func (p *TxPool) OnNewBlock(ctx context.Context, stateChanges *remote.StateChang } } - if err := p.processMinedFinalizedBlobs(coreTx, minedTxs.Txs, stateChanges.FinalizedBlock); err != nil { + if err = p.processMinedFinalizedBlobs(coreTx, minedTxs.Txs, stateChanges.FinalizedBlock); err != nil { return err } - if err := removeMined(p.all, minedTxs.Txs, p.pending, p.baseFee, p.queued, p.discardLocked, p.logger); err != nil { + + if err = removeMined(p.all, minedTxs.Txs, p.pending, p.baseFee, p.queued, p.discardLocked, p.logger); err != nil { return err } - //p.logger.Debug("[txpool] new block", "unwinded", len(unwindTxs.txs), "mined", len(minedTxs.txs), "baseFee", baseFee, "blockHeight", blockHeight) + var announcements types.Announcements + + announcements, err = addTxsOnNewBlock(block, cacheView, stateChanges, p.senders, unwindTxs, /* newTxs */ + pendingBaseFee, stateChanges.BlockGasLimit, p.pending, p.baseFee, p.queued, p.all, p.byHash, p.addLocked, p.discardLocked, p.logger) - announcements, err := addTxsOnNewBlock(p.lastSeenBlock.Load(), cacheView, stateChanges, p.senders, unwindTxs, /* newTxs */ - pendingBaseFee, stateChanges.BlockGasLimit, - p.pending, p.baseFee, p.queued, p.all, p.byHash, p.addLocked, p.discardLocked, p.logger) if err != nil { return err } + p.pending.EnforceWorstInvariants() p.baseFee.EnforceInvariants() p.queued.EnforceInvariants() @@ -394,10 +441,6 @@ func (p *TxPool) OnNewBlock(ctx context.Context, stateChanges *remote.StateChang p.promoted.Reset() p.promoted.AppendOther(announcements) - if p.started.CompareAndSwap(false, true) { - p.logger.Info("[txpool] Started") - } - if p.promoted.Len() > 0 { select { case p.newPendingTxs <- p.promoted.Copy(): @@ -405,12 +448,11 @@ func (p *TxPool) OnNewBlock(ctx context.Context, stateChanges *remote.StateChang } } - //p.logger.Info("[txpool] new block", "number", p.lastSeenBlock.Load(), "pendngBaseFee", pendingBaseFee, "in", time.Since(t)) return nil } func (p *TxPool) processRemoteTxs(ctx context.Context) error { - if !p.started.Load() { + if !p.Started() { return fmt.Errorf("txpool not started yet") } @@ -610,20 +652,29 @@ func (p *TxPool) IsLocal(idHash []byte) bool { func (p *TxPool) AddNewGoodPeer(peerID types.PeerID) { p.recentlyConnectedPeers.AddPeer(peerID) } func (p *TxPool) Started() bool { return p.started.Load() } -func (p *TxPool) best(n uint16, txs *types.TxsRlp, tx kv.Tx, onTopOf, availableGas, availableBlobGas uint64, toSkip mapset.Set[[32]byte]) (bool, int, error) { - // First wait for the corresponding block to arrive - if p.lastSeenBlock.Load() < onTopOf { - return false, 0, nil // Too early +func (p *TxPool) best(n uint16, txs *types.TxsRlp, tx kv.Tx, onTopOf, availableGas, availableBlobGas uint64, yielded mapset.Set[[32]byte]) (bool, int, error) { + p.lock.Lock() + defer p.lock.Unlock() + + for last := p.lastSeenBlock.Load(); last < onTopOf; last = p.lastSeenBlock.Load() { + p.logger.Debug("[txpool] Waiting for block", "expecting", onTopOf, "lastSeen", last, "txRequested", n, "pending", p.pending.Len(), "baseFee", p.baseFee.Len(), "queued", p.queued.Len()) + p.lastSeenCond.Wait() } - isShanghai := p.isShanghai() || p.isAgra() best := p.pending.best + isShanghai := p.isShanghai() || p.isAgra() + txs.Resize(uint(cmp.Min(int(n), len(best.ms)))) var toRemove []*metaTx count := 0 + i := 0 - for i := 0; count < int(n) && i < len(best.ms); i++ { + defer func() { + p.logger.Debug("[txpool] Processing best request", "last", onTopOf, "txRequested", n, "txAvailable", len(best.ms), "txProcessed", i, "txReturned", count) + }() + + for ; count < int(n) && i < len(best.ms); i++ { // if we wouldn't have enough gas for a standard transaction then quit out early if availableGas < fixedgas.TxGas { break @@ -631,7 +682,7 @@ func (p *TxPool) best(n uint16, txs *types.TxsRlp, tx kv.Tx, onTopOf, availableG mt := best.ms[i] - if toSkip.Contains(mt.Tx.IDHash) { + if yielded.Contains(mt.Tx.IDHash) { continue } @@ -669,7 +720,7 @@ func (p *TxPool) best(n uint16, txs *types.TxsRlp, tx kv.Tx, onTopOf, availableG txs.Txs[count] = rlpTx copy(txs.Senders.At(count), sender.Bytes()) txs.IsLocal[count] = isLocal - toSkip.Add(mt.Tx.IDHash) // TODO: Is this unnecessary + yielded.Add(mt.Tx.IDHash) count++ } @@ -682,26 +733,13 @@ func (p *TxPool) best(n uint16, txs *types.TxsRlp, tx kv.Tx, onTopOf, availableG return true, count, nil } -func (p *TxPool) ResetYieldedStatus() { - p.lock.Lock() - defer p.lock.Unlock() - best := p.pending.best - for i := 0; i < len(best.ms); i++ { - best.ms[i].alreadyYielded = false - } -} - func (p *TxPool) YieldBest(n uint16, txs *types.TxsRlp, tx kv.Tx, onTopOf, availableGas, availableBlobGas uint64, toSkip mapset.Set[[32]byte]) (bool, int, error) { - p.lock.Lock() - defer p.lock.Unlock() return p.best(n, txs, tx, onTopOf, availableGas, availableBlobGas, toSkip) } func (p *TxPool) PeekBest(n uint16, txs *types.TxsRlp, tx kv.Tx, onTopOf, availableGas, availableBlobGas uint64) (bool, error) { set := mapset.NewThreadUnsafeSet[[32]byte]() - p.lock.Lock() - defer p.lock.Unlock() - onTime, _, err := p.best(n, txs, tx, onTopOf, availableGas, availableBlobGas, set) + onTime, _, err := p.YieldBest(n, txs, tx, onTopOf, availableGas, availableBlobGas, set) return onTime, err } @@ -1075,15 +1113,6 @@ func (p *TxPool) AddLocalTxs(ctx context.Context, newTransactions types.TxSlots, p.lock.Lock() defer p.lock.Unlock() - if !p.Started() { - if err := p.fromDB(ctx, tx, coreTx); err != nil { - return nil, fmt.Errorf("AddLocalTxs: loading txs from DB: %w", err) - } - if p.started.CompareAndSwap(false, true) { - p.logger.Info("[txpool] Started") - } - } - if err = p.senders.registerNewSenders(&newTransactions, p.logger); err != nil { return nil, err } @@ -1432,27 +1461,38 @@ func removeMined(byNonce *BySenderAndNonce, minedTxs []*types.TxSlot, pending *P } var toDel []*metaTx // can't delete items while iterate them + + discarded := 0 + pendingRemoved := 0 + baseFeeRemoved := 0 + queuedRemoved := 0 + for senderID, nonce := range noncesToRemove { - //if sender.all.Len() > 0 { - //logger.Debug("[txpool] removing mined", "senderID", tx.senderID, "sender.all.len()", sender.all.Len()) - //} - // delete mined transactions from everywhere + byNonce.ascend(senderID, func(mt *metaTx) bool { - //logger.Debug("[txpool] removing mined, cmp nonces", "tx.nonce", it.metaTx.Tx.nonce, "sender.nonce", sender.nonce) if mt.Tx.Nonce > nonce { + if mt.Tx.Traced { + logger.Debug("[txpool] removing mined, cmp nonces", "tx.nonce", mt.Tx.Nonce, "sender.nonce", nonce) + } + return false } + if mt.Tx.Traced { logger.Info(fmt.Sprintf("TX TRACING: removeMined idHash=%x senderId=%d, currentSubPool=%s", mt.Tx.IDHash, mt.Tx.SenderID, mt.currentSubPool)) } + toDel = append(toDel, mt) // del from sub-pool switch mt.currentSubPool { case PendingSubPool: + pendingRemoved++ pending.Remove(mt) case BaseFeeSubPool: + baseFeeRemoved++ baseFee.Remove(mt) case QueuedSubPool: + queuedRemoved++ queued.Remove(mt) default: //already removed @@ -1460,11 +1500,18 @@ func removeMined(byNonce *BySenderAndNonce, minedTxs []*types.TxSlot, pending *P return true }) + discarded += len(toDel) + for _, mt := range toDel { discard(mt, txpoolcfg.Mined) } toDel = toDel[:0] } + + if discarded > 0 { + logger.Debug("Discarding Transactions", "count", discarded, "pending", pendingRemoved, "baseFee", baseFeeRemoved, "queued", queuedRemoved) + } + return nil } @@ -1657,6 +1704,13 @@ func MainLoop(ctx context.Context, db kv.RwDB, coreDB kv.RoDB, p *TxPool, newTxs logEvery := time.NewTicker(p.cfg.LogEvery) defer logEvery.Stop() + err := p.Start(ctx, db) + + if err != nil { + p.logger.Error("[txpool] Failed to start", "err", err) + return + } + for { select { case <-ctx.Done(): @@ -1724,7 +1778,7 @@ func MainLoop(ctx context.Context, db kv.RwDB, coreDB kv.RoDB, p *TxPool, newTxs var remoteTxSizes []uint32 var remoteTxHashes types.Hashes var remoteTxRlps [][]byte - var broadCastedHashes types.Hashes + var broadcastHashes types.Hashes slotsRlp := make([][]byte, 0, announcements.Len()) if err := db.View(ctx, func(tx kv.Tx) error { @@ -1748,7 +1802,7 @@ func MainLoop(ctx context.Context, db kv.RwDB, coreDB kv.RoDB, p *TxPool, newTxs // "Nodes MUST NOT automatically broadcast blob transactions to their peers" - EIP-4844 if t != types.BlobTxType { localTxRlps = append(localTxRlps, slotRlp) - broadCastedHashes = append(broadCastedHashes, hash...) + broadcastHashes = append(broadcastHashes, hash...) } } else { remoteTxTypes = append(remoteTxTypes, t) @@ -1775,12 +1829,12 @@ func MainLoop(ctx context.Context, db kv.RwDB, coreDB kv.RoDB, p *TxPool, newTxs const localTxsBroadcastMaxPeers uint64 = 10 txSentTo := send.BroadcastPooledTxs(localTxRlps, localTxsBroadcastMaxPeers) for i, peer := range txSentTo { - p.logger.Info("Local tx broadcasted", "txHash", hex.EncodeToString(broadCastedHashes.At(i)), "to peer", peer) + p.logger.Trace("Local tx broadcast", "txHash", hex.EncodeToString(broadcastHashes.At(i)), "to peer", peer) } hashSentTo := send.AnnouncePooledTxs(localTxTypes, localTxSizes, localTxHashes, localTxsBroadcastMaxPeers*2) for i := 0; i < localTxHashes.Len(); i++ { hash := localTxHashes.At(i) - p.logger.Info("Local tx announced", "txHash", hex.EncodeToString(hash), "to peer", hashSentTo[i], "baseFee", p.pendingBaseFee.Load()) + p.logger.Trace("Local tx announced", "txHash", hex.EncodeToString(hash), "to peer", hashSentTo[i], "baseFee", p.pendingBaseFee.Load()) } // broadcast remote transactions @@ -1844,6 +1898,7 @@ func (p *TxPool) flush(ctx context.Context, db kv.RwDB) (written uint64, err err } return written, nil } + func (p *TxPool) flushLocked(tx kv.RwTx) (err error) { for i, mt := range p.deletedTxs { id := mt.Tx.SenderID @@ -1927,20 +1982,33 @@ func (p *TxPool) flushLocked(tx kv.RwTx) (err error) { return nil } -func (p *TxPool) fromDBWithLock(ctx context.Context, tx kv.Tx, coreTx kv.Tx) error { - p.lock.Lock() - defer p.lock.Unlock() - return p.fromDB(ctx, tx, coreTx) -} func (p *TxPool) fromDB(ctx context.Context, tx kv.Tx, coreTx kv.Tx) error { if p.lastSeenBlock.Load() == 0 { lastSeenBlock, err := LastSeenBlock(tx) if err != nil { return err } + p.lastSeenBlock.Store(lastSeenBlock) } + // this is neccessary as otherwise best - which waits for sync events + // may wait for ever if blocks have been process before the txpool + // starts with an empty db + lastSeenProgress, err := getExecutionProgress(coreTx) + + if err != nil { + return err + } + + if p.lastSeenBlock.Load() < lastSeenProgress { + // TODO we need to process the blocks since the + // last seen to make sure that the tx pool is in + // sync with the processed blocks + + p.lastSeenBlock.Store(lastSeenProgress) + } + cacheView, err := p._stateCache.View(ctx, coreTx) if err != nil { return err @@ -2031,6 +2099,24 @@ func (p *TxPool) fromDB(ctx context.Context, tx kv.Tx, coreTx kv.Tx) error { p.pendingBlobFee.Store(pendingBlobFee) return nil } + +func getExecutionProgress(db kv.Getter) (uint64, error) { + data, err := db.GetOne(kv.SyncStageProgress, []byte("Execution")) + if err != nil { + return 0, err + } + + if len(data) == 0 { + return 0, nil + } + + if len(data) < 8 { + return 0, fmt.Errorf("value must be at least 8 bytes, got %d", len(data)) + } + + return binary.BigEndian.Uint64(data[:8]), nil +} + func LastSeenBlock(tx kv.Getter) (uint64, error) { v, err := tx.GetOne(kv.PoolInfo, PoolLastSeenBlockKey) if err != nil { @@ -2093,7 +2179,7 @@ func (p *TxPool) printDebug(prefix string) { } } func (p *TxPool) logStats() { - if !p.started.Load() { + if !p.Started() { //p.logger.Info("[txpool] Not started yet, waiting for new blocks...") return } diff --git a/erigon-lib/txpool/pool_fuzz_test.go b/erigon-lib/txpool/pool_fuzz_test.go index e81d316910a..1e8923d88fd 100644 --- a/erigon-lib/txpool/pool_fuzz_test.go +++ b/erigon-lib/txpool/pool_fuzz_test.go @@ -316,6 +316,10 @@ func FuzzOnNewBlocks(f *testing.F) { sendersCache := kvcache.New(kvcache.DefaultCoherentConfig) pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, log.New()) assert.NoError(err) + + err = pool.Start(ctx, db) + assert.NoError(err) + pool.senders.senderIDs = senderIDs for addr, id := range senderIDs { pool.senders.senderID2Addr[id] = addr @@ -538,6 +542,7 @@ func FuzzOnNewBlocks(f *testing.F) { p2, err := New(ch, coreDB, txpoolcfg.DefaultConfig, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, log.New()) assert.NoError(err) + p2.senders = pool.senders // senders are not persisted err = coreDB.View(ctx, func(coreTx kv.Tx) error { return p2.fromDB(ctx, tx, coreTx) }) require.NoError(err) diff --git a/erigon-lib/txpool/pool_test.go b/erigon-lib/txpool/pool_test.go index a438be399e6..ef4347a587e 100644 --- a/erigon-lib/txpool/pool_test.go +++ b/erigon-lib/txpool/pool_test.go @@ -19,6 +19,7 @@ package txpool import ( "bytes" "context" + // "crypto/rand" "fmt" "math" @@ -957,6 +958,10 @@ func TestDropRemoteAtNoGossip(t *testing.T) { require.True(txPool != nil) ctx := context.Background() + + err = txPool.Start(ctx, db) + assert.NoError(err) + var stateVersionID uint64 = 0 pendingBaseFee := uint64(1_000_000) // start blocks from 0, set empty hash - then kvcache will also work on this diff --git a/eth/backend.go b/eth/backend.go index bbec2e31c8e..105092b37cd 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -29,6 +29,7 @@ import ( "strconv" "strings" "sync" + "sync/atomic" "time" lru "github.com/hashicorp/golang-lru/arc/v2" @@ -616,7 +617,6 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger miner := stagedsync.NewMiningState(&config.Miner) backend.pendingBlocks = miner.PendingResultCh - backend.minedBlocks = miner.MiningResultCh var ( snapDb kv.RwDB @@ -780,7 +780,7 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger } }() - if err := backend.StartMining(context.Background(), backend.chainDB, mining, backend.config.Miner, backend.sentriesClient.Hd.QuitPoWMining, tmpdir, logger); err != nil { + if err := backend.StartMining(context.Background(), backend.chainDB, stateDiffClient, mining, miner, backend.gasPrice, backend.sentriesClient.Hd.QuitPoWMining, tmpdir, logger); err != nil { return nil, err } @@ -1010,7 +1010,8 @@ func (s *Ethereum) shouldPreserve(block *types.Block) bool { //nolint // StartMining starts the miner with the given number of CPU threads. If mining // is already running, this method adjust the number of threads allowed to use // and updates the minimum price required by the transaction pool. -func (s *Ethereum) StartMining(ctx context.Context, db kv.RwDB, mining *stagedsync.Sync, cfg params.MiningConfig, quitCh chan struct{}, tmpDir string, logger log.Logger) error { +func (s *Ethereum) StartMining(ctx context.Context, db kv.RwDB, stateDiffClient *direct.StateDiffClientDirect, mining *stagedsync.Sync, miner stagedsync.MiningState, gasPrice *uint256.Int, quitCh chan struct{}, tmpDir string, logger log.Logger) error { + var borcfg *bor.Bor if b, ok := s.engine.(*bor.Bor); ok { borcfg = b @@ -1023,7 +1024,7 @@ func (s *Ethereum) StartMining(ctx context.Context, db kv.RwDB, mining *stagedsy } //if borcfg == nil { - if !cfg.Enabled { + if !miner.MiningConfig.Enabled { return nil } //} @@ -1036,14 +1037,14 @@ func (s *Ethereum) StartMining(ctx context.Context, db kv.RwDB, mining *stagedsy } if borcfg != nil { - if cfg.Enabled { - if cfg.SigKey == nil { + if miner.MiningConfig.Enabled { + if miner.MiningConfig.SigKey == nil { s.logger.Error("Etherbase account unavailable locally", "err", err) return fmt.Errorf("signer missing: %w", err) } borcfg.Authorize(eb, func(_ libcommon.Address, mimeType string, message []byte) ([]byte, error) { - return crypto.Sign(crypto.Keccak256(message), cfg.SigKey) + return crypto.Sign(crypto.Keccak256(message), miner.MiningConfig.SigKey) }) if !s.config.WithoutHeimdall { @@ -1082,47 +1083,73 @@ func (s *Ethereum) StartMining(ctx context.Context, db kv.RwDB, mining *stagedsy } } if clq != nil { - if cfg.SigKey == nil { + if miner.MiningConfig.SigKey == nil { s.logger.Error("Etherbase account unavailable locally", "err", err) return fmt.Errorf("signer missing: %w", err) } clq.Authorize(eb, func(_ libcommon.Address, mimeType string, message []byte) ([]byte, error) { - return crypto.Sign(crypto.Keccak256(message), cfg.SigKey) + return crypto.Sign(crypto.Keccak256(message), miner.MiningConfig.SigKey) }) } + streamCtx, streamCancel := context.WithCancel(ctx) + stream, err := stateDiffClient.StateChanges(streamCtx, &remote.StateChangeRequest{WithStorage: false, WithTransactions: true}, grpc.WaitForReady(true)) + + if err != nil { + streamCancel() + return err + } + + stateChangeCh := make(chan *remote.StateChange) + + go func() { + for req, err := stream.Recv(); ; req, err = stream.Recv() { + if err == nil { + for _, change := range req.ChangeBatch { + stateChangeCh <- change + } + } + } + }() + go func() { defer debug.LogPanic() defer close(s.waitForMiningStop) + defer streamCancel() - mineEvery := time.NewTicker(cfg.Recommit) + mineEvery := time.NewTicker(miner.MiningConfig.Recommit) defer mineEvery.Stop() - // Listen on a new head subscription. This allows us to maintain the block time by - // triggering mining after the block is passed through all stages. - newHeadCh, closeNewHeadCh := s.notifications.Events.AddHeaderSubscription() - defer closeNewHeadCh() - s.logger.Info("Starting to mine", "etherbase", eb) - var works bool + var working bool + var waiting atomic.Bool + hasWork := true // Start mining immediately errc := make(chan error, 1) + workCtx, workCancel := context.WithCancel(ctx) + defer workCancel() + for { // Only reset if some work was done previously as we'd like to rely // on the `miner.recommit` as backup. if hasWork { - mineEvery.Reset(cfg.Recommit) + mineEvery.Reset(miner.MiningConfig.Recommit) } - // Only check for case if you're already mining (i.e. works = true) and + // Only check for case if you're already mining (i.e. working = true) and // waiting for error or you don't have any work yet (i.e. hasWork = false). - if works || !hasWork { + if working || !hasWork { select { - case <-newHeadCh: + case stateChanges := <-stateChangeCh: + block := stateChanges.BlockHeight + s.logger.Debug("Start mining new block based on previous block", "block", block) + // TODO - can do mining clean up here as we have previous + // block info in the state channel hasWork = true + case <-s.notifyMiningAboutNewTxs: // Skip mining based on new tx notif for bor consensus hasWork = s.chainConfig.Bor == nil @@ -1130,10 +1157,12 @@ func (s *Ethereum) StartMining(ctx context.Context, db kv.RwDB, mining *stagedsy s.logger.Debug("Start mining new block based on txpool notif") } case <-mineEvery.C: - s.logger.Debug("Start mining new block based on miner.recommit") - hasWork = true + if !(working || waiting.Load()) { + s.logger.Debug("Start mining new block based on miner.recommit", "duration", miner.MiningConfig.Recommit) + } + hasWork = !(working || waiting.Load()) case err := <-errc: - works = false + working = false hasWork = false if errors.Is(err, libcommon.ErrStopped) { return @@ -1146,11 +1175,36 @@ func (s *Ethereum) StartMining(ctx context.Context, db kv.RwDB, mining *stagedsy } } - if !works && hasWork { - works = true + if !working && hasWork { + working = true hasWork = false - mineEvery.Reset(cfg.Recommit) - go func() { errc <- stages2.MiningStep(ctx, db, mining, tmpDir, logger) }() + mineEvery.Reset(miner.MiningConfig.Recommit) + go func() { + err := stages2.MiningStep(ctx, db, mining, tmpDir, logger) + + waiting.Store(true) + defer waiting.Store(false) + + errc <- err + + if err != nil { + return + } + + for { + select { + case block := <-miner.MiningResultCh: + if block != nil { + s.logger.Debug("Mined block", "block", block.Number()) + s.minedBlocks <- block + } + return + case <-workCtx.Done(): + errc <- workCtx.Err() + return + } + } + }() } } }() diff --git a/eth/stagedsync/chain_reader.go b/eth/stagedsync/chain_reader.go index f1d0e52057e..5c2d75c4292 100644 --- a/eth/stagedsync/chain_reader.go +++ b/eth/stagedsync/chain_reader.go @@ -17,8 +17,7 @@ import ( // ChainReader implements consensus.ChainReader type ChainReader struct { - Cfg chain.Config - + Cfg chain.Config Db kv.Getter BlockReader services.FullBlockReader Logger log.Logger @@ -72,7 +71,7 @@ func (cr ChainReader) HasBlock(hash libcommon.Hash, number uint64) bool { func (cr ChainReader) GetTd(hash libcommon.Hash, number uint64) *big.Int { td, err := rawdb.ReadTd(cr.Db, hash, number) if err != nil { - log.Error("ReadTd failed", "err", err) + cr.Logger.Error("ReadTd failed", "err", err) return nil } return td diff --git a/eth/stagedsync/stage_bor_heimdall.go b/eth/stagedsync/stage_bor_heimdall.go index a6953b3702c..65cff408691 100644 --- a/eth/stagedsync/stage_bor_heimdall.go +++ b/eth/stagedsync/stage_bor_heimdall.go @@ -157,10 +157,13 @@ func BorHeimdallForward( } lastBlockNum := s.BlockNumber + if cfg.blockReader.FrozenBorBlocks() > lastBlockNum { lastBlockNum = cfg.blockReader.FrozenBorBlocks() } + recents, err := lru.NewARC[libcommon.Hash, *bor.Snapshot](inmemorySnapshots) + if err != nil { return err } @@ -168,6 +171,7 @@ func BorHeimdallForward( if err != nil { return err } + chain := NewChainReaderImpl(&cfg.chainConfig, tx, cfg.blockReader, logger) var blockNum uint64 diff --git a/eth/stagedsync/stage_headers.go b/eth/stagedsync/stage_headers.go index 839d7842468..6ac18f587ab 100644 --- a/eth/stagedsync/stage_headers.go +++ b/eth/stagedsync/stage_headers.go @@ -605,7 +605,7 @@ func (cr ChainReaderImpl) BorEventsByBlock(hash libcommon.Hash, number uint64) [ func (cr ChainReaderImpl) BorSpan(spanId uint64) []byte { span, err := cr.blockReader.Span(context.Background(), cr.tx, spanId) if err != nil { - cr.logger.Error("BorSpan failed", "err", err) + cr.logger.Error("[staged sync] BorSpan failed", "err", err) return nil } return span diff --git a/eth/stagedsync/stage_mining_bor_heimdall.go b/eth/stagedsync/stage_mining_bor_heimdall.go index 2dd96a98b85..4a5d21665d4 100644 --- a/eth/stagedsync/stage_mining_bor_heimdall.go +++ b/eth/stagedsync/stage_mining_bor_heimdall.go @@ -77,7 +77,7 @@ func MiningBorHeimdallForward( } logger.Info( - "[%s] Finished processing", logPrefix, + fmt.Sprintf("[%s] Finished processing", logPrefix), "progress", headerNum, "lastSpanID", lastSpanID, "lastStateSyncEventID", lastStateSyncEventID, diff --git a/eth/stagedsync/stage_mining_exec.go b/eth/stagedsync/stage_mining_exec.go index abc94326dc0..7fae41332b3 100644 --- a/eth/stagedsync/stage_mining_exec.go +++ b/eth/stagedsync/stage_mining_exec.go @@ -41,8 +41,8 @@ type MiningExecCfg struct { tmpdir string interrupt *int32 payloadId uint64 - txPool2 TxPoolForMining - txPool2DB kv.RoDB + txPool TxPoolForMining + txPoolDB kv.RoDB } type TxPoolForMining interface { @@ -54,7 +54,7 @@ func StageMiningExecCfg( notifier ChainEventNotifier, chainConfig chain.Config, engine consensus.Engine, vmConfig *vm.Config, tmpdir string, interrupt *int32, payloadId uint64, - txPool2 TxPoolForMining, txPool2DB kv.RoDB, + txPool TxPoolForMining, txPoolDB kv.RoDB, blockReader services.FullBlockReader, ) MiningExecCfg { return MiningExecCfg{ @@ -68,8 +68,8 @@ func StageMiningExecCfg( tmpdir: tmpdir, interrupt: interrupt, payloadId: payloadId, - txPool2: txPool2, - txPool2DB: txPool2DB, + txPool: txPool, + txPoolDB: txPoolDB, } } @@ -150,7 +150,7 @@ func SpawnMiningExecStage(s *StageState, tx kv.RwTx, cfg MiningExecCfg, quit <-c } } - logger.Debug("SpawnMiningExecStage", "block txn", current.Txs.Len(), "payload", cfg.payloadId) + logger.Debug("SpawnMiningExecStage", "block", current.Header.Number, "txn", current.Txs.Len(), "payload", cfg.payloadId) if current.Uncles == nil { current.Uncles = []*types.Header{} } @@ -166,7 +166,8 @@ func SpawnMiningExecStage(s *StageState, tx kv.RwTx, cfg MiningExecCfg, quit <-c if err != nil { return err } - logger.Debug("FinalizeBlockExecution", "current txn", current.Txs.Len(), "current receipt", current.Receipts.Len(), "payload", cfg.payloadId) + + logger.Debug("FinalizeBlockExecution", "block", current.Header.Number, "txn", current.Txs.Len(), "gas", current.Header.GasUsed, "receipt", current.Receipts.Len(), "payload", cfg.payloadId) // hack: pretend that we are real execution stage - next stages will rely on this progress if err := stages.SaveStageProgress(tx, stages.Execution, current.Header.Number.Uint64()); err != nil { @@ -186,23 +187,20 @@ func getNextTransactions( logger log.Logger, ) (types.TransactionsStream, int, error) { txSlots := types2.TxsRlp{} - var onTime bool count := 0 - if err := cfg.txPool2DB.View(context.Background(), func(poolTx kv.Tx) error { + if err := cfg.txPoolDB.View(context.Background(), func(poolTx kv.Tx) error { var err error - counter := 0 - for !onTime && counter < 500 { - remainingGas := header.GasLimit - header.GasUsed - remainingBlobGas := uint64(0) - if header.BlobGasUsed != nil { - remainingBlobGas = cfg.chainConfig.GetMaxBlobGasPerBlock() - *header.BlobGasUsed - } - if onTime, count, err = cfg.txPool2.YieldBest(amount, &txSlots, poolTx, executionAt, remainingGas, remainingBlobGas, alreadyYielded); err != nil { - return err - } - time.Sleep(1 * time.Millisecond) - counter++ + + remainingGas := header.GasLimit - header.GasUsed + remainingBlobGas := uint64(0) + if header.BlobGasUsed != nil { + remainingBlobGas = cfg.chainConfig.GetMaxBlobGasPerBlock() - *header.BlobGasUsed + } + + if _, count, err = cfg.txPool.YieldBest(amount, &txSlots, poolTx, executionAt, remainingGas, remainingBlobGas, alreadyYielded); err != nil { + return err } + return nil }); err != nil { return nil, 0, err @@ -375,7 +373,6 @@ func addTransactionsToMiningBlock(logPrefix string, current *MiningBlock, chainC gasSnap := gasPool.Gas() blobGasSnap := gasPool.BlobGas() snap := ibs.Snapshot() - logger.Debug("addTransactionsToMiningBlock", "txn hash", txn.Hash()) receipt, _, err := core.ApplyTransaction(&chainConfig, core.GetHashFn(header, getHeader), engine, &coinbase, gasPool, ibs, noop, header, txn, &header.GasUsed, header.BlobGasUsed, *vmConfig) if err != nil { ibs.RevertToSnapshot(snap) @@ -464,7 +461,7 @@ LOOP: txs.Pop() } else if err == nil { // Everything ok, collect the logs and shift in the next transaction from the same account - logger.Debug(fmt.Sprintf("[%s] addTransactionsToMiningBlock Successful", logPrefix), "sender", from, "nonce", txn.GetNonce(), "payload", payloadId) + logger.Trace(fmt.Sprintf("[%s] Added transaction", logPrefix), "hash", txn.Hash(), "sender", from, "nonce", txn.GetNonce(), "payload", payloadId) coalescedLogs = append(coalescedLogs, logs...) tcount++ txs.Shift() diff --git a/eth/stagedsync/stage_mining_finish.go b/eth/stagedsync/stage_mining_finish.go index 81cc486e57c..d3d36dfbab6 100644 --- a/eth/stagedsync/stage_mining_finish.go +++ b/eth/stagedsync/stage_mining_finish.go @@ -82,10 +82,10 @@ func SpawnMiningFinishStage(s *StageState, tx kv.RwTx, cfg MiningFinishCfg, quit if block.Transactions().Len() > 0 { logger.Info(fmt.Sprintf("[%s] block ready for seal", logPrefix), - "block_num", block.NumberU64(), + "block", block.NumberU64(), "transactions", block.Transactions().Len(), - "gas_used", block.GasUsed(), - "gas_limit", block.GasLimit(), + "gasUsed", block.GasUsed(), + "gasLimit", block.GasLimit(), "difficulty", block.Difficulty(), ) } diff --git a/polygon/bor/bor.go b/polygon/bor/bor.go index e3c31bdee75..2bdf64a04c6 100644 --- a/polygon/bor/bor.go +++ b/polygon/bor/bor.go @@ -1112,11 +1112,13 @@ func (c *Bor) Seal(chain consensus.ChainHeaderReader, block *types.Block, result select { case <-stop: c.logger.Info("[bor] Stopped sealing operation for block", "number", number) + results <- nil return case <-time.After(delay): if c.headerProgress != nil && c.headerProgress.Progress() >= number { c.logger.Info("Discarding sealing operation for block", "number", number) + results <- nil return } diff --git a/turbo/cli/flags.go b/turbo/cli/flags.go index 75261f14db3..88ab5ca946a 100644 --- a/turbo/cli/flags.go +++ b/turbo/cli/flags.go @@ -478,7 +478,7 @@ func setEmbeddedRpcDaemon(ctx *cli.Context, cfg *nodecfg.Config, logger log.Logg } if c.Enabled { - logger.Info("starting HTTP APIs", "APIs", apis) + logger.Info("starting HTTP APIs", "port", c.HttpPort, "APIs", apis) } if ctx.IsSet(utils.HttpCompressionFlag.Name) { diff --git a/turbo/snapshotsync/freezeblocks/block_reader.go b/turbo/snapshotsync/freezeblocks/block_reader.go index 84837053147..a24367e8387 100644 --- a/turbo/snapshotsync/freezeblocks/block_reader.go +++ b/turbo/snapshotsync/freezeblocks/block_reader.go @@ -1190,7 +1190,7 @@ func (r *BlockReader) Span(ctx context.Context, tx kv.Getter, spanId uint64) ([] return nil, err } if v == nil { - return nil, fmt.Errorf("span %d not found (db), frosenBlocks=%d", spanId, maxBlockNumInFiles) + return nil, fmt.Errorf("span %d not found (db), frozenBlocks=%d", spanId, maxBlockNumInFiles) } return common.Copy(v), nil } diff --git a/turbo/stages/stageloop.go b/turbo/stages/stageloop.go index 951dc4b7b83..95db1e1e84f 100644 --- a/turbo/stages/stageloop.go +++ b/turbo/stages/stageloop.go @@ -329,6 +329,7 @@ func (h *Hook) afterRun(tx kv.Tx, finishProgressBefore uint64) error { pendingBlobFee = f.Uint64() } + h.logger.Debug("[hook] Sending state changes", "currentBlock", currentHeader.Number.Uint64(), "finalizedBlock", finalizedBlock) notifications.Accumulator.SendAndReset(h.ctx, notifications.StateChangesConsumer, pendingBaseFee.Uint64(), pendingBlobFee, currentHeader.GasLimit, finalizedBlock) } // -- send notifications END From f690301c03d35023196c034670cc2813e7cc7b7f Mon Sep 17 00:00:00 2001 From: milen <94537774+taratorio@users.noreply.github.com> Date: Wed, 10 Jan 2024 19:04:27 +0000 Subject: [PATCH 37/92] devnet: integration tests port clash fix (#9194) Integration tests CI is failing due to a port clash in devnet tests. I believe this is because there are 2 packages of devnet integration tests and go can run tests from separate packages in parallel (by default it does package level parallelism). A simple fix would be to just have all devnet integration tests in 1 package and run all these tests sequentially within the package (ie not use t.Parallel). This PR moves all devnet integration tests in 1 package. `"ContextStart devnet start failed: private api: could not create listener: listen top 127.0.0.1:10090: bind: address already in use, addr=localhost:10090"` ![Screenshot 2024-01-10 at 13 38 37](https://github.com/ledgerwatch/erigon/assets/94537774/06bda987-45e5-46ef-9e0b-3876b3f85c01) --- .../tests/{bor/devnet_test.go => bor_devnet_test.go} | 7 +++---- cmd/devnet/tests/context.go | 6 ++++-- .../{generic/devnet_test.go => generic_devnet_test.go} | 9 ++++----- 3 files changed, 11 insertions(+), 11 deletions(-) rename cmd/devnet/tests/{bor/devnet_test.go => bor_devnet_test.go} (93%) rename cmd/devnet/tests/{generic/devnet_test.go => generic_devnet_test.go} (90%) diff --git a/cmd/devnet/tests/bor/devnet_test.go b/cmd/devnet/tests/bor_devnet_test.go similarity index 93% rename from cmd/devnet/tests/bor/devnet_test.go rename to cmd/devnet/tests/bor_devnet_test.go index fa9d9ecee39..30cb8839d38 100644 --- a/cmd/devnet/tests/bor/devnet_test.go +++ b/cmd/devnet/tests/bor_devnet_test.go @@ -1,6 +1,6 @@ //go:build integration -package bor +package tests import ( "context" @@ -13,11 +13,10 @@ import ( contracts_steps "github.com/ledgerwatch/erigon/cmd/devnet/contracts/steps" "github.com/ledgerwatch/erigon/cmd/devnet/requests" "github.com/ledgerwatch/erigon/cmd/devnet/services" - "github.com/ledgerwatch/erigon/cmd/devnet/tests" ) func TestStateSync(t *testing.T) { - runCtx, err := tests.ContextStart(t, networkname.BorDevnetChainName) + runCtx, err := ContextStart(t, networkname.BorDevnetChainName) require.Nil(t, err) var ctx context.Context = runCtx @@ -56,7 +55,7 @@ func TestStateSync(t *testing.T) { func TestChildChainExit(t *testing.T) { t.Skip("FIXME: step CreateAccountWithFunds fails: Failed to get transfer tx: failed to search reserves for hashes: no block heads subscription") - runCtx, err := tests.ContextStart(t, networkname.BorDevnetChainName) + runCtx, err := ContextStart(t, networkname.BorDevnetChainName) require.Nil(t, err) var ctx context.Context = runCtx diff --git a/cmd/devnet/tests/context.go b/cmd/devnet/tests/context.go index 7eb115b0edf..af92c3a0df8 100644 --- a/cmd/devnet/tests/context.go +++ b/cmd/devnet/tests/context.go @@ -7,18 +7,19 @@ import ( "strconv" "testing" + "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/chain/networkname" "github.com/ledgerwatch/erigon/cmd/devnet/devnet" "github.com/ledgerwatch/erigon/cmd/devnet/networks" "github.com/ledgerwatch/erigon/cmd/devnet/services" "github.com/ledgerwatch/erigon/cmd/devnet/services/polygon" "github.com/ledgerwatch/erigon/turbo/debug" - "github.com/ledgerwatch/log/v3" ) func initDevnet(chainName string, dataDir string, producerCount int, gasLimit uint64, logger log.Logger, consoleLogLevel log.Lvl, dirLogLevel log.Lvl) (devnet.Devnet, error) { const baseRpcHost = "localhost" - const baseRpcPort = 8545 + const baseRpcPort = 9545 switch chainName { case networkname.BorDevnetChainName: @@ -42,6 +43,7 @@ func initDevnet(chainName string, dataDir string, producerCount int, gasLimit ui } func ContextStart(t *testing.T, chainName string) (devnet.Context, error) { + //goland:noinspection GoBoolExpressions if runtime.GOOS == "windows" { t.Skip("FIXME: TempDir RemoveAll cleanup error: remove dev-0\\clique\\db\\clique\\mdbx.dat: The process cannot access the file because it is being used by another process") } diff --git a/cmd/devnet/tests/generic/devnet_test.go b/cmd/devnet/tests/generic_devnet_test.go similarity index 90% rename from cmd/devnet/tests/generic/devnet_test.go rename to cmd/devnet/tests/generic_devnet_test.go index 9df1b49e871..8deddfb1fe8 100644 --- a/cmd/devnet/tests/generic/devnet_test.go +++ b/cmd/devnet/tests/generic_devnet_test.go @@ -1,6 +1,6 @@ //go:build integration -package generic +package tests import ( "context" @@ -14,7 +14,6 @@ import ( "github.com/ledgerwatch/erigon/cmd/devnet/contracts/steps" "github.com/ledgerwatch/erigon/cmd/devnet/requests" "github.com/ledgerwatch/erigon/cmd/devnet/services" - "github.com/ledgerwatch/erigon/cmd/devnet/tests" "github.com/ledgerwatch/erigon/cmd/devnet/transactions" ) @@ -40,19 +39,19 @@ func testDynamicTx(t *testing.T, ctx context.Context) { } func TestDynamicTxNode0(t *testing.T) { - runCtx, err := tests.ContextStart(t, "") + runCtx, err := ContextStart(t, "") require.Nil(t, err) testDynamicTx(t, runCtx.WithCurrentNetwork(0).WithCurrentNode(0)) } func TestDynamicTxAnyNode(t *testing.T) { - runCtx, err := tests.ContextStart(t, "") + runCtx, err := ContextStart(t, "") require.Nil(t, err) testDynamicTx(t, runCtx.WithCurrentNetwork(0)) } func TestCallContract(t *testing.T) { - runCtx, err := tests.ContextStart(t, "") + runCtx, err := ContextStart(t, "") require.Nil(t, err) ctx := runCtx.WithCurrentNetwork(0) From 641f53e9d2adc893eaf14eb71c3d0eafc24f58d4 Mon Sep 17 00:00:00 2001 From: Mark Holt <135143369+mh0lt@users.noreply.github.com> Date: Thu, 11 Jan 2024 01:03:12 +0000 Subject: [PATCH 38/92] Remove duplicate flags (#9199) This fixes the snapshot uploader start as flags have been moved to default --- turbo/app/snapshots_cmd.go | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/turbo/app/snapshots_cmd.go b/turbo/app/snapshots_cmd.go index ad17210b399..11ea10b1d53 100644 --- a/turbo/app/snapshots_cmd.go +++ b/turbo/app/snapshots_cmd.go @@ -94,12 +94,13 @@ var snapshotCommand = cli.Command{ Name: "uploader", Action: doUploaderCommand, Usage: "run erigon in snapshot upload mode (no execution)", - Flags: uploaderCommandFlags([]cli.Flag{ - &SnapshotVersionFlag, - &erigoncli.UploadLocationFlag, - &erigoncli.UploadFromFlag, - &erigoncli.FrozenBlockLimitFlag, - }), + Flags: joinFlags(erigoncli.DefaultFlags, + []cli.Flag{ + &SnapshotVersionFlag, + &erigoncli.UploadLocationFlag, + &erigoncli.UploadFromFlag, + &erigoncli.FrozenBlockLimitFlag, + }), Before: func(context *cli.Context) error { erigoncli.SyncLoopBreakAfterFlag.Value = "Senders" erigoncli.SyncLoopBlockLimitFlag.Value = 100000 @@ -645,14 +646,6 @@ func doRetireCommand(cliCtx *cli.Context) error { return nil } -func uploaderCommandFlags(flags []cli.Flag) []cli.Flag { - return joinFlags(erigoncli.DefaultFlags, flags, []cli.Flag{ - &erigoncli.SyncLoopBreakAfterFlag, - &erigoncli.SyncLoopBlockLimitFlag, - &erigoncli.SyncLoopPruneLimitFlag, - }) -} - func doUploaderCommand(cliCtx *cli.Context) error { var logger log.Logger var err error From 1ee439e6ac0caf51ebe90fee8b043a4163d88bae Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Thu, 11 Jan 2024 08:06:35 +0700 Subject: [PATCH 39/92] mdbx: dplimit - support cgroups/gomelimit, avoid using SetOptions after env.Open() (#9189) --- cl/beacon/handler/attestation_rewards_test.go | 2 + cl/beacon/handler/commitees_test.go | 2 + cl/beacon/handler/config_test.go | 2 + cl/beacon/handler/duties_attester_test.go | 2 + cl/beacon/handler/duties_proposer_test.go | 2 + cl/beacon/handler/duties_sync_test.go | 2 + cl/beacon/handler/headers_test.go | 2 + cl/beacon/handler/pool_test.go | 2 + cl/beacon/handler/validators_test.go | 2 + erigon-lib/kv/mdbx/kv_mdbx.go | 69 +++++++++---------- 10 files changed, 50 insertions(+), 37 deletions(-) diff --git a/cl/beacon/handler/attestation_rewards_test.go b/cl/beacon/handler/attestation_rewards_test.go index f5823765c14..b078e844138 100644 --- a/cl/beacon/handler/attestation_rewards_test.go +++ b/cl/beacon/handler/attestation_rewards_test.go @@ -1,3 +1,5 @@ +//go:build integration + package handler import ( diff --git a/cl/beacon/handler/commitees_test.go b/cl/beacon/handler/commitees_test.go index f3cff88891f..d0cf455b3ad 100644 --- a/cl/beacon/handler/commitees_test.go +++ b/cl/beacon/handler/commitees_test.go @@ -1,3 +1,5 @@ +//go:build integration + package handler import ( diff --git a/cl/beacon/handler/config_test.go b/cl/beacon/handler/config_test.go index d97349a94e0..995a38d5abc 100644 --- a/cl/beacon/handler/config_test.go +++ b/cl/beacon/handler/config_test.go @@ -1,3 +1,5 @@ +//go:build integration + package handler import ( diff --git a/cl/beacon/handler/duties_attester_test.go b/cl/beacon/handler/duties_attester_test.go index 6014096cc2a..0035d99e505 100644 --- a/cl/beacon/handler/duties_attester_test.go +++ b/cl/beacon/handler/duties_attester_test.go @@ -1,3 +1,5 @@ +//go:build integration + package handler import ( diff --git a/cl/beacon/handler/duties_proposer_test.go b/cl/beacon/handler/duties_proposer_test.go index bba6c93773e..1994098b27b 100644 --- a/cl/beacon/handler/duties_proposer_test.go +++ b/cl/beacon/handler/duties_proposer_test.go @@ -1,3 +1,5 @@ +//go:build integration + package handler import ( diff --git a/cl/beacon/handler/duties_sync_test.go b/cl/beacon/handler/duties_sync_test.go index eca554c668d..9eabf90e301 100644 --- a/cl/beacon/handler/duties_sync_test.go +++ b/cl/beacon/handler/duties_sync_test.go @@ -1,3 +1,5 @@ +//go:build integration + package handler import ( diff --git a/cl/beacon/handler/headers_test.go b/cl/beacon/handler/headers_test.go index b04df1e6f7f..25efb1a2ca5 100644 --- a/cl/beacon/handler/headers_test.go +++ b/cl/beacon/handler/headers_test.go @@ -1,3 +1,5 @@ +//go:build integration + package handler import ( diff --git a/cl/beacon/handler/pool_test.go b/cl/beacon/handler/pool_test.go index a4349aa1750..c715162af00 100644 --- a/cl/beacon/handler/pool_test.go +++ b/cl/beacon/handler/pool_test.go @@ -1,3 +1,5 @@ +//go:build integration + package handler import ( diff --git a/cl/beacon/handler/validators_test.go b/cl/beacon/handler/validators_test.go index 116b9155867..7f09084685b 100644 --- a/cl/beacon/handler/validators_test.go +++ b/cl/beacon/handler/validators_test.go @@ -1,3 +1,5 @@ +//go:build integration + package handler import ( diff --git a/erigon-lib/kv/mdbx/kv_mdbx.go b/erigon-lib/kv/mdbx/kv_mdbx.go index 60da7e14ca3..85aeb734124 100644 --- a/erigon-lib/kv/mdbx/kv_mdbx.go +++ b/erigon-lib/kv/mdbx/kv_mdbx.go @@ -34,8 +34,8 @@ import ( "github.com/c2h5oh/datasize" "github.com/erigontech/mdbx-go/mdbx" stack2 "github.com/go-stack/stack" + "github.com/ledgerwatch/erigon-lib/mmap" "github.com/ledgerwatch/log/v3" - "github.com/pbnjay/memory" "golang.org/x/exp/maps" "golang.org/x/sync/semaphore" @@ -84,10 +84,6 @@ func NewMDBX(log log.Logger) MdbxOpts { log: log, pageSize: kv.DefaultPageSize(), - // default is (TOTAL_RAM+AVAILABLE_RAM)/42/pageSize - // but for reproducibility of benchmarks - please don't rely on Available RAM - dirtySpace: 2 * (memory.TotalMemory() / 42), - mapSize: DefaultMapSize, growthStep: DefaultGrowthStep, mergeThreshold: 3 * 8192, @@ -280,7 +276,7 @@ func (opts MdbxOpts) Open(ctx context.Context) (kv.RwDB, error) { return nil, err } - if opts.flags&mdbx.Accede == 0 { + if !opts.HasFlag(mdbx.Accede) { if err = env.SetGeometry(-1, -1, int(opts.mapSize), int(opts.growthStep), opts.shrinkThreshold, int(opts.pageSize)); err != nil { return nil, err } @@ -289,29 +285,6 @@ func (opts MdbxOpts) Open(ctx context.Context) (kv.RwDB, error) { } } - err = env.Open(opts.path, opts.flags, 0664) - if err != nil { - if err != nil { - return nil, fmt.Errorf("%w, label: %s, trace: %s", err, opts.label.String(), stack2.Trace().String()) - } - } - - // mdbx will not change pageSize if db already exists. means need read real value after env.open() - in, err := env.Info(nil) - if err != nil { - if err != nil { - return nil, fmt.Errorf("%w, label: %s, trace: %s", err, opts.label.String(), stack2.Trace().String()) - } - } - - opts.pageSize = uint64(in.PageSize) - opts.mapSize = datasize.ByteSize(in.MapSize) - if opts.label == kv.ChainDB { - opts.log.Info("[db] open", "lable", opts.label, "sizeLimit", opts.mapSize, "pageSize", opts.pageSize) - } else { - opts.log.Debug("[db] open", "lable", opts.label, "sizeLimit", opts.mapSize, "pageSize", opts.pageSize) - } - // erigon using big transactions // increase "page measured" options. need do it after env.Open() because default are depend on pageSize known only after env.Open() if !opts.HasFlag(mdbx.Readonly) { @@ -339,17 +312,19 @@ func (opts MdbxOpts) Open(ctx context.Context) (kv.RwDB, error) { } } + // before env.Open() we don't know real pageSize. but will be implemented soon: https://gitflic.ru/project/erthink/libmdbx/issue/15 + // but we want call all `SetOption` before env.Open(), because: + // - after they will require rwtx-lock, which is not acceptable in ACCEDEE mode. + pageSize := opts.pageSize + if pageSize == 0 { + pageSize = kv.DefaultPageSize() + } + var dirtySpace uint64 if opts.dirtySpace > 0 { dirtySpace = opts.dirtySpace } else { - // the default value is based on the RAM amount - dirtyPagesLimit, err := env.GetOption(mdbx.OptTxnDpLimit) - if err != nil { - return nil, err - } - dirtySpace = dirtyPagesLimit * opts.pageSize - + dirtySpace = mmap.TotalMemory() / 42 // it's default of mdbx, but our package also supports cgroups and GOMEMLIMIT // clamp to max size const dirtySpaceMaxChainDB = uint64(2 * datasize.GB) const dirtySpaceMaxDefault = uint64(256 * datasize.MB) @@ -360,7 +335,8 @@ func (opts MdbxOpts) Open(ctx context.Context) (kv.RwDB, error) { dirtySpace = dirtySpaceMaxDefault } } - if err = env.SetOption(mdbx.OptTxnDpLimit, dirtySpace/opts.pageSize); err != nil { + //can't use real pagesize here - it will be known only after env.Open() + if err = env.SetOption(mdbx.OptTxnDpLimit, dirtySpace/pageSize); err != nil { return nil, err } @@ -371,6 +347,25 @@ func (opts MdbxOpts) Open(ctx context.Context) (kv.RwDB, error) { } } + err = env.Open(opts.path, opts.flags, 0664) + if err != nil { + return nil, fmt.Errorf("%w, label: %s, trace: %s", err, opts.label.String(), stack2.Trace().String()) + } + + // mdbx will not change pageSize if db already exists. means need read real value after env.open() + in, err := env.Info(nil) + if err != nil { + return nil, fmt.Errorf("%w, label: %s, trace: %s", err, opts.label.String(), stack2.Trace().String()) + } + + opts.pageSize = uint64(in.PageSize) + opts.mapSize = datasize.ByteSize(in.MapSize) + if opts.label == kv.ChainDB { + opts.log.Info("[db] open", "lable", opts.label, "sizeLimit", opts.mapSize, "pageSize", opts.pageSize) + } else { + opts.log.Debug("[db] open", "lable", opts.label, "sizeLimit", opts.mapSize, "pageSize", opts.pageSize) + } + dirtyPagesLimit, err := env.GetOption(mdbx.OptTxnDpLimit) if err != nil { return nil, err From b1c3006d7abcc43cbaaad2dd0dbcaf84c6a9fc75 Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Thu, 11 Jan 2024 02:45:48 +0100 Subject: [PATCH 40/92] bor: remove duplicate validator_set file and debug logger (#9198) --- cmd/devnet/services/polygon/heimdall.go | 4 +- eth/stagedsync/stagedsynctest/harness.go | 6 +- polygon/bor/bor.go | 2 +- polygon/bor/bor_test.go | 4 +- polygon/bor/snapshot.go | 4 +- polygon/bor/snapshot_test.go | 16 +- polygon/bor/valset/validator_set.go | 40 +- polygon/sync/difficulty.go | 10 +- polygon/sync/difficulty_test.go | 2 +- turbo/jsonrpc/bor_helper.go | 2 + turbo/jsonrpc/bor_snapshot.go | 2 +- turbo/jsonrpc/validator_set.go | 704 ----------------------- 12 files changed, 43 insertions(+), 753 deletions(-) delete mode 100644 turbo/jsonrpc/validator_set.go diff --git a/cmd/devnet/services/polygon/heimdall.go b/cmd/devnet/services/polygon/heimdall.go index 8e00cecd414..81426a68e52 100644 --- a/cmd/devnet/services/polygon/heimdall.go +++ b/cmd/devnet/services/polygon/heimdall.go @@ -357,7 +357,7 @@ func (h *Heimdall) addValidator(validatorAddress libcommon.Address, votingPower VotingPower: votingPower, ProposerPriority: proposerPriority, }, - }, h.logger) + }) } else { h.validatorSet.UpdateWithChangeSet([]*valset.Validator{ { @@ -366,7 +366,7 @@ func (h *Heimdall) addValidator(validatorAddress libcommon.Address, votingPower VotingPower: votingPower, ProposerPriority: proposerPriority, }, - }, h.logger) + }) } } diff --git a/eth/stagedsync/stagedsynctest/harness.go b/eth/stagedsync/stagedsynctest/harness.go index 76fddead0be..a2b6169999c 100644 --- a/eth/stagedsync/stagedsynctest/harness.go +++ b/eth/stagedsync/stagedsynctest/harness.go @@ -109,7 +109,7 @@ func InitHarness(ctx context.Context, t *testing.T, cfg HarnessCfg) Harness { } if cfg.ChainConfig.Bor != nil { - h.setHeimdallNextMockSpan(logger) + h.setHeimdallNextMockSpan() h.mockBorSpanner() h.mockHeimdallClient() } @@ -501,7 +501,7 @@ func (h *Harness) mockChainHeaderReader(ctrl *gomock.Controller) consensus.Chain return mockChainHR } -func (h *Harness) setHeimdallNextMockSpan(logger log.Logger) { +func (h *Harness) setHeimdallNextMockSpan() { validators := []*valset.Validator{ { ID: 1, @@ -511,7 +511,7 @@ func (h *Harness) setHeimdallNextMockSpan(logger log.Logger) { }, } - validatorSet := valset.NewValidatorSet(validators, logger) + validatorSet := valset.NewValidatorSet(validators) selectedProducers := make([]valset.Validator, len(validators)) for i := range validators { selectedProducers[i] = *validators[i] diff --git a/polygon/bor/bor.go b/polygon/bor/bor.go index 2bdf64a04c6..9d96308d3c8 100644 --- a/polygon/bor/bor.go +++ b/polygon/bor/bor.go @@ -1496,7 +1496,7 @@ func getUpdatedValidatorSet(oldValidatorSet *valset.ValidatorSet, newVals []*val } } - if err := v.UpdateWithChangeSet(changes, logger); err != nil { + if err := v.UpdateWithChangeSet(changes); err != nil { logger.Error("[bor] Error while updating change set", "error", err) } diff --git a/polygon/bor/bor_test.go b/polygon/bor/bor_test.go index c1341fb0286..0c9f3c6d3f5 100644 --- a/polygon/bor/bor_test.go +++ b/polygon/bor/bor_test.go @@ -306,7 +306,7 @@ func newValidator(t *testing.T, heimdall *test_heimdall, blocks map[uint64]*type VotingPower: 1000, ProposerPriority: 1, }, - }, logger) + }) } else { heimdall.validatorSet.UpdateWithChangeSet([]*valset.Validator{ { @@ -315,7 +315,7 @@ func newValidator(t *testing.T, heimdall *test_heimdall, blocks map[uint64]*type VotingPower: 1000, ProposerPriority: 1, }, - }, logger) + }) } bor.Authorize(validatorAddress, func(_ libcommon.Address, mimeType string, message []byte) ([]byte, error) { diff --git a/polygon/bor/snapshot.go b/polygon/bor/snapshot.go index 7d055164807..cf4bbef43d1 100644 --- a/polygon/bor/snapshot.go +++ b/polygon/bor/snapshot.go @@ -51,7 +51,7 @@ func NewSnapshot( sigcache: sigcache, Number: number, Hash: hash, - ValidatorSet: valset.NewValidatorSet(validators, logger), + ValidatorSet: valset.NewValidatorSet(validators), Recents: make(map[uint64]common.Address), } return snap @@ -187,7 +187,7 @@ func (s *Snapshot) Apply(parent *types.Header, headers []*types.Header, logger l // get validators from headers and use that for new validator set newVals, _ := valset.ParseValidators(validatorBytes) v := getUpdatedValidatorSet(snap.ValidatorSet.Copy(), newVals, logger) - v.IncrementProposerPriority(1, logger) + v.IncrementProposerPriority(1) snap.ValidatorSet = v } diff --git a/polygon/bor/snapshot_test.go b/polygon/bor/snapshot_test.go index c5bdb215452..4a6d940328f 100644 --- a/polygon/bor/snapshot_test.go +++ b/polygon/bor/snapshot_test.go @@ -5,12 +5,12 @@ import ( "sort" "testing" + "github.com/maticnetwork/crand" + "github.com/stretchr/testify/require" + libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/polygon/bor" "github.com/ledgerwatch/erigon/polygon/bor/valset" - "github.com/ledgerwatch/log/v3" - "github.com/maticnetwork/crand" - "github.com/stretchr/testify/require" ) const ( @@ -21,7 +21,7 @@ func TestGetSignerSuccessionNumber_ProposerIsSigner(t *testing.T) { t.Parallel() validators := buildRandomValidatorSet(numVals) - validatorSet := valset.NewValidatorSet(validators, log.New()) + validatorSet := valset.NewValidatorSet(validators) snap := bor.Snapshot{ ValidatorSet: validatorSet, } @@ -49,7 +49,7 @@ func TestGetSignerSuccessionNumber_SignerIndexIsLarger(t *testing.T) { // give highest ProposerPriority to a particular val, so that they become the proposer validators[proposerIndex].VotingPower = 200 snap := bor.Snapshot{ - ValidatorSet: valset.NewValidatorSet(validators, log.New()), + ValidatorSet: valset.NewValidatorSet(validators), } // choose a signer at an index greater than proposer index @@ -71,7 +71,7 @@ func TestGetSignerSuccessionNumber_SignerIndexIsSmaller(t *testing.T) { // give highest ProposerPriority to a particular val, so that they become the proposer validators[proposerIndex].VotingPower = 200 snap := bor.Snapshot{ - ValidatorSet: valset.NewValidatorSet(validators, log.New()), + ValidatorSet: valset.NewValidatorSet(validators), } // choose a signer at an index greater than proposer index @@ -89,7 +89,7 @@ func TestGetSignerSuccessionNumber_ProposerNotFound(t *testing.T) { validators := buildRandomValidatorSet(numVals) snap := bor.Snapshot{ - ValidatorSet: valset.NewValidatorSet(validators, log.New()), + ValidatorSet: valset.NewValidatorSet(validators), } dummyProposerAddress := randomAddress() @@ -111,7 +111,7 @@ func TestGetSignerSuccessionNumber_SignerNotFound(t *testing.T) { validators := buildRandomValidatorSet(numVals) snap := bor.Snapshot{ - ValidatorSet: valset.NewValidatorSet(validators, log.New()), + ValidatorSet: valset.NewValidatorSet(validators), } dummySignerAddress := randomAddress() diff --git a/polygon/bor/valset/validator_set.go b/polygon/bor/valset/validator_set.go index 4f540dc8e1e..864bb132bed 100644 --- a/polygon/bor/valset/validator_set.go +++ b/polygon/bor/valset/validator_set.go @@ -11,8 +11,6 @@ import ( "sort" "strings" - "github.com/ledgerwatch/log/v3" - libcommon "github.com/ledgerwatch/erigon-lib/common" ) @@ -56,16 +54,16 @@ type ValidatorSet struct { // the new ValidatorSet will have an empty list of Validators. // The addresses of validators in `valz` must be unique otherwise the // function panics. -func NewValidatorSet(valz []*Validator, logger log.Logger) *ValidatorSet { +func NewValidatorSet(valz []*Validator) *ValidatorSet { vals := &ValidatorSet{} - err := vals.updateWithChangeSet(valz, false, logger) + err := vals.updateWithChangeSet(valz, false) if err != nil { panic(fmt.Sprintf("cannot create validator set: %s", err)) } if len(valz) > 0 { - vals.IncrementProposerPriority(1, logger) + vals.IncrementProposerPriority(1) } return vals @@ -77,9 +75,9 @@ func (vals *ValidatorSet) IsNilOrEmpty() bool { } // Increment ProposerPriority and update the proposer on a copy, and return it. -func (vals *ValidatorSet) CopyIncrementProposerPriority(times int, logger log.Logger) *ValidatorSet { +func (vals *ValidatorSet) CopyIncrementProposerPriority(times int) *ValidatorSet { validatorCopy := vals.Copy() - validatorCopy.IncrementProposerPriority(times, logger) + validatorCopy.IncrementProposerPriority(times) return validatorCopy } @@ -87,7 +85,7 @@ func (vals *ValidatorSet) CopyIncrementProposerPriority(times int, logger log.Lo // IncrementProposerPriority increments ProposerPriority of each validator and updates the // proposer. Panics if validator set is empty. // `times` must be positive. -func (vals *ValidatorSet) IncrementProposerPriority(times int, logger log.Logger) { +func (vals *ValidatorSet) IncrementProposerPriority(times int) { if vals.IsNilOrEmpty() { panic("empty validator set") } @@ -99,14 +97,14 @@ func (vals *ValidatorSet) IncrementProposerPriority(times int, logger log.Logger // Cap the difference between priorities to be proportional to 2*totalPower by // re-normalizing priorities, i.e., rescale all priorities by multiplying with: // 2*totalVotingPower/(maxPriority - minPriority) - diffMax := PriorityWindowSizeFactor * vals.TotalVotingPower(logger) + diffMax := PriorityWindowSizeFactor * vals.TotalVotingPower() vals.RescalePriorities(diffMax) vals.shiftByAvgProposerPriority() var proposer *Validator // Call IncrementProposerPriority(1) times times. for i := 0; i < times; i++ { - proposer = vals.incrementProposerPriority(logger) + proposer = vals.incrementProposerPriority() } vals.Proposer = proposer @@ -136,7 +134,7 @@ func (vals *ValidatorSet) RescalePriorities(diffMax int64) { } } -func (vals *ValidatorSet) incrementProposerPriority(logger log.Logger) *Validator { +func (vals *ValidatorSet) incrementProposerPriority() *Validator { for _, val := range vals.Validators { // Check for overflow for sum. newPrio := safeAddClip(val.ProposerPriority, val.VotingPower) @@ -145,7 +143,7 @@ func (vals *ValidatorSet) incrementProposerPriority(logger log.Logger) *Validato // Decrement the validator with most ProposerPriority. mostest := vals.getValWithMostPriority() // Mind the underflow. - mostest.ProposerPriority = safeSubClip(mostest.ProposerPriority, vals.TotalVotingPower(logger)) + mostest.ProposerPriority = safeSubClip(mostest.ProposerPriority, vals.TotalVotingPower()) return mostest } @@ -305,10 +303,8 @@ func (vals *ValidatorSet) UpdateTotalVotingPower() error { // TotalVotingPower returns the sum of the voting powers of all validators. // It recomputes the total voting power if required. -func (vals *ValidatorSet) TotalVotingPower(logger log.Logger) int64 { +func (vals *ValidatorSet) TotalVotingPower() int64 { if vals.totalVotingPower == 0 { - logger.Info("invoking updateTotalVotingPower before returning it") - if err := vals.UpdateTotalVotingPower(); err != nil { // Can/should we do better? panic(err) @@ -429,8 +425,8 @@ func processChanges(origChanges []*Validator) (updates, removals []*Validator, e // 'updates' should be a list of proper validator changes, i.e. they have been verified // by processChanges for duplicates and invalid values. // No changes are made to the validator set 'vals'. -func verifyUpdates(updates []*Validator, vals *ValidatorSet, logger log.Logger) (updatedTotalVotingPower int64, numNewValidators int, err error) { - updatedTotalVotingPower = vals.TotalVotingPower(logger) +func verifyUpdates(updates []*Validator, vals *ValidatorSet) (updatedTotalVotingPower int64, numNewValidators int, err error) { + updatedTotalVotingPower = vals.TotalVotingPower() for _, valUpdate := range updates { address := valUpdate.Address @@ -578,7 +574,7 @@ func (vals *ValidatorSet) applyRemovals(deletes []*Validator) { // If 'allowDeletes' is false then delete operations (identified by validators with voting power 0) // are not allowed and will trigger an error if present in 'changes'. // The 'allowDeletes' flag is set to false by NewValidatorSet() and to true by UpdateWithChangeSet(). -func (vals *ValidatorSet) updateWithChangeSet(changes []*Validator, allowDeletes bool, logger log.Logger) error { +func (vals *ValidatorSet) updateWithChangeSet(changes []*Validator, allowDeletes bool) error { if len(changes) < 1 { return nil } @@ -599,7 +595,7 @@ func (vals *ValidatorSet) updateWithChangeSet(changes []*Validator, allowDeletes } // Verify that applying the 'updates' against 'vals' will not result in error. - updatedTotalVotingPower, numNewValidators, err := verifyUpdates(updates, vals, logger) + updatedTotalVotingPower, numNewValidators, err := verifyUpdates(updates, vals) if err != nil { return err } @@ -620,7 +616,7 @@ func (vals *ValidatorSet) updateWithChangeSet(changes []*Validator, allowDeletes } // Scale and center. - vals.RescalePriorities(PriorityWindowSizeFactor * vals.TotalVotingPower(logger)) + vals.RescalePriorities(PriorityWindowSizeFactor * vals.TotalVotingPower()) vals.shiftByAvgProposerPriority() return nil @@ -654,8 +650,8 @@ func (vals *ValidatorSet) UpdateValidatorMap() { // // If an error is detected during verification steps, it is returned and the validator set // is not changed. -func (vals *ValidatorSet) UpdateWithChangeSet(changes []*Validator, logger log.Logger) error { - return vals.updateWithChangeSet(changes, true, logger) +func (vals *ValidatorSet) UpdateWithChangeSet(changes []*Validator) error { + return vals.updateWithChangeSet(changes, true) } // Difficulty returns the difficulty for a particular signer at the current snapshot number diff --git a/polygon/sync/difficulty.go b/polygon/sync/difficulty.go index 74ec83958ec..6717df0064e 100644 --- a/polygon/sync/difficulty.go +++ b/polygon/sync/difficulty.go @@ -25,13 +25,11 @@ type difficultyCalculatorImpl struct { span *heimdallspan.HeimdallSpan validatorSetFactory func() validatorSetInterface signaturesCache *lru.ARCCache[libcommon.Hash, libcommon.Address] - - log log.Logger } // valset.ValidatorSet abstraction for unit tests type validatorSetInterface interface { - IncrementProposerPriority(times int, logger log.Logger) + IncrementProposerPriority(times int) Difficulty(signer libcommon.Address) (uint64, error) } @@ -50,8 +48,6 @@ func NewDifficultyCalculator( span: span, validatorSetFactory: validatorSetFactory, signaturesCache: signaturesCache, - - log: log, } if validatorSetFactory == nil { @@ -62,7 +58,7 @@ func NewDifficultyCalculator( } func (impl *difficultyCalculatorImpl) makeValidatorSet() validatorSetInterface { - return valset.NewValidatorSet(impl.span.ValidatorSet.Validators, impl.log) + return valset.NewValidatorSet(impl.span.ValidatorSet.Validators) } func (impl *difficultyCalculatorImpl) SetSpan(span *heimdallspan.HeimdallSpan) { @@ -82,7 +78,7 @@ func (impl *difficultyCalculatorImpl) signerDifficulty(signer libcommon.Address, sprintNum := impl.borConfig.CalculateSprintNumber(headerNum) if sprintNum > 0 { - validatorSet.IncrementProposerPriority(int(sprintNum), impl.log) + validatorSet.IncrementProposerPriority(int(sprintNum)) } return validatorSet.Difficulty(signer) diff --git a/polygon/sync/difficulty_test.go b/polygon/sync/difficulty_test.go index 11d4639524d..9a0a184b5fb 100644 --- a/polygon/sync/difficulty_test.go +++ b/polygon/sync/difficulty_test.go @@ -20,7 +20,7 @@ type testValidatorSetInterface struct { sprintNum int } -func (v *testValidatorSetInterface) IncrementProposerPriority(times int, _ log.Logger) { +func (v *testValidatorSetInterface) IncrementProposerPriority(times int) { v.sprintNum = times } diff --git a/turbo/jsonrpc/bor_helper.go b/turbo/jsonrpc/bor_helper.go index dd9ef47d574..db0ad4ea60b 100644 --- a/turbo/jsonrpc/bor_helper.go +++ b/turbo/jsonrpc/bor_helper.go @@ -117,6 +117,8 @@ func validatorContains(a []*valset.Validator, x *valset.Validator) (*valset.Vali return nil, false } +type ValidatorSet = valset.ValidatorSet + // getUpdatedValidatorSet applies changes to a validator set and returns a new validator set func getUpdatedValidatorSet(oldValidatorSet *ValidatorSet, newVals []*valset.Validator) *ValidatorSet { v := oldValidatorSet diff --git a/turbo/jsonrpc/bor_snapshot.go b/turbo/jsonrpc/bor_snapshot.go index 0b41a8117a3..f92d6153a44 100644 --- a/turbo/jsonrpc/bor_snapshot.go +++ b/turbo/jsonrpc/bor_snapshot.go @@ -539,7 +539,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) { } // check if signer is in validator set - if !snap.ValidatorSet.HasAddress(signer.Bytes()) { + if !snap.ValidatorSet.HasAddress(signer) { return nil, &bor.UnauthorizedSignerError{Number: number, Signer: signer.Bytes()} } diff --git a/turbo/jsonrpc/validator_set.go b/turbo/jsonrpc/validator_set.go deleted file mode 100644 index 7f4ddf735b8..00000000000 --- a/turbo/jsonrpc/validator_set.go +++ /dev/null @@ -1,704 +0,0 @@ -package jsonrpc - -// Tendermint leader selection algorithm - -import ( - "bytes" - "fmt" - "math" - "math/big" - "sort" - "strings" - - libcommon "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/log/v3" - - "github.com/ledgerwatch/erigon/polygon/bor/valset" -) - -// MaxTotalVotingPower - the maximum allowed total voting power. -// It needs to be sufficiently small to, in all cases: -// 1. prevent clipping in incrementProposerPriority() -// 2. let (diff+diffMax-1) not overflow in IncrementProposerPriority() -// (Proof of 1 is tricky, left to the reader). -// It could be higher, but this is sufficiently large for our purposes, -// and leaves room for defensive purposes. -// PriorityWindowSizeFactor - is a constant that when multiplied with the total voting power gives -// the maximum allowed distance between validator priorities. - -const ( - MaxTotalVotingPower = int64(math.MaxInt64) / 8 - PriorityWindowSizeFactor = 2 -) - -// ValidatorSet represent a set of *Validator at a given height. -// The validators can be fetched by address or index. -// The index is in order of .Address, so the indices are fixed -// for all rounds of a given blockchain height - ie. the validators -// are sorted by their address. -// On the other hand, the .ProposerPriority of each validator and -// the designated .GetProposer() of a set changes every round, -// upon calling .IncrementProposerPriority(). -// NOTE: Not goroutine-safe. -// NOTE: All get/set to validators should copy the value for safety. -type ValidatorSet struct { - // NOTE: persisted via reflect, must be exported. - Validators []*valset.Validator `json:"validators"` - Proposer *valset.Validator `json:"proposer"` - - // cached (unexported) - totalVotingPower int64 -} - -// NewValidatorSet initializes a ValidatorSet by copying over the -// values from `valz`, a list of Validators. If valz is nil or empty, -// the new ValidatorSet will have an empty list of Validators. -// The addresses of validators in `valz` must be unique otherwise the -// function panics. -func NewValidatorSet(valz []*valset.Validator) *ValidatorSet { - vals := &ValidatorSet{} - err := vals.updateWithChangeSet(valz, false) - if err != nil { - panic(fmt.Sprintf("cannot create validator set: %s", err)) - } - if len(valz) > 0 { - vals.IncrementProposerPriority(1) - } - return vals -} - -// Nil or empty validator sets are invalid. -func (vals *ValidatorSet) IsNilOrEmpty() bool { - return vals == nil || len(vals.Validators) == 0 -} - -// Increment ProposerPriority and update the proposer on a copy, and return it. -func (vals *ValidatorSet) CopyIncrementProposerPriority(times int) *ValidatorSet { - copy := vals.Copy() - copy.IncrementProposerPriority(times) - return copy -} - -// IncrementProposerPriority increments ProposerPriority of each validator and updates the -// proposer. Panics if validator set is empty. -// `times` must be positive. -func (vals *ValidatorSet) IncrementProposerPriority(times int) { - if vals.IsNilOrEmpty() { - panic("empty validator set") - } - if times <= 0 { - panic("Cannot call IncrementProposerPriority with non-positive times") - } - - // Cap the difference between priorities to be proportional to 2*totalPower by - // re-normalizing priorities, i.e., rescale all priorities by multiplying with: - // 2*totalVotingPower/(maxPriority - minPriority) - diffMax := PriorityWindowSizeFactor * vals.TotalVotingPower() - vals.RescalePriorities(diffMax) - vals.shiftByAvgProposerPriority() - - var proposer *valset.Validator - // Call IncrementProposerPriority(1) times times. - for i := 0; i < times; i++ { - proposer = vals.incrementProposerPriority() - } - - vals.Proposer = proposer -} - -func (vals *ValidatorSet) RescalePriorities(diffMax int64) { - if vals.IsNilOrEmpty() { - panic("empty validator set") - } - // NOTE: This check is merely a sanity check which could be - // removed if all tests would init. voting power appropriately; - // i.e. diffMax should always be > 0 - if diffMax <= 0 { - return - } - - // Calculating ceil(diff/diffMax): - // Re-normalization is performed by dividing by an integer for simplicity. - // NOTE: This may make debugging priority issues easier as well. - diff := computeMaxMinPriorityDiff(vals) - ratio := (diff + diffMax - 1) / diffMax - if diff > diffMax { - for _, val := range vals.Validators { - val.ProposerPriority = val.ProposerPriority / ratio - } - } -} - -func (vals *ValidatorSet) incrementProposerPriority() *valset.Validator { - for _, val := range vals.Validators { - // Check for overflow for sum. - newPrio := safeAddClip(val.ProposerPriority, val.VotingPower) - val.ProposerPriority = newPrio - } - // Decrement the validator with most ProposerPriority. - mostest := vals.getValWithMostPriority() - // Mind the underflow. - mostest.ProposerPriority = safeSubClip(mostest.ProposerPriority, vals.TotalVotingPower()) - - return mostest -} - -// Should not be called on an empty validator set. -func (vals *ValidatorSet) computeAvgProposerPriority() int64 { - n := int64(len(vals.Validators)) - sum := big.NewInt(0) - for _, val := range vals.Validators { - sum.Add(sum, big.NewInt(val.ProposerPriority)) - } - avg := sum.Div(sum, big.NewInt(n)) - if avg.IsInt64() { - return avg.Int64() - } - - // This should never happen: each val.ProposerPriority is in bounds of int64. - panic(fmt.Sprintf("Cannot represent avg ProposerPriority as an int64 %v", avg)) -} - -// Compute the difference between the max and min ProposerPriority of that set. -func computeMaxMinPriorityDiff(vals *ValidatorSet) int64 { - if vals.IsNilOrEmpty() { - panic("empty validator set") - } - max := int64(math.MinInt64) - min := int64(math.MaxInt64) - for _, v := range vals.Validators { - if v.ProposerPriority < min { - min = v.ProposerPriority - } - if v.ProposerPriority > max { - max = v.ProposerPriority - } - } - diff := max - min - if diff < 0 { - return -1 * diff - } else { - return diff - } -} - -func (vals *ValidatorSet) getValWithMostPriority() *valset.Validator { - var res *valset.Validator - for _, val := range vals.Validators { - res = res.Cmp(val) - } - return res -} - -func (vals *ValidatorSet) shiftByAvgProposerPriority() { - if vals.IsNilOrEmpty() { - panic("empty validator set") - } - avgProposerPriority := vals.computeAvgProposerPriority() - for _, val := range vals.Validators { - val.ProposerPriority = safeSubClip(val.ProposerPriority, avgProposerPriority) - } -} - -// Makes a copy of the validator list. -func validatorListCopy(valsList []*valset.Validator) []*valset.Validator { - if valsList == nil { - return nil - } - valsCopy := make([]*valset.Validator, len(valsList)) - for i, val := range valsList { - valsCopy[i] = val.Copy() - } - return valsCopy -} - -// Copy each validator into a new ValidatorSet. -func (vals *ValidatorSet) Copy() *ValidatorSet { - return &ValidatorSet{ - Validators: validatorListCopy(vals.Validators), - Proposer: vals.Proposer, - totalVotingPower: vals.totalVotingPower, - } -} - -// HasAddress returns true if address given is in the validator set, false - -// otherwise. -func (vals *ValidatorSet) HasAddress(address []byte) bool { - idx := sort.Search(len(vals.Validators), func(i int) bool { - return bytes.Compare(address, vals.Validators[i].Address.Bytes()) <= 0 - }) - return idx < len(vals.Validators) && bytes.Equal(vals.Validators[idx].Address.Bytes(), address) -} - -// GetByAddress returns an index of the validator with address and validator -// itself if found. Otherwise, -1 and nil are returned. -func (vals *ValidatorSet) GetByAddress(address libcommon.Address) (index int, val *valset.Validator) { - idx := sort.Search(len(vals.Validators), func(i int) bool { - return bytes.Compare(address.Bytes(), vals.Validators[i].Address.Bytes()) <= 0 - }) - if idx < len(vals.Validators) && bytes.Equal(vals.Validators[idx].Address.Bytes(), address.Bytes()) { - return idx, vals.Validators[idx].Copy() - } - return -1, nil -} - -// GetByIndex returns the validator's address and validator itself by index. -// It returns nil values if index is less than 0 or greater or equal to -// len(ValidatorSet.Validators). -func (vals *ValidatorSet) GetByIndex(index int) (address []byte, val *valset.Validator) { - if index < 0 || index >= len(vals.Validators) { - return nil, nil - } - val = vals.Validators[index] - return val.Address.Bytes(), val.Copy() -} - -// Size returns the length of the validator set. -func (vals *ValidatorSet) Size() int { - return len(vals.Validators) -} - -// Force recalculation of the set's total voting power. -func (vals *ValidatorSet) UpdateTotalVotingPower() error { - - sum := int64(0) - for _, val := range vals.Validators { - // mind overflow - sum = safeAddClip(sum, val.VotingPower) - if sum > MaxTotalVotingPower { - return &valset.TotalVotingPowerExceededError{Sum: sum, Validators: vals.Validators} - } - } - vals.totalVotingPower = sum - return nil -} - -// TotalVotingPower returns the sum of the voting powers of all validators. -// It recomputes the total voting power if required. -func (vals *ValidatorSet) TotalVotingPower() int64 { - if vals.totalVotingPower == 0 { - log.Info("invoking updateTotalVotingPower before returning it") - if err := vals.UpdateTotalVotingPower(); err != nil { - // Can/should we do better? - panic(err) - } - } - return vals.totalVotingPower -} - -// GetProposer returns the current proposer. If the validator set is empty, nil -// is returned. -func (vals *ValidatorSet) GetProposer() (proposer *valset.Validator) { - if len(vals.Validators) == 0 { - return nil - } - if vals.Proposer == nil { - vals.Proposer = vals.findProposer() - } - return vals.Proposer.Copy() -} - -func (vals *ValidatorSet) findProposer() *valset.Validator { - var proposer *valset.Validator - for _, val := range vals.Validators { - if proposer == nil || !bytes.Equal(val.Address.Bytes(), proposer.Address.Bytes()) { - proposer = proposer.Cmp(val) - } - } - return proposer -} - -// Hash returns the Merkle root hash build using validators (as leaves) in the -// set. -// func (vals *ValidatorSet) Hash() []byte { -// if len(vals.Validators) == 0 { -// return nil -// } -// bzs := make([][]byte, len(vals.Validators)) -// for i, val := range vals.Validators { -// bzs[i] = val.Bytes() -// } -// return merkle.SimpleHashFromByteSlices(bzs) -// } - -// Iterate will run the given function over the set. -func (vals *ValidatorSet) Iterate(fn func(index int, val *valset.Validator) bool) { - for i, val := range vals.Validators { - stop := fn(i, val.Copy()) - if stop { - break - } - } -} - -// Checks changes against duplicates, splits the changes in updates and removals, sorts them by address. -// -// Returns: -// updates, removals - the sorted lists of updates and removals -// err - non-nil if duplicate entries or entries with negative voting power are seen -// -// No changes are made to 'origChanges'. -func processChanges(origChanges []*valset.Validator) (updates, removals []*valset.Validator, err error) { - // Make a deep copy of the changes and sort by address. - changes := validatorListCopy(origChanges) - sort.Sort(ValidatorsByAddress(changes)) - - removals = make([]*valset.Validator, 0, len(changes)) - updates = make([]*valset.Validator, 0, len(changes)) - var prevAddr libcommon.Address - - // Scan changes by address and append valid validators to updates or removals lists. - for _, valUpdate := range changes { - if bytes.Equal(valUpdate.Address.Bytes(), prevAddr.Bytes()) { - err = fmt.Errorf("duplicate entry %v in %v", valUpdate, changes) - return nil, nil, err - } - if valUpdate.VotingPower < 0 { - err = fmt.Errorf("voting power can't be negative: %v", valUpdate) - return nil, nil, err - } - if valUpdate.VotingPower > MaxTotalVotingPower { - err = fmt.Errorf("to prevent clipping/ overflow, voting power can't be higher than %v: %v ", - MaxTotalVotingPower, valUpdate) - return nil, nil, err - } - if valUpdate.VotingPower == 0 { - removals = append(removals, valUpdate) - } else { - updates = append(updates, valUpdate) - } - prevAddr = valUpdate.Address - } - return updates, removals, err -} - -// Verifies a list of updates against a validator set, making sure the allowed -// total voting power would not be exceeded if these updates would be applied to the set. -// -// Returns: -// updatedTotalVotingPower - the new total voting power if these updates would be applied -// numNewValidators - number of new validators -// err - non-nil if the maximum allowed total voting power would be exceeded -// -// 'updates' should be a list of proper validator changes, i.e. they have been verified -// by processChanges for duplicates and invalid values. -// No changes are made to the validator set 'vals'. -func verifyUpdates(updates []*valset.Validator, vals *ValidatorSet) (updatedTotalVotingPower int64, numNewValidators int, err error) { - - updatedTotalVotingPower = vals.TotalVotingPower() - - for _, valUpdate := range updates { - address := valUpdate.Address - _, val := vals.GetByAddress(address) - if val == nil { - // New validator, add its voting power the the total. - updatedTotalVotingPower += valUpdate.VotingPower - numNewValidators++ - } else { - // Updated validator, add the difference in power to the total. - updatedTotalVotingPower += valUpdate.VotingPower - val.VotingPower - } - overflow := updatedTotalVotingPower > MaxTotalVotingPower - if overflow { - err = fmt.Errorf( - "failed to add/update validator %v, total voting power would exceed the max allowed %v", - valUpdate, MaxTotalVotingPower) - return 0, 0, err - } - } - - return updatedTotalVotingPower, numNewValidators, nil -} - -// Computes the proposer priority for the validators not present in the set based on 'updatedTotalVotingPower'. -// Leaves unchanged the priorities of validators that are changed. -// -// 'updates' parameter must be a list of unique validators to be added or updated. -// No changes are made to the validator set 'vals'. -func computeNewPriorities(updates []*valset.Validator, vals *ValidatorSet, updatedTotalVotingPower int64) { - - for _, valUpdate := range updates { - address := valUpdate.Address - _, val := vals.GetByAddress(address) - if val == nil { - // add val - // Set ProposerPriority to -C*totalVotingPower (with C ~= 1.125) to make sure validators can't - // un-bond and then re-bond to reset their (potentially previously negative) ProposerPriority to zero. - // - // Contract: updatedVotingPower < MaxTotalVotingPower to ensure ProposerPriority does - // not exceed the bounds of int64. - // - // Compute ProposerPriority = -1.125*totalVotingPower == -(updatedVotingPower + (updatedVotingPower >> 3)). - valUpdate.ProposerPriority = -(updatedTotalVotingPower + (updatedTotalVotingPower >> 3)) - } else { - valUpdate.ProposerPriority = val.ProposerPriority - } - } - -} - -// Merges the vals' validator list with the updates list. -// When two elements with same address are seen, the one from updates is selected. -// Expects updates to be a list of updates sorted by address with no duplicates or errors, -// must have been validated with verifyUpdates() and priorities computed with computeNewPriorities(). -func (vals *ValidatorSet) applyUpdates(updates []*valset.Validator) { - - existing := vals.Validators - merged := make([]*valset.Validator, len(existing)+len(updates)) - i := 0 - - for len(existing) > 0 && len(updates) > 0 { - if bytes.Compare(existing[0].Address.Bytes(), updates[0].Address.Bytes()) < 0 { // unchanged validator - merged[i] = existing[0] - existing = existing[1:] - } else { - // Apply add or update. - merged[i] = updates[0] - if bytes.Equal(existing[0].Address.Bytes(), updates[0].Address.Bytes()) { - // bor.Validator is present in both, advance existing. - existing = existing[1:] - } - updates = updates[1:] - } - i++ - } - - // Add the elements which are left. - for j := 0; j < len(existing); j++ { - merged[i] = existing[j] - i++ - } - // OR add updates which are left. - for j := 0; j < len(updates); j++ { - merged[i] = updates[j] - i++ - } - - vals.Validators = merged[:i] -} - -// Checks that the validators to be removed are part of the validator set. -// No changes are made to the validator set 'vals'. -func verifyRemovals(deletes []*valset.Validator, vals *ValidatorSet) error { - - for _, valUpdate := range deletes { - address := valUpdate.Address - _, val := vals.GetByAddress(address) - if val == nil { - return fmt.Errorf("failed to find validator %X to remove", address) - } - } - if len(deletes) > len(vals.Validators) { - panic("more deletes than validators") - } - return nil -} - -// Removes the validators specified in 'deletes' from validator set 'vals'. -// Should not fail as verification has been done before. -func (vals *ValidatorSet) applyRemovals(deletes []*valset.Validator) { - - existing := vals.Validators - - merged := make([]*valset.Validator, len(existing)-len(deletes)) - i := 0 - - // Loop over deletes until we removed all of them. - for len(deletes) > 0 { - if bytes.Equal(existing[0].Address.Bytes(), deletes[0].Address.Bytes()) { - deletes = deletes[1:] - } else { // Leave it in the resulting slice. - merged[i] = existing[0] - i++ - } - existing = existing[1:] - } - - // Add the elements which are left. - for j := 0; j < len(existing); j++ { - merged[i] = existing[j] - i++ - } - - vals.Validators = merged[:i] -} - -// Main function used by UpdateWithChangeSet() and NewValidatorSet(). -// If 'allowDeletes' is false then delete operations (identified by validators with voting power 0) -// are not allowed and will trigger an error if present in 'changes'. -// The 'allowDeletes' flag is set to false by NewValidatorSet() and to true by UpdateWithChangeSet(). -func (vals *ValidatorSet) updateWithChangeSet(changes []*valset.Validator, allowDeletes bool) error { - - if len(changes) < 1 { - return nil - } - - // Check for duplicates within changes, split in 'updates' and 'deletes' lists (sorted). - updates, deletes, err := processChanges(changes) - if err != nil { - return err - } - - if !allowDeletes && len(deletes) != 0 { - return fmt.Errorf("cannot process validators with voting power 0: %v", deletes) - } - - // Verify that applying the 'deletes' against 'vals' will not result in error. - if err := verifyRemovals(deletes, vals); err != nil { - return err - } - - // Verify that applying the 'updates' against 'vals' will not result in error. - updatedTotalVotingPower, numNewValidators, err := verifyUpdates(updates, vals) - if err != nil { - return err - } - - // Check that the resulting set will not be empty. - if numNewValidators == 0 && len(vals.Validators) == len(deletes) { - return fmt.Errorf("applying the validator changes would result in empty set") - } - - // Compute the priorities for updates. - computeNewPriorities(updates, vals, updatedTotalVotingPower) - - // Apply updates and removals. - vals.applyUpdates(updates) - vals.applyRemovals(deletes) - - if err := vals.UpdateTotalVotingPower(); err != nil { - return err - } - - // Scale and center. - vals.RescalePriorities(PriorityWindowSizeFactor * vals.TotalVotingPower()) - vals.shiftByAvgProposerPriority() - - return nil -} - -// UpdateWithChangeSet attempts to update the validator set with 'changes'. -// It performs the following steps: -// - validates the changes making sure there are no duplicates and splits them in updates and deletes -// - verifies that applying the changes will not result in errors -// - computes the total voting power BEFORE removals to ensure that in the next steps the priorities -// across old and newly added validators are fair -// - computes the priorities of new validators against the final set -// - applies the updates against the validator set -// - applies the removals against the validator set -// - performs scaling and centering of priority values -// -// If an error is detected during verification steps, it is returned and the validator set -// is not changed. -func (vals *ValidatorSet) UpdateWithChangeSet(changes []*valset.Validator) error { - return vals.updateWithChangeSet(changes, true) -} - -//----------------- -// ErrTooMuchChange - -func IsErrTooMuchChange(err error) bool { - switch err.(type) { - case errTooMuchChange: - return true - default: - return false - } -} - -type errTooMuchChange struct { - got int64 - needed int64 -} - -func (e errTooMuchChange) Error() string { - return fmt.Sprintf("Invalid commit -- insufficient old voting power: got %v, needed %v", e.got, e.needed) -} - -//---------------- - -func (vals *ValidatorSet) String() string { - return vals.StringIndented("") -} - -func (vals *ValidatorSet) StringIndented(indent string) string { - if vals == nil { - return "nil-ValidatorSet" - } - var valStrings []string - vals.Iterate(func(index int, val *valset.Validator) bool { - valStrings = append(valStrings, val.String()) - return false - }) - return fmt.Sprintf(`ValidatorSet{ -%s Proposer: %v -%s Validators: -%s %v -%s}`, - indent, vals.GetProposer().String(), - indent, - indent, strings.Join(valStrings, "\n"+indent+" "), - indent) - -} - -//------------------------------------- -// Implements sort for sorting validators by address. - -// Sort validators by address. -type ValidatorsByAddress []*valset.Validator - -func (valz ValidatorsByAddress) Len() int { - return len(valz) -} - -func (valz ValidatorsByAddress) Less(i, j int) bool { - return bytes.Compare(valz[i].Address.Bytes(), valz[j].Address.Bytes()) == -1 -} - -func (valz ValidatorsByAddress) Swap(i, j int) { - valz[i], valz[j] = valz[j], valz[i] -} - -/////////////////////////////////////////////////////////////////////////////// -// safe addition/subtraction - -func safeAdd(a, b int64) (int64, bool) { - if b > 0 && a > math.MaxInt64-b { - return -1, true - } else if b < 0 && a < math.MinInt64-b { - return -1, true - } - return a + b, false -} - -func safeSub(a, b int64) (int64, bool) { - if b > 0 && a < math.MinInt64+b { - return -1, true - } else if b < 0 && a > math.MaxInt64+b { - return -1, true - } - return a - b, false -} - -func safeAddClip(a, b int64) int64 { - c, overflow := safeAdd(a, b) - if overflow { - if b < 0 { - return math.MinInt64 - } - return math.MaxInt64 - } - return c -} - -func safeSubClip(a, b int64) int64 { - c, overflow := safeSub(a, b) - if overflow { - if b > 0 { - return math.MinInt64 - } - return math.MaxInt64 - } - return c -} From 470f05ee6f1095b5cdee7401c2ac83cfb8dfd56c Mon Sep 17 00:00:00 2001 From: Michelangelo Riccobene Date: Thu, 11 Jan 2024 02:47:23 +0100 Subject: [PATCH 41/92] clean-exit test: increase test time (#9193) This PR - increase the test time - use the updated python scripts that reports as an issue a long exit time - change the test name to states that it is runned in the snapshot downloading phase (a later PR will add a similar test on the block downloading phase) --- ...clean-exit.yml => qa-clean-exit-snapshot-downloading.yml} | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) rename .github/workflows/{qa-clean-exit.yml => qa-clean-exit-snapshot-downloading.yml} (93%) diff --git a/.github/workflows/qa-clean-exit.yml b/.github/workflows/qa-clean-exit-snapshot-downloading.yml similarity index 93% rename from .github/workflows/qa-clean-exit.yml rename to .github/workflows/qa-clean-exit-snapshot-downloading.yml index ace204be27e..7b04664f762 100644 --- a/.github/workflows/qa-clean-exit.yml +++ b/.github/workflows/qa-clean-exit-snapshot-downloading.yml @@ -1,4 +1,4 @@ -name: QA - Clean exit on Ctrl-C +name: QA - Clean exit (snapshot downloading) on: push: @@ -22,6 +22,7 @@ jobs: runs-on: self-hosted env: ERIGON_DATA_DIR: ${{ github.workspace }}/erigon_data + WORKING_TIME_SECONDS: 600 steps: - name: Check out repository @@ -58,7 +59,7 @@ jobs: - name: Run Erigon, send ctrl-c and check for clean exiting run: | # Run Erigon, send ctrl-c and check logs - python3 ${{ github.workspace }}/../../../../erigon-qa/test_system/qa-tests/clean-exit/run_and_check_clean_exit.py ${{ github.workspace }}/build/bin $ERIGON_DATA_DIR + python3 ${{ github.workspace }}/../../../../erigon-qa/test_system/qa-tests/clean-exit/run_and_check_clean_exit.py ${{ github.workspace }}/build/bin $ERIGON_DATA_DIR $WORKING_TIME_SECONDS # Capture monitoring script exit status monitoring_exit_status=$? From 7308e87c0ed8afbf4dd91be10f05078a1c5745d2 Mon Sep 17 00:00:00 2001 From: Mark Holt <135143369+mh0lt@users.noreply.github.com> Date: Thu, 11 Jan 2024 10:03:41 +0000 Subject: [PATCH 42/92] Fix txpool queue overflow (#9197) When discarding spamming we need to remove the tx from the subpools as well as the sender tx list. Otherwise the tx is ignored by other operations and left in the subpool As well as the fix here this PR also contains several changes to TX TRACING and other logging to make it easier to see what is going on with pool processing --- erigon-lib/txpool/pool.go | 223 ++++++++++++++++----------- eth/backend.go | 6 +- eth/stagedsync/stage_bor_heimdall.go | 1 + 3 files changed, 135 insertions(+), 95 deletions(-) diff --git a/erigon-lib/txpool/pool.go b/erigon-lib/txpool/pool.go index 45dc6f11523..e6e479815eb 100644 --- a/erigon-lib/txpool/pool.go +++ b/erigon-lib/txpool/pool.go @@ -74,6 +74,8 @@ var ( basefeeSubCounter = metrics.GetOrCreateGauge(`txpool_basefee`) ) +var TraceAll = false + // Pool is interface for the transaction pool // This interface exists for the convenience of testing, and not yet because // there are multiple implementations @@ -420,14 +422,14 @@ func (p *TxPool) OnNewBlock(ctx context.Context, stateChanges *remote.StateChang return err } - if err = removeMined(p.all, minedTxs.Txs, p.pending, p.baseFee, p.queued, p.discardLocked, p.logger); err != nil { + if err = p.removeMined(p.all, minedTxs.Txs); err != nil { return err } var announcements types.Announcements - announcements, err = addTxsOnNewBlock(block, cacheView, stateChanges, p.senders, unwindTxs, /* newTxs */ - pendingBaseFee, stateChanges.BlockGasLimit, p.pending, p.baseFee, p.queued, p.all, p.byHash, p.addLocked, p.discardLocked, p.logger) + announcements, err = p.addTxsOnNewBlock(block, cacheView, stateChanges, p.senders, unwindTxs, /* newTxs */ + pendingBaseFee, stateChanges.BlockGasLimit, p.logger) if err != nil { return err @@ -436,7 +438,7 @@ func (p *TxPool) OnNewBlock(ctx context.Context, stateChanges *remote.StateChang p.pending.EnforceWorstInvariants() p.baseFee.EnforceInvariants() p.queued.EnforceInvariants() - promote(p.pending, p.baseFee, p.queued, pendingBaseFee, pendingBlobFee, p.discardLocked, &announcements, p.logger) + p.promote(pendingBaseFee, pendingBlobFee, &announcements, p.logger) p.pending.EnforceBestInvariants() p.promoted.Reset() p.promoted.AppendOther(announcements) @@ -487,8 +489,8 @@ func (p *TxPool) processRemoteTxs(ctx context.Context) error { return err } - announcements, _, err := addTxs(p.lastSeenBlock.Load(), cacheView, p.senders, newTxs, - p.pendingBaseFee.Load(), p.pendingBlobFee.Load(), p.blockGasLimit.Load(), p.pending, p.baseFee, p.queued, p.all, p.byHash, p.addLocked, p.discardLocked, true, p.logger) + announcements, _, err := p.addTxs(p.lastSeenBlock.Load(), cacheView, p.senders, newTxs, + p.pendingBaseFee.Load(), p.pendingBlobFee.Load(), p.blockGasLimit.Load(), true, p.logger) if err != nil { return err } @@ -727,7 +729,7 @@ func (p *TxPool) best(n uint16, txs *types.TxsRlp, tx kv.Tx, onTopOf, availableG txs.Resize(uint(count)) if len(toRemove) > 0 { for _, mt := range toRemove { - p.pending.Remove(mt) + p.pending.Remove(mt, "best", p.logger) } } return true, count, nil @@ -848,13 +850,13 @@ func (p *TxPool) validateTx(txn *types.TxSlot, isLocal bool, stateCache kvcache. } if !isLocal && uint64(p.all.count(txn.SenderID)) > p.cfg.AccountSlots { if txn.Traced { - log.Info(fmt.Sprintf("TX TRACING: validateTx marked as spamming idHash=%x slots=%d, limit=%d", txn.IDHash, p.all.count(txn.SenderID), p.cfg.AccountSlots)) + p.logger.Info(fmt.Sprintf("TX TRACING: validateTx marked as spamming idHash=%x slots=%d, limit=%d", txn.IDHash, p.all.count(txn.SenderID), p.cfg.AccountSlots)) } return txpoolcfg.Spammer } if !isLocal && p.all.blobCount(txn.SenderID) > p.cfg.BlobSlots { if txn.Traced { - log.Info(fmt.Sprintf("TX TRACING: validateTx marked as spamming (too many blobs) idHash=%x slots=%d, limit=%d", txn.IDHash, p.all.count(txn.SenderID), p.cfg.AccountSlots)) + p.logger.Info(fmt.Sprintf("TX TRACING: validateTx marked as spamming (too many blobs) idHash=%x slots=%d, limit=%d", txn.IDHash, p.all.count(txn.SenderID), p.cfg.AccountSlots)) } return txpoolcfg.Spammer } @@ -1076,7 +1078,19 @@ func (p *TxPool) punishSpammer(spammer uint64) { count-- return count > 0 }) + for _, mt := range txsToDelete { + switch mt.currentSubPool { + case PendingSubPool: + p.pending.Remove(mt, "punishSpammer", p.logger) + case BaseFeeSubPool: + p.baseFee.Remove(mt, "punishSpammer", p.logger) + case QueuedSubPool: + p.queued.Remove(mt, "punishSpammer", p.logger) + default: + //already removed + } + p.discardLocked(mt, txpoolcfg.Spammer) // can't call it while iterating by all } } @@ -1122,8 +1136,8 @@ func (p *TxPool) AddLocalTxs(ctx context.Context, newTransactions types.TxSlots, return nil, err } - announcements, addReasons, err := addTxs(p.lastSeenBlock.Load(), cacheView, p.senders, newTxs, - p.pendingBaseFee.Load(), p.pendingBlobFee.Load(), p.blockGasLimit.Load(), p.pending, p.baseFee, p.queued, p.all, p.byHash, p.addLocked, p.discardLocked, true, p.logger) + announcements, addReasons, err := p.addTxs(p.lastSeenBlock.Load(), cacheView, p.senders, newTxs, + p.pendingBaseFee.Load(), p.pendingBlobFee.Load(), p.blockGasLimit.Load(), true, p.logger) if err == nil { for i, reason := range addReasons { if reason != txpoolcfg.NotSet { @@ -1159,11 +1173,9 @@ func (p *TxPool) coreDBWithCache() (kv.RoDB, kvcache.Cache) { defer p.lock.Unlock() return p._chainDB, p._stateCache } -func addTxs(blockNum uint64, cacheView kvcache.CacheView, senders *sendersBatch, - newTxs types.TxSlots, pendingBaseFee, pendingBlobFee, blockGasLimit uint64, - pending *PendingPool, baseFee, queued *SubPool, - byNonce *BySenderAndNonce, byHash map[string]*metaTx, add func(*metaTx, *types.Announcements) txpoolcfg.DiscardReason, discard func(*metaTx, txpoolcfg.DiscardReason), collect bool, - logger log.Logger) (types.Announcements, []txpoolcfg.DiscardReason, error) { + +func (p *TxPool) addTxs(blockNum uint64, cacheView kvcache.CacheView, senders *sendersBatch, + newTxs types.TxSlots, pendingBaseFee, pendingBlobFee, blockGasLimit uint64, collect bool, logger log.Logger) (types.Announcements, []txpoolcfg.DiscardReason, error) { if assert.Enable { for _, txn := range newTxs.Txs { if txn.SenderID == 0 { @@ -1171,6 +1183,7 @@ func addTxs(blockNum uint64, cacheView kvcache.CacheView, senders *sendersBatch, } } } + // This can be thought of a reverse operation from the one described before. // When a block that was deemed "the best" of its height, is no longer deemed "the best", the // transactions contained in it, are now viable for inclusion in other blocks, and therefore should @@ -1184,7 +1197,7 @@ func addTxs(blockNum uint64, cacheView kvcache.CacheView, senders *sendersBatch, discardReasons := make([]txpoolcfg.DiscardReason, len(newTxs.Txs)) announcements := types.Announcements{} for i, txn := range newTxs.Txs { - if found, ok := byHash[string(txn.IDHash[:])]; ok { + if found, ok := p.byHash[string(txn.IDHash[:])]; ok { discardReasons[i] = txpoolcfg.DuplicateHash // In case if the transition is stuck, "poke" it to rebroadcast if collect && newTxs.IsLocal[i] && (found.currentSubPool == PendingSubPool || found.currentSubPool == BaseFeeSubPool) { @@ -1193,7 +1206,7 @@ func addTxs(blockNum uint64, cacheView kvcache.CacheView, senders *sendersBatch, continue } mt := newMetaTx(txn, newTxs.IsLocal[i], blockNum) - if reason := add(mt, &announcements); reason != txpoolcfg.NotSet { + if reason := p.addLocked(mt, &announcements); reason != txpoolcfg.NotSet { discardReasons[i] = reason continue } @@ -1209,22 +1222,18 @@ func addTxs(blockNum uint64, cacheView kvcache.CacheView, senders *sendersBatch, if err != nil { return announcements, discardReasons, err } - onSenderStateChange(senderID, nonce, balance, byNonce, - blockGasLimit, pending, baseFee, queued, discard, logger) + p.onSenderStateChange(senderID, nonce, balance, blockGasLimit, logger) } - promote(pending, baseFee, queued, pendingBaseFee, pendingBlobFee, discard, &announcements, logger) - pending.EnforceBestInvariants() + p.promote(pendingBaseFee, pendingBlobFee, &announcements, logger) + p.pending.EnforceBestInvariants() return announcements, discardReasons, nil } // TODO: Looks like a copy of the above -func addTxsOnNewBlock(blockNum uint64, cacheView kvcache.CacheView, stateChanges *remote.StateChangeBatch, - senders *sendersBatch, newTxs types.TxSlots, pendingBaseFee uint64, blockGasLimit uint64, - pending *PendingPool, baseFee, queued *SubPool, - byNonce *BySenderAndNonce, byHash map[string]*metaTx, add func(*metaTx, *types.Announcements) txpoolcfg.DiscardReason, discard func(*metaTx, txpoolcfg.DiscardReason), - logger log.Logger) (types.Announcements, error) { +func (p *TxPool) addTxsOnNewBlock(blockNum uint64, cacheView kvcache.CacheView, stateChanges *remote.StateChangeBatch, + senders *sendersBatch, newTxs types.TxSlots, pendingBaseFee uint64, blockGasLimit uint64, logger log.Logger) (types.Announcements, error) { if assert.Enable { for _, txn := range newTxs.Txs { if txn.SenderID == 0 { @@ -1244,12 +1253,12 @@ func addTxsOnNewBlock(blockNum uint64, cacheView kvcache.CacheView, stateChanges sendersWithChangedState := map[uint64]struct{}{} announcements := types.Announcements{} for i, txn := range newTxs.Txs { - if _, ok := byHash[string(txn.IDHash[:])]; ok { + if _, ok := p.byHash[string(txn.IDHash[:])]; ok { continue } mt := newMetaTx(txn, newTxs.IsLocal[i], blockNum) - if reason := add(mt, &announcements); reason != txpoolcfg.NotSet { - discard(mt, reason) + if reason := p.addLocked(mt, &announcements); reason != txpoolcfg.NotSet { + p.discardLocked(mt, reason) continue } sendersWithChangedState[mt.Tx.SenderID] = struct{}{} @@ -1277,8 +1286,7 @@ func addTxsOnNewBlock(blockNum uint64, cacheView kvcache.CacheView, stateChanges if err != nil { return announcements, err } - onSenderStateChange(senderID, nonce, balance, byNonce, - blockGasLimit, pending, baseFee, queued, discard, logger) + p.onSenderStateChange(senderID, nonce, balance, blockGasLimit, logger) } return announcements, nil @@ -1345,11 +1353,11 @@ func (p *TxPool) addLocked(mt *metaTx, announcements *types.Announcements) txpoo switch found.currentSubPool { case PendingSubPool: - p.pending.Remove(found) + p.pending.Remove(found, "add", p.logger) case BaseFeeSubPool: - p.baseFee.Remove(found) + p.baseFee.Remove(found, "add", p.logger) case QueuedSubPool: - p.queued.Remove(found) + p.queued.Remove(found, "add", p.logger) default: //already removed } @@ -1365,7 +1373,7 @@ func (p *TxPool) addLocked(mt *metaTx, announcements *types.Announcements) txpoo hashStr := string(mt.Tx.IDHash[:]) p.byHash[hashStr] = mt - if replaced := p.all.replaceOrInsert(mt); replaced != nil { + if replaced := p.all.replaceOrInsert(mt, p.logger); replaced != nil { if assert.Enable { panic("must never happen") } @@ -1375,7 +1383,7 @@ func (p *TxPool) addLocked(mt *metaTx, announcements *types.Announcements) txpoo p.isLocalLRU.Add(hashStr, struct{}{}) } // All transactions are first added to the queued pool and then immediately promoted from there if required - p.queued.Add(mt, p.logger) + p.queued.Add(mt, "addLocked", p.logger) // Remove from mined cache as we are now "resurrecting" it to a sub-pool p.deleteMinedBlobTxn(hashStr) return txpoolcfg.NotSet @@ -1387,7 +1395,7 @@ func (p *TxPool) discardLocked(mt *metaTx, reason txpoolcfg.DiscardReason) { hashStr := string(mt.Tx.IDHash[:]) delete(p.byHash, hashStr) p.deletedTxs = append(p.deletedTxs, mt) - p.all.delete(mt) + p.all.delete(mt, reason, p.logger) p.discardReasonsLRU.Add(hashStr, reason) } @@ -1451,7 +1459,7 @@ func (p *TxPool) NonceFromAddress(addr [20]byte) (nonce uint64, inPool bool) { // modify state_balance and state_nonce, potentially remove some elements (if transaction with some nonce is // included into a block), and finally, walk over the transaction records and update SubPool fields depending on // the actual presence of nonce gaps and what the balance is. -func removeMined(byNonce *BySenderAndNonce, minedTxs []*types.TxSlot, pending *PendingPool, baseFee, queued *SubPool, discard func(*metaTx, txpoolcfg.DiscardReason), logger log.Logger) error { +func (p *TxPool) removeMined(byNonce *BySenderAndNonce, minedTxs []*types.TxSlot) error { noncesToRemove := map[uint64]uint64{} for _, txn := range minedTxs { nonce, ok := noncesToRemove[txn.SenderID] @@ -1468,18 +1476,17 @@ func removeMined(byNonce *BySenderAndNonce, minedTxs []*types.TxSlot, pending *P queuedRemoved := 0 for senderID, nonce := range noncesToRemove { - byNonce.ascend(senderID, func(mt *metaTx) bool { if mt.Tx.Nonce > nonce { if mt.Tx.Traced { - logger.Debug("[txpool] removing mined, cmp nonces", "tx.nonce", mt.Tx.Nonce, "sender.nonce", nonce) + p.logger.Debug("[txpool] removing mined, cmp nonces", "tx.nonce", mt.Tx.Nonce, "sender.nonce", nonce) } return false } if mt.Tx.Traced { - logger.Info(fmt.Sprintf("TX TRACING: removeMined idHash=%x senderId=%d, currentSubPool=%s", mt.Tx.IDHash, mt.Tx.SenderID, mt.currentSubPool)) + p.logger.Info("TX TRACING: removeMined", "idHash", fmt.Sprintf("%x", mt.Tx.IDHash), "senderId", mt.Tx.SenderID, "nonce", mt.Tx.Nonce, "currentSubPool", mt.currentSubPool) } toDel = append(toDel, mt) @@ -1487,13 +1494,13 @@ func removeMined(byNonce *BySenderAndNonce, minedTxs []*types.TxSlot, pending *P switch mt.currentSubPool { case PendingSubPool: pendingRemoved++ - pending.Remove(mt) + p.pending.Remove(mt, "remove-mined", p.logger) case BaseFeeSubPool: baseFeeRemoved++ - baseFee.Remove(mt) + p.baseFee.Remove(mt, "remove-mined", p.logger) case QueuedSubPool: queuedRemoved++ - queued.Remove(mt) + p.queued.Remove(mt, "remove-mined", p.logger) default: //already removed } @@ -1503,13 +1510,13 @@ func removeMined(byNonce *BySenderAndNonce, minedTxs []*types.TxSlot, pending *P discarded += len(toDel) for _, mt := range toDel { - discard(mt, txpoolcfg.Mined) + p.discardLocked(mt, txpoolcfg.Mined) } toDel = toDel[:0] } if discarded > 0 { - logger.Debug("Discarding Transactions", "count", discarded, "pending", pendingRemoved, "baseFee", baseFeeRemoved, "queued", queuedRemoved) + p.logger.Debug("Discarded transactions", "count", discarded, "pending", pendingRemoved, "baseFee", baseFeeRemoved, "queued", queuedRemoved) } return nil @@ -1519,17 +1526,14 @@ func removeMined(byNonce *BySenderAndNonce, minedTxs []*types.TxSlot, pending *P // which sub pool they will need to go to. Since this depends on other transactions from the same sender by with lower // nonces, and also affect other transactions from the same sender with higher nonce, it loops through all transactions // for a given senderID -func onSenderStateChange(senderID uint64, senderNonce uint64, senderBalance uint256.Int, byNonce *BySenderAndNonce, - blockGasLimit uint64, pending *PendingPool, baseFee, queued *SubPool, discard func(*metaTx, txpoolcfg.DiscardReason), logger log.Logger) { +func (p *TxPool) onSenderStateChange(senderID uint64, senderNonce uint64, senderBalance uint256.Int, blockGasLimit uint64, logger log.Logger) { noGapsNonce := senderNonce cumulativeRequiredBalance := uint256.NewInt(0) minFeeCap := uint256.NewInt(0).SetAllOne() minTip := uint64(math.MaxUint64) var toDel []*metaTx // can't delete items while iterate them - byNonce.ascend(senderID, func(mt *metaTx) bool { - if mt.Tx.Traced { - logger.Info(fmt.Sprintf("TX TRACING: onSenderStateChange loop iteration idHash=%x senderID=%d, senderNonce=%d, txn.nonce=%d, currentSubPool=%s", mt.Tx.IDHash, senderID, senderNonce, mt.Tx.Nonce, mt.currentSubPool)) - } + + p.all.ascend(senderID, func(mt *metaTx) bool { deleteAndContinueReasonLog := "" if senderNonce > mt.Tx.Nonce { deleteAndContinueReasonLog = "low nonce" @@ -1538,16 +1542,16 @@ func onSenderStateChange(senderID uint64, senderNonce uint64, senderBalance uint } if deleteAndContinueReasonLog != "" { if mt.Tx.Traced { - logger.Info(fmt.Sprintf("TX TRACING: removing due to %s for idHash=%x senderID=%d, senderNonce=%d, txn.nonce=%d, currentSubPool=%s", deleteAndContinueReasonLog, mt.Tx.IDHash, senderID, senderNonce, mt.Tx.Nonce, mt.currentSubPool)) + logger.Info("TX TRACING: onSenderStateChange loop iteration remove", "idHash", fmt.Sprintf("%x", mt.Tx.IDHash), "senderID", senderID, "senderNonce", senderNonce, "txn.nonce", mt.Tx.Nonce, "currentSubPool", mt.currentSubPool, "reason", deleteAndContinueReasonLog) } // del from sub-pool switch mt.currentSubPool { case PendingSubPool: - pending.Remove(mt) + p.pending.Remove(mt, deleteAndContinueReasonLog, p.logger) case BaseFeeSubPool: - baseFee.Remove(mt) + p.baseFee.Remove(mt, deleteAndContinueReasonLog, p.logger) case QueuedSubPool: - queued.Remove(mt) + p.queued.Remove(mt, deleteAndContinueReasonLog, p.logger) default: //already removed } @@ -1605,60 +1609,62 @@ func onSenderStateChange(senderID uint64, senderNonce uint64, senderBalance uint } if mt.Tx.Traced { - logger.Info(fmt.Sprintf("TX TRACING: onSenderStateChange loop iteration idHash=%x senderId=%d subPool=%b", mt.Tx.IDHash, mt.Tx.SenderID, mt.subPool)) + logger.Info("TX TRACING: onSenderStateChange loop iteration update", "idHash", fmt.Sprintf("%x", mt.Tx.IDHash), "senderId", mt.Tx.SenderID, "nonce", mt.Tx.Nonce, "subPool", mt.currentSubPool) } // Some fields of mt might have changed, need to fix the invariants in the subpool best and worst queues switch mt.currentSubPool { case PendingSubPool: - pending.Updated(mt) + p.pending.Updated(mt) case BaseFeeSubPool: - baseFee.Updated(mt) + p.baseFee.Updated(mt) case QueuedSubPool: - queued.Updated(mt) + p.queued.Updated(mt) } return true }) + for _, mt := range toDel { - discard(mt, txpoolcfg.NonceTooLow) + p.discardLocked(mt, txpoolcfg.NonceTooLow) } + + logger.Trace("[txpool] onSenderStateChange", "sender", senderID, "count", p.all.count(senderID), "pending", p.pending.Len(), "baseFee", p.baseFee.Len(), "queued", p.queued.Len()) } // promote reasserts invariants of the subpool and returns the list of transactions that ended up // being promoted to the pending or basefee pool, for re-broadcasting -func promote(pending *PendingPool, baseFee, queued *SubPool, pendingBaseFee uint64, pendingBlobFee uint64, discard func(*metaTx, txpoolcfg.DiscardReason), announcements *types.Announcements, - logger log.Logger) { +func (p *TxPool) promote(pendingBaseFee uint64, pendingBlobFee uint64, announcements *types.Announcements, logger log.Logger) { // Demote worst transactions that do not qualify for pending sub pool anymore, to other sub pools, or discard - for worst := pending.Worst(); pending.Len() > 0 && (worst.subPool < BaseFeePoolBits || worst.minFeeCap.LtUint64(pendingBaseFee) || (worst.Tx.Type == types.BlobTxType && worst.Tx.BlobFeeCap.LtUint64(pendingBlobFee))); worst = pending.Worst() { + for worst := p.pending.Worst(); p.pending.Len() > 0 && (worst.subPool < BaseFeePoolBits || worst.minFeeCap.LtUint64(pendingBaseFee) || (worst.Tx.Type == types.BlobTxType && worst.Tx.BlobFeeCap.LtUint64(pendingBlobFee))); worst = p.pending.Worst() { if worst.subPool >= BaseFeePoolBits { - tx := pending.PopWorst() + tx := p.pending.PopWorst() announcements.Append(tx.Tx.Type, tx.Tx.Size, tx.Tx.IDHash[:]) - baseFee.Add(tx, logger) + p.baseFee.Add(tx, "demote-pending", logger) } else { - queued.Add(pending.PopWorst(), logger) + p.queued.Add(p.pending.PopWorst(), "demote-pending", logger) } } // Promote best transactions from base fee pool to pending pool while they qualify - for best := baseFee.Best(); baseFee.Len() > 0 && best.subPool >= BaseFeePoolBits && best.minFeeCap.CmpUint64(pendingBaseFee) >= 0 && (best.Tx.Type != types.BlobTxType || best.Tx.BlobFeeCap.CmpUint64(pendingBlobFee) >= 0); best = baseFee.Best() { - tx := baseFee.PopBest() + for best := p.baseFee.Best(); p.baseFee.Len() > 0 && best.subPool >= BaseFeePoolBits && best.minFeeCap.CmpUint64(pendingBaseFee) >= 0 && (best.Tx.Type != types.BlobTxType || best.Tx.BlobFeeCap.CmpUint64(pendingBlobFee) >= 0); best = p.baseFee.Best() { + tx := p.baseFee.PopBest() announcements.Append(tx.Tx.Type, tx.Tx.Size, tx.Tx.IDHash[:]) - pending.Add(tx, logger) + p.pending.Add(tx, logger) } // Demote worst transactions that do not qualify for base fee pool anymore, to queued sub pool, or discard - for worst := baseFee.Worst(); baseFee.Len() > 0 && worst.subPool < BaseFeePoolBits; worst = baseFee.Worst() { - queued.Add(baseFee.PopWorst(), logger) + for worst := p.baseFee.Worst(); p.baseFee.Len() > 0 && worst.subPool < BaseFeePoolBits; worst = p.baseFee.Worst() { + p.queued.Add(p.baseFee.PopWorst(), "demote-base", logger) } // Promote best transactions from the queued pool to either pending or base fee pool, while they qualify - for best := queued.Best(); queued.Len() > 0 && best.subPool >= BaseFeePoolBits; best = queued.Best() { + for best := p.queued.Best(); p.queued.Len() > 0 && best.subPool >= BaseFeePoolBits; best = p.queued.Best() { if best.minFeeCap.Cmp(uint256.NewInt(pendingBaseFee)) >= 0 { - tx := queued.PopBest() + tx := p.queued.PopBest() announcements.Append(tx.Tx.Type, tx.Tx.Size, tx.Tx.IDHash[:]) - pending.Add(tx, logger) + p.pending.Add(tx, logger) } else { - baseFee.Add(queued.PopBest(), logger) + p.baseFee.Add(p.queued.PopBest(), "promote-queued", logger) } } @@ -1666,18 +1672,18 @@ func promote(pending *PendingPool, baseFee, queued *SubPool, pendingBaseFee uint // // Discard worst transactions from pending pool until it is within capacity limit - for pending.Len() > pending.limit { - discard(pending.PopWorst(), txpoolcfg.PendingPoolOverflow) + for p.pending.Len() > p.pending.limit { + p.discardLocked(p.pending.PopWorst(), txpoolcfg.PendingPoolOverflow) } // Discard worst transactions from pending sub pool until it is within capacity limits - for baseFee.Len() > baseFee.limit { - discard(baseFee.PopWorst(), txpoolcfg.BaseFeePoolOverflow) + for p.baseFee.Len() > p.baseFee.limit { + p.discardLocked(p.baseFee.PopWorst(), txpoolcfg.BaseFeePoolOverflow) } // Discard worst transactions from the queued sub pool until it is within its capacity limits - for _ = queued.Worst(); queued.Len() > queued.limit; _ = queued.Worst() { - discard(queued.PopWorst(), txpoolcfg.QueuedPoolOverflow) + for _ = p.queued.Worst(); p.queued.Len() > p.queued.limit; _ = p.queued.Worst() { + p.discardLocked(p.queued.PopWorst(), txpoolcfg.QueuedPoolOverflow) } } @@ -2091,8 +2097,8 @@ func (p *TxPool) fromDB(ctx context.Context, tx kv.Tx, coreTx kv.Tx) error { if err != nil { return err } - if _, _, err := addTxs(p.lastSeenBlock.Load(), cacheView, p.senders, txs, - pendingBaseFee, pendingBlobFee, math.MaxUint64 /* blockGasLimit */, p.pending, p.baseFee, p.queued, p.all, p.byHash, p.addLocked, p.discardLocked, false, p.logger); err != nil { + if _, _, err := p.addTxs(p.lastSeenBlock.Load(), cacheView, p.senders, txs, + pendingBaseFee, pendingBlobFee, math.MaxUint64 /* blockGasLimit */, false, p.logger); err != nil { return err } p.pendingBaseFee.Store(pendingBaseFee) @@ -2288,6 +2294,11 @@ func (sc *sendersBatch) getID(addr common.Address) (uint64, bool) { } func (sc *sendersBatch) getOrCreateID(addr common.Address, logger log.Logger) (uint64, bool) { _, traced := sc.tracedSenders[addr] + + if !traced { + traced = TraceAll + } + id, ok := sc.senderIDs[addr] if !ok { sc.senderID++ @@ -2371,11 +2382,13 @@ func (b *BySenderAndNonce) nonce(senderID uint64) (nonce uint64, ok bool) { }) return nonce, ok } + func (b *BySenderAndNonce) ascendAll(f func(*metaTx) bool) { b.tree.Ascend(func(mt *metaTx) bool { return f(mt) }) } + func (b *BySenderAndNonce) ascend(senderID uint64, f func(*metaTx) bool) { s := b.search s.Tx.SenderID = senderID @@ -2387,6 +2400,7 @@ func (b *BySenderAndNonce) ascend(senderID uint64, f func(*metaTx) bool) { return f(mt) }) } + func (b *BySenderAndNonce) descend(senderID uint64, f func(*metaTx) bool) { s := b.search s.Tx.SenderID = senderID @@ -2398,12 +2412,15 @@ func (b *BySenderAndNonce) descend(senderID uint64, f func(*metaTx) bool) { return f(mt) }) } + func (b *BySenderAndNonce) count(senderID uint64) int { return b.senderIDTxnCount[senderID] } + func (b *BySenderAndNonce) blobCount(senderID uint64) uint64 { return b.senderIDBlobCount[senderID] } + func (b *BySenderAndNonce) hasTxs(senderID uint64) bool { has := false b.ascend(senderID, func(*metaTx) bool { @@ -2412,6 +2429,7 @@ func (b *BySenderAndNonce) hasTxs(senderID uint64) bool { }) return has } + func (b *BySenderAndNonce) get(senderID, txNonce uint64) *metaTx { s := b.search s.Tx.SenderID = senderID @@ -2426,8 +2444,13 @@ func (b *BySenderAndNonce) get(senderID, txNonce uint64) *metaTx { func (b *BySenderAndNonce) has(mt *metaTx) bool { return b.tree.Has(mt) } -func (b *BySenderAndNonce) delete(mt *metaTx) { + +func (b *BySenderAndNonce) delete(mt *metaTx, reason txpoolcfg.DiscardReason, logger log.Logger) { if _, ok := b.tree.Delete(mt); ok { + if mt.Tx.Traced { + logger.Info("TX TRACING: Deleted tx by nonce", "idHash", fmt.Sprintf("%x", mt.Tx.IDHash), "sender", mt.Tx.SenderID, "nonce", mt.Tx.Nonce, "reason", reason) + } + senderID := mt.Tx.SenderID count := b.senderIDTxnCount[senderID] if count > 1 { @@ -2447,11 +2470,21 @@ func (b *BySenderAndNonce) delete(mt *metaTx) { } } } -func (b *BySenderAndNonce) replaceOrInsert(mt *metaTx) *metaTx { + +func (b *BySenderAndNonce) replaceOrInsert(mt *metaTx, logger log.Logger) *metaTx { it, ok := b.tree.ReplaceOrInsert(mt) + if ok { + if mt.Tx.Traced { + logger.Info("TX TRACING: Replaced tx by nonce", "idHash", fmt.Sprintf("%x", mt.Tx.IDHash), "sender", mt.Tx.SenderID, "nonce", mt.Tx.Nonce) + } return it } + + if mt.Tx.Traced { + logger.Info("TX TRACING: Inserted tx by nonce", "idHash", fmt.Sprintf("%x", mt.Tx.IDHash), "sender", mt.Tx.SenderID, "nonce", mt.Tx.Nonce) + } + b.senderIDTxnCount[mt.Tx.SenderID]++ if mt.Tx.Type == types.BlobTxType && mt.Tx.Blobs != nil { b.senderIDBlobCount[mt.Tx.SenderID] += uint64(len(mt.Tx.Blobs)) @@ -2530,7 +2563,10 @@ func (p *PendingPool) Updated(mt *metaTx) { } func (p *PendingPool) Len() int { return len(p.best.ms) } -func (p *PendingPool) Remove(i *metaTx) { +func (p *PendingPool) Remove(i *metaTx, reason string, logger log.Logger) { + if i.Tx.Traced { + logger.Info(fmt.Sprintf("TX TRACING: removed from subpool %s", p.t), "idHash", fmt.Sprintf("%x", i.Tx.IDHash), "sender", i.Tx.SenderID, "nonce", i.Tx.Nonce, "reason", reason) + } if i.worstIndex >= 0 { heap.Remove(p.worst, i.worstIndex) } @@ -2542,7 +2578,7 @@ func (p *PendingPool) Remove(i *metaTx) { func (p *PendingPool) Add(i *metaTx, logger log.Logger) { if i.Tx.Traced { - logger.Info(fmt.Sprintf("TX TRACING: moved to subpool %s, IdHash=%x, sender=%d", p.t, i.Tx.IDHash, i.Tx.SenderID)) + logger.Info(fmt.Sprintf("TX TRACING: added to subpool %s, IdHash=%x, sender=%d, nonce=%d", p.t, i.Tx.IDHash, i.Tx.SenderID, i.Tx.Nonce)) } i.currentSubPool = p.t heap.Push(p.worst, i) @@ -2595,16 +2631,19 @@ func (p *SubPool) PopWorst() *metaTx { //nolint return i } func (p *SubPool) Len() int { return p.best.Len() } -func (p *SubPool) Add(i *metaTx, logger log.Logger) { +func (p *SubPool) Add(i *metaTx, reason string, logger log.Logger) { if i.Tx.Traced { - logger.Info(fmt.Sprintf("TX TRACING: moved to subpool %s, IdHash=%x, sender=%d", p.t, i.Tx.IDHash, i.Tx.SenderID)) + logger.Info(fmt.Sprintf("TX TRACING: added to subpool %s", p.t), "idHash", fmt.Sprintf("%x", i.Tx.IDHash), "sender", i.Tx.SenderID, "nonce", i.Tx.Nonce, "reason", reason) } i.currentSubPool = p.t heap.Push(p.best, i) heap.Push(p.worst, i) } -func (p *SubPool) Remove(i *metaTx) { +func (p *SubPool) Remove(i *metaTx, reason string, logger log.Logger) { + if i.Tx.Traced { + logger.Info(fmt.Sprintf("TX TRACING: removed from subpool %s", p.t), "idHash", fmt.Sprintf("%x", i.Tx.IDHash), "sender", i.Tx.SenderID, "nonce", i.Tx.Nonce, "reason", reason) + } heap.Remove(p.best, i.bestIndex) heap.Remove(p.worst, i.worstIndex) i.currentSubPool = 0 diff --git a/eth/backend.go b/eth/backend.go index 105092b37cd..bc95f34f10e 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -1145,7 +1145,7 @@ func (s *Ethereum) StartMining(ctx context.Context, db kv.RwDB, stateDiffClient select { case stateChanges := <-stateChangeCh: block := stateChanges.BlockHeight - s.logger.Debug("Start mining new block based on previous block", "block", block) + s.logger.Debug("Start mining based on previous block", "block", block) // TODO - can do mining clean up here as we have previous // block info in the state channel hasWork = true @@ -1154,11 +1154,11 @@ func (s *Ethereum) StartMining(ctx context.Context, db kv.RwDB, stateDiffClient // Skip mining based on new tx notif for bor consensus hasWork = s.chainConfig.Bor == nil if hasWork { - s.logger.Debug("Start mining new block based on txpool notif") + s.logger.Debug("Start mining based on txpool notif") } case <-mineEvery.C: if !(working || waiting.Load()) { - s.logger.Debug("Start mining new block based on miner.recommit", "duration", miner.MiningConfig.Recommit) + s.logger.Debug("Start mining based on miner.recommit", "duration", miner.MiningConfig.Recommit) } hasWork = !(working || waiting.Load()) case err := <-errc: diff --git a/eth/stagedsync/stage_bor_heimdall.go b/eth/stagedsync/stage_bor_heimdall.go index 65cff408691..5c7bef88a11 100644 --- a/eth/stagedsync/stage_bor_heimdall.go +++ b/eth/stagedsync/stage_bor_heimdall.go @@ -192,6 +192,7 @@ func BorHeimdallForward( defer logTimer.Stop() logger.Info("["+s.LogPrefix()+"] Processing sync events...", "from", lastBlockNum+1, "to", headNumber) + for blockNum = lastBlockNum + 1; blockNum <= headNumber; blockNum++ { select { default: From 9a9808f715e1d5f4db31cdb0bbbd82834e4fcbd0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Jan 2024 11:45:36 +0100 Subject: [PATCH 43/92] build(deps): bump github.com/quic-go/quic-go from 0.38.1 to 0.38.2 (#9196) Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.38.1 to 0.38.2.
Release notes

Sourced from github.com/quic-go/quic-go's releases.

v0.38.2

This release contains fixes for a resource exhaustion attack on QUIC's path validation logic (CVE-2023-49295), see https://seemann.io/posts/2023-12-18-exploiting-quics-path-validation for details:

Full Changelog: https://github.com/quic-go/quic-go/compare/v0.38.1...v0.38.2

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/quic-go/quic-go&package-manager=go_modules&previous-version=0.38.1&new-version=0.38.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/ledgerwatch/erigon/network/alerts).
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1119355e12e..72a8eabe164 100644 --- a/go.mod +++ b/go.mod @@ -248,7 +248,7 @@ require ( github.com/prometheus/procfs v0.12.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qtls-go1-20 v0.3.3 // indirect - github.com/quic-go/quic-go v0.38.1 // indirect + github.com/quic-go/quic-go v0.38.2 // indirect github.com/quic-go/webtransport-go v0.5.3 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect diff --git a/go.sum b/go.sum index 90a5e4fe9d1..7f9367050e6 100644 --- a/go.sum +++ b/go.sum @@ -778,8 +778,8 @@ github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= github.com/quic-go/qtls-go1-20 v0.3.3 h1:17/glZSLI9P9fDAeyCHBFSWSqJcwx1byhLwP5eUIDCM= github.com/quic-go/qtls-go1-20 v0.3.3/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= -github.com/quic-go/quic-go v0.38.1 h1:M36YWA5dEhEeT+slOu/SwMEucbYd0YFidxG3KlGPZaE= -github.com/quic-go/quic-go v0.38.1/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4= +github.com/quic-go/quic-go v0.38.2 h1:VWv/6gxIoB8hROQJhx1JEyiegsUQ+zMN3em3kynTGdg= +github.com/quic-go/quic-go v0.38.2/go.mod h1:ijnZM7JsFIkp4cRyjxJNIzdSfCLmUMg9wdyhGmg+SN4= github.com/quic-go/webtransport-go v0.5.3 h1:5XMlzemqB4qmOlgIus5zB45AcZ2kCgCy2EptUrfOPWU= github.com/quic-go/webtransport-go v0.5.3/go.mod h1:OhmmgJIzTTqXK5xvtuX0oBpLV2GkLWNDA+UeTGJXErU= github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= From 04498180dcbb66ec5ceb96662cf0ebe73d8c60b3 Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Thu, 11 Jan 2024 16:04:46 +0100 Subject: [PATCH 44/92] p2p/discv4: revert gotreply handler change from #8661 (#9119) (#9195) The handler had race conditions in the candidates processing goroutine. --- p2p/discover/v4_udp.go | 79 ++++++++++-------------------------------- 1 file changed, 18 insertions(+), 61 deletions(-) diff --git a/p2p/discover/v4_udp.go b/p2p/discover/v4_udp.go index bc665d0a1c3..deb4427a7a7 100644 --- a/p2p/discover/v4_udp.go +++ b/p2p/discover/v4_udp.go @@ -29,12 +29,13 @@ import ( "time" lru "github.com/hashicorp/golang-lru/v2" + "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon/common/debug" "github.com/ledgerwatch/erigon/crypto" "github.com/ledgerwatch/erigon/p2p/discover/v4wire" "github.com/ledgerwatch/erigon/p2p/enode" "github.com/ledgerwatch/erigon/p2p/netutil" - "github.com/ledgerwatch/log/v3" ) // Errors @@ -610,74 +611,30 @@ func (t *UDPv4) loop() { }() case r := <-t.gotreply: - - type matchCandidate struct { - el *list.Element - errc chan error - } - - var matchCandidates []matchCandidate - - mutex.Lock() - for el := plist.Front(); el != nil; el = el.Next() { - p := el.Value.(*replyMatcher) - if p.from == r.from && p.ptype == r.data.Kind() && p.ip.Equal(r.ip) { - candidate := matchCandidate{el, p.errc} - p.errc = make(chan error, 1) - matchCandidates = append(matchCandidates, candidate) - } - } - mutex.Unlock() - - if len(matchCandidates) == 0 { - // if there are no matched candidates try again matching against - // ip & port to handle node key changes + func() { mutex.Lock() - for el := plist.Front(); el != nil; el = el.Next() { - p := el.Value.(*replyMatcher) - if p.ptype == r.data.Kind() && p.ip.Equal(r.ip) && p.port == r.port { - candidate := matchCandidate{el, p.errc} - p.errc = make(chan error, 1) - matchCandidates = append(matchCandidates, candidate) - } - } - mutex.Unlock() - - if len(matchCandidates) == 0 { - r.matched <- false - } - } + defer mutex.Unlock() - go func(r reply) { var matched bool // whether any replyMatcher considered the reply acceptable. - for _, candidate := range matchCandidates { - p := candidate.el.Value.(*replyMatcher) - ok, requestDone := p.callback(r.data) - matched = matched || ok - p.reply = r.data - - // Remove the matcher if callback indicates that all replies have been received. - if requestDone { - mutex.Lock() - plist.Remove(candidate.el) - mutex.Unlock() - candidate.errc <- nil - listUpdate <- candidate.el - } else { - select { - case err := <-p.errc: - candidate.errc <- err - default: - p.errc = candidate.errc + for el := plist.Front(); el != nil; el = el.Next() { + p := el.Value.(*replyMatcher) + if (p.ptype == r.data.Kind()) && p.ip.Equal(r.ip) && (p.port == r.port) { + ok, requestDone := p.callback(r.data) + matched = matched || ok + p.reply = r.data + // Remove the matcher if callback indicates that all replies have been received. + if requestDone { + p.errc <- nil + plist.Remove(el) + listUpdate <- el } + // Reset the continuous timeout counter (time drift detection) + contTimeouts = 0 } } - r.matched <- matched - }(r) + }() - // Reset the continuous timeout counter (time drift detection) - contTimeouts = 0 case key := <-t.gotkey: go func() { if key, err := v4wire.DecodePubkey(crypto.S256(), key); err == nil { From c1e3ec59afe2ead088ede4256294d9fe1312f434 Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Thu, 11 Jan 2024 16:42:11 +0100 Subject: [PATCH 45/92] deps: upgrade go-multiaddr to v0.12.1 (#9208) --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 72a8eabe164..86952bf1d78 100644 --- a/go.mod +++ b/go.mod @@ -64,7 +64,7 @@ require ( github.com/libp2p/go-libp2p-pubsub v0.9.3 github.com/maticnetwork/crand v1.0.2 github.com/maticnetwork/polyproto v0.0.3-0.20230216113155-340ea926ca53 - github.com/multiformats/go-multiaddr v0.11.0 + github.com/multiformats/go-multiaddr v0.12.1 github.com/nxadm/tail v1.4.9-0.20211216163028-4472660a31a6 github.com/pelletier/go-toml v1.9.5 github.com/pelletier/go-toml/v2 v2.1.0 diff --git a/go.sum b/go.sum index 7f9367050e6..386b04a07d7 100644 --- a/go.sum +++ b/go.sum @@ -635,8 +635,8 @@ github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9 github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4= github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo= github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4= -github.com/multiformats/go-multiaddr v0.11.0 h1:XqGyJ8ufbCE0HmTDwx2kPdsrQ36AGPZNZX6s6xfJH10= -github.com/multiformats/go-multiaddr v0.11.0/go.mod h1:gWUm0QLR4thQ6+ZF6SXUw8YjtwQSPapICM+NmCkxHSM= +github.com/multiformats/go-multiaddr v0.12.1 h1:vm+BA/WZA8QZDp1pF1FWhi5CT3g1tbi5GJmqpb6wnlk= +github.com/multiformats/go-multiaddr v0.12.1/go.mod h1:7mPkiBMmLeFipt+nNSq9pHZUeJSt8lHBgH6yhj0YQzE= github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A= github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk= github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E= From 8315033a92a68faccf463255c05cc90b51552c99 Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Thu, 11 Jan 2024 20:05:54 +0100 Subject: [PATCH 46/92] Added more checks on state reconstruction + made history reconstruction resumable. (#9211) Co-authored-by: Bayram Guvanjov --- cl/antiquary/state_antiquary.go | 9 +++-- cl/phase1/forkchoice/checkpoint_state.go | 2 +- cl/transition/impl/eth2/operations.go | 44 +++++++++++------------- 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/cl/antiquary/state_antiquary.go b/cl/antiquary/state_antiquary.go index d4d3da32e5a..c4b55bf8787 100644 --- a/cl/antiquary/state_antiquary.go +++ b/cl/antiquary/state_antiquary.go @@ -360,9 +360,11 @@ func (s *Antiquary) IncrementBeaconState(ctx context.Context, to uint64) error { defer progressTimer.Stop() prevSlot := slot first := false + blocksBeforeCommit := 100_000 + blocksProcessed := 0 // This tells us that transition and operations do not happen concurrently and access is safe, so we can optimize for GC. // there is optimized custom cache to recycle big GC overhead. - for ; slot < to; slot++ { + for ; slot < to && blocksProcessed < blocksBeforeCommit; slot++ { slashingOccured = false // Set this to false at the beginning of each slot. key := base_encoding.Encode64ToBytes4(slot) @@ -418,12 +420,13 @@ func (s *Antiquary) IncrementBeaconState(ctx context.Context, to uint64) error { prevValSet = prevValSet[:0] prevValSet = append(prevValSet, s.currentState.RawValidatorSet()...) - fullValidation := slot%100_000 == 0 || first + fullValidation := slot%1000 == 0 || first blockRewardsCollector := ð2.BlockRewardsCollector{} - // We sanity check the state every 100k slots or when we start. + // We sanity check the state every 1k slots or when we start. if err := transition.TransitionState(s.currentState, block, blockRewardsCollector, fullValidation); err != nil { return err } + blocksProcessed++ first = false diff --git a/cl/phase1/forkchoice/checkpoint_state.go b/cl/phase1/forkchoice/checkpoint_state.go index e5937fc3cc5..ba992c6d15f 100644 --- a/cl/phase1/forkchoice/checkpoint_state.go +++ b/cl/phase1/forkchoice/checkpoint_state.go @@ -166,7 +166,7 @@ func (c *checkpointState) isValidIndexedAttestation(att *cltypes.IndexedAttestat pks := [][]byte{} inds.Range(func(_ int, v uint64, _ int) bool { - if v < uint64(len(c.anchorPublicKeys)) { + if v < uint64(len(c.anchorPublicKeys))/length.Bytes48 { pks = append(pks, c.anchorPublicKeys[v*length.Bytes48:(v+1)*length.Bytes48]) } else { offset := uint64(len(c.anchorPublicKeys) / length.Bytes48) diff --git a/cl/transition/impl/eth2/operations.go b/cl/transition/impl/eth2/operations.go index 1f8c5b917a3..0650a1c1c0b 100644 --- a/cl/transition/impl/eth2/operations.go +++ b/cl/transition/impl/eth2/operations.go @@ -114,7 +114,7 @@ func (I *impl) ProcessAttesterSlashing(s abstract.BeaconState, attSlashing *clty if validator.IsSlashable(currentEpoch) { pr, err := s.SlashValidator(ind, nil) if err != nil { - return fmt.Errorf("unable to slash validator: %d", ind) + return fmt.Errorf("unable to slash validator: %d: %s", ind, err) } if I.BlockRewardsCollector != nil { I.BlockRewardsCollector.AttesterSlashings += pr @@ -755,28 +755,26 @@ func batchVerifyAttestations(s abstract.BeaconState, indexedAttestations []*clty } func (I *impl) ProcessBlockHeader(s abstract.BeaconState, block *cltypes.BeaconBlock) error { - if I.FullValidation { - if block.Slot != s.Slot() { - return fmt.Errorf("state slot: %d, not equal to block slot: %d", s.Slot(), block.Slot) - } - if block.Slot <= s.LatestBlockHeader().Slot { - return fmt.Errorf("slock slot: %d, not greater than latest block slot: %d", block.Slot, s.LatestBlockHeader().Slot) - } - propInd, err := s.GetBeaconProposerIndex() - if err != nil { - return fmt.Errorf("error in GetBeaconProposerIndex: %v", err) - } - if block.ProposerIndex != propInd { - return fmt.Errorf("block proposer index: %d, does not match beacon proposer index: %d", block.ProposerIndex, propInd) - } - blockHeader := s.LatestBlockHeader() - latestRoot, err := (&blockHeader).HashSSZ() - if err != nil { - return fmt.Errorf("unable to hash tree root of latest block header: %v", err) - } - if block.ParentRoot != latestRoot { - return fmt.Errorf("block parent root: %x, does not match latest block root: %x", block.ParentRoot, latestRoot) - } + if block.Slot != s.Slot() { + return fmt.Errorf("state slot: %d, not equal to block slot: %d", s.Slot(), block.Slot) + } + if block.Slot <= s.LatestBlockHeader().Slot { + return fmt.Errorf("slock slot: %d, not greater than latest block slot: %d", block.Slot, s.LatestBlockHeader().Slot) + } + propInd, err := s.GetBeaconProposerIndex() + if err != nil { + return fmt.Errorf("error in GetBeaconProposerIndex: %v", err) + } + if block.ProposerIndex != propInd { + return fmt.Errorf("block proposer index: %d, does not match beacon proposer index: %d", block.ProposerIndex, propInd) + } + blockHeader := s.LatestBlockHeader() + latestRoot, err := (&blockHeader).HashSSZ() + if err != nil { + return fmt.Errorf("unable to hash tree root of latest block header: %v", err) + } + if block.ParentRoot != latestRoot { + return fmt.Errorf("block parent root: %x, does not match latest block root: %x", block.ParentRoot, latestRoot) } bodyRoot, err := block.Body.HashSSZ() From 66cd4e71fa2f2abcc40c0b8bd7435d13d86f9a98 Mon Sep 17 00:00:00 2001 From: Mark Holt <135143369+mh0lt@users.noreply.github.com> Date: Thu, 11 Jan 2024 21:15:26 +0000 Subject: [PATCH 47/92] Mumbai uploader regression fixes (#9212) This fixes a couple of regressions for running the uploader for mumbai * Now flags have moved to a higher context they need to be set in the context not the flag values * Span 0 of mumbai has a header/span mismatch for span zero sprint 0. So the check here needs to be suppressed --- eth/stagedsync/stage_bor_heimdall.go | 6 +++++- turbo/app/snapshots_cmd.go | 26 ++++++++++++++++++-------- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/eth/stagedsync/stage_bor_heimdall.go b/eth/stagedsync/stage_bor_heimdall.go index 5c7bef88a11..c7edacb36ff 100644 --- a/eth/stagedsync/stage_bor_heimdall.go +++ b/eth/stagedsync/stage_bor_heimdall.go @@ -559,7 +559,11 @@ func checkBorHeaderExtraData(chr consensus.ChainHeaderReader, header *types.Head return err } - if len(producerSet) != len(headerVals) { + // span 0 at least for mumbai has a header mismatch in + // its first spam. Since we control neither the span, not the + // the headers (they are external data) - we just don't do the + // check as it will hault further processing + if len(producerSet) != len(headerVals) && spanID > 0 { return ErrHeaderValidatorsLengthMismatch } diff --git a/turbo/app/snapshots_cmd.go b/turbo/app/snapshots_cmd.go index 11ea10b1d53..c4419b11444 100644 --- a/turbo/app/snapshots_cmd.go +++ b/turbo/app/snapshots_cmd.go @@ -101,14 +101,24 @@ var snapshotCommand = cli.Command{ &erigoncli.UploadFromFlag, &erigoncli.FrozenBlockLimitFlag, }), - Before: func(context *cli.Context) error { - erigoncli.SyncLoopBreakAfterFlag.Value = "Senders" - erigoncli.SyncLoopBlockLimitFlag.Value = 100000 - erigoncli.SyncLoopPruneLimitFlag.Value = 100000 - erigoncli.FrozenBlockLimitFlag.Value = 1500000 - utils.NoDownloaderFlag.Value = true - utils.HTTPEnabledFlag.Value = false - utils.TxPoolDisableFlag.Value = true + Before: func(ctx *cli.Context) error { + ctx.Set(erigoncli.SyncLoopBreakAfterFlag.Name, "Senders") + ctx.Set(utils.NoDownloaderFlag.Name, "true") + ctx.Set(utils.HTTPEnabledFlag.Name, "false") + ctx.Set(utils.TxPoolDisableFlag.Name, "true") + + if !ctx.IsSet(erigoncli.SyncLoopBlockLimitFlag.Name) { + ctx.Set(erigoncli.SyncLoopBlockLimitFlag.Name, "100000") + } + + if !ctx.IsSet(erigoncli.FrozenBlockLimitFlag.Name) { + ctx.Set(erigoncli.FrozenBlockLimitFlag.Name, "1500000") + } + + if !ctx.IsSet(erigoncli.SyncLoopPruneLimitFlag.Name) { + ctx.Set(erigoncli.SyncLoopPruneLimitFlag.Name, "100000") + } + return nil }, }, From 3bb1917e8a68a107924f810a6e03b1a432316666 Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Fri, 12 Jan 2024 17:26:20 +0700 Subject: [PATCH 48/92] recsplit: reduce ram pressure (#9218) reasons: - indexing done in background (or in many workers) - `recsplit` has 2 etl collectors --- erigon-lib/recsplit/recsplit.go | 6 ++- erigon-lib/state/history.go | 13 +++--- .../freezeblocks/block_snapshots.go | 46 +++++++++---------- 3 files changed, 32 insertions(+), 33 deletions(-) diff --git a/erigon-lib/recsplit/recsplit.go b/erigon-lib/recsplit/recsplit.go index fc41a824c9b..be44bd20f48 100644 --- a/erigon-lib/recsplit/recsplit.go +++ b/erigon-lib/recsplit/recsplit.go @@ -161,7 +161,11 @@ func NewRecSplit(args RecSplitArgs, logger log.Logger) (*RecSplit, error) { rs.baseDataID = args.BaseDataID rs.etlBufLimit = args.EtlBufLimit if rs.etlBufLimit == 0 { - rs.etlBufLimit = etl.BufferOptimalSize + // reduce ram pressure, because: + // - indexing done in background or in many workers (building many indices in-parallel) + // - `recsplit` has 2 etl collectors + // - `rescplit` building is cpu-intencive and bottleneck is not in etl loading + rs.etlBufLimit = etl.BufferOptimalSize / 8 } rs.bucketCollector = etl.NewCollector(RecSplitLogPrefix+" "+fname, rs.tmpDir, etl.NewSortableBuffer(rs.etlBufLimit), logger) rs.bucketCollector.LogLvl(log.LvlDebug) diff --git a/erigon-lib/state/history.go b/erigon-lib/state/history.go index 23fad025128..ba6206d5637 100644 --- a/erigon-lib/state/history.go +++ b/erigon-lib/state/history.go @@ -406,13 +406,12 @@ func iterateForVi(historyItem, iiItem *filesItem, p *background.Progress, compre func buildVi(ctx context.Context, historyItem, iiItem *filesItem, historyIdxPath, tmpdir string, count int, p *background.Progress, compressVals bool, logger log.Logger) error { rs, err := recsplit.NewRecSplit(recsplit.RecSplitArgs{ - KeyCount: count, - Enums: false, - BucketSize: 2000, - LeafSize: 8, - TmpDir: tmpdir, - IndexFile: historyIdxPath, - EtlBufLimit: etl.BufferOptimalSize / 2, + KeyCount: count, + Enums: false, + BucketSize: 2000, + LeafSize: 8, + TmpDir: tmpdir, + IndexFile: historyIdxPath, }, logger) if err != nil { return fmt.Errorf("create recsplit: %w", err) diff --git a/turbo/snapshotsync/freezeblocks/block_snapshots.go b/turbo/snapshotsync/freezeblocks/block_snapshots.go index 200d0bee576..d67457acbf9 100644 --- a/turbo/snapshotsync/freezeblocks/block_snapshots.go +++ b/turbo/snapshotsync/freezeblocks/block_snapshots.go @@ -35,7 +35,6 @@ import ( "github.com/ledgerwatch/erigon-lib/compress" "github.com/ledgerwatch/erigon-lib/diagnostics" "github.com/ledgerwatch/erigon-lib/downloader/snaptype" - "github.com/ledgerwatch/erigon-lib/etl" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/recsplit" types2 "github.com/ledgerwatch/erigon-lib/types" @@ -2173,28 +2172,26 @@ func TransactionsIdx(ctx context.Context, chainConfig *chain.Config, version uin } txnHashIdx, err := recsplit.NewRecSplit(recsplit.RecSplitArgs{ - KeyCount: d.Count(), - Enums: true, - BucketSize: 2000, - LeafSize: 8, - TmpDir: tmpDir, - IndexFile: filepath.Join(snapDir, snaptype.IdxFileName(version, blockFrom, blockTo, snaptype.Transactions.String())), - BaseDataID: firstTxID, - EtlBufLimit: etl.BufferOptimalSize / 2, + KeyCount: d.Count(), + Enums: true, + BucketSize: 2000, + LeafSize: 8, + TmpDir: tmpDir, + IndexFile: filepath.Join(snapDir, snaptype.IdxFileName(version, blockFrom, blockTo, snaptype.Transactions.String())), + BaseDataID: firstTxID, }, logger) if err != nil { return err } txnHash2BlockNumIdx, err := recsplit.NewRecSplit(recsplit.RecSplitArgs{ - KeyCount: d.Count(), - Enums: false, - BucketSize: 2000, - LeafSize: 8, - TmpDir: tmpDir, - IndexFile: filepath.Join(snapDir, snaptype.IdxFileName(version, blockFrom, blockTo, snaptype.Transactions2Block.String())), - BaseDataID: firstBlockNum, - EtlBufLimit: etl.BufferOptimalSize / 2, + KeyCount: d.Count(), + Enums: false, + BucketSize: 2000, + LeafSize: 8, + TmpDir: tmpDir, + IndexFile: filepath.Join(snapDir, snaptype.IdxFileName(version, blockFrom, blockTo, snaptype.Transactions2Block.String())), + BaseDataID: firstBlockNum, }, logger) if err != nil { return err @@ -2382,14 +2379,13 @@ func Idx(ctx context.Context, d *compress.Decompressor, firstDataID uint64, tmpD var idxFilePath = segmentFileName[0:len(segmentFileName)-len(extension)] + ".idx" rs, err := recsplit.NewRecSplit(recsplit.RecSplitArgs{ - KeyCount: d.Count(), - Enums: true, - BucketSize: 2000, - LeafSize: 8, - TmpDir: tmpDir, - IndexFile: idxFilePath, - BaseDataID: firstDataID, - EtlBufLimit: etl.BufferOptimalSize / 2, + KeyCount: d.Count(), + Enums: true, + BucketSize: 2000, + LeafSize: 8, + TmpDir: tmpDir, + IndexFile: idxFilePath, + BaseDataID: firstDataID, }, logger) if err != nil { return err From e806db977f1b6e59665c7414bae6dcca3beb3087 Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Fri, 12 Jan 2024 17:27:18 +0700 Subject: [PATCH 49/92] mdbx: reduce 2 times hard dplimit (#9216) can do it, because we don't do read-after-write in same rwtx --- erigon-lib/kv/mdbx/kv_mdbx.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erigon-lib/kv/mdbx/kv_mdbx.go b/erigon-lib/kv/mdbx/kv_mdbx.go index 85aeb734124..cd465b593b9 100644 --- a/erigon-lib/kv/mdbx/kv_mdbx.go +++ b/erigon-lib/kv/mdbx/kv_mdbx.go @@ -326,8 +326,8 @@ func (opts MdbxOpts) Open(ctx context.Context) (kv.RwDB, error) { } else { dirtySpace = mmap.TotalMemory() / 42 // it's default of mdbx, but our package also supports cgroups and GOMEMLIMIT // clamp to max size - const dirtySpaceMaxChainDB = uint64(2 * datasize.GB) - const dirtySpaceMaxDefault = uint64(256 * datasize.MB) + const dirtySpaceMaxChainDB = uint64(1 * datasize.GB) + const dirtySpaceMaxDefault = uint64(128 * datasize.MB) if opts.label == kv.ChainDB && dirtySpace > dirtySpaceMaxChainDB { dirtySpace = dirtySpaceMaxChainDB From fa1e1bab271c8f9ba8df749f40e0e9157bc0c4bb Mon Sep 17 00:00:00 2001 From: racytech <82003208+racytech@users.noreply.github.com> Date: Fri, 12 Jan 2024 14:42:08 +0300 Subject: [PATCH 50/92] Tests v13 fix (#9200) --- core/types/blob_tx.go | 42 +++++++++++++++++++++++++++++--- tests/testdata | 2 +- turbo/stages/mock/mock_sentry.go | 6 +++++ 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/core/types/blob_tx.go b/core/types/blob_tx.go index d2bede77c40..32547e054bf 100644 --- a/core/types/blob_tx.go +++ b/core/types/blob_tx.go @@ -1,6 +1,7 @@ package types import ( + "errors" "fmt" "io" "math/big" @@ -47,15 +48,50 @@ func (stx BlobTx) GetBlobGas() uint64 { } func (stx BlobTx) AsMessage(s Signer, baseFee *big.Int, rules *chain.Rules) (Message, error) { - msg, err := stx.DynamicFeeTransaction.AsMessage(s, baseFee, rules) - if err != nil { - return Message{}, err + msg := Message{ + nonce: stx.Nonce, + gasLimit: stx.Gas, + gasPrice: *stx.FeeCap, + tip: *stx.Tip, + feeCap: *stx.FeeCap, + to: stx.To, + amount: *stx.Value, + data: stx.Data, + accessList: stx.AccessList, + checkNonce: true, + } + if !rules.IsCancun { + return msg, errors.New("BlobTx transactions require Cancun") + } + if baseFee != nil { + overflow := msg.gasPrice.SetFromBig(baseFee) + if overflow { + return msg, fmt.Errorf("gasPrice higher than 2^256-1") + } } + msg.gasPrice.Add(&msg.gasPrice, stx.Tip) + if msg.gasPrice.Gt(stx.FeeCap) { + msg.gasPrice.Set(stx.FeeCap) + } + var err error + msg.from, err = stx.Sender(s) msg.maxFeePerBlobGas = *stx.MaxFeePerBlobGas msg.blobHashes = stx.BlobVersionedHashes return msg, err } +func (stx *BlobTx) Sender(signer Signer) (libcommon.Address, error) { + if sc := stx.from.Load(); sc != nil { + return sc.(libcommon.Address), nil + } + addr, err := signer.Sender(stx) + if err != nil { + return libcommon.Address{}, err + } + stx.from.Store(addr) + return addr, nil +} + func (stx BlobTx) Hash() libcommon.Hash { if hash := stx.hash.Load(); hash != nil { return *hash.(*libcommon.Hash) diff --git a/tests/testdata b/tests/testdata index 06e276776bc..428f218d7d6 160000 --- a/tests/testdata +++ b/tests/testdata @@ -1 +1 @@ -Subproject commit 06e276776bc87817c38f6efb492bf6f4527fa904 +Subproject commit 428f218d7d6f4a52544e12684afbfe6e2882ffbf diff --git a/turbo/stages/mock/mock_sentry.go b/turbo/stages/mock/mock_sentry.go index eb973d9d70a..14c83977729 100644 --- a/turbo/stages/mock/mock_sentry.go +++ b/turbo/stages/mock/mock_sentry.go @@ -608,6 +608,12 @@ func (ms *MockSentry) insertPoWBlocks(chain *core.ChainPack) error { return nil } + for i := 0; i < chain.Length(); i++ { + if err := chain.Blocks[i].HashCheck(); err != nil { + return err + } + } + // Send NewBlock message b, err := rlp.EncodeToBytes(ð.NewBlockPacket{ Block: chain.Blocks[n-1], From db1dcbb9d7564fe84f051b62a45cbca98bb7ff1d Mon Sep 17 00:00:00 2001 From: ddl Date: Fri, 12 Jan 2024 21:07:49 +0800 Subject: [PATCH 51/92] refactor(erigon-lib/metrics): replace strings.IndexByte with strings.Cut (#9202) above go1.18 Index calls are more clearly written using Cut. https://github.com/golang/go/issues/46336 --- erigon-lib/metrics/parsing.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/erigon-lib/metrics/parsing.go b/erigon-lib/metrics/parsing.go index 34e23ccccb2..2ae74952467 100644 --- a/erigon-lib/metrics/parsing.go +++ b/erigon-lib/metrics/parsing.go @@ -12,25 +12,24 @@ func parseMetric(s string) (string, prometheus.Labels, error) { if len(s) == 0 { return "", nil, fmt.Errorf("metric cannot be empty") } - n := strings.IndexByte(s, '{') - if n < 0 { + + ident, rest, ok := strings.Cut(s, "{") + if !ok { if err := validateIdent(s); err != nil { return "", nil, err } - return s, nil, nil } - ident := s[:n] - s = s[n+1:] + if err := validateIdent(ident); err != nil { return "", nil, err } - if len(s) == 0 || s[len(s)-1] != '}' { + + if len(rest) == 0 || rest[len(rest)-1] != '}' { return "", nil, fmt.Errorf("missing closing curly brace at the end of %q", ident) } - tags, err := parseTags(s[:len(s)-1]) - + tags, err := parseTags(rest[:len(rest)-1]) if err != nil { return "", nil, err } From 574ec8089d44b3446b4078266581c7ee23d6334c Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Fri, 12 Jan 2024 20:19:24 +0700 Subject: [PATCH 52/92] caplin state_antiqate: reduce worst case ram limit (#9217) --- cl/antiquary/state_antiquary.go | 37 +++++++++++++++++---------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/cl/antiquary/state_antiquary.go b/cl/antiquary/state_antiquary.go index c4b55bf8787..892df0a2ceb 100644 --- a/cl/antiquary/state_antiquary.go +++ b/cl/antiquary/state_antiquary.go @@ -150,41 +150,42 @@ func (s *Antiquary) IncrementBeaconState(ctx context.Context, to uint64) error { return next(k, k, v) } - effectiveBalance := etl.NewCollector(kv.ValidatorEffectiveBalance, s.dirs.Tmp, etl.NewSortableBuffer(etl.BufferOptimalSize), s.logger) + etlBufSz := etl.BufferOptimalSize / 8 // 18 collectors * 256mb / 8 = 512mb in worst case + effectiveBalance := etl.NewCollector(kv.ValidatorEffectiveBalance, s.dirs.Tmp, etl.NewSortableBuffer(etlBufSz), s.logger) defer effectiveBalance.Close() - balances := etl.NewCollector(kv.ValidatorBalance, s.dirs.Tmp, etl.NewSortableBuffer(etl.BufferOptimalSize), s.logger) + balances := etl.NewCollector(kv.ValidatorBalance, s.dirs.Tmp, etl.NewSortableBuffer(etlBufSz), s.logger) defer balances.Close() - randaoMixes := etl.NewCollector(kv.RandaoMixes, s.dirs.Tmp, etl.NewSortableBuffer(etl.BufferOptimalSize), s.logger) + randaoMixes := etl.NewCollector(kv.RandaoMixes, s.dirs.Tmp, etl.NewSortableBuffer(etlBufSz), s.logger) defer randaoMixes.Close() - intraRandaoMixes := etl.NewCollector(kv.IntraRandaoMixes, s.dirs.Tmp, etl.NewSortableBuffer(etl.BufferOptimalSize), s.logger) + intraRandaoMixes := etl.NewCollector(kv.IntraRandaoMixes, s.dirs.Tmp, etl.NewSortableBuffer(etlBufSz), s.logger) defer intraRandaoMixes.Close() - proposers := etl.NewCollector(kv.Proposers, s.dirs.Tmp, etl.NewSortableBuffer(etl.BufferOptimalSize), s.logger) + proposers := etl.NewCollector(kv.Proposers, s.dirs.Tmp, etl.NewSortableBuffer(etlBufSz), s.logger) defer proposers.Close() - slashings := etl.NewCollector(kv.ValidatorSlashings, s.dirs.Tmp, etl.NewSortableBuffer(etl.BufferOptimalSize), s.logger) + slashings := etl.NewCollector(kv.ValidatorSlashings, s.dirs.Tmp, etl.NewSortableBuffer(etlBufSz), s.logger) defer slashings.Close() - blockRoots := etl.NewCollector(kv.BlockRoot, s.dirs.Tmp, etl.NewSortableBuffer(etl.BufferOptimalSize), s.logger) + blockRoots := etl.NewCollector(kv.BlockRoot, s.dirs.Tmp, etl.NewSortableBuffer(etlBufSz), s.logger) defer blockRoots.Close() - stateRoots := etl.NewCollector(kv.StateRoot, s.dirs.Tmp, etl.NewSortableBuffer(etl.BufferOptimalSize), s.logger) + stateRoots := etl.NewCollector(kv.StateRoot, s.dirs.Tmp, etl.NewSortableBuffer(etlBufSz), s.logger) defer stateRoots.Close() - slotData := etl.NewCollector(kv.SlotData, s.dirs.Tmp, etl.NewSortableBuffer(etl.BufferOptimalSize), s.logger) + slotData := etl.NewCollector(kv.SlotData, s.dirs.Tmp, etl.NewSortableBuffer(etlBufSz), s.logger) defer slotData.Close() - epochData := etl.NewCollector(kv.EpochData, s.dirs.Tmp, etl.NewSortableBuffer(etl.BufferOptimalSize), s.logger) + epochData := etl.NewCollector(kv.EpochData, s.dirs.Tmp, etl.NewSortableBuffer(etlBufSz), s.logger) defer epochData.Close() - inactivityScoresC := etl.NewCollector(kv.InactivityScores, s.dirs.Tmp, etl.NewSortableBuffer(etl.BufferOptimalSize), s.logger) + inactivityScoresC := etl.NewCollector(kv.InactivityScores, s.dirs.Tmp, etl.NewSortableBuffer(etlBufSz), s.logger) defer inactivityScoresC.Close() - nextSyncCommittee := etl.NewCollector(kv.NextSyncCommittee, s.dirs.Tmp, etl.NewSortableBuffer(etl.BufferOptimalSize), s.logger) + nextSyncCommittee := etl.NewCollector(kv.NextSyncCommittee, s.dirs.Tmp, etl.NewSortableBuffer(etlBufSz), s.logger) defer nextSyncCommittee.Close() - currentSyncCommittee := etl.NewCollector(kv.CurrentSyncCommittee, s.dirs.Tmp, etl.NewSortableBuffer(etl.BufferOptimalSize), s.logger) + currentSyncCommittee := etl.NewCollector(kv.CurrentSyncCommittee, s.dirs.Tmp, etl.NewSortableBuffer(etlBufSz), s.logger) defer currentSyncCommittee.Close() - currentEpochAttestations := etl.NewCollector(kv.CurrentEpochAttestations, s.dirs.Tmp, etl.NewSortableBuffer(etl.BufferOptimalSize), s.logger) + currentEpochAttestations := etl.NewCollector(kv.CurrentEpochAttestations, s.dirs.Tmp, etl.NewSortableBuffer(etlBufSz), s.logger) defer currentEpochAttestations.Close() - previousEpochAttestations := etl.NewCollector(kv.PreviousEpochAttestations, s.dirs.Tmp, etl.NewSortableBuffer(etl.BufferOptimalSize), s.logger) + previousEpochAttestations := etl.NewCollector(kv.PreviousEpochAttestations, s.dirs.Tmp, etl.NewSortableBuffer(etlBufSz), s.logger) defer previousEpochAttestations.Close() - eth1DataVotes := etl.NewCollector(kv.Eth1DataVotes, s.dirs.Tmp, etl.NewSortableBuffer(etl.BufferOptimalSize), s.logger) + eth1DataVotes := etl.NewCollector(kv.Eth1DataVotes, s.dirs.Tmp, etl.NewSortableBuffer(etlBufSz), s.logger) defer eth1DataVotes.Close() - stateEvents := etl.NewCollector(kv.StateEvents, s.dirs.Tmp, etl.NewSortableBuffer(etl.BufferOptimalSize), s.logger) + stateEvents := etl.NewCollector(kv.StateEvents, s.dirs.Tmp, etl.NewSortableBuffer(etlBufSz), s.logger) defer stateEvents.Close() - activeValidatorIndicies := etl.NewCollector(kv.ActiveValidatorIndicies, s.dirs.Tmp, etl.NewSortableBuffer(etl.BufferOptimalSize), s.logger) + activeValidatorIndicies := etl.NewCollector(kv.ActiveValidatorIndicies, s.dirs.Tmp, etl.NewSortableBuffer(etlBufSz), s.logger) defer activeValidatorIndicies.Close() progress, err := state_accessors.GetStateProcessingProgress(tx) From a191296f05647bb5597bf618a6707cd1f1738164 Mon Sep 17 00:00:00 2001 From: Bayram Guvanjov Date: Fri, 12 Jan 2024 22:20:26 +0900 Subject: [PATCH 53/92] Deneb integration to Caplin (#9093) Pr is ready to review and merge. This PR includes implementing and integrating Ethereum Deneb's hard work with the Caplin Ethereum client. Changes: - Full compatibility with Deneb Ethereum hard fork - Added new EIPs introduced in Deneb. (`EIP-4788`, `EIP-4844`, `EIP-7044`, `EIP-7045`, `EIP-7514`) - Tests integration --------- Co-authored-by: Giulio --- cl/abstract/beacon_state.go | 1 + cl/clparams/config.go | 54 ++++++++++--------- cl/cltypes/eth1_header.go | 2 +- cl/phase1/core/state/cache_accessors.go | 13 ++++- cl/phase1/forkchoice/on_operations.go | 11 +++- cl/spectest/Makefile | 7 ++- cl/transition/impl/eth2/operations.go | 12 ++++- .../statechange/process_registry_updates.go | 2 +- 8 files changed, 66 insertions(+), 36 deletions(-) diff --git a/cl/abstract/beacon_state.go b/cl/abstract/beacon_state.go index 304a414dd12..cc77a206181 100644 --- a/cl/abstract/beacon_state.go +++ b/cl/abstract/beacon_state.go @@ -40,6 +40,7 @@ type BeaconStateExtension interface { ValidatorIndexByPubkey(key [48]byte) (uint64, bool) PreviousStateRoot() common.Hash SetPreviousStateRoot(root common.Hash) + GetValidatorActivationChurnLimit() uint64 } type BeaconStateBasic interface { diff --git a/cl/clparams/config.go b/cl/clparams/config.go index 4d51e918dcc..8748f7a8f28 100644 --- a/cl/clparams/config.go +++ b/cl/clparams/config.go @@ -308,20 +308,21 @@ type BeaconChainConfig struct { JustificationBitsLength uint64 `yaml:"JUSTIFICATION_BITS_LENGTH"` // JustificationBitsLength defines number of epochs to track when implementing k-finality in Casper FFG. // Misc constants. - PresetBase string `yaml:"PRESET_BASE" spec:"true"` // PresetBase represents the underlying spec preset this config is based on. - ConfigName string `yaml:"CONFIG_NAME" spec:"true"` // ConfigName for allowing an easy human-readable way of knowing what chain is being used. - TargetCommitteeSize uint64 `yaml:"TARGET_COMMITTEE_SIZE" spec:"true"` // TargetCommitteeSize is the number of validators in a committee when the chain is healthy. - MaxValidatorsPerCommittee uint64 `yaml:"MAX_VALIDATORS_PER_COMMITTEE" spec:"true"` // MaxValidatorsPerCommittee defines the upper bound of the size of a committee. - MaxCommitteesPerSlot uint64 `yaml:"MAX_COMMITTEES_PER_SLOT" spec:"true"` // MaxCommitteesPerSlot defines the max amount of committee in a single slot. - MinPerEpochChurnLimit uint64 `yaml:"MIN_PER_EPOCH_CHURN_LIMIT" spec:"true"` // MinPerEpochChurnLimit is the minimum amount of churn allotted for validator rotations. - ChurnLimitQuotient uint64 `yaml:"CHURN_LIMIT_QUOTIENT" spec:"true"` // ChurnLimitQuotient is used to determine the limit of how many validators can rotate per epoch. - ShuffleRoundCount uint64 `yaml:"SHUFFLE_ROUND_COUNT" spec:"true"` // ShuffleRoundCount is used for retrieving the permuted index. - MinGenesisActiveValidatorCount uint64 `yaml:"MIN_GENESIS_ACTIVE_VALIDATOR_COUNT" spec:"true"` // MinGenesisActiveValidatorCount defines how many validator deposits needed to kick off beacon chain. - MinGenesisTime uint64 `yaml:"MIN_GENESIS_TIME" spec:"true"` // MinGenesisTime is the time that needed to pass before kicking off beacon chain. - TargetAggregatorsPerCommittee uint64 `yaml:"TARGET_AGGREGATORS_PER_COMMITTEE" spec:"true"` // TargetAggregatorsPerCommittee defines the number of aggregators inside one committee. - HysteresisQuotient uint64 `yaml:"HYSTERESIS_QUOTIENT" spec:"true"` // HysteresisQuotient defines the hysteresis quotient for effective balance calculations. - HysteresisDownwardMultiplier uint64 `yaml:"HYSTERESIS_DOWNWARD_MULTIPLIER" spec:"true"` // HysteresisDownwardMultiplier defines the hysteresis downward multiplier for effective balance calculations. - HysteresisUpwardMultiplier uint64 `yaml:"HYSTERESIS_UPWARD_MULTIPLIER" spec:"true"` // HysteresisUpwardMultiplier defines the hysteresis upward multiplier for effective balance calculations. + PresetBase string `yaml:"PRESET_BASE" spec:"true"` // PresetBase represents the underlying spec preset this config is based on. + ConfigName string `yaml:"CONFIG_NAME" spec:"true"` // ConfigName for allowing an easy human-readable way of knowing what chain is being used. + TargetCommitteeSize uint64 `yaml:"TARGET_COMMITTEE_SIZE" spec:"true"` // TargetCommitteeSize is the number of validators in a committee when the chain is healthy. + MaxValidatorsPerCommittee uint64 `yaml:"MAX_VALIDATORS_PER_COMMITTEE" spec:"true"` // MaxValidatorsPerCommittee defines the upper bound of the size of a committee. + MaxCommitteesPerSlot uint64 `yaml:"MAX_COMMITTEES_PER_SLOT" spec:"true"` // MaxCommitteesPerSlot defines the max amount of committee in a single slot. + MinPerEpochChurnLimit uint64 `yaml:"MIN_PER_EPOCH_CHURN_LIMIT" spec:"true"` // MinPerEpochChurnLimit is the minimum amount of churn allotted for validator rotations. + ChurnLimitQuotient uint64 `yaml:"CHURN_LIMIT_QUOTIENT" spec:"true"` // ChurnLimitQuotient is used to determine the limit of how many validators can rotate per epoch. + MaxPerEpochActivationChurnLimit uint64 `yaml:"MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT" spec:"true"` // MaxPerEpochActivationChurnLimit defines the maximum amount of churn allowed in one epoch from deneb. + ShuffleRoundCount uint64 `yaml:"SHUFFLE_ROUND_COUNT" spec:"true"` // ShuffleRoundCount is used for retrieving the permuted index. + MinGenesisActiveValidatorCount uint64 `yaml:"MIN_GENESIS_ACTIVE_VALIDATOR_COUNT" spec:"true"` // MinGenesisActiveValidatorCount defines how many validator deposits needed to kick off beacon chain. + MinGenesisTime uint64 `yaml:"MIN_GENESIS_TIME" spec:"true"` // MinGenesisTime is the time that needed to pass before kicking off beacon chain. + TargetAggregatorsPerCommittee uint64 `yaml:"TARGET_AGGREGATORS_PER_COMMITTEE" spec:"true"` // TargetAggregatorsPerCommittee defines the number of aggregators inside one committee. + HysteresisQuotient uint64 `yaml:"HYSTERESIS_QUOTIENT" spec:"true"` // HysteresisQuotient defines the hysteresis quotient for effective balance calculations. + HysteresisDownwardMultiplier uint64 `yaml:"HYSTERESIS_DOWNWARD_MULTIPLIER" spec:"true"` // HysteresisDownwardMultiplier defines the hysteresis downward multiplier for effective balance calculations. + HysteresisUpwardMultiplier uint64 `yaml:"HYSTERESIS_UPWARD_MULTIPLIER" spec:"true"` // HysteresisUpwardMultiplier defines the hysteresis upward multiplier for effective balance calculations. // Gwei value constants. MinDepositAmount uint64 `yaml:"MIN_DEPOSIT_AMOUNT" spec:"true"` // MinDepositAmount is the minimum amount of Gwei a validator can send to the deposit contract at once (lower amounts will be reverted). @@ -573,18 +574,19 @@ var MainnetBeaconConfig BeaconChainConfig = BeaconChainConfig{ GenesisDelay: 604800, // 1 week. // Misc constant. - TargetCommitteeSize: 128, - MaxValidatorsPerCommittee: 2048, - MaxCommitteesPerSlot: 64, - MinPerEpochChurnLimit: 4, - ChurnLimitQuotient: 1 << 16, - ShuffleRoundCount: 90, - MinGenesisActiveValidatorCount: 16384, - MinGenesisTime: 1606824000, // Dec 1, 2020, 12pm UTC. - TargetAggregatorsPerCommittee: 16, - HysteresisQuotient: 4, - HysteresisDownwardMultiplier: 1, - HysteresisUpwardMultiplier: 5, + TargetCommitteeSize: 128, + MaxValidatorsPerCommittee: 2048, + MaxCommitteesPerSlot: 64, + MinPerEpochChurnLimit: 4, + ChurnLimitQuotient: 1 << 16, + MaxPerEpochActivationChurnLimit: 8, + ShuffleRoundCount: 90, + MinGenesisActiveValidatorCount: 16384, + MinGenesisTime: 1606824000, // Dec 1, 2020, 12pm UTC. + TargetAggregatorsPerCommittee: 16, + HysteresisQuotient: 4, + HysteresisDownwardMultiplier: 1, + HysteresisUpwardMultiplier: 5, // Gwei value constants. MinDepositAmount: 1 * 1e9, diff --git a/cl/cltypes/eth1_header.go b/cl/cltypes/eth1_header.go index 9eabdfc1a6b..e74270fc6ed 100644 --- a/cl/cltypes/eth1_header.go +++ b/cl/cltypes/eth1_header.go @@ -57,7 +57,7 @@ func (e *Eth1Header) Capella() { e.WithdrawalsRoot = libcommon.Hash{} } -// Capella converts the header to capella version. +// Deneb converts the header to deneb version. func (e *Eth1Header) Deneb() { e.version = clparams.DenebVersion e.BlobGasUsed = 0 diff --git a/cl/phase1/core/state/cache_accessors.go b/cl/phase1/core/state/cache_accessors.go index 99f2f17a9bb..80685ec5a24 100644 --- a/cl/phase1/core/state/cache_accessors.go +++ b/cl/phase1/core/state/cache_accessors.go @@ -171,7 +171,10 @@ func (b *CachingBeaconState) GetAttestationParticipationFlagIndicies(data solid. if inclusionDelay <= utils.IntegerSquareRoot(b.BeaconConfig().SlotsPerEpoch) { participationFlagIndicies = append(participationFlagIndicies, b.BeaconConfig().TimelySourceFlagIndex) } - if matchingTarget && inclusionDelay <= b.BeaconConfig().SlotsPerEpoch { + if b.Version() < clparams.DenebVersion && matchingTarget && inclusionDelay <= b.BeaconConfig().SlotsPerEpoch { + participationFlagIndicies = append(participationFlagIndicies, b.BeaconConfig().TimelyTargetFlagIndex) + } + if b.Version() >= clparams.DenebVersion && matchingTarget { participationFlagIndicies = append(participationFlagIndicies, b.BeaconConfig().TimelyTargetFlagIndex) } if matchingHead && inclusionDelay == b.BeaconConfig().MinAttestationInclusionDelay { @@ -295,3 +298,11 @@ func (b *CachingBeaconState) GetValidatorChurnLimit() uint64 { activeIndsCount := uint64(len(b.GetActiveValidatorsIndices(Epoch(b)))) return utils.Max64(activeIndsCount/b.BeaconConfig().ChurnLimitQuotient, b.BeaconConfig().MinPerEpochChurnLimit) } + +// https://github.com/ethereum/consensus-specs/blob/dev/specs/deneb/beacon-chain.md#new-get_validator_activation_churn_limit +func (b *CachingBeaconState) GetValidatorActivationChurnLimit() uint64 { + if b.Version() >= clparams.DenebVersion { + return utils.Min64(b.BeaconConfig().MaxPerEpochActivationChurnLimit, b.GetValidatorChurnLimit()) + } + return b.GetValidatorChurnLimit() +} diff --git a/cl/phase1/forkchoice/on_operations.go b/cl/phase1/forkchoice/on_operations.go index 8679fb6a905..74399523134 100644 --- a/cl/phase1/forkchoice/on_operations.go +++ b/cl/phase1/forkchoice/on_operations.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/Giulio2002/bls" + "github.com/ledgerwatch/erigon/cl/clparams" "github.com/ledgerwatch/erigon/cl/cltypes" "github.com/ledgerwatch/erigon/cl/fork" "github.com/ledgerwatch/erigon/cl/phase1/core/state" @@ -49,10 +50,18 @@ func (f *ForkChoiceStore) OnVoluntaryExit(signedVoluntaryExit *cltypes.SignedVol pk := val.PublicKey() f.mu.Unlock() - domain, err := s.GetDomain(s.BeaconConfig().DomainVoluntaryExit, voluntaryExit.Epoch) + domainType := f.beaconCfg.DomainVoluntaryExit + var domain []byte + + if s.Version() < clparams.DenebVersion { + domain, err = s.GetDomain(domainType, voluntaryExit.Epoch) + } else if s.Version() >= clparams.DenebVersion { + domain, err = fork.ComputeDomain(domainType[:], utils.Uint32ToBytes4(s.BeaconConfig().CapellaForkVersion), s.GenesisValidatorsRoot()) + } if err != nil { return err } + signingRoot, err := fork.ComputeSigningRoot(voluntaryExit, domain) if err != nil { return err diff --git a/cl/spectest/Makefile b/cl/spectest/Makefile index 42877b2a330..23c6cf4c17e 100644 --- a/cl/spectest/Makefile +++ b/cl/spectest/Makefile @@ -3,15 +3,14 @@ tests: GIT_LFS_SKIP_SMUDGE=1 git clone https://github.com/ethereum/consensus-spec-tests - cd consensus-spec-tests && git checkout 99549a414c10baa9e69abcb08eb256fc1a8d54f6 && git lfs pull --exclude=tests/general,tests/minimal && cd .. + cd consensus-spec-tests && git checkout 080c96fbbf3be58e75947debfeb9ba3b2b7c9748 && git lfs pull --exclude=tests/general,tests/minimal && cd .. mv consensus-spec-tests/tests . rm -rf consensus-spec-tests rm -rf tests/minimal # not needed for now rm -rf tests/mainnet/eip6110 - # will not implement until i see it on a testnet - rm -rf tests/mainnet/deneb - + # FIXME: Add fork choice coverage for deneb + rm -rf tests/mainnet/deneb/fork_choice clean: rm -rf tests diff --git a/cl/transition/impl/eth2/operations.go b/cl/transition/impl/eth2/operations.go index 0650a1c1c0b..fd570038fe5 100644 --- a/cl/transition/impl/eth2/operations.go +++ b/cl/transition/impl/eth2/operations.go @@ -217,7 +217,12 @@ func (I *impl) ProcessVoluntaryExit(s abstract.BeaconState, signedVoluntaryExit // We can skip it in some instances if we want to optimistically sync up. if I.FullValidation { - domain, err := s.GetDomain(s.BeaconConfig().DomainVoluntaryExit, voluntaryExit.Epoch) + var domain []byte + if s.Version() < clparams.DenebVersion { + domain, err = s.GetDomain(s.BeaconConfig().DomainVoluntaryExit, voluntaryExit.Epoch) + } else if s.Version() >= clparams.DenebVersion { + domain, err = fork.ComputeDomain(s.BeaconConfig().DomainVoluntaryExit[:], utils.Uint32ToBytes4(s.BeaconConfig().CapellaForkVersion), s.GenesisValidatorsRoot()) + } if err != nil { return err } @@ -697,7 +702,10 @@ func (I *impl) processAttestation(s abstract.BeaconState, attestation *solid.Att if (data.Target().Epoch() != currentEpoch && data.Target().Epoch() != previousEpoch) || data.Target().Epoch() != state.GetEpochAtSlot(s.BeaconConfig(), data.Slot()) { return nil, errors.New("ProcessAttestation: attestation with invalid epoch") } - if data.Slot()+beaconConfig.MinAttestationInclusionDelay > stateSlot || stateSlot > data.Slot()+beaconConfig.SlotsPerEpoch { + if s.Version() < clparams.DenebVersion && ((data.Slot()+beaconConfig.MinAttestationInclusionDelay > stateSlot) || (stateSlot > data.Slot()+beaconConfig.SlotsPerEpoch)) { + return nil, errors.New("ProcessAttestation: attestation slot not in range") + } + if s.Version() >= clparams.DenebVersion && data.Slot()+beaconConfig.MinAttestationInclusionDelay > stateSlot { return nil, errors.New("ProcessAttestation: attestation slot not in range") } if data.ValidatorIndex() >= s.CommitteeCount(data.Target().Epoch()) { diff --git a/cl/transition/impl/eth2/statechange/process_registry_updates.go b/cl/transition/impl/eth2/statechange/process_registry_updates.go index c22c442266b..ee56a2f0ed2 100644 --- a/cl/transition/impl/eth2/statechange/process_registry_updates.go +++ b/cl/transition/impl/eth2/statechange/process_registry_updates.go @@ -62,7 +62,7 @@ func ProcessRegistryUpdates(s abstract.BeaconState) error { } return activationQueue[i].validatorIndex < activationQueue[j].validatorIndex }) - activationQueueLength := s.GetValidatorChurnLimit() + activationQueueLength := s.GetValidatorActivationChurnLimit() if len(activationQueue) > int(activationQueueLength) { activationQueue = activationQueue[:activationQueueLength] } From c11e5047fb6b892e1a378ce11e51d5612ba96168 Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Fri, 12 Jan 2024 16:11:01 +0100 Subject: [PATCH 54/92] polygon: refactor header.Time validation (#9213) --- eth/backend.go | 3 +- eth/stagedsync/stage_bor_heimdall_test.go | 2 +- polygon/bor/bor.go | 98 ++++++++++++-------- polygon/bor/errors.go | 28 ------ polygon/bor/snapshot.go | 68 ++------------ polygon/bor/snapshot_test.go | 4 +- polygon/bor/valset/{error.go => errors.go} | 28 ++++++ polygon/bor/valset/validator_set.go | 19 +++- polygon/sync/canonical_chain_builder.go | 13 ++- polygon/sync/canonical_chain_builder_test.go | 2 +- polygon/sync/difficulty.go | 19 ++-- polygon/sync/difficulty_test.go | 18 ++-- polygon/sync/header_time_validator.go | 74 +++++++++++++++ polygon/sync/validator_set_interface.go | 13 +++ turbo/jsonrpc/bor_snapshot.go | 53 ++--------- 15 files changed, 236 insertions(+), 206 deletions(-) rename polygon/bor/valset/{error.go => errors.go} (51%) create mode 100644 polygon/sync/header_time_validator.go create mode 100644 polygon/sync/validator_set_interface.go diff --git a/eth/backend.go b/eth/backend.go index bc95f34f10e..00f917f080a 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -109,6 +109,7 @@ import ( "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/polygon/bor" "github.com/ledgerwatch/erigon/polygon/bor/finality/flags" + "github.com/ledgerwatch/erigon/polygon/bor/valset" "github.com/ledgerwatch/erigon/polygon/heimdall" "github.com/ledgerwatch/erigon/polygon/heimdall/heimdallgrpc" "github.com/ledgerwatch/erigon/rpc" @@ -1066,7 +1067,7 @@ func (s *Ethereum) StartMining(ctx context.Context, db kv.RwDB, stateDiffClient if s.chainConfig.ChainName == networkname.BorDevnetChainName && s.config.WithoutHeimdall { borcfg.Authorize(eb, func(addr libcommon.Address, _ string, _ []byte) ([]byte, error) { - return nil, &bor.UnauthorizedSignerError{Number: 0, Signer: addr.Bytes()} + return nil, &valset.UnauthorizedSignerError{Number: 0, Signer: addr.Bytes()} }) } diff --git a/eth/stagedsync/stage_bor_heimdall_test.go b/eth/stagedsync/stage_bor_heimdall_test.go index 7da0f8c6988..e937b38f33b 100644 --- a/eth/stagedsync/stage_bor_heimdall_test.go +++ b/eth/stagedsync/stage_bor_heimdall_test.go @@ -205,7 +205,7 @@ func TestBorHeimdallForwardDetectsUnauthorizedSignerError(t *testing.T) { require.Equal(t, invalidHeader.Number.Uint64()-1, testHarness.StateSyncUnwindPoint()) unwindReason := testHarness.StateSyncUnwindReason() require.Equal(t, invalidHeader.Hash(), *unwindReason.Block) - var unauthorizedSignerErr *bor.UnauthorizedSignerError + var unauthorizedSignerErr *valset.UnauthorizedSignerError ok := errors.As(unwindReason.Err, &unauthorizedSignerErr) require.True(t, ok) require.Equal(t, invalidHeader.Number.Uint64(), unauthorizedSignerErr.Number) diff --git a/polygon/bor/bor.go b/polygon/bor/bor.go index 9d96308d3c8..e33af3d106b 100644 --- a/polygon/bor/bor.go +++ b/polygon/bor/bor.go @@ -226,6 +226,48 @@ func CalcProducerDelay(number uint64, succession int, c *borcfg.BorConfig) uint6 return delay } +func MinNextBlockTime(parent *types.Header, succession int, config *borcfg.BorConfig) uint64 { + return parent.Time + CalcProducerDelay(parent.Number.Uint64()+1, succession, config) +} + +// ValidateHeaderTimeSignerSuccessionNumber - valset.ValidatorSet abstraction for unit tests +type ValidateHeaderTimeSignerSuccessionNumber interface { + GetSignerSuccessionNumber(signer libcommon.Address, number uint64) (int, error) +} + +func ValidateHeaderTime( + header *types.Header, + now time.Time, + parent *types.Header, + validatorSet ValidateHeaderTimeSignerSuccessionNumber, + config *borcfg.BorConfig, + signaturesCache *lru.ARCCache[libcommon.Hash, libcommon.Address], +) error { + if header.Time > uint64(now.Unix()) { + return consensus.ErrFutureBlock + } + + if parent == nil { + return nil + } + + signer, err := Ecrecover(header, signaturesCache, config) + if err != nil { + return err + } + + succession, err := validatorSet.GetSignerSuccessionNumber(signer, header.Number.Uint64()) + if err != nil { + return err + } + + if header.Time < MinNextBlockTime(parent, succession, config) { + return &BlockTooSoonError{header.Number.Uint64(), succession} + } + + return nil +} + // BorRLP returns the rlp bytes which needs to be signed for the bor // sealing. The RLP to sign consists of the entire header apart from the 65 byte signature // contained at the end of the extra data. @@ -316,7 +358,7 @@ func New( libcommon.Address{}, func(_ libcommon.Address, _ string, i []byte) ([]byte, error) { // return an error to prevent panics - return nil, &UnauthorizedSignerError{0, libcommon.Address{}.Bytes()} + return nil, &valset.UnauthorizedSignerError{Number: 0, Signer: libcommon.Address{}.Bytes()} }, }) @@ -768,21 +810,6 @@ func (c *Bor) verifySeal(chain consensus.ChainHeaderReader, header *types.Header if number == 0 { return errUnknownBlock } - // Resolve the authorization key and check against signers - signer, err := Ecrecover(header, c.Signatures, c.config) - if err != nil { - return err - } - - if !snap.ValidatorSet.HasAddress(signer) { - // Check the UnauthorizedSignerError.Error() msg to see why we pass number-1 - return &UnauthorizedSignerError{number - 1, signer.Bytes()} - } - - succession, err := snap.GetSignerSuccessionNumber(signer) - if err != nil { - return err - } var parent *types.Header if len(parents) > 0 { // if parents is nil, len(parents) is zero @@ -791,12 +818,17 @@ func (c *Bor) verifySeal(chain consensus.ChainHeaderReader, header *types.Header parent = chain.GetHeader(header.ParentHash, number-1) } - if parent != nil && header.Time < parent.Time+CalcProducerDelay(number, succession, c.config) { - return &BlockTooSoonError{number, succession} + if err := ValidateHeaderTime(header, time.Now(), parent, snap.ValidatorSet, c.config, c.Signatures); err != nil { + return err } // Ensure that the difficulty corresponds to the turn-ness of the signer if !c.fakeDiff { + signer, err := Ecrecover(header, c.Signatures, c.config) + if err != nil { + return err + } + difficulty := snap.Difficulty(signer) if header.Difficulty.Uint64() != difficulty { return &WrongDifficultyError{number, difficulty, header.Difficulty.Uint64(), signer.Bytes()} @@ -806,10 +838,6 @@ func (c *Bor) verifySeal(chain consensus.ChainHeaderReader, header *types.Header return nil } -func IsBlockOnTime(parent *types.Header, header *types.Header, number uint64, succession int, cfg *borcfg.BorConfig) bool { - return parent != nil && header.Time < parent.Time+CalcProducerDelay(number, succession, cfg) -} - // Prepare implements consensus.Engine, preparing all the consensus fields of the // header for running the transactions on top. func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header, state *state.IntraBlockState) error { @@ -901,15 +929,16 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header, s } var succession int + signer := c.authorizedSigner.Load().signer // if signer is not empty - if signer := c.authorizedSigner.Load().signer; !bytes.Equal(signer.Bytes(), libcommon.Address{}.Bytes()) { - succession, err = snap.GetSignerSuccessionNumber(signer) + if !bytes.Equal(signer.Bytes(), libcommon.Address{}.Bytes()) { + succession, err = snap.ValidatorSet.GetSignerSuccessionNumber(signer, number) if err != nil { return err } } - header.Time = parent.Time + CalcProducerDelay(number, succession, c.config) + header.Time = MinNextBlockTime(parent, succession, c.config) if header.Time < uint64(time.Now().Unix()) { header.Time = uint64(time.Now().Unix()) } @@ -1082,13 +1111,7 @@ func (c *Bor) Seal(chain consensus.ChainHeaderReader, block *types.Block, result return err } - // Bail out if we're unauthorized to sign a block - if !snap.ValidatorSet.HasAddress(signer) { - // Check the UnauthorizedSignerError.Error() msg to see why we pass number-1 - return &UnauthorizedSignerError{number - 1, signer.Bytes()} - } - - successionNumber, err := snap.GetSignerSuccessionNumber(signer) + successionNumber, err := snap.ValidatorSet.GetSignerSuccessionNumber(signer, number) if err != nil { return err } @@ -1176,7 +1199,6 @@ func (c *Bor) IsValidator(header *types.Header) (bool, error) { // IsProposer returns true if this instance is the proposer for this block func (c *Bor) IsProposer(header *types.Header) (bool, error) { number := header.Number.Uint64() - if number == 0 { return false, nil } @@ -1186,14 +1208,8 @@ func (c *Bor) IsProposer(header *types.Header) (bool, error) { return false, err } - currentSigner := c.authorizedSigner.Load() - - if !snap.ValidatorSet.HasAddress(currentSigner.signer) { - return false, nil - } - - successionNumber, err := snap.GetSignerSuccessionNumber(currentSigner.signer) - + signer := c.authorizedSigner.Load().signer + successionNumber, err := snap.ValidatorSet.GetSignerSuccessionNumber(signer, number) return successionNumber == 0, err } diff --git a/polygon/bor/errors.go b/polygon/bor/errors.go index 1b33eb634df..1ee6fd9bd06 100644 --- a/polygon/bor/errors.go +++ b/polygon/bor/errors.go @@ -51,34 +51,6 @@ func (e *BlockTooSoonError) Error() string { ) } -// UnauthorizedProposerError is returned if a header is [being] signed by an unauthorized entity. -type UnauthorizedProposerError struct { - Number uint64 - Proposer []byte -} - -func (e *UnauthorizedProposerError) Error() string { - return fmt.Sprintf( - "Proposer 0x%x is not a part of the producer set at block %d", - e.Proposer, - e.Number, - ) -} - -// UnauthorizedSignerError is returned if a header is [being] signed by an unauthorized entity. -type UnauthorizedSignerError struct { - Number uint64 - Signer []byte -} - -func (e *UnauthorizedSignerError) Error() string { - return fmt.Sprintf( - "Signer 0x%x is not a part of the producer set at block %d", - e.Signer, - e.Number, - ) -} - // WrongDifficultyError is returned if the difficulty of a block doesn't match the // turn of the signer. type WrongDifficultyError struct { diff --git a/polygon/bor/snapshot.go b/polygon/bor/snapshot.go index cf4bbef43d1..2427821ffa8 100644 --- a/polygon/bor/snapshot.go +++ b/polygon/bor/snapshot.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/json" + "time" lru "github.com/hashicorp/golang-lru/arc/v2" "github.com/ledgerwatch/log/v3" @@ -20,10 +21,9 @@ type Snapshot struct { config *borcfg.BorConfig // Consensus engine parameters to fine tune behavior sigcache *lru.ARCCache[common.Hash, common.Address] // Cache of recent block signatures to speed up ecrecover - Number uint64 `json:"number"` // Block number where the snapshot was created - Hash common.Hash `json:"hash"` // Block hash where the snapshot was created - ValidatorSet *valset.ValidatorSet `json:"validatorSet"` // Validator set at this moment - Recents map[uint64]common.Address `json:"recents"` // Set of recent signers for spam protections + Number uint64 `json:"number"` // Block number where the snapshot was created + Hash common.Hash `json:"hash"` // Block hash where the snapshot was created + ValidatorSet *valset.ValidatorSet `json:"validatorSet"` // Validator set at this moment } const BorSeparate = "BorSeparate" @@ -52,7 +52,6 @@ func NewSnapshot( Number: number, Hash: hash, ValidatorSet: valset.NewValidatorSet(validators), - Recents: make(map[uint64]common.Address), } return snap } @@ -110,12 +109,7 @@ func (s *Snapshot) copy() *Snapshot { Number: s.Number, Hash: s.Hash, ValidatorSet: s.ValidatorSet.Copy(), - Recents: make(map[uint64]common.Address), } - for block, signer := range s.Recents { - cpy.Recents[block] = signer - } - return cpy } @@ -142,36 +136,15 @@ func (s *Snapshot) Apply(parent *types.Header, headers []*types.Header, logger l number := header.Number.Uint64() sprintLen := s.config.CalculateSprintLength(number) - // Delete the oldest signer from the recent list to allow it signing again - if number >= sprintLen { - delete(snap.Recents, number-sprintLen) + if err := ValidateHeaderTime(header, time.Now(), parent, snap.ValidatorSet, s.config, s.sigcache); err != nil { + return snap, err } - // Resolve the authorization key and check against signers - signer, err := Ecrecover(header, s.sigcache, s.config) + signer, err := Ecrecover(header, s.sigcache, s.config) if err != nil { return nil, err } - var validSigner bool - var succession int - - // check if signer is in validator set - if !snap.ValidatorSet.HasAddress(signer) { - return snap, &UnauthorizedSignerError{number, signer.Bytes()} - } - if succession, err = snap.GetSignerSuccessionNumber(signer); err != nil { - return snap, err - } - - // add recents - snap.Recents[number] = signer - - validSigner = true - - if parent != nil && header.Time < parent.Time+CalcProducerDelay(number, succession, s.config) { - return snap, &BlockTooSoonError{number, succession} - } difficulty := snap.Difficulty(signer) if header.Difficulty.Uint64() != difficulty { return snap, &WrongDifficultyError{number, difficulty, header.Difficulty.Uint64(), signer.Bytes()} @@ -191,9 +164,6 @@ func (s *Snapshot) Apply(parent *types.Header, headers []*types.Header, logger l snap.ValidatorSet = v } - if number > 64 && !validSigner { - return snap, &UnauthorizedSignerError{number, signer.Bytes()} - } parent = header snap.Number = number snap.Hash = header.Hash() @@ -202,30 +172,8 @@ func (s *Snapshot) Apply(parent *types.Header, headers []*types.Header, logger l return snap, nil } -// GetSignerSuccessionNumber returns the relative position of signer in terms of the in-turn proposer func (s *Snapshot) GetSignerSuccessionNumber(signer common.Address) (int, error) { - validators := s.ValidatorSet.Validators - proposer := s.ValidatorSet.GetProposer().Address - proposerIndex, _ := s.ValidatorSet.GetByAddress(proposer) - - if proposerIndex == -1 { - return -1, &UnauthorizedProposerError{s.Number, proposer.Bytes()} - } - - signerIndex, _ := s.ValidatorSet.GetByAddress(signer) - - if signerIndex == -1 { - return -1, &UnauthorizedSignerError{s.Number, signer.Bytes()} - } - - tempIndex := signerIndex - if proposerIndex != tempIndex { - if tempIndex < proposerIndex { - tempIndex = tempIndex + len(validators) - } - } - - return tempIndex - proposerIndex, nil + return s.ValidatorSet.GetSignerSuccessionNumber(signer, s.Number) } // signers retrieves the list of authorized signers in ascending order. diff --git a/polygon/bor/snapshot_test.go b/polygon/bor/snapshot_test.go index 4a6d940328f..e39674bca30 100644 --- a/polygon/bor/snapshot_test.go +++ b/polygon/bor/snapshot_test.go @@ -101,7 +101,7 @@ func TestGetSignerSuccessionNumber_ProposerNotFound(t *testing.T) { _, err := snap.GetSignerSuccessionNumber(signer) require.NotNil(t, err) - e, ok := err.(*bor.UnauthorizedProposerError) + e, ok := err.(*valset.UnauthorizedProposerError) require.True(t, ok) require.Equal(t, dummyProposerAddress.Bytes(), e.Proposer) } @@ -118,7 +118,7 @@ func TestGetSignerSuccessionNumber_SignerNotFound(t *testing.T) { _, err := snap.GetSignerSuccessionNumber(dummySignerAddress) require.NotNil(t, err) - e, ok := err.(*bor.UnauthorizedSignerError) + e, ok := err.(*valset.UnauthorizedSignerError) require.True(t, ok) require.Equal(t, dummySignerAddress.Bytes(), e.Signer) } diff --git a/polygon/bor/valset/error.go b/polygon/bor/valset/errors.go similarity index 51% rename from polygon/bor/valset/error.go rename to polygon/bor/valset/errors.go index 37add216834..e44e8a268ba 100644 --- a/polygon/bor/valset/error.go +++ b/polygon/bor/valset/errors.go @@ -30,3 +30,31 @@ func (e *InvalidStartEndBlockError) Error() string { e.End, ) } + +// UnauthorizedProposerError is returned if a header is [being] signed by an unauthorized entity. +type UnauthorizedProposerError struct { + Number uint64 + Proposer []byte +} + +func (e *UnauthorizedProposerError) Error() string { + return fmt.Sprintf( + "Proposer 0x%x is not a part of the producer set at block %d", + e.Proposer, + e.Number, + ) +} + +// UnauthorizedSignerError is returned if a header is [being] signed by an unauthorized entity. +type UnauthorizedSignerError struct { + Number uint64 + Signer []byte +} + +func (e *UnauthorizedSignerError) Error() string { + return fmt.Sprintf( + "Signer 0x%x is not a part of the producer set at block %d", + e.Signer, + e.Number, + ) +} diff --git a/polygon/bor/valset/validator_set.go b/polygon/bor/valset/validator_set.go index 864bb132bed..8dffbd78f72 100644 --- a/polygon/bor/valset/validator_set.go +++ b/polygon/bor/valset/validator_set.go @@ -4,7 +4,6 @@ package valset import ( "bytes" - "errors" "fmt" "math" "math/big" @@ -656,26 +655,36 @@ func (vals *ValidatorSet) UpdateWithChangeSet(changes []*Validator) error { // Difficulty returns the difficulty for a particular signer at the current snapshot number func (vals *ValidatorSet) Difficulty(signer libcommon.Address) (uint64, error) { + indexDiff, err := vals.GetSignerSuccessionNumber(signer, 0) + if err != nil { + return 0, fmt.Errorf("ValidatorSet.Difficulty: %w", err) + } + + return uint64(len(vals.Validators) - indexDiff), nil +} + +// GetSignerSuccessionNumber returns the relative position of signer in terms of the in-turn proposer +func (vals *ValidatorSet) GetSignerSuccessionNumber(signer libcommon.Address, number uint64) (int, error) { proposer := vals.GetProposer() if proposer == nil { - return 0, errors.New("ValidatorSet.Difficulty: proposer not found") + return -1, &UnauthorizedProposerError{Number: number, Proposer: []byte{}} } proposerIndex, _ := vals.GetByAddress(proposer.Address) if proposerIndex < 0 { - return 0, errors.New("ValidatorSet.Difficulty: proposer index not found") + return -1, &UnauthorizedProposerError{Number: number, Proposer: proposer.Address.Bytes()} } signerIndex, _ := vals.GetByAddress(signer) if signerIndex < 0 { - return 0, errors.New("ValidatorSet.Difficulty: signer index not found") + return -1, &UnauthorizedSignerError{Number: number, Signer: signer.Bytes()} } indexDiff := signerIndex - proposerIndex if indexDiff < 0 { indexDiff += len(vals.Validators) } - return uint64(len(vals.Validators) - indexDiff), nil + return indexDiff, nil } //----------------- diff --git a/polygon/sync/canonical_chain_builder.go b/polygon/sync/canonical_chain_builder.go index 0ddcf2c325b..d808a7d20c0 100644 --- a/polygon/sync/canonical_chain_builder.go +++ b/polygon/sync/canonical_chain_builder.go @@ -3,6 +3,7 @@ package sync import ( "errors" "fmt" + "time" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/core/types" @@ -36,14 +37,19 @@ type canonicalChainBuilderImpl struct { tip *forkTreeNode difficultyCalc DifficultyCalculator + + headerTimeValidator HeaderTimeValidator } func NewCanonicalChainBuilder( root *types.Header, difficultyCalc DifficultyCalculator, + headerTimeValidator HeaderTimeValidator, ) CanonicalChainBuilder { impl := &canonicalChainBuilderImpl{ difficultyCalc: difficultyCalc, + + headerTimeValidator: headerTimeValidator, } impl.Reset(root) return impl @@ -198,9 +204,10 @@ func (impl *canonicalChainBuilderImpl) Connect(headers []*types.Header) error { return errors.New("canonicalChainBuilderImpl.Connect: invalid header.Number") } - // TODO: validate using CalcProducerDelay - if header.Time <= parent.header.Time { - return errors.New("canonicalChainBuilderImpl.Connect: invalid header.Time") + if impl.headerTimeValidator != nil { + if err := impl.headerTimeValidator.ValidateHeaderTime(header, time.Now(), parent.header); err != nil { + return fmt.Errorf("canonicalChainBuilderImpl.Connect: invalid header.Time - %w", err) + } } if err := bor.ValidateHeaderExtraField(header.Extra); err != nil { diff --git a/polygon/sync/canonical_chain_builder_test.go b/polygon/sync/canonical_chain_builder_test.go index a515738b741..86392a8c68e 100644 --- a/polygon/sync/canonical_chain_builder_test.go +++ b/polygon/sync/canonical_chain_builder_test.go @@ -34,7 +34,7 @@ func makeRoot() *types.Header { func makeCCB(root *types.Header) CanonicalChainBuilder { difficultyCalc := testDifficultyCalculator{} - builder := NewCanonicalChainBuilder(root, &difficultyCalc) + builder := NewCanonicalChainBuilder(root, &difficultyCalc, nil) return builder } diff --git a/polygon/sync/difficulty.go b/polygon/sync/difficulty.go index 6717df0064e..1ccb4c0b106 100644 --- a/polygon/sync/difficulty.go +++ b/polygon/sync/difficulty.go @@ -2,7 +2,6 @@ package sync import ( lru "github.com/hashicorp/golang-lru/arc/v2" - "github.com/ledgerwatch/log/v3" "github.com/ledgerwatch/erigon/eth/stagedsync" @@ -27,22 +26,20 @@ type difficultyCalculatorImpl struct { signaturesCache *lru.ARCCache[libcommon.Hash, libcommon.Address] } -// valset.ValidatorSet abstraction for unit tests -type validatorSetInterface interface { - IncrementProposerPriority(times int) - Difficulty(signer libcommon.Address) (uint64, error) -} - func NewDifficultyCalculator( borConfig *borcfg.BorConfig, span *heimdallspan.HeimdallSpan, validatorSetFactory func() validatorSetInterface, - log log.Logger, + signaturesCache *lru.ARCCache[libcommon.Hash, libcommon.Address], ) DifficultyCalculator { - signaturesCache, err := lru.NewARC[libcommon.Hash, libcommon.Address](stagedsync.InMemorySignatures) - if err != nil { - panic(err) + if signaturesCache == nil { + var err error + signaturesCache, err = lru.NewARC[libcommon.Hash, libcommon.Address](stagedsync.InMemorySignatures) + if err != nil { + panic(err) + } } + impl := difficultyCalculatorImpl{ borConfig: borConfig, span: span, diff --git a/polygon/sync/difficulty_test.go b/polygon/sync/difficulty_test.go index 9a0a184b5fb..4a3f7f39fad 100644 --- a/polygon/sync/difficulty_test.go +++ b/polygon/sync/difficulty_test.go @@ -3,7 +3,6 @@ package sync import ( "testing" - "github.com/ledgerwatch/log/v3" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -24,7 +23,7 @@ func (v *testValidatorSetInterface) IncrementProposerPriority(times int) { v.sprintNum = times } -func (v *testValidatorSetInterface) Difficulty(signer libcommon.Address) (uint64, error) { +func (v *testValidatorSetInterface) GetSignerSuccessionNumber(signer libcommon.Address, number uint64) (int, error) { var i int for (i < len(v.signers)) && (v.signers[i] != signer) { i++ @@ -38,6 +37,14 @@ func (v *testValidatorSetInterface) Difficulty(signer libcommon.Address) (uint64 delta = i + len(v.signers) - sprintOffset } + return delta, nil +} + +func (v *testValidatorSetInterface) Difficulty(signer libcommon.Address) (uint64, error) { + delta, err := v.GetSignerSuccessionNumber(signer, 0) + if err != nil { + return 0, nil + } return uint64(len(v.signers) - delta), nil } @@ -45,15 +52,13 @@ func TestSignerDifficulty(t *testing.T) { borConfig := borcfg.BorConfig{ Sprint: map[string]uint64{"0": 16}, } - span := heimdallspan.HeimdallSpan{} signers := []libcommon.Address{ libcommon.HexToAddress("00"), libcommon.HexToAddress("01"), libcommon.HexToAddress("02"), } validatorSetFactory := func() validatorSetInterface { return &testValidatorSetInterface{signers: signers} } - logger := log.New() - calc := NewDifficultyCalculator(&borConfig, &span, validatorSetFactory, logger).(*difficultyCalculatorImpl) + calc := NewDifficultyCalculator(&borConfig, nil, validatorSetFactory, nil).(*difficultyCalculatorImpl) var d uint64 @@ -119,8 +124,7 @@ func TestSignerDifficulty(t *testing.T) { func TestHeaderDifficultyNoSignature(t *testing.T) { borConfig := borcfg.BorConfig{} span := heimdallspan.HeimdallSpan{} - logger := log.New() - calc := NewDifficultyCalculator(&borConfig, &span, nil, logger) + calc := NewDifficultyCalculator(&borConfig, &span, nil, nil) _, err := calc.HeaderDifficulty(new(types.Header)) require.ErrorContains(t, err, "signature suffix missing") diff --git a/polygon/sync/header_time_validator.go b/polygon/sync/header_time_validator.go new file mode 100644 index 00000000000..8b84e36c0a7 --- /dev/null +++ b/polygon/sync/header_time_validator.go @@ -0,0 +1,74 @@ +package sync + +import ( + "time" + + lru "github.com/hashicorp/golang-lru/arc/v2" + + libcommon "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/eth/stagedsync" + "github.com/ledgerwatch/erigon/polygon/bor" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/valset" + heimdallspan "github.com/ledgerwatch/erigon/polygon/heimdall/span" +) + +type HeaderTimeValidator interface { + ValidateHeaderTime(header *types.Header, now time.Time, parent *types.Header) error + SetSpan(span *heimdallspan.HeimdallSpan) +} + +type headerTimeValidatorImpl struct { + borConfig *borcfg.BorConfig + span *heimdallspan.HeimdallSpan + validatorSetFactory func() validatorSetInterface + signaturesCache *lru.ARCCache[libcommon.Hash, libcommon.Address] +} + +func NewHeaderTimeValidator( + borConfig *borcfg.BorConfig, + span *heimdallspan.HeimdallSpan, + validatorSetFactory func() validatorSetInterface, + signaturesCache *lru.ARCCache[libcommon.Hash, libcommon.Address], +) HeaderTimeValidator { + if signaturesCache == nil { + var err error + signaturesCache, err = lru.NewARC[libcommon.Hash, libcommon.Address](stagedsync.InMemorySignatures) + if err != nil { + panic(err) + } + } + + impl := headerTimeValidatorImpl{ + borConfig: borConfig, + span: span, + validatorSetFactory: validatorSetFactory, + signaturesCache: signaturesCache, + } + + if validatorSetFactory == nil { + impl.validatorSetFactory = impl.makeValidatorSet + } + + return &impl +} + +func (impl *headerTimeValidatorImpl) makeValidatorSet() validatorSetInterface { + return valset.NewValidatorSet(impl.span.ValidatorSet.Validators) +} + +func (impl *headerTimeValidatorImpl) SetSpan(span *heimdallspan.HeimdallSpan) { + impl.span = span +} + +func (impl *headerTimeValidatorImpl) ValidateHeaderTime(header *types.Header, now time.Time, parent *types.Header) error { + validatorSet := impl.validatorSetFactory() + + sprintNum := impl.borConfig.CalculateSprintNumber(header.Number.Uint64()) + if sprintNum > 0 { + validatorSet.IncrementProposerPriority(int(sprintNum)) + } + + return bor.ValidateHeaderTime(header, now, parent, validatorSet, impl.borConfig, impl.signaturesCache) +} diff --git a/polygon/sync/validator_set_interface.go b/polygon/sync/validator_set_interface.go new file mode 100644 index 00000000000..a9e5f3a97a9 --- /dev/null +++ b/polygon/sync/validator_set_interface.go @@ -0,0 +1,13 @@ +package sync + +import ( + libcommon "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon/polygon/bor" +) + +// valset.ValidatorSet abstraction for unit tests +type validatorSetInterface interface { + bor.ValidateHeaderTimeSignerSuccessionNumber + IncrementProposerPriority(times int) + Difficulty(signer libcommon.Address) (uint64, error) +} diff --git a/turbo/jsonrpc/bor_snapshot.go b/turbo/jsonrpc/bor_snapshot.go index f92d6153a44..cbe30c751f8 100644 --- a/turbo/jsonrpc/bor_snapshot.go +++ b/turbo/jsonrpc/bor_snapshot.go @@ -24,10 +24,9 @@ import ( type Snapshot struct { config *borcfg.BorConfig // Consensus engine parameters to fine tune behavior - Number uint64 `json:"number"` // Block number where the snapshot was created - Hash common.Hash `json:"hash"` // Block hash where the snapshot was created - ValidatorSet *ValidatorSet `json:"validatorSet"` // Validator set at this moment - Recents map[uint64]common.Address `json:"recents"` // Set of recent signers for spam protections + Number uint64 `json:"number"` // Block number where the snapshot was created + Hash common.Hash `json:"hash"` // Block hash where the snapshot was created + ValidatorSet *ValidatorSet `json:"validatorSet"` // Validator set at this moment } // GetSnapshot retrieves the state snapshot at a given block. @@ -464,37 +463,10 @@ func (s *Snapshot) copy() *Snapshot { Number: s.Number, Hash: s.Hash, ValidatorSet: s.ValidatorSet.Copy(), - Recents: make(map[uint64]common.Address), } - for block, signer := range s.Recents { - cpy.Recents[block] = signer - } - return cpy } -// GetSignerSuccessionNumber returns the relative position of signer in terms of the in-turn proposer -func (s *Snapshot) GetSignerSuccessionNumber(signer common.Address) (int, error) { - validators := s.ValidatorSet.Validators - proposer := s.ValidatorSet.GetProposer().Address - proposerIndex, _ := s.ValidatorSet.GetByAddress(proposer) - if proposerIndex == -1 { - return -1, &bor.UnauthorizedProposerError{Number: s.Number, Proposer: proposer.Bytes()} - } - signerIndex, _ := s.ValidatorSet.GetByAddress(signer) - if signerIndex == -1 { - return -1, &bor.UnauthorizedSignerError{Number: s.Number, Signer: signer.Bytes()} - } - - tempIndex := signerIndex - if proposerIndex != tempIndex { - if tempIndex < proposerIndex { - tempIndex = tempIndex + len(validators) - } - } - return tempIndex - proposerIndex, nil -} - // signers retrieves the list of authorized signers in ascending order. func (s *Snapshot) signers() []common.Address { sigs := make([]common.Address, 0, len(s.ValidatorSet.Validators)) @@ -525,12 +497,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) { for _, header := range headers { // Remove any votes on checkpoint blocks number := header.Number.Uint64() - - // Delete the oldest signer from the recent list to allow it signing again - currentSprint := s.config.CalculateSprintLength(number) - if number >= currentSprint { - delete(snap.Recents, number-currentSprint) - } + currentLen := s.config.CalculateSprintLength(number) // Resolve the authorization key and check against signers signer, err := ecrecover(header, s.config) @@ -540,18 +507,11 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) { // check if signer is in validator set if !snap.ValidatorSet.HasAddress(signer) { - return nil, &bor.UnauthorizedSignerError{Number: number, Signer: signer.Bytes()} - } - - if _, err = snap.GetSignerSuccessionNumber(signer); err != nil { - return nil, err + return nil, &valset.UnauthorizedSignerError{Number: number, Signer: signer.Bytes()} } - // add recents - snap.Recents[number] = signer - // change validator set and change proposer - if number > 0 && (number+1)%currentSprint == 0 { + if number > 0 && (number+1)%currentLen == 0 { if err := bor.ValidateHeaderExtraField(header.Extra); err != nil { return nil, err } @@ -564,6 +524,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) { snap.ValidatorSet = v } } + snap.Number += uint64(len(headers)) snap.Hash = headers[len(headers)-1].Hash() From a592cbf1638d17b432eefe3f9bb448ff02ad4dea Mon Sep 17 00:00:00 2001 From: Arpit Temani Date: Fri, 12 Jan 2024 21:20:53 +0530 Subject: [PATCH 55/92] Removed the check for milestoneID in the GetVoteOnHash() (#9021) Removed the check for milestoneID in the GetVoteOnHash() https://github.com/maticnetwork/bor/pull/1109 --- turbo/jsonrpc/bor_snapshot.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/turbo/jsonrpc/bor_snapshot.go b/turbo/jsonrpc/bor_snapshot.go index cbe30c751f8..5defed92a3d 100644 --- a/turbo/jsonrpc/bor_snapshot.go +++ b/turbo/jsonrpc/bor_snapshot.go @@ -278,19 +278,6 @@ func (api *BorImpl) GetVoteOnHash(ctx context.Context, starBlockNr uint64, endBl return false, fmt.Errorf("hash mismatch: localChainHash %s, milestoneHash %s", localEndBlockHash, hash) } - bor, err := api.bor() - - if err != nil { - return false, errors.New("bor engine not available") - } - - err = bor.HeimdallClient.FetchMilestoneID(ctx, milestoneId) - - if err != nil { - service.UnlockMutex(false, "", endBlockNr, common.Hash{}) - return false, errors.New("milestone ID doesn't exist in Heimdall") - } - service.UnlockMutex(true, milestoneId, endBlockNr, localEndBlock.Hash()) return true, nil From 320fe0ab8b1998a54b628ba1d026f2f9b9505859 Mon Sep 17 00:00:00 2001 From: Mark Holt <135143369+mh0lt@users.noreply.github.com> Date: Fri, 12 Jan 2024 16:07:59 +0000 Subject: [PATCH 56/92] Don't run pos downloader or engine api for bor (#9220) Pos downloader and the engine api code are not necessary for Bor. This adds code to suppress their start up. --- eth/backend.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/eth/backend.go b/eth/backend.go index 00f917f080a..6861094462e 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -895,7 +895,9 @@ func (s *Ethereum) Init(stack *node.Node, config *ethconfig.Config) error { chainKv := s.chainDB var err error - s.sentriesClient.Hd.StartPoSDownloader(s.sentryCtx, s.sentriesClient.SendHeaderRequest, s.sentriesClient.Penalize) + if config.Genesis.Config.Bor == nil { + s.sentriesClient.Hd.StartPoSDownloader(s.sentryCtx, s.sentriesClient.SendHeaderRequest, s.sentriesClient.Penalize) + } emptyBadHash := config.BadBlockHash == libcommon.Hash{} if !emptyBadHash { @@ -948,7 +950,9 @@ func (s *Ethereum) Init(stack *node.Node, config *ethconfig.Config) error { }() } - go s.engineBackendRPC.Start(&httpRpcCfg, s.chainDB, s.blockReader, ff, stateCache, s.agg, s.engine, ethRpcClient, txPoolRpcClient, miningRpcClient) + if config.Genesis.Config.Bor == nil { + go s.engineBackendRPC.Start(&httpRpcCfg, s.chainDB, s.blockReader, ff, stateCache, s.agg, s.engine, ethRpcClient, txPoolRpcClient, miningRpcClient) + } // Register the backend on the node stack.RegisterLifecycle(s) From 52a948731cfd5fcd51e9477b95ef2f116eb7fe0a Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Fri, 12 Jan 2024 21:01:28 +0100 Subject: [PATCH 57/92] polygon: refactor header validations for reuse in sync (#9224) --- polygon/bor/bor.go | 110 ++++++++++++++---------- polygon/bor/snapshot.go | 2 +- polygon/sync/canonical_chain_builder.go | 16 ++-- polygon/sync/header_validator.go | 57 ++++++++++++ turbo/jsonrpc/bor_snapshot.go | 2 +- 5 files changed, 131 insertions(+), 56 deletions(-) create mode 100644 polygon/sync/header_validator.go diff --git a/polygon/bor/bor.go b/polygon/bor/bor.go index e33af3d106b..df251b81daa 100644 --- a/polygon/bor/bor.go +++ b/polygon/bor/bor.go @@ -111,9 +111,9 @@ var ( // their extra-data fields. errExtraValidators = errors.New("non-sprint-end block contains extra validator list") - // errInvalidSpanValidators is returned if a block contains an + // errInvalidSprintValidators is returned if a block contains an // invalid list of validators (i.e. non divisible by 40 bytes). - errInvalidSpanValidators = errors.New("invalid validator list on sprint end block") + errInvalidSprintValidators = errors.New("invalid validator list on sprint end block") // errInvalidMixDigest is returned if a block's mix digest is non-zero. errInvalidMixDigest = errors.New("non-zero mix digest") @@ -479,7 +479,6 @@ func (c *Bor) verifyHeader(chain consensus.ChainHeaderReader, header *types.Head if header.Number == nil { return errUnknownBlock } - number := header.Number.Uint64() // Don't waste time checking blocks from the future @@ -487,56 +486,29 @@ func (c *Bor) verifyHeader(chain consensus.ChainHeaderReader, header *types.Head return consensus.ErrFutureBlock } - if err := ValidateHeaderExtraField(header.Extra); err != nil { + if err := ValidateHeaderUnusedFields(header); err != nil { return err } - // check extr adata - isSprintEnd := isSprintStart(number+1, c.config.CalculateSprintLength(number)) - - // Ensure that the extra-data contains a signer list on checkpoint, but none otherwise - signersBytes := len(GetValidatorBytes(header, c.config)) - if !isSprintEnd && signersBytes != 0 { - return errExtraValidators - } - - if isSprintEnd && signersBytes%validatorHeaderBytesLength != 0 { - return errInvalidSpanValidators - } - - // Ensure that the mix digest is zero as we don't have fork protection currently - if header.MixDigest != (libcommon.Hash{}) { - return errInvalidMixDigest + if err := ValidateHeaderExtraLength(header.Extra); err != nil { + return err } - - // Ensure that the block doesn't contain any uncles which are meaningless in PoA - if header.UncleHash != uncleHash { - return errInvalidUncleHash + if err := ValidateHeaderSprintValidators(header, c.config); err != nil { + return err } // Ensure that the block's difficulty is meaningful (may not be correct at this point) - if number > 0 { - if header.Difficulty == nil { - return errInvalidDifficulty - } - } - - // Verify that the gas limit is <= 2^63-1 - if header.GasLimit > params.MaxGasLimit { - return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, params.MaxGasLimit) - } - - if header.WithdrawalsHash != nil { - return consensus.ErrUnexpectedWithdrawals + if (number > 0) && (header.Difficulty == nil) { + return errInvalidDifficulty } // All basic checks passed, verify cascading fields return c.verifyCascadingFields(chain, header, parents) } -// ValidateHeaderExtraField validates that the extra-data contains both the vanity and signature. +// ValidateHeaderExtraLength validates that the extra-data contains both the vanity and signature. // header.Extra = header.Vanity + header.ProducerBytes (optional) + header.Seal -func ValidateHeaderExtraField(extraBytes []byte) error { +func ValidateHeaderExtraLength(extraBytes []byte) error { if len(extraBytes) < types.ExtraVanityLength { return errMissingVanity } @@ -548,6 +520,41 @@ func ValidateHeaderExtraField(extraBytes []byte) error { return nil } +// ValidateHeaderSprintValidators validates that the extra-data contains a validators list only in the last header of a sprint. +func ValidateHeaderSprintValidators(header *types.Header, config *borcfg.BorConfig) error { + number := header.Number.Uint64() + isSprintEnd := isSprintStart(number+1, config.CalculateSprintLength(number)) + validatorBytes := GetValidatorBytes(header, config) + validatorBytesLen := len(validatorBytes) + + if !isSprintEnd && (validatorBytesLen != 0) { + return errExtraValidators + } + if isSprintEnd && (validatorBytesLen%validatorHeaderBytesLength != 0) { + return errInvalidSprintValidators + } + return nil +} + +// ValidateHeaderUnusedFields validates that unused fields are empty. +func ValidateHeaderUnusedFields(header *types.Header) error { + // Ensure that the mix digest is zero as we don't have fork protection currently + if header.MixDigest != (libcommon.Hash{}) { + return errInvalidMixDigest + } + + // Ensure that the block doesn't contain any uncles which are meaningless in PoA + if header.UncleHash != uncleHash { + return errInvalidUncleHash + } + + if header.WithdrawalsHash != nil { + return consensus.ErrUnexpectedWithdrawals + } + + return nil +} + // verifyCascadingFields verifies all the header fields that are not standalone, // rather depend on a batch of previous headers. The caller may optionally pass // in a batch of parents (ascending order) to avoid looking those up from the @@ -573,12 +580,30 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *t return consensus.ErrUnknownAncestor } + if parent.Time+c.config.CalculatePeriod(number) > header.Time { + return ErrInvalidTimestamp + } + + return ValidateHeaderGas(header, parent, chain.Config()) +} + +// ValidateHeaderGas validates GasUsed, GasLimit and BaseFee. +func ValidateHeaderGas(header *types.Header, parent *types.Header, chainConfig *chain.Config) error { + // Verify that the gas limit is <= 2^63-1 + if header.GasLimit > params.MaxGasLimit { + return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, params.MaxGasLimit) + } + // Verify that the gasUsed is <= gasLimit if header.GasUsed > header.GasLimit { return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit) } - if !chain.Config().IsLondon(header.Number.Uint64()) { + if parent == nil { + return nil + } + + if !chainConfig.IsLondon(header.Number.Uint64()) { // Verify BaseFee not present before EIP-1559 fork. if header.BaseFee != nil { return fmt.Errorf("invalid baseFee before fork: have %d, want ", header.BaseFee) @@ -586,14 +611,11 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *t if err := misc.VerifyGaslimit(parent.GasLimit, header.GasLimit); err != nil { return err } - } else if err := misc.VerifyEip1559Header(chain.Config(), parent, header, false /*skipGasLimit*/); err != nil { + } else if err := misc.VerifyEip1559Header(chainConfig, parent, header, false /*skipGasLimit*/); err != nil { // Verify the header's EIP-1559 attributes. return err } - if parent.Time+c.config.CalculatePeriod(number) > header.Time { - return ErrInvalidTimestamp - } return nil } diff --git a/polygon/bor/snapshot.go b/polygon/bor/snapshot.go index 2427821ffa8..a41c2acad1c 100644 --- a/polygon/bor/snapshot.go +++ b/polygon/bor/snapshot.go @@ -152,7 +152,7 @@ func (s *Snapshot) Apply(parent *types.Header, headers []*types.Header, logger l // change validator set and change proposer if number > 0 && (number+1)%sprintLen == 0 { - if err := ValidateHeaderExtraField(header.Extra); err != nil { + if err := ValidateHeaderExtraLength(header.Extra); err != nil { return snap, err } validatorBytes := GetValidatorBytes(header, s.config) diff --git a/polygon/sync/canonical_chain_builder.go b/polygon/sync/canonical_chain_builder.go index d808a7d20c0..ea864c5cc73 100644 --- a/polygon/sync/canonical_chain_builder.go +++ b/polygon/sync/canonical_chain_builder.go @@ -38,18 +38,18 @@ type canonicalChainBuilderImpl struct { difficultyCalc DifficultyCalculator - headerTimeValidator HeaderTimeValidator + headerValidator HeaderValidator } func NewCanonicalChainBuilder( root *types.Header, difficultyCalc DifficultyCalculator, - headerTimeValidator HeaderTimeValidator, + headerValidator HeaderValidator, ) CanonicalChainBuilder { impl := &canonicalChainBuilderImpl{ difficultyCalc: difficultyCalc, - headerTimeValidator: headerTimeValidator, + headerValidator: headerValidator, } impl.Reset(root) return impl @@ -204,16 +204,12 @@ func (impl *canonicalChainBuilderImpl) Connect(headers []*types.Header) error { return errors.New("canonicalChainBuilderImpl.Connect: invalid header.Number") } - if impl.headerTimeValidator != nil { - if err := impl.headerTimeValidator.ValidateHeaderTime(header, time.Now(), parent.header); err != nil { - return fmt.Errorf("canonicalChainBuilderImpl.Connect: invalid header.Time - %w", err) + if impl.headerValidator != nil { + if err := impl.headerValidator.ValidateHeader(header, parent.header, time.Now()); err != nil { + return fmt.Errorf("canonicalChainBuilderImpl.Connect: invalid header error %w", err) } } - if err := bor.ValidateHeaderExtraField(header.Extra); err != nil { - return fmt.Errorf("canonicalChainBuilderImpl.Connect: invalid header.Extra %w", err) - } - difficulty, err := impl.difficultyCalc.HeaderDifficulty(header) if err != nil { return fmt.Errorf("canonicalChainBuilderImpl.Connect: header difficulty error %w", err) diff --git a/polygon/sync/header_validator.go b/polygon/sync/header_validator.go new file mode 100644 index 00000000000..81b0cf983e2 --- /dev/null +++ b/polygon/sync/header_validator.go @@ -0,0 +1,57 @@ +package sync + +import ( + "time" + + "github.com/ledgerwatch/erigon-lib/chain" + "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/polygon/bor" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" +) + +type HeaderValidator interface { + ValidateHeader(header *types.Header, parent *types.Header, now time.Time) error +} + +type headerValidatorImpl struct { + chainConfig *chain.Config + borConfig *borcfg.BorConfig + headerTimeValidator HeaderTimeValidator +} + +func NewHeaderValidator( + chainConfig *chain.Config, + borConfig *borcfg.BorConfig, + headerTimeValidator HeaderTimeValidator, +) HeaderValidator { + return &headerValidatorImpl{ + chainConfig: chainConfig, + borConfig: borConfig, + headerTimeValidator: headerTimeValidator, + } +} + +func (impl *headerValidatorImpl) ValidateHeader(header *types.Header, parent *types.Header, now time.Time) error { + if err := bor.ValidateHeaderUnusedFields(header); err != nil { + return err + } + + if err := bor.ValidateHeaderGas(header, parent, impl.chainConfig); err != nil { + return err + } + + if err := bor.ValidateHeaderExtraLength(header.Extra); err != nil { + return err + } + if err := bor.ValidateHeaderSprintValidators(header, impl.borConfig); err != nil { + return err + } + + if impl.headerTimeValidator != nil { + if err := impl.headerTimeValidator.ValidateHeaderTime(header, now, parent); err != nil { + return err + } + } + + return nil +} diff --git a/turbo/jsonrpc/bor_snapshot.go b/turbo/jsonrpc/bor_snapshot.go index 5defed92a3d..f59c29951ce 100644 --- a/turbo/jsonrpc/bor_snapshot.go +++ b/turbo/jsonrpc/bor_snapshot.go @@ -499,7 +499,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) { // change validator set and change proposer if number > 0 && (number+1)%currentLen == 0 { - if err := bor.ValidateHeaderExtraField(header.Extra); err != nil { + if err := bor.ValidateHeaderExtraLength(header.Extra); err != nil { return nil, err } validatorBytes := header.Extra[extraVanity : len(header.Extra)-extraSeal] From 7b58dab99819e2cf2ecdeeb8a1366c4df516ecc8 Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Sat, 13 Jan 2024 01:12:02 +0100 Subject: [PATCH 58/92] Added LightClient Containers (#9222) --- cl/cltypes/light_client.go | 289 ++++++++++++++++++++++++ cl/spectest/consensus_tests/appendix.go | 10 +- 2 files changed, 294 insertions(+), 5 deletions(-) create mode 100644 cl/cltypes/light_client.go diff --git a/cl/cltypes/light_client.go b/cl/cltypes/light_client.go new file mode 100644 index 00000000000..b68b1d6bec9 --- /dev/null +++ b/cl/cltypes/light_client.go @@ -0,0 +1,289 @@ +package cltypes + +import ( + "github.com/ledgerwatch/erigon-lib/types/clonable" + "github.com/ledgerwatch/erigon/cl/clparams" + "github.com/ledgerwatch/erigon/cl/cltypes/solid" + "github.com/ledgerwatch/erigon/cl/merkle_tree" + ssz2 "github.com/ledgerwatch/erigon/cl/ssz" +) + +const ( + ExecutionBranchSize = 4 + SyncCommitteeBranchSize = 5 + CurrentSyncCommitteeBranchSize = 5 + FinalizedBranchSize = 6 +) + +type LightClientHeader struct { + Beacon *BeaconBlockHeader `json:"beacon"` + + ExecutionPayloadHeader *Eth1Header `json:"execution_payload_header,omitempty"` + ExecutionBranch solid.HashVectorSSZ `json:"execution_branch,omitempty"` + + version clparams.StateVersion +} + +func NewLightClientHeader(version clparams.StateVersion) *LightClientHeader { + return &LightClientHeader{ + version: version, + Beacon: &BeaconBlockHeader{}, + ExecutionBranch: solid.NewHashVector(ExecutionBranchSize), + ExecutionPayloadHeader: NewEth1Header(version), + } +} + +func (l *LightClientHeader) EncodeSSZ(buf []byte) ([]byte, error) { + return ssz2.MarshalSSZ(buf, l.getSchema()...) +} + +func (l *LightClientHeader) DecodeSSZ(buf []byte, version int) error { + l.version = clparams.StateVersion(version) + l.Beacon = &BeaconBlockHeader{} + l.ExecutionBranch = solid.NewHashVector(ExecutionBranchSize) + l.ExecutionPayloadHeader = NewEth1Header(l.version) + return ssz2.UnmarshalSSZ(buf, version, l.getSchema()...) +} + +func (l *LightClientHeader) EncodingSizeSSZ() int { + size := l.Beacon.EncodingSizeSSZ() + if l.version >= clparams.CapellaVersion { + size += l.ExecutionPayloadHeader.EncodingSizeSSZ() + 4 // the extra 4 is for the offset + size += l.ExecutionBranch.EncodingSizeSSZ() + } + return size +} + +func (l *LightClientHeader) HashSSZ() ([32]byte, error) { + return merkle_tree.HashTreeRoot(l.getSchema()...) +} + +func (l *LightClientHeader) Static() bool { + return l.version < clparams.CapellaVersion +} + +func (l *LightClientHeader) Clone() clonable.Clonable { + return NewLightClientHeader(l.version) +} + +func (l *LightClientHeader) getSchema() []interface{} { + schema := []interface{}{ + l.Beacon, + } + if l.version >= clparams.CapellaVersion { + schema = append(schema, l.ExecutionPayloadHeader, l.ExecutionBranch) + } + return schema +} + +type LightClientUpdate struct { + AttestedHeader *LightClientHeader `json:"attested_header"` + NextSyncCommittee *solid.SyncCommittee `json:"next_sync_committee"` + NextSyncCommitteeBranch solid.HashVectorSSZ `json:"next_sync_committee_branch"` + FinalizedHeader *LightClientHeader `json:"finalized_header"` + FinalityBranch solid.HashVectorSSZ `json:"finality_branch"` + SyncAggregate *SyncAggregate `json:"sync_aggregate"` + SignatureSlot uint64 `json:"signature_slot,string"` +} + +func NewLightClientUpdate(version clparams.StateVersion) *LightClientUpdate { + return &LightClientUpdate{ + AttestedHeader: NewLightClientHeader(version), + NextSyncCommittee: &solid.SyncCommittee{}, + NextSyncCommitteeBranch: solid.NewHashVector(CurrentSyncCommitteeBranchSize), + FinalizedHeader: NewLightClientHeader(version), + FinalityBranch: solid.NewHashVector(FinalizedBranchSize), + SyncAggregate: &SyncAggregate{}, + } +} + +func (l *LightClientUpdate) EncodeSSZ(buf []byte) ([]byte, error) { + return ssz2.MarshalSSZ(buf, l.AttestedHeader, l.NextSyncCommittee, l.NextSyncCommitteeBranch, l.FinalizedHeader, l.FinalityBranch, l.SyncAggregate, &l.SignatureSlot) +} + +func (l *LightClientUpdate) DecodeSSZ(buf []byte, version int) error { + l.AttestedHeader = NewLightClientHeader(clparams.StateVersion(version)) + l.NextSyncCommittee = &solid.SyncCommittee{} + l.NextSyncCommitteeBranch = solid.NewHashVector(CurrentSyncCommitteeBranchSize) + l.FinalizedHeader = NewLightClientHeader(clparams.StateVersion(version)) + l.FinalityBranch = solid.NewHashVector(FinalizedBranchSize) + l.SyncAggregate = &SyncAggregate{} + return ssz2.UnmarshalSSZ(buf, version, l.AttestedHeader, l.NextSyncCommittee, l.NextSyncCommitteeBranch, l.FinalizedHeader, l.FinalityBranch, l.SyncAggregate, &l.SignatureSlot) +} + +func (l *LightClientUpdate) EncodingSizeSSZ() int { + size := l.AttestedHeader.EncodingSizeSSZ() + if !l.AttestedHeader.Static() { + size += 4 // the extra 4 is for the offset + } + size += l.NextSyncCommittee.EncodingSizeSSZ() + size += l.NextSyncCommitteeBranch.EncodingSizeSSZ() + size += l.FinalizedHeader.EncodingSizeSSZ() + if !l.FinalizedHeader.Static() { + size += 4 // the extra 4 is for the offset + } + size += l.FinalityBranch.EncodingSizeSSZ() + size += l.SyncAggregate.EncodingSizeSSZ() + size += 8 // for the slot + return size +} + +func (l *LightClientUpdate) HashSSZ() ([32]byte, error) { + return merkle_tree.HashTreeRoot(l.AttestedHeader, l.NextSyncCommittee, l.NextSyncCommitteeBranch, l.FinalizedHeader, l.FinalityBranch, l.SyncAggregate, &l.SignatureSlot) +} + +func (l *LightClientUpdate) Clone() clonable.Clonable { + v := clparams.Phase0Version + if l.AttestedHeader != nil { + v = l.AttestedHeader.version + } + return NewLightClientUpdate(v) +} + +type LightClientBootstrap struct { + Header *LightClientHeader `json:"header"` + CurrentSyncCommittee *solid.SyncCommittee `json:"current_sync_committee"` + CurrentSyncCommitteeBranch solid.HashVectorSSZ `json:"current_sync_committee_branch"` +} + +func NewLightClientBootstrap(version clparams.StateVersion) *LightClientBootstrap { + return &LightClientBootstrap{ + Header: NewLightClientHeader(version), + CurrentSyncCommittee: &solid.SyncCommittee{}, + CurrentSyncCommitteeBranch: solid.NewHashVector(CurrentSyncCommitteeBranchSize), + } +} + +func (l *LightClientBootstrap) EncodeSSZ(buf []byte) ([]byte, error) { + return ssz2.MarshalSSZ(buf, l.Header, l.CurrentSyncCommittee, l.CurrentSyncCommitteeBranch) +} + +func (l *LightClientBootstrap) DecodeSSZ(buf []byte, version int) error { + l.Header = NewLightClientHeader(clparams.StateVersion(version)) + l.CurrentSyncCommittee = &solid.SyncCommittee{} + l.CurrentSyncCommitteeBranch = solid.NewHashVector(CurrentSyncCommitteeBranchSize) + return ssz2.UnmarshalSSZ(buf, version, l.Header, l.CurrentSyncCommittee, l.CurrentSyncCommitteeBranch) +} + +func (l *LightClientBootstrap) EncodingSizeSSZ() int { + size := l.Header.EncodingSizeSSZ() + if !l.Header.Static() { + size += 4 // the extra 4 is for the offset + } + size += l.CurrentSyncCommittee.EncodingSizeSSZ() + size += l.CurrentSyncCommitteeBranch.EncodingSizeSSZ() + return size +} + +func (l *LightClientBootstrap) HashSSZ() ([32]byte, error) { + return merkle_tree.HashTreeRoot(l.Header, l.CurrentSyncCommittee, l.CurrentSyncCommitteeBranch) +} + +func (l *LightClientBootstrap) Clone() clonable.Clonable { + v := clparams.Phase0Version + if l.Header != nil { + v = l.Header.version + } + return NewLightClientBootstrap(v) +} + +type LightClientFinalityUpdate struct { + AttestedHeader *LightClientHeader `json:"attested_header"` + FinalizedHeader *LightClientHeader `json:"finalized_header"` + FinalityBranch solid.HashVectorSSZ `json:"finality_branch"` + SyncAggregate *SyncAggregate `json:"sync_aggregate"` + SignatureSlot uint64 `json:"signature_slot,string"` +} + +func NewLightClientFinalityUpdate(version clparams.StateVersion) *LightClientFinalityUpdate { + return &LightClientFinalityUpdate{ + AttestedHeader: NewLightClientHeader(version), + FinalizedHeader: NewLightClientHeader(version), + FinalityBranch: solid.NewHashVector(FinalizedBranchSize), + SyncAggregate: &SyncAggregate{}, + } +} + +func (l *LightClientFinalityUpdate) EncodeSSZ(buf []byte) ([]byte, error) { + return ssz2.MarshalSSZ(buf, l.AttestedHeader, l.FinalizedHeader, l.FinalityBranch, l.SyncAggregate, &l.SignatureSlot) +} + +func (l *LightClientFinalityUpdate) DecodeSSZ(buf []byte, version int) error { + l.AttestedHeader = NewLightClientHeader(clparams.StateVersion(version)) + l.FinalizedHeader = NewLightClientHeader(clparams.StateVersion(version)) + l.FinalityBranch = solid.NewHashVector(FinalizedBranchSize) + l.SyncAggregate = &SyncAggregate{} + return ssz2.UnmarshalSSZ(buf, version, l.AttestedHeader, l.FinalizedHeader, l.FinalityBranch, l.SyncAggregate, &l.SignatureSlot) +} + +func (l *LightClientFinalityUpdate) EncodingSizeSSZ() int { + size := l.AttestedHeader.EncodingSizeSSZ() + if !l.AttestedHeader.Static() { + size += 4 // the extra 4 is for the offset + } + size += l.FinalizedHeader.EncodingSizeSSZ() + if !l.FinalizedHeader.Static() { + size += 4 // the extra 4 is for the offset + } + size += l.FinalityBranch.EncodingSizeSSZ() + size += l.SyncAggregate.EncodingSizeSSZ() + size += 8 // for the slot + return size +} + +func (l *LightClientFinalityUpdate) HashSSZ() ([32]byte, error) { + return merkle_tree.HashTreeRoot(l.AttestedHeader, l.FinalizedHeader, l.FinalityBranch, l.SyncAggregate, &l.SignatureSlot) +} + +func (l *LightClientFinalityUpdate) Clone() clonable.Clonable { + v := clparams.Phase0Version + if l.AttestedHeader != nil { + v = l.AttestedHeader.version + } + return NewLightClientFinalityUpdate(v) +} + +type LightClientOptimisticUpdate struct { + AttestedHeader *LightClientHeader `json:"attested_header"` + SyncAggregate *SyncAggregate `json:"sync_aggregate"` + SignatureSlot uint64 `json:"signature_slot,string"` +} + +func NewLightClientOptimisticUpdate(version clparams.StateVersion) *LightClientOptimisticUpdate { + return &LightClientOptimisticUpdate{ + AttestedHeader: NewLightClientHeader(version), + SyncAggregate: &SyncAggregate{}, + } +} + +func (l *LightClientOptimisticUpdate) EncodeSSZ(buf []byte) ([]byte, error) { + return ssz2.MarshalSSZ(buf, l.AttestedHeader, l.SyncAggregate, &l.SignatureSlot) +} + +func (l *LightClientOptimisticUpdate) DecodeSSZ(buf []byte, version int) error { + l.AttestedHeader = NewLightClientHeader(clparams.StateVersion(version)) + l.SyncAggregate = &SyncAggregate{} + return ssz2.UnmarshalSSZ(buf, version, l.AttestedHeader, l.SyncAggregate, &l.SignatureSlot) +} + +func (l *LightClientOptimisticUpdate) EncodingSizeSSZ() int { + size := l.AttestedHeader.EncodingSizeSSZ() + if !l.AttestedHeader.Static() { + size += 4 // the extra 4 is for the offset + } + size += l.SyncAggregate.EncodingSizeSSZ() + size += 8 // for the slot + return size +} + +func (l *LightClientOptimisticUpdate) HashSSZ() ([32]byte, error) { + return merkle_tree.HashTreeRoot(l.AttestedHeader, l.SyncAggregate, &l.SignatureSlot) +} + +func (l *LightClientOptimisticUpdate) Clone() clonable.Clonable { + v := clparams.Phase0Version + if l.AttestedHeader != nil { + v = l.AttestedHeader.version + } + return NewLightClientOptimisticUpdate(v) +} diff --git a/cl/spectest/consensus_tests/appendix.go b/cl/spectest/consensus_tests/appendix.go index 788ac359a65..5a7342cb60e 100644 --- a/cl/spectest/consensus_tests/appendix.go +++ b/cl/spectest/consensus_tests/appendix.go @@ -106,11 +106,11 @@ func addSszTests() { //With("HistoricalBatch", getSSZStaticConsensusTest(&cltypes.HistoricalBatch{})). With("HistoricalSummary", getSSZStaticConsensusTest(&cltypes.HistoricalSummary{})). With("IndexedAttestation", getSSZStaticConsensusTest(&cltypes.IndexedAttestation{})). - // With("LightClientBootstrap", getSSZStaticConsensusTest(&cltypes.LightClientBootstrap{})). Unimplemented - // With("LightClientFinalityUpdate", getSSZStaticConsensusTest(&cltypes.LightClientFinalityUpdate{})). Unimplemented - // With("LightClientHeader", getSSZStaticConsensusTest(&cltypes.LightClientHeader{})). Unimplemented - // With("LightClientOptimisticUpdate", getSSZStaticConsensusTest(&cltypes.LightClientOptimisticUpdate{})). Unimplemented - // With("LightClientUpdate", getSSZStaticConsensusTest(&cltypes.LightClientUpdate{})). Unimplemented + With("LightClientBootstrap", getSSZStaticConsensusTest(&cltypes.LightClientBootstrap{})). + With("LightClientFinalityUpdate", getSSZStaticConsensusTest(&cltypes.LightClientFinalityUpdate{})). + With("LightClientHeader", getSSZStaticConsensusTest(&cltypes.LightClientHeader{})). + With("LightClientOptimisticUpdate", getSSZStaticConsensusTest(&cltypes.LightClientOptimisticUpdate{})). + With("LightClientUpdate", getSSZStaticConsensusTest(&cltypes.LightClientUpdate{})). With("PendingAttestation", getSSZStaticConsensusTest(&solid.PendingAttestation{})). // With("PowBlock", getSSZStaticConsensusTest(&cltypes.PowBlock{})). Unimplemented With("ProposerSlashing", getSSZStaticConsensusTest(&cltypes.ProposerSlashing{})). From 2b0fd6d44748065ec8ccc80e278992c44c0ff015 Mon Sep 17 00:00:00 2001 From: Pan chao <152830401+Pan-chao@users.noreply.github.com> Date: Sat, 13 Jan 2024 06:04:55 +0100 Subject: [PATCH 59/92] chore: some proofreading in the docs (#9223) Hi, caught a few mistakes while reading the docs. Hope I can be of any help. Have a nice day. --- docs/readthedocs/source/etl.rst | 2 +- docs/readthedocs/source/rpc/index.rst | 2 +- docs/readthedocs/source/stagedsync.rst | 2 +- docs/readthedocs/source/types.rst | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/readthedocs/source/etl.rst b/docs/readthedocs/source/etl.rst index 3fbbc2e5c0a..4e12ddbcdf2 100644 --- a/docs/readthedocs/source/etl.rst +++ b/docs/readthedocs/source/etl.rst @@ -110,7 +110,7 @@ To avoid that, the ETL framework allows storing progress by setting `OnLoadCommi Then we can use this data to know the progress the ETL transformation made. -You can also specify `ExtractStartKey` and `ExtractEndKey` to limit the nubmer +You can also specify `ExtractStartKey` and `ExtractEndKey` to limit the number of items transformed. diff --git a/docs/readthedocs/source/rpc/index.rst b/docs/readthedocs/source/rpc/index.rst index 8114154fba7..78c2c520476 100644 --- a/docs/readthedocs/source/rpc/index.rst +++ b/docs/readthedocs/source/rpc/index.rst @@ -1842,7 +1842,7 @@ Submit the mining hashrate to the blockchain. * - Type - Description * - ``BOOLEAN`` - - ``true`` if submitting went through succesfully, ``false`` otherwise + - ``true`` if submitting went through successfully, ``false`` otherwise -------------- diff --git a/docs/readthedocs/source/stagedsync.rst b/docs/readthedocs/source/stagedsync.rst index 537ce3afef3..fef78f79c08 100644 --- a/docs/readthedocs/source/stagedsync.rst +++ b/docs/readthedocs/source/stagedsync.rst @@ -42,7 +42,7 @@ the process method takes the headers retrieve thanks to the fetcher and does the * Save block headers in database. -This process repeates until we reach the maximun height. once it is reached the stage finish. +This process repeats until we reach the maximum height. once it is reached the stage finish. Changes in DB: diff --git a/docs/readthedocs/source/types.rst b/docs/readthedocs/source/types.rst index f5f88ea8832..2af774f3b4d 100644 --- a/docs/readthedocs/source/types.rst +++ b/docs/readthedocs/source/types.rst @@ -22,7 +22,7 @@ Address represents the 20 byte address of an Ethereum account. type Hash [32]byte Hash represents the 32 byte Keccak256 hash of arbitrary data. -Address repressents the 20 byte standard Ethereum Address +Address represents the 20 byte standard Ethereum Address Both Hash and Address are bytes arrays. @@ -60,7 +60,7 @@ Transaction type Transactions []*Transaction -repressent an Ethereum Transaction. +represent an Ethereum Transaction. **from** @@ -218,7 +218,7 @@ Block ReceivedFrom interface{} } -repressent a block of the chain. +represent a block of the chain. **header** From d8b91c4d024ab74d5898e3d057f674123cc3b272 Mon Sep 17 00:00:00 2001 From: Mark Holt <135143369+mh0lt@users.noreply.github.com> Date: Sat, 13 Jan 2024 10:33:34 +0000 Subject: [PATCH 60/92] Fix startup sync for txpool processing for bor block production (#9219) When the sync loop first runs it suppresses block sync events both in the initial loop and when the blocks being processed are greater than 1000. This fix removed the first check, because otherwise the first block received by the process ends up not getting sent to the tx pool. Which means it won't produce new block for polygon. As well as this fix - I have also moved the gas initialization to the txpool start method rather than prompting it with a 'synthetic block event' As the txpool start has access to the core & tx DB's it can find the current block and chain config internally so that it doesn't need to be externally activated it can just do this itself on start up. This has the advantage of making the txpool more self contained. --- cmd/txpool/main.go | 5 ++- consensus/misc/eip1559.go | 39 +++++++++++++++++++ erigon-lib/chain/chain_config.go | 8 ++-- erigon-lib/txpool/pool.go | 31 +++++++++++---- erigon-lib/txpool/pool_fuzz_test.go | 4 +- erigon-lib/txpool/pool_test.go | 14 +++---- .../txpool/txpooluitl/all_components.go | 4 +- eth/backend.go | 23 ++--------- eth/stagedsync/stage_execute.go | 17 ++++---- turbo/shards/state_change_accumulator.go | 1 + .../snapshotsync/freezeblocks/block_reader.go | 9 ++++- .../freezeblocks/block_snapshots.go | 8 +++- turbo/stages/mock/mock_sentry.go | 4 +- 13 files changed, 110 insertions(+), 57 deletions(-) diff --git a/cmd/txpool/main.go b/cmd/txpool/main.go index 463be539be8..905ba3ef774 100644 --- a/cmd/txpool/main.go +++ b/cmd/txpool/main.go @@ -24,6 +24,7 @@ import ( "github.com/ledgerwatch/erigon-lib/types" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/rpcdaemontest" common2 "github.com/ledgerwatch/erigon/common" + "github.com/ledgerwatch/erigon/consensus/misc" "github.com/ledgerwatch/erigon/ethdb/privateapi" "github.com/ledgerwatch/log/v3" "github.com/spf13/cobra" @@ -163,7 +164,7 @@ func doTxpool(ctx context.Context, logger log.Logger) error { newTxs := make(chan types.Announcements, 1024) defer close(newTxs) txPoolDB, txPool, fetch, send, txpoolGrpcServer, err := txpooluitl.AllComponents(ctx, cfg, - kvcache.New(cacheConfig), newTxs, coreDB, sentryClients, kvClient, logger) + kvcache.New(cacheConfig), newTxs, coreDB, sentryClients, kvClient, misc.Eip1559FeeCalculator, logger) if err != nil { return err } @@ -178,7 +179,7 @@ func doTxpool(ctx context.Context, logger log.Logger) error { } notifyMiner := func() {} - txpool.MainLoop(ctx, txPoolDB, coreDB, txPool, newTxs, send, txpoolGrpcServer.NewSlotsStreams, notifyMiner) + txpool.MainLoop(ctx, txPoolDB, txPool, newTxs, send, txpoolGrpcServer.NewSlotsStreams, notifyMiner) grpcServer.GracefulStop() return nil diff --git a/consensus/misc/eip1559.go b/consensus/misc/eip1559.go index de5b4ec0118..b2a53af3f53 100644 --- a/consensus/misc/eip1559.go +++ b/consensus/misc/eip1559.go @@ -22,9 +22,12 @@ import ( "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon-lib/common" + libcommon "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon/polygon/bor/borcfg" "github.com/ledgerwatch/erigon/common/math" + "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/params" ) @@ -56,6 +59,42 @@ func VerifyEip1559Header(config *chain.Config, parent, header *types.Header, ski return nil } +var Eip1559FeeCalculator eip1559Calculator + +type eip1559Calculator struct{} + +func (f eip1559Calculator) CurrentFees(chainConfig *chain.Config, db kv.Getter) (baseFee uint64, blobFee uint64, minBlobGasPrice uint64, err error) { + hash := rawdb.ReadHeadHeaderHash(db) + + if hash == (libcommon.Hash{}) { + return 0, 0, 0, fmt.Errorf("can't get head header hash") + } + + currentHeader, err := rawdb.ReadHeaderByHash(db, hash) + + if err != nil { + return 0, 0, 0, err + } + + if chainConfig != nil { + if currentHeader.BaseFee != nil { + baseFee = CalcBaseFee(chainConfig, currentHeader).Uint64() + } + + if currentHeader.ExcessBlobGas != nil { + excessBlobGas := CalcExcessBlobGas(chainConfig, currentHeader) + b, err := GetBlobGasPrice(chainConfig, excessBlobGas) + if err == nil { + blobFee = b.Uint64() + } + } + } + + minBlobGasPrice = chainConfig.GetMinBlobGasPrice() + + return baseFee, blobFee, minBlobGasPrice, nil +} + // CalcBaseFee calculates the basefee of the header. func CalcBaseFee(config *chain.Config, parent *types.Header) *big.Int { // If the current block is the first EIP-1559 block, return the InitialBaseFee. diff --git a/erigon-lib/chain/chain_config.go b/erigon-lib/chain/chain_config.go index cc8fe6d9468..bb5125660a3 100644 --- a/erigon-lib/chain/chain_config.go +++ b/erigon-lib/chain/chain_config.go @@ -233,28 +233,28 @@ func (c *Config) GetBurntContract(num uint64) *common.Address { } func (c *Config) GetMinBlobGasPrice() uint64 { - if c.MinBlobGasPrice != nil { + if c != nil && c.MinBlobGasPrice != nil { return *c.MinBlobGasPrice } return 1 // MIN_BLOB_GASPRICE (EIP-4844) } func (c *Config) GetMaxBlobGasPerBlock() uint64 { - if c.MaxBlobGasPerBlock != nil { + if c != nil && c.MaxBlobGasPerBlock != nil { return *c.MaxBlobGasPerBlock } return 786432 // MAX_BLOB_GAS_PER_BLOCK (EIP-4844) } func (c *Config) GetTargetBlobGasPerBlock() uint64 { - if c.TargetBlobGasPerBlock != nil { + if c != nil && c.TargetBlobGasPerBlock != nil { return *c.TargetBlobGasPerBlock } return 393216 // TARGET_BLOB_GAS_PER_BLOCK (EIP-4844) } func (c *Config) GetBlobGasPriceUpdateFraction() uint64 { - if c.BlobGasPriceUpdateFraction != nil { + if c != nil && c.BlobGasPriceUpdateFraction != nil { return *c.BlobGasPriceUpdateFraction } return 3338477 // BLOB_GASPRICE_UPDATE_FRACTION (EIP-4844) diff --git a/erigon-lib/txpool/pool.go b/erigon-lib/txpool/pool.go index e6e479815eb..88026073a99 100644 --- a/erigon-lib/txpool/pool.go +++ b/erigon-lib/txpool/pool.go @@ -225,11 +225,17 @@ type TxPool struct { cancunTime *uint64 isPostCancun atomic.Bool maxBlobsPerBlock uint64 + feeCalculator FeeCalculator logger log.Logger } +type FeeCalculator interface { + CurrentFees(chainConfig *chain.Config, db kv.Getter) (baseFee uint64, blobFee uint64, minBlobGasPrice uint64, err error) +} + func New(newTxs chan types.Announcements, coreDB kv.RoDB, cfg txpoolcfg.Config, cache kvcache.Cache, - chainID uint256.Int, shanghaiTime, agraBlock, cancunTime *big.Int, maxBlobsPerBlock uint64, logger log.Logger, + chainID uint256.Int, shanghaiTime, agraBlock, cancunTime *big.Int, maxBlobsPerBlock uint64, + feeCalculator FeeCalculator, logger log.Logger, ) (*TxPool, error) { localsHistory, err := simplelru.NewLRU[string, struct{}](10_000, nil) if err != nil { @@ -275,6 +281,7 @@ func New(newTxs chan types.Announcements, coreDB kv.RoDB, cfg txpoolcfg.Config, minedBlobTxsByBlock: map[uint64][]*metaTx{}, minedBlobTxsByHash: map[string]*metaTx{}, maxBlobsPerBlock: maxBlobsPerBlock, + feeCalculator: feeCalculator, logger: logger, } @@ -331,7 +338,6 @@ func (p *TxPool) Start(ctx context.Context, db kv.RwDB) error { } func (p *TxPool) OnNewBlock(ctx context.Context, stateChanges *remote.StateChangeBatch, unwindTxs, minedTxs types.TxSlots, tx kv.Tx) error { - defer newBlockTimer.ObserveDuration(time.Now()) //t := time.Now() @@ -1700,7 +1706,7 @@ const txMaxBroadcastSize = 4 * 1024 // // promote/demote transactions // reorgs -func MainLoop(ctx context.Context, db kv.RwDB, coreDB kv.RoDB, p *TxPool, newTxs chan types.Announcements, send *Send, newSlotsStreams *NewSlotsStreams, notifyMiningAboutNewSlots func()) { +func MainLoop(ctx context.Context, db kv.RwDB, p *TxPool, newTxs chan types.Announcements, send *Send, newSlotsStreams *NewSlotsStreams, notifyMiningAboutNewSlots func()) { syncToNewPeersEvery := time.NewTicker(p.cfg.SyncToNewPeersEvery) defer syncToNewPeersEvery.Stop() processRemoteTxsEvery := time.NewTicker(p.cfg.ProcessRemoteTxsEvery) @@ -2072,8 +2078,15 @@ func (p *TxPool) fromDB(ctx context.Context, tx kv.Tx, coreTx kv.Tx) error { i++ } - var pendingBaseFee uint64 - { + var pendingBaseFee, pendingBlobFee, minBlobGasPrice uint64 + + if p.feeCalculator != nil { + if chainConfig, _ := ChainConfig(tx); chainConfig != nil { + pendingBaseFee, pendingBlobFee, minBlobGasPrice, _ = p.feeCalculator.CurrentFees(chainConfig, coreTx) + } + } + + if pendingBaseFee == 0 { v, err := tx.GetOne(kv.PoolInfo, PoolPendingBaseFeeKey) if err != nil { return err @@ -2082,8 +2095,8 @@ func (p *TxPool) fromDB(ctx context.Context, tx kv.Tx, coreTx kv.Tx) error { pendingBaseFee = binary.BigEndian.Uint64(v) } } - var pendingBlobFee uint64 = 1 // MIN_BLOB_GAS_PRICE A/EIP-4844 - { + + if pendingBlobFee == 0 { v, err := tx.GetOne(kv.PoolInfo, PoolPendingBlobFeeKey) if err != nil { return err @@ -2093,6 +2106,10 @@ func (p *TxPool) fromDB(ctx context.Context, tx kv.Tx, coreTx kv.Tx) error { } } + if pendingBlobFee == 0 { + pendingBlobFee = minBlobGasPrice + } + err = p.senders.registerNewSenders(&txs, p.logger) if err != nil { return err diff --git a/erigon-lib/txpool/pool_fuzz_test.go b/erigon-lib/txpool/pool_fuzz_test.go index 1e8923d88fd..08106374cdf 100644 --- a/erigon-lib/txpool/pool_fuzz_test.go +++ b/erigon-lib/txpool/pool_fuzz_test.go @@ -314,7 +314,7 @@ func FuzzOnNewBlocks(f *testing.F) { cfg := txpoolcfg.DefaultConfig sendersCache := kvcache.New(kvcache.DefaultCoherentConfig) - pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, log.New()) + pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New()) assert.NoError(err) err = pool.Start(ctx, db) @@ -540,7 +540,7 @@ func FuzzOnNewBlocks(f *testing.F) { check(p2pReceived, types.TxSlots{}, "after_flush") checkNotify(p2pReceived, types.TxSlots{}, "after_flush") - p2, err := New(ch, coreDB, txpoolcfg.DefaultConfig, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, log.New()) + p2, err := New(ch, coreDB, txpoolcfg.DefaultConfig, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New()) assert.NoError(err) p2.senders = pool.senders // senders are not persisted diff --git a/erigon-lib/txpool/pool_test.go b/erigon-lib/txpool/pool_test.go index ef4347a587e..80de08a511d 100644 --- a/erigon-lib/txpool/pool_test.go +++ b/erigon-lib/txpool/pool_test.go @@ -53,7 +53,7 @@ func TestNonceFromAddress(t *testing.T) { cfg := txpoolcfg.DefaultConfig sendersCache := kvcache.New(kvcache.DefaultCoherentConfig) - pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, log.New()) + pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New()) assert.NoError(err) require.True(pool != nil) ctx := context.Background() @@ -173,7 +173,7 @@ func TestReplaceWithHigherFee(t *testing.T) { cfg := txpoolcfg.DefaultConfig sendersCache := kvcache.New(kvcache.DefaultCoherentConfig) - pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, log.New()) + pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New()) assert.NoError(err) require.NotEqual(nil, pool) ctx := context.Background() @@ -290,7 +290,7 @@ func TestReverseNonces(t *testing.T) { cfg := txpoolcfg.DefaultConfig sendersCache := kvcache.New(kvcache.DefaultCoherentConfig) - pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, log.New()) + pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New()) assert.NoError(err) require.True(pool != nil) ctx := context.Background() @@ -417,7 +417,7 @@ func TestTxPoke(t *testing.T) { cfg := txpoolcfg.DefaultConfig sendersCache := kvcache.New(kvcache.DefaultCoherentConfig) - pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, log.New()) + pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, nil, nil, nil, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New()) assert.NoError(err) require.True(pool != nil) ctx := context.Background() @@ -682,7 +682,7 @@ func TestShanghaiValidateTx(t *testing.T) { } cache := &kvcache.DummyCache{} - pool, err := New(ch, coreDB, cfg, cache, *u256.N1, shanghaiTime, nil /* agraBlock */, nil /* cancunTime */, fixedgas.DefaultMaxBlobsPerBlock, logger) + pool, err := New(ch, coreDB, cfg, cache, *u256.N1, shanghaiTime, nil /* agraBlock */, nil /* cancunTime */, fixedgas.DefaultMaxBlobsPerBlock, nil, logger) asrt.NoError(err) ctx := context.Background() tx, err := coreDB.BeginRw(ctx) @@ -728,7 +728,7 @@ func TestBlobTxReplacement(t *testing.T) { db, coreDB := memdb.NewTestPoolDB(t), memdb.NewTestDB(t) cfg := txpoolcfg.DefaultConfig sendersCache := kvcache.New(kvcache.DefaultCoherentConfig) - pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, common.Big0, nil, common.Big0, fixedgas.DefaultMaxBlobsPerBlock, log.New()) + pool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, common.Big0, nil, common.Big0, fixedgas.DefaultMaxBlobsPerBlock, nil, log.New()) assert.NoError(err) require.True(pool != nil) ctx := context.Background() @@ -953,7 +953,7 @@ func TestDropRemoteAtNoGossip(t *testing.T) { logger := log.New() sendersCache := kvcache.New(kvcache.DefaultCoherentConfig) - txPool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, big.NewInt(0), big.NewInt(0), nil, fixedgas.DefaultMaxBlobsPerBlock, logger) + txPool, err := New(ch, coreDB, cfg, sendersCache, *u256.N1, big.NewInt(0), big.NewInt(0), nil, fixedgas.DefaultMaxBlobsPerBlock, nil, logger) assert.NoError(err) require.True(txPool != nil) diff --git a/erigon-lib/txpool/txpooluitl/all_components.go b/erigon-lib/txpool/txpooluitl/all_components.go index 156a5771c2b..ecf884bbe39 100644 --- a/erigon-lib/txpool/txpooluitl/all_components.go +++ b/erigon-lib/txpool/txpooluitl/all_components.go @@ -101,7 +101,7 @@ func SaveChainConfigIfNeed(ctx context.Context, coreDB kv.RoDB, txPoolDB kv.RwDB } func AllComponents(ctx context.Context, cfg txpoolcfg.Config, cache kvcache.Cache, newTxs chan types.Announcements, chainDB kv.RoDB, - sentryClients []direct.SentryClient, stateChangesClient txpool.StateChangesClient, logger log.Logger) (kv.RwDB, *txpool.TxPool, *txpool.Fetch, *txpool.Send, *txpool.GrpcServer, error) { + sentryClients []direct.SentryClient, stateChangesClient txpool.StateChangesClient, feeCalculator txpool.FeeCalculator, logger log.Logger) (kv.RwDB, *txpool.TxPool, *txpool.Fetch, *txpool.Send, *txpool.GrpcServer, error) { opts := mdbx.NewMDBX(logger).Label(kv.TxPoolDB).Path(cfg.DBDir). WithTableCfg(func(defaultBuckets kv.TableCfg) kv.TableCfg { return kv.TxpoolTablesCfg }). WriteMergeThreshold(3 * 8192). @@ -144,7 +144,7 @@ func AllComponents(ctx context.Context, cfg txpoolcfg.Config, cache kvcache.Cach cancunTime = cfg.OverrideCancunTime } - txPool, err := txpool.New(newTxs, chainDB, cfg, cache, *chainID, shanghaiTime, agraBlock, cancunTime, maxBlobsPerBlock, logger) + txPool, err := txpool.New(newTxs, chainDB, cfg, cache, *chainID, shanghaiTime, agraBlock, cancunTime, maxBlobsPerBlock, feeCalculator, logger) if err != nil { return nil, nil, nil, nil, nil, err } diff --git a/eth/backend.go b/eth/backend.go index 6861094462e..1b2e1baee7d 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -604,7 +604,7 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger backend.newTxs = make(chan types2.Announcements, 1024) //defer close(newTxs) backend.txPoolDB, backend.txPool, backend.txPoolFetch, backend.txPoolSend, backend.txPoolGrpcServer, err = txpooluitl.AllComponents( - ctx, config.TxPool, kvcache.NewDummy(), backend.newTxs, backend.chainDB, backend.sentriesClient.Sentries(), stateDiffClient, logger, + ctx, config.TxPool, kvcache.NewDummy(), backend.newTxs, backend.chainDB, backend.sentriesClient.Sentries(), stateDiffClient, misc.Eip1559FeeCalculator, logger, ) if err != nil { return nil, err @@ -708,23 +708,6 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger // 1) Hive tests requires us to do so and starting it from eth_sendRawTransaction is not viable as we have not enough data // to initialize it properly. // 2) we cannot propose for block 1 regardless. - go func() { - time.Sleep(10 * time.Millisecond) - baseFee := uint64(0) - if currentBlock.BaseFee() != nil { - baseFee = misc.CalcBaseFee(chainConfig, currentBlock.Header()).Uint64() - } - blobFee := chainConfig.GetMinBlobGasPrice() - if currentBlock.Header().ExcessBlobGas != nil { - excessBlobGas := misc.CalcExcessBlobGas(chainConfig, currentBlock.Header()) - b, err := misc.GetBlobGasPrice(chainConfig, excessBlobGas) - if err == nil { - blobFee = b.Uint64() - } - } - backend.notifications.Accumulator.StartChange(currentBlock.NumberU64(), currentBlock.Hash(), nil, false) - backend.notifications.Accumulator.SendAndReset(ctx, backend.notifications.StateChangesConsumer, baseFee, blobFee, currentBlock.GasLimit(), 0) - }() if !config.DeprecatedTxPool.Disable { backend.txPoolFetch.ConnectCore() @@ -734,8 +717,7 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger newTxsBroadcaster = casted.NewSlotsStreams } go txpool.MainLoop(backend.sentryCtx, - backend.txPoolDB, backend.chainDB, - backend.txPool, backend.newTxs, backend.txPoolSend, newTxsBroadcaster, + backend.txPoolDB, backend.txPool, backend.newTxs, backend.txPoolSend, newTxsBroadcaster, func() { select { case backend.notifyMiningAboutNewTxs <- struct{}{}: @@ -743,6 +725,7 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger } }) } + go func() { defer debug.LogPanic() for { diff --git a/eth/stagedsync/stage_execute.go b/eth/stagedsync/stage_execute.go index c53e1995d93..7bf77db28d3 100644 --- a/eth/stagedsync/stage_execute.go +++ b/eth/stagedsync/stage_execute.go @@ -145,12 +145,11 @@ func executeBlock( writeChangesets bool, writeReceipts bool, writeCallTraces bool, - initialCycle bool, stateStream bool, logger log.Logger, ) error { blockNum := block.NumberU64() - stateReader, stateWriter, err := newStateReaderWriter(batch, tx, block, writeChangesets, cfg.accumulator, cfg.blockReader, initialCycle, stateStream) + stateReader, stateWriter, err := newStateReaderWriter(batch, tx, block, writeChangesets, cfg.accumulator, cfg.blockReader, stateStream) if err != nil { return err } @@ -211,16 +210,14 @@ func newStateReaderWriter( writeChangesets bool, accumulator *shards.Accumulator, br services.FullBlockReader, - initialCycle bool, stateStream bool, ) (state.StateReader, state.WriterWithChangeSets, error) { - var stateReader state.StateReader var stateWriter state.WriterWithChangeSets stateReader = state.NewPlainStateReader(batch) - if !initialCycle && stateStream { + if stateStream { txs, err := br.RawTransactions(context.Background(), tx, block.NumberU64(), block.NumberU64()) if err != nil { return nil, nil, err @@ -389,16 +386,20 @@ func SpawnExecuteBlocksStage(s *StageState, u Unwinder, txc wrap.TxContainer, to logPrefix := s.LogPrefix() var to = prevStageProgress + if toBlock > 0 { to = cmp.Min(prevStageProgress, toBlock) } + if to <= s.BlockNumber { return nil } + if to > s.BlockNumber+16 { logger.Info(fmt.Sprintf("[%s] Blocks execution", logPrefix), "from", s.BlockNumber, "to", to) } - stateStream := !initialCycle && cfg.stateStream && to-s.BlockNumber < stateStreamLimit + + stateStream := cfg.stateStream && to-s.BlockNumber < stateStreamLimit // changes are stored through memory buffer logEvery := time.NewTicker(logInterval) @@ -468,7 +469,7 @@ Loop: if cfg.silkworm != nil && !isMemoryMutation { blockNum, err = silkworm.ExecuteBlocks(cfg.silkworm, txc.Tx, cfg.chainConfig.ChainID, blockNum, to, uint64(cfg.batchSize), writeChangeSets, writeReceipts, writeCallTraces) } else { - err = executeBlock(block, txc.Tx, batch, cfg, *cfg.vmConfig, writeChangeSets, writeReceipts, writeCallTraces, initialCycle, stateStream, logger) + err = executeBlock(block, txc.Tx, batch, cfg, *cfg.vmConfig, writeChangeSets, writeReceipts, writeCallTraces, stateStream, logger) } if err != nil { @@ -710,7 +711,7 @@ func unwindExecutionStage(u *UnwindState, s *StageState, txc wrap.TxContainer, c storageKeyLength := length.Addr + length.Incarnation + length.Hash var accumulator *shards.Accumulator - if !initialCycle && cfg.stateStream && s.BlockNumber-u.UnwindPoint < stateStreamLimit { + if cfg.stateStream && s.BlockNumber-u.UnwindPoint < stateStreamLimit { accumulator = cfg.accumulator hash, err := cfg.blockReader.CanonicalHash(ctx, txc.Tx, u.UnwindPoint) diff --git a/turbo/shards/state_change_accumulator.go b/turbo/shards/state_change_accumulator.go index 8ba19686ee5..cf0cc8c563b 100644 --- a/turbo/shards/state_change_accumulator.go +++ b/turbo/shards/state_change_accumulator.go @@ -32,6 +32,7 @@ func (a *Accumulator) Reset(plainStateID uint64) { a.storageChangeIndex = nil a.plainStateID = plainStateID } + func (a *Accumulator) SendAndReset(ctx context.Context, c StateChangeConsumer, pendingBaseFee uint64, pendingBlobFee uint64, blockGasLimit uint64, finalizedBlock uint64) { if a == nil || c == nil || len(a.changes) == 0 { return diff --git a/turbo/snapshotsync/freezeblocks/block_reader.go b/turbo/snapshotsync/freezeblocks/block_reader.go index a24367e8387..e80b5d35916 100644 --- a/turbo/snapshotsync/freezeblocks/block_reader.go +++ b/turbo/snapshotsync/freezeblocks/block_reader.go @@ -250,7 +250,8 @@ type BlockReader struct { func NewBlockReader(snapshots services.BlockSnapshots, borSnapshots services.BlockSnapshots) *BlockReader { borSn, _ := borSnapshots.(*BorRoSnapshots) - return &BlockReader{sn: snapshots.(*RoSnapshots), borSn: borSn} + sn, _ := snapshots.(*RoSnapshots) + return &BlockReader{sn: sn, borSn: borSn} } func (r *BlockReader) CanPruneTo(currentBlockInDB uint64) uint64 { @@ -485,7 +486,7 @@ func (r *BlockReader) BlockWithSenders(ctx context.Context, tx kv.Getter, hash c } func (r *BlockReader) blockWithSenders(ctx context.Context, tx kv.Getter, hash common.Hash, blockHeight uint64, forceCanonical bool) (block *types.Block, senders []common.Address, err error) { maxBlockNumInFiles := r.sn.BlocksAvailable() - if maxBlockNumInFiles == 0 || blockHeight > maxBlockNumInFiles { + if tx != nil && (maxBlockNumInFiles == 0 || blockHeight > maxBlockNumInFiles) { if forceCanonical { canonicalHash, err := rawdb.ReadCanonicalHash(tx, blockHeight) if err != nil { @@ -503,6 +504,10 @@ func (r *BlockReader) blockWithSenders(ctx context.Context, tx kv.Getter, hash c return block, senders, nil } + if r.sn == nil { + return + } + view := r.sn.View() defer view.Close() seg, ok := view.HeadersSegment(blockHeight) diff --git a/turbo/snapshotsync/freezeblocks/block_snapshots.go b/turbo/snapshotsync/freezeblocks/block_snapshots.go index d67457acbf9..473af96522f 100644 --- a/turbo/snapshotsync/freezeblocks/block_snapshots.go +++ b/turbo/snapshotsync/freezeblocks/block_snapshots.go @@ -406,7 +406,13 @@ func (s *RoSnapshots) IndicesMax() uint64 { return s.idxMax.Load() } func (s *RoSnapshots) SegmentsMax() uint64 { return s.segmentsMax.Load() } func (s *RoSnapshots) SegmentsMin() uint64 { return s.segmentsMin.Load() } func (s *RoSnapshots) SetSegmentsMin(min uint64) { s.segmentsMin.Store(min) } -func (s *RoSnapshots) BlocksAvailable() uint64 { return cmp.Min(s.segmentsMax.Load(), s.idxMax.Load()) } +func (s *RoSnapshots) BlocksAvailable() uint64 { + if s == nil { + return 0 + } + + return cmp.Min(s.segmentsMax.Load(), s.idxMax.Load()) +} func (s *RoSnapshots) LogStat(label string) { var m runtime.MemStats dbg.ReadMemStats(&m) diff --git a/turbo/stages/mock/mock_sentry.go b/turbo/stages/mock/mock_sentry.go index 14c83977729..6feee7c5994 100644 --- a/turbo/stages/mock/mock_sentry.go +++ b/turbo/stages/mock/mock_sentry.go @@ -311,7 +311,7 @@ func MockWithEverything(tb testing.TB, gspec *types.Genesis, key *ecdsa.PrivateK shanghaiTime := mock.ChainConfig.ShanghaiTime cancunTime := mock.ChainConfig.CancunTime maxBlobsPerBlock := mock.ChainConfig.GetMaxBlobsPerBlock() - mock.TxPool, err = txpool.New(newTxs, mock.DB, poolCfg, kvcache.NewDummy(), *chainID, shanghaiTime, nil /* agraBlock */, cancunTime, maxBlobsPerBlock, logger) + mock.TxPool, err = txpool.New(newTxs, mock.DB, poolCfg, kvcache.NewDummy(), *chainID, shanghaiTime, nil /* agraBlock */, cancunTime, maxBlobsPerBlock, nil, logger) if err != nil { tb.Fatal(err) } @@ -329,7 +329,7 @@ func MockWithEverything(tb testing.TB, gspec *types.Genesis, key *ecdsa.PrivateK mock.TxPoolFetch.ConnectSentries() mock.StreamWg.Wait() - go txpool.MainLoop(mock.Ctx, mock.txPoolDB, mock.DB, mock.TxPool, newTxs, mock.TxPoolSend, mock.TxPoolGrpcServer.NewSlotsStreams, func() {}) + go txpool.MainLoop(mock.Ctx, mock.txPoolDB, mock.TxPool, newTxs, mock.TxPoolSend, mock.TxPoolGrpcServer.NewSlotsStreams, func() {}) } // Committed genesis will be shared between download and mock sentry From ac9f9e0a25f7da5f57351b085db590e5a37c237f Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Sun, 14 Jan 2024 14:40:47 +0100 Subject: [PATCH 61/92] polygon/sync: fork choice logic (#9228) --- polygon/sync/canonical_chain_builder.go | 27 ++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/polygon/sync/canonical_chain_builder.go b/polygon/sync/canonical_chain_builder.go index ea864c5cc73..2c6d6328591 100644 --- a/polygon/sync/canonical_chain_builder.go +++ b/polygon/sync/canonical_chain_builder.go @@ -1,6 +1,7 @@ package sync import ( + "bytes" "errors" "fmt" "time" @@ -142,13 +143,29 @@ func (impl *canonicalChainBuilderImpl) Prune(newRootNum uint64) error { return nil } +// compareForkTreeNodes compares 2 fork tree nodes. +// It returns a positive number if the chain ending at node1 is "better" than the chain ending at node2. +// The better node belongs to the canonical chain, and it has: +// * a greater total difficulty, +// * or a smaller block number, +// * or a lexicographically greater hash. +// See: https://github.com/maticnetwork/bor/blob/master/core/forkchoice.go#L82 +func compareForkTreeNodes(node1 *forkTreeNode, node2 *forkTreeNode) int { + difficultyDiff := int64(node1.totalDifficulty) - int64(node2.totalDifficulty) + if difficultyDiff != 0 { + return int(difficultyDiff) + } + blockNumDiff := node1.header.Number.Cmp(node2.header.Number) + if blockNumDiff != 0 { + return -blockNumDiff + } + return bytes.Compare(node1.headerHash.Bytes(), node2.headerHash.Bytes()) +} + func (impl *canonicalChainBuilderImpl) updateTipIfNeeded(tipCandidate *forkTreeNode) { - if tipCandidate.totalDifficulty > impl.tip.totalDifficulty { + if compareForkTreeNodes(tipCandidate, impl.tip) > 0 { impl.tip = tipCandidate } - // else if tipCandidate.totalDifficulty == impl.tip.totalDifficulty { - // TODO: is it possible? which one is selected? - // } } func (impl *canonicalChainBuilderImpl) Connect(headers []*types.Header) error { @@ -200,7 +217,7 @@ func (impl *canonicalChainBuilderImpl) Connect(headers []*types.Header) error { // attach nodes for the new headers for i, header := range headers { - if (header.Number == nil) && (header.Number.Uint64() != parent.header.Number.Uint64()+1) { + if (header.Number == nil) || (header.Number.Uint64() != parent.header.Number.Uint64()+1) { return errors.New("canonicalChainBuilderImpl.Connect: invalid header.Number") } From 8d4d4d802ca180f78aad760c6dbdaa239b0858b8 Mon Sep 17 00:00:00 2001 From: a Date: Sun, 14 Jan 2024 23:22:34 -0600 Subject: [PATCH 62/92] refac some (#9185) --- cl/beacon/beaconhttp/api.go | 1 - cl/beacon/beaconhttp/args.go | 176 ++ cl/beacon/beaconhttp/beacon_response.go | 95 + cl/beacon/beacontest/errors.go | 8 + cl/beacon/beacontest/harness.go | 436 ++++ cl/beacon/beacontest/harness_test.go | 19 + cl/beacon/beacontest/harness_test_data.yml | 62 + cl/beacon/beacontest/linux_basepathfs.go | 252 +++ cl/beacon/handler/attestation_rewards.go | 8 +- cl/beacon/handler/attestation_rewards_test.go | 152 -- cl/beacon/handler/blocks.go | 51 +- cl/beacon/handler/blocks_test.go | 254 --- cl/beacon/handler/builder.go | 8 +- cl/beacon/handler/commitees_test.go | 169 -- cl/beacon/handler/committees.go | 14 +- cl/beacon/handler/config.go | 7 +- cl/beacon/handler/config_test.go | 83 - cl/beacon/handler/data_test.go | 98 + cl/beacon/handler/duties_attester.go | 10 +- cl/beacon/handler/duties_attester_test.go | 153 -- cl/beacon/handler/duties_proposer.go | 8 +- cl/beacon/handler/duties_proposer_test.go | 114 - cl/beacon/handler/duties_sync.go | 8 +- cl/beacon/handler/duties_sync_test.go | 87 - cl/beacon/handler/forkchoice.go | 2 +- cl/beacon/handler/forkchoice_test.go | 80 - cl/beacon/handler/format.go | 237 +- cl/beacon/handler/genesis.go | 2 +- cl/beacon/handler/genesis_test.go | 35 - cl/beacon/handler/handler.go | 5 + .../harness/attestation_rewards_bellatrix.yml | 31 + .../harness/attestation_rewards_phase0.yml | 33 + cl/beacon/handler/harness/blocks.yml | 100 + cl/beacon/handler/harness/committees.yml | 55 + cl/beacon/handler/harness/committees_f.yml | 55 + cl/beacon/handler/harness/config.yml | 32 + cl/beacon/handler/harness/duties_attester.yml | 45 + .../handler/harness/duties_attester_f.yml | 45 + cl/beacon/handler/harness/duties_proposer.yml | 42 + .../handler/harness/duties_sync_bellatrix.yml | 43 + cl/beacon/handler/harness/fork_choice.yml | 24 + cl/beacon/handler/harness/headers.yml | 38 + cl/beacon/handler/harness/liveness.yml | 13 + cl/beacon/handler/harness_test.go | 53 + cl/beacon/handler/headers.go | 12 +- cl/beacon/handler/headers_test.go | 180 -- cl/beacon/handler/liveness.go | 4 +- cl/beacon/handler/liveness_test.go | 62 - cl/beacon/handler/node.go | 4 +- cl/beacon/handler/node_test.go | 71 - cl/beacon/handler/pool.go | 14 +- cl/beacon/handler/pool_test.go | 248 --- cl/beacon/handler/rewards.go | 14 +- cl/beacon/handler/rewards_test.go | 142 -- cl/beacon/handler/states.go | 62 +- cl/beacon/handler/states_test.go | 504 ----- .../handler/test_data/attestations_1.json | 1 + .../handler/test_data/attestations_2.json | 1 + .../handler/test_data/attestations_3.json | 1 + .../handler/test_data/attestations_4.json | 1 + .../handler/test_data/blinded_block_1.json | 1975 +++++++++++++++++ cl/beacon/handler/test_data/block_1.json | 1974 ++++++++++++++++ cl/beacon/handler/test_data/committees_1.yaml | 6 + cl/beacon/handler/test_data/duties_1.yaml | 2 + .../handler/test_data/duties_sync_1.yaml | 2 + cl/beacon/handler/test_data/forkchoice_1.yaml | 2 + cl/beacon/handler/test_data/rewards_1.yaml | 3 + cl/beacon/handler/test_data/rewards_2.json | 1 + cl/beacon/handler/test_data/states_1.yaml | 2 + .../handler/test_data/sync_committees_1.json | 1 + cl/beacon/handler/test_data/validators_1.yaml | 9 + cl/beacon/handler/utils_test.go | 11 +- cl/beacon/handler/validators.go | 42 +- cl/beacon/handler/validators_test.go | 201 -- go.mod | 13 + go.sum | 34 + 76 files changed, 5933 insertions(+), 2909 deletions(-) create mode 100644 cl/beacon/beaconhttp/args.go create mode 100644 cl/beacon/beaconhttp/beacon_response.go create mode 100644 cl/beacon/beacontest/errors.go create mode 100644 cl/beacon/beacontest/harness.go create mode 100644 cl/beacon/beacontest/harness_test.go create mode 100644 cl/beacon/beacontest/harness_test_data.yml create mode 100644 cl/beacon/beacontest/linux_basepathfs.go delete mode 100644 cl/beacon/handler/attestation_rewards_test.go delete mode 100644 cl/beacon/handler/blocks_test.go delete mode 100644 cl/beacon/handler/commitees_test.go delete mode 100644 cl/beacon/handler/config_test.go create mode 100644 cl/beacon/handler/data_test.go delete mode 100644 cl/beacon/handler/duties_attester_test.go delete mode 100644 cl/beacon/handler/duties_proposer_test.go delete mode 100644 cl/beacon/handler/duties_sync_test.go delete mode 100644 cl/beacon/handler/forkchoice_test.go delete mode 100644 cl/beacon/handler/genesis_test.go create mode 100644 cl/beacon/handler/harness/attestation_rewards_bellatrix.yml create mode 100644 cl/beacon/handler/harness/attestation_rewards_phase0.yml create mode 100644 cl/beacon/handler/harness/blocks.yml create mode 100644 cl/beacon/handler/harness/committees.yml create mode 100644 cl/beacon/handler/harness/committees_f.yml create mode 100644 cl/beacon/handler/harness/config.yml create mode 100644 cl/beacon/handler/harness/duties_attester.yml create mode 100644 cl/beacon/handler/harness/duties_attester_f.yml create mode 100644 cl/beacon/handler/harness/duties_proposer.yml create mode 100644 cl/beacon/handler/harness/duties_sync_bellatrix.yml create mode 100644 cl/beacon/handler/harness/fork_choice.yml create mode 100644 cl/beacon/handler/harness/headers.yml create mode 100644 cl/beacon/handler/harness/liveness.yml create mode 100644 cl/beacon/handler/harness_test.go delete mode 100644 cl/beacon/handler/headers_test.go delete mode 100644 cl/beacon/handler/liveness_test.go delete mode 100644 cl/beacon/handler/node_test.go delete mode 100644 cl/beacon/handler/pool_test.go delete mode 100644 cl/beacon/handler/rewards_test.go delete mode 100644 cl/beacon/handler/states_test.go create mode 100644 cl/beacon/handler/test_data/attestations_1.json create mode 100644 cl/beacon/handler/test_data/attestations_2.json create mode 100644 cl/beacon/handler/test_data/attestations_3.json create mode 100644 cl/beacon/handler/test_data/attestations_4.json create mode 100644 cl/beacon/handler/test_data/blinded_block_1.json create mode 100644 cl/beacon/handler/test_data/block_1.json create mode 100644 cl/beacon/handler/test_data/committees_1.yaml create mode 100644 cl/beacon/handler/test_data/duties_1.yaml create mode 100644 cl/beacon/handler/test_data/duties_sync_1.yaml create mode 100644 cl/beacon/handler/test_data/forkchoice_1.yaml create mode 100644 cl/beacon/handler/test_data/rewards_1.yaml create mode 100644 cl/beacon/handler/test_data/rewards_2.json create mode 100644 cl/beacon/handler/test_data/states_1.yaml create mode 100644 cl/beacon/handler/test_data/sync_committees_1.json create mode 100644 cl/beacon/handler/test_data/validators_1.yaml delete mode 100644 cl/beacon/handler/validators_test.go diff --git a/cl/beacon/beaconhttp/api.go b/cl/beacon/beaconhttp/api.go index 5beffa09f6d..6bc32c58ddf 100644 --- a/cl/beacon/beaconhttp/api.go +++ b/cl/beacon/beaconhttp/api.go @@ -73,7 +73,6 @@ func HandleEndpoint[T any](h EndpointHandler[T]) http.HandlerFunc { ans, err := h.Handle(w, r) log.Debug("beacon api request", "endpoint", r.URL.Path, "duration", time.Since(start)) if err != nil { - log.Error("beacon api request error", "err", err) var endpointError *EndpointError if e, ok := err.(*EndpointError); ok { endpointError = e diff --git a/cl/beacon/beaconhttp/args.go b/cl/beacon/beaconhttp/args.go new file mode 100644 index 00000000000..1701620b074 --- /dev/null +++ b/cl/beacon/beaconhttp/args.go @@ -0,0 +1,176 @@ +package beaconhttp + +import ( + "fmt" + "net/http" + "regexp" + "strconv" + + "github.com/go-chi/chi/v5" + "github.com/ledgerwatch/erigon-lib/common" +) + +type chainTag int + +var ( + Head chainTag = 0 + Finalized chainTag = 1 + Justified chainTag = 2 + Genesis chainTag = 3 +) + +// Represent either state id or block id +type SegmentID struct { + tag chainTag + slot *uint64 + root *common.Hash +} + +func (c *SegmentID) Head() bool { + return c.tag == Head && c.slot == nil && c.root == nil +} + +func (c *SegmentID) Finalized() bool { + return c.tag == Finalized +} + +func (c *SegmentID) Justified() bool { + return c.tag == Justified +} + +func (c *SegmentID) Genesis() bool { + return c.tag == Genesis +} + +func (c *SegmentID) GetSlot() *uint64 { + return c.slot +} + +func (c *SegmentID) GetRoot() *common.Hash { + return c.root +} + +func EpochFromRequest(r *http.Request) (uint64, error) { + // Must only be a number + regex := regexp.MustCompile(`^\d+$`) + epoch := chi.URLParam(r, "epoch") + if !regex.MatchString(epoch) { + return 0, fmt.Errorf("invalid path variable: {epoch}") + } + epochMaybe, err := strconv.ParseUint(epoch, 10, 64) + if err != nil { + return 0, err + } + return epochMaybe, nil +} + +func StringFromRequest(r *http.Request, name string) (string, error) { + str := chi.URLParam(r, name) + if str == "" { + return "", nil + } + return str, nil +} + +func BlockIdFromRequest(r *http.Request) (*SegmentID, error) { + regex := regexp.MustCompile(`^(?:0x[0-9a-fA-F]{64}|head|finalized|genesis|\d+)$`) + + blockId := chi.URLParam(r, "block_id") + if !regex.MatchString(blockId) { + return nil, fmt.Errorf("invalid path variable: {block_id}") + } + + if blockId == "head" { + return &SegmentID{tag: Head}, nil + } + if blockId == "finalized" { + return &SegmentID{tag: Finalized}, nil + } + if blockId == "genesis" { + return &SegmentID{tag: Genesis}, nil + } + slotMaybe, err := strconv.ParseUint(blockId, 10, 64) + if err == nil { + return &SegmentID{slot: &slotMaybe}, nil + } + root := common.HexToHash(blockId) + return &SegmentID{ + root: &root, + }, nil +} + +func StateIdFromRequest(r *http.Request) (*SegmentID, error) { + regex := regexp.MustCompile(`^(?:0x[0-9a-fA-F]{64}|head|finalized|genesis|justified|\d+)$`) + + stateId := chi.URLParam(r, "state_id") + if !regex.MatchString(stateId) { + return nil, fmt.Errorf("invalid path variable: {state_id}") + } + + if stateId == "head" { + return &SegmentID{tag: Head}, nil + } + if stateId == "finalized" { + return &SegmentID{tag: Finalized}, nil + } + if stateId == "genesis" { + return &SegmentID{tag: Genesis}, nil + } + if stateId == "justified" { + return &SegmentID{tag: Justified}, nil + } + slotMaybe, err := strconv.ParseUint(stateId, 10, 64) + if err == nil { + return &SegmentID{slot: &slotMaybe}, nil + } + root := common.HexToHash(stateId) + return &SegmentID{ + root: &root, + }, nil +} + +func HashFromQueryParams(r *http.Request, name string) (*common.Hash, error) { + hashStr := r.URL.Query().Get(name) + if hashStr == "" { + return nil, nil + } + // check if hashstr is an hex string + if len(hashStr) != 2+2*32 { + return nil, fmt.Errorf("invalid hash length") + } + if hashStr[:2] != "0x" { + return nil, fmt.Errorf("invalid hash prefix") + } + notHex, err := regexp.MatchString("[^0-9A-Fa-f]", hashStr[2:]) + if err != nil { + return nil, err + } + if notHex { + return nil, fmt.Errorf("invalid hash characters") + } + + hash := common.HexToHash(hashStr) + return &hash, nil +} + +// uint64FromQueryParams retrieves a number from the query params, in base 10. +func Uint64FromQueryParams(r *http.Request, name string) (*uint64, error) { + str := r.URL.Query().Get(name) + if str == "" { + return nil, nil + } + num, err := strconv.ParseUint(str, 10, 64) + if err != nil { + return nil, err + } + return &num, nil +} + +// decode a list of strings from the query params +func StringListFromQueryParams(r *http.Request, name string) ([]string, error) { + str := r.URL.Query().Get(name) + if str == "" { + return nil, nil + } + return regexp.MustCompile(`\s*,\s*`).Split(str, -1), nil +} diff --git a/cl/beacon/beaconhttp/beacon_response.go b/cl/beacon/beaconhttp/beacon_response.go new file mode 100644 index 00000000000..c0e340915e6 --- /dev/null +++ b/cl/beacon/beaconhttp/beacon_response.go @@ -0,0 +1,95 @@ +package beaconhttp + +import ( + "encoding/json" + "net/http" + + "github.com/ledgerwatch/erigon-lib/types/ssz" + "github.com/ledgerwatch/erigon/cl/clparams" +) + +type BeaconResponse struct { + Data any + Finalized *bool + Version *clparams.StateVersion + ExecutionOptimistic *bool + + Extra map[string]any +} + +func NewBeaconResponse(data any) *BeaconResponse { + return &BeaconResponse{ + Data: data, + } +} + +func (r *BeaconResponse) With(key string, value any) (out *BeaconResponse) { + out = new(BeaconResponse) + *out = *r + out.Extra[key] = value + return out +} + +func (r *BeaconResponse) WithFinalized(finalized bool) (out *BeaconResponse) { + out = new(BeaconResponse) + *out = *r + out.Finalized = new(bool) + out.ExecutionOptimistic = new(bool) + out.Finalized = &finalized + return out +} + +func (r *BeaconResponse) WithOptimistic(optimistic bool) (out *BeaconResponse) { + out = new(BeaconResponse) + *out = *r + out.ExecutionOptimistic = new(bool) + out.ExecutionOptimistic = &optimistic + return out +} + +func (r *BeaconResponse) WithVersion(version clparams.StateVersion) (out *BeaconResponse) { + out = new(BeaconResponse) + *out = *r + out.Version = new(clparams.StateVersion) + out.Version = &version + return out +} + +func (b *BeaconResponse) MarshalJSON() ([]byte, error) { + o := map[string]any{ + "data": b.Data, + } + if b.Finalized != nil { + o["finalized"] = *b.Finalized + } + if b.Version != nil { + o["version"] = *b.Version + } + if b.ExecutionOptimistic != nil { + o["execution_optimistic"] = *b.ExecutionOptimistic + } + for k, v := range b.Extra { + o[k] = v + } + return json.Marshal(o) +} + +func (b *BeaconResponse) EncodeSSZ(xs []byte) ([]byte, error) { + marshaler, ok := b.Data.(ssz.Marshaler) + if !ok { + return nil, NewEndpointError(http.StatusBadRequest, "This endpoint does not support SSZ response") + } + encoded, err := marshaler.EncodeSSZ(nil) + if err != nil { + return nil, err + } + return encoded, nil +} + +func (b *BeaconResponse) EncodingSizeSSZ() int { + marshaler, ok := b.Data.(ssz.Marshaler) + if !ok { + return 9 + } + return marshaler.EncodingSizeSSZ() +} diff --git a/cl/beacon/beacontest/errors.go b/cl/beacon/beacontest/errors.go new file mode 100644 index 00000000000..ecd79566f06 --- /dev/null +++ b/cl/beacon/beacontest/errors.go @@ -0,0 +1,8 @@ +package beacontest + +import "errors" + +var ( + ErrExpressionMustReturnBool = errors.New("cel expression must return bool") + ErrUnknownType = errors.New("unknown type") +) diff --git a/cl/beacon/beacontest/harness.go b/cl/beacon/beacontest/harness.go new file mode 100644 index 00000000000..84287f46530 --- /dev/null +++ b/cl/beacon/beacontest/harness.go @@ -0,0 +1,436 @@ +package beacontest + +import ( + "bytes" + "context" + "crypto/md5" + "encoding/hex" + "encoding/json" + "fmt" + "io" + "net/http" + "net/http/httptest" + "net/url" + "os" + "reflect" + "strings" + "testing" + "text/template" + + "github.com/Masterminds/sprig/v3" + + "github.com/google/cel-go/cel" + "github.com/google/cel-go/common/types" + "github.com/spf13/afero" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "sigs.k8s.io/yaml" +) + +type HarnessOption func(*Harness) error + +func WithTesting(t *testing.T) func(*Harness) error { + return func(h *Harness) error { + h.t = t + return nil + } +} + +func WithTests(name string, xs []Test) func(*Harness) error { + return func(h *Harness) error { + h.tests[name] = xs + return nil + } +} + +func WithHandler(name string, handler http.Handler) func(*Harness) error { + return func(h *Harness) error { + h.handlers[name] = handler + return nil + } +} + +func WithFilesystem(name string, handler afero.Fs) func(*Harness) error { + return func(h *Harness) error { + h.fss[name] = handler + return nil + } +} +func WithTestFromFs(fs afero.Fs, name string) func(*Harness) error { + return func(h *Harness) error { + filename := name + for _, fn := range []string{name, name + ".yaml", name + ".yml", name + ".json"} { + // check if file exists + _, err := fs.Stat(fn) + if err == nil { + filename = fn + break + } + } + xs, err := afero.ReadFile(fs, filename) + if err != nil { + return err + } + return WithTestFromBytes(name, xs)(h) + } +} + +type Extra struct { + Vars map[string]any `json:"vars"` + + RawBodyZZZZ json.RawMessage `json:"tests"` +} + +func WithTestFromBytes(name string, xs []byte) func(*Harness) error { + return func(h *Harness) error { + var t struct { + T []Test `json:"tests"` + } + x := &Extra{} + s := md5.New() + s.Write(xs) + hsh := hex.EncodeToString(s.Sum(nil)) + // unmarshal just the extra data + err := yaml.Unmarshal(xs, &x, yaml.JSONOpt(func(d *json.Decoder) *json.Decoder { + return d + })) + if err != nil { + return err + } + tmpl := template.Must(template.New(hsh).Funcs(sprig.FuncMap()).Parse(string(xs))) + // execute the template using the extra data as the provided top level object + // we can use the original buffer as the output since the original buffer has already been copied when it was passed into template + buf := bytes.NewBuffer(xs) + buf.Reset() + err = tmpl.Execute(buf, x) + if err != nil { + return err + } + err = yaml.Unmarshal(buf.Bytes(), &t) + if err != nil { + return err + } + if len(t.T) == 0 { + return fmt.Errorf("suite with name %s had no tests", name) + } + h.tests[name] = t.T + return nil + } +} + +type Harness struct { + tests map[string][]Test + t *testing.T + + handlers map[string]http.Handler + fss map[string]afero.Fs +} + +func Execute(options ...HarnessOption) { + h := &Harness{ + handlers: map[string]http.Handler{}, + tests: map[string][]Test{}, + fss: map[string]afero.Fs{ + "": afero.NewOsFs(), + }, + } + for _, v := range options { + err := v(h) + if err != nil { + h.t.Error(err) + } + } + h.Execute() +} + +func (h *Harness) Execute() { + ctx := context.Background() + for suiteName, tests := range h.tests { + for idx, v := range tests { + v.Actual.h = h + v.Expect.h = h + name := v.Name + if name == "" { + name = "test" + } + fullname := fmt.Sprintf("%s_%s_%d", suiteName, name, idx) + h.t.Run(fullname, func(t *testing.T) { + err := v.Execute(ctx, t) + require.NoError(t, err) + }) + } + } +} + +type Test struct { + Name string `json:"name"` + Expect Source `json:"expect"` + Actual Source `json:"actual"` + Compare Comparison `json:"compare"` +} + +func (c *Test) Execute(ctx context.Context, t *testing.T) error { + a, aCode, err := c.Expect.Execute(ctx) + if err != nil { + return fmt.Errorf("get expect data: %w", err) + } + b, bCode, err := c.Actual.Execute(ctx) + if err != nil { + return fmt.Errorf("get actual data: %w", err) + } + err = c.Compare.Compare(t, a, b, aCode, bCode) + if err != nil { + return fmt.Errorf("compare: %w", err) + } + + return nil +} + +type Comparison struct { + Expr string `json:"expr"` + Exprs []string `json:"exprs"` + Literal bool `json:"literal"` +} + +func (c *Comparison) Compare(t *testing.T, aRaw, bRaw json.RawMessage, aCode, bCode int) error { + var err error + var a, b any + var aType, bType *types.Type + + if !c.Literal { + var aMap, bMap any + err = yaml.Unmarshal(aRaw, &aMap) + if err != nil { + return err + } + err = yaml.Unmarshal(bRaw, &bMap) + if err != nil { + return err + } + a = aMap + b = bMap + if a != nil { + switch reflect.TypeOf(a).Kind() { + case reflect.Slice: + aType = cel.ListType(cel.MapType(cel.StringType, cel.DynType)) + default: + aType = cel.MapType(cel.StringType, cel.DynType) + } + } else { + aType = cel.MapType(cel.StringType, cel.DynType) + } + if b != nil { + switch reflect.TypeOf(b).Kind() { + case reflect.Slice: + bType = cel.ListType(cel.MapType(cel.StringType, cel.DynType)) + default: + bType = cel.MapType(cel.StringType, cel.DynType) + } + } else { + bType = cel.MapType(cel.StringType, cel.DynType) + } + } else { + a = string(aRaw) + b = string(bRaw) + aType = cel.StringType + bType = cel.StringType + } + + exprs := []string{} + // if no default expr set and no exprs are set, then add the default expr + if len(c.Exprs) == 0 && c.Expr == "" { + exprs = append(exprs, "actual_code == 200", "actual == expect") + } + env, err := cel.NewEnv( + cel.Variable("expect", aType), + cel.Variable("actual", bType), + cel.Variable("expect_code", cel.IntType), + cel.Variable("actual_code", cel.IntType), + ) + if err != nil { + return err + } + + for _, expr := range append(c.Exprs, exprs...) { + ast, issues := env.Compile(expr) + if issues != nil && issues.Err() != nil { + return issues.Err() + } + prg, err := env.Program(ast) + if err != nil { + return fmt.Errorf("program construction error: %w", err) + } + res, _, err := prg.Eval(map[string]any{ + "expect": a, + "actual": b, + "expect_code": aCode, + "actual_code": bCode, + }) + if err != nil { + return err + } + if res.Type() != cel.BoolType { + return ErrExpressionMustReturnBool + } + bres, ok := res.Value().(bool) + if !ok { + return ErrExpressionMustReturnBool + } + if !assert.Equal(t, bres, true, `expr: %s`, expr) { + if os.Getenv("HIDE_HARNESS_LOG") != "1" { + t.Logf(`name: %s + expect%d: %v + actual%d: %v + expr: %s + `, t.Name(), aCode, a, bCode, b, expr) + + } + t.FailNow() + } + } + return nil +} + +type Source struct { + // backref to the harness + h *Harness `json:"-"` + + // remote type + Remote *string `json:"remote,omitempty"` + Handler *string `json:"handler,omitempty"` + Method string `json:"method"` + Path string `json:"path"` + Query map[string]string `json:"query"` + Headers map[string]string `json:"headers"` + Body *Source `json:"body,omitempty"` + + // data type + Data any `json:"data,omitempty"` + + // file type + File *string `json:"file,omitempty"` + Fs string `json:"fs,omitempty"` + + // for raw type + Raw *string `json:"raw,omitempty"` +} + +func (s *Source) Execute(ctx context.Context) (json.RawMessage, int, error) { + if s.Raw != nil { + return s.executeRaw(ctx) + } + if s.File != nil { + return s.executeFile(ctx) + } + if s.Remote != nil || s.Handler != nil { + return s.executeRemote(ctx) + } + if s.Data != nil { + return s.executeData(ctx) + } + return s.executeEmpty(ctx) +} +func (s *Source) executeRemote(ctx context.Context) (json.RawMessage, int, error) { + method := "GET" + if s.Method != "" { + method = s.Method + } + method = strings.ToUpper(method) + var body io.Reader + // hydrate the harness + if s.Body != nil { + s.Body.h = s.h + msg, _, err := s.Body.Execute(ctx) + if err != nil { + return nil, 0, fmt.Errorf("getting body: %w", err) + } + body = bytes.NewBuffer(msg) + } + var purl *url.URL + if s.Remote != nil { + niceUrl, err := url.Parse(*s.Remote) + if err != nil { + return nil, 0, err + } + purl = niceUrl + + } else if s.Handler != nil { + handler, ok := s.h.handlers[*s.Handler] + if !ok { + return nil, 0, fmt.Errorf("handler not registered: %s", *s.Handler) + } + server := httptest.NewServer(handler) + defer server.Close() + niceUrl, err := url.Parse(server.URL) + if err != nil { + return nil, 0, err + } + purl = niceUrl + } else { + panic("impossible code path. bug? source.Execute() should ensure this never happens") + } + + purl = purl.JoinPath(s.Path) + q := purl.Query() + for k, v := range s.Query { + q.Add(k, v) + } + purl.RawQuery = q.Encode() + request, err := http.NewRequest(method, purl.String(), body) + if err != nil { + return nil, 0, err + } + for k, v := range s.Headers { + request.Header.Set(k, v) + } + resp, err := http.DefaultClient.Do(request) + if err != nil { + return nil, 0, err + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return nil, resp.StatusCode, nil + } + out, err := io.ReadAll(resp.Body) + if err != nil { + return nil, 200, err + } + return json.RawMessage(out), 200, nil +} + +func (s *Source) executeData(ctx context.Context) (json.RawMessage, int, error) { + ans, err := json.Marshal(s.Data) + if err != nil { + return nil, 400, nil + } + return ans, 200, nil +} + +func (s *Source) executeFile(ctx context.Context) (json.RawMessage, int, error) { + afs, ok := s.h.fss[s.Fs] + if !ok { + return nil, 404, fmt.Errorf("filesystem %s not defined", s.Fs) + } + name := *s.File + filename := name + for _, fn := range []string{name, name + ".yaml", name + ".yml", name + ".json"} { + // check if file exists + _, err := afs.Stat(fn) + if err == nil { + filename = fn + break + } + } + fileBytes, err := afero.ReadFile(afs, filename) + if err != nil { + return nil, 404, err + } + return json.RawMessage(fileBytes), 200, nil +} +func (s *Source) executeRaw(ctx context.Context) (json.RawMessage, int, error) { + return json.RawMessage(*s.Raw), 200, nil +} + +func (s *Source) executeEmpty(ctx context.Context) (json.RawMessage, int, error) { + return []byte("{}"), 200, nil +} diff --git a/cl/beacon/beacontest/harness_test.go b/cl/beacon/beacontest/harness_test.go new file mode 100644 index 00000000000..d6ee904d7e7 --- /dev/null +++ b/cl/beacon/beacontest/harness_test.go @@ -0,0 +1,19 @@ +package beacontest_test + +import ( + "testing" + + _ "embed" + + "github.com/ledgerwatch/erigon/cl/beacon/beacontest" +) + +//go:embed harness_test_data.yml +var testData []byte + +func TestSimpleHarness(t *testing.T) { + beacontest.Execute( + beacontest.WithTesting(t), + beacontest.WithTestFromBytes("test", testData), + ) +} diff --git a/cl/beacon/beacontest/harness_test_data.yml b/cl/beacon/beacontest/harness_test_data.yml new file mode 100644 index 00000000000..4c307021986 --- /dev/null +++ b/cl/beacon/beacontest/harness_test_data.yml @@ -0,0 +1,62 @@ +tests: + - name: "equality expression" + expect: + data: + hello: world + actual: + data: + hello: world + compare: + type: "expr" + expr: "actual == expect" + - name: "neg equality expr" + expect: + data: + hello: world + actual: + data: + hello: worlds + compare: + expr: "actual != expect" + - name: "subkey world" + expect: + data: + hi: world + actual: + data: + hello: world + compare: + expr: "actual.hello == expect.hi" + - name: "default compare" + expect: + data: + hello: world + actual: + data: + hello: world + - name: "default neg compare" + expect: + data: + hello: world + actual: + data: + hello: worlds + compare: + expr: "actual != expect" + - name: "key order doesnt matter for non literal" + expect: + data: + a: 1 + b: 2 + actual: + raw: '{"b":2,"a":1}' + - name: "key order does matter for literal" + expect: + data: + a: 1 + b: 2 + actual: + raw: '{"b":2,"a":1}' + compare: + literal: true + expr: "actual != expect" diff --git a/cl/beacon/beacontest/linux_basepathfs.go b/cl/beacon/beacontest/linux_basepathfs.go new file mode 100644 index 00000000000..a27754c2723 --- /dev/null +++ b/cl/beacon/beacontest/linux_basepathfs.go @@ -0,0 +1,252 @@ +package beacontest + +import ( + "io/fs" + "os" + "path" + "runtime" + "strings" + "time" + + "github.com/spf13/afero" +) + +var ( + _ afero.Lstater = (*BasePathFs)(nil) + _ fs.ReadDirFile = (*BasePathFile)(nil) +) + +// This is a version of the afero basepathfs that uses path instead of filepath. +// this is needed to work with things like zipfs and embedfs on windows +type BasePathFs struct { + source afero.Fs + path string +} + +type BasePathFile struct { + afero.File + path string +} + +func (f *BasePathFile) Name() string { + sourcename := f.File.Name() + return strings.TrimPrefix(sourcename, path.Clean(f.path)) +} + +func (f *BasePathFile) ReadDir(n int) ([]fs.DirEntry, error) { + if rdf, ok := f.File.(fs.ReadDirFile); ok { + return rdf.ReadDir(n) + } + return readDirFile{f.File}.ReadDir(n) +} + +func NewBasePathFs(source afero.Fs, path string) afero.Fs { + return &BasePathFs{source: source, path: path} +} + +// on a file outside the base path it returns the given file name and an error, +// else the given file with the base path prepended +func (b *BasePathFs) RealPath(name string) (p string, err error) { + if err := validateBasePathName(name); err != nil { + return name, err + } + + bpath := path.Clean(b.path) + p = path.Clean(path.Join(bpath, name)) + if !strings.HasPrefix(p, bpath) { + return name, os.ErrNotExist + } + + return p, nil +} + +func validateBasePathName(name string) error { + if runtime.GOOS != "windows" { + // Not much to do here; + // the virtual file paths all look absolute on *nix. + return nil + } + + // On Windows a common mistake would be to provide an absolute OS path + // We could strip out the base part, but that would not be very portable. + if path.IsAbs(name) { + return os.ErrNotExist + } + + return nil +} + +func (b *BasePathFs) Chtimes(name string, atime, mtime time.Time) (err error) { + if name, err = b.RealPath(name); err != nil { + return &os.PathError{Op: "chtimes", Path: name, Err: err} + } + return b.source.Chtimes(name, atime, mtime) +} + +func (b *BasePathFs) Chmod(name string, mode os.FileMode) (err error) { + if name, err = b.RealPath(name); err != nil { + return &os.PathError{Op: "chmod", Path: name, Err: err} + } + return b.source.Chmod(name, mode) +} + +func (b *BasePathFs) Chown(name string, uid, gid int) (err error) { + if name, err = b.RealPath(name); err != nil { + return &os.PathError{Op: "chown", Path: name, Err: err} + } + return b.source.Chown(name, uid, gid) +} + +func (b *BasePathFs) Name() string { + return "BasePathFs" +} + +func (b *BasePathFs) Stat(name string) (fi os.FileInfo, err error) { + if name, err = b.RealPath(name); err != nil { + return nil, &os.PathError{Op: "stat", Path: name, Err: err} + } + return b.source.Stat(name) +} + +func (b *BasePathFs) Rename(oldname, newname string) (err error) { + if oldname, err = b.RealPath(oldname); err != nil { + return &os.PathError{Op: "rename", Path: oldname, Err: err} + } + if newname, err = b.RealPath(newname); err != nil { + return &os.PathError{Op: "rename", Path: newname, Err: err} + } + return b.source.Rename(oldname, newname) +} + +func (b *BasePathFs) RemoveAll(name string) (err error) { + if name, err = b.RealPath(name); err != nil { + return &os.PathError{Op: "remove_all", Path: name, Err: err} + } + return b.source.RemoveAll(name) +} + +func (b *BasePathFs) Remove(name string) (err error) { + if name, err = b.RealPath(name); err != nil { + return &os.PathError{Op: "remove", Path: name, Err: err} + } + return b.source.Remove(name) +} + +func (b *BasePathFs) OpenFile(name string, flag int, mode os.FileMode) (f afero.File, err error) { + if name, err = b.RealPath(name); err != nil { + return nil, &os.PathError{Op: "openfile", Path: name, Err: err} + } + sourcef, err := b.source.OpenFile(name, flag, mode) + if err != nil { + return nil, err + } + return &BasePathFile{sourcef, b.path}, nil +} + +func (b *BasePathFs) Open(name string) (f afero.File, err error) { + if name, err = b.RealPath(name); err != nil { + return nil, &os.PathError{Op: "open", Path: name, Err: err} + } + sourcef, err := b.source.Open(name) + if err != nil { + return nil, err + } + return &BasePathFile{File: sourcef, path: b.path}, nil +} + +func (b *BasePathFs) Mkdir(name string, mode os.FileMode) (err error) { + if name, err = b.RealPath(name); err != nil { + return &os.PathError{Op: "mkdir", Path: name, Err: err} + } + return b.source.Mkdir(name, mode) +} + +func (b *BasePathFs) MkdirAll(name string, mode os.FileMode) (err error) { + if name, err = b.RealPath(name); err != nil { + return &os.PathError{Op: "mkdir", Path: name, Err: err} + } + return b.source.MkdirAll(name, mode) +} + +func (b *BasePathFs) Create(name string) (f afero.File, err error) { + if name, err = b.RealPath(name); err != nil { + return nil, &os.PathError{Op: "create", Path: name, Err: err} + } + sourcef, err := b.source.Create(name) + if err != nil { + return nil, err + } + return &BasePathFile{File: sourcef, path: b.path}, nil +} + +func (b *BasePathFs) LstatIfPossible(name string) (os.FileInfo, bool, error) { + name, err := b.RealPath(name) + if err != nil { + return nil, false, &os.PathError{Op: "lstat", Path: name, Err: err} + } + if lstater, ok := b.source.(afero.Lstater); ok { + return lstater.LstatIfPossible(name) + } + fi, err := b.source.Stat(name) + return fi, false, err +} + +func (b *BasePathFs) SymlinkIfPossible(oldname, newname string) error { + oldname, err := b.RealPath(oldname) + if err != nil { + return &os.LinkError{Op: "symlink", Old: oldname, New: newname, Err: err} + } + newname, err = b.RealPath(newname) + if err != nil { + return &os.LinkError{Op: "symlink", Old: oldname, New: newname, Err: err} + } + if linker, ok := b.source.(afero.Linker); ok { + return linker.SymlinkIfPossible(oldname, newname) + } + return &os.LinkError{Op: "symlink", Old: oldname, New: newname, Err: afero.ErrNoSymlink} +} + +func (b *BasePathFs) ReadlinkIfPossible(name string) (string, error) { + name, err := b.RealPath(name) + if err != nil { + return "", &os.PathError{Op: "readlink", Path: name, Err: err} + } + if reader, ok := b.source.(afero.LinkReader); ok { + return reader.ReadlinkIfPossible(name) + } + return "", &os.PathError{Op: "readlink", Path: name, Err: afero.ErrNoReadlink} +} + +// the readDirFile helper is requried + +// readDirFile provides adapter from afero.File to fs.ReadDirFile needed for correct Open +type readDirFile struct { + afero.File +} + +var _ fs.ReadDirFile = readDirFile{} + +func (r readDirFile) ReadDir(n int) ([]fs.DirEntry, error) { + items, err := r.File.Readdir(n) + if err != nil { + return nil, err + } + + ret := make([]fs.DirEntry, len(items)) + for i := range items { + ret[i] = fileInfoDirEntry{FileInfo: items[i]} + } + + return ret, nil +} + +// FileInfoDirEntry provides an adapter from os.FileInfo to fs.DirEntry +type fileInfoDirEntry struct { + fs.FileInfo +} + +var _ fs.DirEntry = fileInfoDirEntry{} + +func (d fileInfoDirEntry) Type() fs.FileMode { return d.FileInfo.Mode().Type() } + +func (d fileInfoDirEntry) Info() (fs.FileInfo, error) { return d.FileInfo, nil } diff --git a/cl/beacon/handler/attestation_rewards.go b/cl/beacon/handler/attestation_rewards.go index 51b5e7dadcd..aa823b9b76c 100644 --- a/cl/beacon/handler/attestation_rewards.go +++ b/cl/beacon/handler/attestation_rewards.go @@ -40,7 +40,7 @@ type attestationsRewardsResponse struct { TotalRewards []TotalReward `json:"total_rewards"` } -func (a *ApiHandler) getAttestationsRewards(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getAttestationsRewards(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { ctx := r.Context() tx, err := a.indiciesDB.BeginRo(ctx) @@ -49,7 +49,7 @@ func (a *ApiHandler) getAttestationsRewards(w http.ResponseWriter, r *http.Reque } defer tx.Rollback() - epoch, err := epochFromRequest(r) + epoch, err := beaconhttp.EpochFromRequest(r) if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } @@ -180,7 +180,7 @@ func (a *ApiHandler) baseReward(version clparams.StateVersion, effectiveBalance, return effectiveBalance * a.beaconChainCfg.BaseRewardFactor / activeBalanceRoot / a.beaconChainCfg.BaseRewardsPerEpoch } -func (a *ApiHandler) computeAttestationsRewardsForAltair(validatorSet *solid.ValidatorSet, inactivityScores solid.Uint64ListSSZ, previousParticipation *solid.BitList, inactivityLeak bool, filterIndicies []uint64, epoch uint64) (*beaconResponse, error) { +func (a *ApiHandler) computeAttestationsRewardsForAltair(validatorSet *solid.ValidatorSet, inactivityScores solid.Uint64ListSSZ, previousParticipation *solid.BitList, inactivityLeak bool, filterIndicies []uint64, epoch uint64) (*beaconhttp.BeaconResponse, error) { totalActiveBalance := uint64(0) flagsUnslashedIndiciesSet := statechange.GetUnslashedIndiciesSet(a.beaconChainCfg, epoch, validatorSet, previousParticipation) weights := a.beaconChainCfg.ParticipationWeights() @@ -289,7 +289,7 @@ func (a *ApiHandler) computeAttestationsRewardsForAltair(validatorSet *solid.Val } // processRewardsAndPenaltiesPhase0 process rewards and penalties for phase0 state. -func (a *ApiHandler) computeAttestationsRewardsForPhase0(s *state.CachingBeaconState, filterIndicies []uint64, epoch uint64) (*beaconResponse, error) { +func (a *ApiHandler) computeAttestationsRewardsForPhase0(s *state.CachingBeaconState, filterIndicies []uint64, epoch uint64) (*beaconhttp.BeaconResponse, error) { response := &attestationsRewardsResponse{} beaconConfig := s.BeaconConfig() if epoch == beaconConfig.GenesisEpoch { diff --git a/cl/beacon/handler/attestation_rewards_test.go b/cl/beacon/handler/attestation_rewards_test.go deleted file mode 100644 index b078e844138..00000000000 --- a/cl/beacon/handler/attestation_rewards_test.go +++ /dev/null @@ -1,152 +0,0 @@ -//go:build integration - -package handler - -import ( - "fmt" - "io" - "net/http" - "net/http/httptest" - "strings" - "testing" - - "github.com/ledgerwatch/erigon/cl/clparams" - "github.com/ledgerwatch/erigon/cl/cltypes/solid" - "github.com/stretchr/testify/require" -) - -func TestAttestationRewardsBellatrix(t *testing.T) { - _, blocks, _, _, _, handler, _, _, fcu := setupTestingHandler(t, clparams.BellatrixVersion) - var err error - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - - fcu.JustifiedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, 99999999) - - cases := []struct { - name string - epoch uint64 - code int - request string - expected string - }{ - { - name: "all validators", - epoch: (fcu.HeadSlotVal / 32) - 1, - code: http.StatusOK, - expected: `{"data":{"ideal_rewards":[{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"}],"total_rewards":[{"validator_index":"0","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"1","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"2","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"3","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"4","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"5","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"6","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"7","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"8","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"9","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"10","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"11","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"12","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"13","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"14","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"15","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"16","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"17","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"18","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"19","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"20","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"21","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"22","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"23","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"24","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"25","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"26","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"27","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"28","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"29","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"30","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"31","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"32","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"33","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"34","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"35","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"36","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"37","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"38","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"39","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"40","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"41","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"42","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"43","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"44","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"45","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"46","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"47","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"48","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"49","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"50","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"51","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"52","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"53","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"54","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"55","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"56","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"57","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"58","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"59","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"60","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"61","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"62","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"63","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"64","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"65","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"66","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"67","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"68","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"69","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"70","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"71","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"72","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"73","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"74","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"75","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"76","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"77","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"78","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"79","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"80","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"81","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"82","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"83","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"84","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"85","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"86","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"87","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"88","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"89","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"90","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"91","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"92","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"93","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"94","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"95","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"96","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"97","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"98","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"99","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"100","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"101","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"102","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"103","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"104","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"105","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"106","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"107","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"108","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"109","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"110","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"111","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"112","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"113","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"114","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"115","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"116","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"117","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"118","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"119","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"120","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"121","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"122","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"123","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"124","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"125","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"126","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"127","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"128","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"129","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"130","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"131","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"132","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"133","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"134","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"135","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"136","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"137","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"138","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"139","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"140","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"141","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"142","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"143","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"144","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"145","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"146","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"147","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"148","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"149","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"150","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"151","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"152","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"153","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"154","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"155","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"156","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"157","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"158","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"159","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"160","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"161","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"162","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"163","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"164","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"165","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"166","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"167","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"168","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"169","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"170","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"171","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"172","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"173","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"174","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"175","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"176","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"177","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"178","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"179","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"180","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"181","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"182","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"183","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"184","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"185","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"186","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"187","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"188","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"189","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"190","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"191","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"192","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"193","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"194","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"195","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"196","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"197","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"198","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"199","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"200","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"201","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"202","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"203","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"204","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"205","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"206","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"207","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"208","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"209","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"210","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"211","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"212","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"213","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"214","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"215","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"216","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"217","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"218","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"219","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"220","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"221","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"222","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"223","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"224","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"225","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"226","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"227","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"228","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"229","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"230","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"231","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"232","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"233","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"234","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"235","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"236","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"237","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"238","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"239","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"240","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"241","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"242","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"243","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"244","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"245","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"246","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"247","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"248","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"249","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"250","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"251","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"252","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"253","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"254","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"255","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"}]}}` + "\n", // Add your expected response - }, - { - epoch: 99999999, - code: http.StatusNotFound, - }, - { - name: "2 validators", - epoch: (fcu.HeadSlotVal / 32) - 1, - request: `["1","4"]`, - code: http.StatusOK, - expected: `{"data":{"ideal_rewards":[{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"}],"total_rewards":[{"validator_index":"1","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"4","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"}]}}` + "\n", // Add your expected response - }, - } - for _, c := range cases { - t.Run(c.name, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - url := fmt.Sprintf("%s/eth/v1/beacon/rewards/attestations/%d", server.URL, c.epoch) - - // Create a request - req, err := http.NewRequest("POST", url, strings.NewReader(c.request)) - require.NoError(t, err) - req.Header.Set("Content-Type", "application/json") - - // Perform the request - resp, err := http.DefaultClient.Do(req) - require.NoError(t, err) - defer resp.Body.Close() - - // Check status code - require.Equal(t, c.code, resp.StatusCode) - - if resp.StatusCode != http.StatusOK { - return - } - - // Read the response body - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - // Compare the response with the expected result - require.Equal(t, c.expected, string(out)) - }) - } -} - -func TestAttestationRewardsPhase0(t *testing.T) { - _, blocks, _, _, _, handler, _, _, fcu := setupTestingHandler(t, clparams.Phase0Version) - var err error - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - - fcu.JustifiedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, 99999999) - - cases := []struct { - name string - epoch uint64 - code int - request string - expected string - }{ - { - name: "all validators", - epoch: (fcu.HeadSlotVal / 32) - 1, - code: http.StatusOK, - expected: `{"data":{"ideal_rewards":[{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"20000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"25000000000","head":"84353","target":"84353","source":"84353","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"22000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"11151","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7871","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"66906","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"26000000000","head":"87727","target":"87727","source":"87727","inclusion_delay":"4348","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"6462","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"26762","inactivity":"0"},{"effective_balance":"20000000000","head":"67482","target":"67482","source":"67482","inclusion_delay":"4646","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"26000000000","head":"87727","target":"87727","source":"87727","inclusion_delay":"4941","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"24000000000","head":"80979","target":"80979","source":"80979","inclusion_delay":"9123","inactivity":"0"},{"effective_balance":"21000000000","head":"70856","target":"70856","source":"70856","inclusion_delay":"17562","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4181","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"25000000000","head":"84353","target":"84353","source":"84353","inclusion_delay":"17423","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"4181","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"4442","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"33453","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"25000000000","head":"84353","target":"84353","source":"84353","inclusion_delay":"4355","inactivity":"0"},{"effective_balance":"22000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3231","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"21000000000","head":"70856","target":"70856","source":"70856","inclusion_delay":"5854","inactivity":"0"},{"effective_balance":"18000000000","head":"60734","target":"60734","source":"60734","inclusion_delay":"8363","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"4442","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"11151","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"18000000000","head":"60734","target":"60734","source":"60734","inclusion_delay":"10752","inactivity":"0"},{"effective_balance":"30000000000","head":"101224","target":"101224","source":"101224","inclusion_delay":"3920","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"35543","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"9558","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5575","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"26000000000","head":"87727","target":"87727","source":"87727","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"10293","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2221","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"28000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4181","inactivity":"0"},{"effective_balance":"19000000000","head":"64108","target":"64108","source":"64108","inclusion_delay":"5675","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4956","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"33453","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3231","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"23000000000","head":"77605","target":"77605","source":"77605","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7871","inactivity":"0"},{"effective_balance":"27000000000","head":"91101","target":"91101","source":"91101","inclusion_delay":"3763","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"effective_balance":"23000000000","head":"77605","target":"77605","source":"77605","inclusion_delay":"10686","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"10293","inactivity":"0"},{"effective_balance":"24000000000","head":"80979","target":"80979","source":"80979","inclusion_delay":"4561","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"11151","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5575","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5923","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"33453","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2538","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"4442","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"19116","inactivity":"0"},{"effective_balance":"20000000000","head":"67482","target":"67482","source":"67482","inclusion_delay":"2697","inactivity":"0"},{"effective_balance":"22000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7871","inactivity":"0"},{"effective_balance":"23000000000","head":"77605","target":"77605","source":"77605","inclusion_delay":"8743","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"66906","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"7898","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"17771","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"26762","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"effective_balance":"19000000000","head":"64108","target":"64108","source":"64108","inclusion_delay":"5675","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"19000000000","head":"64108","target":"64108","source":"64108","inclusion_delay":"4673","inactivity":"0"},{"effective_balance":"26000000000","head":"87727","target":"87727","source":"87727","inclusion_delay":"4348","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"4181","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"effective_balance":"27000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"24000000000","head":"80979","target":"80979","source":"80979","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"4442","inactivity":"0"},{"effective_balance":"20000000000","head":"67482","target":"67482","source":"67482","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3949","inactivity":"0"},{"effective_balance":"28000000000","head":"94475","target":"94475","source":"94475","inclusion_delay":"7805","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"18000000000","head":"60734","target":"60734","source":"60734","inclusion_delay":"8363","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"6462","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2843","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"26762","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5468","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"23000000000","head":"77605","target":"77605","source":"77605","inclusion_delay":"3434","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2369","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"17771","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"31000000000","head":"104598","target":"104598","source":"104598","inclusion_delay":"5401","inactivity":"0"},{"effective_balance":"29000000000","head":"97850","target":"97850","source":"97850","inclusion_delay":"20211","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"11847","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2538","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"19116","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"19116","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2843","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"4181","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"effective_balance":"27000000000","head":"91101","target":"91101","source":"91101","inclusion_delay":"5131","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"9558","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2221","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"effective_balance":"23000000000","head":"77605","target":"77605","source":"77605","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"26000000000","head":"87727","target":"87727","source":"87727","inclusion_delay":"3507","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5077","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"effective_balance":"18000000000","head":"60734","target":"60734","source":"60734","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"21000000000","head":"70856","target":"70856","source":"70856","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"effective_balance":"29000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"effective_balance":"18000000000","head":"60734","target":"60734","source":"60734","inclusion_delay":"2508","inactivity":"0"},{"effective_balance":"28000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"28000000000","head":"94475","target":"94475","source":"94475","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"28000000000","head":"94475","target":"94475","source":"94475","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"31000000000","head":"104598","target":"104598","source":"104598","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"effective_balance":"21000000000","head":"70856","target":"70856","source":"70856","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7871","inactivity":"0"},{"effective_balance":"23000000000","head":"77605","target":"77605","source":"77605","inclusion_delay":"13739","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"19116","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"66906","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"effective_balance":"21000000000","head":"70856","target":"70856","source":"70856","inclusion_delay":"14635","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"effective_balance":"21000000000","head":"70856","target":"70856","source":"70856","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"effective_balance":"29000000000","head":"97850","target":"97850","source":"97850","inclusion_delay":"20211","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"effective_balance":"23000000000","head":"77605","target":"77605","source":"77605","inclusion_delay":"19235","inactivity":"0"},{"effective_balance":"18000000000","head":"60734","target":"60734","source":"60734","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"66906","inactivity":"0"},{"effective_balance":"30000000000","head":"101224","target":"101224","source":"101224","inclusion_delay":"5227","inactivity":"0"},{"effective_balance":"25000000000","head":"84353","target":"84353","source":"84353","inclusion_delay":"3604","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"27000000000","head":"91101","target":"91101","source":"91101","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"30000000000","head":"101224","target":"101224","source":"101224","inclusion_delay":"6272","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"17771","inactivity":"0"},{"effective_balance":"19000000000","head":"64108","target":"64108","source":"64108","inclusion_delay":"8827","inactivity":"0"},{"effective_balance":"24000000000","head":"80979","target":"80979","source":"80979","inclusion_delay":"20071","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"31000000000","head":"104598","target":"104598","source":"104598","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5923","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"effective_balance":"19000000000","head":"64108","target":"64108","source":"64108","inclusion_delay":"3310","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"effective_balance":"25000000000","head":"84353","target":"84353","source":"84353","inclusion_delay":"14934","inactivity":"0"},{"effective_balance":"26000000000","head":"87727","target":"87727","source":"87727","inclusion_delay":"54361","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"26762","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"20000000000","head":"67482","target":"67482","source":"67482","inclusion_delay":"3636","inactivity":"0"},{"effective_balance":"27000000000","head":"91101","target":"91101","source":"91101","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"19000000000","head":"64108","target":"64108","source":"64108","inclusion_delay":"6111","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"effective_balance":"24000000000","head":"80979","target":"80979","source":"80979","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"effective_balance":"25000000000","head":"84353","target":"84353","source":"84353","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"27000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3385","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5468","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"9558","inactivity":"0"},{"effective_balance":"20000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3385","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2843","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"9558","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"31000000000","head":"104598","target":"104598","source":"104598","inclusion_delay":"4470","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2369","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"effective_balance":"22000000000","head":"74230","target":"74230","source":"74230","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"26762","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"26000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"effective_balance":"23000000000","head":"77605","target":"77605","source":"77605","inclusion_delay":"3316","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"4181","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4181","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2538","inactivity":"0"},{"effective_balance":"25000000000","head":"84353","target":"84353","source":"84353","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5468","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2221","inactivity":"0"},{"effective_balance":"27000000000","head":"91101","target":"91101","source":"91101","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"66906","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"29000000000","head":"97850","target":"97850","source":"97850","inclusion_delay":"60633","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"effective_balance":"20000000000","head":"67482","target":"67482","source":"67482","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"7898","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"18000000000","head":"60734","target":"60734","source":"60734","inclusion_delay":"4704","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2843","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"25000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"10293","inactivity":"0"},{"effective_balance":"28000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"20000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"35543","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5575","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2293","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"4442","inactivity":"0"},{"effective_balance":"22000000000","head":"74230","target":"74230","source":"74230","inclusion_delay":"5110","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5923","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"effective_balance":"24000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"31000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2369","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"11847","inactivity":"0"},{"effective_balance":"27000000000","head":"91101","target":"91101","source":"91101","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2369","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"4739","inactivity":"0"},{"effective_balance":"18000000000","head":"60734","target":"60734","source":"60734","inclusion_delay":"4427","inactivity":"0"},{"effective_balance":"28000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5575","inactivity":"0"},{"effective_balance":"28000000000","head":"94475","target":"94475","source":"94475","inclusion_delay":"29271","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5575","inactivity":"0"},{"effective_balance":"30000000000","head":"101224","target":"101224","source":"101224","inclusion_delay":"25089","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"30000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"29000000000","head":"97850","target":"97850","source":"97850","inclusion_delay":"3789","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"21000000000","head":"70856","target":"70856","source":"70856","inclusion_delay":"7317","inactivity":"0"},{"effective_balance":"31000000000","head":"104598","target":"104598","source":"104598","inclusion_delay":"7201","inactivity":"0"},{"effective_balance":"22000000000","head":"74230","target":"74230","source":"74230","inclusion_delay":"5411","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"24000000000","head":"80979","target":"80979","source":"80979","inclusion_delay":"7168","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"effective_balance":"19000000000","head":"64108","target":"64108","source":"64108","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5468","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2843","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"10293","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3385","inactivity":"0"},{"effective_balance":"26000000000","head":"87727","target":"87727","source":"87727","inclusion_delay":"4530","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5077","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"effective_balance":"19000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5468","inactivity":"0"},{"effective_balance":"31000000000","head":"104598","target":"104598","source":"104598","inclusion_delay":"4050","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"17771","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2961","inactivity":"0"},{"effective_balance":"24000000000","head":"80979","target":"80979","source":"80979","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"30000000000","head":"101224","target":"101224","source":"101224","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5077","inactivity":"0"},{"effective_balance":"21000000000","head":"70856","target":"70856","source":"70856","inclusion_delay":"7983","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5923","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2538","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"29000000000","head":"97850","target":"97850","source":"97850","inclusion_delay":"5272","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"30000000000","head":"101224","target":"101224","source":"101224","inclusion_delay":"4646","inactivity":"0"},{"effective_balance":"19000000000","head":"64108","target":"64108","source":"64108","inclusion_delay":"39725","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2369","inactivity":"0"},{"effective_balance":"29000000000","head":"97850","target":"97850","source":"97850","inclusion_delay":"4181","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"11847","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"effective_balance":"31000000000","head":"104598","target":"104598","source":"104598","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"29000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"30000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4956","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"effective_balance":"22000000000","head":"74230","target":"74230","source":"74230","inclusion_delay":"22998","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"11151","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2293","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3385","inactivity":"0"},{"effective_balance":"22000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2221","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"11151","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4956","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"35543","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5077","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"6462","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"}],"total_rewards":[{"validator_index":"0","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"1","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"2","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-358422"},{"validator_index":"3","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"4","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"},{"validator_index":"5","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"validator_index":"6","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"7","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"8","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"9","head":"107972","target":"107972","source":"107972","inclusion_delay":"11151","inactivity":"0"},{"validator_index":"10","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"validator_index":"11","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"validator_index":"12","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"13","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"14","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"validator_index":"15","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"validator_index":"16","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"17","head":"107972","target":"107972","source":"107972","inclusion_delay":"7871","inactivity":"0"},{"validator_index":"18","head":"107972","target":"107972","source":"107972","inclusion_delay":"66906","inactivity":"0"},{"validator_index":"19","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"20","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"validator_index":"21","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"validator_index":"22","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"23","head":"87727","target":"87727","source":"87727","inclusion_delay":"4348","inactivity":"0"},{"validator_index":"24","head":"57360","target":"57360","source":"57360","inclusion_delay":"6462","inactivity":"0"},{"validator_index":"25","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"validator_index":"26","head":"107972","target":"107972","source":"107972","inclusion_delay":"26762","inactivity":"0"},{"validator_index":"27","head":"67482","target":"67482","source":"67482","inclusion_delay":"4646","inactivity":"0"},{"validator_index":"28","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"29","head":"87727","target":"87727","source":"87727","inclusion_delay":"4941","inactivity":"0"},{"validator_index":"30","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"31","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"32","head":"80979","target":"80979","source":"80979","inclusion_delay":"9123","inactivity":"0"},{"validator_index":"33","head":"70856","target":"70856","source":"70856","inclusion_delay":"17562","inactivity":"0"},{"validator_index":"34","head":"107972","target":"107972","source":"107972","inclusion_delay":"4181","inactivity":"0"},{"validator_index":"35","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"validator_index":"36","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"37","head":"84353","target":"84353","source":"84353","inclusion_delay":"17423","inactivity":"0"},{"validator_index":"38","head":"57360","target":"57360","source":"57360","inclusion_delay":"4181","inactivity":"0"},{"validator_index":"39","head":"57360","target":"57360","source":"57360","inclusion_delay":"4442","inactivity":"0"},{"validator_index":"40","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"41","head":"107972","target":"107972","source":"107972","inclusion_delay":"33453","inactivity":"0"},{"validator_index":"42","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"43","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"44","head":"84353","target":"84353","source":"84353","inclusion_delay":"4355","inactivity":"0"},{"validator_index":"45","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"46","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"47","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"48","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"validator_index":"49","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"validator_index":"50","head":"57360","target":"57360","source":"57360","inclusion_delay":"3231","inactivity":"0"},{"validator_index":"51","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"52","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"53","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"validator_index":"54","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"validator_index":"55","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"56","head":"70856","target":"70856","source":"70856","inclusion_delay":"5854","inactivity":"0"},{"validator_index":"57","head":"60734","target":"60734","source":"60734","inclusion_delay":"8363","inactivity":"0"},{"validator_index":"58","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"validator_index":"59","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"validator_index":"60","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"validator_index":"61","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"validator_index":"62","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"63","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"64","head":"57360","target":"57360","source":"57360","inclusion_delay":"4442","inactivity":"0"},{"validator_index":"65","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"validator_index":"66","head":"107972","target":"107972","source":"107972","inclusion_delay":"11151","inactivity":"0"},{"validator_index":"67","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"68","head":"60734","target":"60734","source":"60734","inclusion_delay":"10752","inactivity":"0"},{"validator_index":"69","head":"101224","target":"101224","source":"101224","inclusion_delay":"3920","inactivity":"0"},{"validator_index":"70","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"validator_index":"71","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"validator_index":"72","head":"57360","target":"57360","source":"57360","inclusion_delay":"35543","inactivity":"0"},{"validator_index":"73","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"74","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"75","head":"107972","target":"107972","source":"107972","inclusion_delay":"9558","inactivity":"0"},{"validator_index":"76","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"validator_index":"77","head":"107972","target":"107972","source":"107972","inclusion_delay":"5575","inactivity":"0"},{"validator_index":"78","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"79","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"80","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"81","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-372759"},{"validator_index":"82","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"83","head":"107972","target":"107972","source":"107972","inclusion_delay":"10293","inactivity":"0"},{"validator_index":"84","head":"57360","target":"57360","source":"57360","inclusion_delay":"2221","inactivity":"0"},{"validator_index":"85","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"},{"validator_index":"86","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"validator_index":"87","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"88","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"89","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"validator_index":"90","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"validator_index":"91","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"validator_index":"92","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"93","head":"107972","target":"107972","source":"107972","inclusion_delay":"4181","inactivity":"0"},{"validator_index":"94","head":"64108","target":"64108","source":"64108","inclusion_delay":"5675","inactivity":"0"},{"validator_index":"95","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"validator_index":"96","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"validator_index":"97","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"98","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"validator_index":"99","head":"107972","target":"107972","source":"107972","inclusion_delay":"4956","inactivity":"0"},{"validator_index":"100","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"validator_index":"101","head":"107972","target":"107972","source":"107972","inclusion_delay":"33453","inactivity":"0"},{"validator_index":"102","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"103","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"validator_index":"104","head":"57360","target":"57360","source":"57360","inclusion_delay":"3231","inactivity":"0"},{"validator_index":"105","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"106","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"107","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-329748"},{"validator_index":"108","head":"107972","target":"107972","source":"107972","inclusion_delay":"7871","inactivity":"0"},{"validator_index":"109","head":"91101","target":"91101","source":"91101","inclusion_delay":"3763","inactivity":"0"},{"validator_index":"110","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"validator_index":"111","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"112","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"113","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"validator_index":"114","head":"77605","target":"77605","source":"77605","inclusion_delay":"10686","inactivity":"0"},{"validator_index":"115","head":"107972","target":"107972","source":"107972","inclusion_delay":"10293","inactivity":"0"},{"validator_index":"116","head":"80979","target":"80979","source":"80979","inclusion_delay":"4561","inactivity":"0"},{"validator_index":"117","head":"107972","target":"107972","source":"107972","inclusion_delay":"11151","inactivity":"0"},{"validator_index":"118","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"119","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"120","head":"107972","target":"107972","source":"107972","inclusion_delay":"5575","inactivity":"0"},{"validator_index":"121","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"122","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"123","head":"57360","target":"57360","source":"57360","inclusion_delay":"5923","inactivity":"0"},{"validator_index":"124","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"125","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"validator_index":"126","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"validator_index":"127","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"128","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"129","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"130","head":"107972","target":"107972","source":"107972","inclusion_delay":"33453","inactivity":"0"},{"validator_index":"131","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"132","head":"57360","target":"57360","source":"57360","inclusion_delay":"2538","inactivity":"0"},{"validator_index":"133","head":"57360","target":"57360","source":"57360","inclusion_delay":"4442","inactivity":"0"},{"validator_index":"134","head":"107972","target":"107972","source":"107972","inclusion_delay":"19116","inactivity":"0"},{"validator_index":"135","head":"67482","target":"67482","source":"67482","inclusion_delay":"2697","inactivity":"0"},{"validator_index":"136","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"137","head":"107972","target":"107972","source":"107972","inclusion_delay":"7871","inactivity":"0"},{"validator_index":"138","head":"77605","target":"77605","source":"77605","inclusion_delay":"8743","inactivity":"0"},{"validator_index":"139","head":"107972","target":"107972","source":"107972","inclusion_delay":"66906","inactivity":"0"},{"validator_index":"140","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"141","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"validator_index":"142","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"143","head":"57360","target":"57360","source":"57360","inclusion_delay":"7898","inactivity":"0"},{"validator_index":"144","head":"57360","target":"57360","source":"57360","inclusion_delay":"17771","inactivity":"0"},{"validator_index":"145","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"146","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"validator_index":"147","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"148","head":"107972","target":"107972","source":"107972","inclusion_delay":"26762","inactivity":"0"},{"validator_index":"149","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"150","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"},{"validator_index":"151","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"152","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"validator_index":"153","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"validator_index":"154","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"validator_index":"155","head":"64108","target":"64108","source":"64108","inclusion_delay":"5675","inactivity":"0"},{"validator_index":"156","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"157","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"158","head":"64108","target":"64108","source":"64108","inclusion_delay":"4673","inactivity":"0"},{"validator_index":"159","head":"87727","target":"87727","source":"87727","inclusion_delay":"4348","inactivity":"0"},{"validator_index":"160","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"161","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"validator_index":"162","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"163","head":"57360","target":"57360","source":"57360","inclusion_delay":"4181","inactivity":"0"},{"validator_index":"164","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"165","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"validator_index":"166","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"167","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-344085"},{"validator_index":"168","head":"57360","target":"57360","source":"57360","inclusion_delay":"4442","inactivity":"0"},{"validator_index":"169","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-286737"},{"validator_index":"170","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"validator_index":"171","head":"57360","target":"57360","source":"57360","inclusion_delay":"3949","inactivity":"0"},{"validator_index":"172","head":"94475","target":"94475","source":"94475","inclusion_delay":"7805","inactivity":"0"},{"validator_index":"173","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"174","head":"60734","target":"60734","source":"60734","inclusion_delay":"8363","inactivity":"0"},{"validator_index":"175","head":"57360","target":"57360","source":"57360","inclusion_delay":"6462","inactivity":"0"},{"validator_index":"176","head":"57360","target":"57360","source":"57360","inclusion_delay":"2843","inactivity":"0"},{"validator_index":"177","head":"107972","target":"107972","source":"107972","inclusion_delay":"26762","inactivity":"0"},{"validator_index":"178","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"179","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"validator_index":"180","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"181","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"validator_index":"182","head":"57360","target":"57360","source":"57360","inclusion_delay":"5468","inactivity":"0"},{"validator_index":"183","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"validator_index":"184","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"185","head":"77605","target":"77605","source":"77605","inclusion_delay":"3434","inactivity":"0"},{"validator_index":"186","head":"57360","target":"57360","source":"57360","inclusion_delay":"2369","inactivity":"0"},{"validator_index":"187","head":"57360","target":"57360","source":"57360","inclusion_delay":"17771","inactivity":"0"},{"validator_index":"188","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"validator_index":"189","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"190","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"191","head":"104598","target":"104598","source":"104598","inclusion_delay":"5401","inactivity":"0"},{"validator_index":"192","head":"97850","target":"97850","source":"97850","inclusion_delay":"20211","inactivity":"0"},{"validator_index":"193","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"validator_index":"194","head":"57360","target":"57360","source":"57360","inclusion_delay":"11847","inactivity":"0"},{"validator_index":"195","head":"57360","target":"57360","source":"57360","inclusion_delay":"2538","inactivity":"0"},{"validator_index":"196","head":"107972","target":"107972","source":"107972","inclusion_delay":"19116","inactivity":"0"},{"validator_index":"197","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"validator_index":"198","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"validator_index":"199","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"200","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"},{"validator_index":"201","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"validator_index":"202","head":"107972","target":"107972","source":"107972","inclusion_delay":"19116","inactivity":"0"},{"validator_index":"203","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"204","head":"57360","target":"57360","source":"57360","inclusion_delay":"2843","inactivity":"0"},{"validator_index":"205","head":"57360","target":"57360","source":"57360","inclusion_delay":"4181","inactivity":"0"},{"validator_index":"206","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"validator_index":"207","head":"91101","target":"91101","source":"91101","inclusion_delay":"5131","inactivity":"0"},{"validator_index":"208","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"209","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"210","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"211","head":"107972","target":"107972","source":"107972","inclusion_delay":"9558","inactivity":"0"},{"validator_index":"212","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"213","head":"57360","target":"57360","source":"57360","inclusion_delay":"2221","inactivity":"0"},{"validator_index":"214","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"validator_index":"215","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-329748"},{"validator_index":"216","head":"87727","target":"87727","source":"87727","inclusion_delay":"3507","inactivity":"0"},{"validator_index":"217","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"validator_index":"218","head":"57360","target":"57360","source":"57360","inclusion_delay":"5077","inactivity":"0"},{"validator_index":"219","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"validator_index":"220","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"validator_index":"221","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"222","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"validator_index":"223","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-258063"},{"validator_index":"224","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-301074"},{"validator_index":"225","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"validator_index":"226","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"227","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"validator_index":"228","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"229","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"validator_index":"230","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"231","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"validator_index":"232","head":"60734","target":"60734","source":"60734","inclusion_delay":"2508","inactivity":"0"},{"validator_index":"233","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"234","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-401433"},{"validator_index":"235","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-401433"},{"validator_index":"236","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"237","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"238","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"239","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-444444"},{"validator_index":"240","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"241","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"242","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"validator_index":"243","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"244","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"validator_index":"245","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-301074"},{"validator_index":"246","head":"107972","target":"107972","source":"107972","inclusion_delay":"7871","inactivity":"0"},{"validator_index":"247","head":"77605","target":"77605","source":"77605","inclusion_delay":"13739","inactivity":"0"},{"validator_index":"248","head":"107972","target":"107972","source":"107972","inclusion_delay":"19116","inactivity":"0"},{"validator_index":"249","head":"107972","target":"107972","source":"107972","inclusion_delay":"66906","inactivity":"0"},{"validator_index":"250","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"validator_index":"251","head":"70856","target":"70856","source":"70856","inclusion_delay":"14635","inactivity":"0"},{"validator_index":"252","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"validator_index":"253","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-301074"},{"validator_index":"254","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"validator_index":"255","head":"97850","target":"97850","source":"97850","inclusion_delay":"20211","inactivity":"0"},{"validator_index":"256","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"257","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"validator_index":"258","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"validator_index":"259","head":"77605","target":"77605","source":"77605","inclusion_delay":"19235","inactivity":"0"},{"validator_index":"260","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-258063"},{"validator_index":"261","head":"107972","target":"107972","source":"107972","inclusion_delay":"66906","inactivity":"0"},{"validator_index":"262","head":"101224","target":"101224","source":"101224","inclusion_delay":"5227","inactivity":"0"},{"validator_index":"263","head":"84353","target":"84353","source":"84353","inclusion_delay":"3604","inactivity":"0"},{"validator_index":"264","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"validator_index":"265","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"266","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-387096"},{"validator_index":"267","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"268","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"269","head":"101224","target":"101224","source":"101224","inclusion_delay":"6272","inactivity":"0"},{"validator_index":"270","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"validator_index":"271","head":"57360","target":"57360","source":"57360","inclusion_delay":"17771","inactivity":"0"},{"validator_index":"272","head":"64108","target":"64108","source":"64108","inclusion_delay":"8827","inactivity":"0"},{"validator_index":"273","head":"80979","target":"80979","source":"80979","inclusion_delay":"20071","inactivity":"0"},{"validator_index":"274","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"275","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-444444"},{"validator_index":"276","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"277","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"validator_index":"278","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"validator_index":"279","head":"57360","target":"57360","source":"57360","inclusion_delay":"5923","inactivity":"0"},{"validator_index":"280","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"validator_index":"281","head":"64108","target":"64108","source":"64108","inclusion_delay":"3310","inactivity":"0"},{"validator_index":"282","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"283","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"284","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"validator_index":"285","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"286","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"287","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"validator_index":"288","head":"84353","target":"84353","source":"84353","inclusion_delay":"14934","inactivity":"0"},{"validator_index":"289","head":"87727","target":"87727","source":"87727","inclusion_delay":"54361","inactivity":"0"},{"validator_index":"290","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"291","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"292","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"293","head":"107972","target":"107972","source":"107972","inclusion_delay":"26762","inactivity":"0"},{"validator_index":"294","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"295","head":"67482","target":"67482","source":"67482","inclusion_delay":"3636","inactivity":"0"},{"validator_index":"296","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-387096"},{"validator_index":"297","head":"64108","target":"64108","source":"64108","inclusion_delay":"6111","inactivity":"0"},{"validator_index":"298","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"validator_index":"299","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"validator_index":"300","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-344085"},{"validator_index":"301","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"302","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"validator_index":"303","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-358422"},{"validator_index":"304","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"305","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"validator_index":"306","head":"57360","target":"57360","source":"57360","inclusion_delay":"3385","inactivity":"0"},{"validator_index":"307","head":"57360","target":"57360","source":"57360","inclusion_delay":"5468","inactivity":"0"},{"validator_index":"308","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"validator_index":"309","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"310","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"validator_index":"311","head":"107972","target":"107972","source":"107972","inclusion_delay":"9558","inactivity":"0"},{"validator_index":"312","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"313","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"314","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"validator_index":"315","head":"57360","target":"57360","source":"57360","inclusion_delay":"3385","inactivity":"0"},{"validator_index":"316","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"317","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"318","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"319","head":"57360","target":"57360","source":"57360","inclusion_delay":"2843","inactivity":"0"},{"validator_index":"320","head":"107972","target":"107972","source":"107972","inclusion_delay":"9558","inactivity":"0"},{"validator_index":"321","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"322","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"323","head":"104598","target":"104598","source":"104598","inclusion_delay":"4470","inactivity":"0"},{"validator_index":"324","head":"57360","target":"57360","source":"57360","inclusion_delay":"2369","inactivity":"0"},{"validator_index":"325","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"validator_index":"326","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-315411"},{"validator_index":"327","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"328","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"validator_index":"329","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"330","head":"107972","target":"107972","source":"107972","inclusion_delay":"26762","inactivity":"0"},{"validator_index":"331","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"332","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"333","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"validator_index":"334","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"validator_index":"335","head":"77605","target":"77605","source":"77605","inclusion_delay":"3316","inactivity":"0"},{"validator_index":"336","head":"57360","target":"57360","source":"57360","inclusion_delay":"4181","inactivity":"0"},{"validator_index":"337","head":"107972","target":"107972","source":"107972","inclusion_delay":"4181","inactivity":"0"},{"validator_index":"338","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"339","head":"57360","target":"57360","source":"57360","inclusion_delay":"2538","inactivity":"0"},{"validator_index":"340","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-358422"},{"validator_index":"341","head":"57360","target":"57360","source":"57360","inclusion_delay":"5468","inactivity":"0"},{"validator_index":"342","head":"57360","target":"57360","source":"57360","inclusion_delay":"2221","inactivity":"0"},{"validator_index":"343","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-387096"},{"validator_index":"344","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"345","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"346","head":"107972","target":"107972","source":"107972","inclusion_delay":"66906","inactivity":"0"},{"validator_index":"347","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"348","head":"97850","target":"97850","source":"97850","inclusion_delay":"60633","inactivity":"0"},{"validator_index":"349","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"validator_index":"350","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-286737"},{"validator_index":"351","head":"57360","target":"57360","source":"57360","inclusion_delay":"7898","inactivity":"0"},{"validator_index":"352","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"353","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"},{"validator_index":"354","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"355","head":"60734","target":"60734","source":"60734","inclusion_delay":"4704","inactivity":"0"},{"validator_index":"356","head":"57360","target":"57360","source":"57360","inclusion_delay":"2843","inactivity":"0"},{"validator_index":"357","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"358","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"359","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"validator_index":"360","head":"107972","target":"107972","source":"107972","inclusion_delay":"10293","inactivity":"0"},{"validator_index":"361","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"362","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"363","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"validator_index":"364","head":"57360","target":"57360","source":"57360","inclusion_delay":"35543","inactivity":"0"},{"validator_index":"365","head":"107972","target":"107972","source":"107972","inclusion_delay":"5575","inactivity":"0"},{"validator_index":"366","head":"57360","target":"57360","source":"57360","inclusion_delay":"2293","inactivity":"0"},{"validator_index":"367","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"validator_index":"368","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"369","head":"57360","target":"57360","source":"57360","inclusion_delay":"4442","inactivity":"0"},{"validator_index":"370","head":"74230","target":"74230","source":"74230","inclusion_delay":"5110","inactivity":"0"},{"validator_index":"371","head":"57360","target":"57360","source":"57360","inclusion_delay":"5923","inactivity":"0"},{"validator_index":"372","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"373","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"validator_index":"374","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"validator_index":"375","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"376","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"377","head":"57360","target":"57360","source":"57360","inclusion_delay":"2369","inactivity":"0"},{"validator_index":"378","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"379","head":"57360","target":"57360","source":"57360","inclusion_delay":"11847","inactivity":"0"},{"validator_index":"380","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-387096"},{"validator_index":"381","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"validator_index":"382","head":"57360","target":"57360","source":"57360","inclusion_delay":"2369","inactivity":"0"},{"validator_index":"383","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"384","head":"57360","target":"57360","source":"57360","inclusion_delay":"4739","inactivity":"0"},{"validator_index":"385","head":"60734","target":"60734","source":"60734","inclusion_delay":"4427","inactivity":"0"},{"validator_index":"386","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"387","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"validator_index":"388","head":"107972","target":"107972","source":"107972","inclusion_delay":"5575","inactivity":"0"},{"validator_index":"389","head":"94475","target":"94475","source":"94475","inclusion_delay":"29271","inactivity":"0"},{"validator_index":"390","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"391","head":"107972","target":"107972","source":"107972","inclusion_delay":"5575","inactivity":"0"},{"validator_index":"392","head":"101224","target":"101224","source":"101224","inclusion_delay":"25089","inactivity":"0"},{"validator_index":"393","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"394","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"395","head":"97850","target":"97850","source":"97850","inclusion_delay":"3789","inactivity":"0"},{"validator_index":"396","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"397","head":"70856","target":"70856","source":"70856","inclusion_delay":"7317","inactivity":"0"},{"validator_index":"398","head":"104598","target":"104598","source":"104598","inclusion_delay":"7201","inactivity":"0"},{"validator_index":"399","head":"74230","target":"74230","source":"74230","inclusion_delay":"5411","inactivity":"0"},{"validator_index":"400","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"401","head":"80979","target":"80979","source":"80979","inclusion_delay":"7168","inactivity":"0"},{"validator_index":"402","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"403","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"404","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"405","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"validator_index":"406","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"validator_index":"407","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-272400"},{"validator_index":"408","head":"57360","target":"57360","source":"57360","inclusion_delay":"5468","inactivity":"0"},{"validator_index":"409","head":"57360","target":"57360","source":"57360","inclusion_delay":"2843","inactivity":"0"},{"validator_index":"410","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"411","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"validator_index":"412","head":"107972","target":"107972","source":"107972","inclusion_delay":"10293","inactivity":"0"},{"validator_index":"413","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"validator_index":"414","head":"57360","target":"57360","source":"57360","inclusion_delay":"3385","inactivity":"0"},{"validator_index":"415","head":"87727","target":"87727","source":"87727","inclusion_delay":"4530","inactivity":"0"},{"validator_index":"416","head":"57360","target":"57360","source":"57360","inclusion_delay":"5077","inactivity":"0"},{"validator_index":"417","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"validator_index":"418","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"419","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"420","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"validator_index":"421","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"validator_index":"422","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"423","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"validator_index":"424","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"425","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"validator_index":"426","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"427","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"validator_index":"428","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"validator_index":"429","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"validator_index":"430","head":"57360","target":"57360","source":"57360","inclusion_delay":"5468","inactivity":"0"},{"validator_index":"431","head":"104598","target":"104598","source":"104598","inclusion_delay":"4050","inactivity":"0"},{"validator_index":"432","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"433","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"434","head":"57360","target":"57360","source":"57360","inclusion_delay":"17771","inactivity":"0"},{"validator_index":"435","head":"57360","target":"57360","source":"57360","inclusion_delay":"2961","inactivity":"0"},{"validator_index":"436","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-344085"},{"validator_index":"437","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"438","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-430107"},{"validator_index":"439","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"440","head":"57360","target":"57360","source":"57360","inclusion_delay":"5077","inactivity":"0"},{"validator_index":"441","head":"70856","target":"70856","source":"70856","inclusion_delay":"7983","inactivity":"0"},{"validator_index":"442","head":"57360","target":"57360","source":"57360","inclusion_delay":"5923","inactivity":"0"},{"validator_index":"443","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"444","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"445","head":"57360","target":"57360","source":"57360","inclusion_delay":"2538","inactivity":"0"},{"validator_index":"446","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"validator_index":"447","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"448","head":"97850","target":"97850","source":"97850","inclusion_delay":"5272","inactivity":"0"},{"validator_index":"449","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"450","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"451","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"validator_index":"452","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"453","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"454","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"455","head":"101224","target":"101224","source":"101224","inclusion_delay":"4646","inactivity":"0"},{"validator_index":"456","head":"64108","target":"64108","source":"64108","inclusion_delay":"39725","inactivity":"0"},{"validator_index":"457","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"validator_index":"458","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"459","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"validator_index":"460","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"461","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"462","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"validator_index":"463","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"464","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"validator_index":"465","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"validator_index":"466","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"467","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"468","head":"57360","target":"57360","source":"57360","inclusion_delay":"2369","inactivity":"0"},{"validator_index":"469","head":"97850","target":"97850","source":"97850","inclusion_delay":"4181","inactivity":"0"},{"validator_index":"470","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"471","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"472","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"validator_index":"473","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"validator_index":"474","head":"57360","target":"57360","source":"57360","inclusion_delay":"11847","inactivity":"0"},{"validator_index":"475","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"validator_index":"476","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-444444"},{"validator_index":"477","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"validator_index":"478","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"validator_index":"479","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"480","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"481","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"validator_index":"482","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"validator_index":"483","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"validator_index":"484","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"485","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"486","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"487","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"488","head":"107972","target":"107972","source":"107972","inclusion_delay":"4956","inactivity":"0"},{"validator_index":"489","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"validator_index":"490","head":"74230","target":"74230","source":"74230","inclusion_delay":"22998","inactivity":"0"},{"validator_index":"491","head":"107972","target":"107972","source":"107972","inclusion_delay":"11151","inactivity":"0"},{"validator_index":"492","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"validator_index":"493","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"494","head":"57360","target":"57360","source":"57360","inclusion_delay":"2293","inactivity":"0"},{"validator_index":"495","head":"57360","target":"57360","source":"57360","inclusion_delay":"3385","inactivity":"0"},{"validator_index":"496","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"497","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"498","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"499","head":"57360","target":"57360","source":"57360","inclusion_delay":"2221","inactivity":"0"},{"validator_index":"500","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"validator_index":"501","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"validator_index":"502","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"503","head":"107972","target":"107972","source":"107972","inclusion_delay":"11151","inactivity":"0"},{"validator_index":"504","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"505","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"506","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"validator_index":"507","head":"107972","target":"107972","source":"107972","inclusion_delay":"4956","inactivity":"0"},{"validator_index":"508","head":"57360","target":"57360","source":"57360","inclusion_delay":"35543","inactivity":"0"},{"validator_index":"509","head":"57360","target":"57360","source":"57360","inclusion_delay":"5077","inactivity":"0"},{"validator_index":"510","head":"57360","target":"57360","source":"57360","inclusion_delay":"6462","inactivity":"0"},{"validator_index":"511","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"validator_index":"512","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"513","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"514","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"515","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"516","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"517","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"518","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"519","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"520","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"521","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"522","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"523","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"524","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"525","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"526","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"527","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"}]}}` + "\n", // Add your expected response - }, - { - epoch: 99999999, - code: http.StatusNotFound, - }, - { - name: "2 validators", - epoch: (fcu.HeadSlotVal / 32) - 1, - request: `["1","4"]`, - code: http.StatusOK, - expected: `{"data":{"ideal_rewards":[{"effective_balance":"20000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"}],"total_rewards":[{"validator_index":"1","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"4","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"}]}}` + "\n", // Add your expected response - }, - } - for _, c := range cases { - t.Run(c.name, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - url := fmt.Sprintf("%s/eth/v1/beacon/rewards/attestations/%d", server.URL, c.epoch) - - // Create a request - req, err := http.NewRequest("POST", url, strings.NewReader(c.request)) - require.NoError(t, err) - req.Header.Set("Content-Type", "application/json") - - // Perform the request - resp, err := http.DefaultClient.Do(req) - require.NoError(t, err) - defer resp.Body.Close() - - // Check status code - require.Equal(t, c.code, resp.StatusCode) - - if resp.StatusCode != http.StatusOK { - return - } - - // Read the response body - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - // Compare the response with the expected result - require.Equal(t, c.expected, string(out)) - }) - } -} diff --git a/cl/beacon/handler/blocks.go b/cl/beacon/handler/blocks.go index 2035b7663b5..2fd7d38eebf 100644 --- a/cl/beacon/handler/blocks.go +++ b/cl/beacon/handler/blocks.go @@ -23,18 +23,18 @@ type getHeadersRequest struct { ParentRoot *libcommon.Hash `json:"root,omitempty"` } -func (a *ApiHandler) rootFromBlockId(ctx context.Context, tx kv.Tx, blockId *segmentID) (root libcommon.Hash, err error) { +func (a *ApiHandler) rootFromBlockId(ctx context.Context, tx kv.Tx, blockId *beaconhttp.SegmentID) (root libcommon.Hash, err error) { switch { - case blockId.head(): + case blockId.Head(): root, _, err = a.forkchoiceStore.GetHead() if err != nil { return libcommon.Hash{}, err } - case blockId.finalized(): + case blockId.Finalized(): root = a.forkchoiceStore.FinalizedCheckpoint().BlockRoot() - case blockId.justified(): + case blockId.Justified(): root = a.forkchoiceStore.JustifiedCheckpoint().BlockRoot() - case blockId.genesis(): + case blockId.Genesis(): root, err = beacon_indicies.ReadCanonicalBlockRoot(tx, 0) if err != nil { return libcommon.Hash{}, err @@ -42,24 +42,24 @@ func (a *ApiHandler) rootFromBlockId(ctx context.Context, tx kv.Tx, blockId *seg if root == (libcommon.Hash{}) { return libcommon.Hash{}, beaconhttp.NewEndpointError(http.StatusNotFound, "genesis block not found") } - case blockId.getSlot() != nil: - root, err = beacon_indicies.ReadCanonicalBlockRoot(tx, *blockId.getSlot()) + case blockId.GetSlot() != nil: + root, err = beacon_indicies.ReadCanonicalBlockRoot(tx, *blockId.GetSlot()) if err != nil { return libcommon.Hash{}, err } if root == (libcommon.Hash{}) { - return libcommon.Hash{}, beaconhttp.NewEndpointError(http.StatusNotFound, fmt.Sprintf("block not found %d", *blockId.getSlot())) + return libcommon.Hash{}, beaconhttp.NewEndpointError(http.StatusNotFound, fmt.Sprintf("block not found %d", *blockId.GetSlot())) } - case blockId.getRoot() != nil: + case blockId.GetRoot() != nil: // first check if it exists - root = *blockId.getRoot() + root = *blockId.GetRoot() default: return libcommon.Hash{}, beaconhttp.NewEndpointError(http.StatusInternalServerError, "cannot parse block id") } return } -func (a *ApiHandler) getBlock(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getBlock(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { ctx := r.Context() tx, err := a.indiciesDB.BeginRo(ctx) if err != nil { @@ -67,7 +67,7 @@ func (a *ApiHandler) getBlock(w http.ResponseWriter, r *http.Request) (*beaconRe } defer tx.Rollback() - blockId, err := blockIdFromRequest(r) + blockId, err := beaconhttp.BlockIdFromRequest(r) if err != nil { return nil, err } @@ -90,11 +90,11 @@ func (a *ApiHandler) getBlock(w http.ResponseWriter, r *http.Request) (*beaconRe return nil, err } return newBeaconResponse(blk). - withFinalized(root == canonicalRoot && blk.Block.Slot <= a.forkchoiceStore.FinalizedSlot()). - withVersion(blk.Version()), nil + WithFinalized(root == canonicalRoot && blk.Block.Slot <= a.forkchoiceStore.FinalizedSlot()). + WithVersion(blk.Version()), nil } -func (a *ApiHandler) getBlindedBlock(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getBlindedBlock(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { ctx := r.Context() tx, err := a.indiciesDB.BeginRo(ctx) if err != nil { @@ -102,7 +102,7 @@ func (a *ApiHandler) getBlindedBlock(w http.ResponseWriter, r *http.Request) (*b } defer tx.Rollback() - blockId, err := blockIdFromRequest(r) + blockId, err := beaconhttp.BlockIdFromRequest(r) if err != nil { return nil, err } @@ -129,18 +129,18 @@ func (a *ApiHandler) getBlindedBlock(w http.ResponseWriter, r *http.Request) (*b return nil, err } return newBeaconResponse(blinded). - withFinalized(root == canonicalRoot && blk.Block.Slot <= a.forkchoiceStore.FinalizedSlot()). - withVersion(blk.Version()), nil + WithFinalized(root == canonicalRoot && blk.Block.Slot <= a.forkchoiceStore.FinalizedSlot()). + WithVersion(blk.Version()), nil } -func (a *ApiHandler) getBlockAttestations(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getBlockAttestations(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { ctx := r.Context() tx, err := a.indiciesDB.BeginRo(ctx) if err != nil { return nil, err } defer tx.Rollback() - blockId, err := blockIdFromRequest(r) + blockId, err := beaconhttp.BlockIdFromRequest(r) if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } @@ -160,18 +160,19 @@ func (a *ApiHandler) getBlockAttestations(w http.ResponseWriter, r *http.Request if err != nil { return nil, err } - return newBeaconResponse(blk.Block.Body.Attestations).withFinalized(root == canonicalRoot && blk.Block.Slot <= a.forkchoiceStore.FinalizedSlot()). - withVersion(blk.Version()), nil + return newBeaconResponse(blk.Block.Body.Attestations). + WithFinalized(root == canonicalRoot && blk.Block.Slot <= a.forkchoiceStore.FinalizedSlot()). + WithVersion(blk.Version()), nil } -func (a *ApiHandler) getBlockRoot(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getBlockRoot(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { ctx := r.Context() tx, err := a.indiciesDB.BeginRo(ctx) if err != nil { return nil, err } defer tx.Rollback() - blockId, err := blockIdFromRequest(r) + blockId, err := beaconhttp.BlockIdFromRequest(r) if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } @@ -195,5 +196,5 @@ func (a *ApiHandler) getBlockRoot(w http.ResponseWriter, r *http.Request) (*beac } return newBeaconResponse(struct { Root libcommon.Hash `json:"root"` - }{Root: root}).withFinalized(canonicalRoot == root && *slot <= a.forkchoiceStore.FinalizedSlot()), nil + }{Root: root}).WithFinalized(canonicalRoot == root && *slot <= a.forkchoiceStore.FinalizedSlot()), nil } diff --git a/cl/beacon/handler/blocks_test.go b/cl/beacon/handler/blocks_test.go deleted file mode 100644 index f07b506b6fc..00000000000 --- a/cl/beacon/handler/blocks_test.go +++ /dev/null @@ -1,254 +0,0 @@ -package handler - -import ( - "encoding/json" - "io" - "net/http" - "net/http/httptest" - "strconv" - "testing" - - "github.com/ledgerwatch/erigon/cl/clparams" - "github.com/ledgerwatch/erigon/common" - "github.com/stretchr/testify/require" -) - -func TestGetBlindedBlock(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, _, handler, _, _, fcu := setupTestingHandler(t, clparams.Phase0Version) - - // Start by testing - rootBlock1, err := blocks[len(blocks)-1].Block.HashSSZ() - if err != nil { - t.Fatal(err) - } - - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - - cases := []struct { - blockID string - code int - slot uint64 - }{ - { - blockID: "0x" + common.Bytes2Hex(rootBlock1[:]), - code: http.StatusOK, - slot: blocks[0].Block.Slot, - }, - { - blockID: "head", - code: http.StatusOK, - slot: blocks[len(blocks)-1].Block.Slot, - }, - { - blockID: "0x" + common.Bytes2Hex(make([]byte, 32)), - code: http.StatusNotFound, - }, - } - expected := `{"data":{"signature":"0x8b915f3b9d2d4c7ccaacf5d56c1152b1e91eafd1f59ba734d09e78996930b63ca550499997fe6d590343aaf5997f0d0c14c986571992ac9ed188de2b31ae4b7d70dfb68edae8b012f72f284dc8da44f4af5a2bdf3dfc9c0897ec4f7165daa07a","message":{"slot":"8322","proposer_index":"210","parent_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","state_root":"0x933d6650f2999f17012e781f5012981edb549e5935de1c981fce81cdd241d4e1","body":{"randao_reveal":"0xa182a6c7224c53cc43492b7ba87b54e8303094ebcb8c822da09c4224791b461e34d089ac857acf05cd695679c25cffa30404832791fe424fd104e2e96ebbf583dd5ec4dcbc891e7f4e0dea402071dbd294810417221fc41e4f90e4837c694e1a","eth1_data":{"deposit_root":"0x0000000000000000000000000000000000000000000000000000000000000000","deposit_count":"528","block_hash":"0x0000000000000000000000000000000000000000000000000000000000000000"},"graffiti":"0x0000000000000000000000000000000000000000000000000000000000000000","proposer_slashings":[{"signed_header_1":{"message":{"slot":"8321","proposer_index":"476","parent_root":"0x3333333333333333333333333333333333333333333333333333333333333333","state_root":"0x4444444444444444444444444444444444444444444444444444444444444444","body_root":"0x5555555555555555555555555555555555555555555555555555555555555555"},"signature":"0x939584df88598e56fe144105c6933b4727d7b772539e65c57289df64cedee771377e4d0e94f85c25d39a6072997d309c09da8c477267670aa42f26fb0836c72ec5867fa2f34dc0eb7e043ef5d6421282d1515b0f8c7ffd4bbbf56ee8d61ed063"},"signed_header_2":{"message":{"slot":"8321","proposer_index":"476","parent_root":"0x9999999999999999999999999999999999999999999999999999999999999999","state_root":"0x4444444444444444444444444444444444444444444444444444444444444444","body_root":"0x5555555555555555555555555555555555555555555555555555555555555555"},"signature":"0x8a184441d5d944ed3c18549dd9e4640eda879f9e737ac4211fdddfd30a65e1a2a32a8aa918ca65ad9b863a15e8cfefc412608ca78fd54ea1e5cbbd5697d125cc721aac1b01e8984a33f025c4707623669573244a632ec7f37808c01fab143f58"}},{"signed_header_1":{"message":{"slot":"8321","proposer_index":"406","parent_root":"0x3333333333333333333333333333333333333333333333333333333333333333","state_root":"0x4444444444444444444444444444444444444444444444444444444444444444","body_root":"0x5555555555555555555555555555555555555555555555555555555555555555"},"signature":"0xad97a43e9f28a90ff46b07a7bf65d520b89a78af47dbff1c10e4fc6bb36b4ee9c4f27f2a72c65311a03e7b48e06d86db1149147b14a8803d46f6a457092642dc89d3f2782bd48a373e3125af1a84f5b76d4ff7ddc85ac2650ca4c0f99e1af592"},"signed_header_2":{"message":{"slot":"8321","proposer_index":"406","parent_root":"0x9999999999999999999999999999999999999999999999999999999999999999","state_root":"0x4444444444444444444444444444444444444444444444444444444444444444","body_root":"0x5555555555555555555555555555555555555555555555555555555555555555"},"signature":"0x88d860d460526de062ee196400e24cb3055de2ff6abb31331d0bfeeebcdc77839d22ad6dfec39d81279f5527d1ffbd7e0a9d6eee7dce5a1cd6f79451537e9dfb6384f595e9d49673c58c181527a599dd4b38154e1322f1607f192ab0394f1411"}},{"signed_header_1":{"message":{"slot":"8321","proposer_index":"281","parent_root":"0x3333333333333333333333333333333333333333333333333333333333333333","state_root":"0x4444444444444444444444444444444444444444444444444444444444444444","body_root":"0x5555555555555555555555555555555555555555555555555555555555555555"},"signature":"0x8a2358ff11a30100a2492001827f54ff6c10dd6dcea66f6814dd1cccc4a49850bbbe36546e4f9b72410042a9d5882e8219a5a01708b8a95ca57984debe78f419a4ac921270a0f0c11c795a6c5ef1e6bfb96712751a4fee61059ca8fbe69639b6"},"signed_header_2":{"message":{"slot":"8321","proposer_index":"281","parent_root":"0x9999999999999999999999999999999999999999999999999999999999999999","state_root":"0x4444444444444444444444444444444444444444444444444444444444444444","body_root":"0x5555555555555555555555555555555555555555555555555555555555555555"},"signature":"0xb820e03b7bfd21c2d97a4f2bc9dd1fd5325894757f7129646c7a39a02b2c1c8ca33d509b4e83491e79db02ac0490aa3308ee23bfa1f65bf4130ab07e377a8cbd4eace5b69801528322dde425b0a78310504c330da30be7cefc674573dbdb4502"}},{"signed_header_1":{"message":{"slot":"8321","proposer_index":"169","parent_root":"0x3333333333333333333333333333333333333333333333333333333333333333","state_root":"0x4444444444444444444444444444444444444444444444444444444444444444","body_root":"0x5555555555555555555555555555555555555555555555555555555555555555"},"signature":"0x88c81a6029f097a9f23e37c7677abfafa2921982e9aebffc35ca700e1aefcd49c2ab5d51c7b28ef3db3aad49d58a6407082ce1ecd7f7bd89cb764242890440b684fc0e1511e047434b25f3ad1a5e238e5bf97f51e9e37d6eed48e0b9fef64333"},"signed_header_2":{"message":{"slot":"8321","proposer_index":"169","parent_root":"0x9999999999999999999999999999999999999999999999999999999999999999","state_root":"0x4444444444444444444444444444444444444444444444444444444444444444","body_root":"0x5555555555555555555555555555555555555555555555555555555555555555"},"signature":"0x815b492a6a3fb606f01dbc595c8b18b51b7f7a5a86b11f3ae57c48f7506a34606556a3cf2be683ce23cd0c7b2235667613f9dbcf98408b176f134645f122684bd8fe704c7a4eccb7bb7cbe33c6de377be4d742291d35d0ec8d6083c1b17b7261"}},{"signed_header_1":{"message":{"slot":"8321","proposer_index":"397","parent_root":"0x3333333333333333333333333333333333333333333333333333333333333333","state_root":"0x4444444444444444444444444444444444444444444444444444444444444444","body_root":"0x5555555555555555555555555555555555555555555555555555555555555555"},"signature":"0xae352ba8550d04c07591224449bd4967f66f9d639b731795f643b1e3fc5ad28317268dc9e289ce6075e8981a0e37d9440885e4f4292cb4b4656bd0c7bd9fc22d21eb4c7d1b46f1b08cdb1eb08d7a405985e8a406e6d93c5c3fdd20e91baba122"},"signed_header_2":{"message":{"slot":"8321","proposer_index":"397","parent_root":"0x9999999999999999999999999999999999999999999999999999999999999999","state_root":"0x4444444444444444444444444444444444444444444444444444444444444444","body_root":"0x5555555555555555555555555555555555555555555555555555555555555555"},"signature":"0xb9152f5510f2bfa5ab7b61829823f25f0c879ab9b852fcd90c17f751bed6e687dc523fcda177503509cd1befec36046a056a66f5826e2333b6de67430a16f6194416681ae69a1c3498cf8351abae4fac5d8f0b51b1734633d545d540bf269270"}}],"attester_slashings":[{"attestation_1":{"attesting_indicies":["96","353","445"],"data":{"slot":"555","index":"0","beacon_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"17","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}},"signature":"0xa7e932307a82913b23743198182a7e3c97675e8a1133e8d946bc59c62b1765046214ca0ea0e13b77e4f8acc8f226498103684f382826a9fff6c6c2ffdf9c65ffeb1680155025f489f676457634581ee4363bdfbe4d46fc4d1d9df93c3df8750d"},"attestation_2":{"attesting_indicies":["96","353","445"],"data":{"slot":"555","index":"0","beacon_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"17","root":"0x0101010101010101010101010101010101010101010101010101010101010101"}},"signature":"0x89aadbd74370dc6d86b6b61c544c1e18949b0d8aa2d706605d1014d0266a043588a829243d343d1c3812621944ea34540aef1fbd34fe51b03a5734ebc5ec31057d1df0004faeca71d8687dd3af806e4332e19f6da5ab1d7da67fe017c2f2e68b"}}],"attestations":[{"aggregation_bits":"0xff3f","signature":"0x8b63c286bff1c5dc6fb2e4878e73631e16db1cd3b07e9d0150b3ede4175635fe8db571cb486398e35923640606643d630bacc148d84e9c1060c32b55fe644e5c2573326b041767c5d45d45509a5403a7f2f1b2dd60e54bed26f407bb367a8642","data":{"slot":"8314","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0xb731b2df4dcaf841d50747f85b332170471895508c3af7e8bada14e58a816fed435460e1694e87e2887f19a0de201c3d0bc1ece52c26c519fd9131b25fa8a69b229c14ffd1c935d9e853aca8ab07eaae98a65daec09b2640b91961685e96d58c","data":{"slot":"8292","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x876c656d7889c15cd355d6652b347a25dc8fd7ffc383f0d14ad436b5f1af9ac09e06168ad71be76b85c3dd44ae79cc0f04f250a0bcc529d06a1032283e2b8b384d582c0ace50bf747264a199647697f159d06be75ecfb24da2a8b625a3087804","data":{"slot":"8293","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x876c656d7889c15cd355d6652b347a25dc8fd7ffc383f0d14ad436b5f1af9ac09e06168ad71be76b85c3dd44ae79cc0f04f250a0bcc529d06a1032283e2b8b384d582c0ace50bf747264a199647697f159d06be75ecfb24da2a8b625a3087804","data":{"slot":"8293","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x98416260b644654a4a90bda6032053f1eb3a12c59a3c7534f1ef348f2108c2837245bce74b3fd9f61ebae24860cc698100f864c4f26966c36431acbf0beea679807ba4eba9adfd1a267ef8d990290a2548af6456b1d0def6639ac47fd30c5542","data":{"slot":"8317","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x805e92ba1e4c88489f178202ca5d7ce96e7b874fe98bdee80ab6423441bd37ff3f0fe724bc088f58050ac2a8f81ec5e80401d76caeb65795b5794e7a20d0384f3bfd162b281a17e96cc98087c651d893b05154203af7a7591afe1056db934ec4","data":{"slot":"8309","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527","data":{"slot":"8313","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x95bbaf8dcff64306f01e0b09b27ebe3c761def7edd75542e213586ee0c6d3fc313ae102760abd1262b4f8c00e57603fa01627390011e3a5dea555c74798d7a3e1da68e00e3cdb9d8e4af112b6ff83951bd926288d24eb82e3f203a3160a4d7a9","data":{"slot":"8312","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x894270af1854ce4e65c6e09bc83c15171d564a2af871d0b442cacea78536e5cd34cf4a906025a6d87e12a172ceeb79990b86a1de7ed4ef40cffeca6b93402c3542682bb2914c34430e23038a57e8490abe809dc9f96f3b2caebed380113280b3","data":{"slot":"8297","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0xa44792a6341475c3eff0c11ad62bc19154d5ed48a4b81869ed49885499d5f768c81f357dd6a3ea60aa2f15a184b098f40a1382cfaea0a8438d62d9cca27c85023245b1838e2e4f1d4e65926f8c6a3032740b36c0a3c8aa69850648ac6c12b3ce","data":{"slot":"8306","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x98aade2cf9dad0e1528edec0e76be15577601b6cbef68353e51748b6286bf08812e42fe8791147a54eeed34782249e3f0cc463e22d6cb1c6050636ca8d070531fe40e16913f2e5560f6e683a6781268ff08d32bc5899b00306a87eecc5603928","data":{"slot":"8290","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0xab42974cba2e3fa75faa4c1f717caf7c2a953f4964063462ed32629764336124fd2f2f430ddf0291325722206250452c109b14cded0e51171b89b106b6b2044291128c3d6966c804490033b9e5fd06450ea50d22b5ab761892c6c3f4de79e098","data":{"slot":"8291","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x8d852ffa1c5960ba3a5d09837fbdb859bbf9045001b3d1dc1c4d22c6b4bc5b6d506f6ef667b5c7c9fbfb1dd0cfe3617405f56750f8b5eb25b3539d0a4c94822b198c524de92a6c68982ce17f985ff5283cea6ac8dabe41828ce38edb7e9fe223","data":{"slot":"8311","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x8bfaed4667e28ed9e39464c7c57027ae345f22847b6ac1aa7e5f342fdb6cdca9d78a962da68f9e34e0453f68fa363fcd196881e2dd76abcab6814439d73448f404124ad2e2f57b59b0df57699d913e24f79c53f129a09c05f2659e4444f4bb53","data":{"slot":"8320","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"258","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"260","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x97426dbbe61af8a68ac683ba95ad871baade096e9287e2d533c1efba04430b7083283485db5b1624fb03639065e8c754155cfe68986d526c1a771b67e45c0e8c97428dee8c6d80cc68892b961e8352d50f34e2623dc3b7ba2cb5dba28a854079","data":{"slot":"8302","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x94fab4732e767881653a5923ca4a93fc2778d349cef972b077aa0fd2553946f578be6571d7a02fe14aa98b11a77475e115bc8062308b23a23c6ce71cd07c528a6e37d30324d57dcc36fa336575210bce5d71ccabf74f0dd96f839eefc1a49343","data":{"slot":"8296","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x8b63c286bff1c5dc6fb2e4878e73631e16db1cd3b07e9d0150b3ede4175635fe8db571cb486398e35923640606643d630bacc148d84e9c1060c32b55fe644e5c2573326b041767c5d45d45509a5403a7f2f1b2dd60e54bed26f407bb367a8642","data":{"slot":"8314","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x805e92ba1e4c88489f178202ca5d7ce96e7b874fe98bdee80ab6423441bd37ff3f0fe724bc088f58050ac2a8f81ec5e80401d76caeb65795b5794e7a20d0384f3bfd162b281a17e96cc98087c651d893b05154203af7a7591afe1056db934ec4","data":{"slot":"8309","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527","data":{"slot":"8313","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0xb60160a4024734b6c22e6083d755d97b22d107001965d35cd1aa5fc3c1059b4cb482c36c78609c0fa131631eb847d165177c877949e5baebb96a48f6e471c1d1d700619b4adeafa728b4d69de8d03d02854e4240d8e16d790168619cc2027247","data":{"slot":"8318","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527","data":{"slot":"8313","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x8b1fbaba2982cd546a7d19d4af3755163112349a0e6d13f05c69807c709f363359c2cfff8a4afa66bd24445eb12b923615c33892a82d8081575207e4165a1d0c944fd3871ff885662c3921b152e674130879d67a0692b4867ad9fc2d20e24fa3","data":{"slot":"8307","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0xa44792a6341475c3eff0c11ad62bc19154d5ed48a4b81869ed49885499d5f768c81f357dd6a3ea60aa2f15a184b098f40a1382cfaea0a8438d62d9cca27c85023245b1838e2e4f1d4e65926f8c6a3032740b36c0a3c8aa69850648ac6c12b3ce","data":{"slot":"8306","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x8b1fbaba2982cd546a7d19d4af3755163112349a0e6d13f05c69807c709f363359c2cfff8a4afa66bd24445eb12b923615c33892a82d8081575207e4165a1d0c944fd3871ff885662c3921b152e674130879d67a0692b4867ad9fc2d20e24fa3","data":{"slot":"8307","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0xab42974cba2e3fa75faa4c1f717caf7c2a953f4964063462ed32629764336124fd2f2f430ddf0291325722206250452c109b14cded0e51171b89b106b6b2044291128c3d6966c804490033b9e5fd06450ea50d22b5ab761892c6c3f4de79e098","data":{"slot":"8291","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x9494651d4491cfc326f3439cebc3304aaf50a8e5598217da6df2a13b5cb9f9731cc8934f406c0243786b17f936d5892801fc34fc74fb4f52fec147536375dabd9f892940aacdea196e28cb21320bce9ede79b0a11333569d90e6deeb59869217","data":{"slot":"8300","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x87c3f6fac9ea937a8e8bd4f6dccb7893cb8ea39c65e0313a30e903c220dba2c8597df1d75ee21fd905eab1ebf2261ebf085b13115363d72adc9ccd9527293b7218c39e94c257c94a8c95c32cf909cf58e8b7ece89a9bd21107a413b3fe3172e0","data":{"slot":"8304","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x94fab4732e767881653a5923ca4a93fc2778d349cef972b077aa0fd2553946f578be6571d7a02fe14aa98b11a77475e115bc8062308b23a23c6ce71cd07c528a6e37d30324d57dcc36fa336575210bce5d71ccabf74f0dd96f839eefc1a49343","data":{"slot":"8296","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x97426dbbe61af8a68ac683ba95ad871baade096e9287e2d533c1efba04430b7083283485db5b1624fb03639065e8c754155cfe68986d526c1a771b67e45c0e8c97428dee8c6d80cc68892b961e8352d50f34e2623dc3b7ba2cb5dba28a854079","data":{"slot":"8302","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x94fab4732e767881653a5923ca4a93fc2778d349cef972b077aa0fd2553946f578be6571d7a02fe14aa98b11a77475e115bc8062308b23a23c6ce71cd07c528a6e37d30324d57dcc36fa336575210bce5d71ccabf74f0dd96f839eefc1a49343","data":{"slot":"8296","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x98416260b644654a4a90bda6032053f1eb3a12c59a3c7534f1ef348f2108c2837245bce74b3fd9f61ebae24860cc698100f864c4f26966c36431acbf0beea679807ba4eba9adfd1a267ef8d990290a2548af6456b1d0def6639ac47fd30c5542","data":{"slot":"8317","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x8b1fbaba2982cd546a7d19d4af3755163112349a0e6d13f05c69807c709f363359c2cfff8a4afa66bd24445eb12b923615c33892a82d8081575207e4165a1d0c944fd3871ff885662c3921b152e674130879d67a0692b4867ad9fc2d20e24fa3","data":{"slot":"8307","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x894270af1854ce4e65c6e09bc83c15171d564a2af871d0b442cacea78536e5cd34cf4a906025a6d87e12a172ceeb79990b86a1de7ed4ef40cffeca6b93402c3542682bb2914c34430e23038a57e8490abe809dc9f96f3b2caebed380113280b3","data":{"slot":"8297","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x98aade2cf9dad0e1528edec0e76be15577601b6cbef68353e51748b6286bf08812e42fe8791147a54eeed34782249e3f0cc463e22d6cb1c6050636ca8d070531fe40e16913f2e5560f6e683a6781268ff08d32bc5899b00306a87eecc5603928","data":{"slot":"8290","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x805e92ba1e4c88489f178202ca5d7ce96e7b874fe98bdee80ab6423441bd37ff3f0fe724bc088f58050ac2a8f81ec5e80401d76caeb65795b5794e7a20d0384f3bfd162b281a17e96cc98087c651d893b05154203af7a7591afe1056db934ec4","data":{"slot":"8309","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0xa44792a6341475c3eff0c11ad62bc19154d5ed48a4b81869ed49885499d5f768c81f357dd6a3ea60aa2f15a184b098f40a1382cfaea0a8438d62d9cca27c85023245b1838e2e4f1d4e65926f8c6a3032740b36c0a3c8aa69850648ac6c12b3ce","data":{"slot":"8306","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0xa44792a6341475c3eff0c11ad62bc19154d5ed48a4b81869ed49885499d5f768c81f357dd6a3ea60aa2f15a184b098f40a1382cfaea0a8438d62d9cca27c85023245b1838e2e4f1d4e65926f8c6a3032740b36c0a3c8aa69850648ac6c12b3ce","data":{"slot":"8306","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x980e36beab885b1f2d8460e7ece21054e9d235fea5429836bc6df687e0c2f41b7556d9c86cd9c1ca7a69e5a51991b8d617eea619ba8e312d568e38f8de8adb8b4a9ec3e9dab2d47df45b35d9f2488236c042d66cd0916fee70e8a3295353b0ed","data":{"slot":"8308","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527","data":{"slot":"8313","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0xb60160a4024734b6c22e6083d755d97b22d107001965d35cd1aa5fc3c1059b4cb482c36c78609c0fa131631eb847d165177c877949e5baebb96a48f6e471c1d1d700619b4adeafa728b4d69de8d03d02854e4240d8e16d790168619cc2027247","data":{"slot":"8318","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0xb731b2df4dcaf841d50747f85b332170471895508c3af7e8bada14e58a816fed435460e1694e87e2887f19a0de201c3d0bc1ece52c26c519fd9131b25fa8a69b229c14ffd1c935d9e853aca8ab07eaae98a65daec09b2640b91961685e96d58c","data":{"slot":"8292","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x8b63c286bff1c5dc6fb2e4878e73631e16db1cd3b07e9d0150b3ede4175635fe8db571cb486398e35923640606643d630bacc148d84e9c1060c32b55fe644e5c2573326b041767c5d45d45509a5403a7f2f1b2dd60e54bed26f407bb367a8642","data":{"slot":"8314","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x906fd8d1a45b719a36eb5e09b5e13f9d0fb7faaa194d84b90e0b2b811ce299f385bf18bb07844620ec032b6f267d04781480dc303081be7c5d8ba735bccd682dd3ddb6345bae13bd96068eb86b148e73b8931b642705b1696d9ada4159b1dd65","data":{"slot":"8305","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x9494651d4491cfc326f3439cebc3304aaf50a8e5598217da6df2a13b5cb9f9731cc8934f406c0243786b17f936d5892801fc34fc74fb4f52fec147536375dabd9f892940aacdea196e28cb21320bce9ede79b0a11333569d90e6deeb59869217","data":{"slot":"8300","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x98416260b644654a4a90bda6032053f1eb3a12c59a3c7534f1ef348f2108c2837245bce74b3fd9f61ebae24860cc698100f864c4f26966c36431acbf0beea679807ba4eba9adfd1a267ef8d990290a2548af6456b1d0def6639ac47fd30c5542","data":{"slot":"8317","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527","data":{"slot":"8313","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x980e36beab885b1f2d8460e7ece21054e9d235fea5429836bc6df687e0c2f41b7556d9c86cd9c1ca7a69e5a51991b8d617eea619ba8e312d568e38f8de8adb8b4a9ec3e9dab2d47df45b35d9f2488236c042d66cd0916fee70e8a3295353b0ed","data":{"slot":"8308","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527","data":{"slot":"8313","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x815ca84fb30789d731ebf977b6ecdd60c30818202d464acdc2947143f62342c4a5d01c6cdb32b1e223d032c746fa98d30899164e6ab37828e6d049f32e46a5c59d742d82005f9a629938761e3abce454cec104352665cd81bbcffa2fce22a935","data":{"slot":"8299","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527","data":{"slot":"8313","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x906fd8d1a45b719a36eb5e09b5e13f9d0fb7faaa194d84b90e0b2b811ce299f385bf18bb07844620ec032b6f267d04781480dc303081be7c5d8ba735bccd682dd3ddb6345bae13bd96068eb86b148e73b8931b642705b1696d9ada4159b1dd65","data":{"slot":"8305","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x906fd8d1a45b719a36eb5e09b5e13f9d0fb7faaa194d84b90e0b2b811ce299f385bf18bb07844620ec032b6f267d04781480dc303081be7c5d8ba735bccd682dd3ddb6345bae13bd96068eb86b148e73b8931b642705b1696d9ada4159b1dd65","data":{"slot":"8305","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x876c656d7889c15cd355d6652b347a25dc8fd7ffc383f0d14ad436b5f1af9ac09e06168ad71be76b85c3dd44ae79cc0f04f250a0bcc529d06a1032283e2b8b384d582c0ace50bf747264a199647697f159d06be75ecfb24da2a8b625a3087804","data":{"slot":"8293","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x876c656d7889c15cd355d6652b347a25dc8fd7ffc383f0d14ad436b5f1af9ac09e06168ad71be76b85c3dd44ae79cc0f04f250a0bcc529d06a1032283e2b8b384d582c0ace50bf747264a199647697f159d06be75ecfb24da2a8b625a3087804","data":{"slot":"8293","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x8bfaed4667e28ed9e39464c7c57027ae345f22847b6ac1aa7e5f342fdb6cdca9d78a962da68f9e34e0453f68fa363fcd196881e2dd76abcab6814439d73448f404124ad2e2f57b59b0df57699d913e24f79c53f129a09c05f2659e4444f4bb53","data":{"slot":"8320","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"258","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"260","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0xabdb4b0a06e2d036021b0cd847fb6e8f4d2deca86e60788a6ae2bb9bd55b62ebf35716290f958e075812e8dfcba2beef00b002459e5932d7e7478cf00e91300f9f53a84f593ce40afb1f3c07b1db789ba5da757d313a9ee4cac6b2e28ed2f929","data":{"slot":"8298","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0xabdb4b0a06e2d036021b0cd847fb6e8f4d2deca86e60788a6ae2bb9bd55b62ebf35716290f958e075812e8dfcba2beef00b002459e5932d7e7478cf00e91300f9f53a84f593ce40afb1f3c07b1db789ba5da757d313a9ee4cac6b2e28ed2f929","data":{"slot":"8298","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x912fe61ef99df1c96d7e5e6bd01ee5a6be73389978c7f4670c4e978beb6b8e4d640f238c6ba3426e935ac8f8527d118c06f464b08f6527ebebac793728ccc1190ee6701838c6f2b3b06391dc2d69232e63af11023ffe8e1c66eb3bd1075085a6","data":{"slot":"8310","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527","data":{"slot":"8313","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x815ca84fb30789d731ebf977b6ecdd60c30818202d464acdc2947143f62342c4a5d01c6cdb32b1e223d032c746fa98d30899164e6ab37828e6d049f32e46a5c59d742d82005f9a629938761e3abce454cec104352665cd81bbcffa2fce22a935","data":{"slot":"8299","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x8d852ffa1c5960ba3a5d09837fbdb859bbf9045001b3d1dc1c4d22c6b4bc5b6d506f6ef667b5c7c9fbfb1dd0cfe3617405f56750f8b5eb25b3539d0a4c94822b198c524de92a6c68982ce17f985ff5283cea6ac8dabe41828ce38edb7e9fe223","data":{"slot":"8311","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0xab42974cba2e3fa75faa4c1f717caf7c2a953f4964063462ed32629764336124fd2f2f430ddf0291325722206250452c109b14cded0e51171b89b106b6b2044291128c3d6966c804490033b9e5fd06450ea50d22b5ab761892c6c3f4de79e098","data":{"slot":"8291","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0xa44792a6341475c3eff0c11ad62bc19154d5ed48a4b81869ed49885499d5f768c81f357dd6a3ea60aa2f15a184b098f40a1382cfaea0a8438d62d9cca27c85023245b1838e2e4f1d4e65926f8c6a3032740b36c0a3c8aa69850648ac6c12b3ce","data":{"slot":"8306","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x912fe61ef99df1c96d7e5e6bd01ee5a6be73389978c7f4670c4e978beb6b8e4d640f238c6ba3426e935ac8f8527d118c06f464b08f6527ebebac793728ccc1190ee6701838c6f2b3b06391dc2d69232e63af11023ffe8e1c66eb3bd1075085a6","data":{"slot":"8310","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0xabdb4b0a06e2d036021b0cd847fb6e8f4d2deca86e60788a6ae2bb9bd55b62ebf35716290f958e075812e8dfcba2beef00b002459e5932d7e7478cf00e91300f9f53a84f593ce40afb1f3c07b1db789ba5da757d313a9ee4cac6b2e28ed2f929","data":{"slot":"8298","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0xab42974cba2e3fa75faa4c1f717caf7c2a953f4964063462ed32629764336124fd2f2f430ddf0291325722206250452c109b14cded0e51171b89b106b6b2044291128c3d6966c804490033b9e5fd06450ea50d22b5ab761892c6c3f4de79e098","data":{"slot":"8291","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x876c656d7889c15cd355d6652b347a25dc8fd7ffc383f0d14ad436b5f1af9ac09e06168ad71be76b85c3dd44ae79cc0f04f250a0bcc529d06a1032283e2b8b384d582c0ace50bf747264a199647697f159d06be75ecfb24da2a8b625a3087804","data":{"slot":"8293","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x805e92ba1e4c88489f178202ca5d7ce96e7b874fe98bdee80ab6423441bd37ff3f0fe724bc088f58050ac2a8f81ec5e80401d76caeb65795b5794e7a20d0384f3bfd162b281a17e96cc98087c651d893b05154203af7a7591afe1056db934ec4","data":{"slot":"8309","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x95bbaf8dcff64306f01e0b09b27ebe3c761def7edd75542e213586ee0c6d3fc313ae102760abd1262b4f8c00e57603fa01627390011e3a5dea555c74798d7a3e1da68e00e3cdb9d8e4af112b6ff83951bd926288d24eb82e3f203a3160a4d7a9","data":{"slot":"8312","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x815ca84fb30789d731ebf977b6ecdd60c30818202d464acdc2947143f62342c4a5d01c6cdb32b1e223d032c746fa98d30899164e6ab37828e6d049f32e46a5c59d742d82005f9a629938761e3abce454cec104352665cd81bbcffa2fce22a935","data":{"slot":"8299","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x87c3f6fac9ea937a8e8bd4f6dccb7893cb8ea39c65e0313a30e903c220dba2c8597df1d75ee21fd905eab1ebf2261ebf085b13115363d72adc9ccd9527293b7218c39e94c257c94a8c95c32cf909cf58e8b7ece89a9bd21107a413b3fe3172e0","data":{"slot":"8304","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x8b1fbaba2982cd546a7d19d4af3755163112349a0e6d13f05c69807c709f363359c2cfff8a4afa66bd24445eb12b923615c33892a82d8081575207e4165a1d0c944fd3871ff885662c3921b152e674130879d67a0692b4867ad9fc2d20e24fa3","data":{"slot":"8307","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0xa46775d208c119b097221ead6ee9afbf011258b03da07138d01fef8d5bd4681ecbab6f36687e8ae644191acebc94800a002b136de6ff892e4e0910d05402def66858ee8ad8f4b706fab163fe742959dcb86fa90d0b822e5937092852962acbb1","data":{"slot":"8294","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x97426dbbe61af8a68ac683ba95ad871baade096e9287e2d533c1efba04430b7083283485db5b1624fb03639065e8c754155cfe68986d526c1a771b67e45c0e8c97428dee8c6d80cc68892b961e8352d50f34e2623dc3b7ba2cb5dba28a854079","data":{"slot":"8302","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}}],"deposits":[{"proof":["0x1a02000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":{"pubkey":"0xa19c8e80ddc1caad60a172b66eb24e83ef200d77034b3e16bbee4d95e929a5c1a473563973338d22e7a566fdbd352f65","withdrawal_credentials":"0x00edbcfc97a6985ac86187522426240ed81b6493c880d0798360149ec8ce96d8","amount":"32000000000","signature":"0xb9b4b512b2c67a3e89edcbef91fc0ccd88c9a8c8654c51a130ffb2ab539c22a0c6b84928e8db4ca8a9d04f2dee312c3817a2bf360b6f5f2f3d1ba69b43cf4671290f7f58621887ad4dd1c9fe6d02cc59443e12447a20b38913f67597b0e3cc93"}},{"proof":["0x1a02000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":{"pubkey":"0xb1f92d1a612942fb266c1e436f8d417282efa2805d5a5a819e3d07e358a70efbf0cc1671412ee986cd342c3d2255a324","withdrawal_credentials":"0x004ac0f181a01d43a7de32602b440cfbe3a091bb8c108c1fa35726ed301743f9","amount":"32000000000","signature":"0x8dbd6f9b4ce0a5277f66da9ec41776cff88a647ae1b4dde221a3bf41b9d4af1e77d0cff23185796815448f2e8148126a046b4b60947a32a1e201b4e979c91b395c1d4804ead1324d699eaa9c481efa69484a7946a0bad9788e50cf05847a30c4"}},{"proof":["0x1a02000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":{"pubkey":"0xb532643cb8824a2fbd9196c10961f3ad2f0e319c3612bb15a51a3454593f44726383f006425c2e5952b156a6e14aceb0","withdrawal_credentials":"0x00f68c08152911b76f556f9d6dfc66d54e5abd63de04dc073d6b03f333ac00f3","amount":"32000000000","signature":"0x97852e8c02386bcc8a2dd51c70c48661c79bc1f89f9dce113a60fcde345abedf96fa186c4230013cf61f3546c5d9877a0eab7a5a4f4e4e0e4bcd917dc8368a88e3b8380de9e96ed36bfd605d55956af64a17b877f12762acfdd1c3effe4b4d42"}},{"proof":["0x1a02000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":{"pubkey":"0xa7a1c0bbad929dc02699e92597a66266bbd9533419693270c9b56bbdea643cd2ded9664da3c9fd8db2389277b5e585cc","withdrawal_credentials":"0x00e64188226da03f1f3d787ef65d86690aaa24d44e5ac92c99c413463ec47c26","amount":"32000000000","signature":"0xb0e97772997255840a5758e5325b9d1c56a292500838c5b2b697b7dd207c65a2ef928ebb9466d57782edf79f9b74bbbb069235c752f6527e8d8eb1c785d99326da78680056ee3084811b980185287259af64607e218d67a3b8f24d27c0659ce2"}},{"proof":["0x1a02000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":{"pubkey":"0x9919842dee455266e4dc77c74088bddbfdb535b9a1bbe75a3cced0e428598038365afe11c7578e4dbd8fe4cae7237543","withdrawal_credentials":"0x000a2baaef8f6cc730d6a5474879aed4fe8c95da787cc2e15c3cdba14a9cef12","amount":"32000000000","signature":"0x99ef1ab7cfbe40d0a1e136138a4a8094e8f54a59c8d05052749b7af14931274fad1c0a44577de51099f2700505fa8861023b7bddabb274249a091acb3a4f7543f877da3792dad7897351c7a01343116a65959812fd55cc4ce4197b05f698761f"}},{"proof":["0x1a02000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":{"pubkey":"0xb4ed73c02a816ba9d23ba0e023970772f82dd3a32a85eefd922958e33bcab7f9c85e20372e49107665926cca852b8b9a","withdrawal_credentials":"0x0017c0e8e177a6d58e4f8b93b2b66b13aef9c186cfccb9466d857a474b32b0d4","amount":"32000000000","signature":"0xa6dfce815f61ce81bf107bf5ccc1beae5f32b63a55e836a5983b63b90c0e7eac873387107c145ab59c32679091cfd28a0dbf2b73f75cd5ab01b75c6ba984b83c796c92b77adba152ab2a20132324fc4b20c8ec002663f16edec9308bb8f3d298"}},{"proof":["0x1a02000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":{"pubkey":"0xb0d0dfaf7479f59319beb513bee16e1af576a0740a7a124a9947ec7c3826dbc0a5d5db15519e8423d7aa683f638f3da3","withdrawal_credentials":"0x00a61d2fddabb70c2db059af7e298b0395ef882dda24ae144f2b7ac88026e55d","amount":"32000000000","signature":"0x85a06ab8d9d576cb2810a88635b7a462d1cfb238db066b8caeba7f36562bb903630f8f24d157747debad5428c4f42a9a0a08dfd53c687cd7c3e17ec539f353357bbd89b7111246c99cc7fab24b8cd33a88cddf845f7d27c8a33079aa097069e3"}},{"proof":["0x1a02000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":{"pubkey":"0xb69614adf68d58f7d67110d7ced171ab934cb973f19c60cbb83161468655c42fe19a80a8e903030650bfaa9613a1ab2d","withdrawal_credentials":"0x0037c021fdef99bcf9fb90c02440571ab2faa0238485ed72e427b69dc8dddc91","amount":"32000000000","signature":"0x957f48b82d761d3e7f2e34eeff5922358d87f9b31c51e5af37a54fedeab7cfc09c3068f6ef5c97e0323dabff706bc7520113d51841c6dc2eaa044c8526bdaebcf35476c0b08cccb69ab0bab07c8e7ca2d6573b0ae96c32ae3d18764ae7ea78e0"}},{"proof":["0x1a02000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":{"pubkey":"0xac897c8892a6f3effcd276e4f44f410644846a333db600ad12e1099020196b2f8104563c04d78fedf5afc5d87b91b1b5","withdrawal_credentials":"0x0075f9178dd8a199c55d5cebb9dccb00508e619d5b9abd2b7cd5ad3f671c5a9f","amount":"32000000000","signature":"0x95a886b35ead6f8fc09d33975108857abffc32d53db6546a7251d32ca6d1706e899155b3883b05e65a041e44c51db8480703f13cccc6575cd2d50d0506485b9669a096bb1a2d4879008c15b8c1cdcd2e1a5c4f12885311e24dd87dc32e1bce87"}},{"proof":["0x1a02000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":{"pubkey":"0x8794fd3f4e5e66e6e81735d5726943833b82d1efd7d877e495a8c36955b7dfb95b3f6cfcef865fd7969fa2e17e628ab9","withdrawal_credentials":"0x0087adf1a29896ae52be67356ee9a4a5035450764c278382f8940d554668c208","amount":"32000000000","signature":"0xb42aa548fd9068db7916757390f6d011ad890b9f27a75d4676dd9edcd9017f5d7e2cec215a04502fcff253aa821865fb0c30549e7b5d5e62cc8df0264dc3b55538f15cfd375f9cb022a94c2a39201d757a502701acd50554dc4da29173c945bd"}}],"voluntary_exits":[{"message":{"epoch":"260","validator_index":"504"},"signature":"0x8fedc3077271b41f631d6062cc1cc8c8f074e486e9e692f198c5f82b94d2bb3b0fbf71cbac043cee94b56a7a06adf06d07bb7ecf06d8f699add17972ceb54b25e6021c3a2a727afd3370e960afbf345a75fddd2d221ba85a5f7b07e5607eec1e"},{"message":{"epoch":"260","validator_index":"503"},"signature":"0xa44079752dfa36b925f0ff675dfd10b5b7cc0c178839356d0bda9c83b6df01f6bfdd904af92373002bfac40277941d2809c4152fc61007ae4f2c73e550ed02f425419efae0461d8829746c7a3d36dcae5bc37158ede7dd30ccc33930783b6194"},{"message":{"epoch":"260","validator_index":"502"},"signature":"0xb193b547c2d45341c9aedd0a22f4afc565d9aaa3a04889df2f8ad608bb31b44a0391c69383f0f4725cea291332c081ff0a48e850d246dd0be40880bf17316eb4b2eaf4b8b6ba6d59c93aea3af98988f05cb2ddf61d8637f943864ebfe7c9707c"},{"message":{"epoch":"260","validator_index":"501"},"signature":"0x88afe9a0215d2a67c451fcbdc358237c4d5dce6b46973ae527afb7f8fb1da800d6a3dd7f6387028a57737b354b7db88803bd6f2a59c7fb84229f42e6c6ea1b7510cb2a28026ff8f2eefb8fc7e2a83115197b7a1bd35fbf0afcc69e4b6e581911"},{"message":{"epoch":"260","validator_index":"500"},"signature":"0xa2f2399070bcfa3f50894d7170d1343ab5f52d6bdc155124e867bcde936aee4e0bb69f164dee5fa07d47abccb8844ec101126caf0402f1a757934f8e7b5904a60cedc283b5e9801f2a71f80cda16e910d72518d469a9a40cd94b8ad3cca10136"},{"message":{"epoch":"260","validator_index":"499"},"signature":"0x86abacd204c85cfc40d71853422001e44134b1900138fccb409928b7e663270476e3d7a7e0aaa103c693cad3629da1aa056cac30c8aab1a4eb50d81bb0711db3dba1d741562b103f67f495996b18fad779d3d9cc508763ab883a7cd6858bdc51"},{"message":{"epoch":"260","validator_index":"498"},"signature":"0xb86533e02779dd0f959dbf1b0fa195126ccc945fd0a7c5b7370aefc16f8f130d083c0c1c58a5c18e8119d7912dd532d91765dd26ad5ef3991238bc093bab79d511b1d8484482eec9b6b4a98f4a8928819ea58fc857ed80b59fe9cb7a33fe60a2"},{"message":{"epoch":"260","validator_index":"495"},"signature":"0x80a5c7c52a246dcaaf67caf6285ea518581835af668d1a64723b321b167464e238248c0017d5265be373c9079d7b529b10aedc37835683e5e1320c3ad6fa1f72d52046a49b061935e1631565912d2f2482434007957fe9903edecf4dad8e5bb8"},{"message":{"epoch":"260","validator_index":"494"},"signature":"0xb6a0e4cdc1815f03166218963ec9cc4c5d607a67d659d1227386e16f90d3e39c6cddf696e3534f3824ca5aff8c734bab153f3bab701247cdcea16db31c94846c1cd3781b1861485ad813d025bf0a486c592dd1f9afa1134e8288e4fef44d2f3c"},{"message":{"epoch":"260","validator_index":"492"},"signature":"0xad850276510c2e41d059df6a1cefab9f1b66463da47b0fc772b21ed90c13e1bd6f86def8b2ecb867f4f752612d9d25e30a151aa6ef630a1b6ddaa4420c240b37df0234ee332373fe132b0101a0486900c5733762beeacd95429dd34c34230d13"},{"message":{"epoch":"260","validator_index":"491"},"signature":"0x837669180ba01b65157087f49c7af19acb1439016eca9c699b7136da7e9bbc89d6bddc7a030388bbb7e149ebd521c4810f457846b9cf913f7ee6f01db4363d3ce92fc732e52359917d36c7e4a08158653f1a9a78a608c4b56ff3e155b2783974"}],"sync_aggregate":{"sync_committee_bits":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"execution_payload_header":{"parent_hash":"0x0000000000000000000000000000000000000000000000000000000000000000","fee_recipient":"0x0000000000000000000000000000000000000000","state_root":"0x0000000000000000000000000000000000000000000000000000000000000000","receipts_root":"0x0000000000000000000000000000000000000000000000000000000000000000","logs_bloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","prev_randao":"0x0000000000000000000000000000000000000000000000000000000000000000","block_number":"0","gas_limit":"0","gas_used":"0","time":"0","extra_data":null,"base_fee_per_gas":"0x0000000000000000000000000000000000000000000000000000000000000000","block_hash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactions_root":"0x0000000000000000000000000000000000000000000000000000000000000000","withdrawals_root":"0x0000000000000000000000000000000000000000000000000000000000000000"},"execution_changes":[],"blob_kzg_commitments":[]}}},"finalized":false,"version":0,"execution_optimistic":false}` + "\n" - for _, c := range cases { - t.Run(c.blockID, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - // Query the block in the handler with /eth/v2/beacon/blocks/{block_id} - resp, err := http.Get(server.URL + "/eth/v1/beacon/blinded_blocks/" + c.blockID) - require.NoError(t, err) - defer resp.Body.Close() - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - // unmarshal the json - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.Equal(t, expected, string(out)) - }) - } -} - -func TestGetBlock(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, _, handler, _, _, fcu := setupTestingHandler(t, clparams.Phase0Version) - - // Start by testing - rootBlock1, err := blocks[len(blocks)-1].Block.HashSSZ() - if err != nil { - t.Fatal(err) - } - - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - expected := `{"data":{"signature":"0x8b915f3b9d2d4c7ccaacf5d56c1152b1e91eafd1f59ba734d09e78996930b63ca550499997fe6d590343aaf5997f0d0c14c986571992ac9ed188de2b31ae4b7d70dfb68edae8b012f72f284dc8da44f4af5a2bdf3dfc9c0897ec4f7165daa07a","message":{"slot":"8322","proposer_index":"210","parent_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","state_root":"0x933d6650f2999f17012e781f5012981edb549e5935de1c981fce81cdd241d4e1","body":{"randao_reveal":"0xa182a6c7224c53cc43492b7ba87b54e8303094ebcb8c822da09c4224791b461e34d089ac857acf05cd695679c25cffa30404832791fe424fd104e2e96ebbf583dd5ec4dcbc891e7f4e0dea402071dbd294810417221fc41e4f90e4837c694e1a","eth1_data":{"deposit_root":"0x0000000000000000000000000000000000000000000000000000000000000000","deposit_count":"528","block_hash":"0x0000000000000000000000000000000000000000000000000000000000000000"},"graffiti":"0x0000000000000000000000000000000000000000000000000000000000000000","proposer_slashings":[{"signed_header_1":{"message":{"slot":"8321","proposer_index":"476","parent_root":"0x3333333333333333333333333333333333333333333333333333333333333333","state_root":"0x4444444444444444444444444444444444444444444444444444444444444444","body_root":"0x5555555555555555555555555555555555555555555555555555555555555555"},"signature":"0x939584df88598e56fe144105c6933b4727d7b772539e65c57289df64cedee771377e4d0e94f85c25d39a6072997d309c09da8c477267670aa42f26fb0836c72ec5867fa2f34dc0eb7e043ef5d6421282d1515b0f8c7ffd4bbbf56ee8d61ed063"},"signed_header_2":{"message":{"slot":"8321","proposer_index":"476","parent_root":"0x9999999999999999999999999999999999999999999999999999999999999999","state_root":"0x4444444444444444444444444444444444444444444444444444444444444444","body_root":"0x5555555555555555555555555555555555555555555555555555555555555555"},"signature":"0x8a184441d5d944ed3c18549dd9e4640eda879f9e737ac4211fdddfd30a65e1a2a32a8aa918ca65ad9b863a15e8cfefc412608ca78fd54ea1e5cbbd5697d125cc721aac1b01e8984a33f025c4707623669573244a632ec7f37808c01fab143f58"}},{"signed_header_1":{"message":{"slot":"8321","proposer_index":"406","parent_root":"0x3333333333333333333333333333333333333333333333333333333333333333","state_root":"0x4444444444444444444444444444444444444444444444444444444444444444","body_root":"0x5555555555555555555555555555555555555555555555555555555555555555"},"signature":"0xad97a43e9f28a90ff46b07a7bf65d520b89a78af47dbff1c10e4fc6bb36b4ee9c4f27f2a72c65311a03e7b48e06d86db1149147b14a8803d46f6a457092642dc89d3f2782bd48a373e3125af1a84f5b76d4ff7ddc85ac2650ca4c0f99e1af592"},"signed_header_2":{"message":{"slot":"8321","proposer_index":"406","parent_root":"0x9999999999999999999999999999999999999999999999999999999999999999","state_root":"0x4444444444444444444444444444444444444444444444444444444444444444","body_root":"0x5555555555555555555555555555555555555555555555555555555555555555"},"signature":"0x88d860d460526de062ee196400e24cb3055de2ff6abb31331d0bfeeebcdc77839d22ad6dfec39d81279f5527d1ffbd7e0a9d6eee7dce5a1cd6f79451537e9dfb6384f595e9d49673c58c181527a599dd4b38154e1322f1607f192ab0394f1411"}},{"signed_header_1":{"message":{"slot":"8321","proposer_index":"281","parent_root":"0x3333333333333333333333333333333333333333333333333333333333333333","state_root":"0x4444444444444444444444444444444444444444444444444444444444444444","body_root":"0x5555555555555555555555555555555555555555555555555555555555555555"},"signature":"0x8a2358ff11a30100a2492001827f54ff6c10dd6dcea66f6814dd1cccc4a49850bbbe36546e4f9b72410042a9d5882e8219a5a01708b8a95ca57984debe78f419a4ac921270a0f0c11c795a6c5ef1e6bfb96712751a4fee61059ca8fbe69639b6"},"signed_header_2":{"message":{"slot":"8321","proposer_index":"281","parent_root":"0x9999999999999999999999999999999999999999999999999999999999999999","state_root":"0x4444444444444444444444444444444444444444444444444444444444444444","body_root":"0x5555555555555555555555555555555555555555555555555555555555555555"},"signature":"0xb820e03b7bfd21c2d97a4f2bc9dd1fd5325894757f7129646c7a39a02b2c1c8ca33d509b4e83491e79db02ac0490aa3308ee23bfa1f65bf4130ab07e377a8cbd4eace5b69801528322dde425b0a78310504c330da30be7cefc674573dbdb4502"}},{"signed_header_1":{"message":{"slot":"8321","proposer_index":"169","parent_root":"0x3333333333333333333333333333333333333333333333333333333333333333","state_root":"0x4444444444444444444444444444444444444444444444444444444444444444","body_root":"0x5555555555555555555555555555555555555555555555555555555555555555"},"signature":"0x88c81a6029f097a9f23e37c7677abfafa2921982e9aebffc35ca700e1aefcd49c2ab5d51c7b28ef3db3aad49d58a6407082ce1ecd7f7bd89cb764242890440b684fc0e1511e047434b25f3ad1a5e238e5bf97f51e9e37d6eed48e0b9fef64333"},"signed_header_2":{"message":{"slot":"8321","proposer_index":"169","parent_root":"0x9999999999999999999999999999999999999999999999999999999999999999","state_root":"0x4444444444444444444444444444444444444444444444444444444444444444","body_root":"0x5555555555555555555555555555555555555555555555555555555555555555"},"signature":"0x815b492a6a3fb606f01dbc595c8b18b51b7f7a5a86b11f3ae57c48f7506a34606556a3cf2be683ce23cd0c7b2235667613f9dbcf98408b176f134645f122684bd8fe704c7a4eccb7bb7cbe33c6de377be4d742291d35d0ec8d6083c1b17b7261"}},{"signed_header_1":{"message":{"slot":"8321","proposer_index":"397","parent_root":"0x3333333333333333333333333333333333333333333333333333333333333333","state_root":"0x4444444444444444444444444444444444444444444444444444444444444444","body_root":"0x5555555555555555555555555555555555555555555555555555555555555555"},"signature":"0xae352ba8550d04c07591224449bd4967f66f9d639b731795f643b1e3fc5ad28317268dc9e289ce6075e8981a0e37d9440885e4f4292cb4b4656bd0c7bd9fc22d21eb4c7d1b46f1b08cdb1eb08d7a405985e8a406e6d93c5c3fdd20e91baba122"},"signed_header_2":{"message":{"slot":"8321","proposer_index":"397","parent_root":"0x9999999999999999999999999999999999999999999999999999999999999999","state_root":"0x4444444444444444444444444444444444444444444444444444444444444444","body_root":"0x5555555555555555555555555555555555555555555555555555555555555555"},"signature":"0xb9152f5510f2bfa5ab7b61829823f25f0c879ab9b852fcd90c17f751bed6e687dc523fcda177503509cd1befec36046a056a66f5826e2333b6de67430a16f6194416681ae69a1c3498cf8351abae4fac5d8f0b51b1734633d545d540bf269270"}}],"attester_slashings":[{"attestation_1":{"attesting_indicies":["96","353","445"],"data":{"slot":"555","index":"0","beacon_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"17","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}},"signature":"0xa7e932307a82913b23743198182a7e3c97675e8a1133e8d946bc59c62b1765046214ca0ea0e13b77e4f8acc8f226498103684f382826a9fff6c6c2ffdf9c65ffeb1680155025f489f676457634581ee4363bdfbe4d46fc4d1d9df93c3df8750d"},"attestation_2":{"attesting_indicies":["96","353","445"],"data":{"slot":"555","index":"0","beacon_block_root":"0x0000000000000000000000000000000000000000000000000000000000000000","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"17","root":"0x0101010101010101010101010101010101010101010101010101010101010101"}},"signature":"0x89aadbd74370dc6d86b6b61c544c1e18949b0d8aa2d706605d1014d0266a043588a829243d343d1c3812621944ea34540aef1fbd34fe51b03a5734ebc5ec31057d1df0004faeca71d8687dd3af806e4332e19f6da5ab1d7da67fe017c2f2e68b"}}],"attestations":[{"aggregation_bits":"0xff3f","signature":"0x8b63c286bff1c5dc6fb2e4878e73631e16db1cd3b07e9d0150b3ede4175635fe8db571cb486398e35923640606643d630bacc148d84e9c1060c32b55fe644e5c2573326b041767c5d45d45509a5403a7f2f1b2dd60e54bed26f407bb367a8642","data":{"slot":"8314","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0xb731b2df4dcaf841d50747f85b332170471895508c3af7e8bada14e58a816fed435460e1694e87e2887f19a0de201c3d0bc1ece52c26c519fd9131b25fa8a69b229c14ffd1c935d9e853aca8ab07eaae98a65daec09b2640b91961685e96d58c","data":{"slot":"8292","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x876c656d7889c15cd355d6652b347a25dc8fd7ffc383f0d14ad436b5f1af9ac09e06168ad71be76b85c3dd44ae79cc0f04f250a0bcc529d06a1032283e2b8b384d582c0ace50bf747264a199647697f159d06be75ecfb24da2a8b625a3087804","data":{"slot":"8293","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x876c656d7889c15cd355d6652b347a25dc8fd7ffc383f0d14ad436b5f1af9ac09e06168ad71be76b85c3dd44ae79cc0f04f250a0bcc529d06a1032283e2b8b384d582c0ace50bf747264a199647697f159d06be75ecfb24da2a8b625a3087804","data":{"slot":"8293","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x98416260b644654a4a90bda6032053f1eb3a12c59a3c7534f1ef348f2108c2837245bce74b3fd9f61ebae24860cc698100f864c4f26966c36431acbf0beea679807ba4eba9adfd1a267ef8d990290a2548af6456b1d0def6639ac47fd30c5542","data":{"slot":"8317","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x805e92ba1e4c88489f178202ca5d7ce96e7b874fe98bdee80ab6423441bd37ff3f0fe724bc088f58050ac2a8f81ec5e80401d76caeb65795b5794e7a20d0384f3bfd162b281a17e96cc98087c651d893b05154203af7a7591afe1056db934ec4","data":{"slot":"8309","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527","data":{"slot":"8313","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x95bbaf8dcff64306f01e0b09b27ebe3c761def7edd75542e213586ee0c6d3fc313ae102760abd1262b4f8c00e57603fa01627390011e3a5dea555c74798d7a3e1da68e00e3cdb9d8e4af112b6ff83951bd926288d24eb82e3f203a3160a4d7a9","data":{"slot":"8312","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x894270af1854ce4e65c6e09bc83c15171d564a2af871d0b442cacea78536e5cd34cf4a906025a6d87e12a172ceeb79990b86a1de7ed4ef40cffeca6b93402c3542682bb2914c34430e23038a57e8490abe809dc9f96f3b2caebed380113280b3","data":{"slot":"8297","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0xa44792a6341475c3eff0c11ad62bc19154d5ed48a4b81869ed49885499d5f768c81f357dd6a3ea60aa2f15a184b098f40a1382cfaea0a8438d62d9cca27c85023245b1838e2e4f1d4e65926f8c6a3032740b36c0a3c8aa69850648ac6c12b3ce","data":{"slot":"8306","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x98aade2cf9dad0e1528edec0e76be15577601b6cbef68353e51748b6286bf08812e42fe8791147a54eeed34782249e3f0cc463e22d6cb1c6050636ca8d070531fe40e16913f2e5560f6e683a6781268ff08d32bc5899b00306a87eecc5603928","data":{"slot":"8290","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0xab42974cba2e3fa75faa4c1f717caf7c2a953f4964063462ed32629764336124fd2f2f430ddf0291325722206250452c109b14cded0e51171b89b106b6b2044291128c3d6966c804490033b9e5fd06450ea50d22b5ab761892c6c3f4de79e098","data":{"slot":"8291","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x8d852ffa1c5960ba3a5d09837fbdb859bbf9045001b3d1dc1c4d22c6b4bc5b6d506f6ef667b5c7c9fbfb1dd0cfe3617405f56750f8b5eb25b3539d0a4c94822b198c524de92a6c68982ce17f985ff5283cea6ac8dabe41828ce38edb7e9fe223","data":{"slot":"8311","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x8bfaed4667e28ed9e39464c7c57027ae345f22847b6ac1aa7e5f342fdb6cdca9d78a962da68f9e34e0453f68fa363fcd196881e2dd76abcab6814439d73448f404124ad2e2f57b59b0df57699d913e24f79c53f129a09c05f2659e4444f4bb53","data":{"slot":"8320","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"258","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"260","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x97426dbbe61af8a68ac683ba95ad871baade096e9287e2d533c1efba04430b7083283485db5b1624fb03639065e8c754155cfe68986d526c1a771b67e45c0e8c97428dee8c6d80cc68892b961e8352d50f34e2623dc3b7ba2cb5dba28a854079","data":{"slot":"8302","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x94fab4732e767881653a5923ca4a93fc2778d349cef972b077aa0fd2553946f578be6571d7a02fe14aa98b11a77475e115bc8062308b23a23c6ce71cd07c528a6e37d30324d57dcc36fa336575210bce5d71ccabf74f0dd96f839eefc1a49343","data":{"slot":"8296","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x8b63c286bff1c5dc6fb2e4878e73631e16db1cd3b07e9d0150b3ede4175635fe8db571cb486398e35923640606643d630bacc148d84e9c1060c32b55fe644e5c2573326b041767c5d45d45509a5403a7f2f1b2dd60e54bed26f407bb367a8642","data":{"slot":"8314","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x805e92ba1e4c88489f178202ca5d7ce96e7b874fe98bdee80ab6423441bd37ff3f0fe724bc088f58050ac2a8f81ec5e80401d76caeb65795b5794e7a20d0384f3bfd162b281a17e96cc98087c651d893b05154203af7a7591afe1056db934ec4","data":{"slot":"8309","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527","data":{"slot":"8313","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0xb60160a4024734b6c22e6083d755d97b22d107001965d35cd1aa5fc3c1059b4cb482c36c78609c0fa131631eb847d165177c877949e5baebb96a48f6e471c1d1d700619b4adeafa728b4d69de8d03d02854e4240d8e16d790168619cc2027247","data":{"slot":"8318","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527","data":{"slot":"8313","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x8b1fbaba2982cd546a7d19d4af3755163112349a0e6d13f05c69807c709f363359c2cfff8a4afa66bd24445eb12b923615c33892a82d8081575207e4165a1d0c944fd3871ff885662c3921b152e674130879d67a0692b4867ad9fc2d20e24fa3","data":{"slot":"8307","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0xa44792a6341475c3eff0c11ad62bc19154d5ed48a4b81869ed49885499d5f768c81f357dd6a3ea60aa2f15a184b098f40a1382cfaea0a8438d62d9cca27c85023245b1838e2e4f1d4e65926f8c6a3032740b36c0a3c8aa69850648ac6c12b3ce","data":{"slot":"8306","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x8b1fbaba2982cd546a7d19d4af3755163112349a0e6d13f05c69807c709f363359c2cfff8a4afa66bd24445eb12b923615c33892a82d8081575207e4165a1d0c944fd3871ff885662c3921b152e674130879d67a0692b4867ad9fc2d20e24fa3","data":{"slot":"8307","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0xab42974cba2e3fa75faa4c1f717caf7c2a953f4964063462ed32629764336124fd2f2f430ddf0291325722206250452c109b14cded0e51171b89b106b6b2044291128c3d6966c804490033b9e5fd06450ea50d22b5ab761892c6c3f4de79e098","data":{"slot":"8291","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x9494651d4491cfc326f3439cebc3304aaf50a8e5598217da6df2a13b5cb9f9731cc8934f406c0243786b17f936d5892801fc34fc74fb4f52fec147536375dabd9f892940aacdea196e28cb21320bce9ede79b0a11333569d90e6deeb59869217","data":{"slot":"8300","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x87c3f6fac9ea937a8e8bd4f6dccb7893cb8ea39c65e0313a30e903c220dba2c8597df1d75ee21fd905eab1ebf2261ebf085b13115363d72adc9ccd9527293b7218c39e94c257c94a8c95c32cf909cf58e8b7ece89a9bd21107a413b3fe3172e0","data":{"slot":"8304","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x94fab4732e767881653a5923ca4a93fc2778d349cef972b077aa0fd2553946f578be6571d7a02fe14aa98b11a77475e115bc8062308b23a23c6ce71cd07c528a6e37d30324d57dcc36fa336575210bce5d71ccabf74f0dd96f839eefc1a49343","data":{"slot":"8296","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x97426dbbe61af8a68ac683ba95ad871baade096e9287e2d533c1efba04430b7083283485db5b1624fb03639065e8c754155cfe68986d526c1a771b67e45c0e8c97428dee8c6d80cc68892b961e8352d50f34e2623dc3b7ba2cb5dba28a854079","data":{"slot":"8302","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x94fab4732e767881653a5923ca4a93fc2778d349cef972b077aa0fd2553946f578be6571d7a02fe14aa98b11a77475e115bc8062308b23a23c6ce71cd07c528a6e37d30324d57dcc36fa336575210bce5d71ccabf74f0dd96f839eefc1a49343","data":{"slot":"8296","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x98416260b644654a4a90bda6032053f1eb3a12c59a3c7534f1ef348f2108c2837245bce74b3fd9f61ebae24860cc698100f864c4f26966c36431acbf0beea679807ba4eba9adfd1a267ef8d990290a2548af6456b1d0def6639ac47fd30c5542","data":{"slot":"8317","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x8b1fbaba2982cd546a7d19d4af3755163112349a0e6d13f05c69807c709f363359c2cfff8a4afa66bd24445eb12b923615c33892a82d8081575207e4165a1d0c944fd3871ff885662c3921b152e674130879d67a0692b4867ad9fc2d20e24fa3","data":{"slot":"8307","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x894270af1854ce4e65c6e09bc83c15171d564a2af871d0b442cacea78536e5cd34cf4a906025a6d87e12a172ceeb79990b86a1de7ed4ef40cffeca6b93402c3542682bb2914c34430e23038a57e8490abe809dc9f96f3b2caebed380113280b3","data":{"slot":"8297","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x98aade2cf9dad0e1528edec0e76be15577601b6cbef68353e51748b6286bf08812e42fe8791147a54eeed34782249e3f0cc463e22d6cb1c6050636ca8d070531fe40e16913f2e5560f6e683a6781268ff08d32bc5899b00306a87eecc5603928","data":{"slot":"8290","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x805e92ba1e4c88489f178202ca5d7ce96e7b874fe98bdee80ab6423441bd37ff3f0fe724bc088f58050ac2a8f81ec5e80401d76caeb65795b5794e7a20d0384f3bfd162b281a17e96cc98087c651d893b05154203af7a7591afe1056db934ec4","data":{"slot":"8309","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0xa44792a6341475c3eff0c11ad62bc19154d5ed48a4b81869ed49885499d5f768c81f357dd6a3ea60aa2f15a184b098f40a1382cfaea0a8438d62d9cca27c85023245b1838e2e4f1d4e65926f8c6a3032740b36c0a3c8aa69850648ac6c12b3ce","data":{"slot":"8306","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0xa44792a6341475c3eff0c11ad62bc19154d5ed48a4b81869ed49885499d5f768c81f357dd6a3ea60aa2f15a184b098f40a1382cfaea0a8438d62d9cca27c85023245b1838e2e4f1d4e65926f8c6a3032740b36c0a3c8aa69850648ac6c12b3ce","data":{"slot":"8306","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x980e36beab885b1f2d8460e7ece21054e9d235fea5429836bc6df687e0c2f41b7556d9c86cd9c1ca7a69e5a51991b8d617eea619ba8e312d568e38f8de8adb8b4a9ec3e9dab2d47df45b35d9f2488236c042d66cd0916fee70e8a3295353b0ed","data":{"slot":"8308","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527","data":{"slot":"8313","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0xb60160a4024734b6c22e6083d755d97b22d107001965d35cd1aa5fc3c1059b4cb482c36c78609c0fa131631eb847d165177c877949e5baebb96a48f6e471c1d1d700619b4adeafa728b4d69de8d03d02854e4240d8e16d790168619cc2027247","data":{"slot":"8318","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0xb731b2df4dcaf841d50747f85b332170471895508c3af7e8bada14e58a816fed435460e1694e87e2887f19a0de201c3d0bc1ece52c26c519fd9131b25fa8a69b229c14ffd1c935d9e853aca8ab07eaae98a65daec09b2640b91961685e96d58c","data":{"slot":"8292","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x8b63c286bff1c5dc6fb2e4878e73631e16db1cd3b07e9d0150b3ede4175635fe8db571cb486398e35923640606643d630bacc148d84e9c1060c32b55fe644e5c2573326b041767c5d45d45509a5403a7f2f1b2dd60e54bed26f407bb367a8642","data":{"slot":"8314","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x906fd8d1a45b719a36eb5e09b5e13f9d0fb7faaa194d84b90e0b2b811ce299f385bf18bb07844620ec032b6f267d04781480dc303081be7c5d8ba735bccd682dd3ddb6345bae13bd96068eb86b148e73b8931b642705b1696d9ada4159b1dd65","data":{"slot":"8305","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x9494651d4491cfc326f3439cebc3304aaf50a8e5598217da6df2a13b5cb9f9731cc8934f406c0243786b17f936d5892801fc34fc74fb4f52fec147536375dabd9f892940aacdea196e28cb21320bce9ede79b0a11333569d90e6deeb59869217","data":{"slot":"8300","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x98416260b644654a4a90bda6032053f1eb3a12c59a3c7534f1ef348f2108c2837245bce74b3fd9f61ebae24860cc698100f864c4f26966c36431acbf0beea679807ba4eba9adfd1a267ef8d990290a2548af6456b1d0def6639ac47fd30c5542","data":{"slot":"8317","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527","data":{"slot":"8313","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x980e36beab885b1f2d8460e7ece21054e9d235fea5429836bc6df687e0c2f41b7556d9c86cd9c1ca7a69e5a51991b8d617eea619ba8e312d568e38f8de8adb8b4a9ec3e9dab2d47df45b35d9f2488236c042d66cd0916fee70e8a3295353b0ed","data":{"slot":"8308","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527","data":{"slot":"8313","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x815ca84fb30789d731ebf977b6ecdd60c30818202d464acdc2947143f62342c4a5d01c6cdb32b1e223d032c746fa98d30899164e6ab37828e6d049f32e46a5c59d742d82005f9a629938761e3abce454cec104352665cd81bbcffa2fce22a935","data":{"slot":"8299","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527","data":{"slot":"8313","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x906fd8d1a45b719a36eb5e09b5e13f9d0fb7faaa194d84b90e0b2b811ce299f385bf18bb07844620ec032b6f267d04781480dc303081be7c5d8ba735bccd682dd3ddb6345bae13bd96068eb86b148e73b8931b642705b1696d9ada4159b1dd65","data":{"slot":"8305","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x906fd8d1a45b719a36eb5e09b5e13f9d0fb7faaa194d84b90e0b2b811ce299f385bf18bb07844620ec032b6f267d04781480dc303081be7c5d8ba735bccd682dd3ddb6345bae13bd96068eb86b148e73b8931b642705b1696d9ada4159b1dd65","data":{"slot":"8305","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x876c656d7889c15cd355d6652b347a25dc8fd7ffc383f0d14ad436b5f1af9ac09e06168ad71be76b85c3dd44ae79cc0f04f250a0bcc529d06a1032283e2b8b384d582c0ace50bf747264a199647697f159d06be75ecfb24da2a8b625a3087804","data":{"slot":"8293","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x876c656d7889c15cd355d6652b347a25dc8fd7ffc383f0d14ad436b5f1af9ac09e06168ad71be76b85c3dd44ae79cc0f04f250a0bcc529d06a1032283e2b8b384d582c0ace50bf747264a199647697f159d06be75ecfb24da2a8b625a3087804","data":{"slot":"8293","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x8bfaed4667e28ed9e39464c7c57027ae345f22847b6ac1aa7e5f342fdb6cdca9d78a962da68f9e34e0453f68fa363fcd196881e2dd76abcab6814439d73448f404124ad2e2f57b59b0df57699d913e24f79c53f129a09c05f2659e4444f4bb53","data":{"slot":"8320","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"258","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"260","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0xabdb4b0a06e2d036021b0cd847fb6e8f4d2deca86e60788a6ae2bb9bd55b62ebf35716290f958e075812e8dfcba2beef00b002459e5932d7e7478cf00e91300f9f53a84f593ce40afb1f3c07b1db789ba5da757d313a9ee4cac6b2e28ed2f929","data":{"slot":"8298","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0xabdb4b0a06e2d036021b0cd847fb6e8f4d2deca86e60788a6ae2bb9bd55b62ebf35716290f958e075812e8dfcba2beef00b002459e5932d7e7478cf00e91300f9f53a84f593ce40afb1f3c07b1db789ba5da757d313a9ee4cac6b2e28ed2f929","data":{"slot":"8298","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x912fe61ef99df1c96d7e5e6bd01ee5a6be73389978c7f4670c4e978beb6b8e4d640f238c6ba3426e935ac8f8527d118c06f464b08f6527ebebac793728ccc1190ee6701838c6f2b3b06391dc2d69232e63af11023ffe8e1c66eb3bd1075085a6","data":{"slot":"8310","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527","data":{"slot":"8313","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x815ca84fb30789d731ebf977b6ecdd60c30818202d464acdc2947143f62342c4a5d01c6cdb32b1e223d032c746fa98d30899164e6ab37828e6d049f32e46a5c59d742d82005f9a629938761e3abce454cec104352665cd81bbcffa2fce22a935","data":{"slot":"8299","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x8d852ffa1c5960ba3a5d09837fbdb859bbf9045001b3d1dc1c4d22c6b4bc5b6d506f6ef667b5c7c9fbfb1dd0cfe3617405f56750f8b5eb25b3539d0a4c94822b198c524de92a6c68982ce17f985ff5283cea6ac8dabe41828ce38edb7e9fe223","data":{"slot":"8311","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0xab42974cba2e3fa75faa4c1f717caf7c2a953f4964063462ed32629764336124fd2f2f430ddf0291325722206250452c109b14cded0e51171b89b106b6b2044291128c3d6966c804490033b9e5fd06450ea50d22b5ab761892c6c3f4de79e098","data":{"slot":"8291","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0xa44792a6341475c3eff0c11ad62bc19154d5ed48a4b81869ed49885499d5f768c81f357dd6a3ea60aa2f15a184b098f40a1382cfaea0a8438d62d9cca27c85023245b1838e2e4f1d4e65926f8c6a3032740b36c0a3c8aa69850648ac6c12b3ce","data":{"slot":"8306","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x912fe61ef99df1c96d7e5e6bd01ee5a6be73389978c7f4670c4e978beb6b8e4d640f238c6ba3426e935ac8f8527d118c06f464b08f6527ebebac793728ccc1190ee6701838c6f2b3b06391dc2d69232e63af11023ffe8e1c66eb3bd1075085a6","data":{"slot":"8310","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0xabdb4b0a06e2d036021b0cd847fb6e8f4d2deca86e60788a6ae2bb9bd55b62ebf35716290f958e075812e8dfcba2beef00b002459e5932d7e7478cf00e91300f9f53a84f593ce40afb1f3c07b1db789ba5da757d313a9ee4cac6b2e28ed2f929","data":{"slot":"8298","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0xab42974cba2e3fa75faa4c1f717caf7c2a953f4964063462ed32629764336124fd2f2f430ddf0291325722206250452c109b14cded0e51171b89b106b6b2044291128c3d6966c804490033b9e5fd06450ea50d22b5ab761892c6c3f4de79e098","data":{"slot":"8291","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x876c656d7889c15cd355d6652b347a25dc8fd7ffc383f0d14ad436b5f1af9ac09e06168ad71be76b85c3dd44ae79cc0f04f250a0bcc529d06a1032283e2b8b384d582c0ace50bf747264a199647697f159d06be75ecfb24da2a8b625a3087804","data":{"slot":"8293","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x805e92ba1e4c88489f178202ca5d7ce96e7b874fe98bdee80ab6423441bd37ff3f0fe724bc088f58050ac2a8f81ec5e80401d76caeb65795b5794e7a20d0384f3bfd162b281a17e96cc98087c651d893b05154203af7a7591afe1056db934ec4","data":{"slot":"8309","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x95bbaf8dcff64306f01e0b09b27ebe3c761def7edd75542e213586ee0c6d3fc313ae102760abd1262b4f8c00e57603fa01627390011e3a5dea555c74798d7a3e1da68e00e3cdb9d8e4af112b6ff83951bd926288d24eb82e3f203a3160a4d7a9","data":{"slot":"8312","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0x815ca84fb30789d731ebf977b6ecdd60c30818202d464acdc2947143f62342c4a5d01c6cdb32b1e223d032c746fa98d30899164e6ab37828e6d049f32e46a5c59d742d82005f9a629938761e3abce454cec104352665cd81bbcffa2fce22a935","data":{"slot":"8299","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x87c3f6fac9ea937a8e8bd4f6dccb7893cb8ea39c65e0313a30e903c220dba2c8597df1d75ee21fd905eab1ebf2261ebf085b13115363d72adc9ccd9527293b7218c39e94c257c94a8c95c32cf909cf58e8b7ece89a9bd21107a413b3fe3172e0","data":{"slot":"8304","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x8b1fbaba2982cd546a7d19d4af3755163112349a0e6d13f05c69807c709f363359c2cfff8a4afa66bd24445eb12b923615c33892a82d8081575207e4165a1d0c944fd3871ff885662c3921b152e674130879d67a0692b4867ad9fc2d20e24fa3","data":{"slot":"8307","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff7f","signature":"0xa46775d208c119b097221ead6ee9afbf011258b03da07138d01fef8d5bd4681ecbab6f36687e8ae644191acebc94800a002b136de6ff892e4e0910d05402def66858ee8ad8f4b706fab163fe742959dcb86fa90d0b822e5937092852962acbb1","data":{"slot":"8294","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}},{"aggregation_bits":"0xff3f","signature":"0x97426dbbe61af8a68ac683ba95ad871baade096e9287e2d533c1efba04430b7083283485db5b1624fb03639065e8c754155cfe68986d526c1a771b67e45c0e8c97428dee8c6d80cc68892b961e8352d50f34e2623dc3b7ba2cb5dba28a854079","data":{"slot":"8302","index":"0","beacon_block_root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed","source":{"epoch":"257","root":"0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e"},"target":{"epoch":"259","root":"0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed"}}}],"deposits":[{"proof":["0x1a02000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":{"pubkey":"0xa19c8e80ddc1caad60a172b66eb24e83ef200d77034b3e16bbee4d95e929a5c1a473563973338d22e7a566fdbd352f65","withdrawal_credentials":"0x00edbcfc97a6985ac86187522426240ed81b6493c880d0798360149ec8ce96d8","amount":"32000000000","signature":"0xb9b4b512b2c67a3e89edcbef91fc0ccd88c9a8c8654c51a130ffb2ab539c22a0c6b84928e8db4ca8a9d04f2dee312c3817a2bf360b6f5f2f3d1ba69b43cf4671290f7f58621887ad4dd1c9fe6d02cc59443e12447a20b38913f67597b0e3cc93"}},{"proof":["0x1a02000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":{"pubkey":"0xb1f92d1a612942fb266c1e436f8d417282efa2805d5a5a819e3d07e358a70efbf0cc1671412ee986cd342c3d2255a324","withdrawal_credentials":"0x004ac0f181a01d43a7de32602b440cfbe3a091bb8c108c1fa35726ed301743f9","amount":"32000000000","signature":"0x8dbd6f9b4ce0a5277f66da9ec41776cff88a647ae1b4dde221a3bf41b9d4af1e77d0cff23185796815448f2e8148126a046b4b60947a32a1e201b4e979c91b395c1d4804ead1324d699eaa9c481efa69484a7946a0bad9788e50cf05847a30c4"}},{"proof":["0x1a02000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":{"pubkey":"0xb532643cb8824a2fbd9196c10961f3ad2f0e319c3612bb15a51a3454593f44726383f006425c2e5952b156a6e14aceb0","withdrawal_credentials":"0x00f68c08152911b76f556f9d6dfc66d54e5abd63de04dc073d6b03f333ac00f3","amount":"32000000000","signature":"0x97852e8c02386bcc8a2dd51c70c48661c79bc1f89f9dce113a60fcde345abedf96fa186c4230013cf61f3546c5d9877a0eab7a5a4f4e4e0e4bcd917dc8368a88e3b8380de9e96ed36bfd605d55956af64a17b877f12762acfdd1c3effe4b4d42"}},{"proof":["0x1a02000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":{"pubkey":"0xa7a1c0bbad929dc02699e92597a66266bbd9533419693270c9b56bbdea643cd2ded9664da3c9fd8db2389277b5e585cc","withdrawal_credentials":"0x00e64188226da03f1f3d787ef65d86690aaa24d44e5ac92c99c413463ec47c26","amount":"32000000000","signature":"0xb0e97772997255840a5758e5325b9d1c56a292500838c5b2b697b7dd207c65a2ef928ebb9466d57782edf79f9b74bbbb069235c752f6527e8d8eb1c785d99326da78680056ee3084811b980185287259af64607e218d67a3b8f24d27c0659ce2"}},{"proof":["0x1a02000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":{"pubkey":"0x9919842dee455266e4dc77c74088bddbfdb535b9a1bbe75a3cced0e428598038365afe11c7578e4dbd8fe4cae7237543","withdrawal_credentials":"0x000a2baaef8f6cc730d6a5474879aed4fe8c95da787cc2e15c3cdba14a9cef12","amount":"32000000000","signature":"0x99ef1ab7cfbe40d0a1e136138a4a8094e8f54a59c8d05052749b7af14931274fad1c0a44577de51099f2700505fa8861023b7bddabb274249a091acb3a4f7543f877da3792dad7897351c7a01343116a65959812fd55cc4ce4197b05f698761f"}},{"proof":["0x1a02000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":{"pubkey":"0xb4ed73c02a816ba9d23ba0e023970772f82dd3a32a85eefd922958e33bcab7f9c85e20372e49107665926cca852b8b9a","withdrawal_credentials":"0x0017c0e8e177a6d58e4f8b93b2b66b13aef9c186cfccb9466d857a474b32b0d4","amount":"32000000000","signature":"0xa6dfce815f61ce81bf107bf5ccc1beae5f32b63a55e836a5983b63b90c0e7eac873387107c145ab59c32679091cfd28a0dbf2b73f75cd5ab01b75c6ba984b83c796c92b77adba152ab2a20132324fc4b20c8ec002663f16edec9308bb8f3d298"}},{"proof":["0x1a02000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":{"pubkey":"0xb0d0dfaf7479f59319beb513bee16e1af576a0740a7a124a9947ec7c3826dbc0a5d5db15519e8423d7aa683f638f3da3","withdrawal_credentials":"0x00a61d2fddabb70c2db059af7e298b0395ef882dda24ae144f2b7ac88026e55d","amount":"32000000000","signature":"0x85a06ab8d9d576cb2810a88635b7a462d1cfb238db066b8caeba7f36562bb903630f8f24d157747debad5428c4f42a9a0a08dfd53c687cd7c3e17ec539f353357bbd89b7111246c99cc7fab24b8cd33a88cddf845f7d27c8a33079aa097069e3"}},{"proof":["0x1a02000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":{"pubkey":"0xb69614adf68d58f7d67110d7ced171ab934cb973f19c60cbb83161468655c42fe19a80a8e903030650bfaa9613a1ab2d","withdrawal_credentials":"0x0037c021fdef99bcf9fb90c02440571ab2faa0238485ed72e427b69dc8dddc91","amount":"32000000000","signature":"0x957f48b82d761d3e7f2e34eeff5922358d87f9b31c51e5af37a54fedeab7cfc09c3068f6ef5c97e0323dabff706bc7520113d51841c6dc2eaa044c8526bdaebcf35476c0b08cccb69ab0bab07c8e7ca2d6573b0ae96c32ae3d18764ae7ea78e0"}},{"proof":["0x1a02000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":{"pubkey":"0xac897c8892a6f3effcd276e4f44f410644846a333db600ad12e1099020196b2f8104563c04d78fedf5afc5d87b91b1b5","withdrawal_credentials":"0x0075f9178dd8a199c55d5cebb9dccb00508e619d5b9abd2b7cd5ad3f671c5a9f","amount":"32000000000","signature":"0x95a886b35ead6f8fc09d33975108857abffc32d53db6546a7251d32ca6d1706e899155b3883b05e65a041e44c51db8480703f13cccc6575cd2d50d0506485b9669a096bb1a2d4879008c15b8c1cdcd2e1a5c4f12885311e24dd87dc32e1bce87"}},{"proof":["0x1a02000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000000000000000000000000000000000000000000000"],"data":{"pubkey":"0x8794fd3f4e5e66e6e81735d5726943833b82d1efd7d877e495a8c36955b7dfb95b3f6cfcef865fd7969fa2e17e628ab9","withdrawal_credentials":"0x0087adf1a29896ae52be67356ee9a4a5035450764c278382f8940d554668c208","amount":"32000000000","signature":"0xb42aa548fd9068db7916757390f6d011ad890b9f27a75d4676dd9edcd9017f5d7e2cec215a04502fcff253aa821865fb0c30549e7b5d5e62cc8df0264dc3b55538f15cfd375f9cb022a94c2a39201d757a502701acd50554dc4da29173c945bd"}}],"voluntary_exits":[{"message":{"epoch":"260","validator_index":"504"},"signature":"0x8fedc3077271b41f631d6062cc1cc8c8f074e486e9e692f198c5f82b94d2bb3b0fbf71cbac043cee94b56a7a06adf06d07bb7ecf06d8f699add17972ceb54b25e6021c3a2a727afd3370e960afbf345a75fddd2d221ba85a5f7b07e5607eec1e"},{"message":{"epoch":"260","validator_index":"503"},"signature":"0xa44079752dfa36b925f0ff675dfd10b5b7cc0c178839356d0bda9c83b6df01f6bfdd904af92373002bfac40277941d2809c4152fc61007ae4f2c73e550ed02f425419efae0461d8829746c7a3d36dcae5bc37158ede7dd30ccc33930783b6194"},{"message":{"epoch":"260","validator_index":"502"},"signature":"0xb193b547c2d45341c9aedd0a22f4afc565d9aaa3a04889df2f8ad608bb31b44a0391c69383f0f4725cea291332c081ff0a48e850d246dd0be40880bf17316eb4b2eaf4b8b6ba6d59c93aea3af98988f05cb2ddf61d8637f943864ebfe7c9707c"},{"message":{"epoch":"260","validator_index":"501"},"signature":"0x88afe9a0215d2a67c451fcbdc358237c4d5dce6b46973ae527afb7f8fb1da800d6a3dd7f6387028a57737b354b7db88803bd6f2a59c7fb84229f42e6c6ea1b7510cb2a28026ff8f2eefb8fc7e2a83115197b7a1bd35fbf0afcc69e4b6e581911"},{"message":{"epoch":"260","validator_index":"500"},"signature":"0xa2f2399070bcfa3f50894d7170d1343ab5f52d6bdc155124e867bcde936aee4e0bb69f164dee5fa07d47abccb8844ec101126caf0402f1a757934f8e7b5904a60cedc283b5e9801f2a71f80cda16e910d72518d469a9a40cd94b8ad3cca10136"},{"message":{"epoch":"260","validator_index":"499"},"signature":"0x86abacd204c85cfc40d71853422001e44134b1900138fccb409928b7e663270476e3d7a7e0aaa103c693cad3629da1aa056cac30c8aab1a4eb50d81bb0711db3dba1d741562b103f67f495996b18fad779d3d9cc508763ab883a7cd6858bdc51"},{"message":{"epoch":"260","validator_index":"498"},"signature":"0xb86533e02779dd0f959dbf1b0fa195126ccc945fd0a7c5b7370aefc16f8f130d083c0c1c58a5c18e8119d7912dd532d91765dd26ad5ef3991238bc093bab79d511b1d8484482eec9b6b4a98f4a8928819ea58fc857ed80b59fe9cb7a33fe60a2"},{"message":{"epoch":"260","validator_index":"495"},"signature":"0x80a5c7c52a246dcaaf67caf6285ea518581835af668d1a64723b321b167464e238248c0017d5265be373c9079d7b529b10aedc37835683e5e1320c3ad6fa1f72d52046a49b061935e1631565912d2f2482434007957fe9903edecf4dad8e5bb8"},{"message":{"epoch":"260","validator_index":"494"},"signature":"0xb6a0e4cdc1815f03166218963ec9cc4c5d607a67d659d1227386e16f90d3e39c6cddf696e3534f3824ca5aff8c734bab153f3bab701247cdcea16db31c94846c1cd3781b1861485ad813d025bf0a486c592dd1f9afa1134e8288e4fef44d2f3c"},{"message":{"epoch":"260","validator_index":"492"},"signature":"0xad850276510c2e41d059df6a1cefab9f1b66463da47b0fc772b21ed90c13e1bd6f86def8b2ecb867f4f752612d9d25e30a151aa6ef630a1b6ddaa4420c240b37df0234ee332373fe132b0101a0486900c5733762beeacd95429dd34c34230d13"},{"message":{"epoch":"260","validator_index":"491"},"signature":"0x837669180ba01b65157087f49c7af19acb1439016eca9c699b7136da7e9bbc89d6bddc7a030388bbb7e149ebd521c4810f457846b9cf913f7ee6f01db4363d3ce92fc732e52359917d36c7e4a08158653f1a9a78a608c4b56ff3e155b2783974"}],"sync_aggregate":{"sync_committee_bits":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","signature":"0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"},"execution_payload":{"parent_hash":"0x0000000000000000000000000000000000000000000000000000000000000000","fee_recipient":"0x0000000000000000000000000000000000000000","state_root":"0x0000000000000000000000000000000000000000000000000000000000000000","receipts_root":"0x0000000000000000000000000000000000000000000000000000000000000000","logs_bloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","prev_randao":"0x0000000000000000000000000000000000000000000000000000000000000000","block_number":"0","gas_limit":"0","gas_used":"0","timestamp":"0","extra_data":null,"base_fee_per_gas":"0x0000000000000000000000000000000000000000000000000000000000000000","block_hash":"0x0000000000000000000000000000000000000000000000000000000000000000","transactions":null},"execution_changes":[],"blob_kzg_commitments":[]}}},"finalized":false,"version":0,"execution_optimistic":false}` + "\n" - - cases := []struct { - blockID string - code int - slot uint64 - }{ - { - blockID: "0x" + common.Bytes2Hex(rootBlock1[:]), - code: http.StatusOK, - }, - { - blockID: "head", - code: http.StatusOK, - slot: blocks[len(blocks)-1].Block.Slot, - }, - { - blockID: "0x" + common.Bytes2Hex(make([]byte, 32)), - code: http.StatusNotFound, - }, - } - - for _, c := range cases { - t.Run(c.blockID, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - // Query the block in the handler with /eth/v2/beacon/blocks/{block_id} - resp, err := http.Get(server.URL + "/eth/v2/beacon/blocks/" + c.blockID) - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - - // unmarshal the json - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - if string(out) != expected { - panic(string(out)) - } - require.Equal(t, expected, string(out)) - }) - } -} - -func TestGetBlockAttestations(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, _, handler, _, _, fcu := setupTestingHandler(t, clparams.Phase0Version) - - // Start by testing - rootBlock1, err := blocks[0].Block.HashSSZ() - if err != nil { - t.Fatal(err) - } - - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - - cases := []struct { - blockID string - code int - attLen int - }{ - { - blockID: "0x" + common.Bytes2Hex(rootBlock1[:]), - code: http.StatusOK, - attLen: blocks[0].Block.Body.Attestations.Len(), - }, - { - blockID: "head", - code: http.StatusOK, - attLen: blocks[len(blocks)-1].Block.Body.Attestations.Len(), - }, - { - blockID: "0x" + common.Bytes2Hex(make([]byte, 32)), - code: http.StatusNotFound, - }, - } - - for _, c := range cases { - t.Run(c.blockID, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - // Query the block in the handler with /eth/v2/beacon/blocks/{block_id} - resp, err := http.Get(server.URL + "/eth/v1/beacon/blocks/" + c.blockID + "/attestations") - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - jsonVal := make(map[string]interface{}) - // unmarshal the json - require.NoError(t, json.NewDecoder(resp.Body).Decode(&jsonVal)) - data := jsonVal["data"].([]interface{}) - require.Equal(t, len(data), c.attLen) - }) - } -} - -func TestGetBlockRoot(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, _, handler, _, _, fcu := setupTestingHandler(t, clparams.Phase0Version) - - var err error - - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - // compute block 0 and block len -1 root - blk0Root, err := blocks[0].Block.HashSSZ() - require.NoError(t, err) - - blkLastRoot, err := blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - cases := []struct { - blockID string - code int - root string - }{ - { - blockID: strconv.FormatInt(int64(blocks[0].Block.Slot), 10), - code: http.StatusOK, - root: "0x" + common.Bytes2Hex(blk0Root[:]), - }, - { - blockID: "head", - code: http.StatusOK, - root: "0x" + common.Bytes2Hex(blkLastRoot[:]), - }, - { - blockID: "19912929", - code: http.StatusNotFound, - }, - } - - for _, c := range cases { - t.Run(c.blockID, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - // Query the block in the handler with /eth/v2/beacon/blocks/{block_id} - resp, err := http.Get(server.URL + "/eth/v1/beacon/blocks/" + c.blockID + "/root") - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - jsonVal := make(map[string]interface{}) - // unmarshal the json - require.NoError(t, json.NewDecoder(resp.Body).Decode(&jsonVal)) - data := jsonVal["data"].(map[string]interface{}) - root := data["root"].(string) - require.Equal(t, root, c.root) - }) - } -} diff --git a/cl/beacon/handler/builder.go b/cl/beacon/handler/builder.go index d7174008681..94166e021c0 100644 --- a/cl/beacon/handler/builder.go +++ b/cl/beacon/handler/builder.go @@ -10,7 +10,7 @@ import ( "github.com/ledgerwatch/erigon/cl/phase1/core/state" ) -func (a *ApiHandler) GetEth1V1BuilderStatesExpectedWit(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) GetEth1V1BuilderStatesExpectedWit(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { ctx := r.Context() tx, err := a.indiciesDB.BeginRo(ctx) @@ -19,7 +19,7 @@ func (a *ApiHandler) GetEth1V1BuilderStatesExpectedWit(w http.ResponseWriter, r } defer tx.Rollback() - blockId, err := stateIdFromRequest(r) + blockId, err := beaconhttp.StateIdFromRequest(r) if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } @@ -44,7 +44,7 @@ func (a *ApiHandler) GetEth1V1BuilderStatesExpectedWit(w http.ResponseWriter, r if root == headRoot { s, cn := a.syncedData.HeadState() defer cn() - return newBeaconResponse(state.ExpectedWithdrawals(s)).withFinalized(false), nil + return newBeaconResponse(state.ExpectedWithdrawals(s)).WithFinalized(false), nil } lookAhead := 1024 for currSlot := *slot + 1; currSlot < *slot+uint64(lookAhead); currSlot++ { @@ -62,7 +62,7 @@ func (a *ApiHandler) GetEth1V1BuilderStatesExpectedWit(w http.ResponseWriter, r if err != nil { return nil, err } - return newBeaconResponse(blk.Block.Body.ExecutionPayload.Withdrawals).withFinalized(false), nil + return newBeaconResponse(blk.Block.Body.ExecutionPayload.Withdrawals).WithFinalized(false), nil } return nil, beaconhttp.NewEndpointError(http.StatusNotFound, "state not found") diff --git a/cl/beacon/handler/commitees_test.go b/cl/beacon/handler/commitees_test.go deleted file mode 100644 index d0cf455b3ad..00000000000 --- a/cl/beacon/handler/commitees_test.go +++ /dev/null @@ -1,169 +0,0 @@ -//go:build integration - -package handler - -import ( - "io" - "math" - "net/http" - "net/http/httptest" - "strconv" - "testing" - - "github.com/ledgerwatch/erigon/cl/clparams" - "github.com/ledgerwatch/erigon/cl/cltypes/solid" - "github.com/ledgerwatch/erigon/common" - "github.com/stretchr/testify/require" -) - -func TestGetCommitteesAntiquated(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, postState, handler, _, _, fcu := setupTestingHandler(t, clparams.Phase0Version) - - postRoot, err := postState.HashSSZ() - require.NoError(t, err) - - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) - fcu.FinalizedSlotVal = math.MaxUint64 - - fcu.StateAtBlockRootVal[fcu.HeadVal] = postState - - cases := []struct { - name string - blockID string - code int - query string - expected string - }{ - { - name: "slot", - blockID: "0x" + common.Bytes2Hex(postRoot[:]), - code: http.StatusOK, - query: "?slot=" + strconv.FormatUint(fcu.HeadSlotVal, 10), - expected: `{"data":[{"index":"0","slot":"8322","validators":["0","104","491","501","379","318","275","504","75","280","105","399","35","401"]}],"finalized":true,"execution_optimistic":false}` + "\n", - }, - { - name: "empty-index", - blockID: "0x" + common.Bytes2Hex(postRoot[:]), - code: http.StatusOK, - query: "?index=1", - expected: `{"data":[],"finalized":true,"execution_optimistic":false}` + "\n", - }, - { - name: "all-queries", - blockID: "0x" + common.Bytes2Hex(postRoot[:]), - code: http.StatusOK, - query: "?index=0&slot=" + strconv.FormatUint(fcu.HeadSlotVal-32, 10) + "&epoch=" + strconv.FormatUint((fcu.HeadSlotVal/32)-1, 10), - expected: `{"data":[{"index":"0","slot":"8290","validators":["127","377","274","85","309","420","423","398","153","480","273","429","374","260"]}],"finalized":true,"execution_optimistic":false}` + "\n", - }, - { - blockID: "0x" + common.Bytes2Hex(make([]byte, 32)), - code: http.StatusNotFound, - }, - } - - for _, c := range cases { - t.Run(c.name, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - // Query the block in the handler with /eth/v2/beacon/states/{block_id} with content-type octet-stream - req, err := http.NewRequest("GET", server.URL+"/eth/v1/beacon/states/"+c.blockID+"/committees"+c.query, nil) - require.NoError(t, err) - - resp, err := http.DefaultClient.Do(req) - require.NoError(t, err) - - defer resp.Body.Close() - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - // read the all of the octect - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.Equal(t, c.expected, string(out)) - }) - } -} - -func TestGetCommitteesNonAntiquated(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, postState, handler, _, sm, fcu := setupTestingHandler(t, clparams.Phase0Version) - - postRoot, err := postState.HashSSZ() - require.NoError(t, err) - - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) - fcu.FinalizedSlotVal = 0 - - fcu.StateAtBlockRootVal[fcu.HeadVal] = postState - require.NoError(t, sm.OnHeadState(postState)) - cases := []struct { - name string - blockID string - code int - query string - expected string - }{ - { - name: "slot", - blockID: "0x" + common.Bytes2Hex(postRoot[:]), - code: http.StatusOK, - query: "?slot=" + strconv.FormatUint(fcu.HeadSlotVal, 10), - expected: `{"data":[{"index":"0","slot":"8322","validators":["0","104","491","501","379","318","275","504","75","280","105","399","35","401"]}],"finalized":false,"execution_optimistic":false}` + "\n", - }, - { - name: "empty-index", - blockID: "0x" + common.Bytes2Hex(postRoot[:]), - code: http.StatusOK, - query: "?index=1", - expected: `{"data":[],"finalized":false,"execution_optimistic":false}` + "\n", - }, - { - name: "all-queries", - blockID: "0x" + common.Bytes2Hex(postRoot[:]), - code: http.StatusOK, - query: "?index=0&slot=" + strconv.FormatUint(fcu.HeadSlotVal-32, 10) + "&epoch=" + strconv.FormatUint((fcu.HeadSlotVal/32)-1, 10), - expected: `{"data":[{"index":"0","slot":"8290","validators":["127","377","274","85","309","420","423","398","153","480","273","429","374","260"]}],"finalized":false,"execution_optimistic":false}` + "\n", - }, - { - blockID: "0x" + common.Bytes2Hex(make([]byte, 32)), - code: http.StatusNotFound, - }, - } - - for _, c := range cases { - t.Run(c.name, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - // Query the block in the handler with /eth/v2/beacon/states/{block_id} with content-type octet-stream - req, err := http.NewRequest("GET", server.URL+"/eth/v1/beacon/states/"+c.blockID+"/committees"+c.query, nil) - require.NoError(t, err) - - resp, err := http.DefaultClient.Do(req) - require.NoError(t, err) - - defer resp.Body.Close() - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - // read the all of the octect - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.Equal(t, c.expected, string(out)) - }) - } -} diff --git a/cl/beacon/handler/committees.go b/cl/beacon/handler/committees.go index 0ab70fc29cd..c7e527fbe76 100644 --- a/cl/beacon/handler/committees.go +++ b/cl/beacon/handler/committees.go @@ -17,20 +17,20 @@ type committeeResponse struct { Validators []string `json:"validators"` // do string directly but it is still a base10 number } -func (a *ApiHandler) getCommittees(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getCommittees(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { ctx := r.Context() - epochReq, err := uint64FromQueryParams(r, "epoch") + epochReq, err := beaconhttp.Uint64FromQueryParams(r, "epoch") if err != nil { return nil, err } - index, err := uint64FromQueryParams(r, "index") + index, err := beaconhttp.Uint64FromQueryParams(r, "index") if err != nil { return nil, err } - slotFilter, err := uint64FromQueryParams(r, "slot") + slotFilter, err := beaconhttp.Uint64FromQueryParams(r, "slot") if err != nil { return nil, err } @@ -40,7 +40,7 @@ func (a *ApiHandler) getCommittees(w http.ResponseWriter, r *http.Request) (*bea return nil, err } defer tx.Rollback() - blockId, err := stateIdFromRequest(r) + blockId, err := beaconhttp.StateIdFromRequest(r) if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } @@ -100,7 +100,7 @@ func (a *ApiHandler) getCommittees(w http.ResponseWriter, r *http.Request) (*bea resp = append(resp, data) } } - return newBeaconResponse(resp).withFinalized(isFinalized), nil + return newBeaconResponse(resp).WithFinalized(isFinalized), nil } // finality case activeIdxs, err := state_accessors.ReadActiveIndicies(tx, epoch*a.beaconChainCfg.SlotsPerEpoch) @@ -143,5 +143,5 @@ func (a *ApiHandler) getCommittees(w http.ResponseWriter, r *http.Request) (*bea resp = append(resp, data) } } - return newBeaconResponse(resp).withFinalized(isFinalized), nil + return newBeaconResponse(resp).WithFinalized(isFinalized), nil } diff --git a/cl/beacon/handler/config.go b/cl/beacon/handler/config.go index cc37c8a0150..8a0914e769a 100644 --- a/cl/beacon/handler/config.go +++ b/cl/beacon/handler/config.go @@ -6,14 +6,15 @@ import ( "sort" libcommon "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon/cl/beacon/beaconhttp" "github.com/ledgerwatch/erigon/cl/cltypes" ) -func (a *ApiHandler) getSpec(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getSpec(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { return newBeaconResponse(a.beaconChainCfg), nil } -func (a *ApiHandler) getDepositContract(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getDepositContract(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { return newBeaconResponse(struct { ChainId uint64 `json:"chain_id,string"` DepositContract string `json:"address"` @@ -21,7 +22,7 @@ func (a *ApiHandler) getDepositContract(w http.ResponseWriter, r *http.Request) } -func (a *ApiHandler) getForkSchedule(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getForkSchedule(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { response := []cltypes.Fork{} // create first response (unordered and incomplete) for currentVersion, epoch := range a.beaconChainCfg.ForkVersionSchedule { diff --git a/cl/beacon/handler/config_test.go b/cl/beacon/handler/config_test.go deleted file mode 100644 index 995a38d5abc..00000000000 --- a/cl/beacon/handler/config_test.go +++ /dev/null @@ -1,83 +0,0 @@ -//go:build integration - -package handler - -import ( - "encoding/json" - "net/http" - "net/http/httptest" - "testing" - - "github.com/ledgerwatch/erigon/cl/clparams" - "github.com/stretchr/testify/require" -) - -func TestGetSpec(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, _, _, _, _, handler, _, _, _ := setupTestingHandler(t, clparams.Phase0Version) - - server := httptest.NewServer(handler.mux) - defer server.Close() - - resp, err := http.Get(server.URL + "/eth/v1/config/spec") - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, http.StatusOK, resp.StatusCode) - out := make(map[string]interface{}) - err = json.NewDecoder(resp.Body).Decode(&out) - require.NoError(t, err) - - data := out["data"].(map[string]interface{}) - require.Equal(t, data["SlotsPerEpoch"], float64(32)) - require.Equal(t, data["SlotsPerHistoricalRoot"], float64(8192)) -} - -func TestGetForkSchedule(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, _, _, _, _, handler, _, _, _ := setupTestingHandler(t, clparams.Phase0Version) - - server := httptest.NewServer(handler.mux) - defer server.Close() - - resp, err := http.Get(server.URL + "/eth/v1/config/fork_schedule") - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, http.StatusOK, resp.StatusCode) - out := make(map[string]interface{}) - err = json.NewDecoder(resp.Body).Decode(&out) - require.NoError(t, err) - - require.Greater(t, len(out["data"].([]interface{})), 2) - for _, v := range out["data"].([]interface{}) { - data := v.(map[string]interface{}) - require.NotNil(t, data["current_version"]) - require.NotNil(t, data["epoch"]) - require.NotNil(t, data["previous_version"]) - } -} - -func TestGetDepositContract(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, _, _, _, _, handler, _, _, _ := setupTestingHandler(t, clparams.Phase0Version) - - server := httptest.NewServer(handler.mux) - defer server.Close() - - resp, err := http.Get(server.URL + "/eth/v1/config/deposit_contract") - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, http.StatusOK, resp.StatusCode) - out := make(map[string]interface{}) - err = json.NewDecoder(resp.Body).Decode(&out) - require.NoError(t, err) - - data := out["data"].(map[string]interface{}) - require.Equal(t, data["address"], "0x00000000219ab540356cBB839Cbe05303d7705Fa") - require.Equal(t, data["chain_id"], "1") -} diff --git a/cl/beacon/handler/data_test.go b/cl/beacon/handler/data_test.go new file mode 100644 index 00000000000..3b4276e4c8e --- /dev/null +++ b/cl/beacon/handler/data_test.go @@ -0,0 +1,98 @@ +package handler_test + +import ( + "embed" + "math" + "os" + "strings" + "testing" + + "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon/cl/beacon/beacontest" + "github.com/ledgerwatch/erigon/cl/clparams" + "github.com/ledgerwatch/erigon/cl/cltypes/solid" + "github.com/ledgerwatch/erigon/cl/phase1/forkchoice" + "github.com/ledgerwatch/log/v3" + "github.com/spf13/afero" + "github.com/stretchr/testify/require" +) + +//go:embed test_data/* +var testData embed.FS + +var TestDatae = beacontest.NewBasePathFs(afero.FromIOFS{FS: testData}, "test_data") + +//go:embed harness/* +var testHarness embed.FS + +var Harnesses = beacontest.NewBasePathFs(afero.FromIOFS{FS: testHarness}, "harness") + +type harnessConfig struct { + t *testing.T + v clparams.StateVersion + finalized bool + forkmode int +} + +func defaultHarnessOpts(c harnessConfig) []beacontest.HarnessOption { + logger := log.New() + for _, v := range os.Args { + if !strings.Contains(v, "test.v") || strings.Contains(v, "test.v=false") { + logger.SetHandler(log.DiscardHandler()) + } + } + _, blocks, _, _, postState, handler, _, sm, fcu := setupTestingHandler(c.t, c.v, logger) + var err error + + if c.forkmode == 0 { + fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() + require.NoError(c.t, err) + fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot + + fcu.JustifiedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) + if c.finalized { + fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) + fcu.FinalizedSlotVal = math.MaxUint64 + } else { + fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) + fcu.FinalizedSlotVal = 0 + fcu.StateAtBlockRootVal[fcu.HeadVal] = postState + require.NoError(c.t, sm.OnHeadState(postState)) + } + } + + if c.forkmode == 1 { + sm.OnHeadState(postState) + s, cancel := sm.HeadState() + s.SetSlot(789274827847783) + cancel() + + fcu.HeadSlotVal = 128 + fcu.HeadVal = common.Hash{1, 2, 3} + + fcu.WeightsMock = []forkchoice.ForkNode{ + { + BlockRoot: common.Hash{1, 2, 3}, + ParentRoot: common.Hash{1, 2, 3}, + Slot: 128, + Weight: 1, + }, + { + BlockRoot: common.Hash{1, 2, 2, 4, 5, 3}, + ParentRoot: common.Hash{1, 2, 5}, + Slot: 128, + Weight: 2, + }, + } + + fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(common.Hash{1, 2, 3}, 1) + fcu.JustifiedCheckpointVal = solid.NewCheckpointFromParameters(common.Hash{1, 2, 3}, 2) + + } + + return []beacontest.HarnessOption{ + beacontest.WithTesting(c.t), + beacontest.WithFilesystem("td", TestDatae), + beacontest.WithHandler("i", handler), + } +} diff --git a/cl/beacon/handler/duties_attester.go b/cl/beacon/handler/duties_attester.go index a9f1045d0f9..3fb6a3f1609 100644 --- a/cl/beacon/handler/duties_attester.go +++ b/cl/beacon/handler/duties_attester.go @@ -22,8 +22,8 @@ type attesterDutyResponse struct { Slot uint64 `json:"slot,string"` } -func (a *ApiHandler) getAttesterDuties(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { - epoch, err := epochFromRequest(r) +func (a *ApiHandler) getAttesterDuties(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { + epoch, err := beaconhttp.EpochFromRequest(r) if err != nil { return nil, err } @@ -33,7 +33,7 @@ func (a *ApiHandler) getAttesterDuties(w http.ResponseWriter, r *http.Request) ( return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, fmt.Errorf("could not decode request body: %w. request body is required", err).Error()) } if len(idxsStr) == 0 { - return newBeaconResponse([]string{}).withOptimistic(false), nil + return newBeaconResponse([]string{}).WithOptimistic(false), nil } idxSet := map[int]struct{}{} // convert the request to uint64 @@ -100,7 +100,7 @@ func (a *ApiHandler) getAttesterDuties(w http.ResponseWriter, r *http.Request) ( } } } - return newBeaconResponse(resp).withOptimistic(false), nil + return newBeaconResponse(resp).WithOptimistic(false), nil } stageStateProgress, err := state_accessors.GetStateProcessingProgress(tx) @@ -159,5 +159,5 @@ func (a *ApiHandler) getAttesterDuties(w http.ResponseWriter, r *http.Request) ( } } } - return newBeaconResponse(resp).withOptimistic(false), nil + return newBeaconResponse(resp).WithOptimistic(false), nil } diff --git a/cl/beacon/handler/duties_attester_test.go b/cl/beacon/handler/duties_attester_test.go deleted file mode 100644 index 0035d99e505..00000000000 --- a/cl/beacon/handler/duties_attester_test.go +++ /dev/null @@ -1,153 +0,0 @@ -//go:build integration - -package handler - -import ( - "bytes" - "io" - "math" - "net/http" - "net/http/httptest" - "strconv" - "testing" - - "github.com/ledgerwatch/erigon/cl/clparams" - "github.com/ledgerwatch/erigon/cl/cltypes/solid" - "github.com/stretchr/testify/require" -) - -func TestDutiesAttesterAntiquated(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, postState, handler, _, _, fcu := setupTestingHandler(t, clparams.Phase0Version) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) - fcu.FinalizedSlotVal = math.MaxUint64 - - fcu.StateAtBlockRootVal[fcu.HeadVal] = postState - - cases := []struct { - name string - epoch string - code int - reqBody string - expected string - }{ - { - name: "non-empty-indicies", - epoch: strconv.FormatUint(fcu.HeadSlotVal/32, 10), - code: http.StatusOK, - reqBody: `["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]`, - expected: `{"data":[{"pubkey":"0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb","validator_index":"0","committee_index":"0","committee_length":"14","validator_committee_index":"0","committees_at_slot":"1","slot":"8322"},{"pubkey":"0xb0e7791fb972fe014159aa33a98622da3cdc98ff707965e536d8636b5fcc5ac7a91a8c46e59a00dca575af0f18fb13dc","validator_index":"4","committee_index":"0","committee_length":"13","validator_committee_index":"5","committees_at_slot":"1","slot":"8327"},{"pubkey":"0xb928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7","validator_index":"6","committee_index":"0","committee_length":"13","validator_committee_index":"10","committees_at_slot":"1","slot":"8327"},{"pubkey":"0xa6e82f6da4520f85c5d27d8f329eccfa05944fd1096b20734c894966d12a9e2a9a9744529d7212d33883113a0cadb909","validator_index":"5","committee_index":"0","committee_length":"14","validator_committee_index":"10","committees_at_slot":"1","slot":"8329"},{"pubkey":"0x89ece308f9d1f0131765212deca99697b112d61f9be9a5f1f3780a51335b3ff981747a0b2ca2179b96d2c0c9024e5224","validator_index":"2","committee_index":"0","committee_length":"14","validator_committee_index":"11","committees_at_slot":"1","slot":"8331"},{"pubkey":"0xaf81da25ecf1c84b577fefbedd61077a81dc43b00304015b2b596ab67f00e41c86bb00ebd0f90d4b125eb0539891aeed","validator_index":"9","committee_index":"0","committee_length":"14","validator_committee_index":"8","committees_at_slot":"1","slot":"8342"},{"pubkey":"0xac9b60d5afcbd5663a8a44b7c5a02f19e9a77ab0a35bd65809bb5c67ec582c897feb04decc694b13e08587f3ff9b5b60","validator_index":"3","committee_index":"0","committee_length":"13","validator_committee_index":"6","committees_at_slot":"1","slot":"8348"}],"execution_optimistic":false}` + "\n", - }, - { - name: "empty-index", - epoch: strconv.FormatUint(fcu.HeadSlotVal/32, 10), - code: http.StatusOK, - reqBody: `[]`, - expected: `{"data":[],"execution_optimistic":false}` + "\n", - }, - { - name: "404", - reqBody: `["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]`, - epoch: `999999999`, - code: http.StatusBadRequest, - }, - } - - for _, c := range cases { - t.Run(c.name, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - // - body := bytes.Buffer{} - body.WriteString(c.reqBody) - // Query the block in the handler with /eth/v2/beacon/states/{block_id} with content-type octet-stream - req, err := http.NewRequest("POST", server.URL+"/eth/v1/validator/duties/attester/"+c.epoch, &body) - require.NoError(t, err) - - resp, err := http.DefaultClient.Do(req) - require.NoError(t, err) - - defer resp.Body.Close() - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - // read the all of the octect - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.Equal(t, c.expected, string(out)) - }) - } -} - -func TestDutiesAttesterNonAntiquated(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, postState, handler, _, sm, fcu := setupTestingHandler(t, clparams.Phase0Version) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) - fcu.FinalizedSlotVal = 0 - - fcu.StateAtBlockRootVal[fcu.HeadVal] = postState - require.NoError(t, sm.OnHeadState(postState)) - cases := []struct { - name string - epoch string - code int - reqBody string - expected string - }{ - { - name: "non-empty-indicies", - epoch: strconv.FormatUint(fcu.HeadSlotVal/32, 10), - code: http.StatusOK, - reqBody: `["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]`, - expected: `{"data":[{"pubkey":"0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb","validator_index":"0","committee_index":"0","committee_length":"14","validator_committee_index":"0","committees_at_slot":"1","slot":"8322"},{"pubkey":"0xb0e7791fb972fe014159aa33a98622da3cdc98ff707965e536d8636b5fcc5ac7a91a8c46e59a00dca575af0f18fb13dc","validator_index":"4","committee_index":"0","committee_length":"13","validator_committee_index":"5","committees_at_slot":"1","slot":"8327"},{"pubkey":"0xb928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7","validator_index":"6","committee_index":"0","committee_length":"13","validator_committee_index":"10","committees_at_slot":"1","slot":"8327"},{"pubkey":"0xa6e82f6da4520f85c5d27d8f329eccfa05944fd1096b20734c894966d12a9e2a9a9744529d7212d33883113a0cadb909","validator_index":"5","committee_index":"0","committee_length":"14","validator_committee_index":"10","committees_at_slot":"1","slot":"8329"},{"pubkey":"0x89ece308f9d1f0131765212deca99697b112d61f9be9a5f1f3780a51335b3ff981747a0b2ca2179b96d2c0c9024e5224","validator_index":"2","committee_index":"0","committee_length":"14","validator_committee_index":"11","committees_at_slot":"1","slot":"8331"},{"pubkey":"0xaf81da25ecf1c84b577fefbedd61077a81dc43b00304015b2b596ab67f00e41c86bb00ebd0f90d4b125eb0539891aeed","validator_index":"9","committee_index":"0","committee_length":"14","validator_committee_index":"8","committees_at_slot":"1","slot":"8342"},{"pubkey":"0xac9b60d5afcbd5663a8a44b7c5a02f19e9a77ab0a35bd65809bb5c67ec582c897feb04decc694b13e08587f3ff9b5b60","validator_index":"3","committee_index":"0","committee_length":"13","validator_committee_index":"6","committees_at_slot":"1","slot":"8348"}],"execution_optimistic":false}` + "\n", - }, - { - name: "empty-index", - epoch: strconv.FormatUint(fcu.HeadSlotVal/32, 10), - code: http.StatusOK, - reqBody: `[]`, - expected: `{"data":[],"execution_optimistic":false}` + "\n", - }, - { - name: "404", - reqBody: `["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]`, - epoch: `999999999`, - code: http.StatusBadRequest, - }, - } - - for _, c := range cases { - t.Run(c.name, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - // - body := bytes.Buffer{} - body.WriteString(c.reqBody) - // Query the block in the handler with /eth/v2/beacon/states/{block_id} with content-type octet-stream - req, err := http.NewRequest("POST", server.URL+"/eth/v1/validator/duties/attester/"+c.epoch, &body) - require.NoError(t, err) - - resp, err := http.DefaultClient.Do(req) - require.NoError(t, err) - - defer resp.Body.Close() - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - // read the all of the octect - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.Equal(t, c.expected, string(out)) - }) - } -} diff --git a/cl/beacon/handler/duties_proposer.go b/cl/beacon/handler/duties_proposer.go index fb8ae2a09ed..95fd2dfb648 100644 --- a/cl/beacon/handler/duties_proposer.go +++ b/cl/beacon/handler/duties_proposer.go @@ -21,8 +21,8 @@ type proposerDuties struct { Slot uint64 `json:"slot,string"` } -func (a *ApiHandler) getDutiesProposer(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { - epoch, err := epochFromRequest(r) +func (a *ApiHandler) getDutiesProposer(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { + epoch, err := beaconhttp.EpochFromRequest(r) if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } @@ -55,7 +55,7 @@ func (a *ApiHandler) getDutiesProposer(w http.ResponseWriter, r *http.Request) ( Slot: epoch*a.beaconChainCfg.SlotsPerEpoch + i, } } - return newBeaconResponse(duties).withFinalized(true).withVersion(a.beaconChainCfg.GetCurrentStateVersion(epoch)), nil + return newBeaconResponse(duties).WithFinalized(true).WithVersion(a.beaconChainCfg.GetCurrentStateVersion(epoch)), nil } // We need to compute our duties @@ -118,5 +118,5 @@ func (a *ApiHandler) getDutiesProposer(w http.ResponseWriter, r *http.Request) ( } wg.Wait() - return newBeaconResponse(duties).withFinalized(false).withVersion(a.beaconChainCfg.GetCurrentStateVersion(epoch)), nil + return newBeaconResponse(duties).WithFinalized(false).WithVersion(a.beaconChainCfg.GetCurrentStateVersion(epoch)), nil } diff --git a/cl/beacon/handler/duties_proposer_test.go b/cl/beacon/handler/duties_proposer_test.go deleted file mode 100644 index 1994098b27b..00000000000 --- a/cl/beacon/handler/duties_proposer_test.go +++ /dev/null @@ -1,114 +0,0 @@ -//go:build integration - -package handler - -import ( - "encoding/json" - "net/http" - "net/http/httptest" - "strconv" - "testing" - - "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon/cl/clparams" - "github.com/ledgerwatch/erigon/cl/cltypes/solid" - "github.com/stretchr/testify/require" -) - -func TestProposerDutiesProposerFcu(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, postState, _, handler, _, syncedDataManager, fcu := setupTestingHandler(t, clparams.Phase0Version) - epoch := blocks[len(blocks)-1].Block.Slot / 32 - - require.NoError(t, syncedDataManager.OnHeadState(postState)) - - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(common.Hash{}, epoch) - - server := httptest.NewServer(handler.mux) - defer server.Close() - - resp, err := http.Get(server.URL + "/eth/v1/validator/duties/proposer/" + strconv.FormatUint(epoch, 10)) - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, http.StatusOK, resp.StatusCode) - out := make(map[string]interface{}) - err = json.NewDecoder(resp.Body).Decode(&out) - require.NoError(t, err) - - data := out["data"].([]interface{}) - require.Equal(t, len(data), 32) - for _, v := range data { - d := v.(map[string]interface{}) - require.NotNil(t, d["pubkey"]) - require.NotNil(t, d["validator_index"]) - require.NotNil(t, d["slot"]) - } -} - -func TestProposerDutiesProposerBadEpoch(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, _, _, postState, _, handler, _, syncedDataManager, fcu := setupTestingHandler(t, clparams.Phase0Version) - - require.NoError(t, syncedDataManager.OnHeadState(postState)) - - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(common.Hash{}, 1) - - server := httptest.NewServer(handler.mux) - defer server.Close() - - resp, err := http.Get(server.URL + "/eth/v1/validator/duties/proposer/abc") - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, http.StatusBadRequest, resp.StatusCode) -} - -func TestProposerDutiesNotSynced(t *testing.T) { - _, _, _, _, _, handler, _, _, fcu := setupTestingHandler(t, clparams.Phase0Version) - - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(common.Hash{}, 1) - - server := httptest.NewServer(handler.mux) - defer server.Close() - - resp, err := http.Get(server.URL + "/eth/v1/validator/duties/proposer/1") - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, http.StatusServiceUnavailable, resp.StatusCode) -} - -func TestProposerDutiesProposerFcuHistorical(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, postState, _, handler, _, syncedDataManager, fcu := setupTestingHandler(t, clparams.Phase0Version) - epoch := blocks[len(blocks)-1].Block.Slot / 32 - - require.NoError(t, syncedDataManager.OnHeadState(postState)) - - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(common.Hash{}, epoch) - - server := httptest.NewServer(handler.mux) - defer server.Close() - - resp, err := http.Get(server.URL + "/eth/v1/validator/duties/proposer/" + strconv.FormatUint(epoch-1, 10)) - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, http.StatusOK, resp.StatusCode) - out := make(map[string]interface{}) - err = json.NewDecoder(resp.Body).Decode(&out) - require.NoError(t, err) - - data := out["data"].([]interface{}) - require.Equal(t, len(data), 32) - for _, v := range data { - d := v.(map[string]interface{}) - require.NotNil(t, d["pubkey"]) - require.NotNil(t, d["validator_index"]) - require.NotNil(t, d["slot"]) - } -} diff --git a/cl/beacon/handler/duties_sync.go b/cl/beacon/handler/duties_sync.go index e52a8a23246..154b7d40282 100644 --- a/cl/beacon/handler/duties_sync.go +++ b/cl/beacon/handler/duties_sync.go @@ -20,8 +20,8 @@ type syncDutyResponse struct { ValidatorSyncCommitteeIndicies []string `json:"validator_sync_committee_indicies"` } -func (a *ApiHandler) getSyncDuties(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { - epoch, err := epochFromRequest(r) +func (a *ApiHandler) getSyncDuties(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { + epoch, err := beaconhttp.EpochFromRequest(r) if err != nil { return nil, err } @@ -34,7 +34,7 @@ func (a *ApiHandler) getSyncDuties(w http.ResponseWriter, r *http.Request) (*bea return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, fmt.Errorf("could not decode request body: %w. request body is required.", err).Error()) } if len(idxsStr) == 0 { - return newBeaconResponse([]string{}).withOptimistic(false), nil + return newBeaconResponse([]string{}).WithOptimistic(false), nil } duplicates := map[int]struct{}{} // convert the request to uint64 @@ -142,5 +142,5 @@ func (a *ApiHandler) getSyncDuties(w http.ResponseWriter, r *http.Request) (*bea return duties[i].ValidatorIndex < duties[j].ValidatorIndex }) - return newBeaconResponse(duties).withOptimistic(false), nil + return newBeaconResponse(duties).WithOptimistic(false), nil } diff --git a/cl/beacon/handler/duties_sync_test.go b/cl/beacon/handler/duties_sync_test.go deleted file mode 100644 index 9eabf90e301..00000000000 --- a/cl/beacon/handler/duties_sync_test.go +++ /dev/null @@ -1,87 +0,0 @@ -//go:build integration - -package handler - -import ( - "bytes" - "io" - "math" - "net/http" - "net/http/httptest" - "strconv" - "testing" - - "github.com/ledgerwatch/erigon/cl/clparams" - "github.com/ledgerwatch/erigon/cl/cltypes/solid" - "github.com/stretchr/testify/require" -) - -func TestDutiesSync(t *testing.T) { - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, postState, handler, _, _, fcu := setupTestingHandler(t, clparams.BellatrixVersion) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) - fcu.FinalizedSlotVal = math.MaxUint64 - - fcu.StateAtBlockRootVal[fcu.HeadVal] = postState - - cases := []struct { - name string - epoch string - code int - reqBody string - expected string - }{ - { - name: "non-empty-indicies", - epoch: strconv.FormatUint(fcu.HeadSlotVal/32, 10), - code: http.StatusOK, - reqBody: `["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]`, - expected: `{"data":[{"pubkey":"0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb","validator_index":"0","validator_sync_committee_indicies":["30","286"]},{"pubkey":"0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e","validator_index":"1","validator_sync_committee_indicies":["120","376"]},{"pubkey":"0x89ece308f9d1f0131765212deca99697b112d61f9be9a5f1f3780a51335b3ff981747a0b2ca2179b96d2c0c9024e5224","validator_index":"2","validator_sync_committee_indicies":["138","394"]},{"pubkey":"0xac9b60d5afcbd5663a8a44b7c5a02f19e9a77ab0a35bd65809bb5c67ec582c897feb04decc694b13e08587f3ff9b5b60","validator_index":"3","validator_sync_committee_indicies":["10","266"]},{"pubkey":"0xb0e7791fb972fe014159aa33a98622da3cdc98ff707965e536d8636b5fcc5ac7a91a8c46e59a00dca575af0f18fb13dc","validator_index":"4","validator_sync_committee_indicies":["114","370"]},{"pubkey":"0xa6e82f6da4520f85c5d27d8f329eccfa05944fd1096b20734c894966d12a9e2a9a9744529d7212d33883113a0cadb909","validator_index":"5","validator_sync_committee_indicies":["103","359"]},{"pubkey":"0xb928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7","validator_index":"6","validator_sync_committee_indicies":["163","419"]},{"pubkey":"0xa85ae765588126f5e860d019c0e26235f567a9c0c0b2d8ff30f3e8d436b1082596e5e7462d20f5be3764fd473e57f9cf","validator_index":"7","validator_sync_committee_indicies":["197","453"]},{"pubkey":"0x99cdf3807146e68e041314ca93e1fee0991224ec2a74beb2866816fd0826ce7b6263ee31e953a86d1b72cc2215a57793","validator_index":"8","validator_sync_committee_indicies":["175","431"]},{"pubkey":"0xaf81da25ecf1c84b577fefbedd61077a81dc43b00304015b2b596ab67f00e41c86bb00ebd0f90d4b125eb0539891aeed","validator_index":"9","validator_sync_committee_indicies":["53","309"]}],"execution_optimistic":false}` + "\n", - }, - { - name: "empty-index", - epoch: strconv.FormatUint(fcu.HeadSlotVal/32, 10), - code: http.StatusOK, - reqBody: `[]`, - expected: `{"data":[],"execution_optimistic":false}` + "\n", - }, - { - name: "404", - reqBody: `["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]`, - epoch: `999999999`, - code: http.StatusNotFound, - }, - } - - for _, c := range cases { - t.Run(c.name, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - // - body := bytes.Buffer{} - body.WriteString(c.reqBody) - // Query the block in the handler with /eth/v2/beacon/states/{block_id} with content-type octet-stream - req, err := http.NewRequest("POST", server.URL+"/eth/v1/validator/duties/sync/"+c.epoch, &body) - require.NoError(t, err) - - resp, err := http.DefaultClient.Do(req) - require.NoError(t, err) - - defer resp.Body.Close() - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - // read the all of the octect - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - if string(out) != c.expected { - panic(string(out)) - } - require.Equal(t, c.expected, string(out)) - }) - } -} diff --git a/cl/beacon/handler/forkchoice.go b/cl/beacon/handler/forkchoice.go index 4f7f845b707..e8ceea1f655 100644 --- a/cl/beacon/handler/forkchoice.go +++ b/cl/beacon/handler/forkchoice.go @@ -7,7 +7,7 @@ import ( "github.com/ledgerwatch/erigon/cl/beacon/beaconhttp" ) -func (a *ApiHandler) GetEthV2DebugBeaconHeads(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) GetEthV2DebugBeaconHeads(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { if a.syncedData.Syncing() { return nil, beaconhttp.NewEndpointError(http.StatusServiceUnavailable, "beacon node is syncing") } diff --git a/cl/beacon/handler/forkchoice_test.go b/cl/beacon/handler/forkchoice_test.go deleted file mode 100644 index 8b98997f815..00000000000 --- a/cl/beacon/handler/forkchoice_test.go +++ /dev/null @@ -1,80 +0,0 @@ -package handler - -import ( - "io" - "net/http/httptest" - "testing" - - libcommon "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon/cl/clparams" - "github.com/ledgerwatch/erigon/cl/cltypes/solid" - "github.com/ledgerwatch/erigon/cl/phase1/forkchoice" - "github.com/stretchr/testify/require" -) - -func TestGetHeads(t *testing.T) { - // find server - _, _, _, _, p, handler, _, sm, fcu := setupTestingHandler(t, clparams.Phase0Version) - sm.OnHeadState(p) - s, cancel := sm.HeadState() - s.SetSlot(789274827847783) - cancel() - - fcu.HeadSlotVal = 128 - fcu.HeadVal = libcommon.Hash{1, 2, 3} - server := httptest.NewServer(handler.mux) - defer server.Close() - - // get heads - resp, err := server.Client().Get(server.URL + "/eth/v2/debug/beacon/heads") - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, 200, resp.StatusCode) - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - - require.Equal(t, `{"data":[{"execution_optimistic":false,"root":"0x0102030000000000000000000000000000000000000000000000000000000000","slot":128}]}`+"\n", string(out)) -} - -func TestGetForkchoice(t *testing.T) { - // find server - _, _, _, _, p, handler, _, sm, fcu := setupTestingHandler(t, clparams.Phase0Version) - sm.OnHeadState(p) - s, cancel := sm.HeadState() - s.SetSlot(789274827847783) - cancel() - - fcu.HeadSlotVal = 128 - fcu.HeadVal = libcommon.Hash{1, 2, 3} - server := httptest.NewServer(handler.mux) - defer server.Close() - - fcu.WeightsMock = []forkchoice.ForkNode{ - { - BlockRoot: libcommon.Hash{1, 2, 3}, - ParentRoot: libcommon.Hash{1, 2, 3}, - Slot: 128, - Weight: 1, - }, - { - BlockRoot: libcommon.Hash{1, 2, 2, 4, 5, 3}, - ParentRoot: libcommon.Hash{1, 2, 5}, - Slot: 128, - Weight: 2, - }, - } - - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(libcommon.Hash{1, 2, 3}, 1) - fcu.JustifiedCheckpointVal = solid.NewCheckpointFromParameters(libcommon.Hash{1, 2, 3}, 2) - - // get heads - resp, err := server.Client().Get(server.URL + "/eth/v1/debug/fork_choice") - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, 200, resp.StatusCode) - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.Equal(t, `{"finalized_checkpoint":{"epoch":"1","root":"0x0102030000000000000000000000000000000000000000000000000000000000"},"fork_choice_nodes":[{"slot":"128","block_root":"0x0102030000000000000000000000000000000000000000000000000000000000","parent_root":"0x0102030000000000000000000000000000000000000000000000000000000000","justified_epoch":"0","finalized_epoch":"0","weight":"1","validity":"","execution_block_hash":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"slot":"128","block_root":"0x0102020405030000000000000000000000000000000000000000000000000000","parent_root":"0x0102050000000000000000000000000000000000000000000000000000000000","justified_epoch":"0","finalized_epoch":"0","weight":"2","validity":"","execution_block_hash":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"justified_checkpoint":{"epoch":"2","root":"0x0102030000000000000000000000000000000000000000000000000000000000"}}`+"\n", string(out)) -} diff --git a/cl/beacon/handler/format.go b/cl/beacon/handler/format.go index 3a96cf6e8c0..bb071a0b2fc 100644 --- a/cl/beacon/handler/format.go +++ b/cl/beacon/handler/format.go @@ -1,242 +1,9 @@ package handler import ( - "fmt" - "net/http" - "regexp" - "strconv" - - "github.com/go-chi/chi/v5" - libcommon "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon-lib/types/ssz" "github.com/ledgerwatch/erigon/cl/beacon/beaconhttp" - "github.com/ledgerwatch/erigon/cl/clparams" -) - -type apiError struct { - code int - err error -} - -type beaconResponse struct { - Data any `json:"data,omitempty"` - Finalized *bool `json:"finalized,omitempty"` - Version *clparams.StateVersion `json:"version,omitempty"` - ExecutionOptimistic *bool `json:"execution_optimistic,omitempty"` -} - -func (b *beaconResponse) EncodeSSZ(xs []byte) ([]byte, error) { - marshaler, ok := b.Data.(ssz.Marshaler) - if !ok { - return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, "This endpoint does not support SSZ response") - } - encoded, err := marshaler.EncodeSSZ(nil) - if err != nil { - return nil, err - } - return encoded, nil -} - -func (b *beaconResponse) EncodingSizeSSZ() int { - marshaler, ok := b.Data.(ssz.Marshaler) - if !ok { - return 9 - } - return marshaler.EncodingSizeSSZ() -} - -func newBeaconResponse(data any) *beaconResponse { - return &beaconResponse{ - Data: data, - } -} - -func (r *beaconResponse) withFinalized(finalized bool) (out *beaconResponse) { - out = new(beaconResponse) - *out = *r - out.Finalized = new(bool) - out.ExecutionOptimistic = new(bool) - out.Finalized = &finalized - return out -} - -func (r *beaconResponse) withOptimistic(optimistic bool) (out *beaconResponse) { - out = new(beaconResponse) - *out = *r - out.ExecutionOptimistic = new(bool) - out.ExecutionOptimistic = &optimistic - return out -} - -func (r *beaconResponse) withVersion(version clparams.StateVersion) (out *beaconResponse) { - out = new(beaconResponse) - *out = *r - out.Version = new(clparams.StateVersion) - out.Version = &version - return out -} - -type chainTag int - -var ( - Head chainTag = 0 - Finalized chainTag = 1 - Justified chainTag = 2 - Genesis chainTag = 3 ) -// Represent either state id or block id -type segmentID struct { - tag chainTag - slot *uint64 - root *libcommon.Hash -} - -func (c *segmentID) head() bool { - return c.tag == Head && c.slot == nil && c.root == nil -} - -func (c *segmentID) finalized() bool { - return c.tag == Finalized -} - -func (c *segmentID) justified() bool { - return c.tag == Justified -} - -func (c *segmentID) genesis() bool { - return c.tag == Genesis -} - -func (c *segmentID) getSlot() *uint64 { - return c.slot -} - -func (c *segmentID) getRoot() *libcommon.Hash { - return c.root -} - -func epochFromRequest(r *http.Request) (uint64, error) { - // Must only be a number - regex := regexp.MustCompile(`^\d+$`) - epoch := chi.URLParam(r, "epoch") - if !regex.MatchString(epoch) { - return 0, fmt.Errorf("invalid path variable: {epoch}") - } - epochMaybe, err := strconv.ParseUint(epoch, 10, 64) - if err != nil { - return 0, err - } - return epochMaybe, nil -} - -func stringFromRequest(r *http.Request, name string) (string, error) { - str := chi.URLParam(r, name) - if str == "" { - return "", nil - } - return str, nil -} - -func blockIdFromRequest(r *http.Request) (*segmentID, error) { - regex := regexp.MustCompile(`^(?:0x[0-9a-fA-F]{64}|head|finalized|genesis|\d+)$`) - - blockId := chi.URLParam(r, "block_id") - if !regex.MatchString(blockId) { - return nil, fmt.Errorf("invalid path variable: {block_id}") - } - - if blockId == "head" { - return &segmentID{tag: Head}, nil - } - if blockId == "finalized" { - return &segmentID{tag: Finalized}, nil - } - if blockId == "genesis" { - return &segmentID{tag: Genesis}, nil - } - slotMaybe, err := strconv.ParseUint(blockId, 10, 64) - if err == nil { - return &segmentID{slot: &slotMaybe}, nil - } - root := libcommon.HexToHash(blockId) - return &segmentID{ - root: &root, - }, nil -} - -func stateIdFromRequest(r *http.Request) (*segmentID, error) { - regex := regexp.MustCompile(`^(?:0x[0-9a-fA-F]{64}|head|finalized|genesis|justified|\d+)$`) - - stateId := chi.URLParam(r, "state_id") - if !regex.MatchString(stateId) { - return nil, fmt.Errorf("invalid path variable: {state_id}") - } - - if stateId == "head" { - return &segmentID{tag: Head}, nil - } - if stateId == "finalized" { - return &segmentID{tag: Finalized}, nil - } - if stateId == "genesis" { - return &segmentID{tag: Genesis}, nil - } - if stateId == "justified" { - return &segmentID{tag: Justified}, nil - } - slotMaybe, err := strconv.ParseUint(stateId, 10, 64) - if err == nil { - return &segmentID{slot: &slotMaybe}, nil - } - root := libcommon.HexToHash(stateId) - return &segmentID{ - root: &root, - }, nil -} - -func hashFromQueryParams(r *http.Request, name string) (*libcommon.Hash, error) { - hashStr := r.URL.Query().Get(name) - if hashStr == "" { - return nil, nil - } - // check if hashstr is an hex string - if len(hashStr) != 2+2*32 { - return nil, fmt.Errorf("invalid hash length") - } - if hashStr[:2] != "0x" { - return nil, fmt.Errorf("invalid hash prefix") - } - notHex, err := regexp.MatchString("[^0-9A-Fa-f]", hashStr[2:]) - if err != nil { - return nil, err - } - if notHex { - return nil, fmt.Errorf("invalid hash characters") - } - - hash := libcommon.HexToHash(hashStr) - return &hash, nil -} - -// uint64FromQueryParams retrieves a number from the query params, in base 10. -func uint64FromQueryParams(r *http.Request, name string) (*uint64, error) { - str := r.URL.Query().Get(name) - if str == "" { - return nil, nil - } - num, err := strconv.ParseUint(str, 10, 64) - if err != nil { - return nil, err - } - return &num, nil -} - -// decode a list of strings from the query params -func stringListFromQueryParams(r *http.Request, name string) ([]string, error) { - str := r.URL.Query().Get(name) - if str == "" { - return nil, nil - } - return regexp.MustCompile(`\s*,\s*`).Split(str, -1), nil +func newBeaconResponse(data any) *beaconhttp.BeaconResponse { + return beaconhttp.NewBeaconResponse(data) } diff --git a/cl/beacon/handler/genesis.go b/cl/beacon/handler/genesis.go index 3ca18d7dcda..562c65429d2 100644 --- a/cl/beacon/handler/genesis.go +++ b/cl/beacon/handler/genesis.go @@ -15,7 +15,7 @@ type genesisResponse struct { GenesisForkVersion libcommon.Bytes4 `json:"genesis_fork_version"` } -func (a *ApiHandler) getGenesis(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getGenesis(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { if a.genesisCfg == nil { return nil, beaconhttp.NewEndpointError(http.StatusNotFound, "Genesis Config is missing") } diff --git a/cl/beacon/handler/genesis_test.go b/cl/beacon/handler/genesis_test.go deleted file mode 100644 index 544830c86fd..00000000000 --- a/cl/beacon/handler/genesis_test.go +++ /dev/null @@ -1,35 +0,0 @@ -package handler - -import ( - "encoding/json" - "net/http" - "net/http/httptest" - "testing" - - "github.com/ledgerwatch/erigon/cl/clparams" - "github.com/stretchr/testify/require" -) - -func TestGetGenesis(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, _, _, _, _, handler, _, _, _ := setupTestingHandler(t, clparams.Phase0Version) - - server := httptest.NewServer(handler.mux) - defer server.Close() - - resp, err := http.Get(server.URL + "/eth/v1/beacon/genesis") - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, http.StatusOK, resp.StatusCode) - out := make(map[string]interface{}) - err = json.NewDecoder(resp.Body).Decode(&out) - require.NoError(t, err) - - data := out["data"].(map[string]interface{}) - genesisTime := data["genesis_time"].(string) - require.Equal(t, genesisTime, "1606824023") - require.Equal(t, data["genesis_fork_version"], "0xbba4da96") - require.Equal(t, data["genesis_validators_root"], "0x4b363db94e286120d76eb905340fdd4e54bfe9f06bf33ff6cf5ad27f511bfe95") -} diff --git a/cl/beacon/handler/handler.go b/cl/beacon/handler/handler.go index f0fe3bd5ad0..8328efdacff 100644 --- a/cl/beacon/handler/handler.go +++ b/cl/beacon/handler/handler.go @@ -44,6 +44,11 @@ func NewApiHandler(genesisConfig *clparams.GenesisConfig, beaconChainConfig *clp }}, sentinel: sentinel, version: version} } +func (a *ApiHandler) Init() { + a.o.Do(func() { + a.init() + }) +} func (a *ApiHandler) init() { r := chi.NewRouter() a.mux = r diff --git a/cl/beacon/handler/harness/attestation_rewards_bellatrix.yml b/cl/beacon/handler/harness/attestation_rewards_bellatrix.yml new file mode 100644 index 00000000000..66603735457 --- /dev/null +++ b/cl/beacon/handler/harness/attestation_rewards_bellatrix.yml @@ -0,0 +1,31 @@ +vars: + finalized_epoch: "99999999" + justified_slot: "160" + justified_epoch: "4" +tests: + ## blocks + - name: all validators + expect: + file: "attestations_1" + fs: td + actual: + handler: i + method: post + path: /eth/v1/beacon/rewards/attestations/{{.Vars.justified_epoch}} + - name: two validators + expect: + file: "attestations_2" + fs: td + actual: + handler: i + method: post + path: /eth/v1/beacon/rewards/attestations/{{.Vars.justified_epoch}} + body: + data: ["1","4"] + - name: not found + actual: + handler: i + method: post + path: /eth/v1/beacon/rewards/attestations/{{.Vars.finalized_epoch}} + compare: + expr: "actual_code == 404" diff --git a/cl/beacon/handler/harness/attestation_rewards_phase0.yml b/cl/beacon/handler/harness/attestation_rewards_phase0.yml new file mode 100644 index 00000000000..9ce844054c8 --- /dev/null +++ b/cl/beacon/handler/harness/attestation_rewards_phase0.yml @@ -0,0 +1,33 @@ +vars: + head_hash: '0xeffdd8ef40c3c901f0724d48e04ce257967cf1da31929f3b6db614f89ef8d660' + bad_hash: '0xbeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef' + finalized_epoch: "99999999" + justified_slot: "8322" + justified_epoch: "259" +tests: + ## blocks + - name: all validators + expect: + file: "attestations_3" + fs: td + actual: + handler: i + method: post + path: /eth/v1/beacon/rewards/attestations/{{.Vars.justified_epoch}} + - name: two validators + expect: + file: "attestations_4" + fs: td + actual: + handler: i + path: /eth/v1/beacon/rewards/attestations/{{.Vars.justified_epoch}} + method: post + body: + data: ["1","4"] + - name: not found + actual: + handler: i + method: post + path: /eth/v1/beacon/rewards/attestations/{{.Vars.finalized_epoch}} + compare: + expr: "actual_code == 404" diff --git a/cl/beacon/handler/harness/blocks.yml b/cl/beacon/handler/harness/blocks.yml new file mode 100644 index 00000000000..0961b45a3fe --- /dev/null +++ b/cl/beacon/handler/harness/blocks.yml @@ -0,0 +1,100 @@ +vars: + head_hash: '0xeffdd8ef40c3c901f0724d48e04ce257967cf1da31929f3b6db614f89ef8d660' + bad_hash: '0xbeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef' +tests: + ## blocks + - name: by hash + expect: + file: "block_1" + fs: td + actual: + handler: i + path: /eth/v2/beacon/blocks/{{.Vars.head_hash}} + - name: by head + expect: + file: "block_1" + fs: td + compare: + exprs: + - actual_code == 200 + - actual == expect + actual: + handler: i + path: /eth/v2/beacon/blocks/head + - name: not found + actual: + handler: i + path: /eth/v2/beacon/blocks/{{.Vars.bad_hash}} + compare: + expr: "actual_code == 404" + ## blinded blocks + - name: blinded by hash + expect: + file: "blinded_block_1" + fs: td + actual: + handler: i + path: /eth/v1/beacon/blinded_blocks/{{.Vars.head_hash}} + - name: blinded by head + expect: + file: "blinded_block_1" + fs: td + actual: + handler: i + path: /eth/v1/beacon/blinded_blocks/head + - name: blinded not found + actual: + handler: i + path: /eth/v1/beacon/blinded_blocks/{{.Vars.bad_hash}} + compare: + expr: "actual_code == 404" + ### attestations + - name: attestations by hash + expect: + file: "block_1" + fs: td + actual: + handler: i + path: /eth/v1/beacon/blocks/{{.Vars.head_hash}}/attestations + compare: + expr: "size(actual.data) == size(expect.data.message.body.attestations)" + - name: attestions by head + expect: + file: "block_1" + fs: td + actual: + handler: i + path: /eth/v1/beacon/blocks/head/attestations + compare: + exprs: + - actual_code == 200 + - size(actual.data) == size(expect.data.message.body.attestations) + - name: attestions not found + actual: + handler: i + path: /eth/v1/beacon/blocks/{{.Vars.bad_hash}}/attestations + compare: + expr: "actual_code == 404" + ### root + - name: root by hash + actual: + handler: i + path: /eth/v1/beacon/blocks/{{.Vars.head_hash}}/root + compare: + exprs: + - actual_code == 200 + - actual.data.root == "{{.Vars.head_hash}}" + - name: root by head + actual: + handler: i + path: /eth/v1/beacon/blocks/head/root + compare: + exprs: + - actual_code == 200 + - actual.data.root == "{{.Vars.head_hash}}" + - name: root not found + actual: + handler: i + path: /eth/v1/beacon/blocks/19912929/root + compare: + expr: "actual_code == 404" diff --git a/cl/beacon/handler/harness/committees.yml b/cl/beacon/handler/harness/committees.yml new file mode 100644 index 00000000000..268ef20ed1c --- /dev/null +++ b/cl/beacon/handler/harness/committees.yml @@ -0,0 +1,55 @@ +vars: + head_hash: '0xeffdd8ef40c3c901f0724d48e04ce257967cf1da31929f3b6db614f89ef8d660' + bad_hash: '0xbeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef' + post_root: '0x933d6650f2999f17012e781f5012981edb549e5935de1c981fce81cdd241d4e1' + head_slot: 8322 + head_epoch: "260" +tests: + - name: slot non antiquated + expect: + file: "committees_1" + fs: td + actual: + handler: i + path: /eth/v1/beacon/states/{{.Vars.post_root}}/committees + query: + slot: "8322" + compare: + exprs: + - "actual_code == 200" + - "expect[3] == actual" + - name: empty index non antiquated + expect: + file: "committees_1" + fs: td + actual: + handler: i + path: /eth/v1/beacon/states/{{.Vars.post_root}}/committees + query: + index: "1" + compare: + exprs: + - "actual_code == 200" + - "expect[4] == actual" + - name: all queries non antiquated + expect: + file: "committees_1" + fs: td + actual: + handler: i + path: /eth/v1/beacon/states/{{.Vars.post_root}}/committees + query: + index: "0" + slot: "{{sub .Vars.head_slot 32}}" + epoch: "{{sub .Vars.head_epoch 1}}" + compare: + exprs: + - "actual_code == 200" + - "expect[5] == actual" + - name: 404 non antiquated + actual: + handler: i + path: /eth/v1/beacon/states/{{.Vars.bad_hash}}/committees + compare: + exprs: + - "actual_code == 404" diff --git a/cl/beacon/handler/harness/committees_f.yml b/cl/beacon/handler/harness/committees_f.yml new file mode 100644 index 00000000000..f71de0b3958 --- /dev/null +++ b/cl/beacon/handler/harness/committees_f.yml @@ -0,0 +1,55 @@ +vars: + head_hash: '0xeffdd8ef40c3c901f0724d48e04ce257967cf1da31929f3b6db614f89ef8d660' + bad_hash: '0xbeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef' + post_root: '0x933d6650f2999f17012e781f5012981edb549e5935de1c981fce81cdd241d4e1' + head_slot: 8322 + head_epoch: "260" +tests: + - name: slot + expect: + file: "committees_1" + fs: td + actual: + handler: i + path: /eth/v1/beacon/states/{{.Vars.post_root}}/committees + query: + slot: "8322" + compare: + exprs: + - "actual_code == 200" + - "expect[0] == actual" + - name: empty index + expect: + file: "committees_1" + fs: td + actual: + handler: i + path: /eth/v1/beacon/states/{{.Vars.post_root}}/committees + query: + index: "1" + compare: + exprs: + - "actual_code == 200" + - "expect[1] == actual" + - name: all queries + expect: + file: "committees_1" + fs: td + actual: + handler: i + path: /eth/v1/beacon/states/{{.Vars.post_root}}/committees + query: + index: "0" + slot: "{{sub .Vars.head_slot 32}}" + epoch: "{{sub .Vars.head_epoch 1}}" + compare: + exprs: + - "actual_code == 200" + - "expect[2] == actual" + - name: "404" + actual: + handler: i + path: /eth/v1/beacon/states/{{.Vars.bad_hash}}/committees + compare: + exprs: + - "actual_code == 404" diff --git a/cl/beacon/handler/harness/config.yml b/cl/beacon/handler/harness/config.yml new file mode 100644 index 00000000000..e9910ba5c6a --- /dev/null +++ b/cl/beacon/handler/harness/config.yml @@ -0,0 +1,32 @@ +tests: + - name: spec + actual: + handler: i + path: /eth/v1/config/spec + compare: + exprs: + - actual_code == 200 + - actual.data.SlotsPerEpoch == 32 + - actual.data.SlotsPerHistoricalRoot == 8192 + - name: fork schedule + actual: + handler: i + path: /eth/v1/config/fork_schedule + compare: + exprs: + - actual_code == 200 + - has(actual.data[0].current_version) + - has(actual.data[0].previous_version) + - has(actual.data[0].epoch) + - has(actual.data[1].current_version) + - has(actual.data[1].previous_version) + - has(actual.data[1].epoch) + - name: deposit contract + actual: + handler: i + path: /eth/v1/config/deposit_contract + compare: + exprs: + - actual_code == 200 + - actual.data.address == "0x00000000219ab540356cBB839Cbe05303d7705Fa" + - actual.data.chain_id == "1" diff --git a/cl/beacon/handler/harness/duties_attester.yml b/cl/beacon/handler/harness/duties_attester.yml new file mode 100644 index 00000000000..840927438ba --- /dev/null +++ b/cl/beacon/handler/harness/duties_attester.yml @@ -0,0 +1,45 @@ +vars: + head_hash: '0xeffdd8ef40c3c901f0724d48e04ce257967cf1da31929f3b6db614f89ef8d660' + bad_hash: '0xbeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef' + post_root: '0x933d6650f2999f17012e781f5012981edb549e5935de1c981fce81cdd241d4e1' + head_slot: 8322 + head_epoch: "260" +tests: + - name: non empty indices + expect: + file: "duties_1" + fs: td + actual: + handler: i + path: /eth/v1/validator/duties/attester/{{.Vars.head_epoch}} + method: post + body: + data: ["0","1","2","3","4","5","6","7","8","9"] + compare: + exprs: + - "actual_code == 200" + - "expect[0] == actual" + - name: empty index + expect: + file: "duties_1" + fs: td + actual: + handler: i + path: /eth/v1/validator/duties/attester/{{.Vars.head_epoch}} + method: post + body: + data: [] + compare: + exprs: + - "actual_code == 200" + - "expect[1] == actual" + - name: 400 non antiquated + actual: + handler: i + path: /eth/v1/validator/duties/attester/999999999 + method: post + body: + data: ["0","1","2","3","4","5","6","7","8","9"] + compare: + exprs: + - "actual_code == 400" diff --git a/cl/beacon/handler/harness/duties_attester_f.yml b/cl/beacon/handler/harness/duties_attester_f.yml new file mode 100644 index 00000000000..840927438ba --- /dev/null +++ b/cl/beacon/handler/harness/duties_attester_f.yml @@ -0,0 +1,45 @@ +vars: + head_hash: '0xeffdd8ef40c3c901f0724d48e04ce257967cf1da31929f3b6db614f89ef8d660' + bad_hash: '0xbeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef' + post_root: '0x933d6650f2999f17012e781f5012981edb549e5935de1c981fce81cdd241d4e1' + head_slot: 8322 + head_epoch: "260" +tests: + - name: non empty indices + expect: + file: "duties_1" + fs: td + actual: + handler: i + path: /eth/v1/validator/duties/attester/{{.Vars.head_epoch}} + method: post + body: + data: ["0","1","2","3","4","5","6","7","8","9"] + compare: + exprs: + - "actual_code == 200" + - "expect[0] == actual" + - name: empty index + expect: + file: "duties_1" + fs: td + actual: + handler: i + path: /eth/v1/validator/duties/attester/{{.Vars.head_epoch}} + method: post + body: + data: [] + compare: + exprs: + - "actual_code == 200" + - "expect[1] == actual" + - name: 400 non antiquated + actual: + handler: i + path: /eth/v1/validator/duties/attester/999999999 + method: post + body: + data: ["0","1","2","3","4","5","6","7","8","9"] + compare: + exprs: + - "actual_code == 400" diff --git a/cl/beacon/handler/harness/duties_proposer.yml b/cl/beacon/handler/harness/duties_proposer.yml new file mode 100644 index 00000000000..30bded64f3a --- /dev/null +++ b/cl/beacon/handler/harness/duties_proposer.yml @@ -0,0 +1,42 @@ +vars: + head_hash: '0xeffdd8ef40c3c901f0724d48e04ce257967cf1da31929f3b6db614f89ef8d660' + bad_hash: '0xbeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef' + post_root: '0x933d6650f2999f17012e781f5012981edb549e5935de1c981fce81cdd241d4e1' + head_slot: 8322 + head_epoch: "260" +tests: + - name: proposer duties + actual: + handler: i + path: /eth/v1/validator/duties/proposer/{{.Vars.head_epoch}} + compare: + exprs: + - actual_code == 200 + - size(actual.data) == 32 + - has(actual.data[0].pubkey) + - has(actual.data[0].validator_index) + - has(actual.data[0].slot) + - name: proposer bad epoch + actual: + handler: i + path: /eth/v1/validator/duties/proposer/abc + compare: + expr: "actual_code == 400" + + - name: proposer duties not synced + actual: + handler: i + path: /eth/v1/validator/duties/proposer/1 + compare: + expr: "actual_code == 503" + - name: fcu historical + actual: + handler: i + path: /eth/v1/validator/duties/proposer/{{sub .Vars.head_epoch 1}} + compare: + exprs: + - actual_code == 200 + - size(actual.data) == 32 + - has(actual.data[0].pubkey) + - has(actual.data[0].validator_index) + - has(actual.data[0].slot) diff --git a/cl/beacon/handler/harness/duties_sync_bellatrix.yml b/cl/beacon/handler/harness/duties_sync_bellatrix.yml new file mode 100644 index 00000000000..5d19789235f --- /dev/null +++ b/cl/beacon/handler/harness/duties_sync_bellatrix.yml @@ -0,0 +1,43 @@ +vars: + finalized_epoch: 99999999 + head_slot: 160 + head_epoch: 4 +tests: + - name: non empty indices + expect: + file: "duties_sync_1" + fs: td + actual: + handler: i + path: /eth/v1/validator/duties/sync/{{.Vars.head_epoch}} + method: post + body: + data: ["0","1","2","3","4","5","6","7","8","9"] + compare: + exprs: + - "actual_code == 200" + - "expect[0] == actual" + - name: empty index + expect: + file: "duties_sync_1" + fs: td + actual: + handler: i + path: /eth/v1/validator/duties/sync/{{.Vars.head_epoch}} + method: post + body: + data: [] + compare: + exprs: + - "actual_code == 200" + - "expect[1] == actual" + - name: "404 giant epoch" + actual: + handler: i + path: /eth/v1/validator/duties/sync/999999999 + method: post + body: + data: ["0","1","2","3","4","5","6","7","8","9"] + compare: + exprs: + - "actual_code == 404" diff --git a/cl/beacon/handler/harness/fork_choice.yml b/cl/beacon/handler/harness/fork_choice.yml new file mode 100644 index 00000000000..3c1c97b8256 --- /dev/null +++ b/cl/beacon/handler/harness/fork_choice.yml @@ -0,0 +1,24 @@ +vars: +tests: + - name: get fork choice + expect: + file: "forkchoice_1" + fs: td + actual: + handler: i + path: /eth/v2/debug/beacon/heads + compare: + exprs: + - "actual_code == 200" + - "actual == expect[0]" + - name: get heads + expect: + file: "forkchoice_1" + fs: td + actual: + handler: i + path: /eth/v1/debug/fork_choice + compare: + exprs: + - "actual_code == 200" + - "actual == expect[1]" diff --git a/cl/beacon/handler/harness/headers.yml b/cl/beacon/handler/harness/headers.yml new file mode 100644 index 00000000000..38a6a9fbfaa --- /dev/null +++ b/cl/beacon/handler/harness/headers.yml @@ -0,0 +1,38 @@ +vars: + head_hash: '0xeffdd8ef40c3c901f0724d48e04ce257967cf1da31929f3b6db614f89ef8d660' + post_root: '0x933d6650f2999f17012e781f5012981edb549e5935de1c981fce81cdd241d4e1' + bad_hash: '0xbeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeef' + head_slot: 8322 + first_slot: 8288 + head_epoch: "260" + body_root_1: "0x8d07005613673b3684b527f9c4dab5191403177e79b0e0bc1d58f15021abab19" + body_root_2: "0xa6957819a5055b6d760c1b2ec034522cc033a7dd94c743ed936d8f8d0eb5ccce" + block_1_hash: "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" +tests: + - name: not head + actual: + handler: i + path: /eth/v1/beacon/headers/{{.Vars.block_1_hash}} + compare: + exprs: + - actual_code == 200 + - actual.data.canonical == true + - actual.data.header.message.body_root == "{{.Vars.body_root_1}}" + - actual.data.header.message.slot == "{{.Vars.first_slot}}" + - name: head + actual: + handler: i + path: /eth/v1/beacon/headers/head + compare: + exprs: + - actual_code == 200 + - actual.data.canonical == true + - actual.data.header.message.body_root == "{{.Vars.body_root_2}}" + - actual.data.header.message.slot == "{{.Vars.head_slot}}" + - name: not head + actual: + handler: i + path: /eth/v1/beacon/headers/{{.Vars.bad_hash}} + compare: + exprs: + - actual_code == 404 diff --git a/cl/beacon/handler/harness/liveness.yml b/cl/beacon/handler/harness/liveness.yml new file mode 100644 index 00000000000..4d793f7dff9 --- /dev/null +++ b/cl/beacon/handler/harness/liveness.yml @@ -0,0 +1,13 @@ +tests: + - name: spec + actual: + handler: i + path: /eth/v1/validator/liveness/260 + method: post + body: + data: ["0","1","2","3","4","5","6","7","8","9","10"] + compare: + exprs: + - "actual_code==200" + - "size(actual.data) == 11" + - "actual.data.all(x,has(x.is_live) && has(x.index))" diff --git a/cl/beacon/handler/harness_test.go b/cl/beacon/handler/harness_test.go new file mode 100644 index 00000000000..8c0086a09cc --- /dev/null +++ b/cl/beacon/handler/harness_test.go @@ -0,0 +1,53 @@ +package handler_test + +import ( + "testing" + + "github.com/ledgerwatch/erigon/cl/beacon/beacontest" + "github.com/ledgerwatch/erigon/cl/clparams" + + _ "embed" +) + +func TestHarnessPhase0(t *testing.T) { + beacontest.Execute( + append( + defaultHarnessOpts(harnessConfig{t: t, v: clparams.Phase0Version}), + beacontest.WithTestFromFs(Harnesses, "blocks"), + beacontest.WithTestFromFs(Harnesses, "config"), + beacontest.WithTestFromFs(Harnesses, "headers"), + beacontest.WithTestFromFs(Harnesses, "attestation_rewards_phase0"), + beacontest.WithTestFromFs(Harnesses, "committees"), + beacontest.WithTestFromFs(Harnesses, "duties_attester"), + beacontest.WithTestFromFs(Harnesses, "duties_proposer"), + )..., + ) +} +func TestHarnessPhase0Finalized(t *testing.T) { + beacontest.Execute( + append( + defaultHarnessOpts(harnessConfig{t: t, v: clparams.Phase0Version, finalized: true}), + beacontest.WithTestFromFs(Harnesses, "liveness"), + beacontest.WithTestFromFs(Harnesses, "duties_attester_f"), + beacontest.WithTestFromFs(Harnesses, "committees_f"), + )..., + ) +} + +func TestHarnessBellatrix(t *testing.T) { + beacontest.Execute( + append( + defaultHarnessOpts(harnessConfig{t: t, v: clparams.BellatrixVersion, finalized: true}), + beacontest.WithTestFromFs(Harnesses, "attestation_rewards_bellatrix"), + beacontest.WithTestFromFs(Harnesses, "duties_sync_bellatrix"), + )..., + ) +} +func TestHarnessForkChoice(t *testing.T) { + beacontest.Execute( + append( + defaultHarnessOpts(harnessConfig{t: t, v: clparams.BellatrixVersion, forkmode: 1}), + beacontest.WithTestFromFs(Harnesses, "fork_choice"), + )..., + ) +} diff --git a/cl/beacon/handler/headers.go b/cl/beacon/handler/headers.go index 462cdf5cf6f..43c9a66850f 100644 --- a/cl/beacon/handler/headers.go +++ b/cl/beacon/handler/headers.go @@ -9,14 +9,14 @@ import ( "github.com/ledgerwatch/erigon/cl/persistence/beacon_indicies" ) -func (a *ApiHandler) getHeaders(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getHeaders(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { ctx := r.Context() - querySlot, err := uint64FromQueryParams(r, "slot") + querySlot, err := beaconhttp.Uint64FromQueryParams(r, "slot") if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } - queryParentHash, err := hashFromQueryParams(r, "parent_root") + queryParentHash, err := beaconhttp.HashFromQueryParams(r, "parent_root") if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } @@ -89,14 +89,14 @@ func (a *ApiHandler) getHeaders(w http.ResponseWriter, r *http.Request) (*beacon return newBeaconResponse(headers), nil } -func (a *ApiHandler) getHeader(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getHeader(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { ctx := r.Context() tx, err := a.indiciesDB.BeginRo(ctx) if err != nil { return nil, err } defer tx.Rollback() - blockId, err := blockIdFromRequest(r) + blockId, err := beaconhttp.BlockIdFromRequest(r) if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } @@ -125,5 +125,5 @@ func (a *ApiHandler) getHeader(w http.ResponseWriter, r *http.Request) (*beaconR Root: root, Canonical: canonicalRoot == root, Header: signedHeader, - }).withFinalized(canonicalRoot == root && signedHeader.Header.Slot <= a.forkchoiceStore.FinalizedSlot()).withVersion(version), nil + }).WithFinalized(canonicalRoot == root && signedHeader.Header.Slot <= a.forkchoiceStore.FinalizedSlot()).WithVersion(version), nil } diff --git a/cl/beacon/handler/headers_test.go b/cl/beacon/handler/headers_test.go deleted file mode 100644 index 25efb1a2ca5..00000000000 --- a/cl/beacon/handler/headers_test.go +++ /dev/null @@ -1,180 +0,0 @@ -//go:build integration - -package handler - -import ( - "encoding/json" - "net/http" - "net/http/httptest" - "strconv" - "testing" - - libcommon "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon/cl/clparams" - "github.com/ledgerwatch/erigon/common" - "github.com/stretchr/testify/require" -) - -func TestGetHeader(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, _, handler, _, _, fcu := setupTestingHandler(t, clparams.Phase0Version) - - // Start by testing - rootBlock1, err := blocks[0].Block.HashSSZ() - if err != nil { - t.Fatal(err) - } - - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - - bodyRoot1, err := blocks[0].Block.Body.HashSSZ() - require.NoError(t, err) - - bodyRoot2, err := blocks[len(blocks)-1].Block.Body.HashSSZ() - require.NoError(t, err) - - cases := []struct { - blockID string - code int - slot uint64 - bodyRoot string - }{ - { - blockID: "0x" + common.Bytes2Hex(rootBlock1[:]), - code: http.StatusOK, - slot: blocks[0].Block.Slot, - bodyRoot: "0x" + common.Bytes2Hex(bodyRoot1[:]), - }, - { - blockID: "head", - code: http.StatusOK, - slot: blocks[len(blocks)-1].Block.Slot, - bodyRoot: "0x" + common.Bytes2Hex(bodyRoot2[:]), - }, - { - blockID: "0x" + common.Bytes2Hex(make([]byte, 32)), - code: http.StatusNotFound, - }, - } - - for _, c := range cases { - t.Run(c.blockID, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - // Query the block in the handler with /eth/v2/beacon/blocks/{block_id} - resp, err := http.Get(server.URL + "/eth/v1/beacon/headers/" + c.blockID) - require.NoError(t, err) - defer resp.Body.Close() - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - jsonVal := make(map[string]interface{}) - // unmarshal the json - require.NoError(t, json.NewDecoder(resp.Body).Decode(&jsonVal)) - data := jsonVal["data"].(map[string]interface{}) - header := data["header"].(map[string]interface{}) - message := header["message"].(map[string]interface{}) - - // compare the block - require.Equal(t, message["slot"], strconv.FormatInt(int64(c.slot), 10)) - require.Equal(t, message["body_root"], c.bodyRoot) - require.Equal(t, data["canonical"], true) - }) - } -} - -func TestGetHeaders(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, _, handler, _, _, fcu := setupTestingHandler(t, clparams.Phase0Version) - - var err error - - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - - bodyRoot1, err := blocks[0].Block.Body.HashSSZ() - require.NoError(t, err) - - bodyRoot2, err := blocks[len(blocks)-1].Block.Body.HashSSZ() - require.NoError(t, err) - - cases := []struct { - name string - code int - slotReq *uint64 - parentRoot *libcommon.Hash - slot uint64 - bodyRoot string - count int - }{ - { - count: 1, - name: "slot", - code: http.StatusOK, - slotReq: &blocks[0].Block.Slot, - slot: blocks[0].Block.Slot, - bodyRoot: "0x" + common.Bytes2Hex(bodyRoot1[:]), - }, - { - count: 0, - name: "none", - code: http.StatusOK, - slot: blocks[len(blocks)-1].Block.Slot, - bodyRoot: "0x" + common.Bytes2Hex(bodyRoot2[:]), - }, - { - count: 0, - name: "parent", - code: http.StatusOK, - slotReq: &blocks[0].Block.Slot, - slot: blocks[0].Block.Slot, - parentRoot: &blocks[0].Block.ParentRoot, - bodyRoot: "0x" + common.Bytes2Hex(bodyRoot1[:]), - }, - { - count: 0, - name: "wtf", - code: http.StatusOK, - slotReq: new(uint64), - slot: blocks[0].Block.Slot, - parentRoot: &blocks[0].Block.ParentRoot, - bodyRoot: "0x" + common.Bytes2Hex(bodyRoot1[:]), - }, - } - - for _, c := range cases { - t.Run(c.name, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - url := server.URL + "/eth/v1/beacon/headers?lol=0" // lol is a random query param - - if c.slotReq != nil { - url += "&slot=" + strconv.FormatInt(int64(*c.slotReq), 10) - } - if c.parentRoot != nil { - url += "&parent_root=" + "0x" + common.Bytes2Hex(c.parentRoot[:]) - } - // Query the block in the handler with /eth/v2/beacon/blocks/{block_id} - resp, err := http.Get(url) - require.NoError(t, err) - defer resp.Body.Close() - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - jsonVal := make(map[string]interface{}) - // unmarshal the json - require.NoError(t, json.NewDecoder(resp.Body).Decode(&jsonVal)) - data := jsonVal["data"].([]interface{}) - require.Equal(t, len(data), c.count) - }) - } -} diff --git a/cl/beacon/handler/liveness.go b/cl/beacon/handler/liveness.go index f6b8bd4b519..99ec031d831 100644 --- a/cl/beacon/handler/liveness.go +++ b/cl/beacon/handler/liveness.go @@ -20,8 +20,8 @@ type live struct { IsLive bool `json:"is_live"` } -func (a *ApiHandler) liveness(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { - epoch, err := epochFromRequest(r) +func (a *ApiHandler) liveness(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { + epoch, err := beaconhttp.EpochFromRequest(r) if err != nil { return nil, err } diff --git a/cl/beacon/handler/liveness_test.go b/cl/beacon/handler/liveness_test.go deleted file mode 100644 index 73bb5deec91..00000000000 --- a/cl/beacon/handler/liveness_test.go +++ /dev/null @@ -1,62 +0,0 @@ -package handler - -import ( - "bytes" - "encoding/json" - "math" - "net/http" - "net/http/httptest" - "strconv" - "testing" - - "github.com/ledgerwatch/erigon/cl/clparams" - "github.com/ledgerwatch/erigon/cl/cltypes/solid" - "github.com/stretchr/testify/require" -) - -func TestLiveness(t *testing.T) { - // i just want the correct schema to be generated - _, blocks, _, _, _, handler, _, _, fcu := setupTestingHandler(t, clparams.Phase0Version) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) - fcu.FinalizedSlotVal = math.MaxUint64 - reqBody := `["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]` - server := httptest.NewServer(handler.mux) - defer server.Close() - // - body := bytes.Buffer{} - body.WriteString(reqBody) - // Query the block in the handler with /eth/v2/beacon/states/{block_id} with content-type octet-stream - req, err := http.NewRequest("POST", server.URL+"/eth/v1/validator/liveness/"+strconv.FormatUint(fcu.HeadSlotVal/32, 10), &body) - require.NoError(t, err) - - resp, err := http.DefaultClient.Do(req) - require.NoError(t, err) - - defer resp.Body.Close() - require.Equal(t, http.StatusOK, resp.StatusCode) - - out := map[string]interface{}{} - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) - data := out["data"].([]interface{}) - require.Equal(t, 11, len(data)) - // check that is has is_live (bool) and index (stringifed int) - for _, d := range data { - d := d.(map[string]interface{}) - require.Equal(t, 2, len(d)) - isLive, ok := d["is_live"] - require.True(t, ok) - _, ok = isLive.(bool) - require.True(t, ok) - i1, ok := d["index"] - require.True(t, ok) - strIndex, ok := i1.(string) - require.True(t, ok) - _, err := strconv.ParseUint(strIndex, 10, 64) - require.NoError(t, err) - - } - -} diff --git a/cl/beacon/handler/node.go b/cl/beacon/handler/node.go index 72687b2e371..063adacdeb5 100644 --- a/cl/beacon/handler/node.go +++ b/cl/beacon/handler/node.go @@ -5,10 +5,12 @@ import ( "fmt" "net/http" "runtime" + + "github.com/ledgerwatch/erigon/cl/beacon/beaconhttp" ) func (a *ApiHandler) GetEthV1NodeHealth(w http.ResponseWriter, r *http.Request) { - syncingStatus, err := uint64FromQueryParams(r, "syncing_status") + syncingStatus, err := beaconhttp.Uint64FromQueryParams(r, "syncing_status") if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return diff --git a/cl/beacon/handler/node_test.go b/cl/beacon/handler/node_test.go deleted file mode 100644 index 8572f1430fa..00000000000 --- a/cl/beacon/handler/node_test.go +++ /dev/null @@ -1,71 +0,0 @@ -package handler - -import ( - "encoding/json" - "net/http" - "net/http/httptest" - "strings" - "testing" - - "github.com/ledgerwatch/erigon/cl/clparams" - "github.com/stretchr/testify/require" -) - -func TestNodeHealthSyncing(t *testing.T) { - // i just want the correct schema to be generated - _, _, _, _, _, handler, _, _, _ := setupTestingHandler(t, clparams.Phase0Version) - - // Call GET /eth/v1/node/health - server := httptest.NewServer(handler.mux) - defer server.Close() - - req, err := http.NewRequest("GET", server.URL+"/eth/v1/node/health?syncing_status=666", nil) - require.NoError(t, err) - - resp, err := http.DefaultClient.Do(req) - require.NoError(t, err) - defer resp.Body.Close() - require.Equal(t, 666, resp.StatusCode) -} - -func TestNodeHealthSyncingTip(t *testing.T) { - // i just want the correct schema to be generated - _, _, _, _, post, handler, _, sm, _ := setupTestingHandler(t, clparams.Phase0Version) - - // Call GET /eth/v1/node/health - server := httptest.NewServer(handler.mux) - defer server.Close() - - req, err := http.NewRequest("GET", server.URL+"/eth/v1/node/health?syncing_status=666", nil) - require.NoError(t, err) - - require.NoError(t, sm.OnHeadState(post)) - s, cancel := sm.HeadState() - s.SetSlot(999999999999999) - cancel() - - resp, err := http.DefaultClient.Do(req) - require.NoError(t, err) - defer resp.Body.Close() - require.Equal(t, 200, resp.StatusCode) -} - -func TestNodeVersion(t *testing.T) { - // i just want the correct schema to be generated - _, _, _, _, _, handler, _, _, _ := setupTestingHandler(t, clparams.Phase0Version) - - // Call GET /eth/v1/node/health - server := httptest.NewServer(handler.mux) - defer server.Close() - - req, err := http.NewRequest("GET", server.URL+"/eth/v1/node/version", nil) - require.NoError(t, err) - - resp, err := http.DefaultClient.Do(req) - require.NoError(t, err) - defer resp.Body.Close() - out := map[string]interface{}{} - require.NoError(t, json.NewDecoder(resp.Body).Decode(&out)) - v := out["data"].(map[string]interface{})["version"].(string) - require.True(t, strings.Contains(v, "Caplin")) -} diff --git a/cl/beacon/handler/pool.go b/cl/beacon/handler/pool.go index e96549e6b04..6b3a07af7b0 100644 --- a/cl/beacon/handler/pool.go +++ b/cl/beacon/handler/pool.go @@ -11,29 +11,29 @@ import ( "github.com/ledgerwatch/erigon/cl/gossip" ) -func (a *ApiHandler) GetEthV1BeaconPoolVoluntaryExits(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) GetEthV1BeaconPoolVoluntaryExits(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { return newBeaconResponse(a.operationsPool.VoluntaryExistsPool.Raw()), nil } -func (a *ApiHandler) GetEthV1BeaconPoolAttesterSlashings(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) GetEthV1BeaconPoolAttesterSlashings(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { fmt.Println("GetEthV1BeaconPoolAttesterSlashings", a.operationsPool.AttesterSlashingsPool.Raw()) return newBeaconResponse(a.operationsPool.AttesterSlashingsPool.Raw()), nil } -func (a *ApiHandler) GetEthV1BeaconPoolProposerSlashings(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) GetEthV1BeaconPoolProposerSlashings(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { return newBeaconResponse(a.operationsPool.ProposerSlashingsPool.Raw()), nil } -func (a *ApiHandler) GetEthV1BeaconPoolBLSExecutionChanges(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) GetEthV1BeaconPoolBLSExecutionChanges(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { return newBeaconResponse(a.operationsPool.BLSToExecutionChangesPool.Raw()), nil } -func (a *ApiHandler) GetEthV1BeaconPoolAttestations(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { - slot, err := uint64FromQueryParams(r, "slot") +func (a *ApiHandler) GetEthV1BeaconPoolAttestations(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { + slot, err := beaconhttp.Uint64FromQueryParams(r, "slot") if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } - committeeIndex, err := uint64FromQueryParams(r, "committee_index") + committeeIndex, err := beaconhttp.Uint64FromQueryParams(r, "committee_index") if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } diff --git a/cl/beacon/handler/pool_test.go b/cl/beacon/handler/pool_test.go deleted file mode 100644 index c715162af00..00000000000 --- a/cl/beacon/handler/pool_test.go +++ /dev/null @@ -1,248 +0,0 @@ -//go:build integration - -package handler - -import ( - "bytes" - "encoding/json" - "net/http/httptest" - "testing" - - libcommon "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon/cl/clparams" - "github.com/ledgerwatch/erigon/cl/cltypes" - "github.com/ledgerwatch/erigon/cl/cltypes/solid" - "github.com/stretchr/testify/require" -) - -func TestPoolAttesterSlashings(t *testing.T) { - attesterSlashing := &cltypes.AttesterSlashing{ - Attestation_1: &cltypes.IndexedAttestation{ - AttestingIndices: solid.NewRawUint64List(2048, []uint64{2, 3, 4, 5, 6}), - Data: solid.NewAttestationData(), - }, - Attestation_2: &cltypes.IndexedAttestation{ - AttestingIndices: solid.NewRawUint64List(2048, []uint64{2, 3, 4, 1, 6}), - Data: solid.NewAttestationData(), - }, - } - // find server - _, _, _, _, _, handler, _, _, _ := setupTestingHandler(t, clparams.Phase0Version) - - server := httptest.NewServer(handler.mux) - defer server.Close() - // json - req, err := json.Marshal(attesterSlashing) - require.NoError(t, err) - // post attester slashing - resp, err := server.Client().Post(server.URL+"/eth/v1/beacon/pool/attester_slashings", "application/json", bytes.NewBuffer(req)) - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, 200, resp.StatusCode) - // get attester slashings - resp, err = server.Client().Get(server.URL + "/eth/v1/beacon/pool/attester_slashings") - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, 200, resp.StatusCode) - out := struct { - Data []*cltypes.AttesterSlashing `json:"data"` - }{ - Data: []*cltypes.AttesterSlashing{ - cltypes.NewAttesterSlashing(), - }, - } - - err = json.NewDecoder(resp.Body).Decode(&out) - require.NoError(t, err) - - require.Equal(t, 1, len(out.Data)) - require.Equal(t, attesterSlashing, out.Data[0]) -} - -func TestPoolProposerSlashings(t *testing.T) { - proposerSlashing := &cltypes.ProposerSlashing{ - Header1: &cltypes.SignedBeaconBlockHeader{ - Header: &cltypes.BeaconBlockHeader{ - Slot: 1, - ProposerIndex: 3, - }, - }, - Header2: &cltypes.SignedBeaconBlockHeader{ - Header: &cltypes.BeaconBlockHeader{ - Slot: 2, - ProposerIndex: 4, - }, - }, - } - // find server - _, _, _, _, _, handler, _, _, _ := setupTestingHandler(t, clparams.Phase0Version) - - server := httptest.NewServer(handler.mux) - defer server.Close() - // json - req, err := json.Marshal(proposerSlashing) - require.NoError(t, err) - - // post attester slashing - resp, err := server.Client().Post(server.URL+"/eth/v1/beacon/pool/proposer_slashings", "application/json", bytes.NewBuffer(req)) - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, 200, resp.StatusCode) - // get attester slashings - resp, err = server.Client().Get(server.URL + "/eth/v1/beacon/pool/proposer_slashings") - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, 200, resp.StatusCode) - out := struct { - Data []*cltypes.ProposerSlashing `json:"data"` - }{ - Data: []*cltypes.ProposerSlashing{}, - } - - err = json.NewDecoder(resp.Body).Decode(&out) - require.NoError(t, err) - - require.Equal(t, 1, len(out.Data)) - require.Equal(t, proposerSlashing, out.Data[0]) -} - -func TestPoolVoluntaryExits(t *testing.T) { - voluntaryExit := &cltypes.SignedVoluntaryExit{ - VoluntaryExit: &cltypes.VoluntaryExit{ - Epoch: 1, - ValidatorIndex: 3, - }, - } - // find server - _, _, _, _, _, handler, _, _, _ := setupTestingHandler(t, clparams.Phase0Version) - - server := httptest.NewServer(handler.mux) - defer server.Close() - // json - req, err := json.Marshal(voluntaryExit) - require.NoError(t, err) - // post attester slashing - resp, err := server.Client().Post(server.URL+"/eth/v1/beacon/pool/voluntary_exits", "application/json", bytes.NewBuffer(req)) - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, 200, resp.StatusCode) - // get attester slashings - resp, err = server.Client().Get(server.URL + "/eth/v1/beacon/pool/voluntary_exits") - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, 200, resp.StatusCode) - out := struct { - Data []*cltypes.SignedVoluntaryExit `json:"data"` - }{ - Data: []*cltypes.SignedVoluntaryExit{}, - } - - err = json.NewDecoder(resp.Body).Decode(&out) - require.NoError(t, err) - - require.Equal(t, 1, len(out.Data)) - require.Equal(t, voluntaryExit, out.Data[0]) -} - -func TestPoolBlsToExecutionChainges(t *testing.T) { - msg := []*cltypes.SignedBLSToExecutionChange{ - { - Message: &cltypes.BLSToExecutionChange{ - ValidatorIndex: 45, - }, - Signature: libcommon.Bytes96{2}, - }, - { - Message: &cltypes.BLSToExecutionChange{ - ValidatorIndex: 46, - }, - }, - } - // find server - _, _, _, _, _, handler, _, _, _ := setupTestingHandler(t, clparams.Phase0Version) - - server := httptest.NewServer(handler.mux) - defer server.Close() - // json - req, err := json.Marshal(msg) - require.NoError(t, err) - // post attester slashing - resp, err := server.Client().Post(server.URL+"/eth/v1/beacon/pool/bls_to_execution_changes", "application/json", bytes.NewBuffer(req)) - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, 200, resp.StatusCode) - // get attester slashings - resp, err = server.Client().Get(server.URL + "/eth/v1/beacon/pool/bls_to_execution_changes") - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, 200, resp.StatusCode) - out := struct { - Data []*cltypes.SignedBLSToExecutionChange `json:"data"` - }{ - Data: []*cltypes.SignedBLSToExecutionChange{}, - } - - err = json.NewDecoder(resp.Body).Decode(&out) - require.NoError(t, err) - - require.Equal(t, 2, len(out.Data)) - require.Equal(t, msg[0], out.Data[0]) - require.Equal(t, msg[1], out.Data[1]) -} - -func TestPoolAggregatesAndProofs(t *testing.T) { - msg := []*cltypes.SignedAggregateAndProof{ - { - Message: &cltypes.AggregateAndProof{ - Aggregate: solid.NewAttestionFromParameters([]byte{1, 2}, solid.NewAttestationData(), libcommon.Bytes96{3, 45, 6}), - }, - Signature: libcommon.Bytes96{2}, - }, - { - Message: &cltypes.AggregateAndProof{ - Aggregate: solid.NewAttestionFromParameters([]byte{1, 2, 5, 6}, solid.NewAttestationData(), libcommon.Bytes96{3, 0, 6}), - }, - Signature: libcommon.Bytes96{2, 3, 5}, - }, - } - // find server - _, _, _, _, _, handler, _, _, _ := setupTestingHandler(t, clparams.Phase0Version) - - server := httptest.NewServer(handler.mux) - defer server.Close() - // json - req, err := json.Marshal(msg) - require.NoError(t, err) - // post attester slashing - resp, err := server.Client().Post(server.URL+"/eth/v1/validator/aggregate_and_proofs", "application/json", bytes.NewBuffer(req)) - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, 200, resp.StatusCode) - // get attester slashings - resp, err = server.Client().Get(server.URL + "/eth/v1/beacon/pool/attestations") - require.NoError(t, err) - defer resp.Body.Close() - - require.Equal(t, 200, resp.StatusCode) - out := struct { - Data []*solid.Attestation `json:"data"` - }{ - Data: []*solid.Attestation{}, - } - - err = json.NewDecoder(resp.Body).Decode(&out) - require.NoError(t, err) - - require.Equal(t, 2, len(out.Data)) - require.Equal(t, msg[0].Message.Aggregate, out.Data[0]) - require.Equal(t, msg[1].Message.Aggregate, out.Data[1]) -} diff --git a/cl/beacon/handler/rewards.go b/cl/beacon/handler/rewards.go index dc8ca4f8119..cb41352986f 100644 --- a/cl/beacon/handler/rewards.go +++ b/cl/beacon/handler/rewards.go @@ -23,7 +23,7 @@ type blockRewardsResponse struct { Total uint64 `json:"total,string"` } -func (a *ApiHandler) getBlockRewards(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getBlockRewards(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { ctx := r.Context() tx, err := a.indiciesDB.BeginRo(ctx) if err != nil { @@ -31,7 +31,7 @@ func (a *ApiHandler) getBlockRewards(w http.ResponseWriter, r *http.Request) (*b } defer tx.Rollback() - blockId, err := blockIdFromRequest(r) + blockId, err := beaconhttp.BlockIdFromRequest(r) if err != nil { return nil, err } @@ -61,7 +61,7 @@ func (a *ApiHandler) getBlockRewards(w http.ResponseWriter, r *http.Request) (*b AttesterSlashings: blkRewards.AttesterSlashings, SyncAggregate: blkRewards.SyncAggregate, Total: blkRewards.Attestations + blkRewards.ProposerSlashings + blkRewards.AttesterSlashings + blkRewards.SyncAggregate, - }).withFinalized(isFinalized), nil + }).WithFinalized(isFinalized), nil } slotData, err := state_accessors.ReadSlotData(tx, slot) if err != nil { @@ -77,7 +77,7 @@ func (a *ApiHandler) getBlockRewards(w http.ResponseWriter, r *http.Request) (*b AttesterSlashings: slotData.AttesterSlashings, SyncAggregate: slotData.SyncAggregateRewards, Total: slotData.AttestationsRewards + slotData.ProposerSlashings + slotData.AttesterSlashings + slotData.SyncAggregateRewards, - }).withFinalized(isFinalized), nil + }).WithFinalized(isFinalized), nil } type syncCommitteeReward struct { @@ -85,7 +85,7 @@ type syncCommitteeReward struct { Reward int64 `json:"reward,string"` } -func (a *ApiHandler) getSyncCommitteesRewards(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getSyncCommitteesRewards(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { ctx := r.Context() tx, err := a.indiciesDB.BeginRo(ctx) @@ -111,7 +111,7 @@ func (a *ApiHandler) getSyncCommitteesRewards(w http.ResponseWriter, r *http.Req return nil, err } - blockId, err := blockIdFromRequest(r) + blockId, err := beaconhttp.BlockIdFromRequest(r) if err != nil { return nil, err } @@ -220,7 +220,7 @@ func (a *ApiHandler) getSyncCommitteesRewards(w http.ResponseWriter, r *http.Req sort.Slice(rewards, func(i, j int) bool { return rewards[i].ValidatorIndex < rewards[j].ValidatorIndex }) - return newBeaconResponse(rewards).withFinalized(isFinalized), nil + return newBeaconResponse(rewards).WithFinalized(isFinalized), nil } func (a *ApiHandler) syncPartecipantReward(activeBalance uint64) uint64 { diff --git a/cl/beacon/handler/rewards_test.go b/cl/beacon/handler/rewards_test.go deleted file mode 100644 index 2a6cef4a851..00000000000 --- a/cl/beacon/handler/rewards_test.go +++ /dev/null @@ -1,142 +0,0 @@ -package handler - -import ( - "fmt" - "io" - "math" - "net/http" - "net/http/httptest" - "strings" - "testing" - - "github.com/ledgerwatch/erigon/cl/clparams" - "github.com/ledgerwatch/erigon/cl/cltypes/solid" - "github.com/ledgerwatch/erigon/common" - "github.com/stretchr/testify/require" -) - -func TestGetBlockRewards(t *testing.T) { - _, blocks, _, _, _, handler, _, _, fcu := setupTestingHandler(t, clparams.BellatrixVersion) - var err error - fcu.HeadVal, err = blocks[len(blocks)-5].Block.HashSSZ() - require.NoError(t, err) - genesisVal, err := blocks[0].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, math.MaxUint64) - fcu.FinalizedSlotVal = math.MaxUint64 - - cases := []struct { - blockID string - code int - expectedResp string - }{ - { - blockID: "0x" + common.Bytes2Hex(fcu.HeadVal[:]), - code: http.StatusOK, - expectedResp: `{"data":{"proposer_index":"203","attestations":"332205","proposer_slashings":"0","attester_slashings":"0","sync_aggregate":"0","total":"332205"},"finalized":true,"execution_optimistic":false}` + "\n", - }, - { - blockID: "0x" + common.Bytes2Hex(genesisVal[:]), - code: http.StatusOK, - expectedResp: `{"data":{"proposer_index":"98","attestations":"332205","proposer_slashings":"0","attester_slashings":"0","sync_aggregate":"0","total":"332205"},"finalized":true,"execution_optimistic":false}` + "\n", - }, - { - blockID: "0x" + common.Bytes2Hex(make([]byte, 32)), - code: http.StatusNotFound, - }, - } - - for _, c := range cases { - t.Run(c.blockID, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - // Query the block in the handler with /eth/v2/beacon/blocks/{block_id} - resp, err := http.Get(server.URL + "/eth/v1/beacon/rewards/blocks/" + c.blockID) - require.NoError(t, err) - defer resp.Body.Close() - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - - // unmarshal the json - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.Equal(t, c.expectedResp, string(out)) - }) - } -} - -func TestPostSyncCommitteeRewards(t *testing.T) { - _, blocks, _, _, _, handler, _, _, fcu := setupTestingHandler(t, clparams.BellatrixVersion) - var err error - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - fcu.FinalizedSlotVal = math.MaxInt64 - - fcu.JustifiedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, 99999999) - - cases := []struct { - name string - blockId string - code int - request string - expected string - }{ - { - name: "all validators", - blockId: "0x" + common.Bytes2Hex(fcu.HeadVal[:]), - code: http.StatusOK, - expected: `{"data":[{"validator_index":"0","reward":"-698"},{"validator_index":"1","reward":"-698"},{"validator_index":"2","reward":"-698"},{"validator_index":"3","reward":"-698"},{"validator_index":"4","reward":"-698"},{"validator_index":"5","reward":"-698"},{"validator_index":"6","reward":"-698"},{"validator_index":"7","reward":"-698"},{"validator_index":"8","reward":"-698"},{"validator_index":"9","reward":"-698"},{"validator_index":"10","reward":"-698"},{"validator_index":"11","reward":"-698"},{"validator_index":"12","reward":"-698"},{"validator_index":"13","reward":"-698"},{"validator_index":"14","reward":"-698"},{"validator_index":"15","reward":"-698"},{"validator_index":"16","reward":"-698"},{"validator_index":"17","reward":"-698"},{"validator_index":"18","reward":"-698"},{"validator_index":"19","reward":"-698"},{"validator_index":"20","reward":"-698"},{"validator_index":"21","reward":"-698"},{"validator_index":"22","reward":"-698"},{"validator_index":"23","reward":"-698"},{"validator_index":"24","reward":"-698"},{"validator_index":"25","reward":"-698"},{"validator_index":"26","reward":"-698"},{"validator_index":"27","reward":"-698"},{"validator_index":"28","reward":"-698"},{"validator_index":"29","reward":"-698"},{"validator_index":"30","reward":"-698"},{"validator_index":"31","reward":"-698"},{"validator_index":"32","reward":"-698"},{"validator_index":"33","reward":"-698"},{"validator_index":"34","reward":"-698"},{"validator_index":"35","reward":"-698"},{"validator_index":"36","reward":"-698"},{"validator_index":"37","reward":"-698"},{"validator_index":"38","reward":"-698"},{"validator_index":"39","reward":"-698"},{"validator_index":"40","reward":"-698"},{"validator_index":"41","reward":"-698"},{"validator_index":"42","reward":"-698"},{"validator_index":"43","reward":"-698"},{"validator_index":"44","reward":"-698"},{"validator_index":"45","reward":"-698"},{"validator_index":"46","reward":"-698"},{"validator_index":"47","reward":"-698"},{"validator_index":"48","reward":"-698"},{"validator_index":"49","reward":"-698"},{"validator_index":"50","reward":"-698"},{"validator_index":"51","reward":"-698"},{"validator_index":"52","reward":"-698"},{"validator_index":"53","reward":"-698"},{"validator_index":"54","reward":"-698"},{"validator_index":"55","reward":"-698"},{"validator_index":"56","reward":"-698"},{"validator_index":"57","reward":"-698"},{"validator_index":"58","reward":"-698"},{"validator_index":"59","reward":"-698"},{"validator_index":"60","reward":"-698"},{"validator_index":"61","reward":"-698"},{"validator_index":"62","reward":"-698"},{"validator_index":"63","reward":"-698"},{"validator_index":"64","reward":"-698"},{"validator_index":"65","reward":"-698"},{"validator_index":"66","reward":"-698"},{"validator_index":"67","reward":"-698"},{"validator_index":"68","reward":"-698"},{"validator_index":"69","reward":"-698"},{"validator_index":"70","reward":"-698"},{"validator_index":"71","reward":"-698"},{"validator_index":"72","reward":"-698"},{"validator_index":"73","reward":"-698"},{"validator_index":"74","reward":"-698"},{"validator_index":"75","reward":"-698"},{"validator_index":"76","reward":"-698"},{"validator_index":"77","reward":"-698"},{"validator_index":"78","reward":"-698"},{"validator_index":"79","reward":"-698"},{"validator_index":"80","reward":"-698"},{"validator_index":"81","reward":"-698"},{"validator_index":"82","reward":"-698"},{"validator_index":"83","reward":"-698"},{"validator_index":"84","reward":"-698"},{"validator_index":"85","reward":"-698"},{"validator_index":"86","reward":"-698"},{"validator_index":"87","reward":"-698"},{"validator_index":"88","reward":"-698"},{"validator_index":"89","reward":"-698"},{"validator_index":"90","reward":"-698"},{"validator_index":"91","reward":"-698"},{"validator_index":"92","reward":"-698"},{"validator_index":"93","reward":"-698"},{"validator_index":"94","reward":"-698"},{"validator_index":"95","reward":"-698"},{"validator_index":"96","reward":"-698"},{"validator_index":"97","reward":"-698"},{"validator_index":"98","reward":"-698"},{"validator_index":"99","reward":"-698"},{"validator_index":"100","reward":"-698"},{"validator_index":"101","reward":"-698"},{"validator_index":"102","reward":"-698"},{"validator_index":"103","reward":"-698"},{"validator_index":"104","reward":"-698"},{"validator_index":"105","reward":"-698"},{"validator_index":"106","reward":"-698"},{"validator_index":"107","reward":"-698"},{"validator_index":"108","reward":"-698"},{"validator_index":"109","reward":"-698"},{"validator_index":"110","reward":"-698"},{"validator_index":"111","reward":"-698"},{"validator_index":"112","reward":"-698"},{"validator_index":"113","reward":"-698"},{"validator_index":"114","reward":"-698"},{"validator_index":"115","reward":"-698"},{"validator_index":"116","reward":"-698"},{"validator_index":"117","reward":"-698"},{"validator_index":"118","reward":"-698"},{"validator_index":"119","reward":"-698"},{"validator_index":"120","reward":"-698"},{"validator_index":"121","reward":"-698"},{"validator_index":"122","reward":"-698"},{"validator_index":"123","reward":"-698"},{"validator_index":"124","reward":"-698"},{"validator_index":"125","reward":"-698"},{"validator_index":"126","reward":"-698"},{"validator_index":"127","reward":"-698"},{"validator_index":"128","reward":"-698"},{"validator_index":"129","reward":"-698"},{"validator_index":"130","reward":"-698"},{"validator_index":"131","reward":"-698"},{"validator_index":"132","reward":"-698"},{"validator_index":"133","reward":"-698"},{"validator_index":"134","reward":"-698"},{"validator_index":"135","reward":"-698"},{"validator_index":"136","reward":"-698"},{"validator_index":"137","reward":"-698"},{"validator_index":"138","reward":"-698"},{"validator_index":"139","reward":"-698"},{"validator_index":"140","reward":"-698"},{"validator_index":"141","reward":"-698"},{"validator_index":"142","reward":"-698"},{"validator_index":"143","reward":"-698"},{"validator_index":"144","reward":"-698"},{"validator_index":"145","reward":"-698"},{"validator_index":"146","reward":"-698"},{"validator_index":"147","reward":"-698"},{"validator_index":"148","reward":"-698"},{"validator_index":"149","reward":"-698"},{"validator_index":"150","reward":"-698"},{"validator_index":"151","reward":"-698"},{"validator_index":"152","reward":"-698"},{"validator_index":"153","reward":"-698"},{"validator_index":"154","reward":"-698"},{"validator_index":"155","reward":"-698"},{"validator_index":"156","reward":"-698"},{"validator_index":"157","reward":"-698"},{"validator_index":"158","reward":"-698"},{"validator_index":"159","reward":"-698"},{"validator_index":"160","reward":"-698"},{"validator_index":"161","reward":"-698"},{"validator_index":"162","reward":"-698"},{"validator_index":"163","reward":"-698"},{"validator_index":"164","reward":"-698"},{"validator_index":"165","reward":"-698"},{"validator_index":"166","reward":"-698"},{"validator_index":"167","reward":"-698"},{"validator_index":"168","reward":"-698"},{"validator_index":"169","reward":"-698"},{"validator_index":"170","reward":"-698"},{"validator_index":"171","reward":"-698"},{"validator_index":"172","reward":"-698"},{"validator_index":"173","reward":"-698"},{"validator_index":"174","reward":"-698"},{"validator_index":"175","reward":"-698"},{"validator_index":"176","reward":"-698"},{"validator_index":"177","reward":"-698"},{"validator_index":"178","reward":"-698"},{"validator_index":"179","reward":"-698"},{"validator_index":"180","reward":"-698"},{"validator_index":"181","reward":"-698"},{"validator_index":"182","reward":"-698"},{"validator_index":"183","reward":"-698"},{"validator_index":"184","reward":"-698"},{"validator_index":"185","reward":"-698"},{"validator_index":"186","reward":"-698"},{"validator_index":"187","reward":"-698"},{"validator_index":"188","reward":"-698"},{"validator_index":"189","reward":"-698"},{"validator_index":"190","reward":"-698"},{"validator_index":"191","reward":"-698"},{"validator_index":"192","reward":"-698"},{"validator_index":"193","reward":"-698"},{"validator_index":"194","reward":"-698"},{"validator_index":"195","reward":"-698"},{"validator_index":"196","reward":"-698"},{"validator_index":"197","reward":"-698"},{"validator_index":"198","reward":"-698"},{"validator_index":"199","reward":"-698"},{"validator_index":"200","reward":"-698"},{"validator_index":"201","reward":"-698"},{"validator_index":"202","reward":"-698"},{"validator_index":"203","reward":"-698"},{"validator_index":"204","reward":"-698"},{"validator_index":"205","reward":"-698"},{"validator_index":"206","reward":"-698"},{"validator_index":"207","reward":"-698"},{"validator_index":"208","reward":"-698"},{"validator_index":"209","reward":"-698"},{"validator_index":"210","reward":"-698"},{"validator_index":"211","reward":"-698"},{"validator_index":"212","reward":"-698"},{"validator_index":"213","reward":"-698"},{"validator_index":"214","reward":"-698"},{"validator_index":"215","reward":"-698"},{"validator_index":"216","reward":"-698"},{"validator_index":"217","reward":"-698"},{"validator_index":"218","reward":"-698"},{"validator_index":"219","reward":"-698"},{"validator_index":"220","reward":"-698"},{"validator_index":"221","reward":"-698"},{"validator_index":"222","reward":"-698"},{"validator_index":"223","reward":"-698"},{"validator_index":"224","reward":"-698"},{"validator_index":"225","reward":"-698"},{"validator_index":"226","reward":"-698"},{"validator_index":"227","reward":"-698"},{"validator_index":"228","reward":"-698"},{"validator_index":"229","reward":"-698"},{"validator_index":"230","reward":"-698"},{"validator_index":"231","reward":"-698"},{"validator_index":"232","reward":"-698"},{"validator_index":"233","reward":"-698"},{"validator_index":"234","reward":"-698"},{"validator_index":"235","reward":"-698"},{"validator_index":"236","reward":"-698"},{"validator_index":"237","reward":"-698"},{"validator_index":"238","reward":"-698"},{"validator_index":"239","reward":"-698"},{"validator_index":"240","reward":"-698"},{"validator_index":"241","reward":"-698"},{"validator_index":"242","reward":"-698"},{"validator_index":"243","reward":"-698"},{"validator_index":"244","reward":"-698"},{"validator_index":"245","reward":"-698"},{"validator_index":"246","reward":"-698"},{"validator_index":"247","reward":"-698"},{"validator_index":"248","reward":"-698"},{"validator_index":"249","reward":"-698"},{"validator_index":"250","reward":"-698"},{"validator_index":"251","reward":"-698"},{"validator_index":"252","reward":"-698"},{"validator_index":"253","reward":"-698"},{"validator_index":"254","reward":"-698"},{"validator_index":"255","reward":"-698"}],"finalized":true,"execution_optimistic":false}` + "\n", - }, - { - blockId: "0x" + common.Bytes2Hex(make([]byte, 32)), - code: http.StatusNotFound, - }, - { - name: "2 validators", - blockId: "0x" + common.Bytes2Hex(fcu.HeadVal[:]), - request: `["1","4"]`, - code: http.StatusOK, - expected: `{"data":[{"validator_index":"1","reward":"-698"},{"validator_index":"4","reward":"-698"}],"finalized":true,"execution_optimistic":false}` + "\n", // Add your expected response - }, - } - for _, c := range cases { - t.Run(c.name, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - url := fmt.Sprintf("%s/eth/v1/beacon/rewards/sync_committee/%s", server.URL, c.blockId) - - // Create a request - req, err := http.NewRequest("POST", url, strings.NewReader(c.request)) - require.NoError(t, err) - req.Header.Set("Content-Type", "application/json") - - // Perform the request - resp, err := http.DefaultClient.Do(req) - require.NoError(t, err) - defer resp.Body.Close() - - // Check status code - require.Equal(t, c.code, resp.StatusCode) - - if resp.StatusCode != http.StatusOK { - return - } - - // Read the response body - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - if string(out) != c.expected { - panic(string(out)) - } - // Compare the response with the expected result - require.Equal(t, c.expected, string(out)) - }) - } -} diff --git a/cl/beacon/handler/states.go b/cl/beacon/handler/states.go index 335296f349d..e232084d1e2 100644 --- a/cl/beacon/handler/states.go +++ b/cl/beacon/handler/states.go @@ -17,21 +17,21 @@ import ( "github.com/ledgerwatch/erigon/cl/utils" ) -func (a *ApiHandler) blockRootFromStateId(ctx context.Context, tx kv.Tx, stateId *segmentID) (root libcommon.Hash, httpStatusErr int, err error) { +func (a *ApiHandler) blockRootFromStateId(ctx context.Context, tx kv.Tx, stateId *beaconhttp.SegmentID) (root libcommon.Hash, httpStatusErr int, err error) { switch { - case stateId.head(): + case stateId.Head(): root, _, err = a.forkchoiceStore.GetHead() if err != nil { return libcommon.Hash{}, http.StatusInternalServerError, err } return - case stateId.finalized(): + case stateId.Finalized(): root = a.forkchoiceStore.FinalizedCheckpoint().BlockRoot() return - case stateId.justified(): + case stateId.Justified(): root = a.forkchoiceStore.JustifiedCheckpoint().BlockRoot() return - case stateId.genesis(): + case stateId.Genesis(): root, err = beacon_indicies.ReadCanonicalBlockRoot(tx, 0) if err != nil { return libcommon.Hash{}, http.StatusInternalServerError, err @@ -40,17 +40,17 @@ func (a *ApiHandler) blockRootFromStateId(ctx context.Context, tx kv.Tx, stateId return libcommon.Hash{}, http.StatusNotFound, fmt.Errorf("genesis block not found") } return - case stateId.getSlot() != nil: - root, err = beacon_indicies.ReadCanonicalBlockRoot(tx, *stateId.getSlot()) + case stateId.GetSlot() != nil: + root, err = beacon_indicies.ReadCanonicalBlockRoot(tx, *stateId.GetSlot()) if err != nil { return libcommon.Hash{}, http.StatusInternalServerError, err } if root == (libcommon.Hash{}) { - return libcommon.Hash{}, http.StatusNotFound, fmt.Errorf("block not found %d", *stateId.getSlot()) + return libcommon.Hash{}, http.StatusNotFound, fmt.Errorf("block not found %d", *stateId.GetSlot()) } return - case stateId.getRoot() != nil: - root, err = beacon_indicies.ReadBlockRootByStateRoot(tx, *stateId.getRoot()) + case stateId.GetRoot() != nil: + root, err = beacon_indicies.ReadBlockRootByStateRoot(tx, *stateId.GetRoot()) if err != nil { return libcommon.Hash{}, http.StatusInternalServerError, err } @@ -71,7 +71,7 @@ func previousVersion(v clparams.StateVersion) clparams.StateVersion { return v - 1 } -func (a *ApiHandler) getStateFork(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getStateFork(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { ctx := r.Context() tx, err := a.indiciesDB.BeginRo(ctx) @@ -80,7 +80,7 @@ func (a *ApiHandler) getStateFork(w http.ResponseWriter, r *http.Request) (*beac } defer tx.Rollback() - blockId, err := stateIdFromRequest(r) + blockId, err := beaconhttp.StateIdFromRequest(r) if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } @@ -110,7 +110,7 @@ func (a *ApiHandler) getStateFork(w http.ResponseWriter, r *http.Request) (*beac }), nil } -func (a *ApiHandler) getStateRoot(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getStateRoot(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { ctx := r.Context() tx, err := a.indiciesDB.BeginRo(ctx) @@ -119,7 +119,7 @@ func (a *ApiHandler) getStateRoot(w http.ResponseWriter, r *http.Request) (*beac } defer tx.Rollback() - blockId, err := stateIdFromRequest(r) + blockId, err := beaconhttp.StateIdFromRequest(r) if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } @@ -149,10 +149,10 @@ func (a *ApiHandler) getStateRoot(w http.ResponseWriter, r *http.Request) (*beac } return newBeaconResponse(&rootResponse{Root: stateRoot}). - withFinalized(canonicalRoot == root && *slot <= a.forkchoiceStore.FinalizedSlot()), nil + WithFinalized(canonicalRoot == root && *slot <= a.forkchoiceStore.FinalizedSlot()), nil } -func (a *ApiHandler) getFullState(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getFullState(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { ctx := r.Context() tx, err := a.indiciesDB.BeginRo(ctx) @@ -161,7 +161,7 @@ func (a *ApiHandler) getFullState(w http.ResponseWriter, r *http.Request) (*beac } defer tx.Rollback() - blockId, err := stateIdFromRequest(r) + blockId, err := beaconhttp.StateIdFromRequest(r) if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } @@ -198,10 +198,10 @@ func (a *ApiHandler) getFullState(w http.ResponseWriter, r *http.Request) (*beac if state == nil { return nil, beaconhttp.NewEndpointError(http.StatusNotFound, fmt.Sprintf("could not read state: %x", blockRoot)) } - return newBeaconResponse(state).withFinalized(true).withVersion(state.Version()), nil + return newBeaconResponse(state).WithFinalized(true).WithVersion(state.Version()), nil } - return newBeaconResponse(state).withFinalized(false).withVersion(state.Version()), nil + return newBeaconResponse(state).WithFinalized(false).WithVersion(state.Version()), nil } type finalityCheckpointsResponse struct { @@ -210,7 +210,7 @@ type finalityCheckpointsResponse struct { PreviousJustifiedCheckpoint solid.Checkpoint `json:"previous_justified_checkpoint"` } -func (a *ApiHandler) getFinalityCheckpoints(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getFinalityCheckpoints(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { ctx := r.Context() tx, err := a.indiciesDB.BeginRo(ctx) @@ -218,7 +218,7 @@ func (a *ApiHandler) getFinalityCheckpoints(w http.ResponseWriter, r *http.Reque return nil, err } defer tx.Rollback() - blockId, err := stateIdFromRequest(r) + blockId, err := beaconhttp.StateIdFromRequest(r) if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } @@ -259,7 +259,7 @@ func (a *ApiHandler) getFinalityCheckpoints(w http.ResponseWriter, r *http.Reque FinalizedCheckpoint: finalizedCheckpoint, CurrentJustifiedCheckpoint: currentJustifiedCheckpoint, PreviousJustifiedCheckpoint: previousJustifiedCheckpoint, - }).withFinalized(canonicalRoot == blockRoot && *slot <= a.forkchoiceStore.FinalizedSlot()).withVersion(version), nil + }).WithFinalized(canonicalRoot == blockRoot && *slot <= a.forkchoiceStore.FinalizedSlot()).WithVersion(version), nil } type syncCommitteesResponse struct { @@ -267,7 +267,7 @@ type syncCommitteesResponse struct { ValidatorAggregates [][]string `json:"validator_aggregates"` } -func (a *ApiHandler) getSyncCommittees(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getSyncCommittees(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { ctx := r.Context() tx, err := a.indiciesDB.BeginRo(ctx) @@ -275,7 +275,7 @@ func (a *ApiHandler) getSyncCommittees(w http.ResponseWriter, r *http.Request) ( return nil, err } defer tx.Rollback() - blockId, err := stateIdFromRequest(r) + blockId, err := beaconhttp.StateIdFromRequest(r) if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } @@ -312,7 +312,7 @@ func (a *ApiHandler) getSyncCommittees(w http.ResponseWriter, r *http.Request) ( } // Now fetch the data we need statePeriod := a.beaconChainCfg.SyncCommitteePeriod(*slot) - queryEpoch, err := uint64FromQueryParams(r, "epoch") + queryEpoch, err := beaconhttp.Uint64FromQueryParams(r, "epoch") if err != nil { return nil, err } @@ -355,14 +355,14 @@ func (a *ApiHandler) getSyncCommittees(w http.ResponseWriter, r *http.Request) ( return nil, err } - return newBeaconResponse(response).withFinalized(canonicalRoot == blockRoot && *slot <= a.forkchoiceStore.FinalizedSlot()), nil + return newBeaconResponse(response).WithFinalized(canonicalRoot == blockRoot && *slot <= a.forkchoiceStore.FinalizedSlot()), nil } type randaoResponse struct { Randao libcommon.Hash `json:"randao"` } -func (a *ApiHandler) getRandao(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getRandao(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { ctx := r.Context() tx, err := a.indiciesDB.BeginRo(ctx) @@ -370,7 +370,7 @@ func (a *ApiHandler) getRandao(w http.ResponseWriter, r *http.Request) (*beaconR return nil, err } defer tx.Rollback() - blockId, err := stateIdFromRequest(r) + blockId, err := beaconhttp.StateIdFromRequest(r) if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } @@ -380,7 +380,7 @@ func (a *ApiHandler) getRandao(w http.ResponseWriter, r *http.Request) (*beaconR return nil, beaconhttp.NewEndpointError(httpStatus, err.Error()) } - epochReq, err := uint64FromQueryParams(r, "epoch") + epochReq, err := beaconhttp.Uint64FromQueryParams(r, "epoch") if err != nil { return nil, err } @@ -401,7 +401,7 @@ func (a *ApiHandler) getRandao(w http.ResponseWriter, r *http.Request) (*beaconR if a.forkchoiceStore.RandaoMixes(blockRoot, randaoMixes) { mix := randaoMixes.Get(int(epoch % a.beaconChainCfg.EpochsPerHistoricalVector)) - return newBeaconResponse(randaoResponse{Randao: mix}).withFinalized(slot <= a.forkchoiceStore.FinalizedSlot()), nil + return newBeaconResponse(randaoResponse{Randao: mix}).WithFinalized(slot <= a.forkchoiceStore.FinalizedSlot()), nil } // check if the block is canonical canonicalRoot, err := beacon_indicies.ReadCanonicalBlockRoot(tx, slot) @@ -415,5 +415,5 @@ func (a *ApiHandler) getRandao(w http.ResponseWriter, r *http.Request) (*beaconR if err != nil { return nil, err } - return newBeaconResponse(randaoResponse{Randao: mix}).withFinalized(slot <= a.forkchoiceStore.FinalizedSlot()), nil + return newBeaconResponse(randaoResponse{Randao: mix}).WithFinalized(slot <= a.forkchoiceStore.FinalizedSlot()), nil } diff --git a/cl/beacon/handler/states_test.go b/cl/beacon/handler/states_test.go deleted file mode 100644 index eaa6d633a9e..00000000000 --- a/cl/beacon/handler/states_test.go +++ /dev/null @@ -1,504 +0,0 @@ -package handler - -import ( - "encoding/json" - "io" - "net/http" - "net/http/httptest" - "strconv" - "testing" - - "github.com/ledgerwatch/erigon/cl/clparams" - "github.com/ledgerwatch/erigon/cl/cltypes/solid" - "github.com/ledgerwatch/erigon/cl/phase1/core/state" - "github.com/ledgerwatch/erigon/common" - "github.com/stretchr/testify/require" -) - -func TestGetStateFork(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, postState, handler, _, _, fcu := setupTestingHandler(t, clparams.Phase0Version) - - postRoot, err := postState.HashSSZ() - require.NoError(t, err) - - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - - cases := []struct { - blockID string - code int - }{ - { - blockID: "0x" + common.Bytes2Hex(postRoot[:]), - code: http.StatusOK, - }, - { - blockID: "head", - code: http.StatusOK, - }, - { - blockID: "0x" + common.Bytes2Hex(make([]byte, 32)), - code: http.StatusNotFound, - }, - { - blockID: strconv.FormatInt(int64(postState.Slot()), 10), - code: http.StatusOK, - }, - } - - for _, c := range cases { - t.Run(c.blockID, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - // Query the block in the handler with /eth/v2/beacon/blocks/{block_id} - resp, err := http.Get(server.URL + "/eth/v1/beacon/states/" + c.blockID + "/fork") - require.NoError(t, err) - defer resp.Body.Close() - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - jsonVal := make(map[string]interface{}) - // unmarshal the json - require.NoError(t, json.NewDecoder(resp.Body).Decode(&jsonVal)) - data := jsonVal["data"].(map[string]interface{}) - require.Equal(t, data["current_version"], "0x00000000") - require.Equal(t, data["previous_version"], "0x00000000") - require.Equal(t, data["epoch"], "0") - }) - } -} - -func TestGetStateRoot(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, postState, handler, _, _, fcu := setupTestingHandler(t, clparams.Phase0Version) - - postRoot, err := postState.HashSSZ() - require.NoError(t, err) - - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) - - cases := []struct { - blockID string - code int - }{ - { - blockID: "0x" + common.Bytes2Hex(postRoot[:]), - code: http.StatusOK, - }, - { - blockID: "finalized", - code: http.StatusOK, - }, - { - blockID: "0x" + common.Bytes2Hex(make([]byte, 32)), - code: http.StatusNotFound, - }, - { - blockID: strconv.FormatInt(int64(postState.Slot()), 10), - code: http.StatusOK, - }, - } - - for _, c := range cases { - t.Run(c.blockID, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - // Query the block in the handler with /eth/v2/beacon/blocks/{block_id} - resp, err := http.Get(server.URL + "/eth/v1/beacon/states/" + c.blockID + "/root") - require.NoError(t, err) - defer resp.Body.Close() - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - jsonVal := make(map[string]interface{}) - // unmarshal the json - require.NoError(t, json.NewDecoder(resp.Body).Decode(&jsonVal)) - data := jsonVal["data"].(map[string]interface{}) - require.Equal(t, data["root"], "0x"+common.Bytes2Hex(postRoot[:])) - }) - } -} - -func TestGetStateFullHistorical(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, postState, handler, _, _, fcu := setupTestingHandler(t, clparams.Phase0Version) - - postRoot, err := postState.HashSSZ() - require.NoError(t, err) - - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) - - cases := []struct { - blockID string - code int - }{ - { - blockID: "0x" + common.Bytes2Hex(postRoot[:]), - code: http.StatusOK, - }, - { - blockID: "finalized", - code: http.StatusOK, - }, - { - blockID: "0x" + common.Bytes2Hex(make([]byte, 32)), - code: http.StatusNotFound, - }, - { - blockID: strconv.FormatInt(int64(postState.Slot()), 10), - code: http.StatusOK, - }, - } - - for _, c := range cases { - t.Run(c.blockID, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - // Query the block in the handler with /eth/v2/beacon/states/{block_id} with content-type octet-stream - req, err := http.NewRequest("GET", server.URL+"/eth/v2/debug/beacon/states/"+c.blockID, nil) - require.NoError(t, err) - req.Header.Set("Accept", "application/octet-stream") - - resp, err := http.DefaultClient.Do(req) - require.NoError(t, err) - - defer resp.Body.Close() - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - // read the all of the octect - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - other := state.New(&clparams.MainnetBeaconConfig) - require.NoError(t, other.DecodeSSZ(out, int(clparams.Phase0Version))) - - otherRoot, err := other.HashSSZ() - require.NoError(t, err) - require.Equal(t, postRoot, otherRoot) - }) - } -} - -func TestGetStateFullForkchoice(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, postState, handler, _, _, fcu := setupTestingHandler(t, clparams.Phase0Version) - - postRoot, err := postState.HashSSZ() - require.NoError(t, err) - - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) - - fcu.StateAtBlockRootVal[fcu.HeadVal] = postState - - cases := []struct { - blockID string - code int - }{ - { - blockID: "0x" + common.Bytes2Hex(postRoot[:]), - code: http.StatusOK, - }, - { - blockID: "finalized", - code: http.StatusOK, - }, - { - blockID: "0x" + common.Bytes2Hex(make([]byte, 32)), - code: http.StatusNotFound, - }, - { - blockID: strconv.FormatInt(int64(postState.Slot()), 10), - code: http.StatusOK, - }, - } - - for _, c := range cases { - t.Run(c.blockID, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - // Query the block in the handler with /eth/v2/beacon/states/{block_id} with content-type octet-stream - req, err := http.NewRequest("GET", server.URL+"/eth/v2/debug/beacon/states/"+c.blockID, nil) - require.NoError(t, err) - req.Header.Set("Accept", "application/octet-stream") - - resp, err := http.DefaultClient.Do(req) - require.NoError(t, err) - - defer resp.Body.Close() - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - // read the all of the octect - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - other := state.New(&clparams.MainnetBeaconConfig) - require.NoError(t, other.DecodeSSZ(out, int(clparams.Phase0Version))) - - otherRoot, err := other.HashSSZ() - require.NoError(t, err) - require.Equal(t, postRoot, otherRoot) - }) - } -} - -func TestGetStateSyncCommittees(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, postState, handler, _, _, fcu := setupTestingHandler(t, clparams.BellatrixVersion) - - postRoot, err := postState.HashSSZ() - require.NoError(t, err) - - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - - cSyncCommittee := postState.CurrentSyncCommittee().Copy() - nSyncCommittee := postState.NextSyncCommittee().Copy() - - fcu.GetSyncCommitteesVal[fcu.HeadVal] = [2]*solid.SyncCommittee{ - cSyncCommittee, - nSyncCommittee, - } - - fcu.JustifiedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) - - cases := []struct { - blockID string - code int - }{ - { - blockID: "0x" + common.Bytes2Hex(postRoot[:]), - code: http.StatusOK, - }, - { - blockID: "justified", - code: http.StatusOK, - }, - { - blockID: "0x" + common.Bytes2Hex(make([]byte, 32)), - code: http.StatusNotFound, - }, - { - blockID: strconv.FormatInt(int64(postState.Slot()), 10), - code: http.StatusOK, - }, - } - expected := `{"data":{"validators":["109","134","145","89","181","81","159","168","34","251","3","205","213","202","99","121","80","149","18","65","201","227","116","69","100","74","160","198","16","131","0","73","210","122","209","217","97","237","136","98","229","248","176","95","150","171","238","191","200","220","33","219","126","9","214","124","56","86","169","208","125","85","25","88","13","190","153","183","96","165","180","90","164","104","240","123","118","196","163","222","231","127","241","77","68","32","62","79","44","58","14","187","151","243","139","142","174","106","228","102","223","31","120","5","43","255","179","66","119","170","60","152","167","194","4","112","156","233","254","203","1","55","53","19","92","21","28","42","141","162","146","57","23","45","158","93","212","38","2","206","246","225","195","189","47","193","224","242","76","138","84","140","111","51","135","113","41","133","207","30","82","175","161","6","249","83","234","155","244","177","108","252","94","143","173","8","154","75","50","49","39","36","182","101","48","12","172","87","250","59","24","157","215","218","72","185","71","7","253","114","230","226","110","46","166","91","130","20","137","117","132","204","221","52","197","188","11","232","67","115","245","26","35","103","186","37","27","235","64","40","70","239","236","211","61","29","216","199","63","54","78","105","184","15","10","147","247","22","144","107","128","17","178","148","129","192","109","134","145","89","181","81","159","168","34","251","3","205","213","202","99","121","80","149","18","65","201","227","116","69","100","74","160","198","16","131","0","73","210","122","209","217","97","237","136","98","229","248","176","95","150","171","238","191","200","220","33","219","126","9","214","124","56","86","169","208","125","85","25","88","13","190","153","183","96","165","180","90","164","104","240","123","118","196","163","222","231","127","241","77","68","32","62","79","44","58","14","187","151","243","139","142","174","106","228","102","223","31","120","5","43","255","179","66","119","170","60","152","167","194","4","112","156","233","254","203","1","55","53","19","92","21","28","42","141","162","146","57","23","45","158","93","212","38","2","206","246","225","195","189","47","193","224","242","76","138","84","140","111","51","135","113","41","133","207","30","82","175","161","6","249","83","234","155","244","177","108","252","94","143","173","8","154","75","50","49","39","36","182","101","48","12","172","87","250","59","24","157","215","218","72","185","71","7","253","114","230","226","110","46","166","91","130","20","137","117","132","204","221","52","197","188","11","232","67","115","245","26","35","103","186","37","27","235","64","40","70","239","236","211","61","29","216","199","63","54","78","105","184","15","10","147","247","22","144","107","128","17","178","148","129","192"],"validator_aggregates":[["109","134","145","89","181","81","159","168","34","251","3","205","213","202","99","121","80","149","18","65","201","227","116","69","100","74","160","198","16","131","0","73","210","122","209","217","97","237","136","98","229","248","176","95","150","171","238","191","200","220","33","219","126","9","214","124","56","86","169","208","125","85","25","88","13","190","153","183","96","165","180","90","164","104","240","123","118","196","163","222","231","127","241","77","68","32","62","79","44","58","14","187","151","243","139","142","174","106","228","102","223","31","120","5","43","255","179","66","119","170","60","152","167","194","4","112","156","233","254","203","1","55","53","19","92","21","28","42"],["141","162","146","57","23","45","158","93","212","38","2","206","246","225","195","189","47","193","224","242","76","138","84","140","111","51","135","113","41","133","207","30","82","175","161","6","249","83","234","155","244","177","108","252","94","143","173","8","154","75","50","49","39","36","182","101","48","12","172","87","250","59","24","157","215","218","72","185","71","7","253","114","230","226","110","46","166","91","130","20","137","117","132","204","221","52","197","188","11","232","67","115","245","26","35","103","186","37","27","235","64","40","70","239","236","211","61","29","216","199","63","54","78","105","184","15","10","147","247","22","144","107","128","17","178","148","129","192"],["109","134","145","89","181","81","159","168","34","251","3","205","213","202","99","121","80","149","18","65","201","227","116","69","100","74","160","198","16","131","0","73","210","122","209","217","97","237","136","98","229","248","176","95","150","171","238","191","200","220","33","219","126","9","214","124","56","86","169","208","125","85","25","88","13","190","153","183","96","165","180","90","164","104","240","123","118","196","163","222","231","127","241","77","68","32","62","79","44","58","14","187","151","243","139","142","174","106","228","102","223","31","120","5","43","255","179","66","119","170","60","152","167","194","4","112","156","233","254","203","1","55","53","19","92","21","28","42"],["141","162","146","57","23","45","158","93","212","38","2","206","246","225","195","189","47","193","224","242","76","138","84","140","111","51","135","113","41","133","207","30","82","175","161","6","249","83","234","155","244","177","108","252","94","143","173","8","154","75","50","49","39","36","182","101","48","12","172","87","250","59","24","157","215","218","72","185","71","7","253","114","230","226","110","46","166","91","130","20","137","117","132","204","221","52","197","188","11","232","67","115","245","26","35","103","186","37","27","235","64","40","70","239","236","211","61","29","216","199","63","54","78","105","184","15","10","147","247","22","144","107","128","17","178","148","129","192"]]},"finalized":false,"execution_optimistic":false}` + "\n" - for _, c := range cases { - t.Run(c.blockID, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - resp, err := http.Get(server.URL + "/eth/v1/beacon/states/" + c.blockID + "/sync_committees") - require.NoError(t, err) - - defer resp.Body.Close() - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - // read the all of the octect - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.Equal(t, string(out), expected) - }) - } -} - -func TestGetStateSyncCommitteesHistorical(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, postState, handler, _, _, fcu := setupTestingHandler(t, clparams.BellatrixVersion) - - postRoot, err := postState.HashSSZ() - require.NoError(t, err) - - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - - fcu.JustifiedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) - - cases := []struct { - blockID string - code int - }{ - { - blockID: "0x" + common.Bytes2Hex(postRoot[:]), - code: http.StatusOK, - }, - { - blockID: "justified", - code: http.StatusOK, - }, - { - blockID: "0x" + common.Bytes2Hex(make([]byte, 32)), - code: http.StatusNotFound, - }, - { - blockID: strconv.FormatInt(int64(postState.Slot()), 10), - code: http.StatusOK, - }, - } - expected := `{"data":{"validators":["109","134","145","89","181","81","159","168","34","251","3","205","213","202","99","121","80","149","18","65","201","227","116","69","100","74","160","198","16","131","0","73","210","122","209","217","97","237","136","98","229","248","176","95","150","171","238","191","200","220","33","219","126","9","214","124","56","86","169","208","125","85","25","88","13","190","153","183","96","165","180","90","164","104","240","123","118","196","163","222","231","127","241","77","68","32","62","79","44","58","14","187","151","243","139","142","174","106","228","102","223","31","120","5","43","255","179","66","119","170","60","152","167","194","4","112","156","233","254","203","1","55","53","19","92","21","28","42","141","162","146","57","23","45","158","93","212","38","2","206","246","225","195","189","47","193","224","242","76","138","84","140","111","51","135","113","41","133","207","30","82","175","161","6","249","83","234","155","244","177","108","252","94","143","173","8","154","75","50","49","39","36","182","101","48","12","172","87","250","59","24","157","215","218","72","185","71","7","253","114","230","226","110","46","166","91","130","20","137","117","132","204","221","52","197","188","11","232","67","115","245","26","35","103","186","37","27","235","64","40","70","239","236","211","61","29","216","199","63","54","78","105","184","15","10","147","247","22","144","107","128","17","178","148","129","192","109","134","145","89","181","81","159","168","34","251","3","205","213","202","99","121","80","149","18","65","201","227","116","69","100","74","160","198","16","131","0","73","210","122","209","217","97","237","136","98","229","248","176","95","150","171","238","191","200","220","33","219","126","9","214","124","56","86","169","208","125","85","25","88","13","190","153","183","96","165","180","90","164","104","240","123","118","196","163","222","231","127","241","77","68","32","62","79","44","58","14","187","151","243","139","142","174","106","228","102","223","31","120","5","43","255","179","66","119","170","60","152","167","194","4","112","156","233","254","203","1","55","53","19","92","21","28","42","141","162","146","57","23","45","158","93","212","38","2","206","246","225","195","189","47","193","224","242","76","138","84","140","111","51","135","113","41","133","207","30","82","175","161","6","249","83","234","155","244","177","108","252","94","143","173","8","154","75","50","49","39","36","182","101","48","12","172","87","250","59","24","157","215","218","72","185","71","7","253","114","230","226","110","46","166","91","130","20","137","117","132","204","221","52","197","188","11","232","67","115","245","26","35","103","186","37","27","235","64","40","70","239","236","211","61","29","216","199","63","54","78","105","184","15","10","147","247","22","144","107","128","17","178","148","129","192"],"validator_aggregates":[["109","134","145","89","181","81","159","168","34","251","3","205","213","202","99","121","80","149","18","65","201","227","116","69","100","74","160","198","16","131","0","73","210","122","209","217","97","237","136","98","229","248","176","95","150","171","238","191","200","220","33","219","126","9","214","124","56","86","169","208","125","85","25","88","13","190","153","183","96","165","180","90","164","104","240","123","118","196","163","222","231","127","241","77","68","32","62","79","44","58","14","187","151","243","139","142","174","106","228","102","223","31","120","5","43","255","179","66","119","170","60","152","167","194","4","112","156","233","254","203","1","55","53","19","92","21","28","42"],["141","162","146","57","23","45","158","93","212","38","2","206","246","225","195","189","47","193","224","242","76","138","84","140","111","51","135","113","41","133","207","30","82","175","161","6","249","83","234","155","244","177","108","252","94","143","173","8","154","75","50","49","39","36","182","101","48","12","172","87","250","59","24","157","215","218","72","185","71","7","253","114","230","226","110","46","166","91","130","20","137","117","132","204","221","52","197","188","11","232","67","115","245","26","35","103","186","37","27","235","64","40","70","239","236","211","61","29","216","199","63","54","78","105","184","15","10","147","247","22","144","107","128","17","178","148","129","192"],["109","134","145","89","181","81","159","168","34","251","3","205","213","202","99","121","80","149","18","65","201","227","116","69","100","74","160","198","16","131","0","73","210","122","209","217","97","237","136","98","229","248","176","95","150","171","238","191","200","220","33","219","126","9","214","124","56","86","169","208","125","85","25","88","13","190","153","183","96","165","180","90","164","104","240","123","118","196","163","222","231","127","241","77","68","32","62","79","44","58","14","187","151","243","139","142","174","106","228","102","223","31","120","5","43","255","179","66","119","170","60","152","167","194","4","112","156","233","254","203","1","55","53","19","92","21","28","42"],["141","162","146","57","23","45","158","93","212","38","2","206","246","225","195","189","47","193","224","242","76","138","84","140","111","51","135","113","41","133","207","30","82","175","161","6","249","83","234","155","244","177","108","252","94","143","173","8","154","75","50","49","39","36","182","101","48","12","172","87","250","59","24","157","215","218","72","185","71","7","253","114","230","226","110","46","166","91","130","20","137","117","132","204","221","52","197","188","11","232","67","115","245","26","35","103","186","37","27","235","64","40","70","239","236","211","61","29","216","199","63","54","78","105","184","15","10","147","247","22","144","107","128","17","178","148","129","192"]]},"finalized":false,"execution_optimistic":false}` + "\n" - for _, c := range cases { - t.Run(c.blockID, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - resp, err := http.Get(server.URL + "/eth/v1/beacon/states/" + c.blockID + "/sync_committees") - require.NoError(t, err) - - defer resp.Body.Close() - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - // read the all of the octect - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.Equal(t, string(out), expected) - }) - } -} - -func TestGetStateFinalityCheckpoints(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, postState, handler, _, _, fcu := setupTestingHandler(t, clparams.BellatrixVersion) - - postRoot, err := postState.HashSSZ() - require.NoError(t, err) - - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - - fcu.JustifiedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) - - cases := []struct { - blockID string - code int - }{ - { - blockID: "0x" + common.Bytes2Hex(postRoot[:]), - code: http.StatusOK, - }, - { - blockID: "justified", - code: http.StatusOK, - }, - { - blockID: "0x" + common.Bytes2Hex(make([]byte, 32)), - code: http.StatusNotFound, - }, - { - blockID: strconv.FormatInt(int64(postState.Slot()), 10), - code: http.StatusOK, - }, - } - expected := `{"data":{"finalized_checkpoint":{"epoch":"1","root":"0xde46b0f2ed5e72f0cec20246403b14c963ec995d7c2825f3532b0460c09d5693"},"current_justified_checkpoint":{"epoch":"3","root":"0xa6e47f164b1a3ca30ea3b2144bd14711de442f51e5b634750a12a1734e24c987"},"previous_justified_checkpoint":{"epoch":"2","root":"0x4c3ee7969e485696669498a88c17f70e6999c40603e2f4338869004392069063"}},"finalized":false,"version":2,"execution_optimistic":false}` + "\n" - for _, c := range cases { - t.Run(c.blockID, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - resp, err := http.Get(server.URL + "/eth/v1/beacon/states/" + c.blockID + "/finality_checkpoints") - require.NoError(t, err) - - defer resp.Body.Close() - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - // read the all of the octect - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.Equal(t, string(out), expected) - }) - } -} - -func TestGetRandao(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, postState, handler, _, _, fcu := setupTestingHandler(t, clparams.BellatrixVersion) - - postRoot, err := postState.HashSSZ() - require.NoError(t, err) - - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - - fcu.JustifiedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) - - cases := []struct { - blockID string - code int - }{ - { - blockID: "0x" + common.Bytes2Hex(postRoot[:]), - code: http.StatusOK, - }, - { - blockID: "justified", - code: http.StatusOK, - }, - { - blockID: "0x" + common.Bytes2Hex(make([]byte, 32)), - code: http.StatusNotFound, - }, - { - blockID: strconv.FormatInt(int64(postState.Slot()), 10), - code: http.StatusOK, - }, - } - expected := `{"data":{"randao":"0xdeec617717272914bfd73e02ca1da113a83cf4cf33cd4939486509e2da4ccf4e"},"finalized":false,"execution_optimistic":false}` + "\n" - for _, c := range cases { - t.Run(c.blockID, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - resp, err := http.Get(server.URL + "/eth/v1/beacon/states/" + c.blockID + "/randao") - require.NoError(t, err) - - defer resp.Body.Close() - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - // read the all of the octect - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.Equal(t, string(out), expected) - }) - } -} diff --git a/cl/beacon/handler/test_data/attestations_1.json b/cl/beacon/handler/test_data/attestations_1.json new file mode 100644 index 00000000000..c73603b8912 --- /dev/null +++ b/cl/beacon/handler/test_data/attestations_1.json @@ -0,0 +1 @@ +{"data":{"ideal_rewards":[{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"}],"total_rewards":[{"validator_index":"0","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"1","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"2","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"3","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"4","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"5","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"6","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"7","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"8","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"9","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"10","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"11","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"12","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"13","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"14","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"15","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"16","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"17","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"18","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"19","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"20","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"21","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"22","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"23","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"24","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"25","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"26","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"27","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"28","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"29","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"30","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"31","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"32","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"33","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"34","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"35","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"36","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"37","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"38","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"39","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"40","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"41","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"42","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"43","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"44","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"45","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"46","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"47","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"48","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"49","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"50","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"51","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"52","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"53","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"54","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"55","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"56","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"57","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"58","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"59","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"60","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"61","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"62","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"63","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"64","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"65","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"66","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"67","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"68","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"69","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"70","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"71","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"72","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"73","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"74","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"75","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"76","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"77","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"78","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"79","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"80","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"81","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"82","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"83","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"84","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"85","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"86","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"87","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"88","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"89","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"90","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"91","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"92","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"93","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"94","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"95","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"96","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"97","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"98","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"99","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"100","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"101","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"102","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"103","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"104","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"105","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"106","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"107","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"108","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"109","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"110","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"111","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"112","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"113","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"114","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"115","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"116","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"117","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"118","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"119","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"120","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"121","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"122","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"123","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"124","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"125","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"126","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"127","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"128","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"129","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"130","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"131","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"132","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"133","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"134","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"135","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"136","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"137","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"138","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"139","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"140","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"141","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"142","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"143","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"144","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"145","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"146","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"147","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"148","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"149","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"150","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"151","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"152","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"153","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"154","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"155","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"156","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"157","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"158","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"159","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"160","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"161","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"162","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"163","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"164","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"165","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"166","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"167","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"168","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"169","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"170","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"171","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"172","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"173","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"174","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"175","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"176","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"177","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"178","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"179","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"180","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"181","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"182","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"183","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"184","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"185","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"186","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"187","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"188","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"189","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"190","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"191","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"192","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"193","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"194","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"195","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"196","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"197","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"198","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"199","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"200","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"201","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"202","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"203","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"204","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"205","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"206","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"207","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"208","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"209","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"210","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"211","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"212","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"213","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"214","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"215","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"216","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"217","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"218","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"219","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"220","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"221","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"222","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"223","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"224","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"225","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"226","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"227","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"228","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"229","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"230","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"231","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"232","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"233","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"234","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"235","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"236","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"237","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"238","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"239","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"240","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"241","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"242","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"243","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"244","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"245","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"246","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"247","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"248","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"249","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"250","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"251","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"252","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"253","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"254","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"255","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"}]}} diff --git a/cl/beacon/handler/test_data/attestations_2.json b/cl/beacon/handler/test_data/attestations_2.json new file mode 100644 index 00000000000..5f3b03eb6a9 --- /dev/null +++ b/cl/beacon/handler/test_data/attestations_2.json @@ -0,0 +1 @@ +{"data":{"ideal_rewards":[{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"290680","source":"0","inclusion_delay":"0","inactivity":"0"}],"total_rewards":[{"validator_index":"1","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"},{"validator_index":"4","head":"0","target":"290680","source":"-156520","inclusion_delay":"0","inactivity":"0"}]}} diff --git a/cl/beacon/handler/test_data/attestations_3.json b/cl/beacon/handler/test_data/attestations_3.json new file mode 100644 index 00000000000..10168612a39 --- /dev/null +++ b/cl/beacon/handler/test_data/attestations_3.json @@ -0,0 +1 @@ +{"data":{"ideal_rewards":[{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"20000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"25000000000","head":"84353","target":"84353","source":"84353","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"22000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"11151","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7871","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"66906","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"26000000000","head":"87727","target":"87727","source":"87727","inclusion_delay":"4348","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"6462","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"26762","inactivity":"0"},{"effective_balance":"20000000000","head":"67482","target":"67482","source":"67482","inclusion_delay":"4646","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"26000000000","head":"87727","target":"87727","source":"87727","inclusion_delay":"4941","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"24000000000","head":"80979","target":"80979","source":"80979","inclusion_delay":"9123","inactivity":"0"},{"effective_balance":"21000000000","head":"70856","target":"70856","source":"70856","inclusion_delay":"17562","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4181","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"25000000000","head":"84353","target":"84353","source":"84353","inclusion_delay":"17423","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"4181","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"4442","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"33453","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"25000000000","head":"84353","target":"84353","source":"84353","inclusion_delay":"4355","inactivity":"0"},{"effective_balance":"22000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3231","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"21000000000","head":"70856","target":"70856","source":"70856","inclusion_delay":"5854","inactivity":"0"},{"effective_balance":"18000000000","head":"60734","target":"60734","source":"60734","inclusion_delay":"8363","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"4442","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"11151","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"18000000000","head":"60734","target":"60734","source":"60734","inclusion_delay":"10752","inactivity":"0"},{"effective_balance":"30000000000","head":"101224","target":"101224","source":"101224","inclusion_delay":"3920","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"35543","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"9558","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5575","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"26000000000","head":"87727","target":"87727","source":"87727","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"10293","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2221","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"28000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4181","inactivity":"0"},{"effective_balance":"19000000000","head":"64108","target":"64108","source":"64108","inclusion_delay":"5675","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4956","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"33453","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3231","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"23000000000","head":"77605","target":"77605","source":"77605","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7871","inactivity":"0"},{"effective_balance":"27000000000","head":"91101","target":"91101","source":"91101","inclusion_delay":"3763","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"effective_balance":"23000000000","head":"77605","target":"77605","source":"77605","inclusion_delay":"10686","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"10293","inactivity":"0"},{"effective_balance":"24000000000","head":"80979","target":"80979","source":"80979","inclusion_delay":"4561","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"11151","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5575","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5923","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"33453","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2538","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"4442","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"19116","inactivity":"0"},{"effective_balance":"20000000000","head":"67482","target":"67482","source":"67482","inclusion_delay":"2697","inactivity":"0"},{"effective_balance":"22000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7871","inactivity":"0"},{"effective_balance":"23000000000","head":"77605","target":"77605","source":"77605","inclusion_delay":"8743","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"66906","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"7898","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"17771","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"26762","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"effective_balance":"19000000000","head":"64108","target":"64108","source":"64108","inclusion_delay":"5675","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"19000000000","head":"64108","target":"64108","source":"64108","inclusion_delay":"4673","inactivity":"0"},{"effective_balance":"26000000000","head":"87727","target":"87727","source":"87727","inclusion_delay":"4348","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"4181","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"effective_balance":"27000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"24000000000","head":"80979","target":"80979","source":"80979","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"4442","inactivity":"0"},{"effective_balance":"20000000000","head":"67482","target":"67482","source":"67482","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3949","inactivity":"0"},{"effective_balance":"28000000000","head":"94475","target":"94475","source":"94475","inclusion_delay":"7805","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"18000000000","head":"60734","target":"60734","source":"60734","inclusion_delay":"8363","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"6462","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2843","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"26762","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5468","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"23000000000","head":"77605","target":"77605","source":"77605","inclusion_delay":"3434","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2369","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"17771","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"31000000000","head":"104598","target":"104598","source":"104598","inclusion_delay":"5401","inactivity":"0"},{"effective_balance":"29000000000","head":"97850","target":"97850","source":"97850","inclusion_delay":"20211","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"11847","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2538","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"19116","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"19116","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2843","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"4181","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"effective_balance":"27000000000","head":"91101","target":"91101","source":"91101","inclusion_delay":"5131","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"9558","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2221","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"effective_balance":"23000000000","head":"77605","target":"77605","source":"77605","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"26000000000","head":"87727","target":"87727","source":"87727","inclusion_delay":"3507","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5077","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"effective_balance":"18000000000","head":"60734","target":"60734","source":"60734","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"21000000000","head":"70856","target":"70856","source":"70856","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"effective_balance":"29000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"effective_balance":"18000000000","head":"60734","target":"60734","source":"60734","inclusion_delay":"2508","inactivity":"0"},{"effective_balance":"28000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"28000000000","head":"94475","target":"94475","source":"94475","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"28000000000","head":"94475","target":"94475","source":"94475","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"31000000000","head":"104598","target":"104598","source":"104598","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"effective_balance":"21000000000","head":"70856","target":"70856","source":"70856","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7871","inactivity":"0"},{"effective_balance":"23000000000","head":"77605","target":"77605","source":"77605","inclusion_delay":"13739","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"19116","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"66906","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"effective_balance":"21000000000","head":"70856","target":"70856","source":"70856","inclusion_delay":"14635","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"effective_balance":"21000000000","head":"70856","target":"70856","source":"70856","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"effective_balance":"29000000000","head":"97850","target":"97850","source":"97850","inclusion_delay":"20211","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"effective_balance":"23000000000","head":"77605","target":"77605","source":"77605","inclusion_delay":"19235","inactivity":"0"},{"effective_balance":"18000000000","head":"60734","target":"60734","source":"60734","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"66906","inactivity":"0"},{"effective_balance":"30000000000","head":"101224","target":"101224","source":"101224","inclusion_delay":"5227","inactivity":"0"},{"effective_balance":"25000000000","head":"84353","target":"84353","source":"84353","inclusion_delay":"3604","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"27000000000","head":"91101","target":"91101","source":"91101","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"30000000000","head":"101224","target":"101224","source":"101224","inclusion_delay":"6272","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"17771","inactivity":"0"},{"effective_balance":"19000000000","head":"64108","target":"64108","source":"64108","inclusion_delay":"8827","inactivity":"0"},{"effective_balance":"24000000000","head":"80979","target":"80979","source":"80979","inclusion_delay":"20071","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"31000000000","head":"104598","target":"104598","source":"104598","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5923","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"effective_balance":"19000000000","head":"64108","target":"64108","source":"64108","inclusion_delay":"3310","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"effective_balance":"25000000000","head":"84353","target":"84353","source":"84353","inclusion_delay":"14934","inactivity":"0"},{"effective_balance":"26000000000","head":"87727","target":"87727","source":"87727","inclusion_delay":"54361","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"26762","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"20000000000","head":"67482","target":"67482","source":"67482","inclusion_delay":"3636","inactivity":"0"},{"effective_balance":"27000000000","head":"91101","target":"91101","source":"91101","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"19000000000","head":"64108","target":"64108","source":"64108","inclusion_delay":"6111","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"effective_balance":"24000000000","head":"80979","target":"80979","source":"80979","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"effective_balance":"25000000000","head":"84353","target":"84353","source":"84353","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"27000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3385","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5468","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"9558","inactivity":"0"},{"effective_balance":"20000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3385","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2843","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"9558","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"31000000000","head":"104598","target":"104598","source":"104598","inclusion_delay":"4470","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2369","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"effective_balance":"22000000000","head":"74230","target":"74230","source":"74230","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"26762","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"26000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"effective_balance":"23000000000","head":"77605","target":"77605","source":"77605","inclusion_delay":"3316","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"4181","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4181","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2538","inactivity":"0"},{"effective_balance":"25000000000","head":"84353","target":"84353","source":"84353","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5468","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2221","inactivity":"0"},{"effective_balance":"27000000000","head":"91101","target":"91101","source":"91101","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"66906","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"29000000000","head":"97850","target":"97850","source":"97850","inclusion_delay":"60633","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"effective_balance":"20000000000","head":"67482","target":"67482","source":"67482","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"7898","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"18000000000","head":"60734","target":"60734","source":"60734","inclusion_delay":"4704","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2843","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"25000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"10293","inactivity":"0"},{"effective_balance":"28000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"20000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"35543","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5575","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2293","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"4442","inactivity":"0"},{"effective_balance":"22000000000","head":"74230","target":"74230","source":"74230","inclusion_delay":"5110","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5923","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"effective_balance":"24000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"31000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2369","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"11847","inactivity":"0"},{"effective_balance":"27000000000","head":"91101","target":"91101","source":"91101","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2369","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"4739","inactivity":"0"},{"effective_balance":"18000000000","head":"60734","target":"60734","source":"60734","inclusion_delay":"4427","inactivity":"0"},{"effective_balance":"28000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5575","inactivity":"0"},{"effective_balance":"28000000000","head":"94475","target":"94475","source":"94475","inclusion_delay":"29271","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5575","inactivity":"0"},{"effective_balance":"30000000000","head":"101224","target":"101224","source":"101224","inclusion_delay":"25089","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"30000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"29000000000","head":"97850","target":"97850","source":"97850","inclusion_delay":"3789","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"21000000000","head":"70856","target":"70856","source":"70856","inclusion_delay":"7317","inactivity":"0"},{"effective_balance":"31000000000","head":"104598","target":"104598","source":"104598","inclusion_delay":"7201","inactivity":"0"},{"effective_balance":"22000000000","head":"74230","target":"74230","source":"74230","inclusion_delay":"5411","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"24000000000","head":"80979","target":"80979","source":"80979","inclusion_delay":"7168","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"effective_balance":"19000000000","head":"64108","target":"64108","source":"64108","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5468","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2843","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"10293","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3385","inactivity":"0"},{"effective_balance":"26000000000","head":"87727","target":"87727","source":"87727","inclusion_delay":"4530","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5077","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"effective_balance":"19000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5468","inactivity":"0"},{"effective_balance":"31000000000","head":"104598","target":"104598","source":"104598","inclusion_delay":"4050","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"17771","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2961","inactivity":"0"},{"effective_balance":"24000000000","head":"80979","target":"80979","source":"80979","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"30000000000","head":"101224","target":"101224","source":"101224","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5077","inactivity":"0"},{"effective_balance":"21000000000","head":"70856","target":"70856","source":"70856","inclusion_delay":"7983","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5923","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2538","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"29000000000","head":"97850","target":"97850","source":"97850","inclusion_delay":"5272","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"30000000000","head":"101224","target":"101224","source":"101224","inclusion_delay":"4646","inactivity":"0"},{"effective_balance":"19000000000","head":"64108","target":"64108","source":"64108","inclusion_delay":"39725","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2369","inactivity":"0"},{"effective_balance":"29000000000","head":"97850","target":"97850","source":"97850","inclusion_delay":"4181","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"11847","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"effective_balance":"31000000000","head":"104598","target":"104598","source":"104598","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"29000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"30000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4956","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"effective_balance":"22000000000","head":"74230","target":"74230","source":"74230","inclusion_delay":"22998","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"11151","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"effective_balance":"17000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2293","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"3385","inactivity":"0"},{"effective_balance":"22000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"2221","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"11151","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"4956","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"35543","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"5077","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"6462","inactivity":"0"},{"effective_balance":"32000000000","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"32000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"}],"total_rewards":[{"validator_index":"0","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"1","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"2","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-358422"},{"validator_index":"3","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"4","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"},{"validator_index":"5","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"validator_index":"6","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"7","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"8","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"9","head":"107972","target":"107972","source":"107972","inclusion_delay":"11151","inactivity":"0"},{"validator_index":"10","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"validator_index":"11","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"validator_index":"12","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"13","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"14","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"validator_index":"15","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"validator_index":"16","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"17","head":"107972","target":"107972","source":"107972","inclusion_delay":"7871","inactivity":"0"},{"validator_index":"18","head":"107972","target":"107972","source":"107972","inclusion_delay":"66906","inactivity":"0"},{"validator_index":"19","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"20","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"validator_index":"21","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"validator_index":"22","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"23","head":"87727","target":"87727","source":"87727","inclusion_delay":"4348","inactivity":"0"},{"validator_index":"24","head":"57360","target":"57360","source":"57360","inclusion_delay":"6462","inactivity":"0"},{"validator_index":"25","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"validator_index":"26","head":"107972","target":"107972","source":"107972","inclusion_delay":"26762","inactivity":"0"},{"validator_index":"27","head":"67482","target":"67482","source":"67482","inclusion_delay":"4646","inactivity":"0"},{"validator_index":"28","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"29","head":"87727","target":"87727","source":"87727","inclusion_delay":"4941","inactivity":"0"},{"validator_index":"30","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"31","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"32","head":"80979","target":"80979","source":"80979","inclusion_delay":"9123","inactivity":"0"},{"validator_index":"33","head":"70856","target":"70856","source":"70856","inclusion_delay":"17562","inactivity":"0"},{"validator_index":"34","head":"107972","target":"107972","source":"107972","inclusion_delay":"4181","inactivity":"0"},{"validator_index":"35","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"validator_index":"36","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"37","head":"84353","target":"84353","source":"84353","inclusion_delay":"17423","inactivity":"0"},{"validator_index":"38","head":"57360","target":"57360","source":"57360","inclusion_delay":"4181","inactivity":"0"},{"validator_index":"39","head":"57360","target":"57360","source":"57360","inclusion_delay":"4442","inactivity":"0"},{"validator_index":"40","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"41","head":"107972","target":"107972","source":"107972","inclusion_delay":"33453","inactivity":"0"},{"validator_index":"42","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"43","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"44","head":"84353","target":"84353","source":"84353","inclusion_delay":"4355","inactivity":"0"},{"validator_index":"45","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"46","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"47","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"48","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"validator_index":"49","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"validator_index":"50","head":"57360","target":"57360","source":"57360","inclusion_delay":"3231","inactivity":"0"},{"validator_index":"51","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"52","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"53","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"validator_index":"54","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"validator_index":"55","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"56","head":"70856","target":"70856","source":"70856","inclusion_delay":"5854","inactivity":"0"},{"validator_index":"57","head":"60734","target":"60734","source":"60734","inclusion_delay":"8363","inactivity":"0"},{"validator_index":"58","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"validator_index":"59","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"validator_index":"60","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"validator_index":"61","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"validator_index":"62","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"63","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"64","head":"57360","target":"57360","source":"57360","inclusion_delay":"4442","inactivity":"0"},{"validator_index":"65","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"validator_index":"66","head":"107972","target":"107972","source":"107972","inclusion_delay":"11151","inactivity":"0"},{"validator_index":"67","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"68","head":"60734","target":"60734","source":"60734","inclusion_delay":"10752","inactivity":"0"},{"validator_index":"69","head":"101224","target":"101224","source":"101224","inclusion_delay":"3920","inactivity":"0"},{"validator_index":"70","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"validator_index":"71","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"validator_index":"72","head":"57360","target":"57360","source":"57360","inclusion_delay":"35543","inactivity":"0"},{"validator_index":"73","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"74","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"75","head":"107972","target":"107972","source":"107972","inclusion_delay":"9558","inactivity":"0"},{"validator_index":"76","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"validator_index":"77","head":"107972","target":"107972","source":"107972","inclusion_delay":"5575","inactivity":"0"},{"validator_index":"78","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"79","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"80","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"81","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-372759"},{"validator_index":"82","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"83","head":"107972","target":"107972","source":"107972","inclusion_delay":"10293","inactivity":"0"},{"validator_index":"84","head":"57360","target":"57360","source":"57360","inclusion_delay":"2221","inactivity":"0"},{"validator_index":"85","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"},{"validator_index":"86","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"validator_index":"87","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"88","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"89","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"validator_index":"90","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"validator_index":"91","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"validator_index":"92","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"93","head":"107972","target":"107972","source":"107972","inclusion_delay":"4181","inactivity":"0"},{"validator_index":"94","head":"64108","target":"64108","source":"64108","inclusion_delay":"5675","inactivity":"0"},{"validator_index":"95","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"validator_index":"96","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"validator_index":"97","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"98","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"validator_index":"99","head":"107972","target":"107972","source":"107972","inclusion_delay":"4956","inactivity":"0"},{"validator_index":"100","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"validator_index":"101","head":"107972","target":"107972","source":"107972","inclusion_delay":"33453","inactivity":"0"},{"validator_index":"102","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"103","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"validator_index":"104","head":"57360","target":"57360","source":"57360","inclusion_delay":"3231","inactivity":"0"},{"validator_index":"105","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"106","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"107","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-329748"},{"validator_index":"108","head":"107972","target":"107972","source":"107972","inclusion_delay":"7871","inactivity":"0"},{"validator_index":"109","head":"91101","target":"91101","source":"91101","inclusion_delay":"3763","inactivity":"0"},{"validator_index":"110","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"validator_index":"111","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"112","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"113","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"validator_index":"114","head":"77605","target":"77605","source":"77605","inclusion_delay":"10686","inactivity":"0"},{"validator_index":"115","head":"107972","target":"107972","source":"107972","inclusion_delay":"10293","inactivity":"0"},{"validator_index":"116","head":"80979","target":"80979","source":"80979","inclusion_delay":"4561","inactivity":"0"},{"validator_index":"117","head":"107972","target":"107972","source":"107972","inclusion_delay":"11151","inactivity":"0"},{"validator_index":"118","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"119","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"120","head":"107972","target":"107972","source":"107972","inclusion_delay":"5575","inactivity":"0"},{"validator_index":"121","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"122","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"123","head":"57360","target":"57360","source":"57360","inclusion_delay":"5923","inactivity":"0"},{"validator_index":"124","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"125","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"validator_index":"126","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"validator_index":"127","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"128","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"129","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"130","head":"107972","target":"107972","source":"107972","inclusion_delay":"33453","inactivity":"0"},{"validator_index":"131","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"132","head":"57360","target":"57360","source":"57360","inclusion_delay":"2538","inactivity":"0"},{"validator_index":"133","head":"57360","target":"57360","source":"57360","inclusion_delay":"4442","inactivity":"0"},{"validator_index":"134","head":"107972","target":"107972","source":"107972","inclusion_delay":"19116","inactivity":"0"},{"validator_index":"135","head":"67482","target":"67482","source":"67482","inclusion_delay":"2697","inactivity":"0"},{"validator_index":"136","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"137","head":"107972","target":"107972","source":"107972","inclusion_delay":"7871","inactivity":"0"},{"validator_index":"138","head":"77605","target":"77605","source":"77605","inclusion_delay":"8743","inactivity":"0"},{"validator_index":"139","head":"107972","target":"107972","source":"107972","inclusion_delay":"66906","inactivity":"0"},{"validator_index":"140","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"141","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"validator_index":"142","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"143","head":"57360","target":"57360","source":"57360","inclusion_delay":"7898","inactivity":"0"},{"validator_index":"144","head":"57360","target":"57360","source":"57360","inclusion_delay":"17771","inactivity":"0"},{"validator_index":"145","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"146","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"validator_index":"147","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"148","head":"107972","target":"107972","source":"107972","inclusion_delay":"26762","inactivity":"0"},{"validator_index":"149","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"150","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"},{"validator_index":"151","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"152","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"validator_index":"153","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"validator_index":"154","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"validator_index":"155","head":"64108","target":"64108","source":"64108","inclusion_delay":"5675","inactivity":"0"},{"validator_index":"156","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"157","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"158","head":"64108","target":"64108","source":"64108","inclusion_delay":"4673","inactivity":"0"},{"validator_index":"159","head":"87727","target":"87727","source":"87727","inclusion_delay":"4348","inactivity":"0"},{"validator_index":"160","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"161","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"validator_index":"162","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"163","head":"57360","target":"57360","source":"57360","inclusion_delay":"4181","inactivity":"0"},{"validator_index":"164","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"165","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"validator_index":"166","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"167","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-344085"},{"validator_index":"168","head":"57360","target":"57360","source":"57360","inclusion_delay":"4442","inactivity":"0"},{"validator_index":"169","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-286737"},{"validator_index":"170","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"validator_index":"171","head":"57360","target":"57360","source":"57360","inclusion_delay":"3949","inactivity":"0"},{"validator_index":"172","head":"94475","target":"94475","source":"94475","inclusion_delay":"7805","inactivity":"0"},{"validator_index":"173","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"174","head":"60734","target":"60734","source":"60734","inclusion_delay":"8363","inactivity":"0"},{"validator_index":"175","head":"57360","target":"57360","source":"57360","inclusion_delay":"6462","inactivity":"0"},{"validator_index":"176","head":"57360","target":"57360","source":"57360","inclusion_delay":"2843","inactivity":"0"},{"validator_index":"177","head":"107972","target":"107972","source":"107972","inclusion_delay":"26762","inactivity":"0"},{"validator_index":"178","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"179","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"validator_index":"180","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"181","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"validator_index":"182","head":"57360","target":"57360","source":"57360","inclusion_delay":"5468","inactivity":"0"},{"validator_index":"183","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"validator_index":"184","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"185","head":"77605","target":"77605","source":"77605","inclusion_delay":"3434","inactivity":"0"},{"validator_index":"186","head":"57360","target":"57360","source":"57360","inclusion_delay":"2369","inactivity":"0"},{"validator_index":"187","head":"57360","target":"57360","source":"57360","inclusion_delay":"17771","inactivity":"0"},{"validator_index":"188","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"validator_index":"189","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"190","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"191","head":"104598","target":"104598","source":"104598","inclusion_delay":"5401","inactivity":"0"},{"validator_index":"192","head":"97850","target":"97850","source":"97850","inclusion_delay":"20211","inactivity":"0"},{"validator_index":"193","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"validator_index":"194","head":"57360","target":"57360","source":"57360","inclusion_delay":"11847","inactivity":"0"},{"validator_index":"195","head":"57360","target":"57360","source":"57360","inclusion_delay":"2538","inactivity":"0"},{"validator_index":"196","head":"107972","target":"107972","source":"107972","inclusion_delay":"19116","inactivity":"0"},{"validator_index":"197","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"validator_index":"198","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"validator_index":"199","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"200","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"},{"validator_index":"201","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"validator_index":"202","head":"107972","target":"107972","source":"107972","inclusion_delay":"19116","inactivity":"0"},{"validator_index":"203","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"204","head":"57360","target":"57360","source":"57360","inclusion_delay":"2843","inactivity":"0"},{"validator_index":"205","head":"57360","target":"57360","source":"57360","inclusion_delay":"4181","inactivity":"0"},{"validator_index":"206","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"validator_index":"207","head":"91101","target":"91101","source":"91101","inclusion_delay":"5131","inactivity":"0"},{"validator_index":"208","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"209","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"210","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"211","head":"107972","target":"107972","source":"107972","inclusion_delay":"9558","inactivity":"0"},{"validator_index":"212","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"213","head":"57360","target":"57360","source":"57360","inclusion_delay":"2221","inactivity":"0"},{"validator_index":"214","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"validator_index":"215","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-329748"},{"validator_index":"216","head":"87727","target":"87727","source":"87727","inclusion_delay":"3507","inactivity":"0"},{"validator_index":"217","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"validator_index":"218","head":"57360","target":"57360","source":"57360","inclusion_delay":"5077","inactivity":"0"},{"validator_index":"219","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"validator_index":"220","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"validator_index":"221","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"222","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"validator_index":"223","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-258063"},{"validator_index":"224","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-301074"},{"validator_index":"225","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"validator_index":"226","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"227","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"validator_index":"228","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"229","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"validator_index":"230","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"231","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"validator_index":"232","head":"60734","target":"60734","source":"60734","inclusion_delay":"2508","inactivity":"0"},{"validator_index":"233","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"234","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-401433"},{"validator_index":"235","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-401433"},{"validator_index":"236","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"237","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"238","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"239","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-444444"},{"validator_index":"240","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"241","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"242","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"validator_index":"243","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"244","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"validator_index":"245","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-301074"},{"validator_index":"246","head":"107972","target":"107972","source":"107972","inclusion_delay":"7871","inactivity":"0"},{"validator_index":"247","head":"77605","target":"77605","source":"77605","inclusion_delay":"13739","inactivity":"0"},{"validator_index":"248","head":"107972","target":"107972","source":"107972","inclusion_delay":"19116","inactivity":"0"},{"validator_index":"249","head":"107972","target":"107972","source":"107972","inclusion_delay":"66906","inactivity":"0"},{"validator_index":"250","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"validator_index":"251","head":"70856","target":"70856","source":"70856","inclusion_delay":"14635","inactivity":"0"},{"validator_index":"252","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"validator_index":"253","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-301074"},{"validator_index":"254","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"validator_index":"255","head":"97850","target":"97850","source":"97850","inclusion_delay":"20211","inactivity":"0"},{"validator_index":"256","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"257","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"validator_index":"258","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"validator_index":"259","head":"77605","target":"77605","source":"77605","inclusion_delay":"19235","inactivity":"0"},{"validator_index":"260","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-258063"},{"validator_index":"261","head":"107972","target":"107972","source":"107972","inclusion_delay":"66906","inactivity":"0"},{"validator_index":"262","head":"101224","target":"101224","source":"101224","inclusion_delay":"5227","inactivity":"0"},{"validator_index":"263","head":"84353","target":"84353","source":"84353","inclusion_delay":"3604","inactivity":"0"},{"validator_index":"264","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"validator_index":"265","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"266","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-387096"},{"validator_index":"267","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"268","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"269","head":"101224","target":"101224","source":"101224","inclusion_delay":"6272","inactivity":"0"},{"validator_index":"270","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"validator_index":"271","head":"57360","target":"57360","source":"57360","inclusion_delay":"17771","inactivity":"0"},{"validator_index":"272","head":"64108","target":"64108","source":"64108","inclusion_delay":"8827","inactivity":"0"},{"validator_index":"273","head":"80979","target":"80979","source":"80979","inclusion_delay":"20071","inactivity":"0"},{"validator_index":"274","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"275","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-444444"},{"validator_index":"276","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"277","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"validator_index":"278","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"validator_index":"279","head":"57360","target":"57360","source":"57360","inclusion_delay":"5923","inactivity":"0"},{"validator_index":"280","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"validator_index":"281","head":"64108","target":"64108","source":"64108","inclusion_delay":"3310","inactivity":"0"},{"validator_index":"282","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"283","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"284","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"validator_index":"285","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"286","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"287","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"validator_index":"288","head":"84353","target":"84353","source":"84353","inclusion_delay":"14934","inactivity":"0"},{"validator_index":"289","head":"87727","target":"87727","source":"87727","inclusion_delay":"54361","inactivity":"0"},{"validator_index":"290","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"291","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"292","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"293","head":"107972","target":"107972","source":"107972","inclusion_delay":"26762","inactivity":"0"},{"validator_index":"294","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"295","head":"67482","target":"67482","source":"67482","inclusion_delay":"3636","inactivity":"0"},{"validator_index":"296","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-387096"},{"validator_index":"297","head":"64108","target":"64108","source":"64108","inclusion_delay":"6111","inactivity":"0"},{"validator_index":"298","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"validator_index":"299","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"validator_index":"300","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-344085"},{"validator_index":"301","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"302","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"validator_index":"303","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-358422"},{"validator_index":"304","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"305","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"validator_index":"306","head":"57360","target":"57360","source":"57360","inclusion_delay":"3385","inactivity":"0"},{"validator_index":"307","head":"57360","target":"57360","source":"57360","inclusion_delay":"5468","inactivity":"0"},{"validator_index":"308","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"validator_index":"309","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"310","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"validator_index":"311","head":"107972","target":"107972","source":"107972","inclusion_delay":"9558","inactivity":"0"},{"validator_index":"312","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"313","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"314","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"validator_index":"315","head":"57360","target":"57360","source":"57360","inclusion_delay":"3385","inactivity":"0"},{"validator_index":"316","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"317","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"318","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"319","head":"57360","target":"57360","source":"57360","inclusion_delay":"2843","inactivity":"0"},{"validator_index":"320","head":"107972","target":"107972","source":"107972","inclusion_delay":"9558","inactivity":"0"},{"validator_index":"321","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"322","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"323","head":"104598","target":"104598","source":"104598","inclusion_delay":"4470","inactivity":"0"},{"validator_index":"324","head":"57360","target":"57360","source":"57360","inclusion_delay":"2369","inactivity":"0"},{"validator_index":"325","head":"107972","target":"107972","source":"107972","inclusion_delay":"8920","inactivity":"0"},{"validator_index":"326","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-315411"},{"validator_index":"327","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"328","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"validator_index":"329","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"330","head":"107972","target":"107972","source":"107972","inclusion_delay":"26762","inactivity":"0"},{"validator_index":"331","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"332","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"333","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"validator_index":"334","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"validator_index":"335","head":"77605","target":"77605","source":"77605","inclusion_delay":"3316","inactivity":"0"},{"validator_index":"336","head":"57360","target":"57360","source":"57360","inclusion_delay":"4181","inactivity":"0"},{"validator_index":"337","head":"107972","target":"107972","source":"107972","inclusion_delay":"4181","inactivity":"0"},{"validator_index":"338","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"339","head":"57360","target":"57360","source":"57360","inclusion_delay":"2538","inactivity":"0"},{"validator_index":"340","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-358422"},{"validator_index":"341","head":"57360","target":"57360","source":"57360","inclusion_delay":"5468","inactivity":"0"},{"validator_index":"342","head":"57360","target":"57360","source":"57360","inclusion_delay":"2221","inactivity":"0"},{"validator_index":"343","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-387096"},{"validator_index":"344","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"345","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"346","head":"107972","target":"107972","source":"107972","inclusion_delay":"66906","inactivity":"0"},{"validator_index":"347","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"348","head":"97850","target":"97850","source":"97850","inclusion_delay":"60633","inactivity":"0"},{"validator_index":"349","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"validator_index":"350","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-286737"},{"validator_index":"351","head":"57360","target":"57360","source":"57360","inclusion_delay":"7898","inactivity":"0"},{"validator_index":"352","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"353","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"},{"validator_index":"354","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"355","head":"60734","target":"60734","source":"60734","inclusion_delay":"4704","inactivity":"0"},{"validator_index":"356","head":"57360","target":"57360","source":"57360","inclusion_delay":"2843","inactivity":"0"},{"validator_index":"357","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"358","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"359","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"validator_index":"360","head":"107972","target":"107972","source":"107972","inclusion_delay":"10293","inactivity":"0"},{"validator_index":"361","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"362","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"363","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"validator_index":"364","head":"57360","target":"57360","source":"57360","inclusion_delay":"35543","inactivity":"0"},{"validator_index":"365","head":"107972","target":"107972","source":"107972","inclusion_delay":"5575","inactivity":"0"},{"validator_index":"366","head":"57360","target":"57360","source":"57360","inclusion_delay":"2293","inactivity":"0"},{"validator_index":"367","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"validator_index":"368","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"369","head":"57360","target":"57360","source":"57360","inclusion_delay":"4442","inactivity":"0"},{"validator_index":"370","head":"74230","target":"74230","source":"74230","inclusion_delay":"5110","inactivity":"0"},{"validator_index":"371","head":"57360","target":"57360","source":"57360","inclusion_delay":"5923","inactivity":"0"},{"validator_index":"372","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"373","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"validator_index":"374","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"validator_index":"375","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"376","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"377","head":"57360","target":"57360","source":"57360","inclusion_delay":"2369","inactivity":"0"},{"validator_index":"378","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"379","head":"57360","target":"57360","source":"57360","inclusion_delay":"11847","inactivity":"0"},{"validator_index":"380","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-387096"},{"validator_index":"381","head":"107972","target":"107972","source":"107972","inclusion_delay":"6372","inactivity":"0"},{"validator_index":"382","head":"57360","target":"57360","source":"57360","inclusion_delay":"2369","inactivity":"0"},{"validator_index":"383","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"384","head":"57360","target":"57360","source":"57360","inclusion_delay":"4739","inactivity":"0"},{"validator_index":"385","head":"60734","target":"60734","source":"60734","inclusion_delay":"4427","inactivity":"0"},{"validator_index":"386","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"387","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"validator_index":"388","head":"107972","target":"107972","source":"107972","inclusion_delay":"5575","inactivity":"0"},{"validator_index":"389","head":"94475","target":"94475","source":"94475","inclusion_delay":"29271","inactivity":"0"},{"validator_index":"390","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"391","head":"107972","target":"107972","source":"107972","inclusion_delay":"5575","inactivity":"0"},{"validator_index":"392","head":"101224","target":"101224","source":"101224","inclusion_delay":"25089","inactivity":"0"},{"validator_index":"393","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"394","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"395","head":"97850","target":"97850","source":"97850","inclusion_delay":"3789","inactivity":"0"},{"validator_index":"396","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"397","head":"70856","target":"70856","source":"70856","inclusion_delay":"7317","inactivity":"0"},{"validator_index":"398","head":"104598","target":"104598","source":"104598","inclusion_delay":"7201","inactivity":"0"},{"validator_index":"399","head":"74230","target":"74230","source":"74230","inclusion_delay":"5411","inactivity":"0"},{"validator_index":"400","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"401","head":"80979","target":"80979","source":"80979","inclusion_delay":"7168","inactivity":"0"},{"validator_index":"402","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"403","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"404","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"405","head":"107972","target":"107972","source":"107972","inclusion_delay":"4460","inactivity":"0"},{"validator_index":"406","head":"107972","target":"107972","source":"107972","inclusion_delay":"4316","inactivity":"0"},{"validator_index":"407","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-272400"},{"validator_index":"408","head":"57360","target":"57360","source":"57360","inclusion_delay":"5468","inactivity":"0"},{"validator_index":"409","head":"57360","target":"57360","source":"57360","inclusion_delay":"2843","inactivity":"0"},{"validator_index":"410","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"411","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"validator_index":"412","head":"107972","target":"107972","source":"107972","inclusion_delay":"10293","inactivity":"0"},{"validator_index":"413","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"validator_index":"414","head":"57360","target":"57360","source":"57360","inclusion_delay":"3385","inactivity":"0"},{"validator_index":"415","head":"87727","target":"87727","source":"87727","inclusion_delay":"4530","inactivity":"0"},{"validator_index":"416","head":"57360","target":"57360","source":"57360","inclusion_delay":"5077","inactivity":"0"},{"validator_index":"417","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"validator_index":"418","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"419","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"420","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"validator_index":"421","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"validator_index":"422","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"423","head":"107972","target":"107972","source":"107972","inclusion_delay":"22302","inactivity":"0"},{"validator_index":"424","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"425","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"validator_index":"426","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"427","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"validator_index":"428","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"validator_index":"429","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"validator_index":"430","head":"57360","target":"57360","source":"57360","inclusion_delay":"5468","inactivity":"0"},{"validator_index":"431","head":"104598","target":"104598","source":"104598","inclusion_delay":"4050","inactivity":"0"},{"validator_index":"432","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"433","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"434","head":"57360","target":"57360","source":"57360","inclusion_delay":"17771","inactivity":"0"},{"validator_index":"435","head":"57360","target":"57360","source":"57360","inclusion_delay":"2961","inactivity":"0"},{"validator_index":"436","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-344085"},{"validator_index":"437","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"438","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-430107"},{"validator_index":"439","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"440","head":"57360","target":"57360","source":"57360","inclusion_delay":"5077","inactivity":"0"},{"validator_index":"441","head":"70856","target":"70856","source":"70856","inclusion_delay":"7983","inactivity":"0"},{"validator_index":"442","head":"57360","target":"57360","source":"57360","inclusion_delay":"5923","inactivity":"0"},{"validator_index":"443","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"444","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"445","head":"57360","target":"57360","source":"57360","inclusion_delay":"2538","inactivity":"0"},{"validator_index":"446","head":"107972","target":"107972","source":"107972","inclusion_delay":"14868","inactivity":"0"},{"validator_index":"447","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"448","head":"97850","target":"97850","source":"97850","inclusion_delay":"5272","inactivity":"0"},{"validator_index":"449","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"450","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"451","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"validator_index":"452","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"453","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"454","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"455","head":"101224","target":"101224","source":"101224","inclusion_delay":"4646","inactivity":"0"},{"validator_index":"456","head":"64108","target":"64108","source":"64108","inclusion_delay":"39725","inactivity":"0"},{"validator_index":"457","head":"107972","target":"107972","source":"107972","inclusion_delay":"7434","inactivity":"0"},{"validator_index":"458","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"459","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"validator_index":"460","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"461","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"462","head":"57360","target":"57360","source":"57360","inclusion_delay":"3554","inactivity":"0"},{"validator_index":"463","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"464","head":"107972","target":"107972","source":"107972","inclusion_delay":"5817","inactivity":"0"},{"validator_index":"465","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"validator_index":"466","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"467","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"468","head":"57360","target":"57360","source":"57360","inclusion_delay":"2369","inactivity":"0"},{"validator_index":"469","head":"97850","target":"97850","source":"97850","inclusion_delay":"4181","inactivity":"0"},{"validator_index":"470","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"471","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"472","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"validator_index":"473","head":"57360","target":"57360","source":"57360","inclusion_delay":"10155","inactivity":"0"},{"validator_index":"474","head":"57360","target":"57360","source":"57360","inclusion_delay":"11847","inactivity":"0"},{"validator_index":"475","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"validator_index":"476","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-444444"},{"validator_index":"477","head":"107972","target":"107972","source":"107972","inclusion_delay":"6082","inactivity":"0"},{"validator_index":"478","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"validator_index":"479","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"480","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"481","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"validator_index":"482","head":"57360","target":"57360","source":"57360","inclusion_delay":"2632","inactivity":"0"},{"validator_index":"483","head":"107972","target":"107972","source":"107972","inclusion_delay":"12164","inactivity":"0"},{"validator_index":"484","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"485","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"486","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"487","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"488","head":"107972","target":"107972","source":"107972","inclusion_delay":"4956","inactivity":"0"},{"validator_index":"489","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"validator_index":"490","head":"74230","target":"74230","source":"74230","inclusion_delay":"22998","inactivity":"0"},{"validator_index":"491","head":"107972","target":"107972","source":"107972","inclusion_delay":"11151","inactivity":"0"},{"validator_index":"492","head":"107972","target":"107972","source":"107972","inclusion_delay":"4614","inactivity":"0"},{"validator_index":"493","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"494","head":"57360","target":"57360","source":"57360","inclusion_delay":"2293","inactivity":"0"},{"validator_index":"495","head":"57360","target":"57360","source":"57360","inclusion_delay":"3385","inactivity":"0"},{"validator_index":"496","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"497","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"498","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"499","head":"57360","target":"57360","source":"57360","inclusion_delay":"2221","inactivity":"0"},{"validator_index":"500","head":"107972","target":"107972","source":"107972","inclusion_delay":"6690","inactivity":"0"},{"validator_index":"501","head":"107972","target":"107972","source":"107972","inclusion_delay":"4779","inactivity":"0"},{"validator_index":"502","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-243726"},{"validator_index":"503","head":"107972","target":"107972","source":"107972","inclusion_delay":"11151","inactivity":"0"},{"validator_index":"504","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"-458781"},{"validator_index":"505","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"506","head":"107972","target":"107972","source":"107972","inclusion_delay":"8363","inactivity":"0"},{"validator_index":"507","head":"107972","target":"107972","source":"107972","inclusion_delay":"4956","inactivity":"0"},{"validator_index":"508","head":"57360","target":"57360","source":"57360","inclusion_delay":"35543","inactivity":"0"},{"validator_index":"509","head":"57360","target":"57360","source":"57360","inclusion_delay":"5077","inactivity":"0"},{"validator_index":"510","head":"57360","target":"57360","source":"57360","inclusion_delay":"6462","inactivity":"0"},{"validator_index":"511","head":"107972","target":"107972","source":"107972","inclusion_delay":"5352","inactivity":"0"},{"validator_index":"512","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"513","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"514","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"515","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"516","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"517","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"518","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"519","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"520","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"521","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"522","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"523","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"524","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"525","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"526","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"527","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"}]}} diff --git a/cl/beacon/handler/test_data/attestations_4.json b/cl/beacon/handler/test_data/attestations_4.json new file mode 100644 index 00000000000..0904e1e270a --- /dev/null +++ b/cl/beacon/handler/test_data/attestations_4.json @@ -0,0 +1 @@ +{"data":{"ideal_rewards":[{"effective_balance":"20000000000","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"effective_balance":"17000000000","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"}],"total_rewards":[{"validator_index":"1","head":"0","target":"0","source":"0","inclusion_delay":"0","inactivity":"0"},{"validator_index":"4","head":"57360","target":"57360","source":"57360","inclusion_delay":"14217","inactivity":"0"}]}} diff --git a/cl/beacon/handler/test_data/blinded_block_1.json b/cl/beacon/handler/test_data/blinded_block_1.json new file mode 100644 index 00000000000..de776b31230 --- /dev/null +++ b/cl/beacon/handler/test_data/blinded_block_1.json @@ -0,0 +1,1975 @@ +{ + "data": { + "signature": "0x8b915f3b9d2d4c7ccaacf5d56c1152b1e91eafd1f59ba734d09e78996930b63ca550499997fe6d590343aaf5997f0d0c14c986571992ac9ed188de2b31ae4b7d70dfb68edae8b012f72f284dc8da44f4af5a2bdf3dfc9c0897ec4f7165daa07a", + "message": { + "slot": "8322", + "proposer_index": "210", + "parent_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "state_root": "0x933d6650f2999f17012e781f5012981edb549e5935de1c981fce81cdd241d4e1", + "body": { + "randao_reveal": "0xa182a6c7224c53cc43492b7ba87b54e8303094ebcb8c822da09c4224791b461e34d089ac857acf05cd695679c25cffa30404832791fe424fd104e2e96ebbf583dd5ec4dcbc891e7f4e0dea402071dbd294810417221fc41e4f90e4837c694e1a", + "eth1_data": { + "deposit_root": "0x0000000000000000000000000000000000000000000000000000000000000000", + "deposit_count": "528", + "block_hash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "graffiti": "0x0000000000000000000000000000000000000000000000000000000000000000", + "proposer_slashings": [ + { + "signed_header_1": { + "message": { + "slot": "8321", + "proposer_index": "476", + "parent_root": "0x3333333333333333333333333333333333333333333333333333333333333333", + "state_root": "0x4444444444444444444444444444444444444444444444444444444444444444", + "body_root": "0x5555555555555555555555555555555555555555555555555555555555555555" + }, + "signature": "0x939584df88598e56fe144105c6933b4727d7b772539e65c57289df64cedee771377e4d0e94f85c25d39a6072997d309c09da8c477267670aa42f26fb0836c72ec5867fa2f34dc0eb7e043ef5d6421282d1515b0f8c7ffd4bbbf56ee8d61ed063" + }, + "signed_header_2": { + "message": { + "slot": "8321", + "proposer_index": "476", + "parent_root": "0x9999999999999999999999999999999999999999999999999999999999999999", + "state_root": "0x4444444444444444444444444444444444444444444444444444444444444444", + "body_root": "0x5555555555555555555555555555555555555555555555555555555555555555" + }, + "signature": "0x8a184441d5d944ed3c18549dd9e4640eda879f9e737ac4211fdddfd30a65e1a2a32a8aa918ca65ad9b863a15e8cfefc412608ca78fd54ea1e5cbbd5697d125cc721aac1b01e8984a33f025c4707623669573244a632ec7f37808c01fab143f58" + } + }, + { + "signed_header_1": { + "message": { + "slot": "8321", + "proposer_index": "406", + "parent_root": "0x3333333333333333333333333333333333333333333333333333333333333333", + "state_root": "0x4444444444444444444444444444444444444444444444444444444444444444", + "body_root": "0x5555555555555555555555555555555555555555555555555555555555555555" + }, + "signature": "0xad97a43e9f28a90ff46b07a7bf65d520b89a78af47dbff1c10e4fc6bb36b4ee9c4f27f2a72c65311a03e7b48e06d86db1149147b14a8803d46f6a457092642dc89d3f2782bd48a373e3125af1a84f5b76d4ff7ddc85ac2650ca4c0f99e1af592" + }, + "signed_header_2": { + "message": { + "slot": "8321", + "proposer_index": "406", + "parent_root": "0x9999999999999999999999999999999999999999999999999999999999999999", + "state_root": "0x4444444444444444444444444444444444444444444444444444444444444444", + "body_root": "0x5555555555555555555555555555555555555555555555555555555555555555" + }, + "signature": "0x88d860d460526de062ee196400e24cb3055de2ff6abb31331d0bfeeebcdc77839d22ad6dfec39d81279f5527d1ffbd7e0a9d6eee7dce5a1cd6f79451537e9dfb6384f595e9d49673c58c181527a599dd4b38154e1322f1607f192ab0394f1411" + } + }, + { + "signed_header_1": { + "message": { + "slot": "8321", + "proposer_index": "281", + "parent_root": "0x3333333333333333333333333333333333333333333333333333333333333333", + "state_root": "0x4444444444444444444444444444444444444444444444444444444444444444", + "body_root": "0x5555555555555555555555555555555555555555555555555555555555555555" + }, + "signature": "0x8a2358ff11a30100a2492001827f54ff6c10dd6dcea66f6814dd1cccc4a49850bbbe36546e4f9b72410042a9d5882e8219a5a01708b8a95ca57984debe78f419a4ac921270a0f0c11c795a6c5ef1e6bfb96712751a4fee61059ca8fbe69639b6" + }, + "signed_header_2": { + "message": { + "slot": "8321", + "proposer_index": "281", + "parent_root": "0x9999999999999999999999999999999999999999999999999999999999999999", + "state_root": "0x4444444444444444444444444444444444444444444444444444444444444444", + "body_root": "0x5555555555555555555555555555555555555555555555555555555555555555" + }, + "signature": "0xb820e03b7bfd21c2d97a4f2bc9dd1fd5325894757f7129646c7a39a02b2c1c8ca33d509b4e83491e79db02ac0490aa3308ee23bfa1f65bf4130ab07e377a8cbd4eace5b69801528322dde425b0a78310504c330da30be7cefc674573dbdb4502" + } + }, + { + "signed_header_1": { + "message": { + "slot": "8321", + "proposer_index": "169", + "parent_root": "0x3333333333333333333333333333333333333333333333333333333333333333", + "state_root": "0x4444444444444444444444444444444444444444444444444444444444444444", + "body_root": "0x5555555555555555555555555555555555555555555555555555555555555555" + }, + "signature": "0x88c81a6029f097a9f23e37c7677abfafa2921982e9aebffc35ca700e1aefcd49c2ab5d51c7b28ef3db3aad49d58a6407082ce1ecd7f7bd89cb764242890440b684fc0e1511e047434b25f3ad1a5e238e5bf97f51e9e37d6eed48e0b9fef64333" + }, + "signed_header_2": { + "message": { + "slot": "8321", + "proposer_index": "169", + "parent_root": "0x9999999999999999999999999999999999999999999999999999999999999999", + "state_root": "0x4444444444444444444444444444444444444444444444444444444444444444", + "body_root": "0x5555555555555555555555555555555555555555555555555555555555555555" + }, + "signature": "0x815b492a6a3fb606f01dbc595c8b18b51b7f7a5a86b11f3ae57c48f7506a34606556a3cf2be683ce23cd0c7b2235667613f9dbcf98408b176f134645f122684bd8fe704c7a4eccb7bb7cbe33c6de377be4d742291d35d0ec8d6083c1b17b7261" + } + }, + { + "signed_header_1": { + "message": { + "slot": "8321", + "proposer_index": "397", + "parent_root": "0x3333333333333333333333333333333333333333333333333333333333333333", + "state_root": "0x4444444444444444444444444444444444444444444444444444444444444444", + "body_root": "0x5555555555555555555555555555555555555555555555555555555555555555" + }, + "signature": "0xae352ba8550d04c07591224449bd4967f66f9d639b731795f643b1e3fc5ad28317268dc9e289ce6075e8981a0e37d9440885e4f4292cb4b4656bd0c7bd9fc22d21eb4c7d1b46f1b08cdb1eb08d7a405985e8a406e6d93c5c3fdd20e91baba122" + }, + "signed_header_2": { + "message": { + "slot": "8321", + "proposer_index": "397", + "parent_root": "0x9999999999999999999999999999999999999999999999999999999999999999", + "state_root": "0x4444444444444444444444444444444444444444444444444444444444444444", + "body_root": "0x5555555555555555555555555555555555555555555555555555555555555555" + }, + "signature": "0xb9152f5510f2bfa5ab7b61829823f25f0c879ab9b852fcd90c17f751bed6e687dc523fcda177503509cd1befec36046a056a66f5826e2333b6de67430a16f6194416681ae69a1c3498cf8351abae4fac5d8f0b51b1734633d545d540bf269270" + } + } + ], + "attester_slashings": [ + { + "attestation_1": { + "attesting_indicies": [ + "96", + "353", + "445" + ], + "data": { + "slot": "555", + "index": "0", + "beacon_block_root": "0x0000000000000000000000000000000000000000000000000000000000000000", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "17", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + }, + "signature": "0xa7e932307a82913b23743198182a7e3c97675e8a1133e8d946bc59c62b1765046214ca0ea0e13b77e4f8acc8f226498103684f382826a9fff6c6c2ffdf9c65ffeb1680155025f489f676457634581ee4363bdfbe4d46fc4d1d9df93c3df8750d" + }, + "attestation_2": { + "attesting_indicies": [ + "96", + "353", + "445" + ], + "data": { + "slot": "555", + "index": "0", + "beacon_block_root": "0x0000000000000000000000000000000000000000000000000000000000000000", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "17", + "root": "0x0101010101010101010101010101010101010101010101010101010101010101" + } + }, + "signature": "0x89aadbd74370dc6d86b6b61c544c1e18949b0d8aa2d706605d1014d0266a043588a829243d343d1c3812621944ea34540aef1fbd34fe51b03a5734ebc5ec31057d1df0004faeca71d8687dd3af806e4332e19f6da5ab1d7da67fe017c2f2e68b" + } + } + ], + "attestations": [ + { + "aggregation_bits": "0xff3f", + "signature": "0x8b63c286bff1c5dc6fb2e4878e73631e16db1cd3b07e9d0150b3ede4175635fe8db571cb486398e35923640606643d630bacc148d84e9c1060c32b55fe644e5c2573326b041767c5d45d45509a5403a7f2f1b2dd60e54bed26f407bb367a8642", + "data": { + "slot": "8314", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0xb731b2df4dcaf841d50747f85b332170471895508c3af7e8bada14e58a816fed435460e1694e87e2887f19a0de201c3d0bc1ece52c26c519fd9131b25fa8a69b229c14ffd1c935d9e853aca8ab07eaae98a65daec09b2640b91961685e96d58c", + "data": { + "slot": "8292", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x876c656d7889c15cd355d6652b347a25dc8fd7ffc383f0d14ad436b5f1af9ac09e06168ad71be76b85c3dd44ae79cc0f04f250a0bcc529d06a1032283e2b8b384d582c0ace50bf747264a199647697f159d06be75ecfb24da2a8b625a3087804", + "data": { + "slot": "8293", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x876c656d7889c15cd355d6652b347a25dc8fd7ffc383f0d14ad436b5f1af9ac09e06168ad71be76b85c3dd44ae79cc0f04f250a0bcc529d06a1032283e2b8b384d582c0ace50bf747264a199647697f159d06be75ecfb24da2a8b625a3087804", + "data": { + "slot": "8293", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x98416260b644654a4a90bda6032053f1eb3a12c59a3c7534f1ef348f2108c2837245bce74b3fd9f61ebae24860cc698100f864c4f26966c36431acbf0beea679807ba4eba9adfd1a267ef8d990290a2548af6456b1d0def6639ac47fd30c5542", + "data": { + "slot": "8317", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x805e92ba1e4c88489f178202ca5d7ce96e7b874fe98bdee80ab6423441bd37ff3f0fe724bc088f58050ac2a8f81ec5e80401d76caeb65795b5794e7a20d0384f3bfd162b281a17e96cc98087c651d893b05154203af7a7591afe1056db934ec4", + "data": { + "slot": "8309", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527", + "data": { + "slot": "8313", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x95bbaf8dcff64306f01e0b09b27ebe3c761def7edd75542e213586ee0c6d3fc313ae102760abd1262b4f8c00e57603fa01627390011e3a5dea555c74798d7a3e1da68e00e3cdb9d8e4af112b6ff83951bd926288d24eb82e3f203a3160a4d7a9", + "data": { + "slot": "8312", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x894270af1854ce4e65c6e09bc83c15171d564a2af871d0b442cacea78536e5cd34cf4a906025a6d87e12a172ceeb79990b86a1de7ed4ef40cffeca6b93402c3542682bb2914c34430e23038a57e8490abe809dc9f96f3b2caebed380113280b3", + "data": { + "slot": "8297", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0xa44792a6341475c3eff0c11ad62bc19154d5ed48a4b81869ed49885499d5f768c81f357dd6a3ea60aa2f15a184b098f40a1382cfaea0a8438d62d9cca27c85023245b1838e2e4f1d4e65926f8c6a3032740b36c0a3c8aa69850648ac6c12b3ce", + "data": { + "slot": "8306", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x98aade2cf9dad0e1528edec0e76be15577601b6cbef68353e51748b6286bf08812e42fe8791147a54eeed34782249e3f0cc463e22d6cb1c6050636ca8d070531fe40e16913f2e5560f6e683a6781268ff08d32bc5899b00306a87eecc5603928", + "data": { + "slot": "8290", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0xab42974cba2e3fa75faa4c1f717caf7c2a953f4964063462ed32629764336124fd2f2f430ddf0291325722206250452c109b14cded0e51171b89b106b6b2044291128c3d6966c804490033b9e5fd06450ea50d22b5ab761892c6c3f4de79e098", + "data": { + "slot": "8291", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x8d852ffa1c5960ba3a5d09837fbdb859bbf9045001b3d1dc1c4d22c6b4bc5b6d506f6ef667b5c7c9fbfb1dd0cfe3617405f56750f8b5eb25b3539d0a4c94822b198c524de92a6c68982ce17f985ff5283cea6ac8dabe41828ce38edb7e9fe223", + "data": { + "slot": "8311", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x8bfaed4667e28ed9e39464c7c57027ae345f22847b6ac1aa7e5f342fdb6cdca9d78a962da68f9e34e0453f68fa363fcd196881e2dd76abcab6814439d73448f404124ad2e2f57b59b0df57699d913e24f79c53f129a09c05f2659e4444f4bb53", + "data": { + "slot": "8320", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "258", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "260", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x97426dbbe61af8a68ac683ba95ad871baade096e9287e2d533c1efba04430b7083283485db5b1624fb03639065e8c754155cfe68986d526c1a771b67e45c0e8c97428dee8c6d80cc68892b961e8352d50f34e2623dc3b7ba2cb5dba28a854079", + "data": { + "slot": "8302", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x94fab4732e767881653a5923ca4a93fc2778d349cef972b077aa0fd2553946f578be6571d7a02fe14aa98b11a77475e115bc8062308b23a23c6ce71cd07c528a6e37d30324d57dcc36fa336575210bce5d71ccabf74f0dd96f839eefc1a49343", + "data": { + "slot": "8296", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x8b63c286bff1c5dc6fb2e4878e73631e16db1cd3b07e9d0150b3ede4175635fe8db571cb486398e35923640606643d630bacc148d84e9c1060c32b55fe644e5c2573326b041767c5d45d45509a5403a7f2f1b2dd60e54bed26f407bb367a8642", + "data": { + "slot": "8314", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x805e92ba1e4c88489f178202ca5d7ce96e7b874fe98bdee80ab6423441bd37ff3f0fe724bc088f58050ac2a8f81ec5e80401d76caeb65795b5794e7a20d0384f3bfd162b281a17e96cc98087c651d893b05154203af7a7591afe1056db934ec4", + "data": { + "slot": "8309", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527", + "data": { + "slot": "8313", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0xb60160a4024734b6c22e6083d755d97b22d107001965d35cd1aa5fc3c1059b4cb482c36c78609c0fa131631eb847d165177c877949e5baebb96a48f6e471c1d1d700619b4adeafa728b4d69de8d03d02854e4240d8e16d790168619cc2027247", + "data": { + "slot": "8318", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527", + "data": { + "slot": "8313", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x8b1fbaba2982cd546a7d19d4af3755163112349a0e6d13f05c69807c709f363359c2cfff8a4afa66bd24445eb12b923615c33892a82d8081575207e4165a1d0c944fd3871ff885662c3921b152e674130879d67a0692b4867ad9fc2d20e24fa3", + "data": { + "slot": "8307", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0xa44792a6341475c3eff0c11ad62bc19154d5ed48a4b81869ed49885499d5f768c81f357dd6a3ea60aa2f15a184b098f40a1382cfaea0a8438d62d9cca27c85023245b1838e2e4f1d4e65926f8c6a3032740b36c0a3c8aa69850648ac6c12b3ce", + "data": { + "slot": "8306", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x8b1fbaba2982cd546a7d19d4af3755163112349a0e6d13f05c69807c709f363359c2cfff8a4afa66bd24445eb12b923615c33892a82d8081575207e4165a1d0c944fd3871ff885662c3921b152e674130879d67a0692b4867ad9fc2d20e24fa3", + "data": { + "slot": "8307", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0xab42974cba2e3fa75faa4c1f717caf7c2a953f4964063462ed32629764336124fd2f2f430ddf0291325722206250452c109b14cded0e51171b89b106b6b2044291128c3d6966c804490033b9e5fd06450ea50d22b5ab761892c6c3f4de79e098", + "data": { + "slot": "8291", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x9494651d4491cfc326f3439cebc3304aaf50a8e5598217da6df2a13b5cb9f9731cc8934f406c0243786b17f936d5892801fc34fc74fb4f52fec147536375dabd9f892940aacdea196e28cb21320bce9ede79b0a11333569d90e6deeb59869217", + "data": { + "slot": "8300", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x87c3f6fac9ea937a8e8bd4f6dccb7893cb8ea39c65e0313a30e903c220dba2c8597df1d75ee21fd905eab1ebf2261ebf085b13115363d72adc9ccd9527293b7218c39e94c257c94a8c95c32cf909cf58e8b7ece89a9bd21107a413b3fe3172e0", + "data": { + "slot": "8304", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x94fab4732e767881653a5923ca4a93fc2778d349cef972b077aa0fd2553946f578be6571d7a02fe14aa98b11a77475e115bc8062308b23a23c6ce71cd07c528a6e37d30324d57dcc36fa336575210bce5d71ccabf74f0dd96f839eefc1a49343", + "data": { + "slot": "8296", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x97426dbbe61af8a68ac683ba95ad871baade096e9287e2d533c1efba04430b7083283485db5b1624fb03639065e8c754155cfe68986d526c1a771b67e45c0e8c97428dee8c6d80cc68892b961e8352d50f34e2623dc3b7ba2cb5dba28a854079", + "data": { + "slot": "8302", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x94fab4732e767881653a5923ca4a93fc2778d349cef972b077aa0fd2553946f578be6571d7a02fe14aa98b11a77475e115bc8062308b23a23c6ce71cd07c528a6e37d30324d57dcc36fa336575210bce5d71ccabf74f0dd96f839eefc1a49343", + "data": { + "slot": "8296", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x98416260b644654a4a90bda6032053f1eb3a12c59a3c7534f1ef348f2108c2837245bce74b3fd9f61ebae24860cc698100f864c4f26966c36431acbf0beea679807ba4eba9adfd1a267ef8d990290a2548af6456b1d0def6639ac47fd30c5542", + "data": { + "slot": "8317", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x8b1fbaba2982cd546a7d19d4af3755163112349a0e6d13f05c69807c709f363359c2cfff8a4afa66bd24445eb12b923615c33892a82d8081575207e4165a1d0c944fd3871ff885662c3921b152e674130879d67a0692b4867ad9fc2d20e24fa3", + "data": { + "slot": "8307", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x894270af1854ce4e65c6e09bc83c15171d564a2af871d0b442cacea78536e5cd34cf4a906025a6d87e12a172ceeb79990b86a1de7ed4ef40cffeca6b93402c3542682bb2914c34430e23038a57e8490abe809dc9f96f3b2caebed380113280b3", + "data": { + "slot": "8297", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x98aade2cf9dad0e1528edec0e76be15577601b6cbef68353e51748b6286bf08812e42fe8791147a54eeed34782249e3f0cc463e22d6cb1c6050636ca8d070531fe40e16913f2e5560f6e683a6781268ff08d32bc5899b00306a87eecc5603928", + "data": { + "slot": "8290", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x805e92ba1e4c88489f178202ca5d7ce96e7b874fe98bdee80ab6423441bd37ff3f0fe724bc088f58050ac2a8f81ec5e80401d76caeb65795b5794e7a20d0384f3bfd162b281a17e96cc98087c651d893b05154203af7a7591afe1056db934ec4", + "data": { + "slot": "8309", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0xa44792a6341475c3eff0c11ad62bc19154d5ed48a4b81869ed49885499d5f768c81f357dd6a3ea60aa2f15a184b098f40a1382cfaea0a8438d62d9cca27c85023245b1838e2e4f1d4e65926f8c6a3032740b36c0a3c8aa69850648ac6c12b3ce", + "data": { + "slot": "8306", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0xa44792a6341475c3eff0c11ad62bc19154d5ed48a4b81869ed49885499d5f768c81f357dd6a3ea60aa2f15a184b098f40a1382cfaea0a8438d62d9cca27c85023245b1838e2e4f1d4e65926f8c6a3032740b36c0a3c8aa69850648ac6c12b3ce", + "data": { + "slot": "8306", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x980e36beab885b1f2d8460e7ece21054e9d235fea5429836bc6df687e0c2f41b7556d9c86cd9c1ca7a69e5a51991b8d617eea619ba8e312d568e38f8de8adb8b4a9ec3e9dab2d47df45b35d9f2488236c042d66cd0916fee70e8a3295353b0ed", + "data": { + "slot": "8308", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527", + "data": { + "slot": "8313", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0xb60160a4024734b6c22e6083d755d97b22d107001965d35cd1aa5fc3c1059b4cb482c36c78609c0fa131631eb847d165177c877949e5baebb96a48f6e471c1d1d700619b4adeafa728b4d69de8d03d02854e4240d8e16d790168619cc2027247", + "data": { + "slot": "8318", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0xb731b2df4dcaf841d50747f85b332170471895508c3af7e8bada14e58a816fed435460e1694e87e2887f19a0de201c3d0bc1ece52c26c519fd9131b25fa8a69b229c14ffd1c935d9e853aca8ab07eaae98a65daec09b2640b91961685e96d58c", + "data": { + "slot": "8292", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x8b63c286bff1c5dc6fb2e4878e73631e16db1cd3b07e9d0150b3ede4175635fe8db571cb486398e35923640606643d630bacc148d84e9c1060c32b55fe644e5c2573326b041767c5d45d45509a5403a7f2f1b2dd60e54bed26f407bb367a8642", + "data": { + "slot": "8314", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x906fd8d1a45b719a36eb5e09b5e13f9d0fb7faaa194d84b90e0b2b811ce299f385bf18bb07844620ec032b6f267d04781480dc303081be7c5d8ba735bccd682dd3ddb6345bae13bd96068eb86b148e73b8931b642705b1696d9ada4159b1dd65", + "data": { + "slot": "8305", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x9494651d4491cfc326f3439cebc3304aaf50a8e5598217da6df2a13b5cb9f9731cc8934f406c0243786b17f936d5892801fc34fc74fb4f52fec147536375dabd9f892940aacdea196e28cb21320bce9ede79b0a11333569d90e6deeb59869217", + "data": { + "slot": "8300", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x98416260b644654a4a90bda6032053f1eb3a12c59a3c7534f1ef348f2108c2837245bce74b3fd9f61ebae24860cc698100f864c4f26966c36431acbf0beea679807ba4eba9adfd1a267ef8d990290a2548af6456b1d0def6639ac47fd30c5542", + "data": { + "slot": "8317", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527", + "data": { + "slot": "8313", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x980e36beab885b1f2d8460e7ece21054e9d235fea5429836bc6df687e0c2f41b7556d9c86cd9c1ca7a69e5a51991b8d617eea619ba8e312d568e38f8de8adb8b4a9ec3e9dab2d47df45b35d9f2488236c042d66cd0916fee70e8a3295353b0ed", + "data": { + "slot": "8308", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527", + "data": { + "slot": "8313", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x815ca84fb30789d731ebf977b6ecdd60c30818202d464acdc2947143f62342c4a5d01c6cdb32b1e223d032c746fa98d30899164e6ab37828e6d049f32e46a5c59d742d82005f9a629938761e3abce454cec104352665cd81bbcffa2fce22a935", + "data": { + "slot": "8299", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527", + "data": { + "slot": "8313", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x906fd8d1a45b719a36eb5e09b5e13f9d0fb7faaa194d84b90e0b2b811ce299f385bf18bb07844620ec032b6f267d04781480dc303081be7c5d8ba735bccd682dd3ddb6345bae13bd96068eb86b148e73b8931b642705b1696d9ada4159b1dd65", + "data": { + "slot": "8305", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x906fd8d1a45b719a36eb5e09b5e13f9d0fb7faaa194d84b90e0b2b811ce299f385bf18bb07844620ec032b6f267d04781480dc303081be7c5d8ba735bccd682dd3ddb6345bae13bd96068eb86b148e73b8931b642705b1696d9ada4159b1dd65", + "data": { + "slot": "8305", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x876c656d7889c15cd355d6652b347a25dc8fd7ffc383f0d14ad436b5f1af9ac09e06168ad71be76b85c3dd44ae79cc0f04f250a0bcc529d06a1032283e2b8b384d582c0ace50bf747264a199647697f159d06be75ecfb24da2a8b625a3087804", + "data": { + "slot": "8293", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x876c656d7889c15cd355d6652b347a25dc8fd7ffc383f0d14ad436b5f1af9ac09e06168ad71be76b85c3dd44ae79cc0f04f250a0bcc529d06a1032283e2b8b384d582c0ace50bf747264a199647697f159d06be75ecfb24da2a8b625a3087804", + "data": { + "slot": "8293", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x8bfaed4667e28ed9e39464c7c57027ae345f22847b6ac1aa7e5f342fdb6cdca9d78a962da68f9e34e0453f68fa363fcd196881e2dd76abcab6814439d73448f404124ad2e2f57b59b0df57699d913e24f79c53f129a09c05f2659e4444f4bb53", + "data": { + "slot": "8320", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "258", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "260", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0xabdb4b0a06e2d036021b0cd847fb6e8f4d2deca86e60788a6ae2bb9bd55b62ebf35716290f958e075812e8dfcba2beef00b002459e5932d7e7478cf00e91300f9f53a84f593ce40afb1f3c07b1db789ba5da757d313a9ee4cac6b2e28ed2f929", + "data": { + "slot": "8298", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0xabdb4b0a06e2d036021b0cd847fb6e8f4d2deca86e60788a6ae2bb9bd55b62ebf35716290f958e075812e8dfcba2beef00b002459e5932d7e7478cf00e91300f9f53a84f593ce40afb1f3c07b1db789ba5da757d313a9ee4cac6b2e28ed2f929", + "data": { + "slot": "8298", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x912fe61ef99df1c96d7e5e6bd01ee5a6be73389978c7f4670c4e978beb6b8e4d640f238c6ba3426e935ac8f8527d118c06f464b08f6527ebebac793728ccc1190ee6701838c6f2b3b06391dc2d69232e63af11023ffe8e1c66eb3bd1075085a6", + "data": { + "slot": "8310", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527", + "data": { + "slot": "8313", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x815ca84fb30789d731ebf977b6ecdd60c30818202d464acdc2947143f62342c4a5d01c6cdb32b1e223d032c746fa98d30899164e6ab37828e6d049f32e46a5c59d742d82005f9a629938761e3abce454cec104352665cd81bbcffa2fce22a935", + "data": { + "slot": "8299", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x8d852ffa1c5960ba3a5d09837fbdb859bbf9045001b3d1dc1c4d22c6b4bc5b6d506f6ef667b5c7c9fbfb1dd0cfe3617405f56750f8b5eb25b3539d0a4c94822b198c524de92a6c68982ce17f985ff5283cea6ac8dabe41828ce38edb7e9fe223", + "data": { + "slot": "8311", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0xab42974cba2e3fa75faa4c1f717caf7c2a953f4964063462ed32629764336124fd2f2f430ddf0291325722206250452c109b14cded0e51171b89b106b6b2044291128c3d6966c804490033b9e5fd06450ea50d22b5ab761892c6c3f4de79e098", + "data": { + "slot": "8291", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0xa44792a6341475c3eff0c11ad62bc19154d5ed48a4b81869ed49885499d5f768c81f357dd6a3ea60aa2f15a184b098f40a1382cfaea0a8438d62d9cca27c85023245b1838e2e4f1d4e65926f8c6a3032740b36c0a3c8aa69850648ac6c12b3ce", + "data": { + "slot": "8306", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x912fe61ef99df1c96d7e5e6bd01ee5a6be73389978c7f4670c4e978beb6b8e4d640f238c6ba3426e935ac8f8527d118c06f464b08f6527ebebac793728ccc1190ee6701838c6f2b3b06391dc2d69232e63af11023ffe8e1c66eb3bd1075085a6", + "data": { + "slot": "8310", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0xabdb4b0a06e2d036021b0cd847fb6e8f4d2deca86e60788a6ae2bb9bd55b62ebf35716290f958e075812e8dfcba2beef00b002459e5932d7e7478cf00e91300f9f53a84f593ce40afb1f3c07b1db789ba5da757d313a9ee4cac6b2e28ed2f929", + "data": { + "slot": "8298", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0xab42974cba2e3fa75faa4c1f717caf7c2a953f4964063462ed32629764336124fd2f2f430ddf0291325722206250452c109b14cded0e51171b89b106b6b2044291128c3d6966c804490033b9e5fd06450ea50d22b5ab761892c6c3f4de79e098", + "data": { + "slot": "8291", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x876c656d7889c15cd355d6652b347a25dc8fd7ffc383f0d14ad436b5f1af9ac09e06168ad71be76b85c3dd44ae79cc0f04f250a0bcc529d06a1032283e2b8b384d582c0ace50bf747264a199647697f159d06be75ecfb24da2a8b625a3087804", + "data": { + "slot": "8293", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x805e92ba1e4c88489f178202ca5d7ce96e7b874fe98bdee80ab6423441bd37ff3f0fe724bc088f58050ac2a8f81ec5e80401d76caeb65795b5794e7a20d0384f3bfd162b281a17e96cc98087c651d893b05154203af7a7591afe1056db934ec4", + "data": { + "slot": "8309", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x95bbaf8dcff64306f01e0b09b27ebe3c761def7edd75542e213586ee0c6d3fc313ae102760abd1262b4f8c00e57603fa01627390011e3a5dea555c74798d7a3e1da68e00e3cdb9d8e4af112b6ff83951bd926288d24eb82e3f203a3160a4d7a9", + "data": { + "slot": "8312", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x815ca84fb30789d731ebf977b6ecdd60c30818202d464acdc2947143f62342c4a5d01c6cdb32b1e223d032c746fa98d30899164e6ab37828e6d049f32e46a5c59d742d82005f9a629938761e3abce454cec104352665cd81bbcffa2fce22a935", + "data": { + "slot": "8299", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x87c3f6fac9ea937a8e8bd4f6dccb7893cb8ea39c65e0313a30e903c220dba2c8597df1d75ee21fd905eab1ebf2261ebf085b13115363d72adc9ccd9527293b7218c39e94c257c94a8c95c32cf909cf58e8b7ece89a9bd21107a413b3fe3172e0", + "data": { + "slot": "8304", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x8b1fbaba2982cd546a7d19d4af3755163112349a0e6d13f05c69807c709f363359c2cfff8a4afa66bd24445eb12b923615c33892a82d8081575207e4165a1d0c944fd3871ff885662c3921b152e674130879d67a0692b4867ad9fc2d20e24fa3", + "data": { + "slot": "8307", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0xa46775d208c119b097221ead6ee9afbf011258b03da07138d01fef8d5bd4681ecbab6f36687e8ae644191acebc94800a002b136de6ff892e4e0910d05402def66858ee8ad8f4b706fab163fe742959dcb86fa90d0b822e5937092852962acbb1", + "data": { + "slot": "8294", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x97426dbbe61af8a68ac683ba95ad871baade096e9287e2d533c1efba04430b7083283485db5b1624fb03639065e8c754155cfe68986d526c1a771b67e45c0e8c97428dee8c6d80cc68892b961e8352d50f34e2623dc3b7ba2cb5dba28a854079", + "data": { + "slot": "8302", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + } + ], + "deposits": [ + { + "proof": [ + "0x1a02000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": { + "pubkey": "0xa19c8e80ddc1caad60a172b66eb24e83ef200d77034b3e16bbee4d95e929a5c1a473563973338d22e7a566fdbd352f65", + "withdrawal_credentials": "0x00edbcfc97a6985ac86187522426240ed81b6493c880d0798360149ec8ce96d8", + "amount": "32000000000", + "signature": "0xb9b4b512b2c67a3e89edcbef91fc0ccd88c9a8c8654c51a130ffb2ab539c22a0c6b84928e8db4ca8a9d04f2dee312c3817a2bf360b6f5f2f3d1ba69b43cf4671290f7f58621887ad4dd1c9fe6d02cc59443e12447a20b38913f67597b0e3cc93" + } + }, + { + "proof": [ + "0x1a02000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": { + "pubkey": "0xb1f92d1a612942fb266c1e436f8d417282efa2805d5a5a819e3d07e358a70efbf0cc1671412ee986cd342c3d2255a324", + "withdrawal_credentials": "0x004ac0f181a01d43a7de32602b440cfbe3a091bb8c108c1fa35726ed301743f9", + "amount": "32000000000", + "signature": "0x8dbd6f9b4ce0a5277f66da9ec41776cff88a647ae1b4dde221a3bf41b9d4af1e77d0cff23185796815448f2e8148126a046b4b60947a32a1e201b4e979c91b395c1d4804ead1324d699eaa9c481efa69484a7946a0bad9788e50cf05847a30c4" + } + }, + { + "proof": [ + "0x1a02000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": { + "pubkey": "0xb532643cb8824a2fbd9196c10961f3ad2f0e319c3612bb15a51a3454593f44726383f006425c2e5952b156a6e14aceb0", + "withdrawal_credentials": "0x00f68c08152911b76f556f9d6dfc66d54e5abd63de04dc073d6b03f333ac00f3", + "amount": "32000000000", + "signature": "0x97852e8c02386bcc8a2dd51c70c48661c79bc1f89f9dce113a60fcde345abedf96fa186c4230013cf61f3546c5d9877a0eab7a5a4f4e4e0e4bcd917dc8368a88e3b8380de9e96ed36bfd605d55956af64a17b877f12762acfdd1c3effe4b4d42" + } + }, + { + "proof": [ + "0x1a02000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": { + "pubkey": "0xa7a1c0bbad929dc02699e92597a66266bbd9533419693270c9b56bbdea643cd2ded9664da3c9fd8db2389277b5e585cc", + "withdrawal_credentials": "0x00e64188226da03f1f3d787ef65d86690aaa24d44e5ac92c99c413463ec47c26", + "amount": "32000000000", + "signature": "0xb0e97772997255840a5758e5325b9d1c56a292500838c5b2b697b7dd207c65a2ef928ebb9466d57782edf79f9b74bbbb069235c752f6527e8d8eb1c785d99326da78680056ee3084811b980185287259af64607e218d67a3b8f24d27c0659ce2" + } + }, + { + "proof": [ + "0x1a02000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": { + "pubkey": "0x9919842dee455266e4dc77c74088bddbfdb535b9a1bbe75a3cced0e428598038365afe11c7578e4dbd8fe4cae7237543", + "withdrawal_credentials": "0x000a2baaef8f6cc730d6a5474879aed4fe8c95da787cc2e15c3cdba14a9cef12", + "amount": "32000000000", + "signature": "0x99ef1ab7cfbe40d0a1e136138a4a8094e8f54a59c8d05052749b7af14931274fad1c0a44577de51099f2700505fa8861023b7bddabb274249a091acb3a4f7543f877da3792dad7897351c7a01343116a65959812fd55cc4ce4197b05f698761f" + } + }, + { + "proof": [ + "0x1a02000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": { + "pubkey": "0xb4ed73c02a816ba9d23ba0e023970772f82dd3a32a85eefd922958e33bcab7f9c85e20372e49107665926cca852b8b9a", + "withdrawal_credentials": "0x0017c0e8e177a6d58e4f8b93b2b66b13aef9c186cfccb9466d857a474b32b0d4", + "amount": "32000000000", + "signature": "0xa6dfce815f61ce81bf107bf5ccc1beae5f32b63a55e836a5983b63b90c0e7eac873387107c145ab59c32679091cfd28a0dbf2b73f75cd5ab01b75c6ba984b83c796c92b77adba152ab2a20132324fc4b20c8ec002663f16edec9308bb8f3d298" + } + }, + { + "proof": [ + "0x1a02000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": { + "pubkey": "0xb0d0dfaf7479f59319beb513bee16e1af576a0740a7a124a9947ec7c3826dbc0a5d5db15519e8423d7aa683f638f3da3", + "withdrawal_credentials": "0x00a61d2fddabb70c2db059af7e298b0395ef882dda24ae144f2b7ac88026e55d", + "amount": "32000000000", + "signature": "0x85a06ab8d9d576cb2810a88635b7a462d1cfb238db066b8caeba7f36562bb903630f8f24d157747debad5428c4f42a9a0a08dfd53c687cd7c3e17ec539f353357bbd89b7111246c99cc7fab24b8cd33a88cddf845f7d27c8a33079aa097069e3" + } + }, + { + "proof": [ + "0x1a02000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": { + "pubkey": "0xb69614adf68d58f7d67110d7ced171ab934cb973f19c60cbb83161468655c42fe19a80a8e903030650bfaa9613a1ab2d", + "withdrawal_credentials": "0x0037c021fdef99bcf9fb90c02440571ab2faa0238485ed72e427b69dc8dddc91", + "amount": "32000000000", + "signature": "0x957f48b82d761d3e7f2e34eeff5922358d87f9b31c51e5af37a54fedeab7cfc09c3068f6ef5c97e0323dabff706bc7520113d51841c6dc2eaa044c8526bdaebcf35476c0b08cccb69ab0bab07c8e7ca2d6573b0ae96c32ae3d18764ae7ea78e0" + } + }, + { + "proof": [ + "0x1a02000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": { + "pubkey": "0xac897c8892a6f3effcd276e4f44f410644846a333db600ad12e1099020196b2f8104563c04d78fedf5afc5d87b91b1b5", + "withdrawal_credentials": "0x0075f9178dd8a199c55d5cebb9dccb00508e619d5b9abd2b7cd5ad3f671c5a9f", + "amount": "32000000000", + "signature": "0x95a886b35ead6f8fc09d33975108857abffc32d53db6546a7251d32ca6d1706e899155b3883b05e65a041e44c51db8480703f13cccc6575cd2d50d0506485b9669a096bb1a2d4879008c15b8c1cdcd2e1a5c4f12885311e24dd87dc32e1bce87" + } + }, + { + "proof": [ + "0x1a02000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": { + "pubkey": "0x8794fd3f4e5e66e6e81735d5726943833b82d1efd7d877e495a8c36955b7dfb95b3f6cfcef865fd7969fa2e17e628ab9", + "withdrawal_credentials": "0x0087adf1a29896ae52be67356ee9a4a5035450764c278382f8940d554668c208", + "amount": "32000000000", + "signature": "0xb42aa548fd9068db7916757390f6d011ad890b9f27a75d4676dd9edcd9017f5d7e2cec215a04502fcff253aa821865fb0c30549e7b5d5e62cc8df0264dc3b55538f15cfd375f9cb022a94c2a39201d757a502701acd50554dc4da29173c945bd" + } + } + ], + "voluntary_exits": [ + { + "message": { + "epoch": "260", + "validator_index": "504" + }, + "signature": "0x8fedc3077271b41f631d6062cc1cc8c8f074e486e9e692f198c5f82b94d2bb3b0fbf71cbac043cee94b56a7a06adf06d07bb7ecf06d8f699add17972ceb54b25e6021c3a2a727afd3370e960afbf345a75fddd2d221ba85a5f7b07e5607eec1e" + }, + { + "message": { + "epoch": "260", + "validator_index": "503" + }, + "signature": "0xa44079752dfa36b925f0ff675dfd10b5b7cc0c178839356d0bda9c83b6df01f6bfdd904af92373002bfac40277941d2809c4152fc61007ae4f2c73e550ed02f425419efae0461d8829746c7a3d36dcae5bc37158ede7dd30ccc33930783b6194" + }, + { + "message": { + "epoch": "260", + "validator_index": "502" + }, + "signature": "0xb193b547c2d45341c9aedd0a22f4afc565d9aaa3a04889df2f8ad608bb31b44a0391c69383f0f4725cea291332c081ff0a48e850d246dd0be40880bf17316eb4b2eaf4b8b6ba6d59c93aea3af98988f05cb2ddf61d8637f943864ebfe7c9707c" + }, + { + "message": { + "epoch": "260", + "validator_index": "501" + }, + "signature": "0x88afe9a0215d2a67c451fcbdc358237c4d5dce6b46973ae527afb7f8fb1da800d6a3dd7f6387028a57737b354b7db88803bd6f2a59c7fb84229f42e6c6ea1b7510cb2a28026ff8f2eefb8fc7e2a83115197b7a1bd35fbf0afcc69e4b6e581911" + }, + { + "message": { + "epoch": "260", + "validator_index": "500" + }, + "signature": "0xa2f2399070bcfa3f50894d7170d1343ab5f52d6bdc155124e867bcde936aee4e0bb69f164dee5fa07d47abccb8844ec101126caf0402f1a757934f8e7b5904a60cedc283b5e9801f2a71f80cda16e910d72518d469a9a40cd94b8ad3cca10136" + }, + { + "message": { + "epoch": "260", + "validator_index": "499" + }, + "signature": "0x86abacd204c85cfc40d71853422001e44134b1900138fccb409928b7e663270476e3d7a7e0aaa103c693cad3629da1aa056cac30c8aab1a4eb50d81bb0711db3dba1d741562b103f67f495996b18fad779d3d9cc508763ab883a7cd6858bdc51" + }, + { + "message": { + "epoch": "260", + "validator_index": "498" + }, + "signature": "0xb86533e02779dd0f959dbf1b0fa195126ccc945fd0a7c5b7370aefc16f8f130d083c0c1c58a5c18e8119d7912dd532d91765dd26ad5ef3991238bc093bab79d511b1d8484482eec9b6b4a98f4a8928819ea58fc857ed80b59fe9cb7a33fe60a2" + }, + { + "message": { + "epoch": "260", + "validator_index": "495" + }, + "signature": "0x80a5c7c52a246dcaaf67caf6285ea518581835af668d1a64723b321b167464e238248c0017d5265be373c9079d7b529b10aedc37835683e5e1320c3ad6fa1f72d52046a49b061935e1631565912d2f2482434007957fe9903edecf4dad8e5bb8" + }, + { + "message": { + "epoch": "260", + "validator_index": "494" + }, + "signature": "0xb6a0e4cdc1815f03166218963ec9cc4c5d607a67d659d1227386e16f90d3e39c6cddf696e3534f3824ca5aff8c734bab153f3bab701247cdcea16db31c94846c1cd3781b1861485ad813d025bf0a486c592dd1f9afa1134e8288e4fef44d2f3c" + }, + { + "message": { + "epoch": "260", + "validator_index": "492" + }, + "signature": "0xad850276510c2e41d059df6a1cefab9f1b66463da47b0fc772b21ed90c13e1bd6f86def8b2ecb867f4f752612d9d25e30a151aa6ef630a1b6ddaa4420c240b37df0234ee332373fe132b0101a0486900c5733762beeacd95429dd34c34230d13" + }, + { + "message": { + "epoch": "260", + "validator_index": "491" + }, + "signature": "0x837669180ba01b65157087f49c7af19acb1439016eca9c699b7136da7e9bbc89d6bddc7a030388bbb7e149ebd521c4810f457846b9cf913f7ee6f01db4363d3ce92fc732e52359917d36c7e4a08158653f1a9a78a608c4b56ff3e155b2783974" + } + ], + "sync_aggregate": { + "sync_committee_bits": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "signature": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + "execution_payload_header": { + "parent_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "fee_recipient": "0x0000000000000000000000000000000000000000", + "state_root": "0x0000000000000000000000000000000000000000000000000000000000000000", + "receipts_root": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prev_randao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "block_number": "0", + "gas_limit": "0", + "gas_used": "0", + "time": "0", + "extra_data": null, + "base_fee_per_gas": "0x0000000000000000000000000000000000000000000000000000000000000000", + "block_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactions_root": "0x0000000000000000000000000000000000000000000000000000000000000000", + "withdrawals_root": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "execution_changes": [], + "blob_kzg_commitments": [] + } + } + }, + "finalized": false, + "version": 0, + "execution_optimistic": false +} diff --git a/cl/beacon/handler/test_data/block_1.json b/cl/beacon/handler/test_data/block_1.json new file mode 100644 index 00000000000..05289c754eb --- /dev/null +++ b/cl/beacon/handler/test_data/block_1.json @@ -0,0 +1,1974 @@ +{ + "data": { + "signature": "0x8b915f3b9d2d4c7ccaacf5d56c1152b1e91eafd1f59ba734d09e78996930b63ca550499997fe6d590343aaf5997f0d0c14c986571992ac9ed188de2b31ae4b7d70dfb68edae8b012f72f284dc8da44f4af5a2bdf3dfc9c0897ec4f7165daa07a", + "message": { + "slot": "8322", + "proposer_index": "210", + "parent_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "state_root": "0x933d6650f2999f17012e781f5012981edb549e5935de1c981fce81cdd241d4e1", + "body": { + "randao_reveal": "0xa182a6c7224c53cc43492b7ba87b54e8303094ebcb8c822da09c4224791b461e34d089ac857acf05cd695679c25cffa30404832791fe424fd104e2e96ebbf583dd5ec4dcbc891e7f4e0dea402071dbd294810417221fc41e4f90e4837c694e1a", + "eth1_data": { + "deposit_root": "0x0000000000000000000000000000000000000000000000000000000000000000", + "deposit_count": "528", + "block_hash": "0x0000000000000000000000000000000000000000000000000000000000000000" + }, + "graffiti": "0x0000000000000000000000000000000000000000000000000000000000000000", + "proposer_slashings": [ + { + "signed_header_1": { + "message": { + "slot": "8321", + "proposer_index": "476", + "parent_root": "0x3333333333333333333333333333333333333333333333333333333333333333", + "state_root": "0x4444444444444444444444444444444444444444444444444444444444444444", + "body_root": "0x5555555555555555555555555555555555555555555555555555555555555555" + }, + "signature": "0x939584df88598e56fe144105c6933b4727d7b772539e65c57289df64cedee771377e4d0e94f85c25d39a6072997d309c09da8c477267670aa42f26fb0836c72ec5867fa2f34dc0eb7e043ef5d6421282d1515b0f8c7ffd4bbbf56ee8d61ed063" + }, + "signed_header_2": { + "message": { + "slot": "8321", + "proposer_index": "476", + "parent_root": "0x9999999999999999999999999999999999999999999999999999999999999999", + "state_root": "0x4444444444444444444444444444444444444444444444444444444444444444", + "body_root": "0x5555555555555555555555555555555555555555555555555555555555555555" + }, + "signature": "0x8a184441d5d944ed3c18549dd9e4640eda879f9e737ac4211fdddfd30a65e1a2a32a8aa918ca65ad9b863a15e8cfefc412608ca78fd54ea1e5cbbd5697d125cc721aac1b01e8984a33f025c4707623669573244a632ec7f37808c01fab143f58" + } + }, + { + "signed_header_1": { + "message": { + "slot": "8321", + "proposer_index": "406", + "parent_root": "0x3333333333333333333333333333333333333333333333333333333333333333", + "state_root": "0x4444444444444444444444444444444444444444444444444444444444444444", + "body_root": "0x5555555555555555555555555555555555555555555555555555555555555555" + }, + "signature": "0xad97a43e9f28a90ff46b07a7bf65d520b89a78af47dbff1c10e4fc6bb36b4ee9c4f27f2a72c65311a03e7b48e06d86db1149147b14a8803d46f6a457092642dc89d3f2782bd48a373e3125af1a84f5b76d4ff7ddc85ac2650ca4c0f99e1af592" + }, + "signed_header_2": { + "message": { + "slot": "8321", + "proposer_index": "406", + "parent_root": "0x9999999999999999999999999999999999999999999999999999999999999999", + "state_root": "0x4444444444444444444444444444444444444444444444444444444444444444", + "body_root": "0x5555555555555555555555555555555555555555555555555555555555555555" + }, + "signature": "0x88d860d460526de062ee196400e24cb3055de2ff6abb31331d0bfeeebcdc77839d22ad6dfec39d81279f5527d1ffbd7e0a9d6eee7dce5a1cd6f79451537e9dfb6384f595e9d49673c58c181527a599dd4b38154e1322f1607f192ab0394f1411" + } + }, + { + "signed_header_1": { + "message": { + "slot": "8321", + "proposer_index": "281", + "parent_root": "0x3333333333333333333333333333333333333333333333333333333333333333", + "state_root": "0x4444444444444444444444444444444444444444444444444444444444444444", + "body_root": "0x5555555555555555555555555555555555555555555555555555555555555555" + }, + "signature": "0x8a2358ff11a30100a2492001827f54ff6c10dd6dcea66f6814dd1cccc4a49850bbbe36546e4f9b72410042a9d5882e8219a5a01708b8a95ca57984debe78f419a4ac921270a0f0c11c795a6c5ef1e6bfb96712751a4fee61059ca8fbe69639b6" + }, + "signed_header_2": { + "message": { + "slot": "8321", + "proposer_index": "281", + "parent_root": "0x9999999999999999999999999999999999999999999999999999999999999999", + "state_root": "0x4444444444444444444444444444444444444444444444444444444444444444", + "body_root": "0x5555555555555555555555555555555555555555555555555555555555555555" + }, + "signature": "0xb820e03b7bfd21c2d97a4f2bc9dd1fd5325894757f7129646c7a39a02b2c1c8ca33d509b4e83491e79db02ac0490aa3308ee23bfa1f65bf4130ab07e377a8cbd4eace5b69801528322dde425b0a78310504c330da30be7cefc674573dbdb4502" + } + }, + { + "signed_header_1": { + "message": { + "slot": "8321", + "proposer_index": "169", + "parent_root": "0x3333333333333333333333333333333333333333333333333333333333333333", + "state_root": "0x4444444444444444444444444444444444444444444444444444444444444444", + "body_root": "0x5555555555555555555555555555555555555555555555555555555555555555" + }, + "signature": "0x88c81a6029f097a9f23e37c7677abfafa2921982e9aebffc35ca700e1aefcd49c2ab5d51c7b28ef3db3aad49d58a6407082ce1ecd7f7bd89cb764242890440b684fc0e1511e047434b25f3ad1a5e238e5bf97f51e9e37d6eed48e0b9fef64333" + }, + "signed_header_2": { + "message": { + "slot": "8321", + "proposer_index": "169", + "parent_root": "0x9999999999999999999999999999999999999999999999999999999999999999", + "state_root": "0x4444444444444444444444444444444444444444444444444444444444444444", + "body_root": "0x5555555555555555555555555555555555555555555555555555555555555555" + }, + "signature": "0x815b492a6a3fb606f01dbc595c8b18b51b7f7a5a86b11f3ae57c48f7506a34606556a3cf2be683ce23cd0c7b2235667613f9dbcf98408b176f134645f122684bd8fe704c7a4eccb7bb7cbe33c6de377be4d742291d35d0ec8d6083c1b17b7261" + } + }, + { + "signed_header_1": { + "message": { + "slot": "8321", + "proposer_index": "397", + "parent_root": "0x3333333333333333333333333333333333333333333333333333333333333333", + "state_root": "0x4444444444444444444444444444444444444444444444444444444444444444", + "body_root": "0x5555555555555555555555555555555555555555555555555555555555555555" + }, + "signature": "0xae352ba8550d04c07591224449bd4967f66f9d639b731795f643b1e3fc5ad28317268dc9e289ce6075e8981a0e37d9440885e4f4292cb4b4656bd0c7bd9fc22d21eb4c7d1b46f1b08cdb1eb08d7a405985e8a406e6d93c5c3fdd20e91baba122" + }, + "signed_header_2": { + "message": { + "slot": "8321", + "proposer_index": "397", + "parent_root": "0x9999999999999999999999999999999999999999999999999999999999999999", + "state_root": "0x4444444444444444444444444444444444444444444444444444444444444444", + "body_root": "0x5555555555555555555555555555555555555555555555555555555555555555" + }, + "signature": "0xb9152f5510f2bfa5ab7b61829823f25f0c879ab9b852fcd90c17f751bed6e687dc523fcda177503509cd1befec36046a056a66f5826e2333b6de67430a16f6194416681ae69a1c3498cf8351abae4fac5d8f0b51b1734633d545d540bf269270" + } + } + ], + "attester_slashings": [ + { + "attestation_1": { + "attesting_indicies": [ + "96", + "353", + "445" + ], + "data": { + "slot": "555", + "index": "0", + "beacon_block_root": "0x0000000000000000000000000000000000000000000000000000000000000000", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "17", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + }, + "signature": "0xa7e932307a82913b23743198182a7e3c97675e8a1133e8d946bc59c62b1765046214ca0ea0e13b77e4f8acc8f226498103684f382826a9fff6c6c2ffdf9c65ffeb1680155025f489f676457634581ee4363bdfbe4d46fc4d1d9df93c3df8750d" + }, + "attestation_2": { + "attesting_indicies": [ + "96", + "353", + "445" + ], + "data": { + "slot": "555", + "index": "0", + "beacon_block_root": "0x0000000000000000000000000000000000000000000000000000000000000000", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "17", + "root": "0x0101010101010101010101010101010101010101010101010101010101010101" + } + }, + "signature": "0x89aadbd74370dc6d86b6b61c544c1e18949b0d8aa2d706605d1014d0266a043588a829243d343d1c3812621944ea34540aef1fbd34fe51b03a5734ebc5ec31057d1df0004faeca71d8687dd3af806e4332e19f6da5ab1d7da67fe017c2f2e68b" + } + } + ], + "attestations": [ + { + "aggregation_bits": "0xff3f", + "signature": "0x8b63c286bff1c5dc6fb2e4878e73631e16db1cd3b07e9d0150b3ede4175635fe8db571cb486398e35923640606643d630bacc148d84e9c1060c32b55fe644e5c2573326b041767c5d45d45509a5403a7f2f1b2dd60e54bed26f407bb367a8642", + "data": { + "slot": "8314", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0xb731b2df4dcaf841d50747f85b332170471895508c3af7e8bada14e58a816fed435460e1694e87e2887f19a0de201c3d0bc1ece52c26c519fd9131b25fa8a69b229c14ffd1c935d9e853aca8ab07eaae98a65daec09b2640b91961685e96d58c", + "data": { + "slot": "8292", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x876c656d7889c15cd355d6652b347a25dc8fd7ffc383f0d14ad436b5f1af9ac09e06168ad71be76b85c3dd44ae79cc0f04f250a0bcc529d06a1032283e2b8b384d582c0ace50bf747264a199647697f159d06be75ecfb24da2a8b625a3087804", + "data": { + "slot": "8293", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x876c656d7889c15cd355d6652b347a25dc8fd7ffc383f0d14ad436b5f1af9ac09e06168ad71be76b85c3dd44ae79cc0f04f250a0bcc529d06a1032283e2b8b384d582c0ace50bf747264a199647697f159d06be75ecfb24da2a8b625a3087804", + "data": { + "slot": "8293", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x98416260b644654a4a90bda6032053f1eb3a12c59a3c7534f1ef348f2108c2837245bce74b3fd9f61ebae24860cc698100f864c4f26966c36431acbf0beea679807ba4eba9adfd1a267ef8d990290a2548af6456b1d0def6639ac47fd30c5542", + "data": { + "slot": "8317", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x805e92ba1e4c88489f178202ca5d7ce96e7b874fe98bdee80ab6423441bd37ff3f0fe724bc088f58050ac2a8f81ec5e80401d76caeb65795b5794e7a20d0384f3bfd162b281a17e96cc98087c651d893b05154203af7a7591afe1056db934ec4", + "data": { + "slot": "8309", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527", + "data": { + "slot": "8313", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x95bbaf8dcff64306f01e0b09b27ebe3c761def7edd75542e213586ee0c6d3fc313ae102760abd1262b4f8c00e57603fa01627390011e3a5dea555c74798d7a3e1da68e00e3cdb9d8e4af112b6ff83951bd926288d24eb82e3f203a3160a4d7a9", + "data": { + "slot": "8312", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x894270af1854ce4e65c6e09bc83c15171d564a2af871d0b442cacea78536e5cd34cf4a906025a6d87e12a172ceeb79990b86a1de7ed4ef40cffeca6b93402c3542682bb2914c34430e23038a57e8490abe809dc9f96f3b2caebed380113280b3", + "data": { + "slot": "8297", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0xa44792a6341475c3eff0c11ad62bc19154d5ed48a4b81869ed49885499d5f768c81f357dd6a3ea60aa2f15a184b098f40a1382cfaea0a8438d62d9cca27c85023245b1838e2e4f1d4e65926f8c6a3032740b36c0a3c8aa69850648ac6c12b3ce", + "data": { + "slot": "8306", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x98aade2cf9dad0e1528edec0e76be15577601b6cbef68353e51748b6286bf08812e42fe8791147a54eeed34782249e3f0cc463e22d6cb1c6050636ca8d070531fe40e16913f2e5560f6e683a6781268ff08d32bc5899b00306a87eecc5603928", + "data": { + "slot": "8290", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0xab42974cba2e3fa75faa4c1f717caf7c2a953f4964063462ed32629764336124fd2f2f430ddf0291325722206250452c109b14cded0e51171b89b106b6b2044291128c3d6966c804490033b9e5fd06450ea50d22b5ab761892c6c3f4de79e098", + "data": { + "slot": "8291", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x8d852ffa1c5960ba3a5d09837fbdb859bbf9045001b3d1dc1c4d22c6b4bc5b6d506f6ef667b5c7c9fbfb1dd0cfe3617405f56750f8b5eb25b3539d0a4c94822b198c524de92a6c68982ce17f985ff5283cea6ac8dabe41828ce38edb7e9fe223", + "data": { + "slot": "8311", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x8bfaed4667e28ed9e39464c7c57027ae345f22847b6ac1aa7e5f342fdb6cdca9d78a962da68f9e34e0453f68fa363fcd196881e2dd76abcab6814439d73448f404124ad2e2f57b59b0df57699d913e24f79c53f129a09c05f2659e4444f4bb53", + "data": { + "slot": "8320", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "258", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "260", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x97426dbbe61af8a68ac683ba95ad871baade096e9287e2d533c1efba04430b7083283485db5b1624fb03639065e8c754155cfe68986d526c1a771b67e45c0e8c97428dee8c6d80cc68892b961e8352d50f34e2623dc3b7ba2cb5dba28a854079", + "data": { + "slot": "8302", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x94fab4732e767881653a5923ca4a93fc2778d349cef972b077aa0fd2553946f578be6571d7a02fe14aa98b11a77475e115bc8062308b23a23c6ce71cd07c528a6e37d30324d57dcc36fa336575210bce5d71ccabf74f0dd96f839eefc1a49343", + "data": { + "slot": "8296", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x8b63c286bff1c5dc6fb2e4878e73631e16db1cd3b07e9d0150b3ede4175635fe8db571cb486398e35923640606643d630bacc148d84e9c1060c32b55fe644e5c2573326b041767c5d45d45509a5403a7f2f1b2dd60e54bed26f407bb367a8642", + "data": { + "slot": "8314", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x805e92ba1e4c88489f178202ca5d7ce96e7b874fe98bdee80ab6423441bd37ff3f0fe724bc088f58050ac2a8f81ec5e80401d76caeb65795b5794e7a20d0384f3bfd162b281a17e96cc98087c651d893b05154203af7a7591afe1056db934ec4", + "data": { + "slot": "8309", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527", + "data": { + "slot": "8313", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0xb60160a4024734b6c22e6083d755d97b22d107001965d35cd1aa5fc3c1059b4cb482c36c78609c0fa131631eb847d165177c877949e5baebb96a48f6e471c1d1d700619b4adeafa728b4d69de8d03d02854e4240d8e16d790168619cc2027247", + "data": { + "slot": "8318", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527", + "data": { + "slot": "8313", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x8b1fbaba2982cd546a7d19d4af3755163112349a0e6d13f05c69807c709f363359c2cfff8a4afa66bd24445eb12b923615c33892a82d8081575207e4165a1d0c944fd3871ff885662c3921b152e674130879d67a0692b4867ad9fc2d20e24fa3", + "data": { + "slot": "8307", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0xa44792a6341475c3eff0c11ad62bc19154d5ed48a4b81869ed49885499d5f768c81f357dd6a3ea60aa2f15a184b098f40a1382cfaea0a8438d62d9cca27c85023245b1838e2e4f1d4e65926f8c6a3032740b36c0a3c8aa69850648ac6c12b3ce", + "data": { + "slot": "8306", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x8b1fbaba2982cd546a7d19d4af3755163112349a0e6d13f05c69807c709f363359c2cfff8a4afa66bd24445eb12b923615c33892a82d8081575207e4165a1d0c944fd3871ff885662c3921b152e674130879d67a0692b4867ad9fc2d20e24fa3", + "data": { + "slot": "8307", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0xab42974cba2e3fa75faa4c1f717caf7c2a953f4964063462ed32629764336124fd2f2f430ddf0291325722206250452c109b14cded0e51171b89b106b6b2044291128c3d6966c804490033b9e5fd06450ea50d22b5ab761892c6c3f4de79e098", + "data": { + "slot": "8291", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x9494651d4491cfc326f3439cebc3304aaf50a8e5598217da6df2a13b5cb9f9731cc8934f406c0243786b17f936d5892801fc34fc74fb4f52fec147536375dabd9f892940aacdea196e28cb21320bce9ede79b0a11333569d90e6deeb59869217", + "data": { + "slot": "8300", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x87c3f6fac9ea937a8e8bd4f6dccb7893cb8ea39c65e0313a30e903c220dba2c8597df1d75ee21fd905eab1ebf2261ebf085b13115363d72adc9ccd9527293b7218c39e94c257c94a8c95c32cf909cf58e8b7ece89a9bd21107a413b3fe3172e0", + "data": { + "slot": "8304", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x94fab4732e767881653a5923ca4a93fc2778d349cef972b077aa0fd2553946f578be6571d7a02fe14aa98b11a77475e115bc8062308b23a23c6ce71cd07c528a6e37d30324d57dcc36fa336575210bce5d71ccabf74f0dd96f839eefc1a49343", + "data": { + "slot": "8296", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x97426dbbe61af8a68ac683ba95ad871baade096e9287e2d533c1efba04430b7083283485db5b1624fb03639065e8c754155cfe68986d526c1a771b67e45c0e8c97428dee8c6d80cc68892b961e8352d50f34e2623dc3b7ba2cb5dba28a854079", + "data": { + "slot": "8302", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x94fab4732e767881653a5923ca4a93fc2778d349cef972b077aa0fd2553946f578be6571d7a02fe14aa98b11a77475e115bc8062308b23a23c6ce71cd07c528a6e37d30324d57dcc36fa336575210bce5d71ccabf74f0dd96f839eefc1a49343", + "data": { + "slot": "8296", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x98416260b644654a4a90bda6032053f1eb3a12c59a3c7534f1ef348f2108c2837245bce74b3fd9f61ebae24860cc698100f864c4f26966c36431acbf0beea679807ba4eba9adfd1a267ef8d990290a2548af6456b1d0def6639ac47fd30c5542", + "data": { + "slot": "8317", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x8b1fbaba2982cd546a7d19d4af3755163112349a0e6d13f05c69807c709f363359c2cfff8a4afa66bd24445eb12b923615c33892a82d8081575207e4165a1d0c944fd3871ff885662c3921b152e674130879d67a0692b4867ad9fc2d20e24fa3", + "data": { + "slot": "8307", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x894270af1854ce4e65c6e09bc83c15171d564a2af871d0b442cacea78536e5cd34cf4a906025a6d87e12a172ceeb79990b86a1de7ed4ef40cffeca6b93402c3542682bb2914c34430e23038a57e8490abe809dc9f96f3b2caebed380113280b3", + "data": { + "slot": "8297", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x98aade2cf9dad0e1528edec0e76be15577601b6cbef68353e51748b6286bf08812e42fe8791147a54eeed34782249e3f0cc463e22d6cb1c6050636ca8d070531fe40e16913f2e5560f6e683a6781268ff08d32bc5899b00306a87eecc5603928", + "data": { + "slot": "8290", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x805e92ba1e4c88489f178202ca5d7ce96e7b874fe98bdee80ab6423441bd37ff3f0fe724bc088f58050ac2a8f81ec5e80401d76caeb65795b5794e7a20d0384f3bfd162b281a17e96cc98087c651d893b05154203af7a7591afe1056db934ec4", + "data": { + "slot": "8309", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0xa44792a6341475c3eff0c11ad62bc19154d5ed48a4b81869ed49885499d5f768c81f357dd6a3ea60aa2f15a184b098f40a1382cfaea0a8438d62d9cca27c85023245b1838e2e4f1d4e65926f8c6a3032740b36c0a3c8aa69850648ac6c12b3ce", + "data": { + "slot": "8306", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0xa44792a6341475c3eff0c11ad62bc19154d5ed48a4b81869ed49885499d5f768c81f357dd6a3ea60aa2f15a184b098f40a1382cfaea0a8438d62d9cca27c85023245b1838e2e4f1d4e65926f8c6a3032740b36c0a3c8aa69850648ac6c12b3ce", + "data": { + "slot": "8306", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x980e36beab885b1f2d8460e7ece21054e9d235fea5429836bc6df687e0c2f41b7556d9c86cd9c1ca7a69e5a51991b8d617eea619ba8e312d568e38f8de8adb8b4a9ec3e9dab2d47df45b35d9f2488236c042d66cd0916fee70e8a3295353b0ed", + "data": { + "slot": "8308", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527", + "data": { + "slot": "8313", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0xb60160a4024734b6c22e6083d755d97b22d107001965d35cd1aa5fc3c1059b4cb482c36c78609c0fa131631eb847d165177c877949e5baebb96a48f6e471c1d1d700619b4adeafa728b4d69de8d03d02854e4240d8e16d790168619cc2027247", + "data": { + "slot": "8318", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0xb731b2df4dcaf841d50747f85b332170471895508c3af7e8bada14e58a816fed435460e1694e87e2887f19a0de201c3d0bc1ece52c26c519fd9131b25fa8a69b229c14ffd1c935d9e853aca8ab07eaae98a65daec09b2640b91961685e96d58c", + "data": { + "slot": "8292", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x8b63c286bff1c5dc6fb2e4878e73631e16db1cd3b07e9d0150b3ede4175635fe8db571cb486398e35923640606643d630bacc148d84e9c1060c32b55fe644e5c2573326b041767c5d45d45509a5403a7f2f1b2dd60e54bed26f407bb367a8642", + "data": { + "slot": "8314", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x906fd8d1a45b719a36eb5e09b5e13f9d0fb7faaa194d84b90e0b2b811ce299f385bf18bb07844620ec032b6f267d04781480dc303081be7c5d8ba735bccd682dd3ddb6345bae13bd96068eb86b148e73b8931b642705b1696d9ada4159b1dd65", + "data": { + "slot": "8305", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x9494651d4491cfc326f3439cebc3304aaf50a8e5598217da6df2a13b5cb9f9731cc8934f406c0243786b17f936d5892801fc34fc74fb4f52fec147536375dabd9f892940aacdea196e28cb21320bce9ede79b0a11333569d90e6deeb59869217", + "data": { + "slot": "8300", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x98416260b644654a4a90bda6032053f1eb3a12c59a3c7534f1ef348f2108c2837245bce74b3fd9f61ebae24860cc698100f864c4f26966c36431acbf0beea679807ba4eba9adfd1a267ef8d990290a2548af6456b1d0def6639ac47fd30c5542", + "data": { + "slot": "8317", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527", + "data": { + "slot": "8313", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x980e36beab885b1f2d8460e7ece21054e9d235fea5429836bc6df687e0c2f41b7556d9c86cd9c1ca7a69e5a51991b8d617eea619ba8e312d568e38f8de8adb8b4a9ec3e9dab2d47df45b35d9f2488236c042d66cd0916fee70e8a3295353b0ed", + "data": { + "slot": "8308", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527", + "data": { + "slot": "8313", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x815ca84fb30789d731ebf977b6ecdd60c30818202d464acdc2947143f62342c4a5d01c6cdb32b1e223d032c746fa98d30899164e6ab37828e6d049f32e46a5c59d742d82005f9a629938761e3abce454cec104352665cd81bbcffa2fce22a935", + "data": { + "slot": "8299", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527", + "data": { + "slot": "8313", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x906fd8d1a45b719a36eb5e09b5e13f9d0fb7faaa194d84b90e0b2b811ce299f385bf18bb07844620ec032b6f267d04781480dc303081be7c5d8ba735bccd682dd3ddb6345bae13bd96068eb86b148e73b8931b642705b1696d9ada4159b1dd65", + "data": { + "slot": "8305", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x906fd8d1a45b719a36eb5e09b5e13f9d0fb7faaa194d84b90e0b2b811ce299f385bf18bb07844620ec032b6f267d04781480dc303081be7c5d8ba735bccd682dd3ddb6345bae13bd96068eb86b148e73b8931b642705b1696d9ada4159b1dd65", + "data": { + "slot": "8305", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x876c656d7889c15cd355d6652b347a25dc8fd7ffc383f0d14ad436b5f1af9ac09e06168ad71be76b85c3dd44ae79cc0f04f250a0bcc529d06a1032283e2b8b384d582c0ace50bf747264a199647697f159d06be75ecfb24da2a8b625a3087804", + "data": { + "slot": "8293", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x876c656d7889c15cd355d6652b347a25dc8fd7ffc383f0d14ad436b5f1af9ac09e06168ad71be76b85c3dd44ae79cc0f04f250a0bcc529d06a1032283e2b8b384d582c0ace50bf747264a199647697f159d06be75ecfb24da2a8b625a3087804", + "data": { + "slot": "8293", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x8bfaed4667e28ed9e39464c7c57027ae345f22847b6ac1aa7e5f342fdb6cdca9d78a962da68f9e34e0453f68fa363fcd196881e2dd76abcab6814439d73448f404124ad2e2f57b59b0df57699d913e24f79c53f129a09c05f2659e4444f4bb53", + "data": { + "slot": "8320", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "258", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "260", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0xabdb4b0a06e2d036021b0cd847fb6e8f4d2deca86e60788a6ae2bb9bd55b62ebf35716290f958e075812e8dfcba2beef00b002459e5932d7e7478cf00e91300f9f53a84f593ce40afb1f3c07b1db789ba5da757d313a9ee4cac6b2e28ed2f929", + "data": { + "slot": "8298", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0xabdb4b0a06e2d036021b0cd847fb6e8f4d2deca86e60788a6ae2bb9bd55b62ebf35716290f958e075812e8dfcba2beef00b002459e5932d7e7478cf00e91300f9f53a84f593ce40afb1f3c07b1db789ba5da757d313a9ee4cac6b2e28ed2f929", + "data": { + "slot": "8298", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x912fe61ef99df1c96d7e5e6bd01ee5a6be73389978c7f4670c4e978beb6b8e4d640f238c6ba3426e935ac8f8527d118c06f464b08f6527ebebac793728ccc1190ee6701838c6f2b3b06391dc2d69232e63af11023ffe8e1c66eb3bd1075085a6", + "data": { + "slot": "8310", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x90428ae131501833950bbeccfa738a2af4cbb5c6a04ae8f5e21d7fdd00dda2452d32e0630cd989a4863e8cb81303e1ca04b8f3abcf0b4c456fd7856c0af8585d206f109972b635bcefd72a537a67839b033a6c61f00af536a5e7107fdb9bf527", + "data": { + "slot": "8313", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x815ca84fb30789d731ebf977b6ecdd60c30818202d464acdc2947143f62342c4a5d01c6cdb32b1e223d032c746fa98d30899164e6ab37828e6d049f32e46a5c59d742d82005f9a629938761e3abce454cec104352665cd81bbcffa2fce22a935", + "data": { + "slot": "8299", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x8d852ffa1c5960ba3a5d09837fbdb859bbf9045001b3d1dc1c4d22c6b4bc5b6d506f6ef667b5c7c9fbfb1dd0cfe3617405f56750f8b5eb25b3539d0a4c94822b198c524de92a6c68982ce17f985ff5283cea6ac8dabe41828ce38edb7e9fe223", + "data": { + "slot": "8311", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0xab42974cba2e3fa75faa4c1f717caf7c2a953f4964063462ed32629764336124fd2f2f430ddf0291325722206250452c109b14cded0e51171b89b106b6b2044291128c3d6966c804490033b9e5fd06450ea50d22b5ab761892c6c3f4de79e098", + "data": { + "slot": "8291", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0xa44792a6341475c3eff0c11ad62bc19154d5ed48a4b81869ed49885499d5f768c81f357dd6a3ea60aa2f15a184b098f40a1382cfaea0a8438d62d9cca27c85023245b1838e2e4f1d4e65926f8c6a3032740b36c0a3c8aa69850648ac6c12b3ce", + "data": { + "slot": "8306", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x912fe61ef99df1c96d7e5e6bd01ee5a6be73389978c7f4670c4e978beb6b8e4d640f238c6ba3426e935ac8f8527d118c06f464b08f6527ebebac793728ccc1190ee6701838c6f2b3b06391dc2d69232e63af11023ffe8e1c66eb3bd1075085a6", + "data": { + "slot": "8310", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0xabdb4b0a06e2d036021b0cd847fb6e8f4d2deca86e60788a6ae2bb9bd55b62ebf35716290f958e075812e8dfcba2beef00b002459e5932d7e7478cf00e91300f9f53a84f593ce40afb1f3c07b1db789ba5da757d313a9ee4cac6b2e28ed2f929", + "data": { + "slot": "8298", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0xab42974cba2e3fa75faa4c1f717caf7c2a953f4964063462ed32629764336124fd2f2f430ddf0291325722206250452c109b14cded0e51171b89b106b6b2044291128c3d6966c804490033b9e5fd06450ea50d22b5ab761892c6c3f4de79e098", + "data": { + "slot": "8291", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x876c656d7889c15cd355d6652b347a25dc8fd7ffc383f0d14ad436b5f1af9ac09e06168ad71be76b85c3dd44ae79cc0f04f250a0bcc529d06a1032283e2b8b384d582c0ace50bf747264a199647697f159d06be75ecfb24da2a8b625a3087804", + "data": { + "slot": "8293", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x805e92ba1e4c88489f178202ca5d7ce96e7b874fe98bdee80ab6423441bd37ff3f0fe724bc088f58050ac2a8f81ec5e80401d76caeb65795b5794e7a20d0384f3bfd162b281a17e96cc98087c651d893b05154203af7a7591afe1056db934ec4", + "data": { + "slot": "8309", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x95bbaf8dcff64306f01e0b09b27ebe3c761def7edd75542e213586ee0c6d3fc313ae102760abd1262b4f8c00e57603fa01627390011e3a5dea555c74798d7a3e1da68e00e3cdb9d8e4af112b6ff83951bd926288d24eb82e3f203a3160a4d7a9", + "data": { + "slot": "8312", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0x815ca84fb30789d731ebf977b6ecdd60c30818202d464acdc2947143f62342c4a5d01c6cdb32b1e223d032c746fa98d30899164e6ab37828e6d049f32e46a5c59d742d82005f9a629938761e3abce454cec104352665cd81bbcffa2fce22a935", + "data": { + "slot": "8299", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x87c3f6fac9ea937a8e8bd4f6dccb7893cb8ea39c65e0313a30e903c220dba2c8597df1d75ee21fd905eab1ebf2261ebf085b13115363d72adc9ccd9527293b7218c39e94c257c94a8c95c32cf909cf58e8b7ece89a9bd21107a413b3fe3172e0", + "data": { + "slot": "8304", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x8b1fbaba2982cd546a7d19d4af3755163112349a0e6d13f05c69807c709f363359c2cfff8a4afa66bd24445eb12b923615c33892a82d8081575207e4165a1d0c944fd3871ff885662c3921b152e674130879d67a0692b4867ad9fc2d20e24fa3", + "data": { + "slot": "8307", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff7f", + "signature": "0xa46775d208c119b097221ead6ee9afbf011258b03da07138d01fef8d5bd4681ecbab6f36687e8ae644191acebc94800a002b136de6ff892e4e0910d05402def66858ee8ad8f4b706fab163fe742959dcb86fa90d0b822e5937092852962acbb1", + "data": { + "slot": "8294", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + }, + { + "aggregation_bits": "0xff3f", + "signature": "0x97426dbbe61af8a68ac683ba95ad871baade096e9287e2d533c1efba04430b7083283485db5b1624fb03639065e8c754155cfe68986d526c1a771b67e45c0e8c97428dee8c6d80cc68892b961e8352d50f34e2623dc3b7ba2cb5dba28a854079", + "data": { + "slot": "8302", + "index": "0", + "beacon_block_root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed", + "source": { + "epoch": "257", + "root": "0x31885d5a2405876b7203f9cc1a7e115b9977412107c51c81ab4fd49bde93905e" + }, + "target": { + "epoch": "259", + "root": "0x86979f6f6dc7626064ef0d38d4dffb89e91d1d4c18492e3fb7d7ee93cedca3ed" + } + } + } + ], + "deposits": [ + { + "proof": [ + "0x1a02000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": { + "pubkey": "0xa19c8e80ddc1caad60a172b66eb24e83ef200d77034b3e16bbee4d95e929a5c1a473563973338d22e7a566fdbd352f65", + "withdrawal_credentials": "0x00edbcfc97a6985ac86187522426240ed81b6493c880d0798360149ec8ce96d8", + "amount": "32000000000", + "signature": "0xb9b4b512b2c67a3e89edcbef91fc0ccd88c9a8c8654c51a130ffb2ab539c22a0c6b84928e8db4ca8a9d04f2dee312c3817a2bf360b6f5f2f3d1ba69b43cf4671290f7f58621887ad4dd1c9fe6d02cc59443e12447a20b38913f67597b0e3cc93" + } + }, + { + "proof": [ + "0x1a02000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": { + "pubkey": "0xb1f92d1a612942fb266c1e436f8d417282efa2805d5a5a819e3d07e358a70efbf0cc1671412ee986cd342c3d2255a324", + "withdrawal_credentials": "0x004ac0f181a01d43a7de32602b440cfbe3a091bb8c108c1fa35726ed301743f9", + "amount": "32000000000", + "signature": "0x8dbd6f9b4ce0a5277f66da9ec41776cff88a647ae1b4dde221a3bf41b9d4af1e77d0cff23185796815448f2e8148126a046b4b60947a32a1e201b4e979c91b395c1d4804ead1324d699eaa9c481efa69484a7946a0bad9788e50cf05847a30c4" + } + }, + { + "proof": [ + "0x1a02000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": { + "pubkey": "0xb532643cb8824a2fbd9196c10961f3ad2f0e319c3612bb15a51a3454593f44726383f006425c2e5952b156a6e14aceb0", + "withdrawal_credentials": "0x00f68c08152911b76f556f9d6dfc66d54e5abd63de04dc073d6b03f333ac00f3", + "amount": "32000000000", + "signature": "0x97852e8c02386bcc8a2dd51c70c48661c79bc1f89f9dce113a60fcde345abedf96fa186c4230013cf61f3546c5d9877a0eab7a5a4f4e4e0e4bcd917dc8368a88e3b8380de9e96ed36bfd605d55956af64a17b877f12762acfdd1c3effe4b4d42" + } + }, + { + "proof": [ + "0x1a02000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": { + "pubkey": "0xa7a1c0bbad929dc02699e92597a66266bbd9533419693270c9b56bbdea643cd2ded9664da3c9fd8db2389277b5e585cc", + "withdrawal_credentials": "0x00e64188226da03f1f3d787ef65d86690aaa24d44e5ac92c99c413463ec47c26", + "amount": "32000000000", + "signature": "0xb0e97772997255840a5758e5325b9d1c56a292500838c5b2b697b7dd207c65a2ef928ebb9466d57782edf79f9b74bbbb069235c752f6527e8d8eb1c785d99326da78680056ee3084811b980185287259af64607e218d67a3b8f24d27c0659ce2" + } + }, + { + "proof": [ + "0x1a02000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": { + "pubkey": "0x9919842dee455266e4dc77c74088bddbfdb535b9a1bbe75a3cced0e428598038365afe11c7578e4dbd8fe4cae7237543", + "withdrawal_credentials": "0x000a2baaef8f6cc730d6a5474879aed4fe8c95da787cc2e15c3cdba14a9cef12", + "amount": "32000000000", + "signature": "0x99ef1ab7cfbe40d0a1e136138a4a8094e8f54a59c8d05052749b7af14931274fad1c0a44577de51099f2700505fa8861023b7bddabb274249a091acb3a4f7543f877da3792dad7897351c7a01343116a65959812fd55cc4ce4197b05f698761f" + } + }, + { + "proof": [ + "0x1a02000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": { + "pubkey": "0xb4ed73c02a816ba9d23ba0e023970772f82dd3a32a85eefd922958e33bcab7f9c85e20372e49107665926cca852b8b9a", + "withdrawal_credentials": "0x0017c0e8e177a6d58e4f8b93b2b66b13aef9c186cfccb9466d857a474b32b0d4", + "amount": "32000000000", + "signature": "0xa6dfce815f61ce81bf107bf5ccc1beae5f32b63a55e836a5983b63b90c0e7eac873387107c145ab59c32679091cfd28a0dbf2b73f75cd5ab01b75c6ba984b83c796c92b77adba152ab2a20132324fc4b20c8ec002663f16edec9308bb8f3d298" + } + }, + { + "proof": [ + "0x1a02000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": { + "pubkey": "0xb0d0dfaf7479f59319beb513bee16e1af576a0740a7a124a9947ec7c3826dbc0a5d5db15519e8423d7aa683f638f3da3", + "withdrawal_credentials": "0x00a61d2fddabb70c2db059af7e298b0395ef882dda24ae144f2b7ac88026e55d", + "amount": "32000000000", + "signature": "0x85a06ab8d9d576cb2810a88635b7a462d1cfb238db066b8caeba7f36562bb903630f8f24d157747debad5428c4f42a9a0a08dfd53c687cd7c3e17ec539f353357bbd89b7111246c99cc7fab24b8cd33a88cddf845f7d27c8a33079aa097069e3" + } + }, + { + "proof": [ + "0x1a02000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": { + "pubkey": "0xb69614adf68d58f7d67110d7ced171ab934cb973f19c60cbb83161468655c42fe19a80a8e903030650bfaa9613a1ab2d", + "withdrawal_credentials": "0x0037c021fdef99bcf9fb90c02440571ab2faa0238485ed72e427b69dc8dddc91", + "amount": "32000000000", + "signature": "0x957f48b82d761d3e7f2e34eeff5922358d87f9b31c51e5af37a54fedeab7cfc09c3068f6ef5c97e0323dabff706bc7520113d51841c6dc2eaa044c8526bdaebcf35476c0b08cccb69ab0bab07c8e7ca2d6573b0ae96c32ae3d18764ae7ea78e0" + } + }, + { + "proof": [ + "0x1a02000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": { + "pubkey": "0xac897c8892a6f3effcd276e4f44f410644846a333db600ad12e1099020196b2f8104563c04d78fedf5afc5d87b91b1b5", + "withdrawal_credentials": "0x0075f9178dd8a199c55d5cebb9dccb00508e619d5b9abd2b7cd5ad3f671c5a9f", + "amount": "32000000000", + "signature": "0x95a886b35ead6f8fc09d33975108857abffc32d53db6546a7251d32ca6d1706e899155b3883b05e65a041e44c51db8480703f13cccc6575cd2d50d0506485b9669a096bb1a2d4879008c15b8c1cdcd2e1a5c4f12885311e24dd87dc32e1bce87" + } + }, + { + "proof": [ + "0x1a02000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000000" + ], + "data": { + "pubkey": "0x8794fd3f4e5e66e6e81735d5726943833b82d1efd7d877e495a8c36955b7dfb95b3f6cfcef865fd7969fa2e17e628ab9", + "withdrawal_credentials": "0x0087adf1a29896ae52be67356ee9a4a5035450764c278382f8940d554668c208", + "amount": "32000000000", + "signature": "0xb42aa548fd9068db7916757390f6d011ad890b9f27a75d4676dd9edcd9017f5d7e2cec215a04502fcff253aa821865fb0c30549e7b5d5e62cc8df0264dc3b55538f15cfd375f9cb022a94c2a39201d757a502701acd50554dc4da29173c945bd" + } + } + ], + "voluntary_exits": [ + { + "message": { + "epoch": "260", + "validator_index": "504" + }, + "signature": "0x8fedc3077271b41f631d6062cc1cc8c8f074e486e9e692f198c5f82b94d2bb3b0fbf71cbac043cee94b56a7a06adf06d07bb7ecf06d8f699add17972ceb54b25e6021c3a2a727afd3370e960afbf345a75fddd2d221ba85a5f7b07e5607eec1e" + }, + { + "message": { + "epoch": "260", + "validator_index": "503" + }, + "signature": "0xa44079752dfa36b925f0ff675dfd10b5b7cc0c178839356d0bda9c83b6df01f6bfdd904af92373002bfac40277941d2809c4152fc61007ae4f2c73e550ed02f425419efae0461d8829746c7a3d36dcae5bc37158ede7dd30ccc33930783b6194" + }, + { + "message": { + "epoch": "260", + "validator_index": "502" + }, + "signature": "0xb193b547c2d45341c9aedd0a22f4afc565d9aaa3a04889df2f8ad608bb31b44a0391c69383f0f4725cea291332c081ff0a48e850d246dd0be40880bf17316eb4b2eaf4b8b6ba6d59c93aea3af98988f05cb2ddf61d8637f943864ebfe7c9707c" + }, + { + "message": { + "epoch": "260", + "validator_index": "501" + }, + "signature": "0x88afe9a0215d2a67c451fcbdc358237c4d5dce6b46973ae527afb7f8fb1da800d6a3dd7f6387028a57737b354b7db88803bd6f2a59c7fb84229f42e6c6ea1b7510cb2a28026ff8f2eefb8fc7e2a83115197b7a1bd35fbf0afcc69e4b6e581911" + }, + { + "message": { + "epoch": "260", + "validator_index": "500" + }, + "signature": "0xa2f2399070bcfa3f50894d7170d1343ab5f52d6bdc155124e867bcde936aee4e0bb69f164dee5fa07d47abccb8844ec101126caf0402f1a757934f8e7b5904a60cedc283b5e9801f2a71f80cda16e910d72518d469a9a40cd94b8ad3cca10136" + }, + { + "message": { + "epoch": "260", + "validator_index": "499" + }, + "signature": "0x86abacd204c85cfc40d71853422001e44134b1900138fccb409928b7e663270476e3d7a7e0aaa103c693cad3629da1aa056cac30c8aab1a4eb50d81bb0711db3dba1d741562b103f67f495996b18fad779d3d9cc508763ab883a7cd6858bdc51" + }, + { + "message": { + "epoch": "260", + "validator_index": "498" + }, + "signature": "0xb86533e02779dd0f959dbf1b0fa195126ccc945fd0a7c5b7370aefc16f8f130d083c0c1c58a5c18e8119d7912dd532d91765dd26ad5ef3991238bc093bab79d511b1d8484482eec9b6b4a98f4a8928819ea58fc857ed80b59fe9cb7a33fe60a2" + }, + { + "message": { + "epoch": "260", + "validator_index": "495" + }, + "signature": "0x80a5c7c52a246dcaaf67caf6285ea518581835af668d1a64723b321b167464e238248c0017d5265be373c9079d7b529b10aedc37835683e5e1320c3ad6fa1f72d52046a49b061935e1631565912d2f2482434007957fe9903edecf4dad8e5bb8" + }, + { + "message": { + "epoch": "260", + "validator_index": "494" + }, + "signature": "0xb6a0e4cdc1815f03166218963ec9cc4c5d607a67d659d1227386e16f90d3e39c6cddf696e3534f3824ca5aff8c734bab153f3bab701247cdcea16db31c94846c1cd3781b1861485ad813d025bf0a486c592dd1f9afa1134e8288e4fef44d2f3c" + }, + { + "message": { + "epoch": "260", + "validator_index": "492" + }, + "signature": "0xad850276510c2e41d059df6a1cefab9f1b66463da47b0fc772b21ed90c13e1bd6f86def8b2ecb867f4f752612d9d25e30a151aa6ef630a1b6ddaa4420c240b37df0234ee332373fe132b0101a0486900c5733762beeacd95429dd34c34230d13" + }, + { + "message": { + "epoch": "260", + "validator_index": "491" + }, + "signature": "0x837669180ba01b65157087f49c7af19acb1439016eca9c699b7136da7e9bbc89d6bddc7a030388bbb7e149ebd521c4810f457846b9cf913f7ee6f01db4363d3ce92fc732e52359917d36c7e4a08158653f1a9a78a608c4b56ff3e155b2783974" + } + ], + "sync_aggregate": { + "sync_committee_bits": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "signature": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + }, + "execution_payload": { + "parent_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "fee_recipient": "0x0000000000000000000000000000000000000000", + "state_root": "0x0000000000000000000000000000000000000000000000000000000000000000", + "receipts_root": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prev_randao": "0x0000000000000000000000000000000000000000000000000000000000000000", + "block_number": "0", + "gas_limit": "0", + "gas_used": "0", + "timestamp": "0", + "extra_data": null, + "base_fee_per_gas": "0x0000000000000000000000000000000000000000000000000000000000000000", + "block_hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactions": null + }, + "execution_changes": [], + "blob_kzg_commitments": [] + } + } + }, + "finalized": false, + "version": 0, + "execution_optimistic": false +} diff --git a/cl/beacon/handler/test_data/committees_1.yaml b/cl/beacon/handler/test_data/committees_1.yaml new file mode 100644 index 00000000000..feaabdcafe0 --- /dev/null +++ b/cl/beacon/handler/test_data/committees_1.yaml @@ -0,0 +1,6 @@ +- {"data":[{"index":"0","slot":"8322","validators":["0","104","491","501","379","318","275","504","75","280","105","399","35","401"]}],"execution_optimistic":false,"finalized":true} +- {"data":[],"finalized":true,"execution_optimistic":false} +- {"data":[{"index":"0","slot":"8290","validators":["127","377","274","85","309","420","423","398","153","480","273","429","374","260"]}],"execution_optimistic":false,"finalized":true} +- {"data":[{"index":"0","slot":"8322","validators":["0","104","491","501","379","318","275","504","75","280","105","399","35","401"]}],"finalized":false,"execution_optimistic":false} +- {"data":[],"finalized":false,"execution_optimistic":false} +- {"data":[{"index":"0","slot":"8290","validators":["127","377","274","85","309","420","423","398","153","480","273","429","374","260"]}],"finalized":false,"execution_optimistic":false} diff --git a/cl/beacon/handler/test_data/duties_1.yaml b/cl/beacon/handler/test_data/duties_1.yaml new file mode 100644 index 00000000000..f1a51002917 --- /dev/null +++ b/cl/beacon/handler/test_data/duties_1.yaml @@ -0,0 +1,2 @@ +- {"data":[{"pubkey":"0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb","validator_index":"0","committee_index":"0","committee_length":"14","validator_committee_index":"0","committees_at_slot":"1","slot":"8322"},{"pubkey":"0xb0e7791fb972fe014159aa33a98622da3cdc98ff707965e536d8636b5fcc5ac7a91a8c46e59a00dca575af0f18fb13dc","validator_index":"4","committee_index":"0","committee_length":"13","validator_committee_index":"5","committees_at_slot":"1","slot":"8327"},{"pubkey":"0xb928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7","validator_index":"6","committee_index":"0","committee_length":"13","validator_committee_index":"10","committees_at_slot":"1","slot":"8327"},{"pubkey":"0xa6e82f6da4520f85c5d27d8f329eccfa05944fd1096b20734c894966d12a9e2a9a9744529d7212d33883113a0cadb909","validator_index":"5","committee_index":"0","committee_length":"14","validator_committee_index":"10","committees_at_slot":"1","slot":"8329"},{"pubkey":"0x89ece308f9d1f0131765212deca99697b112d61f9be9a5f1f3780a51335b3ff981747a0b2ca2179b96d2c0c9024e5224","validator_index":"2","committee_index":"0","committee_length":"14","validator_committee_index":"11","committees_at_slot":"1","slot":"8331"},{"pubkey":"0xaf81da25ecf1c84b577fefbedd61077a81dc43b00304015b2b596ab67f00e41c86bb00ebd0f90d4b125eb0539891aeed","validator_index":"9","committee_index":"0","committee_length":"14","validator_committee_index":"8","committees_at_slot":"1","slot":"8342"},{"pubkey":"0xac9b60d5afcbd5663a8a44b7c5a02f19e9a77ab0a35bd65809bb5c67ec582c897feb04decc694b13e08587f3ff9b5b60","validator_index":"3","committee_index":"0","committee_length":"13","validator_committee_index":"6","committees_at_slot":"1","slot":"8348"}],"execution_optimistic":false} +- {"data":[],"execution_optimistic":false} diff --git a/cl/beacon/handler/test_data/duties_sync_1.yaml b/cl/beacon/handler/test_data/duties_sync_1.yaml new file mode 100644 index 00000000000..9d655806893 --- /dev/null +++ b/cl/beacon/handler/test_data/duties_sync_1.yaml @@ -0,0 +1,2 @@ +- {"data":[{"pubkey":"0x97f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb","validator_index":"0","validator_sync_committee_indicies":["30","286"]},{"pubkey":"0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e","validator_index":"1","validator_sync_committee_indicies":["120","376"]},{"pubkey":"0x89ece308f9d1f0131765212deca99697b112d61f9be9a5f1f3780a51335b3ff981747a0b2ca2179b96d2c0c9024e5224","validator_index":"2","validator_sync_committee_indicies":["138","394"]},{"pubkey":"0xac9b60d5afcbd5663a8a44b7c5a02f19e9a77ab0a35bd65809bb5c67ec582c897feb04decc694b13e08587f3ff9b5b60","validator_index":"3","validator_sync_committee_indicies":["10","266"]},{"pubkey":"0xb0e7791fb972fe014159aa33a98622da3cdc98ff707965e536d8636b5fcc5ac7a91a8c46e59a00dca575af0f18fb13dc","validator_index":"4","validator_sync_committee_indicies":["114","370"]},{"pubkey":"0xa6e82f6da4520f85c5d27d8f329eccfa05944fd1096b20734c894966d12a9e2a9a9744529d7212d33883113a0cadb909","validator_index":"5","validator_sync_committee_indicies":["103","359"]},{"pubkey":"0xb928f3beb93519eecf0145da903b40a4c97dca00b21f12ac0df3be9116ef2ef27b2ae6bcd4c5bc2d54ef5a70627efcb7","validator_index":"6","validator_sync_committee_indicies":["163","419"]},{"pubkey":"0xa85ae765588126f5e860d019c0e26235f567a9c0c0b2d8ff30f3e8d436b1082596e5e7462d20f5be3764fd473e57f9cf","validator_index":"7","validator_sync_committee_indicies":["197","453"]},{"pubkey":"0x99cdf3807146e68e041314ca93e1fee0991224ec2a74beb2866816fd0826ce7b6263ee31e953a86d1b72cc2215a57793","validator_index":"8","validator_sync_committee_indicies":["175","431"]},{"pubkey":"0xaf81da25ecf1c84b577fefbedd61077a81dc43b00304015b2b596ab67f00e41c86bb00ebd0f90d4b125eb0539891aeed","validator_index":"9","validator_sync_committee_indicies":["53","309"]}],"execution_optimistic":false} +- {"data":[],"execution_optimistic":false} diff --git a/cl/beacon/handler/test_data/forkchoice_1.yaml b/cl/beacon/handler/test_data/forkchoice_1.yaml new file mode 100644 index 00000000000..448f1545a4b --- /dev/null +++ b/cl/beacon/handler/test_data/forkchoice_1.yaml @@ -0,0 +1,2 @@ +- {"data":[{"execution_optimistic":false,"root":"0x0102030000000000000000000000000000000000000000000000000000000000","slot":128}]} +- {"finalized_checkpoint":{"epoch":"1","root":"0x0102030000000000000000000000000000000000000000000000000000000000"},"fork_choice_nodes":[{"slot":"128","block_root":"0x0102030000000000000000000000000000000000000000000000000000000000","parent_root":"0x0102030000000000000000000000000000000000000000000000000000000000","justified_epoch":"0","finalized_epoch":"0","weight":"1","validity":"","execution_block_hash":"0x0000000000000000000000000000000000000000000000000000000000000000"},{"slot":"128","block_root":"0x0102020405030000000000000000000000000000000000000000000000000000","parent_root":"0x0102050000000000000000000000000000000000000000000000000000000000","justified_epoch":"0","finalized_epoch":"0","weight":"2","validity":"","execution_block_hash":"0x0000000000000000000000000000000000000000000000000000000000000000"}],"justified_checkpoint":{"epoch":"2","root":"0x0102030000000000000000000000000000000000000000000000000000000000"}} diff --git a/cl/beacon/handler/test_data/rewards_1.yaml b/cl/beacon/handler/test_data/rewards_1.yaml new file mode 100644 index 00000000000..28d6ba50e08 --- /dev/null +++ b/cl/beacon/handler/test_data/rewards_1.yaml @@ -0,0 +1,3 @@ +- {"data":{"proposer_index":"203","attestations":"332205","proposer_slashings":"0","attester_slashings":"0","sync_aggregate":"0","total":"332205"},"finalized":true,"execution_optimistic":false} +- {"data":{"proposer_index":"98","attestations":"332205","proposer_slashings":"0","attester_slashings":"0","sync_aggregate":"0","total":"332205"},"finalized":true,"execution_optimistic":false} +- {"data":[{"validator_index":"1","reward":"-698"},{"validator_index":"4","reward":"-698"}],"execution_optimistic":false,"finalized":true} diff --git a/cl/beacon/handler/test_data/rewards_2.json b/cl/beacon/handler/test_data/rewards_2.json new file mode 100644 index 00000000000..e73b214703a --- /dev/null +++ b/cl/beacon/handler/test_data/rewards_2.json @@ -0,0 +1 @@ +{"data":[{"validator_index":"0","reward":"-698"},{"validator_index":"1","reward":"-698"},{"validator_index":"2","reward":"-698"},{"validator_index":"3","reward":"-698"},{"validator_index":"4","reward":"-698"},{"validator_index":"5","reward":"-698"},{"validator_index":"6","reward":"-698"},{"validator_index":"7","reward":"-698"},{"validator_index":"8","reward":"-698"},{"validator_index":"9","reward":"-698"},{"validator_index":"10","reward":"-698"},{"validator_index":"11","reward":"-698"},{"validator_index":"12","reward":"-698"},{"validator_index":"13","reward":"-698"},{"validator_index":"14","reward":"-698"},{"validator_index":"15","reward":"-698"},{"validator_index":"16","reward":"-698"},{"validator_index":"17","reward":"-698"},{"validator_index":"18","reward":"-698"},{"validator_index":"19","reward":"-698"},{"validator_index":"20","reward":"-698"},{"validator_index":"21","reward":"-698"},{"validator_index":"22","reward":"-698"},{"validator_index":"23","reward":"-698"},{"validator_index":"24","reward":"-698"},{"validator_index":"25","reward":"-698"},{"validator_index":"26","reward":"-698"},{"validator_index":"27","reward":"-698"},{"validator_index":"28","reward":"-698"},{"validator_index":"29","reward":"-698"},{"validator_index":"30","reward":"-698"},{"validator_index":"31","reward":"-698"},{"validator_index":"32","reward":"-698"},{"validator_index":"33","reward":"-698"},{"validator_index":"34","reward":"-698"},{"validator_index":"35","reward":"-698"},{"validator_index":"36","reward":"-698"},{"validator_index":"37","reward":"-698"},{"validator_index":"38","reward":"-698"},{"validator_index":"39","reward":"-698"},{"validator_index":"40","reward":"-698"},{"validator_index":"41","reward":"-698"},{"validator_index":"42","reward":"-698"},{"validator_index":"43","reward":"-698"},{"validator_index":"44","reward":"-698"},{"validator_index":"45","reward":"-698"},{"validator_index":"46","reward":"-698"},{"validator_index":"47","reward":"-698"},{"validator_index":"48","reward":"-698"},{"validator_index":"49","reward":"-698"},{"validator_index":"50","reward":"-698"},{"validator_index":"51","reward":"-698"},{"validator_index":"52","reward":"-698"},{"validator_index":"53","reward":"-698"},{"validator_index":"54","reward":"-698"},{"validator_index":"55","reward":"-698"},{"validator_index":"56","reward":"-698"},{"validator_index":"57","reward":"-698"},{"validator_index":"58","reward":"-698"},{"validator_index":"59","reward":"-698"},{"validator_index":"60","reward":"-698"},{"validator_index":"61","reward":"-698"},{"validator_index":"62","reward":"-698"},{"validator_index":"63","reward":"-698"},{"validator_index":"64","reward":"-698"},{"validator_index":"65","reward":"-698"},{"validator_index":"66","reward":"-698"},{"validator_index":"67","reward":"-698"},{"validator_index":"68","reward":"-698"},{"validator_index":"69","reward":"-698"},{"validator_index":"70","reward":"-698"},{"validator_index":"71","reward":"-698"},{"validator_index":"72","reward":"-698"},{"validator_index":"73","reward":"-698"},{"validator_index":"74","reward":"-698"},{"validator_index":"75","reward":"-698"},{"validator_index":"76","reward":"-698"},{"validator_index":"77","reward":"-698"},{"validator_index":"78","reward":"-698"},{"validator_index":"79","reward":"-698"},{"validator_index":"80","reward":"-698"},{"validator_index":"81","reward":"-698"},{"validator_index":"82","reward":"-698"},{"validator_index":"83","reward":"-698"},{"validator_index":"84","reward":"-698"},{"validator_index":"85","reward":"-698"},{"validator_index":"86","reward":"-698"},{"validator_index":"87","reward":"-698"},{"validator_index":"88","reward":"-698"},{"validator_index":"89","reward":"-698"},{"validator_index":"90","reward":"-698"},{"validator_index":"91","reward":"-698"},{"validator_index":"92","reward":"-698"},{"validator_index":"93","reward":"-698"},{"validator_index":"94","reward":"-698"},{"validator_index":"95","reward":"-698"},{"validator_index":"96","reward":"-698"},{"validator_index":"97","reward":"-698"},{"validator_index":"98","reward":"-698"},{"validator_index":"99","reward":"-698"},{"validator_index":"100","reward":"-698"},{"validator_index":"101","reward":"-698"},{"validator_index":"102","reward":"-698"},{"validator_index":"103","reward":"-698"},{"validator_index":"104","reward":"-698"},{"validator_index":"105","reward":"-698"},{"validator_index":"106","reward":"-698"},{"validator_index":"107","reward":"-698"},{"validator_index":"108","reward":"-698"},{"validator_index":"109","reward":"-698"},{"validator_index":"110","reward":"-698"},{"validator_index":"111","reward":"-698"},{"validator_index":"112","reward":"-698"},{"validator_index":"113","reward":"-698"},{"validator_index":"114","reward":"-698"},{"validator_index":"115","reward":"-698"},{"validator_index":"116","reward":"-698"},{"validator_index":"117","reward":"-698"},{"validator_index":"118","reward":"-698"},{"validator_index":"119","reward":"-698"},{"validator_index":"120","reward":"-698"},{"validator_index":"121","reward":"-698"},{"validator_index":"122","reward":"-698"},{"validator_index":"123","reward":"-698"},{"validator_index":"124","reward":"-698"},{"validator_index":"125","reward":"-698"},{"validator_index":"126","reward":"-698"},{"validator_index":"127","reward":"-698"},{"validator_index":"128","reward":"-698"},{"validator_index":"129","reward":"-698"},{"validator_index":"130","reward":"-698"},{"validator_index":"131","reward":"-698"},{"validator_index":"132","reward":"-698"},{"validator_index":"133","reward":"-698"},{"validator_index":"134","reward":"-698"},{"validator_index":"135","reward":"-698"},{"validator_index":"136","reward":"-698"},{"validator_index":"137","reward":"-698"},{"validator_index":"138","reward":"-698"},{"validator_index":"139","reward":"-698"},{"validator_index":"140","reward":"-698"},{"validator_index":"141","reward":"-698"},{"validator_index":"142","reward":"-698"},{"validator_index":"143","reward":"-698"},{"validator_index":"144","reward":"-698"},{"validator_index":"145","reward":"-698"},{"validator_index":"146","reward":"-698"},{"validator_index":"147","reward":"-698"},{"validator_index":"148","reward":"-698"},{"validator_index":"149","reward":"-698"},{"validator_index":"150","reward":"-698"},{"validator_index":"151","reward":"-698"},{"validator_index":"152","reward":"-698"},{"validator_index":"153","reward":"-698"},{"validator_index":"154","reward":"-698"},{"validator_index":"155","reward":"-698"},{"validator_index":"156","reward":"-698"},{"validator_index":"157","reward":"-698"},{"validator_index":"158","reward":"-698"},{"validator_index":"159","reward":"-698"},{"validator_index":"160","reward":"-698"},{"validator_index":"161","reward":"-698"},{"validator_index":"162","reward":"-698"},{"validator_index":"163","reward":"-698"},{"validator_index":"164","reward":"-698"},{"validator_index":"165","reward":"-698"},{"validator_index":"166","reward":"-698"},{"validator_index":"167","reward":"-698"},{"validator_index":"168","reward":"-698"},{"validator_index":"169","reward":"-698"},{"validator_index":"170","reward":"-698"},{"validator_index":"171","reward":"-698"},{"validator_index":"172","reward":"-698"},{"validator_index":"173","reward":"-698"},{"validator_index":"174","reward":"-698"},{"validator_index":"175","reward":"-698"},{"validator_index":"176","reward":"-698"},{"validator_index":"177","reward":"-698"},{"validator_index":"178","reward":"-698"},{"validator_index":"179","reward":"-698"},{"validator_index":"180","reward":"-698"},{"validator_index":"181","reward":"-698"},{"validator_index":"182","reward":"-698"},{"validator_index":"183","reward":"-698"},{"validator_index":"184","reward":"-698"},{"validator_index":"185","reward":"-698"},{"validator_index":"186","reward":"-698"},{"validator_index":"187","reward":"-698"},{"validator_index":"188","reward":"-698"},{"validator_index":"189","reward":"-698"},{"validator_index":"190","reward":"-698"},{"validator_index":"191","reward":"-698"},{"validator_index":"192","reward":"-698"},{"validator_index":"193","reward":"-698"},{"validator_index":"194","reward":"-698"},{"validator_index":"195","reward":"-698"},{"validator_index":"196","reward":"-698"},{"validator_index":"197","reward":"-698"},{"validator_index":"198","reward":"-698"},{"validator_index":"199","reward":"-698"},{"validator_index":"200","reward":"-698"},{"validator_index":"201","reward":"-698"},{"validator_index":"202","reward":"-698"},{"validator_index":"203","reward":"-698"},{"validator_index":"204","reward":"-698"},{"validator_index":"205","reward":"-698"},{"validator_index":"206","reward":"-698"},{"validator_index":"207","reward":"-698"},{"validator_index":"208","reward":"-698"},{"validator_index":"209","reward":"-698"},{"validator_index":"210","reward":"-698"},{"validator_index":"211","reward":"-698"},{"validator_index":"212","reward":"-698"},{"validator_index":"213","reward":"-698"},{"validator_index":"214","reward":"-698"},{"validator_index":"215","reward":"-698"},{"validator_index":"216","reward":"-698"},{"validator_index":"217","reward":"-698"},{"validator_index":"218","reward":"-698"},{"validator_index":"219","reward":"-698"},{"validator_index":"220","reward":"-698"},{"validator_index":"221","reward":"-698"},{"validator_index":"222","reward":"-698"},{"validator_index":"223","reward":"-698"},{"validator_index":"224","reward":"-698"},{"validator_index":"225","reward":"-698"},{"validator_index":"226","reward":"-698"},{"validator_index":"227","reward":"-698"},{"validator_index":"228","reward":"-698"},{"validator_index":"229","reward":"-698"},{"validator_index":"230","reward":"-698"},{"validator_index":"231","reward":"-698"},{"validator_index":"232","reward":"-698"},{"validator_index":"233","reward":"-698"},{"validator_index":"234","reward":"-698"},{"validator_index":"235","reward":"-698"},{"validator_index":"236","reward":"-698"},{"validator_index":"237","reward":"-698"},{"validator_index":"238","reward":"-698"},{"validator_index":"239","reward":"-698"},{"validator_index":"240","reward":"-698"},{"validator_index":"241","reward":"-698"},{"validator_index":"242","reward":"-698"},{"validator_index":"243","reward":"-698"},{"validator_index":"244","reward":"-698"},{"validator_index":"245","reward":"-698"},{"validator_index":"246","reward":"-698"},{"validator_index":"247","reward":"-698"},{"validator_index":"248","reward":"-698"},{"validator_index":"249","reward":"-698"},{"validator_index":"250","reward":"-698"},{"validator_index":"251","reward":"-698"},{"validator_index":"252","reward":"-698"},{"validator_index":"253","reward":"-698"},{"validator_index":"254","reward":"-698"},{"validator_index":"255","reward":"-698"}],"finalized":true,"execution_optimistic":false} diff --git a/cl/beacon/handler/test_data/states_1.yaml b/cl/beacon/handler/test_data/states_1.yaml new file mode 100644 index 00000000000..f5e63003f7a --- /dev/null +++ b/cl/beacon/handler/test_data/states_1.yaml @@ -0,0 +1,2 @@ +finality_checkpoint: {"data":{"finalized_checkpoint":{"epoch":"1","root":"0xde46b0f2ed5e72f0cec20246403b14c963ec995d7c2825f3532b0460c09d5693"},"current_justified_checkpoint":{"epoch":"3","root":"0xa6e47f164b1a3ca30ea3b2144bd14711de442f51e5b634750a12a1734e24c987"},"previous_justified_checkpoint":{"epoch":"2","root":"0x4c3ee7969e485696669498a88c17f70e6999c40603e2f4338869004392069063"}},"finalized":false,"version":2,"execution_optimistic":false} +randao: {"data":{"randao":"0xdeec617717272914bfd73e02ca1da113a83cf4cf33cd4939486509e2da4ccf4e"},"finalized":false,"execution_optimistic":false} diff --git a/cl/beacon/handler/test_data/sync_committees_1.json b/cl/beacon/handler/test_data/sync_committees_1.json new file mode 100644 index 00000000000..b593004c7b7 --- /dev/null +++ b/cl/beacon/handler/test_data/sync_committees_1.json @@ -0,0 +1 @@ +{"data":{"validators":["109","134","145","89","181","81","159","168","34","251","3","205","213","202","99","121","80","149","18","65","201","227","116","69","100","74","160","198","16","131","0","73","210","122","209","217","97","237","136","98","229","248","176","95","150","171","238","191","200","220","33","219","126","9","214","124","56","86","169","208","125","85","25","88","13","190","153","183","96","165","180","90","164","104","240","123","118","196","163","222","231","127","241","77","68","32","62","79","44","58","14","187","151","243","139","142","174","106","228","102","223","31","120","5","43","255","179","66","119","170","60","152","167","194","4","112","156","233","254","203","1","55","53","19","92","21","28","42","141","162","146","57","23","45","158","93","212","38","2","206","246","225","195","189","47","193","224","242","76","138","84","140","111","51","135","113","41","133","207","30","82","175","161","6","249","83","234","155","244","177","108","252","94","143","173","8","154","75","50","49","39","36","182","101","48","12","172","87","250","59","24","157","215","218","72","185","71","7","253","114","230","226","110","46","166","91","130","20","137","117","132","204","221","52","197","188","11","232","67","115","245","26","35","103","186","37","27","235","64","40","70","239","236","211","61","29","216","199","63","54","78","105","184","15","10","147","247","22","144","107","128","17","178","148","129","192","109","134","145","89","181","81","159","168","34","251","3","205","213","202","99","121","80","149","18","65","201","227","116","69","100","74","160","198","16","131","0","73","210","122","209","217","97","237","136","98","229","248","176","95","150","171","238","191","200","220","33","219","126","9","214","124","56","86","169","208","125","85","25","88","13","190","153","183","96","165","180","90","164","104","240","123","118","196","163","222","231","127","241","77","68","32","62","79","44","58","14","187","151","243","139","142","174","106","228","102","223","31","120","5","43","255","179","66","119","170","60","152","167","194","4","112","156","233","254","203","1","55","53","19","92","21","28","42","141","162","146","57","23","45","158","93","212","38","2","206","246","225","195","189","47","193","224","242","76","138","84","140","111","51","135","113","41","133","207","30","82","175","161","6","249","83","234","155","244","177","108","252","94","143","173","8","154","75","50","49","39","36","182","101","48","12","172","87","250","59","24","157","215","218","72","185","71","7","253","114","230","226","110","46","166","91","130","20","137","117","132","204","221","52","197","188","11","232","67","115","245","26","35","103","186","37","27","235","64","40","70","239","236","211","61","29","216","199","63","54","78","105","184","15","10","147","247","22","144","107","128","17","178","148","129","192"],"validator_aggregates":[["109","134","145","89","181","81","159","168","34","251","3","205","213","202","99","121","80","149","18","65","201","227","116","69","100","74","160","198","16","131","0","73","210","122","209","217","97","237","136","98","229","248","176","95","150","171","238","191","200","220","33","219","126","9","214","124","56","86","169","208","125","85","25","88","13","190","153","183","96","165","180","90","164","104","240","123","118","196","163","222","231","127","241","77","68","32","62","79","44","58","14","187","151","243","139","142","174","106","228","102","223","31","120","5","43","255","179","66","119","170","60","152","167","194","4","112","156","233","254","203","1","55","53","19","92","21","28","42"],["141","162","146","57","23","45","158","93","212","38","2","206","246","225","195","189","47","193","224","242","76","138","84","140","111","51","135","113","41","133","207","30","82","175","161","6","249","83","234","155","244","177","108","252","94","143","173","8","154","75","50","49","39","36","182","101","48","12","172","87","250","59","24","157","215","218","72","185","71","7","253","114","230","226","110","46","166","91","130","20","137","117","132","204","221","52","197","188","11","232","67","115","245","26","35","103","186","37","27","235","64","40","70","239","236","211","61","29","216","199","63","54","78","105","184","15","10","147","247","22","144","107","128","17","178","148","129","192"],["109","134","145","89","181","81","159","168","34","251","3","205","213","202","99","121","80","149","18","65","201","227","116","69","100","74","160","198","16","131","0","73","210","122","209","217","97","237","136","98","229","248","176","95","150","171","238","191","200","220","33","219","126","9","214","124","56","86","169","208","125","85","25","88","13","190","153","183","96","165","180","90","164","104","240","123","118","196","163","222","231","127","241","77","68","32","62","79","44","58","14","187","151","243","139","142","174","106","228","102","223","31","120","5","43","255","179","66","119","170","60","152","167","194","4","112","156","233","254","203","1","55","53","19","92","21","28","42"],["141","162","146","57","23","45","158","93","212","38","2","206","246","225","195","189","47","193","224","242","76","138","84","140","111","51","135","113","41","133","207","30","82","175","161","6","249","83","234","155","244","177","108","252","94","143","173","8","154","75","50","49","39","36","182","101","48","12","172","87","250","59","24","157","215","218","72","185","71","7","253","114","230","226","110","46","166","91","130","20","137","117","132","204","221","52","197","188","11","232","67","115","245","26","35","103","186","37","27","235","64","40","70","239","236","211","61","29","216","199","63","54","78","105","184","15","10","147","247","22","144","107","128","17","178","148","129","192"]]},"finalized":false,"execution_optimistic":false} diff --git a/cl/beacon/handler/test_data/validators_1.yaml b/cl/beacon/handler/test_data/validators_1.yaml new file mode 100644 index 00000000000..fa092bd7602 --- /dev/null +++ b/cl/beacon/handler/test_data/validators_1.yaml @@ -0,0 +1,9 @@ +- {"data":[{"index":"1","status":"withdrawal_possible","balance":"20125000000","validator":{"pubkey":"0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e","withdrawal_credentials":"0x001f09ed305c0767d56f1b3bdb25f301298027f8e98a8e0cd2dcbcc660723d7b","effective_balance":"20000000000","slashed":false,"activation_eligibility_epoch":"0","activation_epoch":"0","exit_epoch":"253","withdrawable_epoch":"257"}},{"index":"2","status":"active_slashed","balance":"25678253779","validator":{"pubkey":"0x89ece308f9d1f0131765212deca99697b112d61f9be9a5f1f3780a51335b3ff981747a0b2ca2179b96d2c0c9024e5224","withdrawal_credentials":"0x006adc4a1e4caba37c54d56d2411fd0df3a102f8489a4c1be535f4fd5f8810c9","effective_balance":"25000000000","slashed":true,"activation_eligibility_epoch":"0","activation_epoch":"0","exit_epoch":"261","withdrawable_epoch":"8448"}},{"index":"3","status":"active_slashed","balance":"35998164834","validator":{"pubkey":"0xac9b60d5afcbd5663a8a44b7c5a02f19e9a77ab0a35bd65809bb5c67ec582c897feb04decc694b13e08587f3ff9b5b60","withdrawal_credentials":"0x0081c852078a2ad430d438d7eaefc39646f53895292596bbe199e2d7d1884ab8","effective_balance":"32000000000","slashed":true,"activation_eligibility_epoch":"0","activation_epoch":"0","exit_epoch":"261","withdrawable_epoch":"8448"}}],"finalized":true,"execution_optimistic":false} +- {"data":[{"index":"2","status":"active_slashed","balance":"25678253779","validator":{"pubkey":"0x89ece308f9d1f0131765212deca99697b112d61f9be9a5f1f3780a51335b3ff981747a0b2ca2179b96d2c0c9024e5224","withdrawal_credentials":"0x006adc4a1e4caba37c54d56d2411fd0df3a102f8489a4c1be535f4fd5f8810c9","effective_balance":"25000000000","slashed":true,"activation_eligibility_epoch":"0","activation_epoch":"0","exit_epoch":"261","withdrawable_epoch":"8448"}},{"index":"3","status":"active_slashed","balance":"35998164834","validator":{"pubkey":"0xac9b60d5afcbd5663a8a44b7c5a02f19e9a77ab0a35bd65809bb5c67ec582c897feb04decc694b13e08587f3ff9b5b60","withdrawal_credentials":"0x0081c852078a2ad430d438d7eaefc39646f53895292596bbe199e2d7d1884ab8","effective_balance":"32000000000","slashed":true,"activation_eligibility_epoch":"0","activation_epoch":"0","exit_epoch":"261","withdrawable_epoch":"8448"}}],"finalized":true,"execution_optimistic":false} +- {"data":[{"index":"1","status":"withdrawal_possible","balance":"20125000000","validator":{"pubkey":"0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e","withdrawal_credentials":"0x001f09ed305c0767d56f1b3bdb25f301298027f8e98a8e0cd2dcbcc660723d7b","effective_balance":"20000000000","slashed":false,"activation_eligibility_epoch":"0","activation_epoch":"0","exit_epoch":"253","withdrawable_epoch":"257"}}],"finalized":true,"execution_optimistic":false} + +- {"data":[{"index":"1","balance":"20125000000"},{"index":"2","balance":"25678253779"},{"index":"3","balance":"35998164834"}],"finalized":true,"execution_optimistic":false} +- {"data":[{"index":"1","balance":"20125000000"}],"finalized":true,"execution_optimistic":false} + +- {"data":{"index":"1","status":"withdrawal_possible","balance":"20125000000","validator":{"pubkey":"0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e","withdrawal_credentials":"0x001f09ed305c0767d56f1b3bdb25f301298027f8e98a8e0cd2dcbcc660723d7b","effective_balance":"20000000000","slashed":false,"activation_eligibility_epoch":"0","activation_epoch":"0","exit_epoch":"253","withdrawable_epoch":"257"}},"finalized":true,"execution_optimistic":false} +- {"data":{"index":"1","status":"withdrawal_possible","balance":"20125000000","validator":{"pubkey":"0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e","withdrawal_credentials":"0x001f09ed305c0767d56f1b3bdb25f301298027f8e98a8e0cd2dcbcc660723d7b","effective_balance":"20000000000","slashed":false,"activation_eligibility_epoch":"0","activation_epoch":"0","exit_epoch":"253","withdrawable_epoch":"257"}},"finalized":true,"execution_optimistic":false} diff --git a/cl/beacon/handler/utils_test.go b/cl/beacon/handler/utils_test.go index 345cd94d7a6..a23d8654aab 100644 --- a/cl/beacon/handler/utils_test.go +++ b/cl/beacon/handler/utils_test.go @@ -1,4 +1,4 @@ -package handler +package handler_test import ( "context" @@ -9,6 +9,7 @@ import ( "github.com/ledgerwatch/erigon-lib/kv/memdb" "github.com/ledgerwatch/erigon/cl/antiquary" "github.com/ledgerwatch/erigon/cl/antiquary/tests" + "github.com/ledgerwatch/erigon/cl/beacon/handler" "github.com/ledgerwatch/erigon/cl/beacon/synced_data" "github.com/ledgerwatch/erigon/cl/clparams" "github.com/ledgerwatch/erigon/cl/cltypes" @@ -23,7 +24,7 @@ import ( "github.com/stretchr/testify/require" ) -func setupTestingHandler(t *testing.T, v clparams.StateVersion) (db kv.RwDB, blocks []*cltypes.SignedBeaconBlock, f afero.Fs, preState, postState *state.CachingBeaconState, handler *ApiHandler, opPool pool.OperationsPool, syncedData *synced_data.SyncedDataManager, fcu *forkchoice.ForkChoiceStorageMock) { +func setupTestingHandler(t *testing.T, v clparams.StateVersion, logger log.Logger) (db kv.RwDB, blocks []*cltypes.SignedBeaconBlock, f afero.Fs, preState, postState *state.CachingBeaconState, h *handler.ApiHandler, opPool pool.OperationsPool, syncedData *synced_data.SyncedDataManager, fcu *forkchoice.ForkChoiceStorageMock) { bcfg := clparams.MainnetBeaconConfig if v == clparams.Phase0Version { blocks, preState, postState = tests.GetPhase0Random() @@ -44,7 +45,7 @@ func setupTestingHandler(t *testing.T, v clparams.StateVersion) (db kv.RwDB, blo ctx := context.Background() vt := state_accessors.NewStaticValidatorTable() - a := antiquary.NewAntiquary(ctx, preState, vt, &bcfg, datadir.New("/tmp"), nil, db, nil, reader, nil, log.New(), true, true, f) + a := antiquary.NewAntiquary(ctx, preState, vt, &bcfg, datadir.New("/tmp"), nil, db, nil, reader, nil, logger, true, true, f) require.NoError(t, a.IncrementBeaconState(ctx, blocks[len(blocks)-1].Block.Slot+33)) // historical states reader below statesReader := historical_states_reader.NewHistoricalStatesReader(&bcfg, reader, vt, f, preState) @@ -52,7 +53,7 @@ func setupTestingHandler(t *testing.T, v clparams.StateVersion) (db kv.RwDB, blo fcu.Pool = opPool syncedData = synced_data.NewSyncedDataManager(true, &bcfg) gC := clparams.GenesisConfigs[clparams.MainnetNetwork] - handler = NewApiHandler( + h = handler.NewApiHandler( &gC, &bcfg, rawDB, @@ -64,6 +65,6 @@ func setupTestingHandler(t *testing.T, v clparams.StateVersion) (db kv.RwDB, blo statesReader, nil, "test-version") - handler.init() + h.Init() return } diff --git a/cl/beacon/handler/validators.go b/cl/beacon/handler/validators.go index 7935ddf6c0e..f08a9a850b6 100644 --- a/cl/beacon/handler/validators.go +++ b/cl/beacon/handler/validators.go @@ -184,7 +184,7 @@ func checkValidValidatorId(s string) (bool, error) { return false, nil } -func (a *ApiHandler) getAllValidators(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getAllValidators(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { ctx := r.Context() tx, err := a.indiciesDB.BeginRo(ctx) @@ -193,7 +193,7 @@ func (a *ApiHandler) getAllValidators(w http.ResponseWriter, r *http.Request) (* } defer tx.Rollback() - blockId, err := stateIdFromRequest(r) + blockId, err := beaconhttp.StateIdFromRequest(r) if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } @@ -203,12 +203,12 @@ func (a *ApiHandler) getAllValidators(w http.ResponseWriter, r *http.Request) (* return nil, beaconhttp.NewEndpointError(httpStatus, err.Error()) } - queryFilters, err := stringListFromQueryParams(r, "status") + queryFilters, err := beaconhttp.StringListFromQueryParams(r, "status") if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } - validatorIds, err := stringListFromQueryParams(r, "id") + validatorIds, err := beaconhttp.StringListFromQueryParams(r, "id") if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } @@ -226,7 +226,7 @@ func (a *ApiHandler) getAllValidators(w http.ResponseWriter, r *http.Request) (* return nil, err } - if blockId.head() { // Lets see if we point to head, if yes then we need to look at the head state we always keep. + if blockId.Head() { // Lets see if we point to head, if yes then we need to look at the head state we always keep. s, cn := a.syncedData.HeadState() defer cn() if s == nil { @@ -308,7 +308,7 @@ func parseQueryValidatorIndicies(tx kv.Tx, ids []string) ([]uint64, error) { return filterIndicies, nil } -func (a *ApiHandler) getSingleValidator(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getSingleValidator(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { ctx := r.Context() tx, err := a.indiciesDB.BeginRo(ctx) @@ -317,7 +317,7 @@ func (a *ApiHandler) getSingleValidator(w http.ResponseWriter, r *http.Request) } defer tx.Rollback() - blockId, err := stateIdFromRequest(r) + blockId, err := beaconhttp.StateIdFromRequest(r) if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } @@ -327,7 +327,7 @@ func (a *ApiHandler) getSingleValidator(w http.ResponseWriter, r *http.Request) return nil, beaconhttp.NewEndpointError(httpStatus, err.Error()) } - validatorId, err := stringFromRequest(r, "validator_id") + validatorId, err := beaconhttp.StringFromRequest(r, "validator_id") if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } @@ -337,11 +337,11 @@ func (a *ApiHandler) getSingleValidator(w http.ResponseWriter, r *http.Request) return nil, err } - if blockId.head() { // Lets see if we point to head, if yes then we need to look at the head state we always keep. + if blockId.Head() { // Lets see if we point to head, if yes then we need to look at the head state we always keep. s, cn := a.syncedData.HeadState() defer cn() if s.ValidatorLength() <= int(validatorIndex) { - return newBeaconResponse([]int{}).withFinalized(false), nil + return newBeaconResponse([]int{}).WithFinalized(false), nil } if s == nil { return nil, beaconhttp.NewEndpointError(http.StatusNotFound, "node is not synced") @@ -375,7 +375,7 @@ func (a *ApiHandler) getSingleValidator(w http.ResponseWriter, r *http.Request) return responseValidator(validatorIndex, stateEpoch, state.Balances(), state.Validators(), *slot <= a.forkchoiceStore.FinalizedSlot()) } -func (a *ApiHandler) getAllValidatorsBalances(w http.ResponseWriter, r *http.Request) (*beaconResponse, error) { +func (a *ApiHandler) getAllValidatorsBalances(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) { ctx := r.Context() tx, err := a.indiciesDB.BeginRo(ctx) @@ -384,7 +384,7 @@ func (a *ApiHandler) getAllValidatorsBalances(w http.ResponseWriter, r *http.Req } defer tx.Rollback() - blockId, err := stateIdFromRequest(r) + blockId, err := beaconhttp.StateIdFromRequest(r) if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } @@ -394,7 +394,7 @@ func (a *ApiHandler) getAllValidatorsBalances(w http.ResponseWriter, r *http.Req return nil, beaconhttp.NewEndpointError(httpStatus, err.Error()) } - validatorIds, err := stringListFromQueryParams(r, "id") + validatorIds, err := beaconhttp.StringListFromQueryParams(r, "id") if err != nil { return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error()) } @@ -407,7 +407,7 @@ func (a *ApiHandler) getAllValidatorsBalances(w http.ResponseWriter, r *http.Req return nil, err } - if blockId.head() { // Lets see if we point to head, if yes then we need to look at the head state we always keep. + if blockId.Head() { // Lets see if we point to head, if yes then we need to look at the head state we always keep. s, cn := a.syncedData.HeadState() defer cn() if s == nil { @@ -444,7 +444,7 @@ func (d directString) MarshalJSON() ([]byte, error) { return []byte(d), nil } -func responseValidators(filterIndicies []uint64, filterStatuses []validatorStatus, stateEpoch uint64, balances solid.Uint64ListSSZ, validators *solid.ValidatorSet, finalized bool) (*beaconResponse, error) { +func responseValidators(filterIndicies []uint64, filterStatuses []validatorStatus, stateEpoch uint64, balances solid.Uint64ListSSZ, validators *solid.ValidatorSet, finalized bool) (*beaconhttp.BeaconResponse, error) { var b strings.Builder b.WriteString("[") first := true @@ -474,14 +474,14 @@ func responseValidators(filterIndicies []uint64, filterStatuses []validatorStatu _, err = b.WriteString("]\n") - return newBeaconResponse(directString(b.String())).withFinalized(finalized), err + return newBeaconResponse(directString(b.String())).WithFinalized(finalized), err } -func responseValidator(idx uint64, stateEpoch uint64, balances solid.Uint64ListSSZ, validators *solid.ValidatorSet, finalized bool) (*beaconResponse, error) { +func responseValidator(idx uint64, stateEpoch uint64, balances solid.Uint64ListSSZ, validators *solid.ValidatorSet, finalized bool) (*beaconhttp.BeaconResponse, error) { var b strings.Builder var err error if validators.Length() <= int(idx) { - return newBeaconResponse([]int{}).withFinalized(finalized), nil + return newBeaconResponse([]int{}).WithFinalized(finalized), nil } v := validators.Get(int(idx)) @@ -493,10 +493,10 @@ func responseValidator(idx uint64, stateEpoch uint64, balances solid.Uint64ListS _, err = b.WriteString("\n") - return newBeaconResponse(directString(b.String())).withFinalized(finalized), err + return newBeaconResponse(directString(b.String())).WithFinalized(finalized), err } -func responseValidatorsBalances(filterIndicies []uint64, stateEpoch uint64, balances solid.Uint64ListSSZ, finalized bool) (*beaconResponse, error) { +func responseValidatorsBalances(filterIndicies []uint64, stateEpoch uint64, balances solid.Uint64ListSSZ, finalized bool) (*beaconhttp.BeaconResponse, error) { var b strings.Builder b.WriteString("[") jsonTemplate := "{\"index\":\"%d\",\"balance\":\"%d\"}" @@ -524,7 +524,7 @@ func responseValidatorsBalances(filterIndicies []uint64, stateEpoch uint64, bala _, err = b.WriteString("]\n") - return newBeaconResponse(directString(b.String())).withFinalized(finalized), err + return newBeaconResponse(directString(b.String())).WithFinalized(finalized), err } func shouldStatusBeFiltered(status validatorStatus, statuses []validatorStatus) bool { diff --git a/cl/beacon/handler/validators_test.go b/cl/beacon/handler/validators_test.go deleted file mode 100644 index 7f09084685b..00000000000 --- a/cl/beacon/handler/validators_test.go +++ /dev/null @@ -1,201 +0,0 @@ -//go:build integration - -package handler - -import ( - "io" - "net/http" - "net/http/httptest" - "testing" - - "github.com/ledgerwatch/erigon/cl/clparams" - "github.com/ledgerwatch/erigon/cl/cltypes/solid" - "github.com/ledgerwatch/erigon/common" - "github.com/stretchr/testify/require" -) - -func TestGetAllValidators(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, postState, handler, _, _, fcu := setupTestingHandler(t, clparams.Phase0Version) - - postRoot, err := postState.HashSSZ() - require.NoError(t, err) - - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) - - cases := []struct { - blockID string - code int - queryParams string - expectedResp string - }{ - { - blockID: "0x" + common.Bytes2Hex(postRoot[:]), - code: http.StatusOK, - queryParams: "?id=1,2,3", - expectedResp: `{"data":[{"index":"1","status":"withdrawal_possible","balance":"20125000000","validator":{"pubkey":"0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e","withdrawal_credentials":"0x001f09ed305c0767d56f1b3bdb25f301298027f8e98a8e0cd2dcbcc660723d7b","effective_balance":"20000000000","slashed":false,"activation_eligibility_epoch":"0","activation_epoch":"0","exit_epoch":"253","withdrawable_epoch":"257"}},{"index":"2","status":"active_slashed","balance":"25678253779","validator":{"pubkey":"0x89ece308f9d1f0131765212deca99697b112d61f9be9a5f1f3780a51335b3ff981747a0b2ca2179b96d2c0c9024e5224","withdrawal_credentials":"0x006adc4a1e4caba37c54d56d2411fd0df3a102f8489a4c1be535f4fd5f8810c9","effective_balance":"25000000000","slashed":true,"activation_eligibility_epoch":"0","activation_epoch":"0","exit_epoch":"261","withdrawable_epoch":"8448"}},{"index":"3","status":"active_slashed","balance":"35998164834","validator":{"pubkey":"0xac9b60d5afcbd5663a8a44b7c5a02f19e9a77ab0a35bd65809bb5c67ec582c897feb04decc694b13e08587f3ff9b5b60","withdrawal_credentials":"0x0081c852078a2ad430d438d7eaefc39646f53895292596bbe199e2d7d1884ab8","effective_balance":"32000000000","slashed":true,"activation_eligibility_epoch":"0","activation_epoch":"0","exit_epoch":"261","withdrawable_epoch":"8448"}}],"finalized":true,"execution_optimistic":false}` + "\n", - }, - { - blockID: "finalized", - code: http.StatusOK, - queryParams: "?status=active&id=1,2,3", - expectedResp: `{"data":[{"index":"2","status":"active_slashed","balance":"25678253779","validator":{"pubkey":"0x89ece308f9d1f0131765212deca99697b112d61f9be9a5f1f3780a51335b3ff981747a0b2ca2179b96d2c0c9024e5224","withdrawal_credentials":"0x006adc4a1e4caba37c54d56d2411fd0df3a102f8489a4c1be535f4fd5f8810c9","effective_balance":"25000000000","slashed":true,"activation_eligibility_epoch":"0","activation_epoch":"0","exit_epoch":"261","withdrawable_epoch":"8448"}},{"index":"3","status":"active_slashed","balance":"35998164834","validator":{"pubkey":"0xac9b60d5afcbd5663a8a44b7c5a02f19e9a77ab0a35bd65809bb5c67ec582c897feb04decc694b13e08587f3ff9b5b60","withdrawal_credentials":"0x0081c852078a2ad430d438d7eaefc39646f53895292596bbe199e2d7d1884ab8","effective_balance":"32000000000","slashed":true,"activation_eligibility_epoch":"0","activation_epoch":"0","exit_epoch":"261","withdrawable_epoch":"8448"}}],"finalized":true,"execution_optimistic":false}` + "\n", - }, - { - blockID: "finalized", - code: http.StatusOK, - queryParams: "?id=0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e", - expectedResp: `{"data":[{"index":"1","status":"withdrawal_possible","balance":"20125000000","validator":{"pubkey":"0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e","withdrawal_credentials":"0x001f09ed305c0767d56f1b3bdb25f301298027f8e98a8e0cd2dcbcc660723d7b","effective_balance":"20000000000","slashed":false,"activation_eligibility_epoch":"0","activation_epoch":"0","exit_epoch":"253","withdrawable_epoch":"257"}}],"finalized":true,"execution_optimistic":false}` + "\n", - }, - { - blockID: "alabama", - code: http.StatusBadRequest, - }, - } - - for _, c := range cases { - t.Run(c.blockID, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - // Query the block in the handler with /eth/v2/beacon/blocks/{block_id} - resp, err := http.Get(server.URL + "/eth/v1/beacon/states/" + c.blockID + "/validators" + c.queryParams) - require.NoError(t, err) - defer resp.Body.Close() - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - - // unmarshal the json - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.Equal(t, c.expectedResp, string(out)) - - }) - } -} - -func TestGetValidatorsBalances(t *testing.T) { - t.Skip("FIXME: oom") - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, postState, handler, _, _, fcu := setupTestingHandler(t, clparams.Phase0Version) - - postRoot, err := postState.HashSSZ() - require.NoError(t, err) - - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) - - cases := []struct { - blockID string - code int - queryParams string - expectedResp string - }{ - { - blockID: "0x" + common.Bytes2Hex(postRoot[:]), - code: http.StatusOK, - queryParams: "?id=1,2,3", - expectedResp: `{"data":[{"index":"1","balance":"20125000000"},{"index":"2","balance":"25678253779"},{"index":"3","balance":"35998164834"}],"finalized":true,"execution_optimistic":false}` + "\n", - }, - { - blockID: "finalized", - code: http.StatusOK, - queryParams: "?id=0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e", - expectedResp: `{"data":[{"index":"1","balance":"20125000000"}],"finalized":true,"execution_optimistic":false}` + "\n", - }, - { - blockID: "alabama", - code: http.StatusBadRequest, - }, - } - - for _, c := range cases { - t.Run(c.blockID, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - // Query the block in the handler with /eth/v2/beacon/blocks/{block_id} - resp, err := http.Get(server.URL + "/eth/v1/beacon/states/" + c.blockID + "/validator_balances" + c.queryParams) - require.NoError(t, err) - defer resp.Body.Close() - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - // unmarshal the json - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.Equal(t, c.expectedResp, string(out)) - - }) - } -} - -func TestGetSingleValidator(t *testing.T) { - - // setupTestingHandler(t, clparams.Phase0Version) - _, blocks, _, _, postState, handler, _, _, fcu := setupTestingHandler(t, clparams.Phase0Version) - - postRoot, err := postState.HashSSZ() - require.NoError(t, err) - - fcu.HeadVal, err = blocks[len(blocks)-1].Block.HashSSZ() - require.NoError(t, err) - - fcu.HeadSlotVal = blocks[len(blocks)-1].Block.Slot - fcu.FinalizedCheckpointVal = solid.NewCheckpointFromParameters(fcu.HeadVal, fcu.HeadSlotVal/32) - - cases := []struct { - blockID string - code int - validatorIdx string - expectedResp string - }{ - { - blockID: "0x" + common.Bytes2Hex(postRoot[:]), - code: http.StatusOK, - validatorIdx: "1", - expectedResp: `{"data":{"index":"1","status":"withdrawal_possible","balance":"20125000000","validator":{"pubkey":"0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e","withdrawal_credentials":"0x001f09ed305c0767d56f1b3bdb25f301298027f8e98a8e0cd2dcbcc660723d7b","effective_balance":"20000000000","slashed":false,"activation_eligibility_epoch":"0","activation_epoch":"0","exit_epoch":"253","withdrawable_epoch":"257"}},"finalized":true,"execution_optimistic":false}` + "\n", - }, - { - blockID: "finalized", - code: http.StatusOK, - validatorIdx: "0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e", - expectedResp: `{"data":{"index":"1","status":"withdrawal_possible","balance":"20125000000","validator":{"pubkey":"0xa572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e","withdrawal_credentials":"0x001f09ed305c0767d56f1b3bdb25f301298027f8e98a8e0cd2dcbcc660723d7b","effective_balance":"20000000000","slashed":false,"activation_eligibility_epoch":"0","activation_epoch":"0","exit_epoch":"253","withdrawable_epoch":"257"}},"finalized":true,"execution_optimistic":false}` + "\n", - }, - { - blockID: "alabama", - code: http.StatusBadRequest, - validatorIdx: "3", - }, - } - - for _, c := range cases { - t.Run(c.blockID, func(t *testing.T) { - server := httptest.NewServer(handler.mux) - defer server.Close() - // Query the block in the handler with /eth/v2/beacon/blocks/{block_id} - resp, err := http.Get(server.URL + "/eth/v1/beacon/states/" + c.blockID + "/validators/" + c.validatorIdx) - require.NoError(t, err) - defer resp.Body.Close() - require.Equal(t, c.code, resp.StatusCode) - if resp.StatusCode != http.StatusOK { - return - } - // unmarshal the json - out, err := io.ReadAll(resp.Body) - require.NoError(t, err) - require.Equal(t, c.expectedResp, string(out)) - - }) - } -} diff --git a/go.mod b/go.mod index 86952bf1d78..514e8f51903 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( gfx.cafe/util/go/generic v0.0.0-20230721185457-c559e86c829c github.com/99designs/gqlgen v0.17.40 github.com/Giulio2002/bls v0.0.0-20230906201036-c2330c97dc7d + github.com/Masterminds/sprig/v3 v3.2.3 github.com/RoaringBitmap/roaring v1.2.3 github.com/VictoriaMetrics/fastcache v1.12.2 github.com/alecthomas/kong v0.8.0 @@ -45,6 +46,7 @@ require ( github.com/golang/mock v1.6.0 github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb github.com/google/btree v1.1.2 + github.com/google/cel-go v0.18.2 github.com/google/gofuzz v1.2.0 github.com/gorilla/websocket v1.5.1 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 @@ -103,9 +105,12 @@ require ( gopkg.in/yaml.v3 v3.0.1 modernc.org/sqlite v1.28.0 pgregory.net/rapid v1.1.0 + sigs.k8s.io/yaml v1.4.0 ) require ( + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.2.0 // indirect github.com/agnivade/levenshtein v1.1.1 // indirect github.com/ajwerner/btree v0.0.0-20211221152037-f427b3e689c0 // indirect github.com/alecthomas/atomic v0.1.0-alpha2 // indirect @@ -122,6 +127,7 @@ require ( github.com/anacrolix/stm v0.4.1-0.20221221005312-96d17df0e496 // indirect github.com/anacrolix/upnp v0.1.3-0.20220123035249-922794e51c96 // indirect github.com/anacrolix/utp v0.1.0 // indirect + github.com/antlr4-go/antlr/v4 v4.13.0 // indirect github.com/aws/aws-sdk-go-v2 v1.21.2 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.14 // indirect github.com/aws/aws-sdk-go-v2/config v1.19.0 // indirect @@ -178,6 +184,7 @@ require ( github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect github.com/google/uuid v1.3.1 // indirect github.com/ianlancetaylor/cgosymbolizer v0.0.0-20220405231054-a1ae3e4bba26 // indirect + github.com/imdario/mergo v0.3.11 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/ipfs/go-cid v0.4.1 // indirect github.com/ipfs/go-log/v2 v2.5.1 // indirect @@ -207,7 +214,9 @@ require ( github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect github.com/minio/sha256-simd v1.0.1 // indirect + github.com/mitchellh/copystructure v1.0.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mitchellh/reflectwalk v1.0.0 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -256,9 +265,12 @@ require ( github.com/rogpeppe/go-internal v1.12.0 // indirect github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/shopspring/decimal v1.2.0 // indirect github.com/sirupsen/logrus v1.9.0 // indirect github.com/sosodev/duration v1.1.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect + github.com/spf13/cast v1.3.1 // indirect + github.com/stoewer/go-strcase v1.2.0 // indirect github.com/supranational/blst v0.3.11 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect go.etcd.io/bbolt v1.3.6 // indirect @@ -270,6 +282,7 @@ require ( golang.org/x/mod v0.14.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.16.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 // indirect gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect diff --git a/go.sum b/go.sum index 386b04a07d7..4de0d41eac7 100644 --- a/go.sum +++ b/go.sum @@ -55,6 +55,12 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Giulio2002/bls v0.0.0-20230906201036-c2330c97dc7d h1:fAztVLpjcVcd2al4GL8xYr9Yp7LmXXSTuLqu83U8hKo= github.com/Giulio2002/bls v0.0.0-20230906201036-c2330c97dc7d/go.mod h1:nCQrFU6/QsJtLS+SBLWRn9UG2nds1f3hQKfWHCrtUqw= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= +github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/RoaringBitmap/roaring v0.4.7/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w= github.com/RoaringBitmap/roaring v0.4.17/go.mod h1:D3qVegWTmfCaX4Bl5CrBE9hfrSrrXIr8KVNvRsDi1NI= github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo= @@ -137,6 +143,8 @@ github.com/anacrolix/utp v0.1.0 h1:FOpQOmIwYsnENnz7tAGohA+r6iXpRjrq8ssKSre2Cp4= github.com/anacrolix/utp v0.1.0/go.mod h1:MDwc+vsGEq7RMw6lr2GKOEqjWny5hO5OZXRVNaBJ2Dk= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= +github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= @@ -407,6 +415,8 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/cel-go v0.18.2 h1:L0B6sNBSVmt0OyECi8v6VOS74KOc9W/tLiWKfZABvf4= +github.com/google/cel-go v0.18.2/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -419,6 +429,7 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -443,6 +454,7 @@ github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b h1:h9U78+dx9a4BKdQkBB github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= @@ -480,6 +492,7 @@ github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63 github.com/huandu/xstrings v1.3.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huin/goupnp v1.2.0 h1:uOKW26NG1hsSSbXIZ1IR7XP9Gjd1U8pnLaCMgntmkmY= @@ -488,6 +501,8 @@ github.com/ianlancetaylor/cgosymbolizer v0.0.0-20220405231054-a1ae3e4bba26 h1:UT github.com/ianlancetaylor/cgosymbolizer v0.0.0-20220405231054-a1ae3e4bba26/go.mod h1:DvXTE/K/RtHehxU8/GtDs4vFtfw64jJ3PaCnFri8CRg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= @@ -611,8 +626,12 @@ github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8Rv github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= +github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= @@ -808,6 +827,8 @@ github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5P github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= @@ -848,10 +869,14 @@ github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0b github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= +github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -955,6 +980,7 @@ golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220516162934-403b01795ae8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= @@ -1051,6 +1077,7 @@ golang.org/x/net v0.0.0-20220401154927-543a649e0bdd/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220531201128-c960675eff93/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= @@ -1151,6 +1178,7 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1162,6 +1190,7 @@ golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= @@ -1174,6 +1203,7 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= @@ -1321,6 +1351,8 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU= +google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0= google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0= google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= @@ -1429,6 +1461,8 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= zombiezen.com/go/sqlite v0.13.1 h1:qDzxyWWmMtSSEH5qxamqBFmqA2BLSSbtODi3ojaE02o= From c5b75d00ca469b0fe84eadaa3437cd897d32b44d Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Mon, 15 Jan 2024 12:36:25 +0100 Subject: [PATCH 63/92] polygon/sync: span updates (#9229) It is possible that a span update happens during a milestone. A headers slice might cross to the new span. Also if 2 forks evolve simulaneously, a shorter fork can still be in the previous span. In these cases we need access to the previous span to calculate difficulty and validate header times. SpansCache will keep recent spans. The cache will be updated on new span events from the heimdall. The cache is pruned on new milestone events and in practice no more than 2 spans are kept. The header difficulty calculation and time validation depends on having a span for that header in the cache. --- polygon/sync/canonical_chain_builder.go | 17 ++++++--- polygon/sync/canonical_chain_builder_test.go | 2 +- polygon/sync/difficulty.go | 32 +++++++++-------- polygon/sync/difficulty_test.go | 17 ++++++--- polygon/sync/header_time_validator.go | 33 ++++++++++-------- polygon/sync/spans_cache.go | 36 ++++++++++++++++++++ 6 files changed, 96 insertions(+), 41 deletions(-) create mode 100644 polygon/sync/spans_cache.go diff --git a/polygon/sync/canonical_chain_builder.go b/polygon/sync/canonical_chain_builder.go index 2c6d6328591..b6575544ba8 100644 --- a/polygon/sync/canonical_chain_builder.go +++ b/polygon/sync/canonical_chain_builder.go @@ -37,20 +37,21 @@ type canonicalChainBuilderImpl struct { root *forkTreeNode tip *forkTreeNode - difficultyCalc DifficultyCalculator - + difficultyCalc DifficultyCalculator headerValidator HeaderValidator + spansCache *SpansCache } func NewCanonicalChainBuilder( root *types.Header, difficultyCalc DifficultyCalculator, headerValidator HeaderValidator, + spansCache *SpansCache, ) CanonicalChainBuilder { impl := &canonicalChainBuilderImpl{ - difficultyCalc: difficultyCalc, - + difficultyCalc: difficultyCalc, headerValidator: headerValidator, + spansCache: spansCache, } impl.Reset(root) return impl @@ -63,6 +64,9 @@ func (impl *canonicalChainBuilderImpl) Reset(root *types.Header) { headerHash: root.Hash(), } impl.tip = impl.root + if impl.spansCache != nil { + impl.spansCache.Prune(root.Number.Uint64()) + } } // depth-first search @@ -138,8 +142,11 @@ func (impl *canonicalChainBuilderImpl) Prune(newRootNum uint64) error { for newRoot.header.Number.Uint64() > newRootNum { newRoot = newRoot.parent } - impl.root = newRoot + + if impl.spansCache != nil { + impl.spansCache.Prune(newRootNum) + } return nil } diff --git a/polygon/sync/canonical_chain_builder_test.go b/polygon/sync/canonical_chain_builder_test.go index 86392a8c68e..0fb0617323c 100644 --- a/polygon/sync/canonical_chain_builder_test.go +++ b/polygon/sync/canonical_chain_builder_test.go @@ -34,7 +34,7 @@ func makeRoot() *types.Header { func makeCCB(root *types.Header) CanonicalChainBuilder { difficultyCalc := testDifficultyCalculator{} - builder := NewCanonicalChainBuilder(root, &difficultyCalc, nil) + builder := NewCanonicalChainBuilder(root, &difficultyCalc, nil, nil) return builder } diff --git a/polygon/sync/difficulty.go b/polygon/sync/difficulty.go index 1ccb4c0b106..7880ade672f 100644 --- a/polygon/sync/difficulty.go +++ b/polygon/sync/difficulty.go @@ -1,12 +1,12 @@ package sync import ( + "fmt" + lru "github.com/hashicorp/golang-lru/arc/v2" "github.com/ledgerwatch/erigon/eth/stagedsync" - heimdallspan "github.com/ledgerwatch/erigon/polygon/heimdall/span" - libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/polygon/bor" @@ -16,20 +16,19 @@ import ( type DifficultyCalculator interface { HeaderDifficulty(header *types.Header) (uint64, error) - SetSpan(span *heimdallspan.HeimdallSpan) } type difficultyCalculatorImpl struct { borConfig *borcfg.BorConfig - span *heimdallspan.HeimdallSpan - validatorSetFactory func() validatorSetInterface + spans *SpansCache + validatorSetFactory func(headerNum uint64) validatorSetInterface signaturesCache *lru.ARCCache[libcommon.Hash, libcommon.Address] } func NewDifficultyCalculator( borConfig *borcfg.BorConfig, - span *heimdallspan.HeimdallSpan, - validatorSetFactory func() validatorSetInterface, + spans *SpansCache, + validatorSetFactory func(headerNum uint64) validatorSetInterface, signaturesCache *lru.ARCCache[libcommon.Hash, libcommon.Address], ) DifficultyCalculator { if signaturesCache == nil { @@ -42,7 +41,7 @@ func NewDifficultyCalculator( impl := difficultyCalculatorImpl{ borConfig: borConfig, - span: span, + spans: spans, validatorSetFactory: validatorSetFactory, signaturesCache: signaturesCache, } @@ -54,12 +53,12 @@ func NewDifficultyCalculator( return &impl } -func (impl *difficultyCalculatorImpl) makeValidatorSet() validatorSetInterface { - return valset.NewValidatorSet(impl.span.ValidatorSet.Validators) -} - -func (impl *difficultyCalculatorImpl) SetSpan(span *heimdallspan.HeimdallSpan) { - impl.span = span +func (impl *difficultyCalculatorImpl) makeValidatorSet(headerNum uint64) validatorSetInterface { + span := impl.spans.SpanAt(headerNum) + if span == nil { + return nil + } + return valset.NewValidatorSet(span.ValidatorSet.Validators) } func (impl *difficultyCalculatorImpl) HeaderDifficulty(header *types.Header) (uint64, error) { @@ -71,7 +70,10 @@ func (impl *difficultyCalculatorImpl) HeaderDifficulty(header *types.Header) (ui } func (impl *difficultyCalculatorImpl) signerDifficulty(signer libcommon.Address, headerNum uint64) (uint64, error) { - validatorSet := impl.validatorSetFactory() + validatorSet := impl.validatorSetFactory(headerNum) + if validatorSet == nil { + return 0, fmt.Errorf("difficultyCalculatorImpl.signerDifficulty: no span at %d", headerNum) + } sprintNum := impl.borConfig.CalculateSprintNumber(headerNum) if sprintNum > 0 { diff --git a/polygon/sync/difficulty_test.go b/polygon/sync/difficulty_test.go index 4a3f7f39fad..669b8dbcfc3 100644 --- a/polygon/sync/difficulty_test.go +++ b/polygon/sync/difficulty_test.go @@ -7,8 +7,6 @@ import ( "github.com/stretchr/testify/require" - heimdallspan "github.com/ledgerwatch/erigon/polygon/heimdall/span" - libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/polygon/bor/borcfg" @@ -57,7 +55,7 @@ func TestSignerDifficulty(t *testing.T) { libcommon.HexToAddress("01"), libcommon.HexToAddress("02"), } - validatorSetFactory := func() validatorSetInterface { return &testValidatorSetInterface{signers: signers} } + validatorSetFactory := func(uint64) validatorSetInterface { return &testValidatorSetInterface{signers: signers} } calc := NewDifficultyCalculator(&borConfig, nil, validatorSetFactory, nil).(*difficultyCalculatorImpl) var d uint64 @@ -123,9 +121,18 @@ func TestSignerDifficulty(t *testing.T) { func TestHeaderDifficultyNoSignature(t *testing.T) { borConfig := borcfg.BorConfig{} - span := heimdallspan.HeimdallSpan{} - calc := NewDifficultyCalculator(&borConfig, &span, nil, nil) + spans := NewSpansCache() + calc := NewDifficultyCalculator(&borConfig, spans, nil, nil) _, err := calc.HeaderDifficulty(new(types.Header)) require.ErrorContains(t, err, "signature suffix missing") } + +func TestSignerDifficultyNoSpan(t *testing.T) { + borConfig := borcfg.BorConfig{} + spans := NewSpansCache() + calc := NewDifficultyCalculator(&borConfig, spans, nil, nil).(*difficultyCalculatorImpl) + + _, err := calc.signerDifficulty(libcommon.HexToAddress("00"), 0) + require.ErrorContains(t, err, "no span") +} diff --git a/polygon/sync/header_time_validator.go b/polygon/sync/header_time_validator.go index 8b84e36c0a7..d2da61764cc 100644 --- a/polygon/sync/header_time_validator.go +++ b/polygon/sync/header_time_validator.go @@ -1,6 +1,7 @@ package sync import ( + "fmt" "time" lru "github.com/hashicorp/golang-lru/arc/v2" @@ -11,25 +12,23 @@ import ( "github.com/ledgerwatch/erigon/polygon/bor" "github.com/ledgerwatch/erigon/polygon/bor/borcfg" "github.com/ledgerwatch/erigon/polygon/bor/valset" - heimdallspan "github.com/ledgerwatch/erigon/polygon/heimdall/span" ) type HeaderTimeValidator interface { ValidateHeaderTime(header *types.Header, now time.Time, parent *types.Header) error - SetSpan(span *heimdallspan.HeimdallSpan) } type headerTimeValidatorImpl struct { borConfig *borcfg.BorConfig - span *heimdallspan.HeimdallSpan - validatorSetFactory func() validatorSetInterface + spans *SpansCache + validatorSetFactory func(headerNum uint64) validatorSetInterface signaturesCache *lru.ARCCache[libcommon.Hash, libcommon.Address] } func NewHeaderTimeValidator( borConfig *borcfg.BorConfig, - span *heimdallspan.HeimdallSpan, - validatorSetFactory func() validatorSetInterface, + spans *SpansCache, + validatorSetFactory func(headerNum uint64) validatorSetInterface, signaturesCache *lru.ARCCache[libcommon.Hash, libcommon.Address], ) HeaderTimeValidator { if signaturesCache == nil { @@ -42,7 +41,7 @@ func NewHeaderTimeValidator( impl := headerTimeValidatorImpl{ borConfig: borConfig, - span: span, + spans: spans, validatorSetFactory: validatorSetFactory, signaturesCache: signaturesCache, } @@ -54,18 +53,22 @@ func NewHeaderTimeValidator( return &impl } -func (impl *headerTimeValidatorImpl) makeValidatorSet() validatorSetInterface { - return valset.NewValidatorSet(impl.span.ValidatorSet.Validators) -} - -func (impl *headerTimeValidatorImpl) SetSpan(span *heimdallspan.HeimdallSpan) { - impl.span = span +func (impl *headerTimeValidatorImpl) makeValidatorSet(headerNum uint64) validatorSetInterface { + span := impl.spans.SpanAt(headerNum) + if span == nil { + return nil + } + return valset.NewValidatorSet(span.ValidatorSet.Validators) } func (impl *headerTimeValidatorImpl) ValidateHeaderTime(header *types.Header, now time.Time, parent *types.Header) error { - validatorSet := impl.validatorSetFactory() + headerNum := header.Number.Uint64() + validatorSet := impl.validatorSetFactory(headerNum) + if validatorSet == nil { + return fmt.Errorf("headerTimeValidatorImpl.ValidateHeaderTime: no span at %d", headerNum) + } - sprintNum := impl.borConfig.CalculateSprintNumber(header.Number.Uint64()) + sprintNum := impl.borConfig.CalculateSprintNumber(headerNum) if sprintNum > 0 { validatorSet.IncrementProposerPriority(int(sprintNum)) } diff --git a/polygon/sync/spans_cache.go b/polygon/sync/spans_cache.go new file mode 100644 index 00000000000..5c03a422979 --- /dev/null +++ b/polygon/sync/spans_cache.go @@ -0,0 +1,36 @@ +package sync + +import heimdallspan "github.com/ledgerwatch/erigon/polygon/heimdall/span" + +type SpansCache struct { + spans map[uint64]*heimdallspan.HeimdallSpan +} + +func NewSpansCache() *SpansCache { + return &SpansCache{ + spans: make(map[uint64]*heimdallspan.HeimdallSpan), + } +} + +func (cache *SpansCache) Add(span *heimdallspan.HeimdallSpan) { + cache.spans[span.StartBlock] = span +} + +// SpanAt finds a span that contains blockNum. +func (cache *SpansCache) SpanAt(blockNum uint64) *heimdallspan.HeimdallSpan { + for _, span := range cache.spans { + if (span.StartBlock <= blockNum) && (blockNum <= span.EndBlock) { + return span + } + } + return nil +} + +// Prune removes spans that ended before blockNum. +func (cache *SpansCache) Prune(blockNum uint64) { + for key, span := range cache.spans { + if span.EndBlock < blockNum { + delete(cache.spans, key) + } + } +} From fb0226d293d3b44de5afcb06b6a5e37d0efa0bb5 Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Mon, 15 Jan 2024 12:37:37 +0100 Subject: [PATCH 64/92] polygon/sync: move PeersWithBlockNumInfo and mocks, refactor bor.GetRootHash (#9232) --- polygon/bor/bor.go | 22 +++++++++----- polygon/sync/canonical_chain_builder.go | 2 +- .../canonical_chain_builder_mock.go | 4 +-- polygon/sync/db.go | 2 +- polygon/sync/{mock => }/db_mock.go | 4 +-- polygon/sync/header_downloader.go | 9 +++--- polygon/sync/header_downloader_test.go | 29 +++++++++---------- polygon/sync/header_verifier.go | 5 ---- polygon/sync/heimdall.go | 2 +- polygon/sync/{mock => }/heimdall_mock.go | 4 +-- .../peer_with_block_num_info.go | 2 +- polygon/sync/sentry.go | 5 ++-- polygon/sync/{mock => }/sentry_mock.go | 9 +++--- polygon/sync/state_point_headers_verifier.go | 22 ++++++++++++++ 14 files changed, 70 insertions(+), 51 deletions(-) rename polygon/sync/{mock => }/canonical_chain_builder_mock.go (98%) rename polygon/sync/{mock => }/db_mock.go (95%) delete mode 100644 polygon/sync/header_verifier.go rename polygon/sync/{mock => }/heimdall_mock.go (98%) rename polygon/sync/{peerinfo => }/peer_with_block_num_info.go (96%) rename polygon/sync/{mock => }/sentry_mock.go (91%) create mode 100644 polygon/sync/state_point_headers_verifier.go diff --git a/polygon/bor/bor.go b/polygon/bor/bor.go index df251b81daa..90fb15965e3 100644 --- a/polygon/bor/bor.go +++ b/polygon/bor/bor.go @@ -1392,12 +1392,23 @@ func (c *Bor) GetRootHash(ctx context.Context, tx kv.Tx, start, end uint64) (str if start > end || end > currentHeaderNumber { return "", &valset.InvalidStartEndBlockError{Start: start, End: end, CurrentHeader: currentHeaderNumber} } - blockHeaders := make([]*types.Header, end-start+1) + blockHeaders := make([]*types.Header, length) for number := start; number <= end; number++ { blockHeaders[number-start], _ = c.getHeaderByNumber(ctx, tx, number) } - headers := make([][32]byte, NextPowerOfTwo(length)) + hash, err := ComputeHeadersRootHash(blockHeaders) + if err != nil { + return "", err + } + + hashStr := hex.EncodeToString(hash) + c.rootHashCache.Add(cacheKey, hashStr) + return hashStr, nil +} + +func ComputeHeadersRootHash(blockHeaders []*types.Header) ([]byte, error) { + headers := make([][32]byte, NextPowerOfTwo(uint64(len(blockHeaders)))) for i := 0; i < len(blockHeaders); i++ { blockHeader := blockHeaders[i] header := crypto.Keccak256(AppendBytes32( @@ -1413,13 +1424,10 @@ func (c *Bor) GetRootHash(ctx context.Context, tx kv.Tx, start, end uint64) (str } tree := merkle.NewTreeWithOpts(merkle.TreeOptions{EnableHashSorting: false, DisableHashLeaves: true}) if err := tree.Generate(Convert(headers), sha3.NewLegacyKeccak256()); err != nil { - return "", err + return nil, err } - root := hex.EncodeToString(tree.Root().Hash) - - c.rootHashCache.Add(cacheKey, root) - return root, nil + return tree.Root().Hash, nil } func (c *Bor) getHeaderByNumber(ctx context.Context, tx kv.Tx, number uint64) (*types.Header, error) { diff --git a/polygon/sync/canonical_chain_builder.go b/polygon/sync/canonical_chain_builder.go index b6575544ba8..541100c9b7c 100644 --- a/polygon/sync/canonical_chain_builder.go +++ b/polygon/sync/canonical_chain_builder.go @@ -11,7 +11,7 @@ import ( "github.com/ledgerwatch/erigon/polygon/bor" ) -//go:generate mockgen -destination=./mock/canonical_chain_builder_mock.go -package=mock . CanonicalChainBuilder +//go:generate mockgen -destination=./canonical_chain_builder_mock.go -package=sync . CanonicalChainBuilder type CanonicalChainBuilder interface { Reset(root *types.Header) ContainsHash(hash libcommon.Hash) bool diff --git a/polygon/sync/mock/canonical_chain_builder_mock.go b/polygon/sync/canonical_chain_builder_mock.go similarity index 98% rename from polygon/sync/mock/canonical_chain_builder_mock.go rename to polygon/sync/canonical_chain_builder_mock.go index 2985c446798..0ee6e49e3c9 100644 --- a/polygon/sync/mock/canonical_chain_builder_mock.go +++ b/polygon/sync/canonical_chain_builder_mock.go @@ -1,8 +1,8 @@ // Code generated by MockGen. DO NOT EDIT. // Source: github.com/ledgerwatch/erigon/polygon/sync (interfaces: CanonicalChainBuilder) -// Package mock is a generated GoMock package. -package mock +// Package sync is a generated GoMock package. +package sync import ( reflect "reflect" diff --git a/polygon/sync/db.go b/polygon/sync/db.go index 560ab2bc1dd..9fc3ed9bcf6 100644 --- a/polygon/sync/db.go +++ b/polygon/sync/db.go @@ -2,7 +2,7 @@ package sync import "github.com/ledgerwatch/erigon/core/types" -//go:generate mockgen -destination=./mock/db_mock.go -package=mock . DB +//go:generate mockgen -destination=./db_mock.go -package=sync . DB type DB interface { WriteHeaders(headers []*types.Header) error } diff --git a/polygon/sync/mock/db_mock.go b/polygon/sync/db_mock.go similarity index 95% rename from polygon/sync/mock/db_mock.go rename to polygon/sync/db_mock.go index 22e6fa6b482..2993c959eff 100644 --- a/polygon/sync/mock/db_mock.go +++ b/polygon/sync/db_mock.go @@ -1,8 +1,8 @@ // Code generated by MockGen. DO NOT EDIT. // Source: github.com/ledgerwatch/erigon/polygon/sync (interfaces: DB) -// Package mock is a generated GoMock package. -package mock +// Package sync is a generated GoMock package. +package sync import ( reflect "reflect" diff --git a/polygon/sync/header_downloader.go b/polygon/sync/header_downloader.go index 76a8f29f33a..2f67e268478 100644 --- a/polygon/sync/header_downloader.go +++ b/polygon/sync/header_downloader.go @@ -13,12 +13,11 @@ import ( "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/core/types" - "github.com/ledgerwatch/erigon/polygon/sync/peerinfo" ) const headerDownloaderLogPrefix = "HeaderDownloader" -func NewHeaderDownloader(logger log.Logger, sentry Sentry, db DB, heimdall Heimdall, verify HeaderVerifier) *HeaderDownloader { +func NewHeaderDownloader(logger log.Logger, sentry Sentry, db DB, heimdall Heimdall, verify StatePointHeadersVerifier) *HeaderDownloader { statePointHeadersMemo, err := lru.New[common.Hash, []*types.Header](sentry.MaxPeers()) if err != nil { panic(err) @@ -39,7 +38,7 @@ type HeaderDownloader struct { sentry Sentry db DB heimdall Heimdall - verify HeaderVerifier + verify StatePointHeadersVerifier statePointHeadersMemo *lru.Cache[common.Hash, []*types.Header] // statePoint.rootHash->[headers part of state point] } @@ -194,9 +193,9 @@ func (hd *HeaderDownloader) downloadUsingStatePoints(ctx context.Context, stateP } // choosePeers assumes peers are sorted in ascending order based on block num -func (hd *HeaderDownloader) choosePeers(peers peerinfo.PeersWithBlockNumInfo, statePoints statePoints) peerinfo.PeersWithBlockNumInfo { +func (hd *HeaderDownloader) choosePeers(peers PeersWithBlockNumInfo, statePoints statePoints) PeersWithBlockNumInfo { var peersIdx int - chosenPeers := make(peerinfo.PeersWithBlockNumInfo, 0, len(peers)) + chosenPeers := make(PeersWithBlockNumInfo, 0, len(peers)) for _, statePoint := range statePoints { if peersIdx >= len(peers) { break diff --git a/polygon/sync/header_downloader_test.go b/polygon/sync/header_downloader_test.go index ae650902ab9..7a24a6ab56f 100644 --- a/polygon/sync/header_downloader_test.go +++ b/polygon/sync/header_downloader_test.go @@ -12,13 +12,10 @@ import ( "github.com/ledgerwatch/log/v3" "github.com/stretchr/testify/require" - "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" - "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" - "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/core/types" - "github.com/ledgerwatch/erigon/polygon/sync/mock" - "github.com/ledgerwatch/erigon/polygon/sync/peerinfo" + "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" + "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" "github.com/ledgerwatch/erigon/turbo/testlog" ) @@ -28,10 +25,10 @@ func newHeaderDownloaderTest(t *testing.T) *headerDownloaderTest { func newHeaderDownloaderTestWithOpts(t *testing.T, opts headerDownloaderTestOpts) *headerDownloaderTest { ctrl := gomock.NewController(t) - heimdall := mock.NewMockHeimdall(ctrl) - sentry := mock.NewMockSentry(ctrl) + heimdall := NewMockHeimdall(ctrl) + sentry := NewMockSentry(ctrl) sentry.EXPECT().MaxPeers().Return(100).Times(1) - db := mock.NewMockDB(ctrl) + db := NewMockDB(ctrl) logger := testlog.Logger(t, log.LvlDebug) headerVerifier := opts.getOrCreateDefaultHeaderVerifier() headerDownloader := NewHeaderDownloader(logger, sentry, db, heimdall, headerVerifier) @@ -44,10 +41,10 @@ func newHeaderDownloaderTestWithOpts(t *testing.T, opts headerDownloaderTestOpts } type headerDownloaderTestOpts struct { - headerVerifier HeaderVerifier + headerVerifier StatePointHeadersVerifier } -func (opts headerDownloaderTestOpts) getOrCreateDefaultHeaderVerifier() HeaderVerifier { +func (opts headerDownloaderTestOpts) getOrCreateDefaultHeaderVerifier() StatePointHeadersVerifier { if opts.headerVerifier == nil { return func(_ *statePoint, _ []*types.Header) error { return nil @@ -58,14 +55,14 @@ func (opts headerDownloaderTestOpts) getOrCreateDefaultHeaderVerifier() HeaderVe } type headerDownloaderTest struct { - heimdall *mock.MockHeimdall - sentry *mock.MockSentry - db *mock.MockDB + heimdall *MockHeimdall + sentry *MockSentry + db *MockDB headerDownloader *HeaderDownloader } -func (hdt headerDownloaderTest) fakePeers(count int, blockNums ...*big.Int) peerinfo.PeersWithBlockNumInfo { - peers := make(peerinfo.PeersWithBlockNumInfo, count) +func (hdt headerDownloaderTest) fakePeers(count int, blockNums ...*big.Int) PeersWithBlockNumInfo { + peers := make(PeersWithBlockNumInfo, count) for i := range peers { var blockNum *big.Int if i < len(blockNums) { @@ -74,7 +71,7 @@ func (hdt headerDownloaderTest) fakePeers(count int, blockNums ...*big.Int) peer blockNum = new(big.Int).SetUint64(math.MaxUint64) } - peers[i] = &peerinfo.PeerWithBlockNumInfo{ + peers[i] = &PeerWithBlockNumInfo{ ID: fmt.Sprintf("peer%d", i+1), BlockNum: blockNum, } diff --git a/polygon/sync/header_verifier.go b/polygon/sync/header_verifier.go deleted file mode 100644 index 6898f384926..00000000000 --- a/polygon/sync/header_verifier.go +++ /dev/null @@ -1,5 +0,0 @@ -package sync - -import "github.com/ledgerwatch/erigon/core/types" - -type HeaderVerifier func(statePoint *statePoint, headers []*types.Header) error diff --git a/polygon/sync/heimdall.go b/polygon/sync/heimdall.go index b3e3f1e95af..b77d58c8e6a 100644 --- a/polygon/sync/heimdall.go +++ b/polygon/sync/heimdall.go @@ -18,7 +18,7 @@ import ( // Heimdall is a wrapper of Heimdall HTTP API // -//go:generate mockgen -destination=./mock/heimdall_mock.go -package=mock . Heimdall +//go:generate mockgen -destination=./heimdall_mock.go -package=sync . Heimdall type Heimdall interface { FetchCheckpoints(ctx context.Context, start uint64) ([]*checkpoint.Checkpoint, error) FetchMilestones(ctx context.Context, start uint64) ([]*milestone.Milestone, error) diff --git a/polygon/sync/mock/heimdall_mock.go b/polygon/sync/heimdall_mock.go similarity index 98% rename from polygon/sync/mock/heimdall_mock.go rename to polygon/sync/heimdall_mock.go index fe887f30bad..8604e623e8d 100644 --- a/polygon/sync/mock/heimdall_mock.go +++ b/polygon/sync/heimdall_mock.go @@ -1,8 +1,8 @@ // Code generated by MockGen. DO NOT EDIT. // Source: github.com/ledgerwatch/erigon/polygon/sync (interfaces: Heimdall) -// Package mock is a generated GoMock package. -package mock +// Package sync is a generated GoMock package. +package sync import ( context "context" diff --git a/polygon/sync/peerinfo/peer_with_block_num_info.go b/polygon/sync/peer_with_block_num_info.go similarity index 96% rename from polygon/sync/peerinfo/peer_with_block_num_info.go rename to polygon/sync/peer_with_block_num_info.go index 643aa078deb..1cde2bbf7e4 100644 --- a/polygon/sync/peerinfo/peer_with_block_num_info.go +++ b/polygon/sync/peer_with_block_num_info.go @@ -1,4 +1,4 @@ -package peerinfo +package sync import "math/big" diff --git a/polygon/sync/sentry.go b/polygon/sync/sentry.go index aa8e5198cc6..ffea66b08d7 100644 --- a/polygon/sync/sentry.go +++ b/polygon/sync/sentry.go @@ -5,13 +5,12 @@ import ( "math/big" "github.com/ledgerwatch/erigon/core/types" - "github.com/ledgerwatch/erigon/polygon/sync/peerinfo" ) -//go:generate mockgen -destination=./mock/sentry_mock.go -package=mock . Sentry +//go:generate mockgen -destination=./sentry_mock.go -package=sync . Sentry type Sentry interface { MaxPeers() int - PeersWithBlockNumInfo() peerinfo.PeersWithBlockNumInfo + PeersWithBlockNumInfo() PeersWithBlockNumInfo DownloadHeaders(ctx context.Context, start *big.Int, end *big.Int, peerID string) ([]*types.Header, error) Penalize(peerID string) } diff --git a/polygon/sync/mock/sentry_mock.go b/polygon/sync/sentry_mock.go similarity index 91% rename from polygon/sync/mock/sentry_mock.go rename to polygon/sync/sentry_mock.go index 09da633586b..7070b629766 100644 --- a/polygon/sync/mock/sentry_mock.go +++ b/polygon/sync/sentry_mock.go @@ -1,8 +1,8 @@ // Code generated by MockGen. DO NOT EDIT. // Source: github.com/ledgerwatch/erigon/polygon/sync (interfaces: Sentry) -// Package mock is a generated GoMock package. -package mock +// Package sync is a generated GoMock package. +package sync import ( context "context" @@ -11,7 +11,6 @@ import ( gomock "github.com/golang/mock/gomock" types "github.com/ledgerwatch/erigon/core/types" - peerinfo "github.com/ledgerwatch/erigon/polygon/sync/peerinfo" ) // MockSentry is a mock of Sentry interface. @@ -67,10 +66,10 @@ func (mr *MockSentryMockRecorder) MaxPeers() *gomock.Call { } // PeersWithBlockNumInfo mocks base method. -func (m *MockSentry) PeersWithBlockNumInfo() peerinfo.PeersWithBlockNumInfo { +func (m *MockSentry) PeersWithBlockNumInfo() PeersWithBlockNumInfo { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "PeersWithBlockNumInfo") - ret0, _ := ret[0].(peerinfo.PeersWithBlockNumInfo) + ret0, _ := ret[0].(PeersWithBlockNumInfo) return ret0 } diff --git a/polygon/sync/state_point_headers_verifier.go b/polygon/sync/state_point_headers_verifier.go new file mode 100644 index 00000000000..5ee550c92a5 --- /dev/null +++ b/polygon/sync/state_point_headers_verifier.go @@ -0,0 +1,22 @@ +package sync + +import ( + "bytes" + "fmt" + + "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/polygon/bor" +) + +type StatePointHeadersVerifier func(statePoint *statePoint, headers []*types.Header) error + +func VerifyStatePointHeaders(statePoint *statePoint, headers []*types.Header) error { + rootHash, err := bor.ComputeHeadersRootHash(headers) + if err != nil { + return fmt.Errorf("VerifyStatePointHeaders: failed to compute headers root hash %w", err) + } + if !bytes.Equal(rootHash, statePoint.rootHash[:]) { + return fmt.Errorf("VerifyStatePointHeaders: bad headers root hash") + } + return nil +} From a7d5b5525093e651c0c661b60f0d6117d45e5279 Mon Sep 17 00:00:00 2001 From: milen <94537774+taratorio@users.noreply.github.com> Date: Mon, 15 Jan 2024 13:26:39 +0000 Subject: [PATCH 65/92] rpcdaemon: fix remote bor engine for trace transaction (#9214) This PR fixes the below error when running a remote rpcdaemon for Polygon debug_traceTransaction. Request: ``` curl http://localhost:9545/ \ -X POST \ -H "Content-Type: application/json" \ --data '{ "jsonrpc": "2.0", "id": 0, "method": "debug_traceTransaction", "params": [ "0xf265c04fc31c91eec9971e118f059322a910776ce40584114c351732ab01aec7", { "tracer": "callTracer", "borTraceEnabled": true, "borTx": true } ] }' ``` Response: ``` {"jsonrpc":"2.0","id":0,"result":null,"error":{"code":-32000,"message":"method handler crashed"}} ``` Logs: ``` EROR[01-11|18:45:14.087] RPC method debug_traceTransaction crashed: interface conversion: *cli.remoteConsensusEngine is not consensus.Engine: missing method APIs ``` --- cmd/rpcdaemon/cli/config.go | 149 +++++++++++++++++++++++++----------- 1 file changed, 105 insertions(+), 44 deletions(-) diff --git a/cmd/rpcdaemon/cli/config.go b/cmd/rpcdaemon/cli/config.go index 5a2f37db806..b9c2e342938 100644 --- a/cmd/rpcdaemon/cli/config.go +++ b/cmd/rpcdaemon/cli/config.go @@ -5,6 +5,7 @@ import ( "crypto/rand" "errors" "fmt" + "math/big" "net" "net/http" "net/url" @@ -13,32 +14,6 @@ import ( "strings" "time" - "github.com/ledgerwatch/erigon/polygon/heimdall/span" - - "github.com/ledgerwatch/erigon-lib/chain" - "github.com/ledgerwatch/erigon-lib/chain/snapcfg" - libcommon "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon-lib/common/datadir" - "github.com/ledgerwatch/erigon-lib/common/dir" - "github.com/ledgerwatch/erigon-lib/common/hexutility" - "github.com/ledgerwatch/erigon-lib/kv/kvcfg" - "github.com/ledgerwatch/erigon-lib/kv/rawdbv3" - libstate "github.com/ledgerwatch/erigon-lib/state" - "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/consensus/ethash" - "github.com/ledgerwatch/erigon/core/state/temporal" - "github.com/ledgerwatch/erigon/core/systemcontracts" - "github.com/ledgerwatch/erigon/core/types" - "github.com/ledgerwatch/erigon/eth/ethconfig" - "github.com/ledgerwatch/erigon/polygon/bor" - "github.com/ledgerwatch/erigon/polygon/bor/borcfg" - "github.com/ledgerwatch/erigon/polygon/bor/contract" - "github.com/ledgerwatch/erigon/rpc/rpccfg" - "github.com/ledgerwatch/erigon/turbo/debug" - "github.com/ledgerwatch/erigon/turbo/logging" - "github.com/ledgerwatch/erigon/turbo/snapshotsync/freezeblocks" - "github.com/ledgerwatch/erigon/turbo/snapshotsync/snap" - "github.com/ledgerwatch/log/v3" "github.com/spf13/cobra" "golang.org/x/sync/semaphore" @@ -46,6 +21,12 @@ import ( grpcHealth "google.golang.org/grpc/health" "google.golang.org/grpc/health/grpc_health_v1" + "github.com/ledgerwatch/erigon-lib/chain" + "github.com/ledgerwatch/erigon-lib/chain/snapcfg" + libcommon "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon-lib/common/datadir" + "github.com/ledgerwatch/erigon-lib/common/dir" + "github.com/ledgerwatch/erigon-lib/common/hexutility" "github.com/ledgerwatch/erigon-lib/direct" "github.com/ledgerwatch/erigon-lib/gointerfaces" "github.com/ledgerwatch/erigon-lib/gointerfaces/grpcutil" @@ -53,10 +34,12 @@ import ( "github.com/ledgerwatch/erigon-lib/gointerfaces/txpool" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/kvcache" + "github.com/ledgerwatch/erigon-lib/kv/kvcfg" kv2 "github.com/ledgerwatch/erigon-lib/kv/mdbx" + "github.com/ledgerwatch/erigon-lib/kv/rawdbv3" "github.com/ledgerwatch/erigon-lib/kv/remotedb" "github.com/ledgerwatch/erigon-lib/kv/remotedbserver" - + libstate "github.com/ledgerwatch/erigon-lib/state" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/cli/httpcfg" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/graphql" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/health" @@ -65,12 +48,28 @@ import ( "github.com/ledgerwatch/erigon/cmd/utils/flags" "github.com/ledgerwatch/erigon/common" "github.com/ledgerwatch/erigon/common/paths" + "github.com/ledgerwatch/erigon/consensus" + "github.com/ledgerwatch/erigon/consensus/ethash" "github.com/ledgerwatch/erigon/core/rawdb" + "github.com/ledgerwatch/erigon/core/state" + "github.com/ledgerwatch/erigon/core/state/temporal" + "github.com/ledgerwatch/erigon/core/systemcontracts" + "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/eth/ethconfig" "github.com/ledgerwatch/erigon/node" "github.com/ledgerwatch/erigon/node/nodecfg" + "github.com/ledgerwatch/erigon/polygon/bor" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/bor/contract" + "github.com/ledgerwatch/erigon/polygon/heimdall/span" "github.com/ledgerwatch/erigon/rpc" + "github.com/ledgerwatch/erigon/rpc/rpccfg" + "github.com/ledgerwatch/erigon/turbo/debug" + "github.com/ledgerwatch/erigon/turbo/logging" "github.com/ledgerwatch/erigon/turbo/rpchelper" "github.com/ledgerwatch/erigon/turbo/services" + "github.com/ledgerwatch/erigon/turbo/snapshotsync/freezeblocks" + "github.com/ledgerwatch/erigon/turbo/snapshotsync/snap" // Force-load native and js packages, to trigger registration _ "github.com/ledgerwatch/erigon/eth/tracers/js" @@ -785,7 +784,7 @@ func isWebsocket(r *http.Request) bool { strings.Contains(strings.ToLower(r.Header.Get("Connection")), "upgrade") } -// obtainJWTSecret loads the jwt-secret, either from the provided config, +// ObtainJWTSecret loads the jwt-secret, either from the provided config, // or from the default location. If neither of those are present, it generates // a new secret and stores to the default location. func ObtainJWTSecret(cfg *httpcfg.HttpCfg, logger log.Logger) ([]byte, error) { @@ -877,8 +876,10 @@ func createEngineListener(cfg *httpcfg.HttpCfg, engineApi []rpc.API, logger log. return engineListener, engineSrv, engineAddr.String(), nil } +var remoteConsensusEngineNotReadyErr = errors.New("remote consensus engine not ready") + type remoteConsensusEngine struct { - engine consensus.EngineReader + engine consensus.Engine } func (e *remoteConsensusEngine) HasEngine() bool { @@ -889,6 +890,18 @@ func (e *remoteConsensusEngine) Engine() consensus.EngineReader { return e.engine } +func (e *remoteConsensusEngine) validateEngineReady() error { + if !e.HasEngine() { + return remoteConsensusEngineNotReadyErr + } + + return nil +} + +// init - reasoning behind init is that we would like to initialise the remote consensus engine either post rpcdaemon +// service startup or in a background goroutine, so that we do not depend on the liveness of other services when +// starting up rpcdaemon and do not block startup (avoiding "cascade outage" scenario). In this case the DB dependency +// can be a remote DB service running on another machine. func (e *remoteConsensusEngine) init(db kv.RoDB, blockReader services.FullBlockReader, remoteKV remote.KVClient, logger log.Logger) bool { var cc *chain.Config @@ -928,41 +941,89 @@ func (e *remoteConsensusEngine) init(db kv.RoDB, blockReader services.FullBlockR } func (e *remoteConsensusEngine) Author(header *types.Header) (libcommon.Address, error) { - if e.engine != nil { - return e.engine.Author(header) + if err := e.validateEngineReady(); err != nil { + return libcommon.Address{}, err } - return libcommon.Address{}, fmt.Errorf("remote consensus engine not iinitialized") + return e.engine.Author(header) } func (e *remoteConsensusEngine) IsServiceTransaction(sender libcommon.Address, syscall consensus.SystemCall) bool { - if e.engine != nil { - return e.engine.IsServiceTransaction(sender, syscall) + if err := e.validateEngineReady(); err != nil { + panic(err) } - return false + return e.engine.IsServiceTransaction(sender, syscall) } func (e *remoteConsensusEngine) Type() chain.ConsensusName { - if e.engine != nil { - return e.engine.Type() + if err := e.validateEngineReady(); err != nil { + panic(err) } - return "" + return e.engine.Type() } func (e *remoteConsensusEngine) CalculateRewards(config *chain.Config, header *types.Header, uncles []*types.Header, syscall consensus.SystemCall) ([]consensus.Reward, error) { - if e.engine != nil { - return e.engine.CalculateRewards(config, header, uncles, syscall) + if err := e.validateEngineReady(); err != nil { + return nil, err } - return nil, fmt.Errorf("remote consensus engine not iinitialized") + return e.engine.CalculateRewards(config, header, uncles, syscall) } func (e *remoteConsensusEngine) Close() error { - if e.engine != nil { - return e.engine.Close() + if err := e.validateEngineReady(); err != nil { + return err } - return nil + return e.engine.Close() +} + +func (e *remoteConsensusEngine) Initialize(config *chain.Config, chain consensus.ChainHeaderReader, header *types.Header, state *state.IntraBlockState, syscall consensus.SysCallCustom, logger log.Logger) { + if err := e.validateEngineReady(); err != nil { + panic(err) + } + + e.engine.Initialize(config, chain, header, state, syscall, logger) +} + +func (e *remoteConsensusEngine) VerifyHeader(_ consensus.ChainHeaderReader, _ *types.Header, _ bool) error { + panic("remoteConsensusEngine.VerifyHeader not supported") +} + +func (e *remoteConsensusEngine) VerifyUncles(_ consensus.ChainReader, _ *types.Header, _ []*types.Header) error { + panic("remoteConsensusEngine.VerifyUncles not supported") +} + +func (e *remoteConsensusEngine) Prepare(_ consensus.ChainHeaderReader, _ *types.Header, _ *state.IntraBlockState) error { + panic("remoteConsensusEngine.Prepare not supported") +} + +func (e *remoteConsensusEngine) Finalize(_ *chain.Config, _ *types.Header, _ *state.IntraBlockState, _ types.Transactions, _ []*types.Header, _ types.Receipts, _ []*types.Withdrawal, _ consensus.ChainReader, _ consensus.SystemCall, _ log.Logger) (types.Transactions, types.Receipts, error) { + panic("remoteConsensusEngine.Finalize not supported") +} + +func (e *remoteConsensusEngine) FinalizeAndAssemble(_ *chain.Config, _ *types.Header, _ *state.IntraBlockState, _ types.Transactions, _ []*types.Header, _ types.Receipts, _ []*types.Withdrawal, _ consensus.ChainReader, _ consensus.SystemCall, _ consensus.Call, _ log.Logger) (*types.Block, types.Transactions, types.Receipts, error) { + panic("remoteConsensusEngine.FinalizeAndAssemble not supported") +} + +func (e *remoteConsensusEngine) Seal(_ consensus.ChainHeaderReader, _ *types.Block, _ chan<- *types.Block, _ <-chan struct{}) error { + panic("remoteConsensusEngine.Seal not supported") +} + +func (e *remoteConsensusEngine) SealHash(_ *types.Header) libcommon.Hash { + panic("remoteConsensusEngine.SealHash not supported") +} + +func (e *remoteConsensusEngine) CalcDifficulty(_ consensus.ChainHeaderReader, _ uint64, _ uint64, _ *big.Int, _ uint64, _ libcommon.Hash, _ libcommon.Hash, _ uint64) *big.Int { + panic("remoteConsensusEngine.CalcDifficulty not supported") +} + +func (e *remoteConsensusEngine) GenerateSeal(_ consensus.ChainHeaderReader, _ *types.Header, _ *types.Header, _ consensus.Call) []byte { + panic("remoteConsensusEngine.GenerateSeal not supported") +} + +func (e *remoteConsensusEngine) APIs(_ consensus.ChainHeaderReader) []rpc.API { + panic("remoteConsensusEngine.APIs not supported") } From f03d2665ff9f62b1071bbda80063b0511f322105 Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Mon, 15 Jan 2024 15:01:33 +0100 Subject: [PATCH 66/92] Added merkle proof and fixed bad handling of new validators (#9233) --- cl/cltypes/beacon_block.go | 4 ++ cl/merkle_tree/merkle_root.go | 42 +++++++++++++++ cl/phase1/core/state/raw/hashing.go | 39 ++++++++++++++ cl/phase1/forkchoice/checkpoint_state.go | 4 +- cl/phase1/forkchoice/forkchoice.go | 15 ++++++ cl/phase1/forkchoice/forkchoice_mock.go | 8 +++ cl/phase1/forkchoice/interface.go | 2 + cl/phase1/forkchoice/on_attestation.go | 6 +++ cl/phase1/stages/clstages.go | 1 + cl/spectest/consensus_tests/appendix.go | 3 +- cl/spectest/consensus_tests/fork_choice.go | 1 + cl/spectest/consensus_tests/light_client.go | 59 +++++++++++++++++++++ spectest/consts.go | 7 +-- spectest/util.go | 24 ++++++++- 14 files changed, 207 insertions(+), 8 deletions(-) create mode 100644 cl/spectest/consensus_tests/light_client.go diff --git a/cl/cltypes/beacon_block.go b/cl/cltypes/beacon_block.go index c2592f4527a..d9763803706 100644 --- a/cl/cltypes/beacon_block.go +++ b/cl/cltypes/beacon_block.go @@ -293,3 +293,7 @@ func (*BeaconBody) Static() bool { func (*BeaconBlock) Static() bool { return false } + +func (b *BeaconBody) ExecutionPayloadMerkleProof() ([][32]byte, error) { + return merkle_tree.MerkleProof(4, 9, b.getSchema(false)...) +} diff --git a/cl/merkle_tree/merkle_root.go b/cl/merkle_tree/merkle_root.go index ba231d4853f..a4b9791f966 100644 --- a/cl/merkle_tree/merkle_root.go +++ b/cl/merkle_tree/merkle_root.go @@ -10,6 +10,7 @@ import ( "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/length" "github.com/ledgerwatch/erigon-lib/types/ssz" + "github.com/ledgerwatch/erigon/cl/utils" "github.com/prysmaticlabs/gohashtree" ) @@ -116,3 +117,44 @@ func MerkleRootFromFlatLeaves(leaves []byte, out []byte) (err error) { func MerkleRootFromFlatLeavesWithLimit(leaves []byte, out []byte, limit uint64) (err error) { return globalHasher.merkleizeTrieLeavesFlat(leaves, out, limit) } + +// Merkle Proof computes the merkle proof for a given schema of objects. +func MerkleProof(depth, proofIndex int, schema ...interface{}) ([][32]byte, error) { + // Calculate the total number of leaves needed based on the schema length + maxDepth := GetDepth(uint64(len(schema))) + if utils.PowerOf2(uint64(maxDepth)) != uint64(len(schema)) { + maxDepth++ + } + + if depth != int(maxDepth) { // TODO: Add support for lower depths + return nil, fmt.Errorf("depth is different than maximum depth, have %d, want %d", depth, maxDepth) + } + var err error + proof := make([][32]byte, maxDepth) + currentSizeDepth := utils.PowerOf2(uint64(maxDepth)) + for len(schema) != int(currentSizeDepth) { // Augment the schema to be a power of 2 + schema = append(schema, make([]byte, 32)) + } + + for i := 0; i < depth; i++ { + // Hash the left branch + if proofIndex >= int(currentSizeDepth)/2 { + proof[depth-i-1], err = HashTreeRoot(schema[0 : currentSizeDepth/2]...) + if err != nil { + return nil, err + } + schema = schema[currentSizeDepth/2:] // explore the right branch + proofIndex -= int(currentSizeDepth) / 2 + currentSizeDepth /= 2 + continue + } + // Hash the right branch + proof[depth-i-1], err = HashTreeRoot(schema[currentSizeDepth/2:]...) + if err != nil { + return nil, err + } + schema = schema[0 : currentSizeDepth/2] // explore the left branch + currentSizeDepth /= 2 + } + return proof, nil +} diff --git a/cl/phase1/core/state/raw/hashing.go b/cl/phase1/core/state/raw/hashing.go index 72c840fbf35..7be41d67830 100644 --- a/cl/phase1/core/state/raw/hashing.go +++ b/cl/phase1/core/state/raw/hashing.go @@ -23,6 +23,45 @@ func (b *BeaconState) HashSSZ() (out [32]byte, err error) { return } +func (b *BeaconState) CurrentSyncCommitteeBranch() ([][32]byte, error) { + if err := b.computeDirtyLeaves(); err != nil { + return nil, err + } + schema := []interface{}{} + for i := 0; i < len(b.leaves); i += 32 { + schema = append(schema, b.leaves[i:i+32]) + } + return merkle_tree.MerkleProof(5, 22, schema...) +} + +func (b *BeaconState) NextSyncCommitteeBranch() ([][32]byte, error) { + if err := b.computeDirtyLeaves(); err != nil { + return nil, err + } + schema := []interface{}{} + for i := 0; i < len(b.leaves); i += 32 { + schema = append(schema, b.leaves[i:i+32]) + } + return merkle_tree.MerkleProof(5, 23, schema...) +} + +func (b *BeaconState) FinalityRootBranch() ([][32]byte, error) { + if err := b.computeDirtyLeaves(); err != nil { + return nil, err + } + schema := []interface{}{} + for i := 0; i < len(b.leaves); i += 32 { + schema = append(schema, b.leaves[i:i+32]) + } + proof, err := merkle_tree.MerkleProof(5, 20, schema...) + if err != nil { + return nil, err + } + + proof = append([][32]byte{merkle_tree.Uint64Root(b.finalizedCheckpoint.Epoch())}, proof...) + return proof, nil +} + func preparateRootsForHashing(roots []common.Hash) [][32]byte { ret := make([][32]byte, len(roots)) for i := range roots { diff --git a/cl/phase1/forkchoice/checkpoint_state.go b/cl/phase1/forkchoice/checkpoint_state.go index ba992c6d15f..612068945dc 100644 --- a/cl/phase1/forkchoice/checkpoint_state.go +++ b/cl/phase1/forkchoice/checkpoint_state.go @@ -69,7 +69,7 @@ func newCheckpointState(beaconConfig *clparams.BeaconChainConfig, anchorPublicKe // Add the post-anchor public keys as surplus for i := len(anchorPublicKeys) / length.Bytes48; i < len(validatorSet); i++ { pos := i - len(anchorPublicKeys)/length.Bytes48 - copy(publicKeys[pos*length.Bytes48:], validatorSet[i].PublicKeyBytes()) + copy(publicKeys[pos*length.Bytes48:(pos+1)*length.Bytes48], validatorSet[i].PublicKeyBytes()) } mixes := solid.NewHashVector(randaoMixesLength) @@ -170,7 +170,7 @@ func (c *checkpointState) isValidIndexedAttestation(att *cltypes.IndexedAttestat pks = append(pks, c.anchorPublicKeys[v*length.Bytes48:(v+1)*length.Bytes48]) } else { offset := uint64(len(c.anchorPublicKeys) / length.Bytes48) - pks = append(pks, c.publicKeys[(v-offset)*length.Bytes48:]) + pks = append(pks, c.publicKeys[(v-offset)*length.Bytes48:(v-offset+1)*length.Bytes48]) } return true }) diff --git a/cl/phase1/forkchoice/forkchoice.go b/cl/phase1/forkchoice/forkchoice.go index bde4d322f37..1e87939540b 100644 --- a/cl/phase1/forkchoice/forkchoice.go +++ b/cl/phase1/forkchoice/forkchoice.go @@ -4,6 +4,7 @@ import ( "context" "sort" "sync" + "sync/atomic" "github.com/ledgerwatch/erigon/cl/clparams" "github.com/ledgerwatch/erigon/cl/cltypes/solid" @@ -115,6 +116,8 @@ type ForkChoiceStore struct { // operations pool operationsPool pool.OperationsPool beaconCfg *clparams.BeaconChainConfig + + synced atomic.Bool } type LatestMessage struct { @@ -469,3 +472,15 @@ func (f *ForkChoiceStore) ForkNodes() []ForkNode { }) return forkNodes } + +func (f *ForkChoiceStore) Synced() bool { + f.mu.Lock() + defer f.mu.Unlock() + return f.synced.Load() +} + +func (f *ForkChoiceStore) SetSynced(s bool) { + f.mu.Lock() + defer f.mu.Unlock() + f.synced.Store(s) +} diff --git a/cl/phase1/forkchoice/forkchoice_mock.go b/cl/phase1/forkchoice/forkchoice_mock.go index 3683e5cc3e2..665b0f12621 100644 --- a/cl/phase1/forkchoice/forkchoice_mock.go +++ b/cl/phase1/forkchoice/forkchoice_mock.go @@ -225,3 +225,11 @@ func (f *ForkChoiceStorageMock) OnAggregateAndProof(aggregateAndProof *cltypes.S f.Pool.AttestationsPool.Insert(aggregateAndProof.Message.Aggregate.Signature(), aggregateAndProof.Message.Aggregate) return nil } + +func (f *ForkChoiceStorageMock) Synced() bool { + return true +} + +func (f *ForkChoiceStorageMock) SetSynced(synced bool) { + panic("implement me") +} diff --git a/cl/phase1/forkchoice/interface.go b/cl/phase1/forkchoice/interface.go index 0b62ff8f3e1..955bd188d4a 100644 --- a/cl/phase1/forkchoice/interface.go +++ b/cl/phase1/forkchoice/interface.go @@ -41,6 +41,7 @@ type ForkChoiceStorageReader interface { GetStateAtSlot(slot uint64, alwaysCopy bool) (*state.CachingBeaconState, error) GetStateAtStateRoot(root libcommon.Hash, alwaysCopy bool) (*state.CachingBeaconState, error) ForkNodes() []ForkNode + Synced() bool } type ForkChoiceStorageWriter interface { @@ -52,4 +53,5 @@ type ForkChoiceStorageWriter interface { OnBlsToExecutionChange(signedChange *cltypes.SignedBLSToExecutionChange, test bool) error OnBlock(block *cltypes.SignedBeaconBlock, newPayload bool, fullValidation bool) error OnTick(time uint64) + SetSynced(synced bool) } diff --git a/cl/phase1/forkchoice/on_attestation.go b/cl/phase1/forkchoice/on_attestation.go index 5dd9326b0fc..3e80efac4e8 100644 --- a/cl/phase1/forkchoice/on_attestation.go +++ b/cl/phase1/forkchoice/on_attestation.go @@ -15,6 +15,9 @@ import ( // OnAttestation processes incoming attestations. func (f *ForkChoiceStore) OnAttestation(attestation *solid.Attestation, fromBlock bool, insert bool) error { + if !f.synced.Load() { + return nil + } f.mu.Lock() defer f.mu.Unlock() f.headHash = libcommon.Hash{} @@ -70,6 +73,9 @@ func (f *ForkChoiceStore) OnAttestation(attestation *solid.Attestation, fromBloc } func (f *ForkChoiceStore) OnAggregateAndProof(aggregateAndProof *cltypes.SignedAggregateAndProof, test bool) error { + if !f.synced.Load() { + return nil + } slot := aggregateAndProof.Message.Aggregate.AttestantionData().Slot() selectionProof := aggregateAndProof.Message.SelectionProof committeeIndex := aggregateAndProof.Message.Aggregate.AttestantionData().ValidatorIndex() diff --git a/cl/phase1/stages/clstages.go b/cl/phase1/stages/clstages.go index 8c5710bfe50..5f5e18c80e2 100644 --- a/cl/phase1/stages/clstages.go +++ b/cl/phase1/stages/clstages.go @@ -507,6 +507,7 @@ func ConsensusClStages(ctx context.Context, if err != nil { return err } + cfg.forkChoice.SetSynced(true) if err := cfg.syncedData.OnHeadState(headState); err != nil { return err } diff --git a/cl/spectest/consensus_tests/appendix.go b/cl/spectest/consensus_tests/appendix.go index 5a7342cb60e..b547533edb2 100644 --- a/cl/spectest/consensus_tests/appendix.go +++ b/cl/spectest/consensus_tests/appendix.go @@ -11,6 +11,7 @@ import ( var TestFormats = spectest.Appendix{} func init() { + TestFormats.Add("bls"). With("aggregate_verify", &BlsAggregateVerify{}). With("aggregate", spectest.UnimplementedHandler). @@ -47,7 +48,7 @@ func init() { TestFormats.Add("kzg"). With("", spectest.UnimplementedHandler) TestFormats.Add("light_client"). - With("", spectest.UnimplementedHandler) + WithFn("single_merkle_proof", LightClientBeaconBlockBodyExecutionMerkleProof) TestFormats.Add("operations"). WithFn("attestation", operationAttestationHandler). WithFn("attester_slashing", operationAttesterSlashingHandler). diff --git a/cl/spectest/consensus_tests/fork_choice.go b/cl/spectest/consensus_tests/fork_choice.go index ac33534e067..4eff9f50c11 100644 --- a/cl/spectest/consensus_tests/fork_choice.go +++ b/cl/spectest/consensus_tests/fork_choice.go @@ -158,6 +158,7 @@ func (b *ForkChoice) Run(t *testing.T, root fs.FS, c spectest.TestCase) (err err forkStore, err := forkchoice.NewForkChoiceStore(context.Background(), anchorState, nil, nil, pool.NewOperationsPool(&clparams.MainnetBeaconConfig), fork_graph.NewForkGraphDisk(anchorState, afero.NewMemMapFs())) require.NoError(t, err) + forkStore.SetSynced(true) var steps []ForkChoiceStep err = spectest.ReadYml(root, "steps.yaml", &steps) diff --git a/cl/spectest/consensus_tests/light_client.go b/cl/spectest/consensus_tests/light_client.go new file mode 100644 index 00000000000..370d7fe7948 --- /dev/null +++ b/cl/spectest/consensus_tests/light_client.go @@ -0,0 +1,59 @@ +package consensus_tests + +import ( + "io/fs" + "testing" + + libcommon "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon/cl/clparams" + "github.com/ledgerwatch/erigon/cl/cltypes" + "github.com/ledgerwatch/erigon/cl/phase1/core/state" + "github.com/ledgerwatch/erigon/spectest" + "github.com/stretchr/testify/require" +) + +type LcBranch struct { + Branch []string `yaml:"branch"` +} + +var LightClientBeaconBlockBodyExecutionMerkleProof = spectest.HandlerFunc(func(t *testing.T, root fs.FS, c spectest.TestCase) (err error) { + var proof [][32]byte + switch c.CaseName { + case "execution_merkle_proof": + beaconBody := cltypes.NewBeaconBody(&clparams.MainnetBeaconConfig) + require.NoError(t, spectest.ReadSsz(root, c.Version(), spectest.ObjectSSZ, beaconBody)) + proof, err = beaconBody.ExecutionPayloadMerkleProof() + require.NoError(t, err) + case "current_sync_committee_merkle_proof": + state := state.New(&clparams.MainnetBeaconConfig) + require.NoError(t, spectest.ReadSsz(root, c.Version(), spectest.ObjectSSZ, state)) + proof, err = state.CurrentSyncCommitteeBranch() + require.NoError(t, err) + case "next_sync_committee_merkle_proof": + state := state.New(&clparams.MainnetBeaconConfig) + require.NoError(t, spectest.ReadSsz(root, c.Version(), spectest.ObjectSSZ, state)) + proof, err = state.NextSyncCommitteeBranch() + require.NoError(t, err) + case "finality_root_merkle_proof": + state := state.New(&clparams.MainnetBeaconConfig) + require.NoError(t, spectest.ReadSsz(root, c.Version(), spectest.ObjectSSZ, state)) + + proof, err = state.FinalityRootBranch() + require.NoError(t, err) + default: + t.Skip("skipping: ", c.CaseName) + } + + // read proof.yaml + proofYaml := LcBranch{} + err = spectest.ReadYml(root, "proof.yaml", &proofYaml) + require.NoError(t, err) + + branch := make([][32]byte, len(proofYaml.Branch)) + for i, b := range proofYaml.Branch { + branch[i] = libcommon.HexToHash(b) + } + + require.Equal(t, branch, proof) + return nil +}) diff --git a/spectest/consts.go b/spectest/consts.go index 0de7e99f04c..36be88ac62f 100644 --- a/spectest/consts.go +++ b/spectest/consts.go @@ -1,7 +1,8 @@ package spectest const ( - PreSsz = "pre.ssz_snappy" - PostSsz = "post.ssz_snappy" - MetaYaml = "meta.yaml" + PreSsz = "pre.ssz_snappy" + PostSsz = "post.ssz_snappy" + MetaYaml = "meta.yaml" + ObjectSSZ = "object.ssz_snappy" ) diff --git a/spectest/util.go b/spectest/util.go index b34ae6ced81..220a9a2ee09 100644 --- a/spectest/util.go +++ b/spectest/util.go @@ -2,12 +2,13 @@ package spectest import ( "fmt" + "io/fs" + "os" + clparams2 "github.com/ledgerwatch/erigon/cl/clparams" "github.com/ledgerwatch/erigon/cl/cltypes" "github.com/ledgerwatch/erigon/cl/phase1/core/state" "github.com/ledgerwatch/erigon/cl/utils" - "io/fs" - "os" "gopkg.in/yaml.v3" @@ -80,6 +81,25 @@ func ReadBlock(root fs.FS, version clparams2.StateVersion, index int) (*cltypes. return blk, nil } + +func ReadBlockByPath(root fs.FS, version clparams2.StateVersion, path string) (*cltypes.SignedBeaconBlock, error) { + var blockBytes []byte + var err error + blockBytes, err = fs.ReadFile(root, path) + if os.IsNotExist(err) { + return nil, nil + } + if err != nil { + return nil, err + } + blk := cltypes.NewSignedBeaconBlock(&clparams2.MainnetBeaconConfig) + if err = utils.DecodeSSZSnappy(blk, blockBytes, int(version)); err != nil { + return nil, err + } + + return blk, nil +} + func ReadAnchorBlock(root fs.FS, version clparams2.StateVersion, name string) (*cltypes.BeaconBlock, error) { var blockBytes []byte var err error From cda48aeaf71d74a578ef8872ac0da2190b887be6 Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Mon, 15 Jan 2024 16:49:46 +0100 Subject: [PATCH 67/92] polygon/heimdall: drop GRPC support (#9230) --- cmd/devnet/args/node_args.go | 2 +- cmd/devnet/main.go | 25 +- cmd/devnet/networks/devnet_bor.go | 16 +- cmd/devnet/services/polygon/heimdall.go | 165 +++++++++++- cmd/devnet/services/polygon/heimdall_test.go | 64 +++++ cmd/devnet/services/polygon/statesync.go | 11 +- cmd/devnet/tests/context.go | 4 +- cmd/integration/commands/flags.go | 1 - cmd/integration/commands/stages.go | 7 +- cmd/utils/flags.go | 22 +- eth/backend.go | 7 +- eth/ethconfig/config.go | 3 - go.mod | 1 - go.sum | 2 - polygon/heimdall/heimdall.go | 13 - polygon/heimdall/heimdallgrpc/checkpoint.go | 50 ---- polygon/heimdall/heimdallgrpc/client.go | 53 ---- polygon/heimdall/heimdallgrpc/milestone.go | 103 -------- polygon/heimdall/heimdallgrpc/server.go | 251 ------------------- polygon/heimdall/heimdallgrpc/span.go | 63 ----- polygon/heimdall/heimdallgrpc/state_sync.go | 58 ----- turbo/cli/default_flags.go | 1 - 22 files changed, 259 insertions(+), 663 deletions(-) create mode 100644 cmd/devnet/services/polygon/heimdall_test.go delete mode 100644 polygon/heimdall/heimdallgrpc/checkpoint.go delete mode 100644 polygon/heimdall/heimdallgrpc/client.go delete mode 100644 polygon/heimdall/heimdallgrpc/milestone.go delete mode 100644 polygon/heimdall/heimdallgrpc/server.go delete mode 100644 polygon/heimdall/heimdallgrpc/span.go delete mode 100644 polygon/heimdall/heimdallgrpc/state_sync.go diff --git a/cmd/devnet/args/node_args.go b/cmd/devnet/args/node_args.go index 1fba7caaf90..1bbf714562c 100644 --- a/cmd/devnet/args/node_args.go +++ b/cmd/devnet/args/node_args.go @@ -49,7 +49,7 @@ type NodeArgs struct { MetricsAddr string `arg:"--metrics.addr" json:"metrics.addr,omitempty"` StaticPeers string `arg:"--staticpeers" json:"staticpeers,omitempty"` WithoutHeimdall bool `arg:"--bor.withoutheimdall" flag:"" default:"false" json:"bor.withoutheimdall,omitempty"` - HeimdallGrpcAddr string `arg:"--bor.heimdallgRPC" json:"bor.heimdallgRPC,omitempty"` + HeimdallURL string `arg:"--bor.heimdall" json:"bor.heimdall,omitempty"` WithHeimdallMilestones bool `arg:"--bor.milestone" json:"bor.milestone"` VMDebug bool `arg:"--vmdebug" flag:"" default:"false" json:"dmdebug"` diff --git a/cmd/devnet/main.go b/cmd/devnet/main.go index 92a41aca153..b8f5ff4ae3a 100644 --- a/cmd/devnet/main.go +++ b/cmd/devnet/main.go @@ -11,9 +11,8 @@ import ( "syscall" "time" - "github.com/ledgerwatch/erigon/cmd/devnet/networks" - "github.com/ledgerwatch/erigon/cmd/devnet/services" - "github.com/ledgerwatch/erigon/cmd/devnet/services/polygon" + "github.com/ledgerwatch/log/v3" + "github.com/urfave/cli/v2" "github.com/ledgerwatch/erigon-lib/chain/networkname" "github.com/ledgerwatch/erigon-lib/common/metrics" @@ -23,16 +22,16 @@ import ( _ "github.com/ledgerwatch/erigon/cmd/devnet/contracts/steps" "github.com/ledgerwatch/erigon/cmd/devnet/devnet" "github.com/ledgerwatch/erigon/cmd/devnet/devnetutils" + "github.com/ledgerwatch/erigon/cmd/devnet/networks" "github.com/ledgerwatch/erigon/cmd/devnet/requests" "github.com/ledgerwatch/erigon/cmd/devnet/scenarios" - "github.com/ledgerwatch/log/v3" - + "github.com/ledgerwatch/erigon/cmd/devnet/services" + "github.com/ledgerwatch/erigon/cmd/devnet/services/polygon" "github.com/ledgerwatch/erigon/cmd/utils/flags" "github.com/ledgerwatch/erigon/params" erigon_app "github.com/ledgerwatch/erigon/turbo/app" "github.com/ledgerwatch/erigon/turbo/debug" "github.com/ledgerwatch/erigon/turbo/logging" - "github.com/urfave/cli/v2" ) var ( @@ -77,10 +76,10 @@ var ( Usage: "Run with a devnet local Heimdall service", } - HeimdallGrpcAddressFlag = cli.StringFlag{ - Name: "bor.heimdallgRPC", - Usage: "Address of Heimdall gRPC service", - Value: polygon.HeimdallGrpcAddressDefault, + HeimdallURLFlag = cli.StringFlag{ + Name: "bor.heimdall", + Usage: "URL of Heimdall service", + Value: polygon.HeimdallURLDefault, } BorSprintSizeFlag = cli.IntFlag{ @@ -166,7 +165,7 @@ func main() { &BaseRpcPortFlag, &WithoutHeimdallFlag, &LocalHeimdallFlag, - &HeimdallGrpcAddressFlag, + &HeimdallURLFlag, &BorSprintSizeFlag, &MetricsEnabledFlag, &MetricsNodeFlag, @@ -409,9 +408,9 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { if ctx.Bool(WithoutHeimdallFlag.Name) { return networks.NewBorDevnetWithoutHeimdall(dataDir, baseRpcHost, baseRpcPort, gasLimit, logger, consoleLogLevel, dirLogLevel), nil } else if ctx.Bool(LocalHeimdallFlag.Name) { - heimdallGrpcAddr := ctx.String(HeimdallGrpcAddressFlag.Name) + heimdallURL := ctx.String(HeimdallURLFlag.Name) sprintSize := uint64(ctx.Int(BorSprintSizeFlag.Name)) - return networks.NewBorDevnetWithLocalHeimdall(dataDir, baseRpcHost, baseRpcPort, heimdallGrpcAddr, sprintSize, producerCount, gasLimit, logger, consoleLogLevel, dirLogLevel), nil + return networks.NewBorDevnetWithLocalHeimdall(dataDir, baseRpcHost, baseRpcPort, heimdallURL, sprintSize, producerCount, gasLimit, logger, consoleLogLevel, dirLogLevel), nil } else { return networks.NewBorDevnetWithRemoteHeimdall(dataDir, baseRpcHost, baseRpcPort, producerCount, gasLimit, logger, consoleLogLevel, dirLogLevel), nil } diff --git a/cmd/devnet/networks/devnet_bor.go b/cmd/devnet/networks/devnet_bor.go index 41d4993ea18..ce81a45a060 100644 --- a/cmd/devnet/networks/devnet_bor.go +++ b/cmd/devnet/networks/devnet_bor.go @@ -74,7 +74,7 @@ func NewBorDevnetWithHeimdall( baseRpcHost string, baseRpcPort int, heimdall *polygon.Heimdall, - heimdallGrpcAddr string, + heimdallURL string, checkpointOwner *accounts.Account, producerCount int, gasLimit uint64, @@ -101,7 +101,7 @@ func NewBorDevnetWithHeimdall( NodeArgs: args.NodeArgs{ ConsoleVerbosity: strconv.Itoa(int(consoleLogLevel)), DirVerbosity: strconv.Itoa(int(dirLogLevel)), - HeimdallGrpcAddr: heimdallGrpcAddr, + HeimdallURL: heimdallURL, }, AccountSlots: 20000, }) @@ -129,7 +129,7 @@ func NewBorDevnetWithHeimdall( NodeArgs: args.NodeArgs{ ConsoleVerbosity: strconv.Itoa(int(consoleLogLevel)), DirVerbosity: strconv.Itoa(int(dirLogLevel)), - HeimdallGrpcAddr: heimdallGrpcAddr, + HeimdallURL: heimdallURL, }, }), } @@ -185,7 +185,7 @@ func NewBorDevnetWithRemoteHeimdall( consoleLogLevel log.Lvl, dirLogLevel log.Lvl, ) devnet.Devnet { - heimdallGrpcAddr := "" + heimdallURL := "" checkpointOwner := accounts.NewAccount("checkpoint-owner") withMilestones := utils.WithHeimdallMilestones.Value return NewBorDevnetWithHeimdall( @@ -193,7 +193,7 @@ func NewBorDevnetWithRemoteHeimdall( baseRpcHost, baseRpcPort, nil, - heimdallGrpcAddr, + heimdallURL, checkpointOwner, producerCount, gasLimit, @@ -207,7 +207,7 @@ func NewBorDevnetWithLocalHeimdall( dataDir string, baseRpcHost string, baseRpcPort int, - heimdallGrpcAddr string, + heimdallURL string, sprintSize uint64, producerCount int, gasLimit uint64, @@ -225,7 +225,7 @@ func NewBorDevnetWithLocalHeimdall( heimdall := polygon.NewHeimdall( &config, - heimdallGrpcAddr, + heimdallURL, &polygon.CheckpointConfig{ CheckpointBufferTime: 60 * time.Second, CheckpointAccount: checkpointOwner, @@ -237,7 +237,7 @@ func NewBorDevnetWithLocalHeimdall( baseRpcHost, baseRpcPort, heimdall, - heimdallGrpcAddr, + heimdallURL, checkpointOwner, producerCount, gasLimit, diff --git a/cmd/devnet/services/polygon/heimdall.go b/cmd/devnet/services/polygon/heimdall.go index 81426a68e52..1288f67c683 100644 --- a/cmd/devnet/services/polygon/heimdall.go +++ b/cmd/devnet/services/polygon/heimdall.go @@ -2,16 +2,22 @@ package polygon import ( "context" + "encoding/json" + "errors" "fmt" "math/big" + "net" + "net/http" + "strconv" "strings" "sync" "time" + "github.com/go-chi/chi/v5" "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon/polygon/heimdall" "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" - "github.com/ledgerwatch/erigon/polygon/heimdall/heimdallgrpc" "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" "github.com/ledgerwatch/erigon/polygon/heimdall/span" @@ -55,7 +61,7 @@ const ( DefaultCheckpointBufferTime time.Duration = 1000 * time.Second ) -const HeimdallGrpcAddressDefault = "localhost:8540" +const HeimdallURLDefault = "http://localhost:1317" type CheckpointConfig struct { RootChainTxConfirmations uint64 @@ -71,7 +77,7 @@ type Heimdall struct { sync.Mutex chainConfig *chain.Config borConfig *borcfg.BorConfig - grpcAddr string + listenAddr string validatorSet *valset.ValidatorSet pendingCheckpoint *checkpoint.Checkpoint latestCheckpoint *CheckpointAck @@ -94,14 +100,14 @@ type Heimdall struct { func NewHeimdall( chainConfig *chain.Config, - grpcAddr string, + serverURL string, checkpointConfig *CheckpointConfig, logger log.Logger, ) *Heimdall { heimdall := &Heimdall{ chainConfig: chainConfig, borConfig: chainConfig.Bor.(*borcfg.BorConfig), - grpcAddr: grpcAddr, + listenAddr: serverURL[7:], checkpointConfig: *checkpointConfig, spans: map[uint64]*span.HeimdallSpan{}, pendingSyncRecords: map[syncRecordKey]*EventRecordWithBlock{}, @@ -382,7 +388,154 @@ func (h *Heimdall) Start(ctx context.Context) error { // if this is a restart h.unsubscribe() - return heimdallgrpc.StartHeimdallServer(ctx, h, h.grpcAddr, h.logger) + server := &http.Server{Addr: h.listenAddr, Handler: makeHeimdallRouter(ctx, h)} + return startHTTPServer(ctx, server, "devnet Heimdall service", h.logger) +} + +func makeHeimdallRouter(ctx context.Context, client heimdall.IHeimdallClient) *chi.Mux { + router := chi.NewRouter() + + writeResponse := func(w http.ResponseWriter, result any, err error) { + if err != nil { + http.Error(w, http.StatusText(500), 500) + return + } + + var resultEnvelope struct { + Height string `json:"height"` + Result any `json:"result"` + } + resultEnvelope.Height = "0" + resultEnvelope.Result = result + + response, err := json.Marshal(resultEnvelope) + if err != nil { + http.Error(w, http.StatusText(500), 500) + return + } + + _, _ = w.Write(response) + } + + wrapResult := func(result any) map[string]any { + return map[string]any{ + "result": result, + } + } + + router.Get("/clerk/event-record/list", func(w http.ResponseWriter, r *http.Request) { + fromIdStr := r.URL.Query().Get("from-id") + fromId, err := strconv.ParseUint(fromIdStr, 10, 64) + if err != nil { + http.Error(w, http.StatusText(400), 400) + return + } + + toTimeStr := r.URL.Query().Get("to-time") + toTime, err := strconv.ParseInt(toTimeStr, 10, 64) + if err != nil { + http.Error(w, http.StatusText(400), 400) + return + } + + result, err := client.StateSyncEvents(ctx, fromId, toTime) + writeResponse(w, result, err) + }) + + router.Get("/bor/span/{id}", func(w http.ResponseWriter, r *http.Request) { + idStr := chi.URLParam(r, "id") + id, err := strconv.ParseUint(idStr, 10, 64) + if err != nil { + http.Error(w, http.StatusText(400), 400) + return + } + result, err := client.Span(ctx, id) + writeResponse(w, result, err) + }) + + router.Get("/checkpoints/{number}", func(w http.ResponseWriter, r *http.Request) { + numberStr := chi.URLParam(r, "number") + number, err := strconv.ParseInt(numberStr, 10, 64) + if err != nil { + http.Error(w, http.StatusText(400), 400) + return + } + result, err := client.FetchCheckpoint(ctx, number) + writeResponse(w, result, err) + }) + + router.Get("/checkpoints/latest", func(w http.ResponseWriter, r *http.Request) { + result, err := client.FetchCheckpoint(ctx, -1) + writeResponse(w, result, err) + }) + + router.Get("/checkpoints/count", func(w http.ResponseWriter, r *http.Request) { + result, err := client.FetchCheckpointCount(ctx) + writeResponse(w, wrapResult(result), err) + }) + + router.Get("/milestone/{number}", func(w http.ResponseWriter, r *http.Request) { + numberStr := chi.URLParam(r, "number") + number, err := strconv.ParseInt(numberStr, 10, 64) + if err != nil { + http.Error(w, http.StatusText(400), 400) + return + } + result, err := client.FetchMilestone(ctx, number) + writeResponse(w, result, err) + }) + + router.Get("/milestone/latest", func(w http.ResponseWriter, r *http.Request) { + result, err := client.FetchMilestone(ctx, -1) + writeResponse(w, result, err) + }) + + router.Get("/milestone/count", func(w http.ResponseWriter, r *http.Request) { + result, err := client.FetchMilestoneCount(ctx) + writeResponse(w, milestone.MilestoneCount{Count: result}, err) + }) + + router.Get("/milestone/noAck/{id}", func(w http.ResponseWriter, r *http.Request) { + id := chi.URLParam(r, "id") + err := client.FetchNoAckMilestone(ctx, id) + result := err == nil + writeResponse(w, wrapResult(result), err) + }) + + router.Get("/milestone/lastNoAck", func(w http.ResponseWriter, r *http.Request) { + result, err := client.FetchLastNoAckMilestone(ctx) + writeResponse(w, wrapResult(result), err) + }) + + router.Get("/milestone/ID/{id}", func(w http.ResponseWriter, r *http.Request) { + id := chi.URLParam(r, "id") + err := client.FetchMilestoneID(ctx, id) + result := err == nil + writeResponse(w, wrapResult(result), err) + }) + + return router +} + +func startHTTPServer(ctx context.Context, server *http.Server, serverName string, logger log.Logger) error { + listener, err := net.Listen("tcp", server.Addr) + if err != nil { + return err + } + + go func() { + err := server.Serve(listener) + if (err != nil) && !errors.Is(err, http.ErrServerClosed) { + logger.Error("server.Serve error", "serverName", serverName, "err", err) + } + }() + + go func() { + <-ctx.Done() + _ = server.Close() + }() + + return nil } func (h *Heimdall) Stop() { diff --git a/cmd/devnet/services/polygon/heimdall_test.go b/cmd/devnet/services/polygon/heimdall_test.go new file mode 100644 index 00000000000..a9b34d3bdc6 --- /dev/null +++ b/cmd/devnet/services/polygon/heimdall_test.go @@ -0,0 +1,64 @@ +package polygon + +import ( + "context" + "math/big" + "net/http" + "testing" + "time" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/require" + + "github.com/ledgerwatch/erigon/polygon/bor/clerk" + "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" + heimdallmock "github.com/ledgerwatch/erigon/polygon/heimdall/mock" + heimdallspan "github.com/ledgerwatch/erigon/polygon/heimdall/span" +) + +func TestHeimdallServer(t *testing.T) { + t.Skip() + + ctx := context.Background() + ctrl := gomock.NewController(t) + client := heimdallmock.NewMockIHeimdallClient(ctrl) + + events := []*clerk.EventRecordWithTime{ + { + EventRecord: clerk.EventRecord{ + ID: 1, + ChainID: "80001", + }, + Time: time.Now(), + }, + { + EventRecord: clerk.EventRecord{ + ID: 2, + ChainID: "80001", + }, + Time: time.Now(), + }, + } + client.EXPECT().StateSyncEvents(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(events, nil) + + span := &heimdallspan.HeimdallSpan{ + Span: heimdallspan.Span{ + ID: 1, + StartBlock: 1000, + EndBlock: 2000, + }, + ChainID: "80001", + } + client.EXPECT().Span(gomock.Any(), gomock.Any()).AnyTimes().Return(span, nil) + + checkpoint1 := &checkpoint.Checkpoint{ + StartBlock: big.NewInt(1000), + EndBlock: big.NewInt(1999), + BorChainID: "80001", + } + client.EXPECT().FetchCheckpoint(gomock.Any(), gomock.Any()).AnyTimes().Return(checkpoint1, nil) + client.EXPECT().FetchCheckpointCount(gomock.Any()).AnyTimes().Return(int64(1), nil) + + err := http.ListenAndServe(HeimdallURLDefault[7:], makeHeimdallRouter(ctx, client)) + require.Nil(t, err) +} diff --git a/cmd/devnet/services/polygon/statesync.go b/cmd/devnet/services/polygon/statesync.go index ed7232ae59c..cf4bbd1861b 100644 --- a/cmd/devnet/services/polygon/statesync.go +++ b/cmd/devnet/services/polygon/statesync.go @@ -42,7 +42,7 @@ func (h *Heimdall) startStateSyncSubscription() { } } -func (h *Heimdall) StateSyncEvents(ctx context.Context, fromID uint64, to int64, limit int) (uint64, []*clerk.EventRecordWithTime, error) { +func (h *Heimdall) StateSyncEvents(ctx context.Context, fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error) { h.Lock() defer h.Unlock() @@ -72,19 +72,14 @@ func (h *Heimdall) StateSyncEvents(ctx context.Context, fromID uint64, to int64, if len(events) == 0 { h.logger.Info("Processed sync request", "from", fromID, "to", time.Unix(to, 0), "min-time", minEventTime, "pending", len(h.pendingSyncRecords), "filtered", len(events)) - return 0, nil, nil + return nil, nil } sort.Slice(events, func(i, j int) bool { return events[i].ID < events[j].ID }) - if len(events) > limit { - events = events[0 : limit-1] - } - eventsWithTime := make([]*clerk.EventRecordWithTime, len(events)) - for i, event := range events { eventsWithTime[i] = &event.EventRecordWithTime } @@ -98,7 +93,7 @@ func (h *Heimdall) StateSyncEvents(ctx context.Context, fromID uint64, to int64, "pending", len(h.pendingSyncRecords), "filtered", len(events), "sent", fmt.Sprintf("%d-%d", events[0].ID, events[len(events)-1].ID)) - return events[len(events)-1].BlockNumber, eventsWithTime, nil + return eventsWithTime, nil } // handleStateSyncEvent - handle state sync event from rootchain diff --git a/cmd/devnet/tests/context.go b/cmd/devnet/tests/context.go index af92c3a0df8..554bf99d000 100644 --- a/cmd/devnet/tests/context.go +++ b/cmd/devnet/tests/context.go @@ -23,9 +23,9 @@ func initDevnet(chainName string, dataDir string, producerCount int, gasLimit ui switch chainName { case networkname.BorDevnetChainName: - heimdallGrpcAddr := polygon.HeimdallGrpcAddressDefault + heimdallURL := polygon.HeimdallURLDefault const sprintSize uint64 = 0 - return networks.NewBorDevnetWithLocalHeimdall(dataDir, baseRpcHost, baseRpcPort, heimdallGrpcAddr, sprintSize, producerCount, gasLimit, logger, consoleLogLevel, dirLogLevel), nil + return networks.NewBorDevnetWithLocalHeimdall(dataDir, baseRpcHost, baseRpcPort, heimdallURL, sprintSize, producerCount, gasLimit, logger, consoleLogLevel, dirLogLevel), nil case networkname.DevChainName: return networks.NewDevDevnet(dataDir, baseRpcHost, baseRpcPort, producerCount, gasLimit, logger, consoleLogLevel, dirLogLevel), nil diff --git a/cmd/integration/commands/flags.go b/cmd/integration/commands/flags.go index ea80e124110..70036f55425 100644 --- a/cmd/integration/commands/flags.go +++ b/cmd/integration/commands/flags.go @@ -22,7 +22,6 @@ var ( migration string integrityFast, integritySlow bool file string - HeimdallgRPCAddress string HeimdallURL string txtrace bool // Whether to trace the execution (should only be used together with `block`) pruneFlag string diff --git a/cmd/integration/commands/stages.go b/cmd/integration/commands/stages.go index 386fc86f91a..ab9851c2d50 100644 --- a/cmd/integration/commands/stages.go +++ b/cmd/integration/commands/stages.go @@ -19,7 +19,6 @@ import ( "golang.org/x/exp/slices" "github.com/ledgerwatch/erigon/polygon/heimdall" - "github.com/ledgerwatch/erigon/polygon/heimdall/heimdallgrpc" "github.com/ledgerwatch/erigon/core/rawdb/blockio" "github.com/ledgerwatch/erigon/node/nodecfg" @@ -1682,11 +1681,7 @@ func initConsensusEngine(ctx context.Context, cc *chain2.Config, dir string, db consensusConfig = cc.Bor config.HeimdallURL = HeimdallURL if !config.WithoutHeimdall { - if config.HeimdallgRPCAddress != "" { - heimdallClient = heimdallgrpc.NewHeimdallGRPCClient(config.HeimdallgRPCAddress, logger) - } else { - heimdallClient = heimdall.NewHeimdallClient(config.HeimdallURL, logger) - } + heimdallClient = heimdall.NewHeimdallClient(config.HeimdallURL, logger) } } else { consensusConfig = &config.Ethash diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 1700d5a853a..23bb4fa55c8 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -760,18 +760,18 @@ var ( Usage: "Enabling grpc health check", } - HeimdallURLFlag = cli.StringFlag{ - Name: "bor.heimdall", - Usage: "URL of Heimdall service", - Value: "http://localhost:1317", - } - WebSeedsFlag = cli.StringFlag{ Name: "webseed", Usage: "Comma-separated URL's, holding metadata about network-support infrastructure (like S3 buckets with snapshots, bootnodes, etc...)", Value: "", } + HeimdallURLFlag = cli.StringFlag{ + Name: "bor.heimdall", + Usage: "URL of Heimdall service", + Value: "http://localhost:1317", + } + // WithoutHeimdallFlag no heimdall (for testing purpose) WithoutHeimdallFlag = cli.BoolFlag{ Name: "bor.withoutheimdall", @@ -794,18 +794,12 @@ var ( Value: true, } - // HeimdallgRPCAddressFlag flag for heimdall gRPC address - HeimdallgRPCAddressFlag = cli.StringFlag{ - Name: "bor.heimdallgRPC", - Usage: "Address of Heimdall gRPC service", - Value: "", - } - ConfigFlag = cli.StringFlag{ Name: "config", Usage: "Sets erigon flags from YAML/TOML file", Value: "", } + LightClientDiscoveryAddrFlag = cli.StringFlag{ Name: "lightclient.discovery.addr", Usage: "Address for lightclient DISCV5 protocol", @@ -821,6 +815,7 @@ var ( Usage: "TCP Port for lightclient DISCV5 protocol", Value: 4001, } + SentinelAddrFlag = cli.StringFlag{ Name: "sentinel.addr", Usage: "Address for sentinel", @@ -1497,7 +1492,6 @@ func setClique(ctx *cli.Context, cfg *params.ConsensusSnapshotConfig, datadir st func setBorConfig(ctx *cli.Context, cfg *ethconfig.Config) { cfg.HeimdallURL = ctx.String(HeimdallURLFlag.Name) cfg.WithoutHeimdall = ctx.Bool(WithoutHeimdallFlag.Name) - cfg.HeimdallgRPCAddress = ctx.String(HeimdallgRPCAddressFlag.Name) cfg.WithHeimdallMilestones = ctx.Bool(WithHeimdallMilestones.Name) } diff --git a/eth/backend.go b/eth/backend.go index 1b2e1baee7d..12fd0863957 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -111,7 +111,6 @@ import ( "github.com/ledgerwatch/erigon/polygon/bor/finality/flags" "github.com/ledgerwatch/erigon/polygon/bor/valset" "github.com/ledgerwatch/erigon/polygon/heimdall" - "github.com/ledgerwatch/erigon/polygon/heimdall/heimdallgrpc" "github.com/ledgerwatch/erigon/rpc" "github.com/ledgerwatch/erigon/turbo/builder" "github.com/ledgerwatch/erigon/turbo/engineapi" @@ -515,11 +514,7 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger var heimdallClient heimdall.IHeimdallClient if chainConfig.Bor != nil { if !config.WithoutHeimdall { - if config.HeimdallgRPCAddress != "" { - heimdallClient = heimdallgrpc.NewHeimdallGRPCClient(config.HeimdallgRPCAddress, logger) - } else { - heimdallClient = heimdall.NewHeimdallClient(config.HeimdallURL, logger) - } + heimdallClient = heimdall.NewHeimdallClient(config.HeimdallURL, logger) } flags.Milestone = config.WithHeimdallMilestones diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index a75b5783ac6..a66e54cf44f 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -229,9 +229,6 @@ type Config struct { // New DB and Snapshots format of history allows: parallel blocks execution, get state as of given transaction without executing whole block.", HistoryV3 bool - // gRPC Address to connect to Heimdall node - HeimdallgRPCAddress string - // URL to connect to Heimdall node HeimdallURL string diff --git a/go.mod b/go.mod index 514e8f51903..f2ab6ea4449 100644 --- a/go.mod +++ b/go.mod @@ -65,7 +65,6 @@ require ( github.com/libp2p/go-libp2p-mplex v0.9.0 github.com/libp2p/go-libp2p-pubsub v0.9.3 github.com/maticnetwork/crand v1.0.2 - github.com/maticnetwork/polyproto v0.0.3-0.20230216113155-340ea926ca53 github.com/multiformats/go-multiaddr v0.12.1 github.com/nxadm/tail v1.4.9-0.20211216163028-4472660a31a6 github.com/pelletier/go-toml v1.9.5 diff --git a/go.sum b/go.sum index 4de0d41eac7..afc6c4286ef 100644 --- a/go.sum +++ b/go.sum @@ -598,8 +598,6 @@ github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8 github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU= github.com/maticnetwork/crand v1.0.2 h1:Af0tAivC8zrxXDpGWNWVT/0s1fOz8w0eRbahZgURS8I= github.com/maticnetwork/crand v1.0.2/go.mod h1:/NRNL3bj2eYdqpWmoIP5puxndTpi0XRxpj5ZKxfHjyg= -github.com/maticnetwork/polyproto v0.0.3-0.20230216113155-340ea926ca53 h1:PjYV+lghs106JKkrYgOnrsfDLoTc11BxZd4rUa4Rus4= -github.com/maticnetwork/polyproto v0.0.3-0.20230216113155-340ea926ca53/go.mod h1:e1mU2EXSwEpn5jM7GfNwu3AupsV6WAGoPFFfswXOF0o= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= diff --git a/polygon/heimdall/heimdall.go b/polygon/heimdall/heimdall.go index 673a5ff4a77..e72cf25ec8d 100644 --- a/polygon/heimdall/heimdall.go +++ b/polygon/heimdall/heimdall.go @@ -28,16 +28,3 @@ type IHeimdallClient interface { FetchMilestoneID(ctx context.Context, milestoneID string) error //Fetch the bool value whether milestone corresponding to the given id is in process in Heimdall Close() } - -type HeimdallServer interface { - StateSyncEvents(ctx context.Context, fromID uint64, to int64, limit int) (uint64, []*clerk.EventRecordWithTime, error) - Span(ctx context.Context, spanID uint64) (*span.HeimdallSpan, error) - FetchCheckpoint(ctx context.Context, number int64) (*checkpoint.Checkpoint, error) - FetchCheckpointCount(ctx context.Context) (int64, error) - FetchMilestone(ctx context.Context, number int64) (*milestone.Milestone, error) - FetchMilestoneCount(ctx context.Context) (int64, error) - FetchNoAckMilestone(ctx context.Context, milestoneID string) error - FetchLastNoAckMilestone(ctx context.Context) (string, error) - FetchMilestoneID(ctx context.Context, milestoneID string) error - Close() -} diff --git a/polygon/heimdall/heimdallgrpc/checkpoint.go b/polygon/heimdall/heimdallgrpc/checkpoint.go deleted file mode 100644 index f02398a3b37..00000000000 --- a/polygon/heimdall/heimdallgrpc/checkpoint.go +++ /dev/null @@ -1,50 +0,0 @@ -package heimdallgrpc - -import ( - "context" - "math/big" - - "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" - - proto "github.com/maticnetwork/polyproto/heimdall" - protoutils "github.com/maticnetwork/polyproto/utils" -) - -func (h *HeimdallGRPCClient) FetchCheckpointCount(ctx context.Context) (int64, error) { - h.logger.Info("Fetching checkpoint count") - - res, err := h.client.FetchCheckpointCount(ctx, nil) - if err != nil { - return 0, err - } - - h.logger.Info("Fetched checkpoint count") - - return res.Result.Result, nil -} - -func (h *HeimdallGRPCClient) FetchCheckpoint(ctx context.Context, number int64) (*checkpoint.Checkpoint, error) { - req := &proto.FetchCheckpointRequest{ - ID: number, - } - - h.logger.Info("Fetching checkpoint", "number", number) - - res, err := h.client.FetchCheckpoint(ctx, req) - if err != nil { - return nil, err - } - - h.logger.Info("Fetched checkpoint", "number", number) - - checkpoint := &checkpoint.Checkpoint{ - StartBlock: new(big.Int).SetUint64(res.Result.StartBlock), - EndBlock: new(big.Int).SetUint64(res.Result.EndBlock), - RootHash: protoutils.ConvertH256ToHash(res.Result.RootHash), - Proposer: protoutils.ConvertH160toAddress(res.Result.Proposer), - BorChainID: res.Result.BorChainID, - Timestamp: uint64(res.Result.Timestamp.GetSeconds()), - } - - return checkpoint, nil -} diff --git a/polygon/heimdall/heimdallgrpc/client.go b/polygon/heimdall/heimdallgrpc/client.go deleted file mode 100644 index 6c5799d0415..00000000000 --- a/polygon/heimdall/heimdallgrpc/client.go +++ /dev/null @@ -1,53 +0,0 @@ -package heimdallgrpc - -import ( - "time" - - grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry" - "github.com/ledgerwatch/log/v3" - proto "github.com/maticnetwork/polyproto/heimdall" - - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/credentials/insecure" -) - -const ( - stateFetchLimit = 50 -) - -type HeimdallGRPCClient struct { - conn *grpc.ClientConn - client proto.HeimdallClient - logger log.Logger -} - -func NewHeimdallGRPCClient(address string, logger log.Logger) *HeimdallGRPCClient { - opts := []grpc_retry.CallOption{ - grpc_retry.WithMax(10000), - grpc_retry.WithBackoff(grpc_retry.BackoffLinear(5 * time.Second)), - grpc_retry.WithCodes(codes.Internal, codes.Unavailable, codes.Aborted, codes.NotFound), - } - - conn, err := grpc.Dial(address, - grpc.WithStreamInterceptor(grpc_retry.StreamClientInterceptor(opts...)), - grpc.WithUnaryInterceptor(grpc_retry.UnaryClientInterceptor(opts...)), - grpc.WithTransportCredentials(insecure.NewCredentials()), - ) - if err != nil { - logger.Crit("Failed to connect to Heimdall gRPC", "error", err) - } - - logger.Info("Connected to Heimdall gRPC server", "address", address) - - return &HeimdallGRPCClient{ - conn: conn, - client: proto.NewHeimdallClient(conn), - logger: logger, - } -} - -func (h *HeimdallGRPCClient) Close() { - h.logger.Debug("Shutdown detected, Closing Heimdall gRPC client") - h.conn.Close() -} diff --git a/polygon/heimdall/heimdallgrpc/milestone.go b/polygon/heimdall/heimdallgrpc/milestone.go deleted file mode 100644 index a20b4d7dc3b..00000000000 --- a/polygon/heimdall/heimdallgrpc/milestone.go +++ /dev/null @@ -1,103 +0,0 @@ -package heimdallgrpc - -import ( - "context" - "fmt" - "math/big" - - "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" - - proto "github.com/maticnetwork/polyproto/heimdall" - protoutils "github.com/maticnetwork/polyproto/utils" -) - -func (h *HeimdallGRPCClient) FetchMilestoneCount(ctx context.Context) (int64, error) { - h.logger.Info("Fetching milestone count") - - res, err := h.client.FetchMilestoneCount(ctx, nil) - if err != nil { - return 0, err - } - - h.logger.Info("Fetched milestone count") - - return res.Result.Count, nil -} - -func (h *HeimdallGRPCClient) FetchMilestone(ctx context.Context, number int64) (*milestone.Milestone, error) { - h.logger.Info("Fetching milestone") - - // TODO: use number - res, err := h.client.FetchMilestone(ctx, nil) - if err != nil { - return nil, err - } - - h.logger.Info("Fetched milestone") - - milestone := &milestone.Milestone{ - StartBlock: new(big.Int).SetUint64(res.Result.StartBlock), - EndBlock: new(big.Int).SetUint64(res.Result.EndBlock), - Hash: protoutils.ConvertH256ToHash(res.Result.RootHash), - Proposer: protoutils.ConvertH160toAddress(res.Result.Proposer), - BorChainID: res.Result.BorChainID, - Timestamp: uint64(res.Result.Timestamp.GetSeconds()), - } - - return milestone, nil -} - -func (h *HeimdallGRPCClient) FetchLastNoAckMilestone(ctx context.Context) (string, error) { - h.logger.Info("Fetching latest no ack milestone Id") - - res, err := h.client.FetchLastNoAckMilestone(ctx, nil) - if err != nil { - return "", err - } - - h.logger.Info("Fetched last no-ack milestone") - - return res.Result.Result, nil -} - -func (h *HeimdallGRPCClient) FetchNoAckMilestone(ctx context.Context, milestoneID string) error { - req := &proto.FetchMilestoneNoAckRequest{ - MilestoneID: milestoneID, - } - - h.logger.Info("Fetching no ack milestone", "milestoneID", milestoneID) - - res, err := h.client.FetchNoAckMilestone(ctx, req) - if err != nil { - return err - } - - if !res.Result.Result { - return fmt.Errorf("Not in rejected list: milestoneID %q", milestoneID) - } - - h.logger.Info("Fetched no ack milestone", "milestoneID", milestoneID) - - return nil -} - -func (h *HeimdallGRPCClient) FetchMilestoneID(ctx context.Context, milestoneID string) error { - req := &proto.FetchMilestoneIDRequest{ - MilestoneID: milestoneID, - } - - h.logger.Info("Fetching milestone id", "milestoneID", milestoneID) - - res, err := h.client.FetchMilestoneID(ctx, req) - if err != nil { - return err - } - - if !res.Result.Result { - return fmt.Errorf("This milestoneID %q does not exist", milestoneID) - } - - h.logger.Info("Fetched milestone id", "milestoneID", milestoneID) - - return nil -} diff --git a/polygon/heimdall/heimdallgrpc/server.go b/polygon/heimdall/heimdallgrpc/server.go deleted file mode 100644 index ea0ee45ad9e..00000000000 --- a/polygon/heimdall/heimdallgrpc/server.go +++ /dev/null @@ -1,251 +0,0 @@ -package heimdallgrpc - -import ( - "context" - "fmt" - "net" - "time" - - "github.com/ledgerwatch/log/v3" - proto "github.com/maticnetwork/polyproto/heimdall" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" - "google.golang.org/protobuf/types/known/emptypb" - "google.golang.org/protobuf/types/known/timestamppb" - - "github.com/ledgerwatch/erigon/polygon/heimdall" - - "github.com/ledgerwatch/erigon-lib/gointerfaces" -) - -type HeimdallGRPCServer struct { - proto.UnimplementedHeimdallServer - heimdall heimdall.HeimdallServer - logger log.Logger -} - -func (h *HeimdallGRPCServer) Span(ctx context.Context, in *proto.SpanRequest) (*proto.SpanResponse, error) { - result, err := h.heimdall.Span(ctx, in.ID) - - if err != nil { - h.logger.Error("[bor.heimdall] Error while fetching span") - return nil, err - } - - validators := make([]*proto.Validator, len(result.ValidatorSet.Validators)) - - for i, validator := range result.ValidatorSet.Validators { - h160 := gointerfaces.ConvertAddressToH160(validator.Address) - validators[i] = &proto.Validator{ - ID: validator.ID, - Address: &proto.H160{ - Hi: &proto.H128{ - Hi: h160.Hi.Hi, - Lo: h160.Hi.Lo, - }, - Lo: h160.Lo, - }, - VotingPower: validator.VotingPower, - ProposerPriority: validator.ProposerPriority, - } - } - - var proposer *proto.Validator - - if vsp := result.ValidatorSet.Proposer; vsp != nil { - proposerH160 := gointerfaces.ConvertAddressToH160(vsp.Address) - proposer = &proto.Validator{ - ID: vsp.ID, - Address: &proto.H160{ - Hi: &proto.H128{ - Hi: proposerH160.Hi.Hi, - Lo: proposerH160.Hi.Lo, - }, - Lo: proposerH160.Lo, - }, - VotingPower: vsp.VotingPower, - ProposerPriority: vsp.ProposerPriority, - } - } - - producers := make([]*proto.Validator, len(result.SelectedProducers)) - - for i, producer := range result.SelectedProducers { - h160 := gointerfaces.ConvertAddressToH160(producer.Address) - producers[i] = &proto.Validator{ - ID: producer.ID, - Address: &proto.H160{ - Hi: &proto.H128{ - Hi: h160.Hi.Hi, - Lo: h160.Hi.Lo, - }, - Lo: h160.Lo, - }, - VotingPower: producer.VotingPower, - ProposerPriority: producer.ProposerPriority, - } - } - - resp := &proto.SpanResponse{ - Result: &proto.Span{ - ID: result.ID, - StartBlock: result.StartBlock, - EndBlock: result.EndBlock, - ValidatorSet: &proto.ValidatorSet{ - Validators: validators, - Proposer: proposer, - }, - SelectedProducers: producers, - ChainID: result.ChainID, - }, - } - - return resp, nil -} - -func (h *HeimdallGRPCServer) FetchCheckpointCount(ctx context.Context, in *emptypb.Empty) (*proto.FetchCheckpointCountResponse, error) { - count, err := h.heimdall.FetchCheckpointCount(ctx) - - if err != nil { - h.logger.Error("[bor.heimdall] Error while fetching checkpoint count") - return nil, err - } - - resp := &proto.FetchCheckpointCountResponse{} - resp.Height = fmt.Sprint(count) - - return resp, nil -} - -func (h *HeimdallGRPCServer) FetchCheckpoint(ctx context.Context, in *proto.FetchCheckpointRequest) (*proto.FetchCheckpointResponse, error) { - - _ /*checkpoint*/, err := h.heimdall.FetchCheckpoint(ctx, in.ID) - - if err != nil { - h.logger.Error("[bor.heimdall] Error while fetching checkpoint") - return nil, err - } - - /* TODO - - var hash [32]byte - - copy(hash[:], checkPoint.RootHash.Bytes()) - - var address [20]byte - - copy(address[:], checkPoint.Proposer.Bytes()) - */ - - resp := &proto.FetchCheckpointResponse{} - - /* TODO - resp.Height = fmt.Sprint(result.Height) - resp.Result = &proto.Checkpoint{ - StartBlock: checkPoint.StartBlock, - EndBlock: checkPoint.EndBlock, - RootHash: protoutils.ConvertHashToH256(hash), - Proposer: protoutils.ConvertAddressToH160(address), - Timestamp: timestamppb.New(time.Unix(int64(checkPoint.TimeStamp), 0)), - BorChainID: checkPoint.BorChainID, - } - */ - return resp, nil -} - -func (h *HeimdallGRPCServer) StateSyncEvents(req *proto.StateSyncEventsRequest, reply proto.Heimdall_StateSyncEventsServer) error { - fromId := req.FromID - - for { - height, events, err := h.heimdall.StateSyncEvents(context.Background(), fromId, int64(req.ToTime), int(req.Limit)) - - if err != nil { - h.logger.Error("[bor.heimdall] Error while fetching event records", "error", err) - return status.Errorf(codes.Internal, err.Error()) - } - - eventRecords := make([]*proto.EventRecord, len(events)) - - for i, event := range events { - eventRecords[i] = &proto.EventRecord{ - ID: event.ID, - Contract: event.Contract.Hex(), - Data: event.Data.String(), - TxHash: event.TxHash.Hex(), - LogIndex: event.LogIndex, - ChainID: event.ChainID, - Time: timestamppb.New(event.Time), - } - } - - if len(eventRecords) == 0 { - break - } - - err = reply.Send(&proto.StateSyncEventsResponse{ - Height: fmt.Sprint(height), - Result: eventRecords, - }) - - if err != nil { - h.logger.Error("[bor.heimdall] Error while sending event record", "error", err) - return status.Errorf(codes.Internal, err.Error()) - } - - if len(eventRecords) < int(req.Limit) { - break - } - - fromId += req.Limit - } - - return nil -} - -// StartHeimdallServer creates a heimdall GRPC server - which is implemented via the passed in client -// interface. It is intended for use in testing where more than a single test validator is required rather -// than to replace the maticnetwork implementation -func StartHeimdallServer(shutDownCtx context.Context, heimdall heimdall.HeimdallServer, addr string, logger log.Logger) error { - grpcServer := grpc.NewServer(withLoggingUnaryInterceptor(logger)) - proto.RegisterHeimdallServer(grpcServer, - &HeimdallGRPCServer{ - heimdall: heimdall, - logger: logger, - }) - - lis, err := net.Listen("tcp", addr) - if err != nil { - return err - } - - go func() { - if err := grpcServer.Serve(lis); err != nil { - logger.Error("[bor.heimdall] failed to serve grpc server", "err", err) - } - - <-shutDownCtx.Done() - grpcServer.Stop() - lis.Close() - logger.Info("[bor.heimdall] GRPC Server stopped", "addr", addr) - }() - - logger.Info("[bor.heimdall] GRPC Server started", "addr", addr) - - return nil -} - -func withLoggingUnaryInterceptor(logger log.Logger) grpc.ServerOption { - return grpc.UnaryInterceptor(func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { - start := time.Now() - - h, err := handler(ctx, req) - if err != nil { - err = status.Errorf(codes.Internal, err.Error()) - } - - logger.Debug("[bor.heimdall] Request", "method", info.FullMethod, "duration", time.Since(start), "error", err) - - return h, err - }) -} diff --git a/polygon/heimdall/heimdallgrpc/span.go b/polygon/heimdall/heimdallgrpc/span.go deleted file mode 100644 index 9d9a24b787e..00000000000 --- a/polygon/heimdall/heimdallgrpc/span.go +++ /dev/null @@ -1,63 +0,0 @@ -package heimdallgrpc - -import ( - "context" - - "github.com/ledgerwatch/erigon/polygon/heimdall/span" - - "github.com/ledgerwatch/erigon/polygon/bor/valset" - - proto "github.com/maticnetwork/polyproto/heimdall" - protoutils "github.com/maticnetwork/polyproto/utils" -) - -func (h *HeimdallGRPCClient) Span(ctx context.Context, spanID uint64) (*span.HeimdallSpan, error) { - req := &proto.SpanRequest{ - ID: spanID, - } - - h.logger.Info("Fetching span", "spanID", spanID) - - res, err := h.client.Span(ctx, req) - if err != nil { - return nil, err - } - - h.logger.Info("Fetched span", "spanID", spanID) - - return parseSpan(res.Result), nil -} - -func parseSpan(protoSpan *proto.Span) *span.HeimdallSpan { - resp := &span.HeimdallSpan{ - Span: span.Span{ - ID: protoSpan.ID, - StartBlock: protoSpan.StartBlock, - EndBlock: protoSpan.EndBlock, - }, - ValidatorSet: valset.ValidatorSet{}, - SelectedProducers: []valset.Validator{}, - ChainID: protoSpan.ChainID, - } - - for _, validator := range protoSpan.ValidatorSet.Validators { - resp.ValidatorSet.Validators = append(resp.ValidatorSet.Validators, parseValidator(validator)) - } - - resp.ValidatorSet.Proposer = parseValidator(protoSpan.ValidatorSet.Proposer) - - for _, validator := range protoSpan.SelectedProducers { - resp.SelectedProducers = append(resp.SelectedProducers, *parseValidator(validator)) - } - - return resp -} - -func parseValidator(validator *proto.Validator) *valset.Validator { - return &valset.Validator{ - ID: validator.ID, - Address: protoutils.ConvertH160toAddress(validator.Address), - VotingPower: validator.VotingPower, - ProposerPriority: validator.ProposerPriority, - } -} diff --git a/polygon/heimdall/heimdallgrpc/state_sync.go b/polygon/heimdall/heimdallgrpc/state_sync.go deleted file mode 100644 index 0d32a1908e3..00000000000 --- a/polygon/heimdall/heimdallgrpc/state_sync.go +++ /dev/null @@ -1,58 +0,0 @@ -package heimdallgrpc - -import ( - "context" - "errors" - "io" - - libcommon "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon/polygon/bor/clerk" - proto "github.com/maticnetwork/polyproto/heimdall" -) - -func (h *HeimdallGRPCClient) StateSyncEvents(ctx context.Context, fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error) { - eventRecords := make([]*clerk.EventRecordWithTime, 0) - - req := &proto.StateSyncEventsRequest{ - FromID: fromID, - ToTime: uint64(to), - Limit: uint64(stateFetchLimit), - } - - var ( - res proto.Heimdall_StateSyncEventsClient - events *proto.StateSyncEventsResponse - err error - ) - - res, err = h.client.StateSyncEvents(ctx, req) - if err != nil { - return nil, err - } - - for { - events, err = res.Recv() - if errors.Is(err, io.EOF) { - return eventRecords, nil - } - - if err != nil { - return nil, err - } - - for _, event := range events.Result { - eventRecord := &clerk.EventRecordWithTime{ - EventRecord: clerk.EventRecord{ - ID: event.ID, - Contract: libcommon.HexToAddress(event.Contract), - Data: libcommon.Hex2Bytes(event.Data[2:]), - TxHash: libcommon.HexToHash(event.TxHash), - LogIndex: event.LogIndex, - ChainID: event.ChainID, - }, - Time: event.Time.AsTime(), - } - eventRecords = append(eventRecords, eventRecord) - } - } -} diff --git a/turbo/cli/default_flags.go b/turbo/cli/default_flags.go index d5ab5f85a5d..45a39a2a963 100644 --- a/turbo/cli/default_flags.go +++ b/turbo/cli/default_flags.go @@ -149,7 +149,6 @@ var DefaultFlags = []cli.Flag{ &utils.HeimdallURLFlag, &utils.WebSeedsFlag, &utils.WithoutHeimdallFlag, - &utils.HeimdallgRPCAddressFlag, &utils.BorBlockPeriodFlag, &utils.BorBlockSizeFlag, &utils.WithHeimdallMilestones, From 79499b5cac7462788f79cb93c390d24b2c4f073d Mon Sep 17 00:00:00 2001 From: ddl Date: Tue, 16 Jan 2024 02:46:26 +0800 Subject: [PATCH 68/92] refactor(p2p/dnsdisc): replace strings.IndexByte with strings.Cut (#9236) similar to https://github.com/ledgerwatch/erigon/pull/9202 --- p2p/dnsdisc/tree.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/p2p/dnsdisc/tree.go b/p2p/dnsdisc/tree.go index 8329e6667c2..0c47edf9478 100644 --- a/p2p/dnsdisc/tree.go +++ b/p2p/dnsdisc/tree.go @@ -311,11 +311,11 @@ func parseLink(e string) (*linkEntry, error) { return nil, fmt.Errorf("wrong/missing scheme 'enrtree' in URL") } e = e[len(linkPrefix):] - pos := strings.IndexByte(e, '@') - if pos == -1 { + keystring, domain, ok := strings.Cut(e, "@") + if !ok { return nil, entryError{"link", errNoPubkey} } - keystring, domain := e[:pos], e[pos+1:] + keybytes, err := b32format.DecodeString(keystring) if err != nil { return nil, entryError{"link", errBadPubkey} From 2793ef6ec1f5a673646a1b5bcaa284e5bcf9b2cc Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Tue, 16 Jan 2024 09:23:02 +0100 Subject: [PATCH 69/92] polygon: flatten redundant packages (#9241) * move mocks to the owner packages * squash single file packages * move types to more appropriate files * remove unused mocks --- cmd/devnet/services/polygon/checkpoint.go | 5 +- cmd/devnet/services/polygon/heimdall.go | 28 ++- cmd/devnet/services/polygon/heimdall_test.go | 19 +- .../services/polygon/proofgenerator_test.go | 16 +- cmd/devnet/services/polygon/statesync.go | 12 +- cmd/integration/commands/stages.go | 2 +- cmd/rpcdaemon/cli/config.go | 10 +- eth/backend.go | 2 +- eth/ethconsensusconfig/config.go | 11 +- eth/stagedsync/bor_heimdall_shared.go | 10 +- eth/stagedsync/stage_bor_heimdall.go | 24 ++- eth/stagedsync/stagedsynctest/harness.go | 41 ++-- polygon/bor/abi/interface.go | 6 - polygon/bor/bor.go | 24 ++- polygon/bor/bor_test.go | 41 ++-- polygon/bor/contract/client.go | 82 -------- polygon/bor/errors.go | 20 -- polygon/bor/finality/bor_verifier.go | 3 +- polygon/bor/finality/generics/generics.go | 7 - polygon/bor/finality/milestone_rewind.go | 12 ++ polygon/bor/finality/whitelist.go | 14 +- polygon/bor/finality/whitelist_helpers.go | 8 +- polygon/bor/genesis_contract.go | 14 -- polygon/bor/genesis_contracts.go | 87 +++++++++ polygon/bor/mock/genesis_contract_mock.go | 66 ------- polygon/{heimdall/span => bor}/span_id.go | 18 +- polygon/bor/span_id_test.go | 44 +++++ polygon/bor/spanner.go | 164 +++++++++++++++- polygon/bor/{mock => }/spanner_mock.go | 12 +- .../spanner_test_validators.go} | 2 +- .../heimdall/{checkpoint => }/checkpoint.go | 2 +- polygon/heimdall/client.go | 56 +++--- polygon/heimdall/client_mock.go | 180 +++++++++++++++++ polygon/heimdall/client_test.go | 6 +- .../clerk.go => heimdall/event_record.go} | 7 +- polygon/heimdall/heimdall.go | 30 --- .../heimdall/{mock => }/http_client_mock.go | 4 +- polygon/heimdall/{milestone => }/milestone.go | 2 +- polygon/heimdall/mock/heimdall_client_mock.go | 184 ------------------ polygon/heimdall/{span => }/span.go | 8 +- polygon/heimdall/span/span_id_test.go | 44 ----- polygon/heimdall/span/spanner.go | 160 --------------- polygon/sync/canonical_chain_builder_test.go | 3 +- polygon/sync/header_downloader_test.go | 15 +- polygon/sync/heimdall.go | 37 ++-- polygon/sync/heimdall_mock.go | 15 +- polygon/sync/heimdall_test.go | 35 ++-- polygon/sync/spans_cache.go | 4 +- polygon/sync/state_point.go | 8 +- polygon/sync/state_points.go | 7 +- .../snapshotsync/freezeblocks/block_reader.go | 11 +- .../freezeblocks/block_snapshots.go | 5 +- .../freezeblocks/bor_snapshots.go | 9 +- turbo/stages/stageloop.go | 5 +- 54 files changed, 743 insertions(+), 898 deletions(-) delete mode 100644 polygon/bor/abi/interface.go delete mode 100644 polygon/bor/contract/client.go create mode 100644 polygon/bor/finality/milestone_rewind.go delete mode 100644 polygon/bor/genesis_contract.go create mode 100644 polygon/bor/genesis_contracts.go delete mode 100644 polygon/bor/mock/genesis_contract_mock.go rename polygon/{heimdall/span => bor}/span_id.go (50%) create mode 100644 polygon/bor/span_id_test.go rename polygon/bor/{mock => }/spanner_mock.go (92%) rename polygon/{heimdall/span/testValidators.go => bor/spanner_test_validators.go} (98%) rename polygon/heimdall/{checkpoint => }/checkpoint.go (98%) create mode 100644 polygon/heimdall/client_mock.go rename polygon/{bor/clerk/clerk.go => heimdall/event_record.go} (89%) delete mode 100644 polygon/heimdall/heimdall.go rename polygon/heimdall/{mock => }/http_client_mock.go (96%) rename polygon/heimdall/{milestone => }/milestone.go (98%) delete mode 100644 polygon/heimdall/mock/heimdall_client_mock.go rename polygon/heimdall/{span => }/span.go (88%) delete mode 100644 polygon/heimdall/span/span_id_test.go delete mode 100644 polygon/heimdall/span/spanner.go diff --git a/cmd/devnet/services/polygon/checkpoint.go b/cmd/devnet/services/polygon/checkpoint.go index 5386ab019e9..903919ecb49 100644 --- a/cmd/devnet/services/polygon/checkpoint.go +++ b/cmd/devnet/services/polygon/checkpoint.go @@ -10,8 +10,6 @@ import ( "strings" "time" - "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" - "github.com/ledgerwatch/erigon-lib/chain/networkname" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/hexutility" @@ -23,6 +21,7 @@ import ( "github.com/ledgerwatch/erigon/cmd/devnet/requests" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/crypto" + "github.com/ledgerwatch/erigon/polygon/heimdall" ) type CheckpointBlock struct { @@ -177,7 +176,7 @@ func (h *Heimdall) handleChildHeader(ctx context.Context, header *types.Header) return err } - h.pendingCheckpoint = &checkpoint.Checkpoint{ + h.pendingCheckpoint = &heimdall.Checkpoint{ Timestamp: timeStamp, StartBlock: big.NewInt(int64(expectedCheckpointState.newStart)), EndBlock: big.NewInt(int64(expectedCheckpointState.newEnd)), diff --git a/cmd/devnet/services/polygon/heimdall.go b/cmd/devnet/services/polygon/heimdall.go index 1288f67c683..80253bf276f 100644 --- a/cmd/devnet/services/polygon/heimdall.go +++ b/cmd/devnet/services/polygon/heimdall.go @@ -16,11 +16,6 @@ import ( "github.com/go-chi/chi/v5" "github.com/ledgerwatch/log/v3" - "github.com/ledgerwatch/erigon/polygon/heimdall" - "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" - "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" - "github.com/ledgerwatch/erigon/polygon/heimdall/span" - ethereum "github.com/ledgerwatch/erigon" "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" @@ -31,6 +26,7 @@ import ( "github.com/ledgerwatch/erigon/cmd/devnet/devnet" "github.com/ledgerwatch/erigon/polygon/bor/borcfg" "github.com/ledgerwatch/erigon/polygon/bor/valset" + "github.com/ledgerwatch/erigon/polygon/heimdall" ) type BridgeEvent string @@ -79,11 +75,11 @@ type Heimdall struct { borConfig *borcfg.BorConfig listenAddr string validatorSet *valset.ValidatorSet - pendingCheckpoint *checkpoint.Checkpoint + pendingCheckpoint *heimdall.Checkpoint latestCheckpoint *CheckpointAck ackWaiter *sync.Cond - currentSpan *span.HeimdallSpan - spans map[uint64]*span.HeimdallSpan + currentSpan *heimdall.HeimdallSpan + spans map[uint64]*heimdall.HeimdallSpan logger log.Logger cancelFunc context.CancelFunc syncSenderAddress libcommon.Address @@ -109,7 +105,7 @@ func NewHeimdall( borConfig: chainConfig.Bor.(*borcfg.BorConfig), listenAddr: serverURL[7:], checkpointConfig: *checkpointConfig, - spans: map[uint64]*span.HeimdallSpan{}, + spans: map[uint64]*heimdall.HeimdallSpan{}, pendingSyncRecords: map[syncRecordKey]*EventRecordWithBlock{}, logger: logger} @@ -146,7 +142,7 @@ func NewHeimdall( return heimdall } -func (h *Heimdall) Span(ctx context.Context, spanID uint64) (*span.HeimdallSpan, error) { +func (h *Heimdall) Span(ctx context.Context, spanID uint64) (*heimdall.HeimdallSpan, error) { h.Lock() defer h.Unlock() @@ -155,7 +151,7 @@ func (h *Heimdall) Span(ctx context.Context, spanID uint64) (*span.HeimdallSpan, return span, nil } - var nextSpan = span.Span{ + var nextSpan = heimdall.Span{ ID: spanID, } @@ -179,7 +175,7 @@ func (h *Heimdall) Span(ctx context.Context, spanID uint64) (*span.HeimdallSpan, selectedProducers[i] = *v } - h.currentSpan = &span.HeimdallSpan{ + h.currentSpan = &heimdall.HeimdallSpan{ Span: nextSpan, ValidatorSet: *h.validatorSet, SelectedProducers: selectedProducers, @@ -205,7 +201,7 @@ func (h *Heimdall) getSpanOverrideHeight() uint64 { //MumbaiChain: 10205000 } -func (h *Heimdall) FetchCheckpoint(ctx context.Context, number int64) (*checkpoint.Checkpoint, error) { +func (h *Heimdall) FetchCheckpoint(ctx context.Context, number int64) (*heimdall.Checkpoint, error) { return nil, fmt.Errorf("TODO") } @@ -213,7 +209,7 @@ func (h *Heimdall) FetchCheckpointCount(ctx context.Context) (int64, error) { return 0, fmt.Errorf("TODO") } -func (h *Heimdall) FetchMilestone(ctx context.Context, number int64) (*milestone.Milestone, error) { +func (h *Heimdall) FetchMilestone(ctx context.Context, number int64) (*heimdall.Milestone, error) { return nil, fmt.Errorf("TODO") } @@ -392,7 +388,7 @@ func (h *Heimdall) Start(ctx context.Context) error { return startHTTPServer(ctx, server, "devnet Heimdall service", h.logger) } -func makeHeimdallRouter(ctx context.Context, client heimdall.IHeimdallClient) *chi.Mux { +func makeHeimdallRouter(ctx context.Context, client heimdall.HeimdallClient) *chi.Mux { router := chi.NewRouter() writeResponse := func(w http.ResponseWriter, result any, err error) { @@ -492,7 +488,7 @@ func makeHeimdallRouter(ctx context.Context, client heimdall.IHeimdallClient) *c router.Get("/milestone/count", func(w http.ResponseWriter, r *http.Request) { result, err := client.FetchMilestoneCount(ctx) - writeResponse(w, milestone.MilestoneCount{Count: result}, err) + writeResponse(w, heimdall.MilestoneCount{Count: result}, err) }) router.Get("/milestone/noAck/{id}", func(w http.ResponseWriter, r *http.Request) { diff --git a/cmd/devnet/services/polygon/heimdall_test.go b/cmd/devnet/services/polygon/heimdall_test.go index a9b34d3bdc6..0cb3e58ab94 100644 --- a/cmd/devnet/services/polygon/heimdall_test.go +++ b/cmd/devnet/services/polygon/heimdall_test.go @@ -10,10 +10,7 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" - "github.com/ledgerwatch/erigon/polygon/bor/clerk" - "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" - heimdallmock "github.com/ledgerwatch/erigon/polygon/heimdall/mock" - heimdallspan "github.com/ledgerwatch/erigon/polygon/heimdall/span" + "github.com/ledgerwatch/erigon/polygon/heimdall" ) func TestHeimdallServer(t *testing.T) { @@ -21,18 +18,18 @@ func TestHeimdallServer(t *testing.T) { ctx := context.Background() ctrl := gomock.NewController(t) - client := heimdallmock.NewMockIHeimdallClient(ctrl) + client := heimdall.NewMockHeimdallClient(ctrl) - events := []*clerk.EventRecordWithTime{ + events := []*heimdall.EventRecordWithTime{ { - EventRecord: clerk.EventRecord{ + EventRecord: heimdall.EventRecord{ ID: 1, ChainID: "80001", }, Time: time.Now(), }, { - EventRecord: clerk.EventRecord{ + EventRecord: heimdall.EventRecord{ ID: 2, ChainID: "80001", }, @@ -41,8 +38,8 @@ func TestHeimdallServer(t *testing.T) { } client.EXPECT().StateSyncEvents(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(events, nil) - span := &heimdallspan.HeimdallSpan{ - Span: heimdallspan.Span{ + span := &heimdall.HeimdallSpan{ + Span: heimdall.Span{ ID: 1, StartBlock: 1000, EndBlock: 2000, @@ -51,7 +48,7 @@ func TestHeimdallServer(t *testing.T) { } client.EXPECT().Span(gomock.Any(), gomock.Any()).AnyTimes().Return(span, nil) - checkpoint1 := &checkpoint.Checkpoint{ + checkpoint1 := &heimdall.Checkpoint{ StartBlock: big.NewInt(1000), EndBlock: big.NewInt(1999), BorChainID: "80001", diff --git a/cmd/devnet/services/polygon/proofgenerator_test.go b/cmd/devnet/services/polygon/proofgenerator_test.go index 4fc3829d86d..79565cd9fb3 100644 --- a/cmd/devnet/services/polygon/proofgenerator_test.go +++ b/cmd/devnet/services/polygon/proofgenerator_test.go @@ -14,8 +14,6 @@ import ( "github.com/ledgerwatch/log/v3" "github.com/pion/randutil" - "github.com/ledgerwatch/erigon/polygon/heimdall/span" - "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon-lib/common" libcommon "github.com/ledgerwatch/erigon-lib/common" @@ -34,8 +32,8 @@ import ( "github.com/ledgerwatch/erigon/crypto" "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/polygon/bor" - "github.com/ledgerwatch/erigon/polygon/bor/contract" "github.com/ledgerwatch/erigon/polygon/bor/valset" + "github.com/ledgerwatch/erigon/polygon/heimdall" "github.com/ledgerwatch/erigon/rlp" "github.com/ledgerwatch/erigon/rpc" "github.com/ledgerwatch/erigon/turbo/jsonrpc" @@ -77,9 +75,9 @@ func newRequestGenerator(sentry *mock.MockSentry, chain *core.ChainPack) (*reque sentry: sentry, bor: bor.NewRo(params.BorDevnetChainConfig, db, reader, &spanner{ - span.NewChainSpanner(contract.ValidatorSet(), params.BorDevnetChainConfig, false, log.Root()), + bor.NewChainSpanner(bor.GenesisContractValidatorSetABI(), params.BorDevnetChainConfig, false, log.Root()), libcommon.Address{}, - span.Span{}}, + heimdall.Span{}}, genesisContract{}, log.Root()), txBlockMap: map[libcommon.Hash]*types.Block{}, }, nil @@ -276,16 +274,16 @@ func (g genesisContract) LastStateId(syscall consensus.SystemCall) (*big.Int, er } type spanner struct { - *span.ChainSpanner + *bor.ChainSpanner validatorAddress libcommon.Address - currentSpan span.Span + currentSpan heimdall.Span } -func (c spanner) GetCurrentSpan(_ consensus.SystemCall) (*span.Span, error) { +func (c spanner) GetCurrentSpan(_ consensus.SystemCall) (*heimdall.Span, error) { return &c.currentSpan, nil } -func (c *spanner) CommitSpan(heimdallSpan span.HeimdallSpan, syscall consensus.SystemCall) error { +func (c *spanner) CommitSpan(heimdallSpan heimdall.HeimdallSpan, syscall consensus.SystemCall) error { c.currentSpan = heimdallSpan.Span return nil } diff --git a/cmd/devnet/services/polygon/statesync.go b/cmd/devnet/services/polygon/statesync.go index cf4bbd1861b..6c79c92c1f2 100644 --- a/cmd/devnet/services/polygon/statesync.go +++ b/cmd/devnet/services/polygon/statesync.go @@ -9,7 +9,7 @@ import ( "github.com/ledgerwatch/erigon/accounts/abi/bind" "github.com/ledgerwatch/erigon/cmd/devnet/contracts" - "github.com/ledgerwatch/erigon/polygon/bor/clerk" + "github.com/ledgerwatch/erigon/polygon/heimdall" ) // Maximum allowed event record data size @@ -19,7 +19,7 @@ const LegacyMaxStateSyncSize = 100000 const MaxStateSyncSize = 30000 type EventRecordWithBlock struct { - clerk.EventRecordWithTime + heimdall.EventRecordWithTime BlockNumber uint64 } @@ -42,7 +42,7 @@ func (h *Heimdall) startStateSyncSubscription() { } } -func (h *Heimdall) StateSyncEvents(ctx context.Context, fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error) { +func (h *Heimdall) StateSyncEvents(ctx context.Context, fromID uint64, to int64) ([]*heimdall.EventRecordWithTime, error) { h.Lock() defer h.Unlock() @@ -79,7 +79,7 @@ func (h *Heimdall) StateSyncEvents(ctx context.Context, fromID uint64, to int64) return events[i].ID < events[j].ID }) - eventsWithTime := make([]*clerk.EventRecordWithTime, len(events)) + eventsWithTime := make([]*heimdall.EventRecordWithTime, len(events)) for i, event := range events { eventsWithTime[i] = &event.EventRecordWithTime } @@ -139,8 +139,8 @@ func (h *Heimdall) handleStateSynced(event *contracts.TestStateSenderStateSynced } h.pendingSyncRecords[syncRecordKey{event.Raw.TxHash, uint64(event.Raw.Index)}] = &EventRecordWithBlock{ - EventRecordWithTime: clerk.EventRecordWithTime{ - EventRecord: clerk.EventRecord{ + EventRecordWithTime: heimdall.EventRecordWithTime{ + EventRecord: heimdall.EventRecord{ ID: event.Id.Uint64(), Contract: event.ContractAddress, Data: event.Data, diff --git a/cmd/integration/commands/stages.go b/cmd/integration/commands/stages.go index ab9851c2d50..18959df6224 100644 --- a/cmd/integration/commands/stages.go +++ b/cmd/integration/commands/stages.go @@ -1669,7 +1669,7 @@ func overrideStorageMode(db kv.RwDB, logger log.Logger) error { }) } -func initConsensusEngine(ctx context.Context, cc *chain2.Config, dir string, db kv.RwDB, blockReader services.FullBlockReader, logger log.Logger) (engine consensus.Engine, heimdallClient heimdall.IHeimdallClient) { +func initConsensusEngine(ctx context.Context, cc *chain2.Config, dir string, db kv.RwDB, blockReader services.FullBlockReader, logger log.Logger) (engine consensus.Engine, heimdallClient heimdall.HeimdallClient) { config := ethconfig.Defaults var consensusConfig interface{} diff --git a/cmd/rpcdaemon/cli/config.go b/cmd/rpcdaemon/cli/config.go index b9c2e342938..9dbdc7c51ce 100644 --- a/cmd/rpcdaemon/cli/config.go +++ b/cmd/rpcdaemon/cli/config.go @@ -60,8 +60,6 @@ import ( "github.com/ledgerwatch/erigon/node/nodecfg" "github.com/ledgerwatch/erigon/polygon/bor" "github.com/ledgerwatch/erigon/polygon/bor/borcfg" - "github.com/ledgerwatch/erigon/polygon/bor/contract" - "github.com/ledgerwatch/erigon/polygon/heimdall/span" "github.com/ledgerwatch/erigon/rpc" "github.com/ledgerwatch/erigon/rpc/rpccfg" "github.com/ledgerwatch/erigon/turbo/debug" @@ -507,8 +505,8 @@ func RemoteServices(ctx context.Context, cfg *httpcfg.HttpCfg, logger log.Logger borConfig := cc.Bor.(*borcfg.BorConfig) engine = bor.NewRo(cc, borKv, blockReader, - span.NewChainSpanner(contract.ValidatorSet(), cc, true, logger), - contract.NewGenesisContractsClient(cc, borConfig.ValidatorContract, borConfig.StateReceiverContract, logger), logger) + bor.NewChainSpanner(bor.GenesisContractValidatorSetABI(), cc, true, logger), + bor.NewGenesisContractsClient(cc, borConfig.ValidatorContract, borConfig.StateReceiverContract, logger), logger) default: engine = ethash.NewFaker() @@ -931,8 +929,8 @@ func (e *remoteConsensusEngine) init(db kv.RoDB, blockReader services.FullBlockR borConfig := cc.Bor.(*borcfg.BorConfig) e.engine = bor.NewRo(cc, borKv, blockReader, - span.NewChainSpanner(contract.ValidatorSet(), cc, true, logger), - contract.NewGenesisContractsClient(cc, borConfig.ValidatorContract, borConfig.StateReceiverContract, logger), logger) + bor.NewChainSpanner(bor.GenesisContractValidatorSetABI(), cc, true, logger), + bor.NewGenesisContractsClient(cc, borConfig.ValidatorContract, borConfig.StateReceiverContract, logger), logger) } else { e.engine = ethash.NewFaker() } diff --git a/eth/backend.go b/eth/backend.go index 12fd0863957..9d24aabaf21 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -511,7 +511,7 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger } else { consensusConfig = &config.Ethash } - var heimdallClient heimdall.IHeimdallClient + var heimdallClient heimdall.HeimdallClient if chainConfig.Bor != nil { if !config.WithoutHeimdall { heimdallClient = heimdall.NewHeimdallClient(config.HeimdallURL, logger) diff --git a/eth/ethconsensusconfig/config.go b/eth/ethconsensusconfig/config.go index 5eb4399f3a1..8050c5161ba 100644 --- a/eth/ethconsensusconfig/config.go +++ b/eth/ethconsensusconfig/config.go @@ -10,9 +10,6 @@ import ( "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon/polygon/bor/borcfg" - "github.com/ledgerwatch/erigon/polygon/heimdall" - "github.com/ledgerwatch/erigon/polygon/heimdall/span" - "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/consensus/aura" @@ -24,12 +21,12 @@ import ( "github.com/ledgerwatch/erigon/node/nodecfg" "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/polygon/bor" - "github.com/ledgerwatch/erigon/polygon/bor/contract" + "github.com/ledgerwatch/erigon/polygon/heimdall" "github.com/ledgerwatch/erigon/turbo/services" ) func CreateConsensusEngine(ctx context.Context, nodeConfig *nodecfg.Config, chainConfig *chain.Config, config interface{}, notify []string, noVerify bool, - heimdallClient heimdall.IHeimdallClient, withoutHeimdall bool, blockReader services.FullBlockReader, readonly bool, + heimdallClient heimdall.HeimdallClient, withoutHeimdall bool, blockReader services.FullBlockReader, readonly bool, logger log.Logger, ) consensus.Engine { var eng consensus.Engine @@ -102,9 +99,9 @@ func CreateConsensusEngine(ctx context.Context, nodeConfig *nodecfg.Config, chai // In order to pass the ethereum transaction tests, we need to set the burn contract which is in the bor config // Then, bor != nil will also be enabled for ethash and clique. Only enable Bor for real if there is a validator contract present. if chainConfig.Bor != nil && consensusCfg.ValidatorContract != "" { - genesisContractsClient := contract.NewGenesisContractsClient(chainConfig, consensusCfg.ValidatorContract, consensusCfg.StateReceiverContract, logger) + genesisContractsClient := bor.NewGenesisContractsClient(chainConfig, consensusCfg.ValidatorContract, consensusCfg.StateReceiverContract, logger) - spanner := span.NewChainSpanner(contract.ValidatorSet(), chainConfig, withoutHeimdall, logger) + spanner := bor.NewChainSpanner(bor.GenesisContractValidatorSetABI(), chainConfig, withoutHeimdall, logger) var err error var db kv.RwDB diff --git a/eth/stagedsync/bor_heimdall_shared.go b/eth/stagedsync/bor_heimdall_shared.go index 323d443eada..cbb213f775c 100644 --- a/eth/stagedsync/bor_heimdall_shared.go +++ b/eth/stagedsync/bor_heimdall_shared.go @@ -15,8 +15,8 @@ import ( "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon/core/types" + "github.com/ledgerwatch/erigon/polygon/bor" "github.com/ledgerwatch/erigon/polygon/heimdall" - "github.com/ledgerwatch/erigon/polygon/heimdall/span" "github.com/ledgerwatch/erigon/rlp" "github.com/ledgerwatch/erigon/turbo/services" ) @@ -92,7 +92,7 @@ func FetchSpanZeroForMiningIfNeeded( ctx context.Context, db kv.RwDB, blockReader services.FullBlockReader, - heimdallClient heimdall.IHeimdallClient, + heimdallClient heimdall.HeimdallClient, logger log.Logger, ) error { return db.Update(ctx, func(tx kv.RwTx) error { @@ -120,8 +120,8 @@ func fetchRequiredHeimdallSpansIfNeeded( logPrefix string, logger log.Logger, ) (uint64, error) { - requiredSpanID := span.IDAt(toBlockNum) - if span.BlockInLastSprintOfSpan(toBlockNum, cfg.borConfig) { + requiredSpanID := bor.SpanIDAt(toBlockNum) + if bor.IsBlockInLastSprintOfSpan(toBlockNum, cfg.borConfig) { requiredSpanID++ } @@ -153,7 +153,7 @@ func fetchAndWriteHeimdallSpan( ctx context.Context, spanID uint64, tx kv.RwTx, - heimdallClient heimdall.IHeimdallClient, + heimdallClient heimdall.HeimdallClient, logPrefix string, logger log.Logger, ) (uint64, error) { diff --git a/eth/stagedsync/stage_bor_heimdall.go b/eth/stagedsync/stage_bor_heimdall.go index c7edacb36ff..88199f74774 100644 --- a/eth/stagedsync/stage_bor_heimdall.go +++ b/eth/stagedsync/stage_bor_heimdall.go @@ -25,12 +25,10 @@ import ( "github.com/ledgerwatch/erigon/eth/stagedsync/stages" "github.com/ledgerwatch/erigon/polygon/bor" "github.com/ledgerwatch/erigon/polygon/bor/borcfg" - "github.com/ledgerwatch/erigon/polygon/bor/contract" - "github.com/ledgerwatch/erigon/polygon/bor/finality/generics" + "github.com/ledgerwatch/erigon/polygon/bor/finality" "github.com/ledgerwatch/erigon/polygon/bor/finality/whitelist" "github.com/ledgerwatch/erigon/polygon/bor/valset" "github.com/ledgerwatch/erigon/polygon/heimdall" - "github.com/ledgerwatch/erigon/polygon/heimdall/span" "github.com/ledgerwatch/erigon/turbo/services" "github.com/ledgerwatch/erigon/turbo/stages/headerdownload" ) @@ -49,7 +47,7 @@ type BorHeimdallCfg struct { miningState MiningState chainConfig chain.Config borConfig *borcfg.BorConfig - heimdallClient heimdall.IHeimdallClient + heimdallClient heimdall.HeimdallClient blockReader services.FullBlockReader hd *headerdownload.HeaderDownload penalize func(context.Context, []headerdownload.PenaltyItem) @@ -64,7 +62,7 @@ func StageBorHeimdallCfg( snapDb kv.RwDB, miningState MiningState, chainConfig chain.Config, - heimdallClient heimdall.IHeimdallClient, + heimdallClient heimdall.HeimdallClient, blockReader services.FullBlockReader, hd *headerdownload.HeaderDownload, penalize func(context.Context, []headerdownload.PenaltyItem), @@ -87,7 +85,7 @@ func StageBorHeimdallCfg( blockReader: blockReader, hd: hd, penalize: penalize, - stateReceiverABI: contract.StateReceiver(), + stateReceiverABI: bor.GenesisContractStateReceiverABI(), loopBreakCheck: loopBreakCheck, recents: recents, signatures: signatures, @@ -126,7 +124,7 @@ func BorHeimdallForward( } whitelistService := whitelist.GetWhitelistingService() - if unwindPointPtr := generics.BorMilestoneRewind.Load(); unwindPointPtr != nil && *unwindPointPtr != 0 { + if unwindPointPtr := finality.BorMilestoneRewind.Load(); unwindPointPtr != nil && *unwindPointPtr != 0 { unwindPoint := *unwindPointPtr if whitelistService != nil && unwindPoint < headNumber { header, err := cfg.blockReader.HeaderByNumber(ctx, tx, headNumber) @@ -147,7 +145,7 @@ func BorHeimdallForward( dataflow.HeaderDownloadStates.AddChange(headNumber, dataflow.HeaderInvalidated) s.state.UnwindTo(unwindPoint, ForkReset(hash)) var reset uint64 = 0 - generics.BorMilestoneRewind.Store(&reset) + finality.BorMilestoneRewind.Store(&reset) return fmt.Errorf("verification failed for header %d: %x", headNumber, header.Hash()) } } @@ -428,7 +426,7 @@ func initValidatorSets( tx kv.RwTx, blockReader services.FullBlockReader, config *borcfg.BorConfig, - heimdallClient heimdall.IHeimdallClient, + heimdallClient heimdall.HeimdallClient, chain consensus.ChainHeaderReader, blockNum uint64, recents *lru.ARCCache[libcommon.Hash, *bor.Snapshot], @@ -471,7 +469,7 @@ func initValidatorSets( return nil, fmt.Errorf("zero span not found") } - var zeroSpan span.HeimdallSpan + var zeroSpan heimdall.HeimdallSpan if err = json.Unmarshal(zeroSpanBytes, &zeroSpan); err != nil { return nil, err } @@ -540,9 +538,9 @@ func checkBorHeaderExtraDataIfRequired(chr consensus.ChainHeaderReader, header * } func checkBorHeaderExtraData(chr consensus.ChainHeaderReader, header *types.Header, cfg *borcfg.BorConfig) error { - spanID := span.IDAt(header.Number.Uint64() + 1) + spanID := bor.SpanIDAt(header.Number.Uint64() + 1) spanBytes := chr.BorSpan(spanID) - var sp span.HeimdallSpan + var sp heimdall.HeimdallSpan if err := json.Unmarshal(spanBytes, &sp); err != nil { return err } @@ -629,7 +627,7 @@ func BorHeimdallUnwind(u *UnwindState, ctx context.Context, s *StageState, tx kv return err } defer spanCursor.Close() - lastSpanToKeep := span.IDAt(u.UnwindPoint) + lastSpanToKeep := bor.SpanIDAt(u.UnwindPoint) var spanIdBytes [8]byte binary.BigEndian.PutUint64(spanIdBytes[:], lastSpanToKeep+1) for k, _, err = spanCursor.Seek(spanIdBytes[:]); err == nil && k != nil; k, _, err = spanCursor.Next() { diff --git a/eth/stagedsync/stagedsynctest/harness.go b/eth/stagedsync/stagedsynctest/harness.go index a2b6169999c..ea203b65fa0 100644 --- a/eth/stagedsync/stagedsynctest/harness.go +++ b/eth/stagedsync/stagedsynctest/harness.go @@ -12,15 +12,13 @@ import ( "time" "github.com/ledgerwatch/erigon/polygon/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/heimdall" "github.com/golang/mock/gomock" "github.com/holiman/uint256" "github.com/ledgerwatch/log/v3" "github.com/stretchr/testify/require" - heimdallmock "github.com/ledgerwatch/erigon/polygon/heimdall/mock" - "github.com/ledgerwatch/erigon/polygon/heimdall/span" - "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" @@ -36,9 +34,6 @@ import ( "github.com/ledgerwatch/erigon/eth/stagedsync" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" "github.com/ledgerwatch/erigon/polygon/bor" - "github.com/ledgerwatch/erigon/polygon/bor/clerk" - "github.com/ledgerwatch/erigon/polygon/bor/contract" - bormock "github.com/ledgerwatch/erigon/polygon/bor/mock" "github.com/ledgerwatch/erigon/polygon/bor/valset" "github.com/ledgerwatch/erigon/turbo/services" "github.com/ledgerwatch/erigon/turbo/stages/mock" @@ -53,7 +48,7 @@ func InitHarness(ctx context.Context, t *testing.T, cfg HarnessCfg) Harness { blockReader := m.BlockReader borConsensusDB := memdb.NewTestDB(t) ctrl := gomock.NewController(t) - heimdallClient := heimdallmock.NewMockIHeimdallClient(ctrl) + heimdallClient := heimdall.NewMockHeimdallClient(ctrl) bhCfg := stagedsync.StageBorHeimdallCfg( chainDataDB, borConsensusDB, @@ -102,7 +97,7 @@ func InitHarness(ctx context.Context, t *testing.T, cfg HarnessCfg) Harness { heimdallClient: heimdallClient, heimdallProducersOverride: cfg.GetOrCreateDefaultHeimdallProducersOverride(), sealedHeaders: make(map[uint64]*types.Header), - borSpanner: bormock.NewMockSpanner(ctrl), + borSpanner: bor.NewMockSpanner(ctrl), validatorAddress: validatorAddress, validatorKey: validatorKey, genesisInitData: genesisInit, @@ -151,13 +146,13 @@ type Harness struct { stateSyncStages []*stagedsync.Stage stateSync *stagedsync.Sync bhCfg stagedsync.BorHeimdallCfg - heimdallClient *heimdallmock.MockIHeimdallClient - heimdallNextMockSpan *span.HeimdallSpan + heimdallClient *heimdall.MockHeimdallClient + heimdallNextMockSpan *heimdall.HeimdallSpan heimdallLastEventID uint64 heimdallLastEventHeaderNum uint64 heimdallProducersOverride map[uint64][]valset.Validator // spanID -> selected producers override sealedHeaders map[uint64]*types.Header - borSpanner *bormock.MockSpanner + borSpanner *bor.MockSpanner validatorAddress libcommon.Address validatorKey *ecdsa.PrivateKey genesisInitData *genesisInitData @@ -222,7 +217,7 @@ func (h *Harness) RunStageForwardWithReturnError(t *testing.T, id stages.SyncSta return stage.Forward(true, false, stageState, h.stateSync, wrap.TxContainer{}, h.logger) } -func (h *Harness) ReadSpansFromDB(ctx context.Context) (spans []*span.HeimdallSpan, err error) { +func (h *Harness) ReadSpansFromDB(ctx context.Context) (spans []*heimdall.HeimdallSpan, err error) { err = h.chainDataDB.View(ctx, func(tx kv.Tx) error { spanIter, err := tx.Range(kv.BorSpans, nil, nil) if err != nil { @@ -236,7 +231,7 @@ func (h *Harness) ReadSpansFromDB(ctx context.Context) (spans []*span.HeimdallSp } spanKey := binary.BigEndian.Uint64(keyBytes) - var heimdallSpan span.HeimdallSpan + var heimdallSpan heimdall.HeimdallSpan if err = json.Unmarshal(spanBytes, &heimdallSpan); err != nil { return err } @@ -425,7 +420,7 @@ func (h *Harness) seal(t *testing.T, chr consensus.ChainHeaderReader, eng consen func (h *Harness) consensusEngine(t *testing.T, cfg HarnessCfg) consensus.Engine { if h.chainConfig.Bor != nil { - genesisContracts := contract.NewGenesisContractsClient( + genesisContracts := bor.NewGenesisContractsClient( h.chainConfig, h.borConfig.ValidatorContract, h.borConfig.StateReceiverContract, @@ -517,8 +512,8 @@ func (h *Harness) setHeimdallNextMockSpan() { selectedProducers[i] = *validators[i] } - h.heimdallNextMockSpan = &span.HeimdallSpan{ - Span: span.Span{ + h.heimdallNextMockSpan = &heimdall.HeimdallSpan{ + Span: heimdall.Span{ ID: 0, StartBlock: 0, EndBlock: 255, @@ -553,10 +548,10 @@ func (h *Harness) mockHeimdallClient() { h.heimdallClient. EXPECT(). Span(gomock.Any(), gomock.Any()). - DoAndReturn(func(ctx context.Context, spanID uint64) (*span.HeimdallSpan, error) { + DoAndReturn(func(ctx context.Context, spanID uint64) (*heimdall.HeimdallSpan, error) { res := h.heimdallNextMockSpan - h.heimdallNextMockSpan = &span.HeimdallSpan{ - Span: span.Span{ + h.heimdallNextMockSpan = &heimdall.HeimdallSpan{ + Span: heimdall.Span{ ID: res.ID + 1, StartBlock: res.EndBlock + 1, EndBlock: res.EndBlock + 6400, @@ -576,12 +571,12 @@ func (h *Harness) mockHeimdallClient() { h.heimdallClient. EXPECT(). StateSyncEvents(gomock.Any(), gomock.Any(), gomock.Any()). - DoAndReturn(func(_ context.Context, _ uint64, _ int64) ([]*clerk.EventRecordWithTime, error) { + DoAndReturn(func(_ context.Context, _ uint64, _ int64) ([]*heimdall.EventRecordWithTime, error) { h.heimdallLastEventID++ h.heimdallLastEventHeaderNum += h.borConfig.CalculateSprintLength(h.heimdallLastEventHeaderNum) stateSyncDelay := h.borConfig.CalculateStateSyncDelay(h.heimdallLastEventHeaderNum) - newEvent := clerk.EventRecordWithTime{ - EventRecord: clerk.EventRecord{ + newEvent := heimdall.EventRecordWithTime{ + EventRecord: heimdall.EventRecord{ ID: h.heimdallLastEventID, ChainID: h.chainConfig.ChainID.String(), }, @@ -589,7 +584,7 @@ func (h *Harness) mockHeimdallClient() { } // 1 per sprint - return []*clerk.EventRecordWithTime{&newEvent}, nil + return []*heimdall.EventRecordWithTime{&newEvent}, nil }). AnyTimes() } diff --git a/polygon/bor/abi/interface.go b/polygon/bor/abi/interface.go deleted file mode 100644 index bb05bf0b23f..00000000000 --- a/polygon/bor/abi/interface.go +++ /dev/null @@ -1,6 +0,0 @@ -package abi - -type ABI interface { - Pack(name string, args ...interface{}) ([]byte, error) - UnpackIntoInterface(v interface{}, name string, data []byte) error -} diff --git a/polygon/bor/bor.go b/polygon/bor/bor.go index 90fb15965e3..d37f9888004 100644 --- a/polygon/bor/bor.go +++ b/polygon/bor/bor.go @@ -22,9 +22,6 @@ import ( "golang.org/x/crypto/sha3" "golang.org/x/sync/errgroup" - "github.com/ledgerwatch/erigon/polygon/heimdall" - "github.com/ledgerwatch/erigon/polygon/heimdall/span" - "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/length" @@ -46,6 +43,7 @@ import ( "github.com/ledgerwatch/erigon/polygon/bor/finality/whitelist" "github.com/ledgerwatch/erigon/polygon/bor/statefull" "github.com/ledgerwatch/erigon/polygon/bor/valset" + "github.com/ledgerwatch/erigon/polygon/heimdall" "github.com/ledgerwatch/erigon/rlp" "github.com/ledgerwatch/erigon/rpc" "github.com/ledgerwatch/erigon/turbo/services" @@ -297,8 +295,8 @@ type Bor struct { execCtx context.Context // context of caller execution stage spanner Spanner - GenesisContractsClient GenesisContract - HeimdallClient heimdall.IHeimdallClient + GenesisContractsClient GenesisContracts + HeimdallClient heimdall.HeimdallClient // scope event.SubscriptionScope // The fields below are for testing only @@ -323,8 +321,8 @@ func New( db kv.RwDB, blockReader services.FullBlockReader, spanner Spanner, - heimdallClient heimdall.IHeimdallClient, - genesisContracts GenesisContract, + heimdallClient heimdall.HeimdallClient, + genesisContracts GenesisContracts, logger log.Logger, ) *Bor { // get bor config @@ -394,7 +392,7 @@ func (w rwWrapper) BeginRwNosync(ctx context.Context) (kv.RwTx, error) { // This is used by the rpcdaemon and tests which need read only access to the provided data services func NewRo(chainConfig *chain.Config, db kv.RoDB, blockReader services.FullBlockReader, spanner Spanner, - genesisContracts GenesisContract, logger log.Logger) *Bor { + genesisContracts GenesisContracts, logger log.Logger) *Bor { // get bor config borConfig := chainConfig.Bor.(*borcfg.BorConfig) @@ -890,7 +888,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header, s // where it fetches producers internally. As we fetch data from span // in Erigon, use directly the `GetCurrentProducers` function. if isSprintStart(number+1, c.config.CalculateSprintLength(number)) { - spanID := span.IDAt(number + 1) + spanID := SpanIDAt(number + 1) newValidators, err := c.spanner.GetCurrentProducers(spanID, c.authorizedSigner.Load().signer, chain) if err != nil { return errUnknownValidators @@ -1338,7 +1336,7 @@ func (c *Bor) fetchAndCommitSpan( chain statefull.ChainContext, syscall consensus.SystemCall, ) error { - var heimdallSpan span.HeimdallSpan + var heimdallSpan heimdall.HeimdallSpan if c.HeimdallClient == nil { // fixme: move to a new mock or fake and remove c.HeimdallClient completely @@ -1457,7 +1455,7 @@ func (c *Bor) CommitStates( return nil } -func (c *Bor) SetHeimdallClient(h heimdall.IHeimdallClient) { +func (c *Bor) SetHeimdallClient(h heimdall.HeimdallClient) { c.HeimdallClient = h } @@ -1471,7 +1469,7 @@ func (c *Bor) getNextHeimdallSpanForTest( header *types.Header, chain statefull.ChainContext, syscall consensus.SystemCall, -) (*span.HeimdallSpan, error) { +) (*heimdall.HeimdallSpan, error) { headerNumber := header.Number.Uint64() spanBor, err := c.spanner.GetCurrentSpan(syscall) @@ -1500,7 +1498,7 @@ func (c *Bor) getNextHeimdallSpanForTest( selectedProducers[i] = *v } - heimdallSpan := &span.HeimdallSpan{ + heimdallSpan := &heimdall.HeimdallSpan{ Span: *spanBor, ValidatorSet: *snap.ValidatorSet, SelectedProducers: selectedProducers, diff --git a/polygon/bor/bor_test.go b/polygon/bor/bor_test.go index 0c9f3c6d3f5..ee3586d734b 100644 --- a/polygon/bor/bor_test.go +++ b/polygon/bor/bor_test.go @@ -8,13 +8,10 @@ import ( "testing" "github.com/ledgerwatch/erigon/polygon/bor/borcfg" + "github.com/ledgerwatch/erigon/polygon/heimdall" "github.com/ledgerwatch/log/v3" - "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" - "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" - "github.com/ledgerwatch/erigon/polygon/heimdall/span" - "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon-lib/common" libcommon "github.com/ledgerwatch/erigon-lib/common" @@ -28,19 +25,17 @@ import ( "github.com/ledgerwatch/erigon/ethdb/prune" "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/polygon/bor" - "github.com/ledgerwatch/erigon/polygon/bor/clerk" - "github.com/ledgerwatch/erigon/polygon/bor/contract" "github.com/ledgerwatch/erigon/polygon/bor/valset" "github.com/ledgerwatch/erigon/rlp" "github.com/ledgerwatch/erigon/turbo/stages/mock" ) type test_heimdall struct { - currentSpan *span.HeimdallSpan + currentSpan *heimdall.HeimdallSpan chainConfig *chain.Config borConfig *borcfg.BorConfig validatorSet *valset.ValidatorSet - spans map[uint64]*span.HeimdallSpan + spans map[uint64]*heimdall.HeimdallSpan } func newTestHeimdall(chainConfig *chain.Config) *test_heimdall { @@ -49,7 +44,7 @@ func newTestHeimdall(chainConfig *chain.Config) *test_heimdall { chainConfig: chainConfig, borConfig: chainConfig.Bor.(*borcfg.BorConfig), validatorSet: nil, - spans: map[uint64]*span.HeimdallSpan{}, + spans: map[uint64]*heimdall.HeimdallSpan{}, } } @@ -57,18 +52,18 @@ func (h *test_heimdall) BorConfig() *borcfg.BorConfig { return h.borConfig } -func (h test_heimdall) StateSyncEvents(ctx context.Context, fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error) { +func (h test_heimdall) StateSyncEvents(ctx context.Context, fromID uint64, to int64) ([]*heimdall.EventRecordWithTime, error) { return nil, nil } -func (h *test_heimdall) Span(ctx context.Context, spanID uint64) (*span.HeimdallSpan, error) { +func (h *test_heimdall) Span(ctx context.Context, spanID uint64) (*heimdall.HeimdallSpan, error) { if span, ok := h.spans[spanID]; ok { h.currentSpan = span return span, nil } - var nextSpan = span.Span{ + var nextSpan = heimdall.Span{ ID: spanID, } @@ -92,7 +87,7 @@ func (h *test_heimdall) Span(ctx context.Context, spanID uint64) (*span.Heimdall selectedProducers[i] = *v } - h.currentSpan = &span.HeimdallSpan{ + h.currentSpan = &heimdall.HeimdallSpan{ Span: nextSpan, ValidatorSet: *h.validatorSet, SelectedProducers: selectedProducers, @@ -112,7 +107,7 @@ func (h test_heimdall) currentSprintLength() int { return int(h.borConfig.CalculateSprintLength(256)) } -func (h test_heimdall) FetchCheckpoint(ctx context.Context, number int64) (*checkpoint.Checkpoint, error) { +func (h test_heimdall) FetchCheckpoint(ctx context.Context, number int64) (*heimdall.Checkpoint, error) { return nil, fmt.Errorf("TODO") } @@ -120,7 +115,7 @@ func (h test_heimdall) FetchCheckpointCount(ctx context.Context) (int64, error) return 0, fmt.Errorf("TODO") } -func (h test_heimdall) FetchMilestone(ctx context.Context, number int64) (*milestone.Milestone, error) { +func (h test_heimdall) FetchMilestone(ctx context.Context, number int64) (*heimdall.Milestone, error) { return nil, fmt.Errorf("TODO") } @@ -196,16 +191,16 @@ func (r headerReader) BorSpan(spanId uint64) []byte { } type spanner struct { - *span.ChainSpanner + *bor.ChainSpanner validatorAddress common.Address - currentSpan span.Span + currentSpan heimdall.Span } -func (c spanner) GetCurrentSpan(_ consensus.SystemCall) (*span.Span, error) { +func (c spanner) GetCurrentSpan(_ consensus.SystemCall) (*heimdall.Span, error) { return &c.currentSpan, nil } -func (c *spanner) CommitSpan(heimdallSpan span.HeimdallSpan, syscall consensus.SystemCall) error { +func (c *spanner) CommitSpan(heimdallSpan heimdall.HeimdallSpan, syscall consensus.SystemCall) error { c.currentSpan = heimdallSpan.Span return nil } @@ -278,6 +273,8 @@ func (v validator) verifyBlocks(blocks []*types.Block) error { return nil } +type heimdallSpan = heimdall.Span + func newValidator(t *testing.T, heimdall *test_heimdall, blocks map[uint64]*types.Block) validator { logger := log.Root() @@ -287,7 +284,11 @@ func newValidator(t *testing.T, heimdall *test_heimdall, blocks map[uint64]*type heimdall.chainConfig, memdb.New(""), nil, /* blockReader */ - &spanner{span.NewChainSpanner(contract.ValidatorSet(), heimdall.chainConfig, false, logger), validatorAddress, span.Span{}}, + &spanner{ + ChainSpanner: bor.NewChainSpanner(bor.GenesisContractValidatorSetABI(), heimdall.chainConfig, false, logger), + validatorAddress: validatorAddress, + currentSpan: heimdallSpan{}, + }, heimdall, test_genesisContract{}, logger, diff --git a/polygon/bor/contract/client.go b/polygon/bor/contract/client.go deleted file mode 100644 index 09f2ba5a340..00000000000 --- a/polygon/bor/contract/client.go +++ /dev/null @@ -1,82 +0,0 @@ -package contract - -import ( - "math/big" - "strings" - - "github.com/ledgerwatch/erigon-lib/chain" - libcommon "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon/accounts/abi" - "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/rlp" - "github.com/ledgerwatch/log/v3" -) - -var ( - vABI, _ = abi.JSON(strings.NewReader(ValidatorsetABI)) - sABI, _ = abi.JSON(strings.NewReader(StateReceiverABI)) -) - -func ValidatorSet() abi.ABI { - return vABI -} - -func StateReceiver() abi.ABI { - return sABI -} - -type GenesisContractsClient struct { - validatorSetABI abi.ABI - stateReceiverABI abi.ABI - ValidatorContract libcommon.Address - StateReceiverContract libcommon.Address - chainConfig *chain.Config - logger log.Logger -} - -const ( - ValidatorsetABI = `[{"constant":true,"inputs":[],"name":"SPRINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"CHAIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FIRST_END_BLOCK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"producers","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ROUND_TYPE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"BOR_ID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spanNumbers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"VOTE_TYPE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"validators","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spans","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"startBlock","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"endBlock","type":"uint256"}],"name":"NewSpan","type":"event"},{"constant":true,"inputs":[],"name":"currentSprint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNextSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"getSpanByBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentSpanNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getValidatorsTotalStakeBySpan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getProducersTotalStakeBySpan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"getValidatorBySigner","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct BorValidatorSet.Validator","name":"result","type":"tuple"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"isValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"isProducer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isCurrentValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isCurrentProducer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"getBorValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitialValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newSpan","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"},{"internalType":"bytes","name":"validatorBytes","type":"bytes"},{"internalType":"bytes","name":"producerBytes","type":"bytes"}],"name":"commitSpan","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"bytes","name":"sigs","type":"bytes"}],"name":"getStakePowerBySigs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"bytes32","name":"leaf","type":"bytes32"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"checkMembership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"d","type":"bytes32"}],"name":"leafNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"left","type":"bytes32"},{"internalType":"bytes32","name":"right","type":"bytes32"}],"name":"innerNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"}]` - StateReceiverABI = `[{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastStateId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"syncTime","type":"uint256"},{"internalType":"bytes","name":"recordBytes","type":"bytes"}],"name":"commitState","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]` -) - -func NewGenesisContractsClient( - chainConfig *chain.Config, - validatorContract, - stateReceiverContract string, - logger log.Logger, -) *GenesisContractsClient { - return &GenesisContractsClient{ - validatorSetABI: ValidatorSet(), - stateReceiverABI: StateReceiver(), - ValidatorContract: libcommon.HexToAddress(validatorContract), - StateReceiverContract: libcommon.HexToAddress(stateReceiverContract), - chainConfig: chainConfig, - logger: logger, - } -} - -func (gc *GenesisContractsClient) CommitState(event rlp.RawValue, syscall consensus.SystemCall) error { - _, err := syscall(gc.StateReceiverContract, event) - return err -} - -func (gc *GenesisContractsClient) LastStateId(syscall consensus.SystemCall) (*big.Int, error) { - const method = "lastStateId" - - data, err := gc.stateReceiverABI.Pack(method) - if err != nil { - gc.logger.Error("[bor] Unable to pack tx for LastStateId", "err", err) - return nil, err - } - - result, err := syscall(gc.StateReceiverContract, data) - if err != nil { - return nil, err - } - - var ret = new(*big.Int) - if err := gc.stateReceiverABI.UnpackIntoInterface(ret, method, result); err != nil { - return nil, err - } - return *ret, nil -} diff --git a/polygon/bor/errors.go b/polygon/bor/errors.go index 1ee6fd9bd06..7d57658ff8d 100644 --- a/polygon/bor/errors.go +++ b/polygon/bor/errors.go @@ -2,9 +2,6 @@ package bor import ( "fmt" - "time" - - "github.com/ledgerwatch/erigon/polygon/bor/clerk" ) type MaxCheckpointLengthExceededError struct { @@ -69,20 +66,3 @@ func (e *WrongDifficultyError) Error() string { e.Signer, ) } - -type InvalidStateReceivedError struct { - Number uint64 - LastStateID uint64 - To *time.Time - Event *clerk.EventRecordWithTime -} - -func (e *InvalidStateReceivedError) Error() string { - return fmt.Sprintf( - "Received invalid event %v at block %d. Requested events until %s. Last state id was %d", - e.Event, - e.Number, - e.To.Format(time.RFC3339), - e.LastStateID, - ) -} diff --git a/polygon/bor/finality/bor_verifier.go b/polygon/bor/finality/bor_verifier.go index 1cbb566e0dc..9a6da3203e6 100644 --- a/polygon/bor/finality/bor_verifier.go +++ b/polygon/bor/finality/bor_verifier.go @@ -10,7 +10,6 @@ import ( "github.com/ledgerwatch/erigon-lib/metrics" "github.com/ledgerwatch/erigon/core/rawdb" - "github.com/ledgerwatch/erigon/polygon/bor/finality/generics" "github.com/ledgerwatch/erigon/polygon/bor/finality/whitelist" ) @@ -161,5 +160,5 @@ func rewindBack(head uint64, rewindTo uint64) { // Chain cannot be rewinded from this routine // hence we are using a shared variable - generics.BorMilestoneRewind.Store(&rewindTo) + BorMilestoneRewind.Store(&rewindTo) } diff --git a/polygon/bor/finality/generics/generics.go b/polygon/bor/finality/generics/generics.go index d54b26fbbda..7185ee893da 100644 --- a/polygon/bor/finality/generics/generics.go +++ b/polygon/bor/finality/generics/generics.go @@ -1,8 +1,6 @@ package generics import ( - "sync/atomic" - libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/core/types" ) @@ -11,11 +9,6 @@ func Empty[T any]() (t T) { return } -// BorMilestoneRewind is used as a flag/variable -// Flag: if equals 0, no rewind according to bor whitelisting service -// Variable: if not equals 0, rewind chain back to BorMilestoneRewind -var BorMilestoneRewind atomic.Pointer[uint64] - type Response struct { Headers []*types.Header Hashes []libcommon.Hash diff --git a/polygon/bor/finality/milestone_rewind.go b/polygon/bor/finality/milestone_rewind.go new file mode 100644 index 00000000000..772d91d9845 --- /dev/null +++ b/polygon/bor/finality/milestone_rewind.go @@ -0,0 +1,12 @@ +package finality + +import "sync/atomic" + +// BorMilestoneRewind is used as a flag/variable +// Flag: if equals 0, no rewind according to bor whitelisting service +// Variable: if not equals 0, rewind chain back to BorMilestoneRewind +var BorMilestoneRewind atomic.Pointer[uint64] + +func IsMilestoneRewindPending() bool { + return BorMilestoneRewind.Load() != nil && *BorMilestoneRewind.Load() != 0 +} diff --git a/polygon/bor/finality/whitelist.go b/polygon/bor/finality/whitelist.go index 60a2731eb1b..97584eb6f09 100644 --- a/polygon/bor/finality/whitelist.go +++ b/polygon/bor/finality/whitelist.go @@ -17,7 +17,7 @@ import ( ) type config struct { - heimdall heimdall.IHeimdallClient + heimdall heimdall.HeimdallClient borDB kv.RwDB chainDB kv.RwDB blockReader services.BlockReader @@ -30,7 +30,7 @@ type BorAPI interface { GetRootHash(start uint64, end uint64) (string, error) } -func Whitelist(heimdall heimdall.IHeimdallClient, borDB kv.RwDB, chainDB kv.RwDB, blockReader services.BlockReader, logger log.Logger, borAPI BorAPI, closeCh chan struct{}) { +func Whitelist(heimdall heimdall.HeimdallClient, borDB kv.RwDB, chainDB kv.RwDB, blockReader services.BlockReader, logger log.Logger, borAPI BorAPI, closeCh chan struct{}) { if !flags.Milestone { return } @@ -96,7 +96,7 @@ func startNoAckMilestoneByIDService(config *config) { RetryHeimdallHandler(handleNoAckMilestoneByID, config, tickerDuration, noAckMilestoneTimeout, fnName) } -type heimdallHandler func(ctx context.Context, heimdallClient heimdall.IHeimdallClient, config *config) error +type heimdallHandler func(ctx context.Context, heimdallClient heimdall.HeimdallClient, config *config) error func RetryHeimdallHandler(fn heimdallHandler, config *config, tickerDuration time.Duration, timeout time.Duration, fnName string) { retryHeimdallHandler(fn, config, tickerDuration, timeout, fnName) @@ -159,7 +159,7 @@ func retryHeimdallHandler(fn heimdallHandler, config *config, tickerDuration tim } // handleWhitelistCheckpoint handles the checkpoint whitelist mechanism. -func handleWhitelistCheckpoint(ctx context.Context, heimdallClient heimdall.IHeimdallClient, config *config) error { +func handleWhitelistCheckpoint(ctx context.Context, heimdallClient heimdall.HeimdallClient, config *config) error { service := whitelist.GetWhitelistingService() // Create a new bor verifier, which will be used to verify checkpoints and milestones @@ -179,7 +179,7 @@ func handleWhitelistCheckpoint(ctx context.Context, heimdallClient heimdall.IHei } // handleMilestone handles the milestone mechanism. -func handleMilestone(ctx context.Context, heimdallClient heimdall.IHeimdallClient, config *config) error { +func handleMilestone(ctx context.Context, heimdallClient heimdall.HeimdallClient, config *config) error { service := whitelist.GetWhitelistingService() // Create a new bor verifier, which will be used to verify checkpoints and milestones @@ -207,7 +207,7 @@ func handleMilestone(ctx context.Context, heimdallClient heimdall.IHeimdallClien return nil } -func handleNoAckMilestone(ctx context.Context, heimdallClient heimdall.IHeimdallClient, config *config) error { +func handleNoAckMilestone(ctx context.Context, heimdallClient heimdall.HeimdallClient, config *config) error { service := whitelist.GetWhitelistingService() milestoneID, err := fetchNoAckMilestone(ctx, heimdallClient, config.logger) @@ -224,7 +224,7 @@ func handleNoAckMilestone(ctx context.Context, heimdallClient heimdall.IHeimdall return nil } -func handleNoAckMilestoneByID(ctx context.Context, heimdallClient heimdall.IHeimdallClient, config *config) error { +func handleNoAckMilestoneByID(ctx context.Context, heimdallClient heimdall.HeimdallClient, config *config) error { service := whitelist.GetWhitelistingService() milestoneIDs := service.GetMilestoneIDsList() diff --git a/polygon/bor/finality/whitelist_helpers.go b/polygon/bor/finality/whitelist_helpers.go index b5d28cad084..f680c0d0fa7 100644 --- a/polygon/bor/finality/whitelist_helpers.go +++ b/polygon/bor/finality/whitelist_helpers.go @@ -26,7 +26,7 @@ var ( // fetchWhitelistCheckpoint fetches the latest checkpoint from it's local heimdall // and verifies the data against bor data. -func fetchWhitelistCheckpoint(ctx context.Context, heimdallClient heimdall.IHeimdallClient, verifier *borVerifier, config *config) (uint64, common.Hash, error) { +func fetchWhitelistCheckpoint(ctx context.Context, heimdallClient heimdall.HeimdallClient, verifier *borVerifier, config *config) (uint64, common.Hash, error) { var ( blockNum uint64 blockHash common.Hash @@ -66,7 +66,7 @@ func fetchWhitelistCheckpoint(ctx context.Context, heimdallClient heimdall.IHeim // fetchWhitelistMilestone fetches the latest milestone from it's local heimdall // and verifies the data against bor data. -func fetchWhitelistMilestone(ctx context.Context, heimdallClient heimdall.IHeimdallClient, verifier *borVerifier, config *config) (uint64, common.Hash, error) { +func fetchWhitelistMilestone(ctx context.Context, heimdallClient heimdall.HeimdallClient, verifier *borVerifier, config *config) (uint64, common.Hash, error) { var ( num uint64 hash common.Hash @@ -101,7 +101,7 @@ func fetchWhitelistMilestone(ctx context.Context, heimdallClient heimdall.IHeimd return num, hash, nil } -func fetchNoAckMilestone(ctx context.Context, heimdallClient heimdall.IHeimdallClient, logger log.Logger) (string, error) { +func fetchNoAckMilestone(ctx context.Context, heimdallClient heimdall.HeimdallClient, logger log.Logger) (string, error) { var ( milestoneID string ) @@ -120,7 +120,7 @@ func fetchNoAckMilestone(ctx context.Context, heimdallClient heimdall.IHeimdallC return milestoneID, nil } -func fetchNoAckMilestoneByID(ctx context.Context, heimdallClient heimdall.IHeimdallClient, milestoneID string, logger log.Logger) error { +func fetchNoAckMilestoneByID(ctx context.Context, heimdallClient heimdall.HeimdallClient, milestoneID string, logger log.Logger) error { err := heimdallClient.FetchNoAckMilestone(ctx, milestoneID) if errors.Is(err, heimdall.ErrServiceUnavailable) { logger.Debug("[bor.heimdall] Failed to fetch no-ack milestone by ID", "milestoneID", milestoneID, "err", err) diff --git a/polygon/bor/genesis_contract.go b/polygon/bor/genesis_contract.go deleted file mode 100644 index 7a232733bf2..00000000000 --- a/polygon/bor/genesis_contract.go +++ /dev/null @@ -1,14 +0,0 @@ -package bor - -import ( - "math/big" - - "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/rlp" -) - -//go:generate mockgen -destination=./mock/genesis_contract_mock.go -package=mock . GenesisContract -type GenesisContract interface { - CommitState(event rlp.RawValue, syscall consensus.SystemCall) error - LastStateId(syscall consensus.SystemCall) (*big.Int, error) -} diff --git a/polygon/bor/genesis_contracts.go b/polygon/bor/genesis_contracts.go new file mode 100644 index 00000000000..59af92c777c --- /dev/null +++ b/polygon/bor/genesis_contracts.go @@ -0,0 +1,87 @@ +package bor + +import ( + "math/big" + "strings" + + "github.com/ledgerwatch/log/v3" + + "github.com/ledgerwatch/erigon-lib/chain" + libcommon "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon/accounts/abi" + "github.com/ledgerwatch/erigon/consensus" + "github.com/ledgerwatch/erigon/rlp" +) + +const ( + validatorSetABIJSON = `[{"constant":true,"inputs":[],"name":"SPRINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"CHAIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FIRST_END_BLOCK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"producers","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ROUND_TYPE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"BOR_ID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spanNumbers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"VOTE_TYPE","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"validators","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"spans","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"startBlock","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"endBlock","type":"uint256"}],"name":"NewSpan","type":"event"},{"constant":true,"inputs":[],"name":"currentSprint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getCurrentSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getNextSpan","outputs":[{"internalType":"uint256","name":"number","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"getSpanByBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentSpanNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getValidatorsTotalStakeBySpan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"}],"name":"getProducersTotalStakeBySpan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"getValidatorBySigner","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"internalType":"struct BorValidatorSet.Validator","name":"result","type":"tuple"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"isValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"address","name":"signer","type":"address"}],"name":"isProducer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isCurrentValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"signer","type":"address"}],"name":"isCurrentProducer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"number","type":"uint256"}],"name":"getBorValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getInitialValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getValidators","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"newSpan","type":"uint256"},{"internalType":"uint256","name":"startBlock","type":"uint256"},{"internalType":"uint256","name":"endBlock","type":"uint256"},{"internalType":"bytes","name":"validatorBytes","type":"bytes"},{"internalType":"bytes","name":"producerBytes","type":"bytes"}],"name":"commitSpan","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"span","type":"uint256"},{"internalType":"bytes32","name":"dataHash","type":"bytes32"},{"internalType":"bytes","name":"sigs","type":"bytes"}],"name":"getStakePowerBySigs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"bytes32","name":"leaf","type":"bytes32"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"checkMembership","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"d","type":"bytes32"}],"name":"leafNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"left","type":"bytes32"},{"internalType":"bytes32","name":"right","type":"bytes32"}],"name":"innerNode","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"}]` + stateReceiverABIJSON = `[{"constant":true,"inputs":[],"name":"SYSTEM_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastStateId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"syncTime","type":"uint256"},{"internalType":"bytes","name":"recordBytes","type":"bytes"}],"name":"commitState","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]` +) + +var ( + validatorSetABI, _ = abi.JSON(strings.NewReader(validatorSetABIJSON)) + stateReceiverABI, _ = abi.JSON(strings.NewReader(stateReceiverABIJSON)) +) + +func GenesisContractValidatorSetABI() abi.ABI { + return validatorSetABI +} +func GenesisContractStateReceiverABI() abi.ABI { + return stateReceiverABI +} + +type GenesisContracts interface { + CommitState(event rlp.RawValue, syscall consensus.SystemCall) error + LastStateId(syscall consensus.SystemCall) (*big.Int, error) +} + +type GenesisContractsClient struct { + validatorSetABI abi.ABI + stateReceiverABI abi.ABI + ValidatorContract libcommon.Address + StateReceiverContract libcommon.Address + chainConfig *chain.Config + logger log.Logger +} + +func NewGenesisContractsClient( + chainConfig *chain.Config, + validatorContract, + stateReceiverContract string, + logger log.Logger, +) *GenesisContractsClient { + return &GenesisContractsClient{ + validatorSetABI: GenesisContractValidatorSetABI(), + stateReceiverABI: GenesisContractStateReceiverABI(), + ValidatorContract: libcommon.HexToAddress(validatorContract), + StateReceiverContract: libcommon.HexToAddress(stateReceiverContract), + chainConfig: chainConfig, + logger: logger, + } +} + +func (gc *GenesisContractsClient) CommitState(event rlp.RawValue, syscall consensus.SystemCall) error { + _, err := syscall(gc.StateReceiverContract, event) + return err +} + +func (gc *GenesisContractsClient) LastStateId(syscall consensus.SystemCall) (*big.Int, error) { + const method = "lastStateId" + + data, err := gc.stateReceiverABI.Pack(method) + if err != nil { + gc.logger.Error("[bor] Unable to pack tx for LastStateId", "err", err) + return nil, err + } + + result, err := syscall(gc.StateReceiverContract, data) + if err != nil { + return nil, err + } + + var ret = new(*big.Int) + if err := gc.stateReceiverABI.UnpackIntoInterface(ret, method, result); err != nil { + return nil, err + } + return *ret, nil +} diff --git a/polygon/bor/mock/genesis_contract_mock.go b/polygon/bor/mock/genesis_contract_mock.go deleted file mode 100644 index 475ae6ece49..00000000000 --- a/polygon/bor/mock/genesis_contract_mock.go +++ /dev/null @@ -1,66 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/ledgerwatch/erigon/polygon/bor (interfaces: GenesisContract) - -// Package mock is a generated GoMock package. -package mock - -import ( - big "math/big" - reflect "reflect" - - gomock "github.com/golang/mock/gomock" - consensus "github.com/ledgerwatch/erigon/consensus" - rlp "github.com/ledgerwatch/erigon/rlp" -) - -// MockGenesisContract is a mock of GenesisContract interface. -type MockGenesisContract struct { - ctrl *gomock.Controller - recorder *MockGenesisContractMockRecorder -} - -// MockGenesisContractMockRecorder is the mock recorder for MockGenesisContract. -type MockGenesisContractMockRecorder struct { - mock *MockGenesisContract -} - -// NewMockGenesisContract creates a new mock instance. -func NewMockGenesisContract(ctrl *gomock.Controller) *MockGenesisContract { - mock := &MockGenesisContract{ctrl: ctrl} - mock.recorder = &MockGenesisContractMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockGenesisContract) EXPECT() *MockGenesisContractMockRecorder { - return m.recorder -} - -// CommitState mocks base method. -func (m *MockGenesisContract) CommitState(arg0 rlp.RawValue, arg1 consensus.SystemCall) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CommitState", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// CommitState indicates an expected call of CommitState. -func (mr *MockGenesisContractMockRecorder) CommitState(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitState", reflect.TypeOf((*MockGenesisContract)(nil).CommitState), arg0, arg1) -} - -// LastStateId mocks base method. -func (m *MockGenesisContract) LastStateId(arg0 consensus.SystemCall) (*big.Int, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "LastStateId", arg0) - ret0, _ := ret[0].(*big.Int) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// LastStateId indicates an expected call of LastStateId. -func (mr *MockGenesisContractMockRecorder) LastStateId(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LastStateId", reflect.TypeOf((*MockGenesisContract)(nil).LastStateId), arg0) -} diff --git a/polygon/heimdall/span/span_id.go b/polygon/bor/span_id.go similarity index 50% rename from polygon/heimdall/span/span_id.go rename to polygon/bor/span_id.go index 0485aa6fb30..1c9348b6e1b 100644 --- a/polygon/heimdall/span/span_id.go +++ b/polygon/bor/span_id.go @@ -1,4 +1,4 @@ -package span +package bor import ( "github.com/ledgerwatch/erigon/polygon/bor/borcfg" @@ -9,26 +9,26 @@ const ( zerothSpanEnd = 255 // End block of 0th span ) -// IDAt returns the corresponding span id for the given block number. -func IDAt(blockNum uint64) uint64 { +// SpanIDAt returns the corresponding span id for the given block number. +func SpanIDAt(blockNum uint64) uint64 { if blockNum > zerothSpanEnd { return 1 + (blockNum-zerothSpanEnd-1)/spanLength } return 0 } -// EndBlockNum returns the number of the last block in the given span. -func EndBlockNum(spanID uint64) uint64 { +// SpanEndBlockNum returns the number of the last block in the given span. +func SpanEndBlockNum(spanID uint64) uint64 { if spanID > 0 { return spanID*spanLength + zerothSpanEnd } return zerothSpanEnd } -// BlockInLastSprintOfSpan returns true if a block num is within the last sprint of a span and false otherwise. -func BlockInLastSprintOfSpan(blockNum uint64, config *borcfg.BorConfig) bool { - spanNum := IDAt(blockNum) - endBlockNum := EndBlockNum(spanNum) +// IsBlockInLastSprintOfSpan returns true if a block num is within the last sprint of a span and false otherwise. +func IsBlockInLastSprintOfSpan(blockNum uint64, config *borcfg.BorConfig) bool { + spanNum := SpanIDAt(blockNum) + endBlockNum := SpanEndBlockNum(spanNum) sprintLen := config.CalculateSprintLength(blockNum) startBlockNum := endBlockNum - sprintLen + 1 return startBlockNum <= blockNum && blockNum <= endBlockNum diff --git a/polygon/bor/span_id_test.go b/polygon/bor/span_id_test.go new file mode 100644 index 00000000000..3281486576a --- /dev/null +++ b/polygon/bor/span_id_test.go @@ -0,0 +1,44 @@ +package bor + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" +) + +func TestSpanIDAt(t *testing.T) { + assert.Equal(t, uint64(0), SpanIDAt(0)) + assert.Equal(t, uint64(0), SpanIDAt(1)) + assert.Equal(t, uint64(0), SpanIDAt(2)) + assert.Equal(t, uint64(0), SpanIDAt(zerothSpanEnd)) + assert.Equal(t, uint64(1), SpanIDAt(zerothSpanEnd+1)) + assert.Equal(t, uint64(1), SpanIDAt(zerothSpanEnd+2)) + assert.Equal(t, uint64(1), SpanIDAt(6655)) + assert.Equal(t, uint64(2), SpanIDAt(6656)) + assert.Equal(t, uint64(2), SpanIDAt(6657)) + assert.Equal(t, uint64(2), SpanIDAt(13055)) + assert.Equal(t, uint64(3), SpanIDAt(13056)) + assert.Equal(t, uint64(6839), SpanIDAt(43763456)) +} + +func TestSpanEndBlockNum(t *testing.T) { + assert.Equal(t, uint64(zerothSpanEnd), SpanEndBlockNum(0)) + assert.Equal(t, uint64(6655), SpanEndBlockNum(1)) + assert.Equal(t, uint64(13055), SpanEndBlockNum(2)) + assert.Equal(t, uint64(43769855), SpanEndBlockNum(6839)) +} + +func TestBlockInLastSprintOfSpan(t *testing.T) { + config := &borcfg.BorConfig{ + Sprint: map[string]uint64{ + "0": 16, + }, + } + assert.True(t, IsBlockInLastSprintOfSpan(6640, config)) + assert.True(t, IsBlockInLastSprintOfSpan(6645, config)) + assert.True(t, IsBlockInLastSprintOfSpan(6655, config)) + assert.False(t, IsBlockInLastSprintOfSpan(6639, config)) + assert.False(t, IsBlockInLastSprintOfSpan(6656, config)) +} diff --git a/polygon/bor/spanner.go b/polygon/bor/spanner.go index ab7710dd558..728bc20f229 100644 --- a/polygon/bor/spanner.go +++ b/polygon/bor/spanner.go @@ -1,17 +1,173 @@ package bor import ( - "github.com/ledgerwatch/erigon/polygon/heimdall/span" + "encoding/hex" + "encoding/json" + "math/big" + "github.com/ledgerwatch/log/v3" + + "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/consensus" + "github.com/ledgerwatch/erigon/polygon/bor/borcfg" "github.com/ledgerwatch/erigon/polygon/bor/valset" + "github.com/ledgerwatch/erigon/polygon/heimdall" + "github.com/ledgerwatch/erigon/rlp" ) -//go:generate mockgen -destination=./mock/spanner_mock.go -package=mock . Spanner +//go:generate mockgen -destination=./spanner_mock.go -package=bor . Spanner type Spanner interface { - GetCurrentSpan(syscall consensus.SystemCall) (*span.Span, error) + GetCurrentSpan(syscall consensus.SystemCall) (*heimdall.Span, error) GetCurrentValidators(spanId uint64, signer libcommon.Address, chain consensus.ChainHeaderReader) ([]*valset.Validator, error) GetCurrentProducers(spanId uint64, signer libcommon.Address, chain consensus.ChainHeaderReader) ([]*valset.Validator, error) - CommitSpan(heimdallSpan span.HeimdallSpan, syscall consensus.SystemCall) error + CommitSpan(heimdallSpan heimdall.HeimdallSpan, syscall consensus.SystemCall) error +} + +type ABI interface { + Pack(name string, args ...interface{}) ([]byte, error) + UnpackIntoInterface(v interface{}, name string, data []byte) error +} + +type ChainSpanner struct { + validatorSet ABI + chainConfig *chain.Config + borConfig *borcfg.BorConfig + logger log.Logger + withoutHeimdall bool +} + +func NewChainSpanner(validatorSet ABI, chainConfig *chain.Config, withoutHeimdall bool, logger log.Logger) *ChainSpanner { + borConfig := chainConfig.Bor.(*borcfg.BorConfig) + return &ChainSpanner{ + validatorSet: validatorSet, + chainConfig: chainConfig, + borConfig: borConfig, + logger: logger, + withoutHeimdall: withoutHeimdall, + } +} + +// GetCurrentSpan get current span from contract +func (c *ChainSpanner) GetCurrentSpan(syscall consensus.SystemCall) (*heimdall.Span, error) { + + // method + const method = "getCurrentSpan" + + data, err := c.validatorSet.Pack(method) + if err != nil { + c.logger.Error("[bor] Unable to pack tx for getCurrentSpan", "error", err) + return nil, err + } + + result, err := syscall(libcommon.HexToAddress(c.borConfig.ValidatorContract), data) + if err != nil { + return nil, err + } + + // span result + ret := new(struct { + Number *big.Int + StartBlock *big.Int + EndBlock *big.Int + }) + + if err := c.validatorSet.UnpackIntoInterface(ret, method, result); err != nil { + return nil, err + } + + // create new span + span := heimdall.Span{ + ID: ret.Number.Uint64(), + StartBlock: ret.StartBlock.Uint64(), + EndBlock: ret.EndBlock.Uint64(), + } + + return &span, nil +} + +func (c *ChainSpanner) GetCurrentValidators(spanId uint64, signer libcommon.Address, chain consensus.ChainHeaderReader) ([]*valset.Validator, error) { + // Use hardcoded bor devnet valset if chain-name = bor-devnet + if NetworkNameVals[c.chainConfig.ChainName] != nil && c.withoutHeimdall { + return NetworkNameVals[c.chainConfig.ChainName], nil + } + + spanBytes := chain.BorSpan(spanId) + var span heimdall.HeimdallSpan + if err := json.Unmarshal(spanBytes, &span); err != nil { + return nil, err + } + + return span.ValidatorSet.Validators, nil +} + +func (c *ChainSpanner) GetCurrentProducers(spanId uint64, signer libcommon.Address, chain consensus.ChainHeaderReader) ([]*valset.Validator, error) { + // Use hardcoded bor devnet valset if chain-name = bor-devnet + if NetworkNameVals[c.chainConfig.ChainName] != nil && c.withoutHeimdall { + return NetworkNameVals[c.chainConfig.ChainName], nil + } + + spanBytes := chain.BorSpan(spanId) + var span heimdall.HeimdallSpan + if err := json.Unmarshal(spanBytes, &span); err != nil { + return nil, err + } + + producers := make([]*valset.Validator, len(span.SelectedProducers)) + for i := range span.SelectedProducers { + producers[i] = &span.SelectedProducers[i] + } + + return producers, nil +} + +func (c *ChainSpanner) CommitSpan(heimdallSpan heimdall.HeimdallSpan, syscall consensus.SystemCall) error { + + // method + const method = "commitSpan" + + // get validators bytes + validators := make([]valset.MinimalVal, 0, len(heimdallSpan.ValidatorSet.Validators)) + for _, val := range heimdallSpan.ValidatorSet.Validators { + validators = append(validators, val.MinimalVal()) + } + validatorBytes, err := rlp.EncodeToBytes(validators) + if err != nil { + return err + } + + // get producers bytes + producers := make([]valset.MinimalVal, 0, len(heimdallSpan.SelectedProducers)) + for _, val := range heimdallSpan.SelectedProducers { + producers = append(producers, val.MinimalVal()) + } + producerBytes, err := rlp.EncodeToBytes(producers) + if err != nil { + return err + } + + c.logger.Debug("[bor] ✅ Committing new span", + "id", heimdallSpan.ID, + "startBlock", heimdallSpan.StartBlock, + "endBlock", heimdallSpan.EndBlock, + "validatorBytes", hex.EncodeToString(validatorBytes), + "producerBytes", hex.EncodeToString(producerBytes), + ) + + // get packed data + data, err := c.validatorSet.Pack(method, + big.NewInt(0).SetUint64(heimdallSpan.ID), + big.NewInt(0).SetUint64(heimdallSpan.StartBlock), + big.NewInt(0).SetUint64(heimdallSpan.EndBlock), + validatorBytes, + producerBytes, + ) + if err != nil { + c.logger.Error("[bor] Unable to pack tx for commitSpan", "error", err) + return err + } + + _, err = syscall(libcommon.HexToAddress(c.borConfig.ValidatorContract), data) + + return err } diff --git a/polygon/bor/mock/spanner_mock.go b/polygon/bor/spanner_mock.go similarity index 92% rename from polygon/bor/mock/spanner_mock.go rename to polygon/bor/spanner_mock.go index 07c9b881bad..45d65a5178a 100644 --- a/polygon/bor/mock/spanner_mock.go +++ b/polygon/bor/spanner_mock.go @@ -1,8 +1,8 @@ // Code generated by MockGen. DO NOT EDIT. // Source: github.com/ledgerwatch/erigon/polygon/bor (interfaces: Spanner) -// Package mock is a generated GoMock package. -package mock +// Package bor is a generated GoMock package. +package bor import ( reflect "reflect" @@ -10,8 +10,8 @@ import ( gomock "github.com/golang/mock/gomock" common "github.com/ledgerwatch/erigon-lib/common" consensus "github.com/ledgerwatch/erigon/consensus" - span "github.com/ledgerwatch/erigon/polygon/heimdall/span" valset "github.com/ledgerwatch/erigon/polygon/bor/valset" + heimdall "github.com/ledgerwatch/erigon/polygon/heimdall" ) // MockSpanner is a mock of Spanner interface. @@ -38,7 +38,7 @@ func (m *MockSpanner) EXPECT() *MockSpannerMockRecorder { } // CommitSpan mocks base method. -func (m *MockSpanner) CommitSpan(arg0 span.HeimdallSpan, arg1 consensus.SystemCall) error { +func (m *MockSpanner) CommitSpan(arg0 heimdall.HeimdallSpan, arg1 consensus.SystemCall) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CommitSpan", arg0, arg1) ret0, _ := ret[0].(error) @@ -67,10 +67,10 @@ func (mr *MockSpannerMockRecorder) GetCurrentProducers(arg0, arg1, arg2 interfac } // GetCurrentSpan mocks base method. -func (m *MockSpanner) GetCurrentSpan(arg0 consensus.SystemCall) (*span.Span, error) { +func (m *MockSpanner) GetCurrentSpan(arg0 consensus.SystemCall) (*heimdall.Span, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "GetCurrentSpan", arg0) - ret0, _ := ret[0].(*span.Span) + ret0, _ := ret[0].(*heimdall.Span) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/polygon/heimdall/span/testValidators.go b/polygon/bor/spanner_test_validators.go similarity index 98% rename from polygon/heimdall/span/testValidators.go rename to polygon/bor/spanner_test_validators.go index 1dfaa722e5e..7cc3d5d3ecc 100644 --- a/polygon/heimdall/span/testValidators.go +++ b/polygon/bor/spanner_test_validators.go @@ -1,4 +1,4 @@ -package span +package bor import ( "github.com/ledgerwatch/erigon-lib/chain/networkname" diff --git a/polygon/heimdall/checkpoint/checkpoint.go b/polygon/heimdall/checkpoint.go similarity index 98% rename from polygon/heimdall/checkpoint/checkpoint.go rename to polygon/heimdall/checkpoint.go index ebced7beef8..267bb7d8b89 100644 --- a/polygon/heimdall/checkpoint/checkpoint.go +++ b/polygon/heimdall/checkpoint.go @@ -1,4 +1,4 @@ -package checkpoint +package heimdall import ( "fmt" diff --git a/polygon/heimdall/client.go b/polygon/heimdall/client.go index 6b2f83c6fc1..26339058077 100644 --- a/polygon/heimdall/client.go +++ b/polygon/heimdall/client.go @@ -15,12 +15,7 @@ import ( "github.com/ledgerwatch/log/v3" - "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" - "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" - "github.com/ledgerwatch/erigon/polygon/heimdall/span" - "github.com/ledgerwatch/erigon-lib/metrics" - "github.com/ledgerwatch/erigon/polygon/bor/clerk" ) var ( @@ -40,14 +35,25 @@ const ( maxRetries = 5 ) -type StateSyncEventsResponse struct { - Height string `json:"height"` - Result []*clerk.EventRecordWithTime `json:"result"` -} +//go:generate mockgen -destination=./client_mock.go -package=heimdall . HeimdallClient +type HeimdallClient interface { + StateSyncEvents(ctx context.Context, fromID uint64, to int64) ([]*EventRecordWithTime, error) + Span(ctx context.Context, spanID uint64) (*HeimdallSpan, error) + FetchCheckpoint(ctx context.Context, number int64) (*Checkpoint, error) + FetchCheckpointCount(ctx context.Context) (int64, error) + FetchMilestone(ctx context.Context, number int64) (*Milestone, error) + FetchMilestoneCount(ctx context.Context) (int64, error) + + // FetchNoAckMilestone fetches a bool value whether milestone corresponding to the given id failed in the Heimdall + FetchNoAckMilestone(ctx context.Context, milestoneID string) error + + // FetchLastNoAckMilestone fetches the latest failed milestone id + FetchLastNoAckMilestone(ctx context.Context) (string, error) + + // FetchMilestoneID fetches a bool value whether milestone corresponding to the given id is in process in Heimdall + FetchMilestoneID(ctx context.Context, milestoneID string) error -type SpanResponse struct { - Height string `json:"height"` - Result span.HeimdallSpan `json:"result"` + Close() } type Client struct { @@ -65,7 +71,7 @@ type Request struct { start time.Time } -//go:generate mockgen -destination=./mock/http_client_mock.go -package=mock . HttpClient +//go:generate mockgen -destination=./http_client_mock.go -package=heimdall . HttpClient type HttpClient interface { Do(req *http.Request) (*http.Response, error) CloseIdleConnections() @@ -107,8 +113,8 @@ const ( fetchSpanFormat = "bor/span/%d" ) -func (c *Client) StateSyncEvents(ctx context.Context, fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error) { - eventRecords := make([]*clerk.EventRecordWithTime, 0) +func (c *Client) StateSyncEvents(ctx context.Context, fromID uint64, to int64) ([]*EventRecordWithTime, error) { + eventRecords := make([]*EventRecordWithTime, 0) for { url, err := stateSyncURL(c.urlString, fromID, to) @@ -154,7 +160,7 @@ func (c *Client) StateSyncEvents(ctx context.Context, fromID uint64, to int64) ( return eventRecords, nil } -func (c *Client) Span(ctx context.Context, spanID uint64) (*span.HeimdallSpan, error) { +func (c *Client) Span(ctx context.Context, spanID uint64) (*HeimdallSpan, error) { url, err := spanURL(c.urlString, spanID) if err != nil { return nil, err @@ -171,7 +177,7 @@ func (c *Client) Span(ctx context.Context, spanID uint64) (*span.HeimdallSpan, e } // FetchCheckpoint fetches the checkpoint from heimdall -func (c *Client) FetchCheckpoint(ctx context.Context, number int64) (*checkpoint.Checkpoint, error) { +func (c *Client) FetchCheckpoint(ctx context.Context, number int64) (*Checkpoint, error) { url, err := checkpointURL(c.urlString, number) if err != nil { return nil, err @@ -179,7 +185,7 @@ func (c *Client) FetchCheckpoint(ctx context.Context, number int64) (*checkpoint ctx = withRequestType(ctx, checkpointRequest) - response, err := FetchWithRetry[checkpoint.CheckpointResponse](ctx, c, url) + response, err := FetchWithRetry[CheckpointResponse](ctx, c, url) if err != nil { return nil, err } @@ -193,7 +199,7 @@ func isInvalidMilestoneIndexError(err error) bool { } // FetchMilestone fetches a milestone from heimdall -func (c *Client) FetchMilestone(ctx context.Context, number int64) (*milestone.Milestone, error) { +func (c *Client) FetchMilestone(ctx context.Context, number int64) (*Milestone, error) { url, err := milestoneURL(c.urlString, number) if err != nil { return nil, err @@ -205,7 +211,7 @@ func (c *Client) FetchMilestone(ctx context.Context, number int64) (*milestone.M return !isInvalidMilestoneIndexError(err) } - response, err := FetchWithRetryEx[milestone.MilestoneResponse](ctx, c, url, isRecoverableError) + response, err := FetchWithRetryEx[MilestoneResponse](ctx, c, url, isRecoverableError) if err != nil { if isInvalidMilestoneIndexError(err) { return nil, fmt.Errorf("%w: number %d", ErrNotInMilestoneList, number) @@ -225,7 +231,7 @@ func (c *Client) FetchCheckpointCount(ctx context.Context) (int64, error) { ctx = withRequestType(ctx, checkpointCountRequest) - response, err := FetchWithRetry[checkpoint.CheckpointCountResponse](ctx, c, url) + response, err := FetchWithRetry[CheckpointCountResponse](ctx, c, url) if err != nil { return 0, err } @@ -242,7 +248,7 @@ func (c *Client) FetchMilestoneCount(ctx context.Context) (int64, error) { ctx = withRequestType(ctx, milestoneCountRequest) - response, err := FetchWithRetry[milestone.MilestoneCountResponse](ctx, c, url) + response, err := FetchWithRetry[MilestoneCountResponse](ctx, c, url) if err != nil { return 0, err } @@ -259,7 +265,7 @@ func (c *Client) FetchLastNoAckMilestone(ctx context.Context) (string, error) { ctx = withRequestType(ctx, milestoneLastNoAckRequest) - response, err := FetchWithRetry[milestone.MilestoneLastNoAckResponse](ctx, c, url) + response, err := FetchWithRetry[MilestoneLastNoAckResponse](ctx, c, url) if err != nil { return "", err } @@ -276,7 +282,7 @@ func (c *Client) FetchNoAckMilestone(ctx context.Context, milestoneID string) er ctx = withRequestType(ctx, milestoneNoAckRequest) - response, err := FetchWithRetry[milestone.MilestoneNoAckResponse](ctx, c, url) + response, err := FetchWithRetry[MilestoneNoAckResponse](ctx, c, url) if err != nil { return err } @@ -298,7 +304,7 @@ func (c *Client) FetchMilestoneID(ctx context.Context, milestoneID string) error ctx = withRequestType(ctx, milestoneIDRequest) - response, err := FetchWithRetry[milestone.MilestoneIDResponse](ctx, c, url) + response, err := FetchWithRetry[MilestoneIDResponse](ctx, c, url) if err != nil { return err diff --git a/polygon/heimdall/client_mock.go b/polygon/heimdall/client_mock.go new file mode 100644 index 00000000000..352ae1b5f3a --- /dev/null +++ b/polygon/heimdall/client_mock.go @@ -0,0 +1,180 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/ledgerwatch/erigon/polygon/heimdall (interfaces: HeimdallClient) + +// Package heimdall is a generated GoMock package. +package heimdall + +import ( + context "context" + reflect "reflect" + + gomock "github.com/golang/mock/gomock" +) + +// MockHeimdallClient is a mock of HeimdallClient interface. +type MockHeimdallClient struct { + ctrl *gomock.Controller + recorder *MockHeimdallClientMockRecorder +} + +// MockHeimdallClientMockRecorder is the mock recorder for MockHeimdallClient. +type MockHeimdallClientMockRecorder struct { + mock *MockHeimdallClient +} + +// NewMockHeimdallClient creates a new mock instance. +func NewMockHeimdallClient(ctrl *gomock.Controller) *MockHeimdallClient { + mock := &MockHeimdallClient{ctrl: ctrl} + mock.recorder = &MockHeimdallClientMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockHeimdallClient) EXPECT() *MockHeimdallClientMockRecorder { + return m.recorder +} + +// Close mocks base method. +func (m *MockHeimdallClient) Close() { + m.ctrl.T.Helper() + m.ctrl.Call(m, "Close") +} + +// Close indicates an expected call of Close. +func (mr *MockHeimdallClientMockRecorder) Close() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockHeimdallClient)(nil).Close)) +} + +// FetchCheckpoint mocks base method. +func (m *MockHeimdallClient) FetchCheckpoint(arg0 context.Context, arg1 int64) (*Checkpoint, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FetchCheckpoint", arg0, arg1) + ret0, _ := ret[0].(*Checkpoint) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FetchCheckpoint indicates an expected call of FetchCheckpoint. +func (mr *MockHeimdallClientMockRecorder) FetchCheckpoint(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchCheckpoint", reflect.TypeOf((*MockHeimdallClient)(nil).FetchCheckpoint), arg0, arg1) +} + +// FetchCheckpointCount mocks base method. +func (m *MockHeimdallClient) FetchCheckpointCount(arg0 context.Context) (int64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FetchCheckpointCount", arg0) + ret0, _ := ret[0].(int64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FetchCheckpointCount indicates an expected call of FetchCheckpointCount. +func (mr *MockHeimdallClientMockRecorder) FetchCheckpointCount(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchCheckpointCount", reflect.TypeOf((*MockHeimdallClient)(nil).FetchCheckpointCount), arg0) +} + +// FetchLastNoAckMilestone mocks base method. +func (m *MockHeimdallClient) FetchLastNoAckMilestone(arg0 context.Context) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FetchLastNoAckMilestone", arg0) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FetchLastNoAckMilestone indicates an expected call of FetchLastNoAckMilestone. +func (mr *MockHeimdallClientMockRecorder) FetchLastNoAckMilestone(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchLastNoAckMilestone", reflect.TypeOf((*MockHeimdallClient)(nil).FetchLastNoAckMilestone), arg0) +} + +// FetchMilestone mocks base method. +func (m *MockHeimdallClient) FetchMilestone(arg0 context.Context, arg1 int64) (*Milestone, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FetchMilestone", arg0, arg1) + ret0, _ := ret[0].(*Milestone) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FetchMilestone indicates an expected call of FetchMilestone. +func (mr *MockHeimdallClientMockRecorder) FetchMilestone(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchMilestone", reflect.TypeOf((*MockHeimdallClient)(nil).FetchMilestone), arg0, arg1) +} + +// FetchMilestoneCount mocks base method. +func (m *MockHeimdallClient) FetchMilestoneCount(arg0 context.Context) (int64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FetchMilestoneCount", arg0) + ret0, _ := ret[0].(int64) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// FetchMilestoneCount indicates an expected call of FetchMilestoneCount. +func (mr *MockHeimdallClientMockRecorder) FetchMilestoneCount(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchMilestoneCount", reflect.TypeOf((*MockHeimdallClient)(nil).FetchMilestoneCount), arg0) +} + +// FetchMilestoneID mocks base method. +func (m *MockHeimdallClient) FetchMilestoneID(arg0 context.Context, arg1 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FetchMilestoneID", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// FetchMilestoneID indicates an expected call of FetchMilestoneID. +func (mr *MockHeimdallClientMockRecorder) FetchMilestoneID(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchMilestoneID", reflect.TypeOf((*MockHeimdallClient)(nil).FetchMilestoneID), arg0, arg1) +} + +// FetchNoAckMilestone mocks base method. +func (m *MockHeimdallClient) FetchNoAckMilestone(arg0 context.Context, arg1 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FetchNoAckMilestone", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// FetchNoAckMilestone indicates an expected call of FetchNoAckMilestone. +func (mr *MockHeimdallClientMockRecorder) FetchNoAckMilestone(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchNoAckMilestone", reflect.TypeOf((*MockHeimdallClient)(nil).FetchNoAckMilestone), arg0, arg1) +} + +// Span mocks base method. +func (m *MockHeimdallClient) Span(arg0 context.Context, arg1 uint64) (*HeimdallSpan, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Span", arg0, arg1) + ret0, _ := ret[0].(*HeimdallSpan) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Span indicates an expected call of Span. +func (mr *MockHeimdallClientMockRecorder) Span(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Span", reflect.TypeOf((*MockHeimdallClient)(nil).Span), arg0, arg1) +} + +// StateSyncEvents mocks base method. +func (m *MockHeimdallClient) StateSyncEvents(arg0 context.Context, arg1 uint64, arg2 int64) ([]*EventRecordWithTime, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "StateSyncEvents", arg0, arg1, arg2) + ret0, _ := ret[0].([]*EventRecordWithTime) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// StateSyncEvents indicates an expected call of StateSyncEvents. +func (mr *MockHeimdallClientMockRecorder) StateSyncEvents(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateSyncEvents", reflect.TypeOf((*MockHeimdallClient)(nil).StateSyncEvents), arg0, arg1, arg2) +} diff --git a/polygon/heimdall/client_test.go b/polygon/heimdall/client_test.go index b8804bba64d..19638dab8dc 100644 --- a/polygon/heimdall/client_test.go +++ b/polygon/heimdall/client_test.go @@ -11,8 +11,6 @@ import ( "github.com/ledgerwatch/log/v3" "github.com/stretchr/testify/require" - "github.com/ledgerwatch/erigon/polygon/heimdall/mock" - "github.com/ledgerwatch/erigon/turbo/testlog" ) @@ -29,7 +27,7 @@ func (ebrc emptyBodyReadCloser) Close() error { func TestHeimdallClientFetchesTerminateUponTooManyErrors(t *testing.T) { ctx := context.Background() ctrl := gomock.NewController(t) - httpClient := mock.NewMockHttpClient(ctrl) + httpClient := NewMockHttpClient(ctrl) httpClient.EXPECT(). Do(gomock.Any()). Return(&http.Response{ @@ -48,7 +46,7 @@ func TestHeimdallClientFetchesTerminateUponTooManyErrors(t *testing.T) { func TestHeimdallClientStateSyncEventsReturnsErrNoResponseWhenHttp200WithEmptyBody(t *testing.T) { ctx := context.Background() ctrl := gomock.NewController(t) - httpClient := mock.NewMockHttpClient(ctrl) + httpClient := NewMockHttpClient(ctrl) httpClient.EXPECT(). Do(gomock.Any()). Return(&http.Response{ diff --git a/polygon/bor/clerk/clerk.go b/polygon/heimdall/event_record.go similarity index 89% rename from polygon/bor/clerk/clerk.go rename to polygon/heimdall/event_record.go index 39b9aefb8c7..09d9be406de 100644 --- a/polygon/bor/clerk/clerk.go +++ b/polygon/heimdall/event_record.go @@ -1,4 +1,4 @@ -package clerk +package heimdall import ( "fmt" @@ -47,3 +47,8 @@ func (e *EventRecordWithTime) BuildEventRecord() *EventRecord { ChainID: e.ChainID, } } + +type StateSyncEventsResponse struct { + Height string `json:"height"` + Result []*EventRecordWithTime `json:"result"` +} diff --git a/polygon/heimdall/heimdall.go b/polygon/heimdall/heimdall.go deleted file mode 100644 index e72cf25ec8d..00000000000 --- a/polygon/heimdall/heimdall.go +++ /dev/null @@ -1,30 +0,0 @@ -package heimdall - -import ( - "context" - - "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" - "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" - "github.com/ledgerwatch/erigon/polygon/heimdall/span" - - "github.com/ledgerwatch/erigon/polygon/bor/clerk" - "github.com/ledgerwatch/erigon/polygon/bor/finality/generics" -) - -func MilestoneRewindPending() bool { - return generics.BorMilestoneRewind.Load() != nil && *generics.BorMilestoneRewind.Load() != 0 -} - -//go:generate mockgen -destination=./mock/heimdall_client_mock.go -package=mock . IHeimdallClient -type IHeimdallClient interface { - StateSyncEvents(ctx context.Context, fromID uint64, to int64) ([]*clerk.EventRecordWithTime, error) - Span(ctx context.Context, spanID uint64) (*span.HeimdallSpan, error) - FetchCheckpoint(ctx context.Context, number int64) (*checkpoint.Checkpoint, error) - FetchCheckpointCount(ctx context.Context) (int64, error) - FetchMilestone(ctx context.Context, number int64) (*milestone.Milestone, error) - FetchMilestoneCount(ctx context.Context) (int64, error) - FetchNoAckMilestone(ctx context.Context, milestoneID string) error //Fetch the bool value whether milestone corresponding to the given id failed in the Heimdall - FetchLastNoAckMilestone(ctx context.Context) (string, error) //Fetch latest failed milestone id - FetchMilestoneID(ctx context.Context, milestoneID string) error //Fetch the bool value whether milestone corresponding to the given id is in process in Heimdall - Close() -} diff --git a/polygon/heimdall/mock/http_client_mock.go b/polygon/heimdall/http_client_mock.go similarity index 96% rename from polygon/heimdall/mock/http_client_mock.go rename to polygon/heimdall/http_client_mock.go index b41cfa8f139..bf1564bb500 100644 --- a/polygon/heimdall/mock/http_client_mock.go +++ b/polygon/heimdall/http_client_mock.go @@ -1,8 +1,8 @@ // Code generated by MockGen. DO NOT EDIT. // Source: github.com/ledgerwatch/erigon/polygon/heimdall (interfaces: HttpClient) -// Package mock is a generated GoMock package. -package mock +// Package heimdall is a generated GoMock package. +package heimdall import ( http "net/http" diff --git a/polygon/heimdall/milestone/milestone.go b/polygon/heimdall/milestone.go similarity index 98% rename from polygon/heimdall/milestone/milestone.go rename to polygon/heimdall/milestone.go index a849f4461bd..44cfa2e9c1b 100644 --- a/polygon/heimdall/milestone/milestone.go +++ b/polygon/heimdall/milestone.go @@ -1,4 +1,4 @@ -package milestone +package heimdall import ( "math/big" diff --git a/polygon/heimdall/mock/heimdall_client_mock.go b/polygon/heimdall/mock/heimdall_client_mock.go deleted file mode 100644 index de176271602..00000000000 --- a/polygon/heimdall/mock/heimdall_client_mock.go +++ /dev/null @@ -1,184 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/ledgerwatch/erigon/polygon/heimdall (interfaces: IHeimdallClient) - -// Package mock is a generated GoMock package. -package mock - -import ( - context "context" - reflect "reflect" - - gomock "github.com/golang/mock/gomock" - clerk "github.com/ledgerwatch/erigon/polygon/bor/clerk" - checkpoint "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" - milestone "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" - span "github.com/ledgerwatch/erigon/polygon/heimdall/span" -) - -// MockIHeimdallClient is a mock of IHeimdallClient interface. -type MockIHeimdallClient struct { - ctrl *gomock.Controller - recorder *MockIHeimdallClientMockRecorder -} - -// MockIHeimdallClientMockRecorder is the mock recorder for MockIHeimdallClient. -type MockIHeimdallClientMockRecorder struct { - mock *MockIHeimdallClient -} - -// NewMockIHeimdallClient creates a new mock instance. -func NewMockIHeimdallClient(ctrl *gomock.Controller) *MockIHeimdallClient { - mock := &MockIHeimdallClient{ctrl: ctrl} - mock.recorder = &MockIHeimdallClientMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockIHeimdallClient) EXPECT() *MockIHeimdallClientMockRecorder { - return m.recorder -} - -// Close mocks base method. -func (m *MockIHeimdallClient) Close() { - m.ctrl.T.Helper() - m.ctrl.Call(m, "Close") -} - -// Close indicates an expected call of Close. -func (mr *MockIHeimdallClientMockRecorder) Close() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockIHeimdallClient)(nil).Close)) -} - -// FetchCheckpoint mocks base method. -func (m *MockIHeimdallClient) FetchCheckpoint(arg0 context.Context, arg1 int64) (*checkpoint.Checkpoint, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FetchCheckpoint", arg0, arg1) - ret0, _ := ret[0].(*checkpoint.Checkpoint) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// FetchCheckpoint indicates an expected call of FetchCheckpoint. -func (mr *MockIHeimdallClientMockRecorder) FetchCheckpoint(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchCheckpoint", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchCheckpoint), arg0, arg1) -} - -// FetchCheckpointCount mocks base method. -func (m *MockIHeimdallClient) FetchCheckpointCount(arg0 context.Context) (int64, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FetchCheckpointCount", arg0) - ret0, _ := ret[0].(int64) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// FetchCheckpointCount indicates an expected call of FetchCheckpointCount. -func (mr *MockIHeimdallClientMockRecorder) FetchCheckpointCount(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchCheckpointCount", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchCheckpointCount), arg0) -} - -// FetchLastNoAckMilestone mocks base method. -func (m *MockIHeimdallClient) FetchLastNoAckMilestone(arg0 context.Context) (string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FetchLastNoAckMilestone", arg0) - ret0, _ := ret[0].(string) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// FetchLastNoAckMilestone indicates an expected call of FetchLastNoAckMilestone. -func (mr *MockIHeimdallClientMockRecorder) FetchLastNoAckMilestone(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchLastNoAckMilestone", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchLastNoAckMilestone), arg0) -} - -// FetchMilestone mocks base method. -func (m *MockIHeimdallClient) FetchMilestone(arg0 context.Context, arg1 int64) (*milestone.Milestone, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FetchMilestone", arg0, arg1) - ret0, _ := ret[0].(*milestone.Milestone) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// FetchMilestone indicates an expected call of FetchMilestone. -func (mr *MockIHeimdallClientMockRecorder) FetchMilestone(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchMilestone", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchMilestone), arg0, arg1) -} - -// FetchMilestoneCount mocks base method. -func (m *MockIHeimdallClient) FetchMilestoneCount(arg0 context.Context) (int64, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FetchMilestoneCount", arg0) - ret0, _ := ret[0].(int64) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// FetchMilestoneCount indicates an expected call of FetchMilestoneCount. -func (mr *MockIHeimdallClientMockRecorder) FetchMilestoneCount(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchMilestoneCount", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchMilestoneCount), arg0) -} - -// FetchMilestoneID mocks base method. -func (m *MockIHeimdallClient) FetchMilestoneID(arg0 context.Context, arg1 string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FetchMilestoneID", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// FetchMilestoneID indicates an expected call of FetchMilestoneID. -func (mr *MockIHeimdallClientMockRecorder) FetchMilestoneID(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchMilestoneID", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchMilestoneID), arg0, arg1) -} - -// FetchNoAckMilestone mocks base method. -func (m *MockIHeimdallClient) FetchNoAckMilestone(arg0 context.Context, arg1 string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "FetchNoAckMilestone", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// FetchNoAckMilestone indicates an expected call of FetchNoAckMilestone. -func (mr *MockIHeimdallClientMockRecorder) FetchNoAckMilestone(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FetchNoAckMilestone", reflect.TypeOf((*MockIHeimdallClient)(nil).FetchNoAckMilestone), arg0, arg1) -} - -// Span mocks base method. -func (m *MockIHeimdallClient) Span(arg0 context.Context, arg1 uint64) (*span.HeimdallSpan, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Span", arg0, arg1) - ret0, _ := ret[0].(*span.HeimdallSpan) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Span indicates an expected call of Span. -func (mr *MockIHeimdallClientMockRecorder) Span(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Span", reflect.TypeOf((*MockIHeimdallClient)(nil).Span), arg0, arg1) -} - -// StateSyncEvents mocks base method. -func (m *MockIHeimdallClient) StateSyncEvents(arg0 context.Context, arg1 uint64, arg2 int64) ([]*clerk.EventRecordWithTime, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "StateSyncEvents", arg0, arg1, arg2) - ret0, _ := ret[0].([]*clerk.EventRecordWithTime) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// StateSyncEvents indicates an expected call of StateSyncEvents. -func (mr *MockIHeimdallClientMockRecorder) StateSyncEvents(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StateSyncEvents", reflect.TypeOf((*MockIHeimdallClient)(nil).StateSyncEvents), arg0, arg1, arg2) -} diff --git a/polygon/heimdall/span/span.go b/polygon/heimdall/span.go similarity index 88% rename from polygon/heimdall/span/span.go rename to polygon/heimdall/span.go index 7ab715b539e..862f0573f43 100644 --- a/polygon/heimdall/span/span.go +++ b/polygon/heimdall/span.go @@ -1,7 +1,8 @@ -package span +package heimdall import ( "github.com/google/btree" + "github.com/ledgerwatch/erigon/polygon/bor/valset" ) @@ -28,3 +29,8 @@ func (hs *HeimdallSpan) Less(other btree.Item) bool { } return hs.EndBlock < otherHs.EndBlock } + +type SpanResponse struct { + Height string `json:"height"` + Result HeimdallSpan `json:"result"` +} diff --git a/polygon/heimdall/span/span_id_test.go b/polygon/heimdall/span/span_id_test.go deleted file mode 100644 index 34c2b669f16..00000000000 --- a/polygon/heimdall/span/span_id_test.go +++ /dev/null @@ -1,44 +0,0 @@ -package span - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "github.com/ledgerwatch/erigon/polygon/bor/borcfg" -) - -func TestSpanIDAt(t *testing.T) { - assert.Equal(t, uint64(0), IDAt(0)) - assert.Equal(t, uint64(0), IDAt(1)) - assert.Equal(t, uint64(0), IDAt(2)) - assert.Equal(t, uint64(0), IDAt(zerothSpanEnd)) - assert.Equal(t, uint64(1), IDAt(zerothSpanEnd+1)) - assert.Equal(t, uint64(1), IDAt(zerothSpanEnd+2)) - assert.Equal(t, uint64(1), IDAt(6655)) - assert.Equal(t, uint64(2), IDAt(6656)) - assert.Equal(t, uint64(2), IDAt(6657)) - assert.Equal(t, uint64(2), IDAt(13055)) - assert.Equal(t, uint64(3), IDAt(13056)) - assert.Equal(t, uint64(6839), IDAt(43763456)) -} - -func TestSpanEndBlockNum(t *testing.T) { - assert.Equal(t, uint64(zerothSpanEnd), EndBlockNum(0)) - assert.Equal(t, uint64(6655), EndBlockNum(1)) - assert.Equal(t, uint64(13055), EndBlockNum(2)) - assert.Equal(t, uint64(43769855), EndBlockNum(6839)) -} - -func TestBlockInLastSprintOfSpan(t *testing.T) { - config := &borcfg.BorConfig{ - Sprint: map[string]uint64{ - "0": 16, - }, - } - assert.True(t, BlockInLastSprintOfSpan(6640, config)) - assert.True(t, BlockInLastSprintOfSpan(6645, config)) - assert.True(t, BlockInLastSprintOfSpan(6655, config)) - assert.False(t, BlockInLastSprintOfSpan(6639, config)) - assert.False(t, BlockInLastSprintOfSpan(6656, config)) -} diff --git a/polygon/heimdall/span/spanner.go b/polygon/heimdall/span/spanner.go deleted file mode 100644 index 315617f9eff..00000000000 --- a/polygon/heimdall/span/spanner.go +++ /dev/null @@ -1,160 +0,0 @@ -package span - -import ( - "encoding/hex" - "encoding/json" - "math/big" - - "github.com/ledgerwatch/log/v3" - - "github.com/ledgerwatch/erigon-lib/chain" - libcommon "github.com/ledgerwatch/erigon-lib/common" - "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/polygon/bor/abi" - "github.com/ledgerwatch/erigon/polygon/bor/borcfg" - "github.com/ledgerwatch/erigon/polygon/bor/valset" - "github.com/ledgerwatch/erigon/rlp" -) - -type ChainSpanner struct { - validatorSet abi.ABI - chainConfig *chain.Config - borConfig *borcfg.BorConfig - logger log.Logger - withoutHeimdall bool -} - -func NewChainSpanner(validatorSet abi.ABI, chainConfig *chain.Config, withoutHeimdall bool, logger log.Logger) *ChainSpanner { - borConfig := chainConfig.Bor.(*borcfg.BorConfig) - return &ChainSpanner{ - validatorSet: validatorSet, - chainConfig: chainConfig, - borConfig: borConfig, - logger: logger, - withoutHeimdall: withoutHeimdall, - } -} - -// GetCurrentSpan get current span from contract -func (c *ChainSpanner) GetCurrentSpan(syscall consensus.SystemCall) (*Span, error) { - - // method - const method = "getCurrentSpan" - - data, err := c.validatorSet.Pack(method) - if err != nil { - c.logger.Error("[bor] Unable to pack tx for getCurrentSpan", "error", err) - return nil, err - } - - result, err := syscall(libcommon.HexToAddress(c.borConfig.ValidatorContract), data) - if err != nil { - return nil, err - } - - // span result - ret := new(struct { - Number *big.Int - StartBlock *big.Int - EndBlock *big.Int - }) - - if err := c.validatorSet.UnpackIntoInterface(ret, method, result); err != nil { - return nil, err - } - - // create new span - span := Span{ - ID: ret.Number.Uint64(), - StartBlock: ret.StartBlock.Uint64(), - EndBlock: ret.EndBlock.Uint64(), - } - - return &span, nil -} - -func (c *ChainSpanner) GetCurrentValidators(spanId uint64, signer libcommon.Address, chain consensus.ChainHeaderReader) ([]*valset.Validator, error) { - // Use hardcoded bor devnet valset if chain-name = bor-devnet - if NetworkNameVals[c.chainConfig.ChainName] != nil && c.withoutHeimdall { - return NetworkNameVals[c.chainConfig.ChainName], nil - } - - spanBytes := chain.BorSpan(spanId) - var span HeimdallSpan - if err := json.Unmarshal(spanBytes, &span); err != nil { - return nil, err - } - - return span.ValidatorSet.Validators, nil -} - -func (c *ChainSpanner) GetCurrentProducers(spanId uint64, signer libcommon.Address, chain consensus.ChainHeaderReader) ([]*valset.Validator, error) { - // Use hardcoded bor devnet valset if chain-name = bor-devnet - if NetworkNameVals[c.chainConfig.ChainName] != nil && c.withoutHeimdall { - return NetworkNameVals[c.chainConfig.ChainName], nil - } - - spanBytes := chain.BorSpan(spanId) - var span HeimdallSpan - if err := json.Unmarshal(spanBytes, &span); err != nil { - return nil, err - } - - producers := make([]*valset.Validator, len(span.SelectedProducers)) - for i := range span.SelectedProducers { - producers[i] = &span.SelectedProducers[i] - } - - return producers, nil -} - -func (c *ChainSpanner) CommitSpan(heimdallSpan HeimdallSpan, syscall consensus.SystemCall) error { - - // method - const method = "commitSpan" - - // get validators bytes - validators := make([]valset.MinimalVal, 0, len(heimdallSpan.ValidatorSet.Validators)) - for _, val := range heimdallSpan.ValidatorSet.Validators { - validators = append(validators, val.MinimalVal()) - } - validatorBytes, err := rlp.EncodeToBytes(validators) - if err != nil { - return err - } - - // get producers bytes - producers := make([]valset.MinimalVal, 0, len(heimdallSpan.SelectedProducers)) - for _, val := range heimdallSpan.SelectedProducers { - producers = append(producers, val.MinimalVal()) - } - producerBytes, err := rlp.EncodeToBytes(producers) - if err != nil { - return err - } - - c.logger.Debug("[bor] ✅ Committing new span", - "id", heimdallSpan.ID, - "startBlock", heimdallSpan.StartBlock, - "endBlock", heimdallSpan.EndBlock, - "validatorBytes", hex.EncodeToString(validatorBytes), - "producerBytes", hex.EncodeToString(producerBytes), - ) - - // get packed data - data, err := c.validatorSet.Pack(method, - big.NewInt(0).SetUint64(heimdallSpan.ID), - big.NewInt(0).SetUint64(heimdallSpan.StartBlock), - big.NewInt(0).SetUint64(heimdallSpan.EndBlock), - validatorBytes, - producerBytes, - ) - if err != nil { - c.logger.Error("[bor] Unable to pack tx for commitSpan", "error", err) - return err - } - - _, err = syscall(libcommon.HexToAddress(c.borConfig.ValidatorContract), data) - - return err -} diff --git a/polygon/sync/canonical_chain_builder_test.go b/polygon/sync/canonical_chain_builder_test.go index 0fb0617323c..fec41c509c8 100644 --- a/polygon/sync/canonical_chain_builder_test.go +++ b/polygon/sync/canonical_chain_builder_test.go @@ -9,9 +9,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - heimdallspan "github.com/ledgerwatch/erigon/polygon/heimdall/span" - "github.com/ledgerwatch/erigon/core/types" + heimdallspan "github.com/ledgerwatch/erigon/polygon/heimdall" ) type testDifficultyCalculator struct { diff --git a/polygon/sync/header_downloader_test.go b/polygon/sync/header_downloader_test.go index 7a24a6ab56f..5c430bf4f6a 100644 --- a/polygon/sync/header_downloader_test.go +++ b/polygon/sync/header_downloader_test.go @@ -14,8 +14,7 @@ import ( "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon/core/types" - "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" - "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" + "github.com/ledgerwatch/erigon/polygon/heimdall" "github.com/ledgerwatch/erigon/turbo/testlog" ) @@ -80,11 +79,11 @@ func (hdt headerDownloaderTest) fakePeers(count int, blockNums ...*big.Int) Peer return peers } -func (hdt headerDownloaderTest) fakeCheckpoints(count int) []*checkpoint.Checkpoint { - checkpoints := make([]*checkpoint.Checkpoint, count) +func (hdt headerDownloaderTest) fakeCheckpoints(count int) []*heimdall.Checkpoint { + checkpoints := make([]*heimdall.Checkpoint, count) for i := range checkpoints { num := i + 1 - checkpoints[i] = &checkpoint.Checkpoint{ + checkpoints[i] = &heimdall.Checkpoint{ StartBlock: big.NewInt(int64(num)), EndBlock: big.NewInt(int64(num)), RootHash: common.BytesToHash([]byte(fmt.Sprintf("0x%d", num))), @@ -94,11 +93,11 @@ func (hdt headerDownloaderTest) fakeCheckpoints(count int) []*checkpoint.Checkpo return checkpoints } -func (hdt headerDownloaderTest) fakeMilestones(count int) []*milestone.Milestone { - milestones := make([]*milestone.Milestone, count) +func (hdt headerDownloaderTest) fakeMilestones(count int) []*heimdall.Milestone { + milestones := make([]*heimdall.Milestone, count) for i := range milestones { num := i + 1 - milestones[i] = &milestone.Milestone{ + milestones[i] = &heimdall.Milestone{ StartBlock: big.NewInt(int64(num)), EndBlock: big.NewInt(int64(num)), Hash: common.BytesToHash([]byte(fmt.Sprintf("0x%d", num))), diff --git a/polygon/sync/heimdall.go b/polygon/sync/heimdall.go index b77d58c8e6a..0491b9c2367 100644 --- a/polygon/sync/heimdall.go +++ b/polygon/sync/heimdall.go @@ -8,34 +8,31 @@ import ( "github.com/ledgerwatch/log/v3" - "github.com/ledgerwatch/erigon/polygon/heimdall" - "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" - "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" - "github.com/ledgerwatch/erigon/polygon/heimdall/span" - "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon/polygon/bor" + "github.com/ledgerwatch/erigon/polygon/heimdall" ) // Heimdall is a wrapper of Heimdall HTTP API // //go:generate mockgen -destination=./heimdall_mock.go -package=sync . Heimdall type Heimdall interface { - FetchCheckpoints(ctx context.Context, start uint64) ([]*checkpoint.Checkpoint, error) - FetchMilestones(ctx context.Context, start uint64) ([]*milestone.Milestone, error) - FetchSpan(ctx context.Context, start uint64) (*span.HeimdallSpan, error) - OnMilestoneEvent(ctx context.Context, callback func(*milestone.Milestone)) error + FetchCheckpoints(ctx context.Context, start uint64) ([]*heimdall.Checkpoint, error) + FetchMilestones(ctx context.Context, start uint64) ([]*heimdall.Milestone, error) + FetchSpan(ctx context.Context, start uint64) (*heimdall.HeimdallSpan, error) + OnMilestoneEvent(ctx context.Context, callback func(*heimdall.Milestone)) error } // ErrIncompleteMilestoneRange happens when FetchMilestones is called with an old start block because old milestones are evicted var ErrIncompleteMilestoneRange = errors.New("milestone range doesn't contain the start block") type HeimdallImpl struct { - client heimdall.IHeimdallClient + client heimdall.HeimdallClient pollDelay time.Duration logger log.Logger } -func NewHeimdall(client heimdall.IHeimdallClient, logger log.Logger) Heimdall { +func NewHeimdall(client heimdall.HeimdallClient, logger log.Logger) Heimdall { impl := HeimdallImpl{ client: client, pollDelay: time.Second, @@ -55,21 +52,21 @@ func cmpNumToRange(n uint64, min *big.Int, max *big.Int) int { return 0 } -func cmpBlockNumToCheckpointRange(n uint64, c *checkpoint.Checkpoint) int { +func cmpBlockNumToCheckpointRange(n uint64, c *heimdall.Checkpoint) int { return cmpNumToRange(n, c.StartBlock, c.EndBlock) } -func cmpBlockNumToMilestoneRange(n uint64, m *milestone.Milestone) int { +func cmpBlockNumToMilestoneRange(n uint64, m *heimdall.Milestone) int { return cmpNumToRange(n, m.StartBlock, m.EndBlock) } -func (impl *HeimdallImpl) FetchCheckpoints(ctx context.Context, start uint64) ([]*checkpoint.Checkpoint, error) { +func (impl *HeimdallImpl) FetchCheckpoints(ctx context.Context, start uint64) ([]*heimdall.Checkpoint, error) { count, err := impl.client.FetchCheckpointCount(ctx) if err != nil { return nil, err } - var checkpoints []*checkpoint.Checkpoint + var checkpoints []*heimdall.Checkpoint for i := count; i >= 1; i-- { c, err := impl.client.FetchCheckpoint(ctx, i) @@ -95,13 +92,13 @@ func (impl *HeimdallImpl) FetchCheckpoints(ctx context.Context, start uint64) ([ return checkpoints, nil } -func (impl *HeimdallImpl) FetchMilestones(ctx context.Context, start uint64) ([]*milestone.Milestone, error) { +func (impl *HeimdallImpl) FetchMilestones(ctx context.Context, start uint64) ([]*heimdall.Milestone, error) { count, err := impl.client.FetchMilestoneCount(ctx) if err != nil { return nil, err } - var milestones []*milestone.Milestone + var milestones []*heimdall.Milestone for i := count; i >= 1; i-- { m, err := impl.client.FetchMilestone(ctx, i) @@ -131,11 +128,11 @@ func (impl *HeimdallImpl) FetchMilestones(ctx context.Context, start uint64) ([] return milestones, nil } -func (impl *HeimdallImpl) FetchSpan(ctx context.Context, start uint64) (*span.HeimdallSpan, error) { - return impl.client.Span(ctx, span.IDAt(start)) +func (impl *HeimdallImpl) FetchSpan(ctx context.Context, start uint64) (*heimdall.HeimdallSpan, error) { + return impl.client.Span(ctx, bor.SpanIDAt(start)) } -func (impl *HeimdallImpl) OnMilestoneEvent(ctx context.Context, callback func(*milestone.Milestone)) error { +func (impl *HeimdallImpl) OnMilestoneEvent(ctx context.Context, callback func(*heimdall.Milestone)) error { currentCount, err := impl.client.FetchMilestoneCount(ctx) if err != nil { return err diff --git a/polygon/sync/heimdall_mock.go b/polygon/sync/heimdall_mock.go index 8604e623e8d..ca7d1e1fbf6 100644 --- a/polygon/sync/heimdall_mock.go +++ b/polygon/sync/heimdall_mock.go @@ -9,9 +9,8 @@ import ( reflect "reflect" gomock "github.com/golang/mock/gomock" - checkpoint "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" - milestone "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" - span "github.com/ledgerwatch/erigon/polygon/heimdall/span" + + checkpoint "github.com/ledgerwatch/erigon/polygon/heimdall" ) // MockHeimdall is a mock of Heimdall interface. @@ -53,10 +52,10 @@ func (mr *MockHeimdallMockRecorder) FetchCheckpoints(arg0, arg1 interface{}) *go } // FetchMilestones mocks base method. -func (m *MockHeimdall) FetchMilestones(arg0 context.Context, arg1 uint64) ([]*milestone.Milestone, error) { +func (m *MockHeimdall) FetchMilestones(arg0 context.Context, arg1 uint64) ([]*checkpoint.Milestone, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "FetchMilestones", arg0, arg1) - ret0, _ := ret[0].([]*milestone.Milestone) + ret0, _ := ret[0].([]*checkpoint.Milestone) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -68,10 +67,10 @@ func (mr *MockHeimdallMockRecorder) FetchMilestones(arg0, arg1 interface{}) *gom } // FetchSpan mocks base method. -func (m *MockHeimdall) FetchSpan(arg0 context.Context, arg1 uint64) (*span.HeimdallSpan, error) { +func (m *MockHeimdall) FetchSpan(arg0 context.Context, arg1 uint64) (*checkpoint.HeimdallSpan, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "FetchSpan", arg0, arg1) - ret0, _ := ret[0].(*span.HeimdallSpan) + ret0, _ := ret[0].(*checkpoint.HeimdallSpan) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -83,7 +82,7 @@ func (mr *MockHeimdallMockRecorder) FetchSpan(arg0, arg1 interface{}) *gomock.Ca } // OnMilestoneEvent mocks base method. -func (m *MockHeimdall) OnMilestoneEvent(arg0 context.Context, arg1 func(*milestone.Milestone)) error { +func (m *MockHeimdall) OnMilestoneEvent(arg0 context.Context, arg1 func(*checkpoint.Milestone)) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "OnMilestoneEvent", arg0, arg1) ret0, _ := ret[0].(error) diff --git a/polygon/sync/heimdall_test.go b/polygon/sync/heimdall_test.go index 2d809749d6e..2c4f11c075a 100644 --- a/polygon/sync/heimdall_test.go +++ b/polygon/sync/heimdall_test.go @@ -12,13 +12,10 @@ import ( "github.com/stretchr/testify/require" heimdallclient "github.com/ledgerwatch/erigon/polygon/heimdall" - "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" - "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" - heimdallmock "github.com/ledgerwatch/erigon/polygon/heimdall/mock" ) -func makeCheckpoint(start uint64, len uint) *checkpoint.Checkpoint { - c := checkpoint.Checkpoint{ +func makeCheckpoint(start uint64, len uint) *heimdallclient.Checkpoint { + c := heimdallclient.Checkpoint{ StartBlock: new(big.Int).SetUint64(start), EndBlock: new(big.Int).SetUint64(start + uint64(len) - 1), Timestamp: uint64(time.Now().Unix()), @@ -26,8 +23,8 @@ func makeCheckpoint(start uint64, len uint) *checkpoint.Checkpoint { return &c } -func makeMilestone(start uint64, len uint) *milestone.Milestone { - m := milestone.Milestone{ +func makeMilestone(start uint64, len uint) *heimdallclient.Milestone { + m := heimdallclient.Milestone{ StartBlock: new(big.Int).SetUint64(start), EndBlock: new(big.Int).SetUint64(start + uint64(len) - 1), Timestamp: uint64(time.Now().Unix()), @@ -37,7 +34,7 @@ func makeMilestone(start uint64, len uint) *milestone.Milestone { type heimdallTest struct { ctx context.Context - client *heimdallmock.MockIHeimdallClient + client *heimdallclient.MockHeimdallClient heimdall Heimdall logger log.Logger } @@ -49,7 +46,7 @@ func newHeimdallTest(t *testing.T) heimdallTest { ctrl := gomock.NewController(t) t.Cleanup(ctrl.Finish) - client := heimdallmock.NewMockIHeimdallClient(ctrl) + client := heimdallclient.NewMockHeimdallClient(ctrl) heimdall := NewHeimdall(client, logger) return heimdallTest{ @@ -60,8 +57,8 @@ func newHeimdallTest(t *testing.T) heimdallTest { } } -func (test heimdallTest) setupCheckpoints(count int) []*checkpoint.Checkpoint { - var expectedCheckpoints []*checkpoint.Checkpoint +func (test heimdallTest) setupCheckpoints(count int) []*heimdallclient.Checkpoint { + var expectedCheckpoints []*heimdallclient.Checkpoint for i := 0; i < count; i++ { c := makeCheckpoint(uint64(i*256), 256) expectedCheckpoints = append(expectedCheckpoints, c) @@ -69,15 +66,15 @@ func (test heimdallTest) setupCheckpoints(count int) []*checkpoint.Checkpoint { client := test.client client.EXPECT().FetchCheckpointCount(gomock.Any()).Return(int64(len(expectedCheckpoints)), nil) - client.EXPECT().FetchCheckpoint(gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, number int64) (*checkpoint.Checkpoint, error) { + client.EXPECT().FetchCheckpoint(gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, number int64) (*heimdallclient.Checkpoint, error) { return expectedCheckpoints[number-1], nil }).AnyTimes() return expectedCheckpoints } -func (test heimdallTest) setupMilestones(count int) []*milestone.Milestone { - var expectedMilestones []*milestone.Milestone +func (test heimdallTest) setupMilestones(count int) []*heimdallclient.Milestone { + var expectedMilestones []*heimdallclient.Milestone for i := 0; i < count; i++ { m := makeMilestone(uint64(i*16), 16) expectedMilestones = append(expectedMilestones, m) @@ -85,7 +82,7 @@ func (test heimdallTest) setupMilestones(count int) []*milestone.Milestone { client := test.client client.EXPECT().FetchMilestoneCount(gomock.Any()).Return(int64(len(expectedMilestones)), nil) - client.EXPECT().FetchMilestone(gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, number int64) (*milestone.Milestone, error) { + client.EXPECT().FetchMilestone(gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, number int64) (*heimdallclient.Milestone, error) { return expectedMilestones[number-1], nil }).AnyTimes() @@ -191,7 +188,7 @@ func TestFetchMilestonesMiddleStart(t *testing.T) { func TestFetchMilestonesStartingBeforeEvictionPoint(t *testing.T) { test := newHeimdallTest(t) - var expectedMilestones []*milestone.Milestone + var expectedMilestones []*heimdallclient.Milestone for i := 0; i < 20; i++ { m := makeMilestone(uint64(i*16), 16) expectedMilestones = append(expectedMilestones, m) @@ -200,7 +197,7 @@ func TestFetchMilestonesStartingBeforeEvictionPoint(t *testing.T) { client := test.client client.EXPECT().FetchMilestoneCount(gomock.Any()).Return(int64(len(expectedMilestones)), nil) - client.EXPECT().FetchMilestone(gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, number int64) (*milestone.Milestone, error) { + client.EXPECT().FetchMilestone(gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, number int64) (*heimdallclient.Milestone, error) { if int(number) <= len(expectedMilestones)-keptMilestones { return nil, heimdallclient.ErrNotInMilestoneList } @@ -239,8 +236,8 @@ func TestOnMilestoneEvent(t *testing.T) { expectedMilestone := makeMilestone(0, 12) client.EXPECT().FetchMilestone(gomock.Any(), gomock.Any()).Return(expectedMilestone, nil) - eventChan := make(chan *milestone.Milestone) - err := test.heimdall.OnMilestoneEvent(test.ctx, func(m *milestone.Milestone) { + eventChan := make(chan *heimdallclient.Milestone) + err := test.heimdall.OnMilestoneEvent(test.ctx, func(m *heimdallclient.Milestone) { eventChan <- m }) require.Nil(t, err) diff --git a/polygon/sync/spans_cache.go b/polygon/sync/spans_cache.go index 5c03a422979..6d359849536 100644 --- a/polygon/sync/spans_cache.go +++ b/polygon/sync/spans_cache.go @@ -1,6 +1,8 @@ package sync -import heimdallspan "github.com/ledgerwatch/erigon/polygon/heimdall/span" +import ( + heimdallspan "github.com/ledgerwatch/erigon/polygon/heimdall" +) type SpansCache struct { spans map[uint64]*heimdallspan.HeimdallSpan diff --git a/polygon/sync/state_point.go b/polygon/sync/state_point.go index cad44407de0..c8f9c39971e 100644 --- a/polygon/sync/state_point.go +++ b/polygon/sync/state_point.go @@ -3,13 +3,11 @@ package sync import ( "math/big" - "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" - "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" - "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon/polygon/heimdall" ) -func statePointFromCheckpoint(checkpoint *checkpoint.Checkpoint) *statePoint { +func statePointFromCheckpoint(checkpoint *heimdall.Checkpoint) *statePoint { return &statePoint{ proposer: checkpoint.Proposer, startBlock: new(big.Int).Set(checkpoint.StartBlock), @@ -21,7 +19,7 @@ func statePointFromCheckpoint(checkpoint *checkpoint.Checkpoint) *statePoint { } } -func statePointFromMilestone(milestone *milestone.Milestone) *statePoint { +func statePointFromMilestone(milestone *heimdall.Milestone) *statePoint { return &statePoint{ proposer: milestone.Proposer, startBlock: new(big.Int).Set(milestone.StartBlock), diff --git a/polygon/sync/state_points.go b/polygon/sync/state_points.go index e88c3160ceb..650dc80f99e 100644 --- a/polygon/sync/state_points.go +++ b/polygon/sync/state_points.go @@ -1,11 +1,10 @@ package sync import ( - "github.com/ledgerwatch/erigon/polygon/heimdall/checkpoint" - "github.com/ledgerwatch/erigon/polygon/heimdall/milestone" + "github.com/ledgerwatch/erigon/polygon/heimdall" ) -func statePointsFromCheckpoints(checkpoints []*checkpoint.Checkpoint) statePoints { +func statePointsFromCheckpoints(checkpoints []*heimdall.Checkpoint) statePoints { statePoints := make(statePoints, len(checkpoints)) for i, checkpoint := range checkpoints { statePoints[i] = statePointFromCheckpoint(checkpoint) @@ -14,7 +13,7 @@ func statePointsFromCheckpoints(checkpoints []*checkpoint.Checkpoint) statePoint return statePoints } -func statePointsFromMilestones(milestones []*milestone.Milestone) statePoints { +func statePointsFromMilestones(milestones []*heimdall.Milestone) statePoints { statePoints := make(statePoints, len(milestones)) for i, milestone := range milestones { statePoints[i] = statePointFromMilestone(milestone) diff --git a/turbo/snapshotsync/freezeblocks/block_reader.go b/turbo/snapshotsync/freezeblocks/block_reader.go index e80b5d35916..fc6834937fa 100644 --- a/turbo/snapshotsync/freezeblocks/block_reader.go +++ b/turbo/snapshotsync/freezeblocks/block_reader.go @@ -10,8 +10,6 @@ import ( "github.com/ledgerwatch/log/v3" - "github.com/ledgerwatch/erigon/polygon/heimdall/span" - "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/dbg" "github.com/ledgerwatch/erigon-lib/common/length" @@ -22,6 +20,7 @@ import ( "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/eth/ethconfig" + "github.com/ledgerwatch/erigon/polygon/bor" "github.com/ledgerwatch/erigon/rlp" "github.com/ledgerwatch/erigon/turbo/services" ) @@ -1174,7 +1173,7 @@ func (r *BlockReader) LastFrozenSpanID() uint64 { return 0 } - lastSpanID := span.IDAt(lastSegment.to) + lastSpanID := bor.SpanIDAt(lastSegment.to) if lastSpanID > 0 { lastSpanID-- } @@ -1184,7 +1183,7 @@ func (r *BlockReader) LastFrozenSpanID() uint64 { func (r *BlockReader) Span(ctx context.Context, tx kv.Getter, spanId uint64) ([]byte, error) { var endBlock uint64 if spanId > 0 { - endBlock = span.EndBlockNum(spanId) + endBlock = bor.SpanEndBlockNum(spanId) } var buf [8]byte binary.BigEndian.PutUint64(buf[:], spanId) @@ -1207,11 +1206,11 @@ func (r *BlockReader) Span(ctx context.Context, tx kv.Getter, spanId uint64) ([] if sn.idx == nil { continue } - spanFrom := span.IDAt(sn.from) + spanFrom := bor.SpanIDAt(sn.from) if spanId < spanFrom { continue } - spanTo := span.IDAt(sn.to) + spanTo := bor.SpanIDAt(sn.to) if spanId >= spanTo { continue } diff --git a/turbo/snapshotsync/freezeblocks/block_snapshots.go b/turbo/snapshotsync/freezeblocks/block_snapshots.go index 473af96522f..866a21553d4 100644 --- a/turbo/snapshotsync/freezeblocks/block_snapshots.go +++ b/turbo/snapshotsync/freezeblocks/block_snapshots.go @@ -21,8 +21,6 @@ import ( "golang.org/x/exp/slices" "golang.org/x/sync/errgroup" - "github.com/ledgerwatch/erigon/polygon/heimdall/span" - "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon-lib/chain/snapcfg" common2 "github.com/ledgerwatch/erigon-lib/common" @@ -48,6 +46,7 @@ import ( "github.com/ledgerwatch/erigon/eth/ethconfig/estimate" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" "github.com/ledgerwatch/erigon/params" + "github.com/ledgerwatch/erigon/polygon/bor" "github.com/ledgerwatch/erigon/rlp" "github.com/ledgerwatch/erigon/turbo/services" "github.com/ledgerwatch/erigon/turbo/silkworm" @@ -1476,7 +1475,7 @@ func (br *BlockRetire) PruneAncientBlocks(tx kv.RwTx, limit int) error { canDeleteTo := CanDeleteTo(currentProgress, br.blockReader.FrozenBorBlocks()) br.logger.Info("[snapshots] Prune Bor Blocks", "to", canDeleteTo, "limit", limit) - if err := br.blockWriter.PruneBorBlocks(context.Background(), tx, canDeleteTo, limit, span.IDAt); err != nil { + if err := br.blockWriter.PruneBorBlocks(context.Background(), tx, canDeleteTo, limit, bor.SpanIDAt); err != nil { return err } } diff --git a/turbo/snapshotsync/freezeblocks/bor_snapshots.go b/turbo/snapshotsync/freezeblocks/bor_snapshots.go index 39a683bbfb0..af486ef9347 100644 --- a/turbo/snapshotsync/freezeblocks/bor_snapshots.go +++ b/turbo/snapshotsync/freezeblocks/bor_snapshots.go @@ -17,8 +17,6 @@ import ( "github.com/ledgerwatch/log/v3" "golang.org/x/exp/slices" - "github.com/ledgerwatch/erigon/polygon/heimdall/span" - "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon-lib/chain/snapcfg" common2 "github.com/ledgerwatch/erigon-lib/common" @@ -35,6 +33,7 @@ import ( "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/eth/ethconfig" + "github.com/ledgerwatch/erigon/polygon/bor" "github.com/ledgerwatch/erigon/turbo/services" ) @@ -377,8 +376,8 @@ func DumpBorEvents(ctx context.Context, db kv.RoDB, blockFrom, blockTo uint64, w func DumpBorSpans(ctx context.Context, db kv.RoDB, blockFrom, blockTo uint64, workers int, lvl log.Lvl, logger log.Logger, collect func([]byte) error) error { logEvery := time.NewTicker(20 * time.Second) defer logEvery.Stop() - spanFrom := span.IDAt(blockFrom) - spanTo := span.IDAt(blockTo) + spanFrom := bor.SpanIDAt(blockFrom) + spanTo := bor.SpanIDAt(blockTo) from := hexutility.EncodeTs(spanFrom) if err := kv.BigChunks(db, kv.BorSpans, from, func(tx kv.Tx, spanIdBytes, spanBytes []byte) (bool, error) { spanId := binary.BigEndian.Uint64(spanIdBytes) @@ -509,7 +508,7 @@ func BorSpansIdx(ctx context.Context, segmentFilePath string, version uint8, blo g := d.MakeGetter() var idxFilePath = filepath.Join(snapDir, snaptype.IdxFileName(version, blockFrom, blockTo, snaptype.BorSpans.String())) - baseSpanId := span.IDAt(blockFrom) + baseSpanId := bor.SpanIDAt(blockFrom) rs, err := recsplit.NewRecSplit(recsplit.RecSplitArgs{ KeyCount: d.Count(), diff --git a/turbo/stages/stageloop.go b/turbo/stages/stageloop.go index 95db1e1e84f..35aab454bcd 100644 --- a/turbo/stages/stageloop.go +++ b/turbo/stages/stageloop.go @@ -20,6 +20,7 @@ import ( "github.com/ledgerwatch/erigon-lib/kv/membatchwithdb" "github.com/ledgerwatch/erigon-lib/state" "github.com/ledgerwatch/erigon-lib/wrap" + "github.com/ledgerwatch/erigon/polygon/bor/finality" "github.com/ledgerwatch/erigon/polygon/heimdall" @@ -471,7 +472,7 @@ func NewDefaultStages(ctx context.Context, agg *state.AggregatorV3, silkworm *silkworm.Silkworm, forkValidator *engine_helpers.ForkValidator, - heimdallClient heimdall.IHeimdallClient, + heimdallClient heimdall.HeimdallClient, recents *lru.ARCCache[libcommon.Hash, *bor.Snapshot], signatures *lru.ARCCache[libcommon.Hash, libcommon.Address], logger log.Logger, @@ -487,7 +488,7 @@ func NewDefaultStages(ctx context.Context, if heimdallClient != nil && flags.Milestone { loopBreakCheck = func(int) bool { - return heimdall.MilestoneRewindPending() + return finality.IsMilestoneRewindPending() } } From e979d79c08def4c5b1944d8e335f41c16df1d29f Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Tue, 16 Jan 2024 09:34:31 +0100 Subject: [PATCH 70/92] p2p: panic in enode DB Close on shutdown (#9237) (#9240) If any DB method is called while Close() is waiting for db.kv.Close() (it waits for ongoing method calls/transactions to finish) a panic: "WaitGroup is reused before previous Wait has returned" might happen. Use context cancellation to ensure that new method calls immediately return during db.kv.Close(). --- p2p/enode/nodedb.go | 84 ++++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 40 deletions(-) diff --git a/p2p/enode/nodedb.go b/p2p/enode/nodedb.go index 34f1cc1f334..b955a7a29f5 100644 --- a/p2p/enode/nodedb.go +++ b/p2p/enode/nodedb.go @@ -29,14 +29,13 @@ import ( "time" "github.com/c2h5oh/datasize" + mdbx1 "github.com/erigontech/mdbx-go/mdbx" + "github.com/ledgerwatch/log/v3" + libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/mdbx" - "github.com/ledgerwatch/erigon/rlp" - "github.com/ledgerwatch/log/v3" - - mdbx1 "github.com/erigontech/mdbx-go/mdbx" ) // Keys in the node database. @@ -75,16 +74,18 @@ var zeroIP = make(net.IP, 16) // DB is the node database, storing previously seen nodes and any collected metadata about // them for QoS purposes. type DB struct { - kv kv.RwDB // Interface to the database itself - runner sync.Once // Ensures we can start at most one expirer - quit chan struct{} // Channel to signal the expiring thread to stop + kv kv.RwDB // Interface to the database itself + runner sync.Once // Ensures we can start at most one expirer + + ctx context.Context + ctxCancel func() } // OpenDB opens a node database for storing and retrieving infos about known peers in the // network. If no path is given an in-memory, temporary database is constructed. func OpenDB(ctx context.Context, path string, tmpDir string, logger log.Logger) (*DB, error) { if path == "" { - return newMemoryDB(logger, tmpDir) + return newMemoryDB(ctx, logger, tmpDir) } return newPersistentDB(ctx, logger, path) } @@ -97,22 +98,27 @@ func bucketsConfig(_ kv.TableCfg) kv.TableCfg { } // newMemoryNodeDB creates a new in-memory node database without a persistent backend. -func newMemoryDB(logger log.Logger, tmpDir string) (*DB, error) { - db := &DB{quit: make(chan struct{})} - var err error - db.kv, err = mdbx.NewMDBX(logger).InMem(tmpDir).Label(kv.SentryDB).WithTableCfg(bucketsConfig).MapSize(1 * datasize.GB).Open(context.Background()) +func newMemoryDB(ctx context.Context, logger log.Logger, tmpDir string) (*DB, error) { + db, err := mdbx.NewMDBX(logger). + InMem(tmpDir). + Label(kv.SentryDB). + WithTableCfg(bucketsConfig). + MapSize(1 * datasize.GB). + Open(ctx) if err != nil { return nil, err } - return db, nil + + nodeDB := &DB{kv: db} + nodeDB.ctx, nodeDB.ctxCancel = context.WithCancel(ctx) + + return nodeDB, nil } // newPersistentNodeDB creates/opens a persistent node database, // also flushing its contents in case of a version mismatch. func newPersistentDB(ctx context.Context, logger log.Logger, path string) (*DB, error) { - var db kv.RwDB - var err error - db, err = mdbx.NewMDBX(logger). + db, err := mdbx.NewMDBX(logger). Path(path). Label(kv.SentryDB). WithTableCfg(bucketsConfig). @@ -125,13 +131,14 @@ func newPersistentDB(ctx context.Context, logger log.Logger, path string) (*DB, if err != nil { return nil, err } + // The nodes contained in the cache correspond to a certain protocol version. // Flush all nodes if the version doesn't match. currentVer := make([]byte, binary.MaxVarintLen64) currentVer = currentVer[:binary.PutVarint(currentVer, int64(dbVersion))] var blob []byte - if err := db.Update(context.Background(), func(tx kv.RwTx) error { + if err := db.Update(ctx, func(tx kv.RwTx) error { c, err := tx.RwCursor(kv.Inodes) if err != nil { return err @@ -150,6 +157,7 @@ func newPersistentDB(ctx context.Context, logger log.Logger, path string) (*DB, }); err != nil { return nil, err } + if blob != nil && !bytes.Equal(blob, currentVer) { db.Close() if err := os.RemoveAll(path); err != nil { @@ -157,7 +165,11 @@ func newPersistentDB(ctx context.Context, logger log.Logger, path string) (*DB, } return newPersistentDB(ctx, logger, path) } - return &DB{kv: db, quit: make(chan struct{})}, nil + + nodeDB := &DB{kv: db} + nodeDB.ctx, nodeDB.ctxCancel = context.WithCancel(ctx) + + return nodeDB, nil } // nodeKey returns the database key for a node record. @@ -227,7 +239,7 @@ func localItemKey(id ID, field string) []byte { // fetchInt64 retrieves an integer associated with a particular key. func (db *DB) fetchInt64(key []byte) int64 { var val int64 - if err := db.kv.View(context.Background(), func(tx kv.Tx) error { + if err := db.kv.View(db.ctx, func(tx kv.Tx) error { blob, errGet := tx.GetOne(kv.Inodes, key) if errGet != nil { return errGet @@ -249,7 +261,7 @@ func (db *DB) fetchInt64(key []byte) int64 { func (db *DB) storeInt64(key []byte, n int64) error { blob := make([]byte, binary.MaxVarintLen64) blob = blob[:binary.PutVarint(blob, n)] - return db.kv.Update(context.Background(), func(tx kv.RwTx) error { + return db.kv.Update(db.ctx, func(tx kv.RwTx) error { return tx.Put(kv.Inodes, libcommon.CopyBytes(key), blob) }) } @@ -257,7 +269,7 @@ func (db *DB) storeInt64(key []byte, n int64) error { // fetchUint64 retrieves an integer associated with a particular key. func (db *DB) fetchUint64(key []byte) uint64 { var val uint64 - if err := db.kv.View(context.Background(), func(tx kv.Tx) error { + if err := db.kv.View(db.ctx, func(tx kv.Tx) error { blob, errGet := tx.GetOne(kv.Inodes, key) if errGet != nil { return errGet @@ -276,7 +288,7 @@ func (db *DB) fetchUint64(key []byte) uint64 { func (db *DB) storeUint64(key []byte, n uint64) error { blob := make([]byte, binary.MaxVarintLen64) blob = blob[:binary.PutUvarint(blob, n)] - return db.kv.Update(context.Background(), func(tx kv.RwTx) error { + return db.kv.Update(db.ctx, func(tx kv.RwTx) error { return tx.Put(kv.Inodes, libcommon.CopyBytes(key), blob) }) } @@ -284,7 +296,7 @@ func (db *DB) storeUint64(key []byte, n uint64) error { // Node retrieves a node with a given id from the database. func (db *DB) Node(id ID) *Node { var blob []byte - if err := db.kv.View(context.Background(), func(tx kv.Tx) error { + if err := db.kv.View(db.ctx, func(tx kv.Tx) error { v, errGet := tx.GetOne(kv.NodeRecords, nodeKey(id)) if errGet != nil { return errGet @@ -322,7 +334,7 @@ func (db *DB) UpdateNode(node *Node) error { if err != nil { return err } - if err := db.kv.Update(context.Background(), func(tx kv.RwTx) error { + if err := db.kv.Update(db.ctx, func(tx kv.RwTx) error { return tx.Put(kv.NodeRecords, nodeKey(node.ID()), blob) }); err != nil { return err @@ -346,11 +358,11 @@ func (db *DB) Resolve(n *Node) *Node { // DeleteNode deletes all information associated with a node. func (db *DB) DeleteNode(id ID) { - deleteRange(db.kv, nodeKey(id)) + db.deleteRange(nodeKey(id)) } -func deleteRange(db kv.RwDB, prefix []byte) { - if err := db.Update(context.Background(), func(tx kv.RwTx) error { +func (db *DB) deleteRange(prefix []byte) { + if err := db.kv.Update(db.ctx, func(tx kv.RwTx) error { for bucket := range bucketsConfig(nil) { if err := deleteRangeInBucket(tx, prefix, bucket); err != nil { return err @@ -398,7 +410,7 @@ func (db *DB) expirer() { select { case <-tick.C: db.expireNodes() - case <-db.quit: + case <-db.ctx.Done(): return } } @@ -412,7 +424,7 @@ func (db *DB) expireNodes() { youngestPong int64 ) var toDelete [][]byte - if err := db.kv.View(context.Background(), func(tx kv.Tx) error { + if err := db.kv.View(db.ctx, func(tx kv.Tx) error { c, err := tx.Cursor(kv.Inodes) if err != nil { return err @@ -455,7 +467,7 @@ func (db *DB) expireNodes() { log.Warn("nodeDB.expireNodes failed", "err", err) } for _, td := range toDelete { - deleteRange(db.kv, td) + db.deleteRange(td) } } @@ -545,7 +557,7 @@ func (db *DB) QuerySeeds(n int, maxAge time.Duration) []*Node { id ID ) - if err := db.kv.View(context.Background(), func(tx kv.Tx) error { + if err := db.kv.View(db.ctx, func(tx kv.Tx) error { c, err := tx.Cursor(kv.NodeRecords) if err != nil { return err @@ -603,14 +615,6 @@ func (db *DB) QuerySeeds(n int, maxAge time.Duration) []*Node { // close flushes and closes the database files. func (db *DB) Close() { - select { - case <-db.quit: - return // means closed already - default: - } - if db.quit == nil { - return - } - libcommon.SafeClose(db.quit) + db.ctxCancel() db.kv.Close() } From a1eee5eb8b5ab53bfb212bf60e885ccadca08e6e Mon Sep 17 00:00:00 2001 From: ddl Date: Wed, 17 Jan 2024 15:21:39 +0800 Subject: [PATCH 71/92] fix udpOrHttpTrackers amount (#9245) seems we just choose the first 8 trackers in https://github.com/ledgerwatch/trackerslist/blob/master/trackers_best.txt. --- erigon-lib/downloader/util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erigon-lib/downloader/util.go b/erigon-lib/downloader/util.go index f169064e86a..b7ee2525756 100644 --- a/erigon-lib/downloader/util.go +++ b/erigon-lib/downloader/util.go @@ -47,7 +47,7 @@ import ( "github.com/ledgerwatch/erigon-lib/kv" ) -// udpOrHttpTrackers - torrent library spawning several goroutines and producing many requests for each tracker. So we limit amout of trackers by 7 +// udpOrHttpTrackers - torrent library spawning several goroutines and producing many requests for each tracker. So we limit amout of trackers by 8 var udpOrHttpTrackers = []string{ "udp://tracker.opentrackr.org:1337/announce", "udp://9.rarbg.com:2810/announce", From 26ce6aa88befc14a2e5f43db4d39fdbe2dfa868f Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Wed, 17 Jan 2024 14:21:51 +0700 Subject: [PATCH 72/92] return 1 lost mainnet file (#9242) --- erigon-lib/go.mod | 2 +- erigon-lib/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/erigon-lib/go.mod b/erigon-lib/go.mod index 8ca0787b1a3..e424d2cb2c8 100644 --- a/erigon-lib/go.mod +++ b/erigon-lib/go.mod @@ -4,7 +4,7 @@ go 1.20 require ( github.com/erigontech/mdbx-go v0.27.21 - github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240101230756-23fbc6c56a1d + github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240115083615-b5feeb63e191 github.com/ledgerwatch/interfaces v0.0.0-20240105174738-fe57049f198c github.com/ledgerwatch/log/v3 v3.9.0 github.com/ledgerwatch/secp256k1 v1.0.0 diff --git a/erigon-lib/go.sum b/erigon-lib/go.sum index f91070155b8..126b278b19e 100644 --- a/erigon-lib/go.sum +++ b/erigon-lib/go.sum @@ -293,8 +293,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= -github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240101230756-23fbc6c56a1d h1:rMqDEGLdmVgGdpDmaNp4Do1vc9BtUQ3rjFD9gQBRSx0= -github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240101230756-23fbc6c56a1d/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo= +github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240115083615-b5feeb63e191 h1:X/mHEyh0xEuhixj6hKCNQl04NuNDToYWJ08vr66e6L0= +github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240115083615-b5feeb63e191/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo= github.com/ledgerwatch/interfaces v0.0.0-20240105174738-fe57049f198c h1:j9IrDNf6oTtc9R+1rra3Umf7xIYvTgJWXsCavGcqv7k= github.com/ledgerwatch/interfaces v0.0.0-20240105174738-fe57049f198c/go.mod h1:ugQv1QllJzBny3cKZKxUrSnykkjkBgm27eQM6dnGAcc= github.com/ledgerwatch/log/v3 v3.9.0 h1:iDwrXe0PVwBC68Dd94YSsHbMgQ3ufsgjzXtFNFVZFRk= diff --git a/go.mod b/go.mod index f2ab6ea4449..4aaa1848490 100644 --- a/go.mod +++ b/go.mod @@ -193,7 +193,7 @@ require ( github.com/koron/go-ssdp v0.0.4 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240101230756-23fbc6c56a1d // indirect + github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240115083615-b5feeb63e191 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-flow-metrics v0.1.0 // indirect diff --git a/go.sum b/go.sum index afc6c4286ef..5484d069ca9 100644 --- a/go.sum +++ b/go.sum @@ -559,8 +559,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758 h1:0D5M2HQSGD3PYPwICLl+/9oulQauOuETfgFvhBDffs0= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240101230756-23fbc6c56a1d h1:rMqDEGLdmVgGdpDmaNp4Do1vc9BtUQ3rjFD9gQBRSx0= -github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240101230756-23fbc6c56a1d/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo= +github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240115083615-b5feeb63e191 h1:X/mHEyh0xEuhixj6hKCNQl04NuNDToYWJ08vr66e6L0= +github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240115083615-b5feeb63e191/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo= github.com/ledgerwatch/log/v3 v3.9.0 h1:iDwrXe0PVwBC68Dd94YSsHbMgQ3ufsgjzXtFNFVZFRk= github.com/ledgerwatch/log/v3 v3.9.0/go.mod h1:EiAY6upmI/6LkNhOVxb4eVsmsP11HZCnZ3PlJMjYiqE= github.com/ledgerwatch/secp256k1 v1.0.0 h1:Usvz87YoTG0uePIV8woOof5cQnLXGYa162rFf3YnwaQ= From dd010bbb31fccab1273982507b08d10b5c084016 Mon Sep 17 00:00:00 2001 From: Michelangelo Riccobene Date: Wed, 17 Jan 2024 08:23:07 +0100 Subject: [PATCH 73/92] qa tests: add clean exit test on block downloading (#9238) This test uses a pre-built database to test Erigon's behaviour on ctrl-c during the block download phase (Caplin sync). --- .../qa-clean-exit-block-downloading.yml | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 .github/workflows/qa-clean-exit-block-downloading.yml diff --git a/.github/workflows/qa-clean-exit-block-downloading.yml b/.github/workflows/qa-clean-exit-block-downloading.yml new file mode 100644 index 00000000000..73104382ce8 --- /dev/null +++ b/.github/workflows/qa-clean-exit-block-downloading.yml @@ -0,0 +1,81 @@ +name: QA - Clean exit (block downloading) + +on: + push: + branches: + - 'release/**' + pull_request: + branches: + - devel + - 'release/**' + types: + - ready_for_review + +jobs: + long-running-test: + runs-on: self-hosted + env: + ERIGON_REFERENCE_DATA_DIR: /opt/erigon-release/datadir + ERIGON_TESTBED_DATA_DIR: /opt/erigon-testbed/datadir + WORKING_TIME_SECONDS: 600 + + steps: + - name: Check out repository + uses: actions/checkout@v2 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: '1.21' + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.x' + + #- name: Install dependencies + # run: | + # sudo apt-get update + # sudo apt-get install -y build-essential make gcc + + - name: Restore Erigon Testbed Data Directory + run: | + rsync -av --delete $ERIGON_REFERENCE_DATA_DIR/ $ERIGON_TESTBED_DATA_DIR/ + + - name: Clean Erigon Build Directory + run: | + make clean + + - name: Build Erigon + run: | + make erigon + working-directory: ${{ github.workspace }} + + #- name: Download Python Script for Logs Checking + # run: | + # curl -o check_erigon_exit.py 'https://gist.githubusercontent.com/mriccobene/8db4030a745de34d527f136f2caa104f/raw/3c1a860cb87d61075e78ce399e17f0ab157cacc6/check_erigon_exit.py' + + - name: Run Erigon, send ctrl-c and check for clean exiting + run: | + # Run Erigon, send ctrl-c and check logs + python3 ${{ github.workspace }}/../../../../erigon-qa/test_system/qa-tests/clean-exit/run_and_check_clean_exit.py ${{ github.workspace }}/build/bin $ERIGON_TESTBED_DATA_DIR $WORKING_TIME_SECONDS + + # Capture monitoring script exit status + monitoring_exit_status=$? + + # Clean up Erigon process if it's still running + if kill -0 $ERIGON_PID 2> /dev/null; then + echo "Terminating Erigon" + kill $ERIGON_PID + wait $ERIGON_PID + else + echo "Erigon has already terminated" + fi + + # Check monitoring script exit status + if [ $monitoring_exit_status -eq 0 ]; then + echo "Monitoring completed successfully" + else + echo "Error detected in Erigon logs or monitoring script exited unexpectedly" + exit 1 + fi From e1195bad2ab32c4c5bbbcff15c31076257f5e4ad Mon Sep 17 00:00:00 2001 From: Arun Sathiya Date: Tue, 16 Jan 2024 23:23:20 -0800 Subject: [PATCH 74/92] ci: Use GITHUB_OUTPUT envvar instead of set-output command (#9215) `save-state` and `set-output` commands used in GitHub Actions are deprecated and [GitHub recommends using environment files](https://github.blog/changelog/2023-07-24-github-actions-update-on-save-state-and-set-output-commands/). This PR updates the usage of `set-output` to `$GITHUB_OUTPUT` Instructions for envvar usage from GitHub docs: https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-output-parameter --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e3e0d0e2499..9b61c414e24 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -47,7 +47,7 @@ jobs: id: prepare run: | TAG=${GITHUB_REF#refs/tags/} - echo ::set-output name=tag_name::${TAG} + echo "tag_name=${TAG}" >> $GITHUB_OUTPUT - name: Set up QEMU uses: docker/setup-qemu-action@v2 From e1a1c0c049c04ddd85726c0f204724bb4728513e Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Wed, 17 Jan 2024 10:06:18 +0100 Subject: [PATCH 75/92] Caplin: Fixed goroutine hell (#9246) --- cl/cltypes/blinded_beacon_block.go | 4 ++ .../format/snapshot_format/blocks.go | 29 +++++++++++ .../format/snapshot_format/blocks_test.go | 12 ++++- cl/phase1/forkchoice/forkchoice.go | 2 + cl/phase1/forkchoice/on_attestation.go | 50 +++++++++++++++---- cmd/caplin/caplin1/run.go | 2 + 6 files changed, 89 insertions(+), 10 deletions(-) diff --git a/cl/cltypes/blinded_beacon_block.go b/cl/cltypes/blinded_beacon_block.go index ca62b8580d0..f15a6d83c66 100644 --- a/cl/cltypes/blinded_beacon_block.go +++ b/cl/cltypes/blinded_beacon_block.go @@ -309,6 +309,10 @@ func (b *SignedBlindedBeaconBlock) Clone() clonable.Clonable { return NewSignedBlindedBeaconBlock(b.Block.Body.beaconCfg) } +func (b *BlindedBeaconBody) ExecutionPayloadMerkleProof() ([][32]byte, error) { + return merkle_tree.MerkleProof(4, 9, b.getSchema(false)...) +} + // make sure that the type implements the interface ssz2.ObjectSSZ var _ ssz2.ObjectSSZ = (*BlindedBeaconBody)(nil) var _ ssz2.ObjectSSZ = (*BlindedBeaconBlock)(nil) diff --git a/cl/persistence/format/snapshot_format/blocks.go b/cl/persistence/format/snapshot_format/blocks.go index 3692a6de30b..11f68d4b8e5 100644 --- a/cl/persistence/format/snapshot_format/blocks.go +++ b/cl/persistence/format/snapshot_format/blocks.go @@ -156,3 +156,32 @@ func ReadBlockHeaderFromSnapshotWithExecutionData(r io.Reader, cfg *clparams.Bea blockHash := blindedBlock.Block.Body.ExecutionPayload.BlockHash return blockHeader, blockNumber, blockHash, nil } + +func ReadBlindedBlockFromSnapshot(r io.Reader, cfg *clparams.BeaconChainConfig) (*cltypes.SignedBlindedBeaconBlock, error) { + buffer := buffersPool.Get().(*bytes.Buffer) + defer buffersPool.Put(buffer) + buffer.Reset() + + blindedBlock := cltypes.NewSignedBlindedBeaconBlock(cfg) + + // Read the metadata + metadataSlab := make([]byte, 33) + v, _, err := readMetadataForBlock(r, metadataSlab) + if err != nil { + return nil, err + } + // Read the length + length := make([]byte, 8) + if _, err := io.ReadFull(r, length); err != nil { + return nil, err + } + // Read the block + if _, err := io.CopyN(buffer, r, int64(binary.BigEndian.Uint64(length))); err != nil { + return nil, err + } + // Decode the block in blinded + if err := blindedBlock.DecodeSSZ(buffer.Bytes(), int(v)); err != nil { + return nil, err + } + return blindedBlock, nil +} diff --git a/cl/persistence/format/snapshot_format/blocks_test.go b/cl/persistence/format/snapshot_format/blocks_test.go index 8c357fd4b01..eae38978810 100644 --- a/cl/persistence/format/snapshot_format/blocks_test.go +++ b/cl/persistence/format/snapshot_format/blocks_test.go @@ -74,12 +74,22 @@ func TestBlockSnapshotEncoding(t *testing.T) { require.NoError(t, err) hash3, err := header.HashSSZ() require.NoError(t, err) - + // now do it with blinded require.Equal(t, hash1, hash2) require.Equal(t, header.Signature, blk.Signature) require.Equal(t, header.Header.Slot, blk.Block.Slot) + b.Reset() + _, err = snapshot_format.WriteBlockForSnapshot(&b, blk, nil) + require.NoError(t, err) + blk4, err := snapshot_format.ReadBlindedBlockFromSnapshot(&b, &clparams.MainnetBeaconConfig) + require.NoError(t, err) + + hash4, err := blk4.HashSSZ() + require.NoError(t, err) + require.Equal(t, hash1, hash4) + if blk.Version() >= clparams.BellatrixVersion { require.Equal(t, bn, blk.Block.Body.ExecutionPayload.BlockNumber) require.Equal(t, bHash, blk.Block.Body.ExecutionPayload.BlockHash) diff --git a/cl/phase1/forkchoice/forkchoice.go b/cl/phase1/forkchoice/forkchoice.go index 1e87939540b..689c8240d3a 100644 --- a/cl/phase1/forkchoice/forkchoice.go +++ b/cl/phase1/forkchoice/forkchoice.go @@ -80,6 +80,8 @@ type ForkChoiceStore struct { unrealizedJustifiedCheckpoint solid.Checkpoint unrealizedFinalizedCheckpoint solid.Checkpoint proposerBoostRoot libcommon.Hash + // attestations that are not yet processed + attestationSet sync.Map // head data headHash libcommon.Hash headSlot uint64 diff --git a/cl/phase1/forkchoice/on_attestation.go b/cl/phase1/forkchoice/on_attestation.go index 3e80efac4e8..3c59c4c2eb8 100644 --- a/cl/phase1/forkchoice/on_attestation.go +++ b/cl/phase1/forkchoice/on_attestation.go @@ -13,6 +13,8 @@ import ( libcommon "github.com/ledgerwatch/erigon-lib/common" ) +const maxAttestationJobLifetime = 30 * time.Minute + // OnAttestation processes incoming attestations. func (f *ForkChoiceStore) OnAttestation(attestation *solid.Attestation, fromBlock bool, insert bool) error { if !f.synced.Load() { @@ -81,6 +83,10 @@ func (f *ForkChoiceStore) OnAggregateAndProof(aggregateAndProof *cltypes.SignedA committeeIndex := aggregateAndProof.Message.Aggregate.AttestantionData().ValidatorIndex() epoch := state.GetEpochAtSlot(f.beaconCfg, slot) + if err := f.validateOnAttestation(aggregateAndProof.Message.Aggregate, false); err != nil { + return err + } + target := aggregateAndProof.Message.Aggregate.AttestantionData().Target() targetState, err := f.getCheckpointState(target) if err != nil { @@ -101,22 +107,48 @@ func (f *ForkChoiceStore) OnAggregateAndProof(aggregateAndProof *cltypes.SignedA return f.OnAttestation(aggregateAndProof.Message.Aggregate, false, false) } +type attestationJob struct { + attestation *solid.Attestation + insert bool + when time.Time +} + // scheduleAttestationForLaterProcessing scheudules an attestation for later processing func (f *ForkChoiceStore) scheduleAttestationForLaterProcessing(attestation *solid.Attestation, insert bool) { + root, err := attestation.HashSSZ() + if err != nil { + log.Error("failed to hash attestation", "err", err) + return + } + f.attestationSet.Store(root, &attestationJob{ + attestation: attestation, + insert: insert, + when: time.Now(), + }) +} + +func (f *ForkChoiceStore) StartAttestationsRTT() { go func() { - logInterval := time.NewTicker(50 * time.Millisecond) + interval := time.NewTicker(500 * time.Millisecond) for { select { case <-f.ctx.Done(): return - case <-logInterval.C: - if f.Slot() < attestation.AttestantionData().Slot()+1 { - continue - } - if err := f.OnAttestation(attestation, false, insert); err != nil { - log.Debug("could not process scheduled attestation", "reason", err) - } - return + case <-interval.C: + f.attestationSet.Range(func(key, value interface{}) bool { + job := value.(*attestationJob) + if time.Since(job.when) > maxAttestationJobLifetime { + f.attestationSet.Delete(key) + return true + } + if f.Slot() >= job.attestation.AttestantionData().Slot()+1 { + if err := f.OnAttestation(job.attestation, false, job.insert); err != nil { + log.Warn("failed to process attestation", "err", err) + } + f.attestationSet.Delete(key) + } + return true + }) } } }() diff --git a/cmd/caplin/caplin1/run.go b/cmd/caplin/caplin1/run.go index 6edd4857287..a2b27138178 100644 --- a/cmd/caplin/caplin1/run.go +++ b/cmd/caplin/caplin1/run.go @@ -226,6 +226,8 @@ func RunCaplinPhase1(ctx context.Context, sentinel sentinel.SentinelClient, engi log.Info("Beacon API started", "addr", cfg.Address) } + forkChoice.StartAttestationsRTT() + stageCfg := stages.ClStagesCfg(beaconRpc, antiq, genesisConfig, beaconConfig, state, engine, gossipManager, forkChoice, historyDB, indexDB, csn, dirs.Tmp, dbConfig, backfilling, syncedDataManager) sync := stages.ConsensusClStages(ctx, stageCfg) From 8f6fe88b29c9eefb5e017caa8c04a1dadff4eba9 Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Wed, 17 Jan 2024 11:50:13 +0100 Subject: [PATCH 76/92] Update TestGoerliForkDigest after Dencun (#9251) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current fork digest for Görli has changed after the [Dencun upgrade](https://blog.ethereum.org/2024/01/10/goerli-dencun-announcement) on 17 Jan. --- cl/fork/fork_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cl/fork/fork_test.go b/cl/fork/fork_test.go index 8e272facf2f..568be1e4dc5 100644 --- a/cl/fork/fork_test.go +++ b/cl/fork/fork_test.go @@ -56,7 +56,7 @@ func TestGoerliForkDigest(t *testing.T) { require.NoError(t, err) _, err = ComputeForkId(&beaconCfg, &genesisCfg) require.NoError(t, err) - require.Equal(t, [4]uint8{0x62, 0x89, 0x41, 0xef}, digest) + require.Equal(t, [4]uint8{0xa7, 0x5d, 0xcc, 0xf2}, digest) } func TestSepoliaForkDigest(t *testing.T) { From b38e17e393de1da0ce4ff892544751cc158199fb Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Wed, 17 Jan 2024 14:13:16 +0100 Subject: [PATCH 77/92] Implement PIP-33: Napoli Hardfork (#8975) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Initial support of the upcoming Napoli hard fork on Polygon – see [PIP-33](https://forum.polygon.technology/t/pip-33-napoli-upgrade). Per [PIP-31](https://github.com/maticnetwork/Polygon-Improvement-Proposals/blob/main/PIPs/PIP-31.md), it parallels the [Cancun](https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/cancun.md) upgrade of Ethereum, but does not include [EIP-4788](https://eips.ethereum.org/EIPS/eip-4788), [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844), [EIP-7516](https://eips.ethereum.org/EIPS/eip-7516). In other words, Napoli includes [EIP-1153](https://eips.ethereum.org/EIPS/eip-1153), [EIP-5656](https://eips.ethereum.org/EIPS/eip-5656), [EIP-6780](https://eips.ethereum.org/EIPS/eip-6780) from Cancun. This PR implements [PIP-31](https://github.com/maticnetwork/Polygon-Improvement-Proposals/blob/main/PIPs/PIP-31.md), [PIP-16: Transaction Dependency Data](https://github.com/maticnetwork/Polygon-Improvement-Proposals/blob/main/PIPs/PIP-16.md) (by merging `ParallelUniverseBlock` into `NapoliBlock`; the bulk of PIP-16 was implemented in PR #8037), and [PIP-27: Precompiled for secp256r1 Curve Support](https://github.com/maticnetwork/Polygon-Improvement-Proposals/blob/main/PIPs/PIP-27.md) ([EIP-7212](https://eips.ethereum.org/EIPS/eip-7212); see also https://github.com/maticnetwork/bor/pull/1069 & https://github.com/ethereum/go-ethereum/pull/27540). --------- Co-authored-by: Anshal Shukla --- core/forkid/forkid.go | 9 +++- core/types/block_test.go | 2 +- core/vm/contracts.go | 57 +++++++++++++++++++- core/vm/contracts_test.go | 57 +++++++++++++------- core/vm/evm.go | 2 + core/vm/interpreter.go | 2 + core/vm/jump_table.go | 11 +++- core/vm/testdata/precompiles/p256Verify.json | 37 +++++++++++++ crypto/secp256r1/publickey.go | 26 +++++++++ crypto/secp256r1/verifier.go | 21 ++++++++ erigon-lib/chain/chain_config.go | 20 +++++-- erigon-lib/txpool/pool.go | 2 +- params/protocol_params.go | 3 ++ polygon/bor/bor.go | 8 +-- polygon/bor/borcfg/bor_config.go | 25 ++++----- 15 files changed, 231 insertions(+), 51 deletions(-) create mode 100644 core/vm/testdata/precompiles/p256Verify.json create mode 100644 crypto/secp256r1/publickey.go create mode 100644 crypto/secp256r1/verifier.go diff --git a/core/forkid/forkid.go b/core/forkid/forkid.go index f5c51cb3c1e..7e5202657cd 100644 --- a/core/forkid/forkid.go +++ b/core/forkid/forkid.go @@ -244,8 +244,13 @@ func GatherForks(config *chain.Config, genesisTime uint64) (heightForks []uint64 heightForks = append(heightForks, *config.Aura.PosdaoTransition) } - if config.Bor != nil && config.Bor.GetAgraBlock() != nil { - heightForks = append(heightForks, config.Bor.GetAgraBlock().Uint64()) + if config.Bor != nil { + if config.Bor.GetAgraBlock() != nil { + heightForks = append(heightForks, config.Bor.GetAgraBlock().Uint64()) + } + if config.Bor.GetNapoliBlock() != nil { + heightForks = append(heightForks, config.Bor.GetNapoliBlock().Uint64()) + } } // Sort the fork block numbers & times to permit chronological XOR diff --git a/core/types/block_test.go b/core/types/block_test.go index 4e2a8303d3f..9db421134ac 100644 --- a/core/types/block_test.go +++ b/core/types/block_test.go @@ -42,7 +42,7 @@ import ( // the following 2 functions are replica for the test // This is a replica of `bor.GetValidatorBytes` function -// This was needed because currently, `IsParallelUniverse` will always return false. +// This was needed because currently, `IsNapoli` will always return false. func GetValidatorBytesTest(h *Header) []byte { if len(h.Extra) < ExtraVanityLength+ExtraSealLength { log.Error("length of extra is less than vanity and seal") diff --git a/core/vm/contracts.go b/core/vm/contracts.go index ccc55074486..b71f949ef1f 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -20,13 +20,13 @@ import ( "crypto/sha256" "encoding/binary" "errors" - "github.com/ledgerwatch/erigon-lib/crypto/blake2b" "math/big" "github.com/holiman/uint256" "github.com/ledgerwatch/erigon-lib/chain" libcommon "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon-lib/crypto/blake2b" libkzg "github.com/ledgerwatch/erigon-lib/crypto/kzg" "github.com/ledgerwatch/erigon/common" @@ -34,7 +34,7 @@ import ( "github.com/ledgerwatch/erigon/crypto" "github.com/ledgerwatch/erigon/crypto/bls12381" "github.com/ledgerwatch/erigon/crypto/bn256" - + "github.com/ledgerwatch/erigon/crypto/secp256r1" "github.com/ledgerwatch/erigon/params" //lint:ignore SA1019 Needed for precompile @@ -112,6 +112,19 @@ var PrecompiledContractsCancun = map[libcommon.Address]PrecompiledContract{ libcommon.BytesToAddress([]byte{0x0a}): &pointEvaluation{}, } +var PrecompiledContractsNapoli = map[libcommon.Address]PrecompiledContract{ + libcommon.BytesToAddress([]byte{0x01}): &ecrecover{}, + libcommon.BytesToAddress([]byte{0x02}): &sha256hash{}, + libcommon.BytesToAddress([]byte{0x03}): &ripemd160hash{}, + libcommon.BytesToAddress([]byte{0x04}): &dataCopy{}, + libcommon.BytesToAddress([]byte{0x05}): &bigModExp{eip2565: true}, + libcommon.BytesToAddress([]byte{0x06}): &bn256AddIstanbul{}, + libcommon.BytesToAddress([]byte{0x07}): &bn256ScalarMulIstanbul{}, + libcommon.BytesToAddress([]byte{0x08}): &bn256PairingIstanbul{}, + libcommon.BytesToAddress([]byte{0x09}): &blake2F{}, + libcommon.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{}, +} + // PrecompiledContractsBLS contains the set of pre-compiled Ethereum // contracts specified in EIP-2537. These are exported for testing purposes. var PrecompiledContractsBLS = map[libcommon.Address]PrecompiledContract{ @@ -127,6 +140,7 @@ var PrecompiledContractsBLS = map[libcommon.Address]PrecompiledContract{ } var ( + PrecompiledAddressesNapoli []libcommon.Address PrecompiledAddressesCancun []libcommon.Address PrecompiledAddressesBerlin []libcommon.Address PrecompiledAddressesIstanbul []libcommon.Address @@ -150,11 +164,16 @@ func init() { for k := range PrecompiledContractsCancun { PrecompiledAddressesCancun = append(PrecompiledAddressesCancun, k) } + for k := range PrecompiledContractsNapoli { + PrecompiledAddressesNapoli = append(PrecompiledAddressesNapoli, k) + } } // ActivePrecompiles returns the precompiles enabled with the current configuration. func ActivePrecompiles(rules *chain.Rules) []libcommon.Address { switch { + case rules.IsNapoli: + return PrecompiledAddressesNapoli case rules.IsCancun: return PrecompiledAddressesCancun case rules.IsBerlin: @@ -1098,3 +1117,37 @@ func (c *pointEvaluation) RequiredGas(input []byte) uint64 { func (c *pointEvaluation) Run(input []byte) ([]byte, error) { return libkzg.PointEvaluationPrecompile(input) } + +// P256VERIFY (secp256r1 signature verification) +// implemented as a native contract +type p256Verify struct{} + +// RequiredGas returns the gas required to execute the precompiled contract +func (c *p256Verify) RequiredGas(input []byte) uint64 { + return params.P256VerifyGas +} + +// Run executes the precompiled contract with given 160 bytes of param, returning the output and the used gas +func (c *p256Verify) Run(input []byte) ([]byte, error) { + // Required input length is 160 bytes + const p256VerifyInputLength = 160 + // Check the input length + if len(input) != p256VerifyInputLength { + // Input length is invalid + return nil, nil + } + + // Extract the hash, r, s, x, y from the input + hash := input[0:32] + r, s := new(big.Int).SetBytes(input[32:64]), new(big.Int).SetBytes(input[64:96]) + x, y := new(big.Int).SetBytes(input[96:128]), new(big.Int).SetBytes(input[128:160]) + + // Verify the secp256r1 signature + if secp256r1.Verify(hash, r, s, x, y) { + // Signature is valid + return common.LeftPadBytes(big1.Bytes(), 32), nil + } else { + // Signature is invalid + return nil, nil + } +} diff --git a/core/vm/contracts_test.go b/core/vm/contracts_test.go index a9ca23ef1b6..d9b05437a71 100644 --- a/core/vm/contracts_test.go +++ b/core/vm/contracts_test.go @@ -48,26 +48,27 @@ type precompiledFailureTest struct { // allPrecompiles does not map to the actual set of precompiles, as it also contains // repriced versions of precompiles at certain slots var allPrecompiles = map[libcommon.Address]PrecompiledContract{ - libcommon.BytesToAddress([]byte{1}): &ecrecover{}, - libcommon.BytesToAddress([]byte{2}): &sha256hash{}, - libcommon.BytesToAddress([]byte{3}): &ripemd160hash{}, - libcommon.BytesToAddress([]byte{4}): &dataCopy{}, - libcommon.BytesToAddress([]byte{5}): &bigModExp{eip2565: false}, - libcommon.BytesToAddress([]byte{0xf5}): &bigModExp{eip2565: true}, - libcommon.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, - libcommon.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, - libcommon.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, - libcommon.BytesToAddress([]byte{9}): &blake2F{}, - libcommon.BytesToAddress([]byte{10}): &bls12381G1Add{}, - libcommon.BytesToAddress([]byte{11}): &bls12381G1Mul{}, - libcommon.BytesToAddress([]byte{12}): &bls12381G1MultiExp{}, - libcommon.BytesToAddress([]byte{13}): &bls12381G2Add{}, - libcommon.BytesToAddress([]byte{14}): &bls12381G2Mul{}, - libcommon.BytesToAddress([]byte{15}): &bls12381G2MultiExp{}, - libcommon.BytesToAddress([]byte{16}): &bls12381Pairing{}, - libcommon.BytesToAddress([]byte{17}): &bls12381MapG1{}, - libcommon.BytesToAddress([]byte{18}): &bls12381MapG2{}, - libcommon.BytesToAddress([]byte{20}): &pointEvaluation{}, + libcommon.BytesToAddress([]byte{1}): &ecrecover{}, + libcommon.BytesToAddress([]byte{2}): &sha256hash{}, + libcommon.BytesToAddress([]byte{3}): &ripemd160hash{}, + libcommon.BytesToAddress([]byte{4}): &dataCopy{}, + libcommon.BytesToAddress([]byte{5}): &bigModExp{eip2565: false}, + libcommon.BytesToAddress([]byte{0xf5}): &bigModExp{eip2565: true}, + libcommon.BytesToAddress([]byte{6}): &bn256AddIstanbul{}, + libcommon.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{}, + libcommon.BytesToAddress([]byte{8}): &bn256PairingIstanbul{}, + libcommon.BytesToAddress([]byte{9}): &blake2F{}, + libcommon.BytesToAddress([]byte{10}): &bls12381G1Add{}, + libcommon.BytesToAddress([]byte{11}): &bls12381G1Mul{}, + libcommon.BytesToAddress([]byte{12}): &bls12381G1MultiExp{}, + libcommon.BytesToAddress([]byte{13}): &bls12381G2Add{}, + libcommon.BytesToAddress([]byte{14}): &bls12381G2Mul{}, + libcommon.BytesToAddress([]byte{15}): &bls12381G2MultiExp{}, + libcommon.BytesToAddress([]byte{16}): &bls12381Pairing{}, + libcommon.BytesToAddress([]byte{17}): &bls12381MapG1{}, + libcommon.BytesToAddress([]byte{18}): &bls12381MapG2{}, + libcommon.BytesToAddress([]byte{20}): &pointEvaluation{}, + libcommon.BytesToAddress([]byte{0x01, 0x00}): &p256Verify{}, } // EIP-152 test vectors @@ -400,3 +401,19 @@ func BenchmarkPrecompiledBLS12381G2MultiExpWorstCase(b *testing.B) { } benchmarkPrecompiled(b, "0f", testcase) } + +// Benchmarks the sample inputs from the P256VERIFY precompile. +func BenchmarkPrecompiledP256Verify(b *testing.B) { + testcase := precompiledTest{ + Input: "4cee90eb86eaa050036147a12d49004b6b9c72bd725d39d4785011fe190f0b4da73bd4903f0ce3b639bbbf6e8e80d16931ff4bcf5993d58468e8fb19086e8cac36dbcd03009df8c59286b162af3bd7fcc0450c9aa81be5d10d312af6c66b1d604aebd3099c618202fcfe16ae7770b0c49ab5eadf74b754204a3bb6060e44eff37618b065f9832de4ca6ca971a7a1adc826d0f7c00181a5fb2ddf79ae00b4e10e", + Expected: "0000000000000000000000000000000000000000000000000000000000000001", + Name: "p256Verify", + } + benchmarkPrecompiled(b, "100", testcase) +} + +func TestPrecompiledP256Verify(t *testing.T) { + t.Parallel() + + testJson("p256Verify", "100", t) +} diff --git a/core/vm/evm.go b/core/vm/evm.go index dc5dce586c8..56ffc3bc2fa 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -37,6 +37,8 @@ var emptyCodeHash = crypto.Keccak256Hash(nil) func (evm *EVM) precompile(addr libcommon.Address) (PrecompiledContract, bool) { var precompiles map[libcommon.Address]PrecompiledContract switch { + case evm.chainRules.IsNapoli: + precompiles = PrecompiledContractsNapoli case evm.chainRules.IsCancun: precompiles = PrecompiledContractsCancun case evm.chainRules.IsBerlin: diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 161068229bf..e2cf325c105 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -128,6 +128,8 @@ func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter { jt = &pragueInstructionSet case evm.ChainRules().IsCancun: jt = &cancunInstructionSet + case evm.ChainRules().IsNapoli: + jt = &napoliInstructionSet case evm.ChainRules().IsShanghai: jt = &shanghaiInstructionSet case evm.ChainRules().IsLondon: diff --git a/core/vm/jump_table.go b/core/vm/jump_table.go index 047c9f53845..806ae494133 100644 --- a/core/vm/jump_table.go +++ b/core/vm/jump_table.go @@ -61,6 +61,7 @@ var ( berlinInstructionSet = newBerlinInstructionSet() londonInstructionSet = newLondonInstructionSet() shanghaiInstructionSet = newShanghaiInstructionSet() + napoliInstructionSet = newNapoliInstructionSet() cancunInstructionSet = newCancunInstructionSet() pragueInstructionSet = newPragueInstructionSet() ) @@ -99,12 +100,18 @@ func newPragueInstructionSet() JumpTable { // constantinople, istanbul, petersburg, berlin, london, paris, shanghai, // and cancun instructions. func newCancunInstructionSet() JumpTable { + instructionSet := newNapoliInstructionSet() + enable4844(&instructionSet) // BLOBHASH opcode + enable7516(&instructionSet) // BLOBBASEFEE opcode + validateAndFillMaxStack(&instructionSet) + return instructionSet +} + +func newNapoliInstructionSet() JumpTable { instructionSet := newShanghaiInstructionSet() enable1153(&instructionSet) // Transient storage opcodes - enable4844(&instructionSet) // BLOBHASH opcode enable5656(&instructionSet) // MCOPY opcode enable6780(&instructionSet) // SELFDESTRUCT only in same transaction - enable7516(&instructionSet) // BLOBBASEFEE opcode validateAndFillMaxStack(&instructionSet) return instructionSet } diff --git a/core/vm/testdata/precompiles/p256Verify.json b/core/vm/testdata/precompiles/p256Verify.json new file mode 100644 index 00000000000..54723147a51 --- /dev/null +++ b/core/vm/testdata/precompiles/p256Verify.json @@ -0,0 +1,37 @@ +[ + { + "Input": "4cee90eb86eaa050036147a12d49004b6b9c72bd725d39d4785011fe190f0b4da73bd4903f0ce3b639bbbf6e8e80d16931ff4bcf5993d58468e8fb19086e8cac36dbcd03009df8c59286b162af3bd7fcc0450c9aa81be5d10d312af6c66b1d604aebd3099c618202fcfe16ae7770b0c49ab5eadf74b754204a3bb6060e44eff37618b065f9832de4ca6ca971a7a1adc826d0f7c00181a5fb2ddf79ae00b4e10e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 3450, + "Name": "CallP256Verify", + "NoBenchmark": false + }, + { + "Input": "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9414de3726ee4d237b410c1d85ebcb05553dc578561d9f7942b7250795beb9b9027b657067322fc00ab35263fde0acabf998cd9fcf1282df9555f85dba7bdbbe2dc90f74c9e210bc3e0c60aeaa03729c9e6acde4a048ee58fd2e466c1e7b0374e606b8c22ad2985df7d792ff344f03ce94a079da801006b13640bc5af7932a7b9", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 3450, + "Name": "CallP256Verify", + "NoBenchmark": false + }, + { + "Input": "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9b35d6a4f7f6fc5620c97d4287696f5174b3d37fa537b74b5fc26997ba79c725d62fe5e5fe6da76eec924e822c5ef853ede6c17069a9e9133a38f87d61599f68e7d5f3c812a255436846ee84a262b79ec4d0783afccf2433deabdca9ecf62bef5ff24e90988c7f139d378549c3a8bc6c94e6a1c911c1e02e6f48ed65aaf3d296e", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 3450, + "Name": "CallP256Verify", + "NoBenchmark": false + }, + { + "Input": "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9c29c3df6ce3431b6f030b1b68b1589508ad9d1a149830489c638653aa4b08af93f6e86a9a7643403b6f5c593410d9f7234a8cd27309bce90447073ce17476850615ff147863bc8652be1e369444f90bbc5f9df05a26362e609f73ab1f1839fe3cd34fd2ae672c110671d49115825fc56b5148321aabe5ba39f2b46f71149cff9", + "Expected": "", + "Gas": 3450, + "Name": "CallP256Verify", + "NoBenchmark": false + }, + { + "Input": "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9", + "Expected": "", + "Gas": 3450, + "Name": "CallP256Verify", + "NoBenchmark": false + } +] \ No newline at end of file diff --git a/crypto/secp256r1/publickey.go b/crypto/secp256r1/publickey.go new file mode 100644 index 00000000000..9b84044efa0 --- /dev/null +++ b/crypto/secp256r1/publickey.go @@ -0,0 +1,26 @@ +package secp256r1 + +import ( + "crypto/ecdsa" + "crypto/elliptic" + "math/big" +) + +// Generates approptiate public key format from given coordinates +func newPublicKey(x, y *big.Int) *ecdsa.PublicKey { + // Check if the given coordinates are valid + if x == nil || y == nil || !elliptic.P256().IsOnCurve(x, y) { + return nil + } + + // Check if the given coordinates are the reference point (infinity) + if x.Sign() == 0 && y.Sign() == 0 { + return nil + } + + return &ecdsa.PublicKey{ + Curve: elliptic.P256(), + X: x, + Y: y, + } +} diff --git a/crypto/secp256r1/verifier.go b/crypto/secp256r1/verifier.go new file mode 100644 index 00000000000..ccc0786610b --- /dev/null +++ b/crypto/secp256r1/verifier.go @@ -0,0 +1,21 @@ +package secp256r1 + +import ( + "crypto/ecdsa" + "math/big" +) + +// Verifies the given signature (r, s) for the given hash and public key (x, y). +func Verify(hash []byte, r, s, x, y *big.Int) bool { + // Create the public key format + publicKey := newPublicKey(x, y) + + // Check if they are invalid public key coordinates + if publicKey == nil { + return false + } + + // Verify the signature with the public key, + // then return true if it's valid, false otherwise + return ecdsa.Verify(publicKey, hash, r, s) +} diff --git a/erigon-lib/chain/chain_config.go b/erigon-lib/chain/chain_config.go index bb5125660a3..4d2069ee396 100644 --- a/erigon-lib/chain/chain_config.go +++ b/erigon-lib/chain/chain_config.go @@ -90,6 +90,8 @@ type BorConfig interface { fmt.Stringer IsAgra(num uint64) bool GetAgraBlock() *big.Int + IsNapoli(num uint64) bool + GetNapoliBlock() *big.Int } func (c *Config) String() string { @@ -214,6 +216,11 @@ func (c *Config) IsAgra(num uint64) bool { return (c != nil) && (c.Bor != nil) && c.Bor.IsAgra(num) } +// Refer to https://forum.polygon.technology/t/pip-33-napoli-upgrade +func (c *Config) IsNapoli(num uint64) bool { + return (c != nil) && (c.Bor != nil) && c.Bor.IsNapoli(num) +} + // IsCancun returns whether time is either equal to the Cancun fork time or greater. func (c *Config) IsCancun(time uint64) bool { return isForked(c.CancunTime, time) @@ -484,11 +491,13 @@ func borKeyValueConfigHelper[T uint64 | common.Address](field map[string]T, numb // Rules is a one time interface meaning that it shouldn't be used in between transition // phases. type Rules struct { - ChainID *big.Int - IsHomestead, IsTangerineWhistle, IsSpuriousDragon bool - IsByzantium, IsConstantinople, IsPetersburg, IsIstanbul bool - IsBerlin, IsLondon, IsShanghai, IsCancun, IsPrague bool - IsAura bool + ChainID *big.Int + IsHomestead, IsTangerineWhistle, IsSpuriousDragon bool + IsByzantium, IsConstantinople, IsPetersburg bool + IsIstanbul, IsBerlin, IsLondon, IsShanghai bool + IsCancun, IsNapoli bool + IsPrague bool + IsAura bool } // Rules ensures c's ChainID is not nil and returns a new Rules instance @@ -511,6 +520,7 @@ func (c *Config) Rules(num uint64, time uint64) *Rules { IsLondon: c.IsLondon(num), IsShanghai: c.IsShanghai(time) || c.IsAgra(num), IsCancun: c.IsCancun(time), + IsNapoli: c.IsNapoli(num), IsPrague: c.IsPrague(time), IsAura: c.Aura != nil, } diff --git a/erigon-lib/txpool/pool.go b/erigon-lib/txpool/pool.go index 88026073a99..a3eb55f255f 100644 --- a/erigon-lib/txpool/pool.go +++ b/erigon-lib/txpool/pool.go @@ -945,7 +945,7 @@ func (p *TxPool) isShanghai() bool { } func (p *TxPool) isAgra() bool { - // once this flag has been set for the first time we no longer need to check the timestamp + // once this flag has been set for the first time we no longer need to check the block set := p.isPostAgra.Load() if set { return true diff --git a/params/protocol_params.go b/params/protocol_params.go index 33ffda9a94c..8b8c37325ae 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -168,6 +168,9 @@ const ( // EIP-4844: Shard Blob Transactions PointEvaluationGas uint64 = 50000 + + // PIP-27: secp256r1 elliptic curve signature verifier gas price + P256VerifyGas uint64 = 3450 ) // EIP-4788: Beacon block root in the EVM diff --git a/polygon/bor/bor.go b/polygon/bor/bor.go index d37f9888004..aef97e200cb 100644 --- a/polygon/bor/bor.go +++ b/polygon/bor/bor.go @@ -550,7 +550,7 @@ func ValidateHeaderUnusedFields(header *types.Header) error { return consensus.ErrUnexpectedWithdrawals } - return nil + return misc.VerifyAbsenceOfCancunHeaderFields(header) } // verifyCascadingFields verifies all the header fields that are not standalone, @@ -897,7 +897,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header, s // sort validator by address sort.Sort(valset.ValidatorsByAddress(newValidators)) - if c.config.IsParallelUniverse(header.Number.Uint64()) { + if c.config.IsNapoli(header.Number.Uint64()) { // PIP-16: Transaction Dependency Data var tempValidatorBytes []byte for _, validator := range newValidators { @@ -921,7 +921,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header, s header.Extra = append(header.Extra, validator.HeaderBytes()...) } } - } else if c.config.IsParallelUniverse(header.Number.Uint64()) { + } else if c.config.IsNapoli(header.Number.Uint64()) { // PIP-16: Transaction Dependency Data blockExtraData := &BlockExtraData{ ValidatorBytes: nil, TxDependency: nil, @@ -1584,7 +1584,7 @@ func GetTxDependency(b *types.Block) [][]uint64 { func GetValidatorBytes(h *types.Header, config *borcfg.BorConfig) []byte { tempExtra := h.Extra - if !config.IsParallelUniverse(h.Number.Uint64()) { + if !config.IsNapoli(h.Number.Uint64()) { return tempExtra[types.ExtraVanityLength : len(tempExtra)-types.ExtraSealLength] } diff --git a/polygon/bor/borcfg/bor_config.go b/polygon/bor/borcfg/bor_config.go index d73f20a830a..6c02f069b82 100644 --- a/polygon/bor/borcfg/bor_config.go +++ b/polygon/bor/borcfg/bor_config.go @@ -20,14 +20,13 @@ type BorConfig struct { OverrideStateSyncRecords map[string]int `json:"overrideStateSyncRecords"` // override state records count BlockAlloc map[string]interface{} `json:"blockAlloc"` - JaipurBlock *big.Int `json:"jaipurBlock"` // Jaipur switch block (nil = no fork, 0 = already on jaipur) - DelhiBlock *big.Int `json:"delhiBlock"` // Delhi switch block (nil = no fork, 0 = already on delhi) - IndoreBlock *big.Int `json:"indoreBlock"` // Indore switch block (nil = no fork, 0 = already on indore) - AgraBlock *big.Int `json:"agraBlock"` // Agra switch block (nil = no fork, 0 = already in agra) + JaipurBlock *big.Int `json:"jaipurBlock"` // Jaipur switch block (nil = no fork, 0 = already on Jaipur) + DelhiBlock *big.Int `json:"delhiBlock"` // Delhi switch block (nil = no fork, 0 = already on Delhi) + IndoreBlock *big.Int `json:"indoreBlock"` // Indore switch block (nil = no fork, 0 = already on Indore) + AgraBlock *big.Int `json:"agraBlock"` // Agra switch block (nil = no fork, 0 = already on Agra) + NapoliBlock *big.Int `json:"napoliBlock"` // Napoli switch block (nil = no fork, 0 = already on Napoli) StateSyncConfirmationDelay map[string]uint64 `json:"stateSyncConfirmationDelay"` // StateSync Confirmation Delay, in seconds, to calculate `to` - ParallelUniverseBlock *big.Int `json:"parallelUniverseBlock"` // TODO: update all occurrence, change name and finalize number (hardfork for block-stm related changes) - sprints sprints } @@ -126,15 +125,13 @@ func (c *BorConfig) GetAgraBlock() *big.Int { return c.AgraBlock } -// TODO: modify this function once the block number is finalized -func (c *BorConfig) IsParallelUniverse(number uint64) bool { - if c.ParallelUniverseBlock != nil { - if c.ParallelUniverseBlock.Cmp(big.NewInt(0)) == 0 { - return false - } - } +// Refer to https://forum.polygon.technology/t/pip-33-napoli-upgrade +func (c *BorConfig) IsNapoli(num uint64) bool { + return isForked(c.NapoliBlock, num) +} - return isForked(c.ParallelUniverseBlock, number) +func (c *BorConfig) GetNapoliBlock() *big.Int { + return c.NapoliBlock } func (c *BorConfig) CalculateStateSyncDelay(number uint64) uint64 { From 5e5d8490b1b70613c76c642a61d102597f1ebfc3 Mon Sep 17 00:00:00 2001 From: Somnath Date: Wed, 17 Jan 2024 17:46:02 +0400 Subject: [PATCH 78/92] Move blob cache check in txpool (#9250) This should help with less frequent lock/unlock. Following from an earlier "TODO" --- erigon-lib/txpool/fetch.go | 17 +---- erigon-lib/txpool/mocks_test.go | 108 ++++++++-------------------- erigon-lib/txpool/pool.go | 20 ++++-- erigon-lib/txpool/pool_fuzz_test.go | 8 +-- erigon-lib/txpool/pool_test.go | 12 ++-- 5 files changed, 57 insertions(+), 108 deletions(-) diff --git a/erigon-lib/txpool/fetch.go b/erigon-lib/txpool/fetch.go index e5097a7f706..a4ca77bff1a 100644 --- a/erigon-lib/txpool/fetch.go +++ b/erigon-lib/txpool/fetch.go @@ -476,7 +476,7 @@ func (f *Fetch) handleStateChanges(ctx context.Context, client StateChangesClien } func (f *Fetch) handleStateChangesRequest(ctx context.Context, req *remote.StateChangeBatch) error { - var unwindTxs, minedTxs types2.TxSlots + var unwindTxs, unwindBlobTxs, minedTxs types2.TxSlots for _, change := range req.ChangeBatch { if change.Direction == remote.Direction_FORWARD { minedTxs.Resize(uint(len(change.Txs))) @@ -500,18 +500,7 @@ func (f *Fetch) handleStateChangesRequest(ctx context.Context, req *remote.State return err } if utx.Type == types2.BlobTxType { - var knownBlobTxn *metaTx - //TODO: don't check `KnownBlobTxn()` here - because each call require `txpool.mutex.lock()`. Better add all hashes here and do check inside `OnNewBlock` - if err := f.db.View(ctx, func(tx kv.Tx) error { - knownBlobTxn, err = f.pool.GetKnownBlobTxn(tx, utx.IDHash[:]) - return err - }); err != nil { - return err - } - // Get the blob tx from cache; ignore altogether if it isn't there - if knownBlobTxn != nil { - unwindTxs.Append(knownBlobTxn.Tx, sender, false) - } + unwindBlobTxs.Append(utx, sender, false) } else { unwindTxs.Append(utx, sender, false) } @@ -525,7 +514,7 @@ func (f *Fetch) handleStateChangesRequest(ctx context.Context, req *remote.State } if err := f.db.View(ctx, func(tx kv.Tx) error { - return f.pool.OnNewBlock(ctx, req, unwindTxs, minedTxs, tx) + return f.pool.OnNewBlock(ctx, req, unwindTxs, unwindBlobTxs, minedTxs, tx) }); err != nil && !errors.Is(err, context.Canceled) { return err } diff --git a/erigon-lib/txpool/mocks_test.go b/erigon-lib/txpool/mocks_test.go index 22e8e8121af..502b4a69002 100644 --- a/erigon-lib/txpool/mocks_test.go +++ b/erigon-lib/txpool/mocks_test.go @@ -34,16 +34,13 @@ var _ Pool = &PoolMock{} // FilterKnownIdHashesFunc: func(tx kv.Tx, hashes types2.Hashes) (types2.Hashes, error) { // panic("mock out the FilterKnownIdHashes method") // }, -// GetKnownBlobTxnFunc: func(tx kv.Tx, hash []byte) (*metaTx, error) { -// panic("mock out the GetKnownBlobTxn method") -// }, // GetRlpFunc: func(tx kv.Tx, hash []byte) ([]byte, error) { // panic("mock out the GetRlp method") // }, // IdHashKnownFunc: func(tx kv.Tx, hash []byte) (bool, error) { // panic("mock out the IdHashKnown method") // }, -// OnNewBlockFunc: func(ctx context.Context, stateChanges *remote.StateChangeBatch, unwindTxs types2.TxSlots, minedTxs types2.TxSlots, tx kv.Tx) error { +// OnNewBlockFunc: func(ctx context.Context, stateChanges *remote.StateChangeBatch, unwindTxs types2.TxSlots, unwindBlobTxs types2.TxSlots, minedTxs types2.TxSlots, tx kv.Tx) error { // panic("mock out the OnNewBlock method") // }, // StartedFunc: func() bool { @@ -71,9 +68,6 @@ type PoolMock struct { // FilterKnownIdHashesFunc mocks the FilterKnownIdHashes method. FilterKnownIdHashesFunc func(tx kv.Tx, hashes types2.Hashes) (types2.Hashes, error) - // GetKnownBlobTxnFunc mocks the GetKnownBlobTxn method. - GetKnownBlobTxnFunc func(tx kv.Tx, hash []byte) (*metaTx, error) - // GetRlpFunc mocks the GetRlp method. GetRlpFunc func(tx kv.Tx, hash []byte) ([]byte, error) @@ -81,7 +75,7 @@ type PoolMock struct { IdHashKnownFunc func(tx kv.Tx, hash []byte) (bool, error) // OnNewBlockFunc mocks the OnNewBlock method. - OnNewBlockFunc func(ctx context.Context, stateChanges *remote.StateChangeBatch, unwindTxs types2.TxSlots, minedTxs types2.TxSlots, tx kv.Tx) error + OnNewBlockFunc func(ctx context.Context, stateChanges *remote.StateChangeBatch, unwindTxs types2.TxSlots, unwindBlobTxs types2.TxSlots, minedTxs types2.TxSlots, tx kv.Tx) error // StartedFunc mocks the Started method. StartedFunc func() bool @@ -119,13 +113,6 @@ type PoolMock struct { // Hashes is the hashes argument value. Hashes types2.Hashes } - // GetKnownBlobTxn holds details about calls to the GetKnownBlobTxn method. - GetKnownBlobTxn []struct { - // Tx is the tx argument value. - Tx kv.Tx - // Hash is the hash argument value. - Hash []byte - } // GetRlp holds details about calls to the GetRlp method. GetRlp []struct { // Tx is the tx argument value. @@ -148,6 +135,8 @@ type PoolMock struct { StateChanges *remote.StateChangeBatch // UnwindTxs is the unwindTxs argument value. UnwindTxs types2.TxSlots + // UnwindBlobTxs is the unwindBlobTxs argument value. + UnwindBlobTxs types2.TxSlots // MinedTxs is the minedTxs argument value. MinedTxs types2.TxSlots // Tx is the tx argument value. @@ -166,7 +155,6 @@ type PoolMock struct { lockAddNewGoodPeer sync.RWMutex lockAddRemoteTxs sync.RWMutex lockFilterKnownIdHashes sync.RWMutex - lockGetKnownBlobTxn sync.RWMutex lockGetRlp sync.RWMutex lockIdHashKnown sync.RWMutex lockOnNewBlock sync.RWMutex @@ -326,46 +314,6 @@ func (mock *PoolMock) FilterKnownIdHashesCalls() []struct { return calls } -// GetKnownBlobTxn calls GetKnownBlobTxnFunc. -func (mock *PoolMock) GetKnownBlobTxn(tx kv.Tx, hash []byte) (*metaTx, error) { - callInfo := struct { - Tx kv.Tx - Hash []byte - }{ - Tx: tx, - Hash: hash, - } - mock.lockGetKnownBlobTxn.Lock() - mock.calls.GetKnownBlobTxn = append(mock.calls.GetKnownBlobTxn, callInfo) - mock.lockGetKnownBlobTxn.Unlock() - if mock.GetKnownBlobTxnFunc == nil { - var ( - metaTxMoqParamOut *metaTx - errOut error - ) - return metaTxMoqParamOut, errOut - } - return mock.GetKnownBlobTxnFunc(tx, hash) -} - -// GetKnownBlobTxnCalls gets all the calls that were made to GetKnownBlobTxn. -// Check the length with: -// -// len(mockedPool.GetKnownBlobTxnCalls()) -func (mock *PoolMock) GetKnownBlobTxnCalls() []struct { - Tx kv.Tx - Hash []byte -} { - var calls []struct { - Tx kv.Tx - Hash []byte - } - mock.lockGetKnownBlobTxn.RLock() - calls = mock.calls.GetKnownBlobTxn - mock.lockGetKnownBlobTxn.RUnlock() - return calls -} - // GetRlp calls GetRlpFunc. func (mock *PoolMock) GetRlp(tx kv.Tx, hash []byte) ([]byte, error) { callInfo := struct { @@ -447,19 +395,21 @@ func (mock *PoolMock) IdHashKnownCalls() []struct { } // OnNewBlock calls OnNewBlockFunc. -func (mock *PoolMock) OnNewBlock(ctx context.Context, stateChanges *remote.StateChangeBatch, unwindTxs types2.TxSlots, minedTxs types2.TxSlots, tx kv.Tx) error { +func (mock *PoolMock) OnNewBlock(ctx context.Context, stateChanges *remote.StateChangeBatch, unwindTxs types2.TxSlots, unwindBlobTxs types2.TxSlots, minedTxs types2.TxSlots, tx kv.Tx) error { callInfo := struct { - Ctx context.Context - StateChanges *remote.StateChangeBatch - UnwindTxs types2.TxSlots - MinedTxs types2.TxSlots - Tx kv.Tx + Ctx context.Context + StateChanges *remote.StateChangeBatch + UnwindTxs types2.TxSlots + UnwindBlobTxs types2.TxSlots + MinedTxs types2.TxSlots + Tx kv.Tx }{ - Ctx: ctx, - StateChanges: stateChanges, - UnwindTxs: unwindTxs, - MinedTxs: minedTxs, - Tx: tx, + Ctx: ctx, + StateChanges: stateChanges, + UnwindTxs: unwindTxs, + UnwindBlobTxs: unwindBlobTxs, + MinedTxs: minedTxs, + Tx: tx, } mock.lockOnNewBlock.Lock() mock.calls.OnNewBlock = append(mock.calls.OnNewBlock, callInfo) @@ -470,7 +420,7 @@ func (mock *PoolMock) OnNewBlock(ctx context.Context, stateChanges *remote.State ) return errOut } - return mock.OnNewBlockFunc(ctx, stateChanges, unwindTxs, minedTxs, tx) + return mock.OnNewBlockFunc(ctx, stateChanges, unwindTxs, unwindBlobTxs, minedTxs, tx) } // OnNewBlockCalls gets all the calls that were made to OnNewBlock. @@ -478,18 +428,20 @@ func (mock *PoolMock) OnNewBlock(ctx context.Context, stateChanges *remote.State // // len(mockedPool.OnNewBlockCalls()) func (mock *PoolMock) OnNewBlockCalls() []struct { - Ctx context.Context - StateChanges *remote.StateChangeBatch - UnwindTxs types2.TxSlots - MinedTxs types2.TxSlots - Tx kv.Tx + Ctx context.Context + StateChanges *remote.StateChangeBatch + UnwindTxs types2.TxSlots + UnwindBlobTxs types2.TxSlots + MinedTxs types2.TxSlots + Tx kv.Tx } { var calls []struct { - Ctx context.Context - StateChanges *remote.StateChangeBatch - UnwindTxs types2.TxSlots - MinedTxs types2.TxSlots - Tx kv.Tx + Ctx context.Context + StateChanges *remote.StateChangeBatch + UnwindTxs types2.TxSlots + UnwindBlobTxs types2.TxSlots + MinedTxs types2.TxSlots + Tx kv.Tx } mock.lockOnNewBlock.RLock() calls = mock.calls.OnNewBlock diff --git a/erigon-lib/txpool/pool.go b/erigon-lib/txpool/pool.go index a3eb55f255f..d56b4d7ccec 100644 --- a/erigon-lib/txpool/pool.go +++ b/erigon-lib/txpool/pool.go @@ -85,13 +85,12 @@ type Pool interface { // Handle 3 main events - new remote txs from p2p, new local txs from RPC, new blocks from execution layer AddRemoteTxs(ctx context.Context, newTxs types.TxSlots) AddLocalTxs(ctx context.Context, newTxs types.TxSlots, tx kv.Tx) ([]txpoolcfg.DiscardReason, error) - OnNewBlock(ctx context.Context, stateChanges *remote.StateChangeBatch, unwindTxs, minedTxs types.TxSlots, tx kv.Tx) error + OnNewBlock(ctx context.Context, stateChanges *remote.StateChangeBatch, unwindTxs, unwindBlobTxs, minedTxs types.TxSlots, tx kv.Tx) error // IdHashKnown check whether transaction with given Id hash is known to the pool IdHashKnown(tx kv.Tx, hash []byte) (bool, error) FilterKnownIdHashes(tx kv.Tx, hashes types.Hashes) (unknownHashes types.Hashes, err error) Started() bool GetRlp(tx kv.Tx, hash []byte) ([]byte, error) - GetKnownBlobTxn(tx kv.Tx, hash []byte) (*metaTx, error) AddNewGoodPeer(peerID types.PeerID) } @@ -337,7 +336,7 @@ func (p *TxPool) Start(ctx context.Context, db kv.RwDB) error { }) } -func (p *TxPool) OnNewBlock(ctx context.Context, stateChanges *remote.StateChangeBatch, unwindTxs, minedTxs types.TxSlots, tx kv.Tx) error { +func (p *TxPool) OnNewBlock(ctx context.Context, stateChanges *remote.StateChangeBatch, unwindTxs, unwindBlobTxs, minedTxs types.TxSlots, tx kv.Tx) error { defer newBlockTimer.ObserveDuration(time.Now()) //t := time.Now() @@ -401,6 +400,17 @@ func (p *TxPool) OnNewBlock(ctx context.Context, stateChanges *remote.StateChang p.blockGasLimit.Store(stateChanges.BlockGasLimit) + for i, txn := range unwindBlobTxs.Txs { + if txn.Type == types.BlobTxType { + knownBlobTxn, err := p.getCachedBlobTxnLocked(coreTx, txn.IDHash[:]) + if err != nil { + return err + } + if knownBlobTxn != nil { + unwindTxs.Append(knownBlobTxn.Tx, unwindBlobTxs.Senders.At(i), false) + } + } + } if err = p.senders.onNewBlock(stateChanges, unwindTxs, minedTxs, p.logger); err != nil { return err } @@ -619,10 +629,8 @@ func (p *TxPool) getUnprocessedTxn(hashS string) (*types.TxSlot, bool) { return nil, false } -func (p *TxPool) GetKnownBlobTxn(tx kv.Tx, hash []byte) (*metaTx, error) { +func (p *TxPool) getCachedBlobTxnLocked(tx kv.Tx, hash []byte) (*metaTx, error) { hashS := string(hash) - p.lock.Lock() - defer p.lock.Unlock() if mt, ok := p.minedBlobTxsByHash[hashS]; ok { return mt, nil } diff --git a/erigon-lib/txpool/pool_fuzz_test.go b/erigon-lib/txpool/pool_fuzz_test.go index 08106374cdf..54b1beb0238 100644 --- a/erigon-lib/txpool/pool_fuzz_test.go +++ b/erigon-lib/txpool/pool_fuzz_test.go @@ -485,7 +485,7 @@ func FuzzOnNewBlocks(f *testing.F) { } // go to first fork txs1, txs2, p2pReceived, txs3 := splitDataset(txs) - err = pool.OnNewBlock(ctx, change, txs1, types.TxSlots{}, tx) + err = pool.OnNewBlock(ctx, change, txs1, types.TxSlots{}, types.TxSlots{}, tx) assert.NoError(err) check(txs1, types.TxSlots{}, "fork1") checkNotify(txs1, types.TxSlots{}, "fork1") @@ -498,7 +498,7 @@ func FuzzOnNewBlocks(f *testing.F) { {BlockHeight: 1, BlockHash: h0}, }, } - err = pool.OnNewBlock(ctx, change, types.TxSlots{}, txs2, tx) + err = pool.OnNewBlock(ctx, change, types.TxSlots{}, types.TxSlots{}, txs2, tx) assert.NoError(err) check(types.TxSlots{}, txs2, "fork1 mined") checkNotify(types.TxSlots{}, txs2, "fork1 mined") @@ -511,7 +511,7 @@ func FuzzOnNewBlocks(f *testing.F) { {BlockHeight: 0, BlockHash: h0, Direction: remote.Direction_UNWIND}, }, } - err = pool.OnNewBlock(ctx, change, txs2, types.TxSlots{}, tx) + err = pool.OnNewBlock(ctx, change, txs2, types.TxSlots{}, types.TxSlots{}, tx) assert.NoError(err) check(txs2, types.TxSlots{}, "fork2") checkNotify(txs2, types.TxSlots{}, "fork2") @@ -523,7 +523,7 @@ func FuzzOnNewBlocks(f *testing.F) { {BlockHeight: 1, BlockHash: h22}, }, } - err = pool.OnNewBlock(ctx, change, types.TxSlots{}, txs3, tx) + err = pool.OnNewBlock(ctx, change, types.TxSlots{}, types.TxSlots{}, txs3, tx) assert.NoError(err) check(types.TxSlots{}, txs3, "fork2 mined") checkNotify(types.TxSlots{}, txs3, "fork2 mined") diff --git a/erigon-lib/txpool/pool_test.go b/erigon-lib/txpool/pool_test.go index 80de08a511d..9dcbf1cc908 100644 --- a/erigon-lib/txpool/pool_test.go +++ b/erigon-lib/txpool/pool_test.go @@ -81,7 +81,7 @@ func TestNonceFromAddress(t *testing.T) { tx, err := db.BeginRw(ctx) require.NoError(err) defer tx.Rollback() - err = pool.OnNewBlock(ctx, change, types.TxSlots{}, types.TxSlots{}, tx) + err = pool.OnNewBlock(ctx, change, types.TxSlots{}, types.TxSlots{}, types.TxSlots{}, tx) assert.NoError(err) { @@ -201,7 +201,7 @@ func TestReplaceWithHigherFee(t *testing.T) { tx, err := db.BeginRw(ctx) require.NoError(err) defer tx.Rollback() - err = pool.OnNewBlock(ctx, change, types.TxSlots{}, types.TxSlots{}, tx) + err = pool.OnNewBlock(ctx, change, types.TxSlots{}, types.TxSlots{}, types.TxSlots{}, tx) assert.NoError(err) { @@ -318,7 +318,7 @@ func TestReverseNonces(t *testing.T) { tx, err := db.BeginRw(ctx) require.NoError(err) defer tx.Rollback() - err = pool.OnNewBlock(ctx, change, types.TxSlots{}, types.TxSlots{}, tx) + err = pool.OnNewBlock(ctx, change, types.TxSlots{}, types.TxSlots{}, types.TxSlots{}, tx) assert.NoError(err) // 1. Send high fee transaction with nonce gap { @@ -445,7 +445,7 @@ func TestTxPoke(t *testing.T) { tx, err := db.BeginRw(ctx) require.NoError(err) defer tx.Rollback() - err = pool.OnNewBlock(ctx, change, types.TxSlots{}, types.TxSlots{}, tx) + err = pool.OnNewBlock(ctx, change, types.TxSlots{}, types.TxSlots{}, types.TxSlots{}, tx) assert.NoError(err) var idHash types.Hashes @@ -759,7 +759,7 @@ func TestBlobTxReplacement(t *testing.T) { tx, err := db.BeginRw(ctx) require.NoError(err) defer tx.Rollback() - err = pool.OnNewBlock(ctx, change, types.TxSlots{}, types.TxSlots{}, tx) + err = pool.OnNewBlock(ctx, change, types.TxSlots{}, types.TxSlots{}, types.TxSlots{}, tx) assert.NoError(err) tip, feeCap, blobFeeCap := uint256.NewInt(100_000), uint256.NewInt(200_000), uint256.NewInt(200_000) @@ -986,7 +986,7 @@ func TestDropRemoteAtNoGossip(t *testing.T) { tx, err := db.BeginRw(ctx) require.NoError(err) defer tx.Rollback() - err = txPool.OnNewBlock(ctx, change, types.TxSlots{}, types.TxSlots{}, tx) + err = txPool.OnNewBlock(ctx, change, types.TxSlots{}, types.TxSlots{}, types.TxSlots{}, tx) assert.NoError(err) // 1. Try Local Tx { From 1914b52de03fc45922e45e5455303fa42c3e66a4 Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Wed, 17 Jan 2024 15:28:37 +0100 Subject: [PATCH 79/92] mdbx: race conditions in MdbxKV.Close (#8409) (#9244) In the previous code WaitGroup db.wg.Add(), Wait() and db.closed were not treated in sync. In particular, it was theoretically possible to first check closed, then set closed and Wait, and then call wg.Add() while waiting (leading to WaitGroup panic). In theory it was also possible that db.env.BeginTxn() is called on a closed or nil db.env, because db.wg.Add() was called only after BeginTxn (db.wg.Wait() could already return). WaitGroup is replaced with a Cond variable. Now it is not possible to increase the active transactions count on a closed database. It is also not possible to call BeginTxn on a closed database. --- erigon-lib/kv/mdbx/kv_mdbx.go | 78 +++++++++++++++--- erigon-lib/kv/mdbx/kv_mdbx_test.go | 128 ++++++++++++++++++++++++++++- 2 files changed, 191 insertions(+), 15 deletions(-) diff --git a/erigon-lib/kv/mdbx/kv_mdbx.go b/erigon-lib/kv/mdbx/kv_mdbx.go index cd465b593b9..58ff2f4a00b 100644 --- a/erigon-lib/kv/mdbx/kv_mdbx.go +++ b/erigon-lib/kv/mdbx/kv_mdbx.go @@ -34,7 +34,6 @@ import ( "github.com/c2h5oh/datasize" "github.com/erigontech/mdbx-go/mdbx" stack2 "github.com/go-stack/stack" - "github.com/ledgerwatch/erigon-lib/mmap" "github.com/ledgerwatch/log/v3" "golang.org/x/exp/maps" "golang.org/x/sync/semaphore" @@ -44,6 +43,7 @@ import ( "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/iter" "github.com/ledgerwatch/erigon-lib/kv/order" + "github.com/ledgerwatch/erigon-lib/mmap" ) const NonExistingDBI kv.DBI = 999_999_999 @@ -385,15 +385,20 @@ func (opts MdbxOpts) Open(ctx context.Context) (kv.RwDB, error) { targetSemCount := int64(runtime.GOMAXPROCS(-1) * 16) opts.roTxsLimiter = semaphore.NewWeighted(targetSemCount) // 1 less than max to allow unlocking to happen } + + txsCountMutex := &sync.Mutex{} + db := &MdbxKV{ opts: opts, env: env, log: opts.log, - wg: &sync.WaitGroup{}, buckets: kv.TableCfg{}, txSize: dirtyPagesLimit * opts.pageSize, roTxsLimiter: opts.roTxsLimiter, + txsCountMutex: txsCountMutex, + txsAllDoneOnCloseCond: sync.NewCond(txsCountMutex), + leakDetector: dbg.NewLeakDetector("db."+opts.label.String(), dbg.SlowTx()), } @@ -457,7 +462,6 @@ func (opts MdbxOpts) MustOpen() kv.RwDB { type MdbxKV struct { log log.Logger env *mdbx.Env - wg *sync.WaitGroup buckets kv.TableCfg roTxsLimiter *semaphore.Weighted // does limit amount of concurrent Ro transactions - in most casess runtime.NumCPU() is good value for this channel capacity - this channel can be shared with other components (like Decompressor) opts MdbxOpts @@ -465,6 +469,10 @@ type MdbxKV struct { closed atomic.Bool path string + txsCount uint + txsCountMutex *sync.Mutex + txsAllDoneOnCloseCond *sync.Cond + leakDetector *dbg.LeakDetector } @@ -507,13 +515,53 @@ func (db *MdbxKV) openDBIs(buckets []string) error { }) } +func (db *MdbxKV) trackTxBegin() bool { + db.txsCountMutex.Lock() + defer db.txsCountMutex.Unlock() + + isOpen := !db.closed.Load() + if isOpen { + db.txsCount++ + } + return isOpen +} + +func (db *MdbxKV) hasTxsAllDoneAndClosed() bool { + return (db.txsCount == 0) && db.closed.Load() +} + +func (db *MdbxKV) trackTxEnd() { + db.txsCountMutex.Lock() + defer db.txsCountMutex.Unlock() + + if db.txsCount > 0 { + db.txsCount-- + } else { + panic("MdbxKV: unmatched trackTxEnd") + } + + if db.hasTxsAllDoneAndClosed() { + db.txsAllDoneOnCloseCond.Signal() + } +} + +func (db *MdbxKV) waitTxsAllDoneOnClose() { + db.txsCountMutex.Lock() + defer db.txsCountMutex.Unlock() + + for !db.hasTxsAllDoneAndClosed() { + db.txsAllDoneOnCloseCond.Wait() + } +} + // Close closes db // All transactions must be closed before closing the database. func (db *MdbxKV) Close() { if ok := db.closed.CompareAndSwap(false, true); !ok { return } - db.wg.Wait() + db.waitTxsAllDoneOnClose() + db.env.Close() db.env = nil @@ -526,10 +574,6 @@ func (db *MdbxKV) Close() { } func (db *MdbxKV) BeginRo(ctx context.Context) (txn kv.Tx, err error) { - if db.closed.Load() { - return nil, fmt.Errorf("db closed") - } - // don't try to acquire if the context is already done select { case <-ctx.Done(): @@ -538,8 +582,13 @@ func (db *MdbxKV) BeginRo(ctx context.Context) (txn kv.Tx, err error) { // otherwise carry on } + if !db.trackTxBegin() { + return nil, fmt.Errorf("db closed") + } + // will return nil err if context is cancelled (may appear to acquire the semaphore) if semErr := db.roTxsLimiter.Acquire(ctx, 1); semErr != nil { + db.trackTxEnd() return nil, semErr } @@ -548,6 +597,7 @@ func (db *MdbxKV) BeginRo(ctx context.Context) (txn kv.Tx, err error) { // on error, or if there is whatever reason that we don't return a tx, // we need to free up the limiter slot, otherwise it could lead to deadlocks db.roTxsLimiter.Release(1) + db.trackTxEnd() } }() @@ -555,7 +605,7 @@ func (db *MdbxKV) BeginRo(ctx context.Context) (txn kv.Tx, err error) { if err != nil { return nil, fmt.Errorf("%w, label: %s, trace: %s", err, db.opts.label.String(), stack2.Trace().String()) } - db.wg.Add(1) + return &MdbxTx{ ctx: ctx, db: db, @@ -579,16 +629,18 @@ func (db *MdbxKV) beginRw(ctx context.Context, flags uint) (txn kv.RwTx, err err default: } - if db.closed.Load() { + if !db.trackTxBegin() { return nil, fmt.Errorf("db closed") } + runtime.LockOSThread() tx, err := db.env.BeginTxn(nil, flags) if err != nil { runtime.UnlockOSThread() // unlock only in case of error. normal flow is "defer .Rollback()" + db.trackTxEnd() return nil, fmt.Errorf("%w, lable: %s, trace: %s", err, db.opts.label.String(), stack2.Trace().String()) } - db.wg.Add(1) + return &MdbxTx{ db: db, tx: tx, @@ -830,7 +882,7 @@ func (tx *MdbxTx) Commit() error { } defer func() { tx.tx = nil - tx.db.wg.Done() + tx.db.trackTxEnd() if tx.readOnly { tx.db.roTxsLimiter.Release(1) } else { @@ -881,7 +933,7 @@ func (tx *MdbxTx) Rollback() { } defer func() { tx.tx = nil - tx.db.wg.Done() + tx.db.trackTxEnd() if tx.readOnly { tx.db.roTxsLimiter.Release(1) } else { diff --git a/erigon-lib/kv/mdbx/kv_mdbx_test.go b/erigon-lib/kv/mdbx/kv_mdbx_test.go index e79a852dae2..66506ef720f 100644 --- a/erigon-lib/kv/mdbx/kv_mdbx_test.go +++ b/erigon-lib/kv/mdbx/kv_mdbx_test.go @@ -18,14 +18,17 @@ package mdbx import ( "context" + "sync/atomic" "testing" + "time" "github.com/c2h5oh/datasize" - "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon-lib/kv/order" "github.com/ledgerwatch/log/v3" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon-lib/kv/order" ) func BaseCase(t *testing.T) (kv.RwDB, kv.RwTx, kv.RwCursorDupSort) { @@ -773,3 +776,124 @@ func TestAutoConversionSeekBothRange(t *testing.T) { require.NoError(t, err) assert.Nil(t, v) } + +func TestBeginRoAfterClose(t *testing.T) { + db := NewMDBX(log.New()).InMem(t.TempDir()).MustOpen() + db.Close() + _, err := db.BeginRo(context.Background()) + require.ErrorContains(t, err, "closed") +} + +func TestBeginRwAfterClose(t *testing.T) { + db := NewMDBX(log.New()).InMem(t.TempDir()).MustOpen() + db.Close() + _, err := db.BeginRw(context.Background()) + require.ErrorContains(t, err, "closed") +} + +func TestBeginRoWithDoneContext(t *testing.T) { + db := NewMDBX(log.New()).InMem(t.TempDir()).MustOpen() + defer db.Close() + ctx, cancel := context.WithCancel(context.Background()) + cancel() + _, err := db.BeginRo(ctx) + require.ErrorIs(t, err, context.Canceled) +} + +func TestBeginRwWithDoneContext(t *testing.T) { + db := NewMDBX(log.New()).InMem(t.TempDir()).MustOpen() + defer db.Close() + ctx, cancel := context.WithCancel(context.Background()) + cancel() + _, err := db.BeginRw(ctx) + require.ErrorIs(t, err, context.Canceled) +} + +func testCloseWaitsAfterTxBegin( + t *testing.T, + count int, + txBeginFunc func(kv.RwDB) (kv.StatelessReadTx, error), + txEndFunc func(kv.StatelessReadTx) error, +) { + t.Helper() + db := NewMDBX(log.New()).InMem(t.TempDir()).MustOpen() + var txs []kv.StatelessReadTx + for i := 0; i < count; i++ { + tx, err := txBeginFunc(db) + require.Nil(t, err) + txs = append(txs, tx) + } + + isClosed := &atomic.Bool{} + closeDone := make(chan struct{}) + + go func() { + db.Close() + isClosed.Store(true) + close(closeDone) + }() + + for _, tx := range txs { + // arbitrary delay to give db.Close() a chance to exit prematurely + time.Sleep(time.Millisecond * 20) + assert.False(t, isClosed.Load()) + + err := txEndFunc(tx) + require.Nil(t, err) + } + + <-closeDone + assert.True(t, isClosed.Load()) +} + +func TestCloseWaitsAfterTxBegin(t *testing.T) { + ctx := context.Background() + t.Run("BeginRoAndCommit", func(t *testing.T) { + testCloseWaitsAfterTxBegin( + t, + 1, + func(db kv.RwDB) (kv.StatelessReadTx, error) { return db.BeginRo(ctx) }, + func(tx kv.StatelessReadTx) error { return tx.Commit() }, + ) + }) + t.Run("BeginRoAndCommit3", func(t *testing.T) { + testCloseWaitsAfterTxBegin( + t, + 3, + func(db kv.RwDB) (kv.StatelessReadTx, error) { return db.BeginRo(ctx) }, + func(tx kv.StatelessReadTx) error { return tx.Commit() }, + ) + }) + t.Run("BeginRoAndRollback", func(t *testing.T) { + testCloseWaitsAfterTxBegin( + t, + 1, + func(db kv.RwDB) (kv.StatelessReadTx, error) { return db.BeginRo(ctx) }, + func(tx kv.StatelessReadTx) error { tx.Rollback(); return nil }, + ) + }) + t.Run("BeginRoAndRollback3", func(t *testing.T) { + testCloseWaitsAfterTxBegin( + t, + 3, + func(db kv.RwDB) (kv.StatelessReadTx, error) { return db.BeginRo(ctx) }, + func(tx kv.StatelessReadTx) error { tx.Rollback(); return nil }, + ) + }) + t.Run("BeginRwAndCommit", func(t *testing.T) { + testCloseWaitsAfterTxBegin( + t, + 1, + func(db kv.RwDB) (kv.StatelessReadTx, error) { return db.BeginRw(ctx) }, + func(tx kv.StatelessReadTx) error { return tx.Commit() }, + ) + }) + t.Run("BeginRwAndRollback", func(t *testing.T) { + testCloseWaitsAfterTxBegin( + t, + 1, + func(db kv.RwDB) (kv.StatelessReadTx, error) { return db.BeginRw(ctx) }, + func(tx kv.StatelessReadTx) error { tx.Rollback(); return nil }, + ) + }) +} From 4abc6cd119e29203e36bc50f78c7864513d1af87 Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Thu, 18 Jan 2024 09:27:03 +0100 Subject: [PATCH 80/92] =?UTF-8?q?Schedule=20Dencun=20for=20Sepolia=20&=20H?= =?UTF-8?q?ole=C5=A1ky=20(#9255)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://github.com/ethereum/EIPs/pull/8051 & https://github.com/ethereum/execution-specs/pull/860 --- cl/clparams/config.go | 2 ++ core/forkid/forkid_test.go | 14 ++++++++------ params/chainspecs/holesky.json | 3 ++- params/chainspecs/sepolia.json | 1 + 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/cl/clparams/config.go b/cl/clparams/config.go index 8748f7a8f28..ec7ba8516fd 100644 --- a/cl/clparams/config.go +++ b/cl/clparams/config.go @@ -805,6 +805,8 @@ func sepoliaConfig() BeaconChainConfig { cfg.BellatrixForkVersion = 0x90000071 cfg.CapellaForkEpoch = 56832 cfg.CapellaForkVersion = 0x90000072 + cfg.DenebForkEpoch = 132608 + cfg.DenebForkVersion = 0x90000073 cfg.TerminalTotalDifficulty = "17000000000000000" cfg.DepositContractAddress = "0x7f02C3E3c98b133055B8B348B2Ac625669Ed295D" cfg.InitializeForkSchedule() diff --git a/core/forkid/forkid_test.go b/core/forkid/forkid_test.go index ab631f9e246..179c2dd0e90 100644 --- a/core/forkid/forkid_test.go +++ b/core/forkid/forkid_test.go @@ -93,8 +93,8 @@ func TestCreation(t *testing.T) { {5062605, 1625109579, ID{Hash: checksumToBytes(0xB8C6299D), Next: 1678832736}}, // First London block {8656122, 1678832724, ID{Hash: checksumToBytes(0xB8C6299D), Next: 1678832736}}, // Last pre-Shanghai block {8656123, 1678832784, ID{Hash: checksumToBytes(0xf9843abf), Next: 1705473120}}, // First Shanghai block - {10416288, 1705473108, ID{Hash: checksumToBytes(0xf9843abf), Next: 1705473120}}, // Last Shanghai block (approx) - {10416289, 1705473120, ID{Hash: checksumToBytes(0x70cc14e2), Next: 0}}, // First Cancun block (approx) + {10388175, 1705473108, ID{Hash: checksumToBytes(0xf9843abf), Next: 1705473120}}, // Last Shanghai block + {10388176, 1705473120, ID{Hash: checksumToBytes(0x70cc14e2), Next: 0}}, // First Cancun block {12000000, 1800000000, ID{Hash: checksumToBytes(0x70cc14e2), Next: 0}}, // Future Cancun block (mock) }, }, @@ -107,8 +107,10 @@ func TestCreation(t *testing.T) { {1735370, 1661130096, ID{Hash: checksumToBytes(0xfe3366e7), Next: 1735371}}, // Last pre-MergeNetsplit block {1735371, 1661130108, ID{Hash: checksumToBytes(0xb96cbd13), Next: 1677557088}}, // First MergeNetsplit block {2990907, 1677557076, ID{Hash: checksumToBytes(0xb96cbd13), Next: 1677557088}}, // Last pre-Shanghai block - {2990908, 1677557088, ID{Hash: checksumToBytes(0xf7f9bc08), Next: 0}}, // First Shanghai block - {5000000, 1700000000, ID{Hash: checksumToBytes(0xf7f9bc08), Next: 0}}, // Future Shanghai block (mock) + {2990908, 1677557088, ID{Hash: checksumToBytes(0xf7f9bc08), Next: 1706655072}}, // First Shanghai block + {5198775, 1706655060, ID{Hash: checksumToBytes(0xf7f9bc08), Next: 1706655072}}, // Last Shanghai block (approx) + {5198776, 1706655072, ID{Hash: checksumToBytes(0x88cf81d9), Next: 0}}, // First Cancun block (approx) + {8000000, 1800000000, ID{Hash: checksumToBytes(0x88cf81d9), Next: 0}}, // Future Cancun block (mock) }, }, // Gnosis test cases @@ -130,8 +132,8 @@ func TestCreation(t *testing.T) { {19039999, 1636753575, ID{Hash: checksumToBytes(0x069a83d9), Next: 19040000}}, // Last Berlin block {19040000, 1636753580, ID{Hash: checksumToBytes(0x018479d3), Next: 1690889660}}, // First London block {21735000, 1650443255, ID{Hash: checksumToBytes(0x018479d3), Next: 1690889660}}, // First GIP-31 block - {29272666, 1690889655, ID{Hash: checksumToBytes(0x018479d3), Next: 1690889660}}, // Last pre-Shanghai block (approx) - {29272667, 1690889660, ID{Hash: checksumToBytes(0x2efe91ba), Next: 0}}, // First Shanghai block (approx) + {29242931, 1690889650, ID{Hash: checksumToBytes(0x018479d3), Next: 1690889660}}, // Last pre-Shanghai block + {29242932, 1690889660, ID{Hash: checksumToBytes(0x2efe91ba), Next: 0}}, // First Shanghai block }, }, // Chiado test cases diff --git a/params/chainspecs/holesky.json b/params/chainspecs/holesky.json index 852beb80e3d..e582e406008 100644 --- a/params/chainspecs/holesky.json +++ b/params/chainspecs/holesky.json @@ -13,5 +13,6 @@ "mergeForkBlock": 0, "terminalTotalDifficulty": 0, "terminalTotalDifficultyPassed": true, - "shanghaiTime": 1696000704 + "shanghaiTime": 1696000704, + "cancunTime": 1707305664 } \ No newline at end of file diff --git a/params/chainspecs/sepolia.json b/params/chainspecs/sepolia.json index 9c9d42410d9..9fe80a63fbe 100644 --- a/params/chainspecs/sepolia.json +++ b/params/chainspecs/sepolia.json @@ -16,5 +16,6 @@ "terminalTotalDifficultyPassed": true, "mergeNetsplitBlock": 1735371, "shanghaiTime": 1677557088, + "cancunTime": 1706655072, "ethash": {} } From 3040e2576c29512addaf8ce50528609b4ff9a8e0 Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Thu, 18 Jan 2024 14:27:36 +0100 Subject: [PATCH 81/92] logs: remove "height=unknown" (#9261) "[EngineBlockDownloader] Downloading PoS headers... height=unknown" might be [confusing](https://discord.com/channels/687972960811745322/1001501454076477450/1197365760125841550) for users. --- .../engineapi/engine_block_downloader/block_downloader.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/turbo/engineapi/engine_block_downloader/block_downloader.go b/turbo/engineapi/engine_block_downloader/block_downloader.go index 7c08b42ee86..83c0e4dfece 100644 --- a/turbo/engineapi/engine_block_downloader/block_downloader.go +++ b/turbo/engineapi/engine_block_downloader/block_downloader.go @@ -5,7 +5,6 @@ import ( "context" "encoding/binary" "fmt" - "github.com/ledgerwatch/erigon-lib/kv/dbutils" "math/big" "sync" "sync/atomic" @@ -18,6 +17,8 @@ import ( "github.com/ledgerwatch/erigon-lib/etl" "github.com/ledgerwatch/erigon-lib/gointerfaces/execution" "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon-lib/kv/dbutils" + "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/rlp" @@ -101,9 +102,9 @@ func (e *EngineBlockDownloader) scheduleHeadersDownload( } if heightToDownload == 0 { - e.logger.Info("[EngineBlockDownloader] Downloading PoS headers...", "height", "unknown", "hash", hashToDownload, "requestId", requestId) + e.logger.Info("[EngineBlockDownloader] Downloading PoS headers...", "hash", hashToDownload, "requestId", requestId) } else { - e.logger.Info("[EngineBlockDownloader] Downloading PoS headers...", "height", heightToDownload, "hash", hashToDownload, "requestId", requestId) + e.logger.Info("[EngineBlockDownloader] Downloading PoS headers...", "hash", hashToDownload, "requestId", requestId, "height", heightToDownload) } e.hd.SetRequestId(requestId) From 4f6eda7694b4f33d2f907b40088e3a83192b5c2c Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Thu, 18 Jan 2024 17:04:17 +0100 Subject: [PATCH 82/92] release params: remove dev (#9265) --- params/version.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/params/version.go b/params/version.go index a1b0c0ae15b..e8a837e574d 100644 --- a/params/version.go +++ b/params/version.go @@ -31,10 +31,10 @@ var ( // see https://calver.org const ( - VersionMajor = 2 // Major version component of the current release - VersionMinor = 57 // Minor version component of the current release - VersionMicro = 0 // Patch version component of the current release - VersionModifier = "dev" // Modifier component of the current release + VersionMajor = 2 // Major version component of the current release + VersionMinor = 57 // Minor version component of the current release + VersionMicro = 0 // Patch version component of the current release + VersionModifier = "" // Modifier component of the current release VersionKeyCreated = "ErigonVersionCreated" VersionKeyFinished = "ErigonVersionFinished" ) From 20999401b291cc48d6d1778ba580d4c8d0ffa800 Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Wed, 24 Jan 2024 12:41:31 +0100 Subject: [PATCH 83/92] release: downloader: prohibit_new_downloads.lock check missed download (#9300) Cherry pick PR #9295 --------- Co-authored-by: Alex Sharov --- erigon-lib/downloader/downloader.go | 26 +--------- .../downloader/downloader_grpc_server.go | 2 +- erigon-lib/downloader/torrent_files.go | 49 ++++++++++++++++--- erigon-lib/downloader/webseed.go | 3 ++ eth/backend.go | 6 ++- params/version.go | 2 +- 6 files changed, 53 insertions(+), 35 deletions(-) diff --git a/erigon-lib/downloader/downloader.go b/erigon-lib/downloader/downloader.go index 8a42ed2c21f..ecb10ae267d 100644 --- a/erigon-lib/downloader/downloader.go +++ b/erigon-lib/downloader/downloader.go @@ -21,8 +21,6 @@ import ( "errors" "fmt" "net/url" - "os" - "path/filepath" "runtime" "strings" "sync" @@ -41,7 +39,6 @@ import ( "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/datadir" "github.com/ledgerwatch/erigon-lib/common/dbg" - "github.com/ledgerwatch/erigon-lib/common/dir" "github.com/ledgerwatch/erigon-lib/diagnostics" "github.com/ledgerwatch/erigon-lib/downloader/downloadercfg" "github.com/ledgerwatch/erigon-lib/downloader/snaptype" @@ -147,27 +144,6 @@ func New(ctx context.Context, cfg *downloadercfg.Cfg, dirs datadir.Dirs, logger return d, nil } -const ProhibitNewDownloadsFileName = "prohibit_new_downloads.lock" - -// Erigon "download once" - means restart/upgrade/downgrade will not download files (and will be fast) -// After "download once" - Erigon will produce and seed new files -// Downloader will able: seed new files (already existing on FS), download uncomplete parts of existing files (if Verify found some bad parts) -func (d *Downloader) prohibitNewDownloads() error { - fPath := filepath.Join(d.SnapDir(), ProhibitNewDownloadsFileName) - f, err := os.Create(fPath) - if err != nil { - return err - } - defer f.Close() - if err := f.Sync(); err != nil { - return err - } - return nil -} -func (d *Downloader) newDownloadsAreProhibited() bool { - return dir.FileExist(filepath.Join(d.SnapDir(), ProhibitNewDownloadsFileName)) -} - func (d *Downloader) MainLoopInBackground(silent bool) { d.wg.Add(1) go func() { @@ -605,7 +581,7 @@ func (d *Downloader) AddMagnetLink(ctx context.Context, infoHash metainfo.Hash, if d.alreadyHaveThisName(name) { return nil } - if d.newDownloadsAreProhibited() { + if d.torrentFiles.newDownloadsAreProhibited() { return nil } diff --git a/erigon-lib/downloader/downloader_grpc_server.go b/erigon-lib/downloader/downloader_grpc_server.go index 33410793475..8f448788e85 100644 --- a/erigon-lib/downloader/downloader_grpc_server.go +++ b/erigon-lib/downloader/downloader_grpc_server.go @@ -46,7 +46,7 @@ type GrpcServer struct { } func (s *GrpcServer) ProhibitNewDownloads(context.Context, *proto_downloader.ProhibitNewDownloadsRequest) (*emptypb.Empty, error) { - if err := s.d.prohibitNewDownloads(); err != nil { + if err := s.d.torrentFiles.prohibitNewDownloads(); err != nil { return nil, err } return nil, nil diff --git a/erigon-lib/downloader/torrent_files.go b/erigon-lib/downloader/torrent_files.go index 51d1c8ddd1a..d8eb8c815c8 100644 --- a/erigon-lib/downloader/torrent_files.go +++ b/erigon-lib/downloader/torrent_files.go @@ -4,6 +4,7 @@ import ( "fmt" "os" "path/filepath" + "strings" "sync" "github.com/anacrolix/torrent" @@ -28,8 +29,10 @@ func (tf *TorrentFiles) Exists(name string) bool { } func (tf *TorrentFiles) exists(name string) bool { - fPath := filepath.Join(tf.dir, name) - return dir2.FileExist(fPath + ".torrent") + if !strings.HasSuffix(name, ".torrent") { + name += ".torrent" + } + return dir2.FileExist(filepath.Join(tf.dir, name)) } func (tf *TorrentFiles) Delete(name string) error { tf.lock.Lock() @@ -38,8 +41,10 @@ func (tf *TorrentFiles) Delete(name string) error { } func (tf *TorrentFiles) delete(name string) error { - fPath := filepath.Join(tf.dir, name) - return os.Remove(fPath + ".torrent") + if !strings.HasSuffix(name, ".torrent") { + name += ".torrent" + } + return os.Remove(filepath.Join(tf.dir, name)) } func (tf *TorrentFiles) Create(torrentFilePath string, res []byte) error { @@ -91,11 +96,10 @@ func (tf *TorrentFiles) createTorrentFromMetaInfo(fPath string, mi *metainfo.Met return nil } -func (tf *TorrentFiles) LoadByName(fName string) (*torrent.TorrentSpec, error) { +func (tf *TorrentFiles) LoadByName(name string) (*torrent.TorrentSpec, error) { tf.lock.Lock() defer tf.lock.Unlock() - fPath := filepath.Join(tf.dir, fName+".torrent") - return tf.load(fPath) + return tf.load(filepath.Join(tf.dir, name)) } func (tf *TorrentFiles) LoadByPath(fPath string) (*torrent.TorrentSpec, error) { @@ -105,6 +109,9 @@ func (tf *TorrentFiles) LoadByPath(fPath string) (*torrent.TorrentSpec, error) { } func (tf *TorrentFiles) load(fPath string) (*torrent.TorrentSpec, error) { + if !strings.HasSuffix(fPath, ".torrent") { + fPath += ".torrent" + } mi, err := metainfo.LoadFromFile(fPath) if err != nil { return nil, fmt.Errorf("LoadFromFile: %w, file=%s", err, fPath) @@ -112,3 +119,31 @@ func (tf *TorrentFiles) load(fPath string) (*torrent.TorrentSpec, error) { mi.AnnounceList = Trackers return torrent.TorrentSpecFromMetaInfoErr(mi) } + +const ProhibitNewDownloadsFileName = "prohibit_new_downloads.lock" + +// Erigon "download once" - means restart/upgrade/downgrade will not download files (and will be fast) +// After "download once" - Erigon will produce and seed new files +// Downloader will able: seed new files (already existing on FS), download uncomplete parts of existing files (if Verify found some bad parts) +func (tf *TorrentFiles) prohibitNewDownloads() error { + tf.lock.Lock() + defer tf.lock.Unlock() + return CreateProhibitNewDownloadsFile(tf.dir) +} +func (tf *TorrentFiles) newDownloadsAreProhibited() bool { + tf.lock.Lock() + defer tf.lock.Unlock() + return dir2.FileExist(filepath.Join(tf.dir, ProhibitNewDownloadsFileName)) +} +func CreateProhibitNewDownloadsFile(dir string) error { + fPath := filepath.Join(dir, ProhibitNewDownloadsFileName) + f, err := os.Create(fPath) + if err != nil { + return err + } + defer f.Close() + if err := f.Sync(); err != nil { + return err + } + return nil +} diff --git a/erigon-lib/downloader/webseed.go b/erigon-lib/downloader/webseed.go index f6433103356..6dc4519dd74 100644 --- a/erigon-lib/downloader/webseed.go +++ b/erigon-lib/downloader/webseed.go @@ -237,6 +237,9 @@ func (d *WebSeeds) downloadTorrentFilesFromProviders(ctx context.Context, rootDi if len(d.TorrentUrls()) == 0 { return } + if d.torrentFiles.newDownloadsAreProhibited() { + return + } var addedNew int e, ctx := errgroup.WithContext(ctx) e.SetLimit(1024) diff --git a/eth/backend.go b/eth/backend.go index 9d24aabaf21..38e52211e6e 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -266,11 +266,15 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger config.Sync.UseSnapshots = useSnapshots config.Snapshot.Enabled = ethconfig.UseSnapshotsByChainName(config.Genesis.Config.ChainName) && useSnapshots } - return nil }); err != nil { return nil, err } + if !config.Sync.UseSnapshots { + if err := downloader.CreateProhibitNewDownloadsFile(dirs.Snap); err != nil { + return nil, err + } + } ctx, ctxCancel := context.WithCancel(context.Background()) diff --git a/params/version.go b/params/version.go index e8a837e574d..ce8420074a6 100644 --- a/params/version.go +++ b/params/version.go @@ -33,7 +33,7 @@ var ( const ( VersionMajor = 2 // Major version component of the current release VersionMinor = 57 // Minor version component of the current release - VersionMicro = 0 // Patch version component of the current release + VersionMicro = 1 // Patch version component of the current release VersionModifier = "" // Modifier component of the current release VersionKeyCreated = "ErigonVersionCreated" VersionKeyFinished = "ErigonVersionFinished" From 9f1cd651f0b1b443b4bd96eaed84502c149fdca2 Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Wed, 24 Jan 2024 13:33:28 +0100 Subject: [PATCH 84/92] (release) txpool: fix initial blockGasLimit and setBlobFee() (#9303) Cherry pick PR #9301 --- consensus/misc/eip1559.go | 8 ++++---- erigon-lib/txpool/pool.go | 20 +++++++++++++++----- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/consensus/misc/eip1559.go b/consensus/misc/eip1559.go index b2a53af3f53..88c0fe55435 100644 --- a/consensus/misc/eip1559.go +++ b/consensus/misc/eip1559.go @@ -63,17 +63,17 @@ var Eip1559FeeCalculator eip1559Calculator type eip1559Calculator struct{} -func (f eip1559Calculator) CurrentFees(chainConfig *chain.Config, db kv.Getter) (baseFee uint64, blobFee uint64, minBlobGasPrice uint64, err error) { +func (f eip1559Calculator) CurrentFees(chainConfig *chain.Config, db kv.Getter) (baseFee, blobFee, minBlobGasPrice, blockGasLimit uint64, err error) { hash := rawdb.ReadHeadHeaderHash(db) if hash == (libcommon.Hash{}) { - return 0, 0, 0, fmt.Errorf("can't get head header hash") + return 0, 0, 0, 0, fmt.Errorf("can't get head header hash") } currentHeader, err := rawdb.ReadHeaderByHash(db, hash) if err != nil { - return 0, 0, 0, err + return 0, 0, 0, 0, err } if chainConfig != nil { @@ -92,7 +92,7 @@ func (f eip1559Calculator) CurrentFees(chainConfig *chain.Config, db kv.Getter) minBlobGasPrice = chainConfig.GetMinBlobGasPrice() - return baseFee, blobFee, minBlobGasPrice, nil + return baseFee, blobFee, minBlobGasPrice, currentHeader.GasLimit, nil } // CalcBaseFee calculates the basefee of the header. diff --git a/erigon-lib/txpool/pool.go b/erigon-lib/txpool/pool.go index d56b4d7ccec..fa5a0b1b5b7 100644 --- a/erigon-lib/txpool/pool.go +++ b/erigon-lib/txpool/pool.go @@ -61,6 +61,8 @@ import ( "github.com/ledgerwatch/erigon-lib/types" ) +const DefaultBlockGasLimit = uint64(30000000) + var ( processBatchTxsTimer = metrics.NewSummary(`pool_process_remote_txs`) addRemoteTxsTimer = metrics.NewSummary(`pool_add_remote_txs`) @@ -229,7 +231,7 @@ type TxPool struct { } type FeeCalculator interface { - CurrentFees(chainConfig *chain.Config, db kv.Getter) (baseFee uint64, blobFee uint64, minBlobGasPrice uint64, err error) + CurrentFees(chainConfig *chain.Config, db kv.Getter) (baseFee uint64, blobFee uint64, minBlobGasPrice, blockGasLimit uint64, err error) } func New(newTxs chan types.Announcements, coreDB kv.RoDB, cfg txpoolcfg.Config, cache kvcache.Cache, @@ -1317,7 +1319,7 @@ func (p *TxPool) setBaseFee(baseFee uint64) (uint64, bool) { func (p *TxPool) setBlobFee(blobFee uint64) { if blobFee > 0 { - p.pendingBaseFee.Store(blobFee) + p.pendingBlobFee.Store(blobFee) } } @@ -2086,11 +2088,14 @@ func (p *TxPool) fromDB(ctx context.Context, tx kv.Tx, coreTx kv.Tx) error { i++ } - var pendingBaseFee, pendingBlobFee, minBlobGasPrice uint64 + var pendingBaseFee, pendingBlobFee, minBlobGasPrice, blockGasLimit uint64 if p.feeCalculator != nil { if chainConfig, _ := ChainConfig(tx); chainConfig != nil { - pendingBaseFee, pendingBlobFee, minBlobGasPrice, _ = p.feeCalculator.CurrentFees(chainConfig, coreTx) + pendingBaseFee, pendingBlobFee, minBlobGasPrice, blockGasLimit, err = p.feeCalculator.CurrentFees(chainConfig, coreTx) + if err != nil { + return err + } } } @@ -2118,16 +2123,21 @@ func (p *TxPool) fromDB(ctx context.Context, tx kv.Tx, coreTx kv.Tx) error { pendingBlobFee = minBlobGasPrice } + if blockGasLimit == 0 { + blockGasLimit = DefaultBlockGasLimit + } + err = p.senders.registerNewSenders(&txs, p.logger) if err != nil { return err } if _, _, err := p.addTxs(p.lastSeenBlock.Load(), cacheView, p.senders, txs, - pendingBaseFee, pendingBlobFee, math.MaxUint64 /* blockGasLimit */, false, p.logger); err != nil { + pendingBaseFee, pendingBlobFee, blockGasLimit, false, p.logger); err != nil { return err } p.pendingBaseFee.Store(pendingBaseFee) p.pendingBlobFee.Store(pendingBlobFee) + p.blockGasLimit.Store(blockGasLimit) return nil } From ffb6b83c0929c473164c53080441458947c43aa3 Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Mon, 29 Jan 2024 13:49:47 +0100 Subject: [PATCH 85/92] (release) RpcDaemon doesn't see recently retired blocks (#9336) Cherry pick PR #9318 --------- Co-authored-by: Alex Sharov --- .../kv/remotedbserver/remotedbserver.go | 16 +++++-- eth/integrity/snap_blocks_read.go | 46 +++++++++++++++++++ params/version.go | 2 +- turbo/app/snapshots_cmd.go | 7 ++- 4 files changed, 66 insertions(+), 5 deletions(-) create mode 100644 eth/integrity/snap_blocks_read.go diff --git a/erigon-lib/kv/remotedbserver/remotedbserver.go b/erigon-lib/kv/remotedbserver/remotedbserver.go index f276674cb78..8537cef2612 100644 --- a/erigon-lib/kv/remotedbserver/remotedbserver.go +++ b/erigon-lib/kv/remotedbserver/remotedbserver.go @@ -458,17 +458,27 @@ func (s *KvServer) SendStateChanges(_ context.Context, sc *remote.StateChangeBat s.stateChangeStreams.Pub(sc) } -func (s *KvServer) Snapshots(_ context.Context, _ *remote.SnapshotsRequest) (*remote.SnapshotsReply, error) { +func (s *KvServer) Snapshots(_ context.Context, _ *remote.SnapshotsRequest) (reply *remote.SnapshotsReply, err error) { + defer func() { + if rec := recover(); rec != nil { + err = fmt.Errorf("%v, %s", rec, dbg.Stack()) + } + }() if s.blockSnapshots == nil || reflect.ValueOf(s.blockSnapshots).IsNil() { // nolint return &remote.SnapshotsReply{BlocksFiles: []string{}, HistoryFiles: []string{}}, nil } blockFiles := s.blockSnapshots.Files() - if s.borSnapshots != nil { + if s.borSnapshots != nil && !reflect.ValueOf(s.borSnapshots).IsNil() { // nolint blockFiles = append(blockFiles, s.borSnapshots.Files()...) } - return &remote.SnapshotsReply{BlocksFiles: blockFiles, HistoryFiles: s.historySnapshots.Files()}, nil + reply = &remote.SnapshotsReply{BlocksFiles: blockFiles} + if s.historySnapshots != nil && !reflect.ValueOf(s.historySnapshots).IsNil() { // nolint + reply.HistoryFiles = s.historySnapshots.Files() + } + + return reply, nil } type StateChangePubSub struct { diff --git a/eth/integrity/snap_blocks_read.go b/eth/integrity/snap_blocks_read.go new file mode 100644 index 00000000000..c7fcf356f73 --- /dev/null +++ b/eth/integrity/snap_blocks_read.go @@ -0,0 +1,46 @@ +package integrity + +import ( + "context" + "fmt" + "time" + + "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon/turbo/services" + "github.com/ledgerwatch/log/v3" +) + +func SnapBlocksRead(db kv.RoDB, blockReader services.FullBlockReader, ctx context.Context, failFast bool) error { + defer log.Info("[integrity] SnapBlocksRead: done") + logEvery := time.NewTicker(10 * time.Second) + defer logEvery.Stop() + + maxBlockNum := blockReader.Snapshots().SegmentsMax() + for i := uint64(0); i < maxBlockNum; i += 10_000 { + if err := db.View(ctx, func(tx kv.Tx) error { + b, err := blockReader.BlockByNumber(ctx, tx, i) + if err != nil { + return err + } + if b == nil { + err := fmt.Errorf("block not found in snapshots: %d\n", i) + if failFast { + return err + } + log.Error("[integrity] SnapBlocksRead", "err", err) + } + return nil + }); err != nil { + return err + } + + select { + case <-ctx.Done(): + return nil + case <-logEvery.C: + log.Info("[integrity] SnapBlocksRead", "blockNum", fmt.Sprintf("%dK/%dK", i/1000, maxBlockNum/1000)) + default: + } + } + return nil +} diff --git a/params/version.go b/params/version.go index ce8420074a6..6d1ca420d22 100644 --- a/params/version.go +++ b/params/version.go @@ -33,7 +33,7 @@ var ( const ( VersionMajor = 2 // Major version component of the current release VersionMinor = 57 // Minor version component of the current release - VersionMicro = 1 // Patch version component of the current release + VersionMicro = 2 // Patch version component of the current release VersionModifier = "" // Modifier component of the current release VersionKeyCreated = "ErigonVersionCreated" VersionKeyFinished = "ErigonVersionFinished" diff --git a/turbo/app/snapshots_cmd.go b/turbo/app/snapshots_cmd.go index c4419b11444..88912a6fba7 100644 --- a/turbo/app/snapshots_cmd.go +++ b/turbo/app/snapshots_cmd.go @@ -19,6 +19,7 @@ import ( "github.com/ledgerwatch/erigon-lib/common/dbg" "github.com/ledgerwatch/erigon-lib/common/dir" "github.com/ledgerwatch/erigon-lib/metrics" + "github.com/ledgerwatch/erigon/eth/integrity" "github.com/ledgerwatch/log/v3" "github.com/urfave/cli/v2" "golang.org/x/sync/semaphore" @@ -223,10 +224,14 @@ func doIntegrity(cliCtx *cli.Context) error { defer agg.Close() blockReader, _ := blockRetire.IO() - if err := blockReader.(*freezeblocks.BlockReader).IntegrityTxnID(false); err != nil { + if err := integrity.SnapBlocksRead(chainDB, blockReader, ctx, false); err != nil { return err } + //if err := blockReader.(*freezeblocks.BlockReader).IntegrityTxnID(false); err != nil { + // return err + //} + //if err := integrity.E3HistoryNoSystemTxs(ctx, chainDB, agg); err != nil { // return err //} From 705814b1ab72f3f25bef5230bd0c4dbaa0bc1f2a Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Tue, 30 Jan 2024 10:45:47 +0100 Subject: [PATCH 86/92] Mumbai: add Napoli block (#9346) Cherry pick PR #9345 --------- Co-authored-by: Arpit Temani --- core/forkid/forkid_test.go | 3 ++- params/chainspecs/mumbai.json | 3 ++- params/version.go | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/core/forkid/forkid_test.go b/core/forkid/forkid_test.go index 179c2dd0e90..41c52891bf5 100644 --- a/core/forkid/forkid_test.go +++ b/core/forkid/forkid_test.go @@ -158,7 +158,8 @@ func TestCreation(t *testing.T) { {2722000, 0, ID{Hash: checksumToBytes(0x8647df30), Next: 13996000}}, // First Istanbul block {13996000, 0, ID{Hash: checksumToBytes(0x06cc1179), Next: 22640000}}, // First Berlin block {22640000, 0, ID{Hash: checksumToBytes(0x9adf950e), Next: 41874000}}, // First London block - {41874000, 0, ID{Hash: checksumToBytes(0x0c015a91), Next: 0}}, // First Agra block + {41874000, 0, ID{Hash: checksumToBytes(0x0c015a91), Next: 45648608}}, // First Agra block + {45648608, 0, ID{Hash: checksumToBytes(0x0f2316c1), Next: 0}}, // First Napoli block }, }, // Amoy test cases diff --git a/params/chainspecs/mumbai.json b/params/chainspecs/mumbai.json index 3a61eb1acd1..0222a381bfb 100644 --- a/params/chainspecs/mumbai.json +++ b/params/chainspecs/mumbai.json @@ -58,6 +58,7 @@ "jaipurBlock": 22770000, "delhiBlock": 29638656, "indoreBlock": 37075456, - "agraBlock": 41874000 + "agraBlock": 41874000, + "napoliBlock": 45648608 } } diff --git a/params/version.go b/params/version.go index 6d1ca420d22..368bfc842dd 100644 --- a/params/version.go +++ b/params/version.go @@ -33,7 +33,7 @@ var ( const ( VersionMajor = 2 // Major version component of the current release VersionMinor = 57 // Minor version component of the current release - VersionMicro = 2 // Patch version component of the current release + VersionMicro = 3 // Patch version component of the current release VersionModifier = "" // Modifier component of the current release VersionKeyCreated = "ErigonVersionCreated" VersionKeyFinished = "ErigonVersionFinished" From 5b026e70104d00c7980feddbacf0610328d15b0f Mon Sep 17 00:00:00 2001 From: Tei Im Date: Wed, 17 Apr 2024 10:45:05 -0600 Subject: [PATCH 87/92] erigon-interfaces update --- erigon-lib/go.mod | 4 +-- erigon-lib/go.sum | 74 ++++++++++++++++++++++++++++++++++++++++++++++- go.sum | 52 +++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+), 3 deletions(-) diff --git a/erigon-lib/go.mod b/erigon-lib/go.mod index e56376e5ea4..3b70b38405f 100644 --- a/erigon-lib/go.mod +++ b/erigon-lib/go.mod @@ -2,10 +2,10 @@ module github.com/ledgerwatch/erigon-lib go 1.20 -replace github.com/ledgerwatch/interfaces v0.0.0-20231209102305-b17e86fbe07d => github.com/testinprod-io/erigon-interfaces v0.0.0-20240405014735-94dc72a592c4 +replace github.com/ledgerwatch/interfaces v0.0.0-20240105174738-fe57049f198c => github.com/testinprod-io/erigon-interfaces v0.0.0-20240417162243-646e6c71bb81 //for local dev: -//replace github.com/ledgerwatch/interfaces v0.0.0-20231209102305-b17e86fbe07d => ../erigon-interfaces +//replace github.com/ledgerwatch/interfaces v0.0.0-20240105174738-fe57049f198c => ../erigon-interfaces require ( github.com/erigontech/mdbx-go v0.27.21 diff --git a/erigon-lib/go.sum b/erigon-lib/go.sum index 606a3bc287a..e764c27c388 100644 --- a/erigon-lib/go.sum +++ b/erigon-lib/go.sum @@ -293,16 +293,23 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= +github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240115083615-b5feeb63e191 h1:X/mHEyh0xEuhixj6hKCNQl04NuNDToYWJ08vr66e6L0= github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240115083615-b5feeb63e191/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo= -github.com/ledgerwatch/interfaces v0.0.0-20240105174738-fe57049f198c/go.mod h1:ugQv1QllJzBny3cKZKxUrSnykkjkBgm27eQM6dnGAcc= +github.com/ledgerwatch/log/v3 v3.9.0 h1:iDwrXe0PVwBC68Dd94YSsHbMgQ3ufsgjzXtFNFVZFRk= github.com/ledgerwatch/log/v3 v3.9.0/go.mod h1:EiAY6upmI/6LkNhOVxb4eVsmsP11HZCnZ3PlJMjYiqE= +github.com/ledgerwatch/secp256k1 v1.0.0 h1:Usvz87YoTG0uePIV8woOof5cQnLXGYa162rFf3YnwaQ= github.com/ledgerwatch/secp256k1 v1.0.0/go.mod h1:SPmqJFciiF/Q0mPt2jVs2dTr/1TZBTIA+kPMmKgBAak= +github.com/matryer/moq v0.3.3 h1:pScMH9VyrdT4S93yiLpVyU8rCDqGQr24uOyBxmktG5Q= github.com/matryer/moq v0.3.3/go.mod h1:RJ75ZZZD71hejp39j4crZLsEDszGk6iH4v4YsWFKH4s= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= +github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -310,6 +317,7 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= +github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -323,79 +331,113 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pion/datachannel v1.5.2 h1:piB93s8LGmbECrpO84DnkIVWasRMk3IimbcXkTQLE6E= github.com/pion/datachannel v1.5.2/go.mod h1:FTGQWaHrdCwIJ1rw6xBIfZVkslikjShim5yr05XFuCQ= github.com/pion/dtls/v2 v2.1.3/go.mod h1:o6+WvyLDAlXF7YiPB/RlskRoeK+/JtuaZa5emwQcWus= github.com/pion/dtls/v2 v2.1.5/go.mod h1:BqCE7xPZbPSubGasRoDFJeTsyJtdD1FanJYL0JGheqY= +github.com/pion/dtls/v2 v2.2.4 h1:YSfYwDQgrxMYXLBc/m7PFY5BVtWlNm/DN4qoU2CbcWg= github.com/pion/dtls/v2 v2.2.4/go.mod h1:WGKfxqhrddne4Kg3p11FUMJrynkOY4lb25zHNO49wuw= +github.com/pion/ice/v2 v2.2.6 h1:R/vaLlI1J2gCx141L5PEwtuGAGcyS6e7E0hDeJFq5Ig= github.com/pion/ice/v2 v2.2.6/go.mod h1:SWuHiOGP17lGromHTFadUe1EuPgFh/oCU6FCMZHooVE= +github.com/pion/interceptor v0.1.11 h1:00U6OlqxA3FFB50HSg25J/8cWi7P6FbSzw4eFn24Bvs= github.com/pion/interceptor v0.1.11/go.mod h1:tbtKjZY14awXd7Bq0mmWvgtHB5MDaRN7HV3OZ/uy7s8= +github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= +github.com/pion/mdns v0.0.5 h1:Q2oj/JB3NqfzY9xGZ1fPzZzK7sDSD8rZPOvcIQ10BCw= github.com/pion/mdns v0.0.5/go.mod h1:UgssrvdD3mxpi8tMxAXbsppL3vJ4Jipw1mTCW+al01g= +github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= +github.com/pion/rtcp v1.2.9 h1:1ujStwg++IOLIEoOiIQ2s+qBuJ1VN81KW+9pMPsif+U= github.com/pion/rtcp v1.2.9/go.mod h1:qVPhiCzAm4D/rxb6XzKeyZiQK69yJpbUDJSF7TgrqNo= +github.com/pion/rtp v1.7.13 h1:qcHwlmtiI50t1XivvoawdCGTP4Uiypzfrsap+bijcoA= github.com/pion/rtp v1.7.13/go.mod h1:bDb5n+BFZxXx0Ea7E5qe+klMuqiBrP+w8XSjiWtCUko= github.com/pion/sctp v1.8.0/go.mod h1:xFe9cLMZ5Vj6eOzpyiKjT9SwGM4KpK/8Jbw5//jc+0s= +github.com/pion/sctp v1.8.2 h1:yBBCIrUMJ4yFICL3RIvR4eh/H2BTTvlligmSTy+3kiA= github.com/pion/sctp v1.8.2/go.mod h1:xFe9cLMZ5Vj6eOzpyiKjT9SwGM4KpK/8Jbw5//jc+0s= +github.com/pion/sdp/v3 v3.0.5 h1:ouvI7IgGl+V4CrqskVtr3AaTrPvPisEOxwgpdktctkU= github.com/pion/sdp/v3 v3.0.5/go.mod h1:iiFWFpQO8Fy3S5ldclBkpXqmWy02ns78NOKoLLL0YQw= +github.com/pion/srtp/v2 v2.0.9 h1:JJq3jClmDFBPX/F5roEb0U19jSU7eUhyDqR/NZ34EKQ= github.com/pion/srtp/v2 v2.0.9/go.mod h1:5TtM9yw6lsH0ppNCehB/EjEUli7VkUgKSPJqWVqbhQ4= +github.com/pion/stun v0.3.5 h1:uLUCBCkQby4S1cf6CGuR9QrVOKcvUwFeemaC865QHDg= github.com/pion/stun v0.3.5/go.mod h1:gDMim+47EeEtfWogA37n6qXZS88L5V6LqFcf+DZA2UA= github.com/pion/transport v0.12.2/go.mod h1:N3+vZQD9HlDP5GWkZ85LohxNsDcNgofQmyL6ojX5d8Q= github.com/pion/transport v0.12.3/go.mod h1:OViWW9SP2peE/HbwBvARicmAVnesphkNkCVZIWJ6q9A= github.com/pion/transport v0.13.0/go.mod h1:yxm9uXpK9bpBBWkITk13cLo1y5/ur5VQpG22ny6EP7g= +github.com/pion/transport v0.13.1 h1:/UH5yLeQtwm2VZIPjxwnNFxjS4DFhyLfS4GlfuKUzfA= github.com/pion/transport v0.13.1/go.mod h1:EBxbqzyv+ZrmDb82XswEE0BjfQFtuw1Nu6sjnjWCsGg= +github.com/pion/transport/v2 v2.0.0 h1:bsMYyqHCbkvHwj+eNCFBuxtlKndKfyGI2vaQmM3fIE4= github.com/pion/transport/v2 v2.0.0/go.mod h1:HS2MEBJTwD+1ZI2eSXSvHJx/HnzQqRy2/LXxt6eVMHc= +github.com/pion/turn/v2 v2.0.8 h1:KEstL92OUN3k5k8qxsXHpr7WWfrdp7iJZHx99ud8muw= github.com/pion/turn/v2 v2.0.8/go.mod h1:+y7xl719J8bAEVpSXBXvTxStjJv3hbz9YFflvkpcGPw= github.com/pion/udp v0.1.1/go.mod h1:6AFo+CMdKQm7UiA0eUPA8/eVCTx8jBIITLZHc9DWX5M= +github.com/pion/udp v0.1.4 h1:OowsTmu1Od3sD6i3fQUJxJn2fEvJO6L1TidgadtbTI8= github.com/pion/udp v0.1.4/go.mod h1:G8LDo56HsFwC24LIcnT4YIDU5qcB6NepqqjP0keL2us= +github.com/pion/webrtc/v3 v3.1.42 h1:wJEQFIXVanptnQcHOLTuIo4AtGB2+mG2x4OhIhnITOA= github.com/pion/webrtc/v3 v3.1.42/go.mod h1:ffD9DulDrPxyWvDPUIPAOSAWx9GUlOExiJPf7cCcMLA= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417 h1:Lt9DzQALzHoDwMBGJ6v8ObDPR0dzr2a6sXTB1Fq7IHs= github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417/go.mod h1:qe5TWALJ8/a1Lqznoc5BDHpYX/8HU60Hm2AwRmqzxqA= +github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46 h1:GHRpF1pTW19a8tTFrMLUcfWwyC0pnifVo2ClaLq+hP8= github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5PCi+MFsC7HjREoAz1BU+Mq60+05gifQSsHSDG/8= github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20190215210624-980c5ac6f3ac/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= github.com/smartystreets/goconvey v0.0.0-20190306220146-200a235640ff/go.mod h1:KSQcGKpxUMHk3nbYzs/tIBAM2iDooCn0BmttHOJEbLs= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -411,7 +453,11 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/testinprod-io/erigon-interfaces v0.0.0-20240417162243-646e6c71bb81 h1:fXwFSDzZaHRYXlz/rhwqXwPAaCLO+agOoKBpu2kmal8= +github.com/testinprod-io/erigon-interfaces v0.0.0-20240417162243-646e6c71bb81/go.mod h1:ugQv1QllJzBny3cKZKxUrSnykkjkBgm27eQM6dnGAcc= +github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg= github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY= github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= @@ -422,14 +468,18 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opentelemetry.io/otel v1.8.0 h1:zcvBFizPbpa1q7FehvFiHbQwGzmPILebO0tyqIR5Djg= go.opentelemetry.io/otel v1.8.0/go.mod h1:2pkj+iMj0o03Y+cW6/m8Y4WkRdYN3AvCXCnzRMp9yvM= +go.opentelemetry.io/otel/trace v1.8.0 h1:cSy0DF9eGI5WIfNwZ1q2iUyGj00tGzP24dE1lOlHrfY= go.opentelemetry.io/otel/trace v1.8.0/go.mod h1:0Bt3PXY8w+3pheS3hQUt+wow8b1ojPaTBoTCh2zIFI4= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -441,8 +491,10 @@ golang.org/x/crypto v0.0.0-20220131195533-30dcbda58838/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220516162934-403b01795ae8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -453,6 +505,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -483,6 +536,7 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -495,6 +549,7 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -533,6 +588,7 @@ golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -547,7 +603,9 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -563,6 +621,7 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -576,6 +635,7 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0= google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -584,7 +644,9 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -594,11 +656,13 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= @@ -608,16 +672,24 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +modernc.org/libc v1.24.1 h1:uvJSeCKL/AgzBo2yYIPPTy82v21KgGnizcGYfBHaNuM= modernc.org/libc v1.24.1/go.mod h1:FmfO1RLrU3MHJfyi9eYYmZBfi/R+tqZ6+hQ3yQQUkak= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.6.0 h1:i6mzavxrE9a30whzMfwf7XWVODx2r5OYXvU46cirX7o= modernc.org/memory v1.6.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= +modernc.org/sqlite v1.26.0 h1:SocQdLRSYlA8W99V8YH0NES75thx19d9sB/aFc4R8Lw= modernc.org/sqlite v1.26.0/go.mod h1:FL3pVXie73rg3Rii6V/u5BoHlSoyeZeIgKZEgHARyCU= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= +zombiezen.com/go/sqlite v0.13.1 h1:qDzxyWWmMtSSEH5qxamqBFmqA2BLSSbtODi3ojaE02o= zombiezen.com/go/sqlite v0.13.1/go.mod h1:Ht/5Rg3Ae2hoyh1I7gbWtWAl89CNocfqeb/aAMTkJr4= diff --git a/go.sum b/go.sum index b46be3fdecd..74de75cadf6 100644 --- a/go.sum +++ b/go.sum @@ -46,6 +46,7 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= +filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= gfx.cafe/util/go/generic v0.0.0-20230721185457-c559e86c829c h1:alCfDKmPC0EC0KGlZWrNF0hilVWBkzMz+aAYTJ/2hY4= gfx.cafe/util/go/generic v0.0.0-20230721185457-c559e86c829c/go.mod h1:WvSX4JsCRBuIXj0FRBFX9YLg+2SoL3w8Ww19uZO9yNE= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= @@ -75,11 +76,13 @@ github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVb github.com/ajwerner/btree v0.0.0-20211221152037-f427b3e689c0 h1:byYvvbfSo3+9efR4IeReh77gVs4PnNDR3AMOE9NJ7a0= github.com/ajwerner/btree v0.0.0-20211221152037-f427b3e689c0/go.mod h1:q37NoqncT41qKc048STsifIt69LfUJ8SrWWcz/yam5k= github.com/alecthomas/assert/v2 v2.1.0 h1:tbredtNcQnoSd3QBhQWI7QZ3XHOVkw1Moklp2ojoH/0= +github.com/alecthomas/assert/v2 v2.1.0/go.mod h1:b/+1DI2Q6NckYi+3mXyH3wFb8qG37K/DuK80n7WefXA= github.com/alecthomas/atomic v0.1.0-alpha2 h1:dqwXmax66gXvHhsOS4pGPZKqYOlTkapELkLb3MNdlH8= github.com/alecthomas/atomic v0.1.0-alpha2/go.mod h1:zD6QGEyw49HIq19caJDc2NMXAy8rNi9ROrxtMXATfyI= github.com/alecthomas/kong v0.8.0 h1:ryDCzutfIqJPnNn0omnrgHLbAggDQM2VWHikE1xqK7s= github.com/alecthomas/kong v0.8.0/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U= github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE= +github.com/alecthomas/repr v0.1.0/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -142,6 +145,7 @@ github.com/anacrolix/upnp v0.1.3-0.20220123035249-922794e51c96/go.mod h1:Wa6n8cY github.com/anacrolix/utp v0.1.0 h1:FOpQOmIwYsnENnz7tAGohA+r6iXpRjrq8ssKSre2Cp4= github.com/anacrolix/utp v0.1.0/go.mod h1:MDwc+vsGEq7RMw6lr2GKOEqjWny5hO5OZXRVNaBJ2Dk= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= @@ -260,6 +264,7 @@ github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS3 github.com/deckarep/golang-set/v2 v2.3.1 h1:vjmkvJt/IV27WXPyYQpAh4bRyWJc5Y435D17XQ9QU5A= github.com/deckarep/golang-set/v2 v2.3.1/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g= @@ -310,6 +315,7 @@ github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJn github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/frankban/quicktest v1.9.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= @@ -485,6 +491,7 @@ github.com/hashicorp/golang-lru/arc/v2 v2.0.6/go.mod h1:cfdDIX05DWvYV6/shsxDfa/O github.com/hashicorp/golang-lru/v2 v2.0.6 h1:3xi/Cafd1NaoEnS/yDssIiuVeDVywU0QdFGl3aQaQHM= github.com/hashicorp/golang-lru/v2 v2.0.6/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= +github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o= github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= @@ -559,6 +566,7 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758 h1:0D5M2HQSGD3PYPwICLl+/9oulQauOuETfgFvhBDffs0= +github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240115083615-b5feeb63e191 h1:X/mHEyh0xEuhixj6hKCNQl04NuNDToYWJ08vr66e6L0= @@ -582,6 +590,7 @@ github.com/libp2p/go-libp2p-mplex v0.9.0/go.mod h1:ro1i4kuwiFT+uMPbIDIFkcLs1KRbN github.com/libp2p/go-libp2p-pubsub v0.9.3 h1:ihcz9oIBMaCK9kcx+yHWm3mLAFBMAUsM4ux42aikDxo= github.com/libp2p/go-libp2p-pubsub v0.9.3/go.mod h1:RYA7aM9jIic5VV47WXu4GkcRxRhrdElWf8xtyli+Dzc= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= +github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= github.com/libp2p/go-mplex v0.7.0 h1:BDhFZdlk5tbr0oyFq/xv/NPGfjbnrsDam1EvutpBDbY= github.com/libp2p/go-mplex v0.7.0/go.mod h1:rW8ThnRcYWft/Jb2jeORBmPd6xuG3dGxWN/W168L9EU= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= @@ -609,6 +618,7 @@ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= @@ -692,6 +702,7 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc= +github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg= github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= @@ -827,6 +838,7 @@ github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5P github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= @@ -947,6 +959,7 @@ go.opentelemetry.io/otel/trace v1.8.0 h1:cSy0DF9eGI5WIfNwZ1q2iUyGj00tGzP24dE1lOl go.opentelemetry.io/otel/trace v1.8.0/go.mod h1:0Bt3PXY8w+3pheS3hQUt+wow8b1ojPaTBoTCh2zIFI4= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= +go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/dig v1.17.0 h1:5Chju+tUvcC+N7N6EV08BJz41UZuO3BmHcN4A287ZLI= go.uber.org/dig v1.17.0/go.mod h1:rTxpf7l5I0eBTlE6/9RL+lDybC7WFwY2QH55ZSjy1mU= go.uber.org/fx v1.20.0 h1:ZMC/pnRvhsthOZh9MZjMq5U8Or3mA9zBSPaLnzs3ihQ= @@ -954,6 +967,7 @@ go.uber.org/fx v1.20.0/go.mod h1:qCUj0btiR3/JnanEr1TYEePfSw6o/4qYJscgvzQ5Ub0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= +go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -1186,6 +1200,7 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1205,11 +1220,13 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1269,6 +1286,7 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1347,7 +1365,9 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU= google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97/go.mod h1:iargEX0SFPm3xcfMI0d1domjg0ZF4Aa0p2awqyxhvF0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0= google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= @@ -1368,7 +1388,9 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0/go.mod h1:Dk1tviKTvMCz5tvh7t+fh94dhmQVHuCt2OzJB3CTW9Y= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -1382,17 +1404,22 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y= gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UDAkHu8BrjI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1400,9 +1427,11 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1413,23 +1442,46 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI= lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= +lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo= lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.41.0 h1:QoR1Sn3YWlmA1T4vLaKZfawdVtSiGx8H+cEojbC7v1Q= modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y= +modernc.org/ccgo/v3 v3.16.15 h1:KbDR3ZAVU+wiLyMESPtbtE/Add4elztFyfsWoNTgxS0= modernc.org/ccgo/v3 v3.16.15/go.mod h1:yT7B+/E2m43tmMOT51GMoM98/MtHIcQQSleGnddkUNI= +modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= +modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/libc v1.29.0 h1:tTFRFq69YKCF2QyGNuRUQxKBm1uZZLubf6Cjh/pVHXs= modernc.org/libc v1.29.0/go.mod h1:DaG/4Q3LRRdqpiLyP0C2m1B8ZMGkQ+cCgOIjEtQlYhQ= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= +modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.28.0 h1:Zx+LyDDmXczNnEQdvPuEfcFVA2ZPyaD7UCZDjef3BHQ= modernc.org/sqlite v1.28.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0= +modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= +modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY= +modernc.org/tcl v1.15.2/go.mod h1:3+k/ZaEbKrC8ePv8zJWPtBSW0V7Gg9g8rkmhI1Kfs3c= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY= +modernc.org/z v1.7.3/go.mod h1:Ipv4tsdxZRbQyLq9Q1M6gdbkxYzdlrciF2Hi/lS7nWE= +pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= +zombiezen.com/go/sqlite v0.13.1 h1:qDzxyWWmMtSSEH5qxamqBFmqA2BLSSbtODi3ojaE02o= zombiezen.com/go/sqlite v0.13.1/go.mod h1:Ht/5Rg3Ae2hoyh1I7gbWtWAl89CNocfqeb/aAMTkJr4= From 84c5e7501b9cb424a1fe6defcde04c9141fa85b0 Mon Sep 17 00:00:00 2001 From: Tei Im Date: Wed, 17 Apr 2024 10:50:26 -0600 Subject: [PATCH 88/92] Revert go version --- go.mod | 4 +--- go.sum | 18 ------------------ 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/go.mod b/go.mod index ff93993c0e4..5b0991798dc 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,6 @@ module github.com/ledgerwatch/erigon -go 1.21 - -toolchain go1.21.0 +go 1.20 require ( github.com/erigontech/mdbx-go v0.27.21 diff --git a/go.sum b/go.sum index 74de75cadf6..1f2de97d526 100644 --- a/go.sum +++ b/go.sum @@ -46,7 +46,6 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= -filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns= gfx.cafe/util/go/generic v0.0.0-20230721185457-c559e86c829c h1:alCfDKmPC0EC0KGlZWrNF0hilVWBkzMz+aAYTJ/2hY4= gfx.cafe/util/go/generic v0.0.0-20230721185457-c559e86c829c/go.mod h1:WvSX4JsCRBuIXj0FRBFX9YLg+2SoL3w8Ww19uZO9yNE= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= @@ -76,13 +75,11 @@ github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVb github.com/ajwerner/btree v0.0.0-20211221152037-f427b3e689c0 h1:byYvvbfSo3+9efR4IeReh77gVs4PnNDR3AMOE9NJ7a0= github.com/ajwerner/btree v0.0.0-20211221152037-f427b3e689c0/go.mod h1:q37NoqncT41qKc048STsifIt69LfUJ8SrWWcz/yam5k= github.com/alecthomas/assert/v2 v2.1.0 h1:tbredtNcQnoSd3QBhQWI7QZ3XHOVkw1Moklp2ojoH/0= -github.com/alecthomas/assert/v2 v2.1.0/go.mod h1:b/+1DI2Q6NckYi+3mXyH3wFb8qG37K/DuK80n7WefXA= github.com/alecthomas/atomic v0.1.0-alpha2 h1:dqwXmax66gXvHhsOS4pGPZKqYOlTkapELkLb3MNdlH8= github.com/alecthomas/atomic v0.1.0-alpha2/go.mod h1:zD6QGEyw49HIq19caJDc2NMXAy8rNi9ROrxtMXATfyI= github.com/alecthomas/kong v0.8.0 h1:ryDCzutfIqJPnNn0omnrgHLbAggDQM2VWHikE1xqK7s= github.com/alecthomas/kong v0.8.0/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U= github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE= -github.com/alecthomas/repr v0.1.0/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -145,7 +142,6 @@ github.com/anacrolix/upnp v0.1.3-0.20220123035249-922794e51c96/go.mod h1:Wa6n8cY github.com/anacrolix/utp v0.1.0 h1:FOpQOmIwYsnENnz7tAGohA+r6iXpRjrq8ssKSre2Cp4= github.com/anacrolix/utp v0.1.0/go.mod h1:MDwc+vsGEq7RMw6lr2GKOEqjWny5hO5OZXRVNaBJ2Dk= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ= -github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= @@ -264,7 +260,6 @@ github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS3 github.com/deckarep/golang-set/v2 v2.3.1 h1:vjmkvJt/IV27WXPyYQpAh4bRyWJc5Y435D17XQ9QU5A= github.com/deckarep/golang-set/v2 v2.3.1/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= -github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48 h1:fRzb/w+pyskVMQ+UbP35JkH8yB7MYb4q/qhBarqZE6g= @@ -315,7 +310,6 @@ github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJn github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/frankban/quicktest v1.9.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= -github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= @@ -491,7 +485,6 @@ github.com/hashicorp/golang-lru/arc/v2 v2.0.6/go.mod h1:cfdDIX05DWvYV6/shsxDfa/O github.com/hashicorp/golang-lru/v2 v2.0.6 h1:3xi/Cafd1NaoEnS/yDssIiuVeDVywU0QdFGl3aQaQHM= github.com/hashicorp/golang-lru/v2 v2.0.6/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= -github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= github.com/holiman/uint256 v1.2.3 h1:K8UWO1HUJpRMXBxbmaY1Y8IAMZC/RsKB+ArEnnK4l5o= github.com/holiman/uint256 v1.2.3/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= @@ -566,7 +559,6 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758 h1:0D5M2HQSGD3PYPwICLl+/9oulQauOuETfgFvhBDffs0= -github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20240115083615-b5feeb63e191 h1:X/mHEyh0xEuhixj6hKCNQl04NuNDToYWJ08vr66e6L0= @@ -590,7 +582,6 @@ github.com/libp2p/go-libp2p-mplex v0.9.0/go.mod h1:ro1i4kuwiFT+uMPbIDIFkcLs1KRbN github.com/libp2p/go-libp2p-pubsub v0.9.3 h1:ihcz9oIBMaCK9kcx+yHWm3mLAFBMAUsM4ux42aikDxo= github.com/libp2p/go-libp2p-pubsub v0.9.3/go.mod h1:RYA7aM9jIic5VV47WXu4GkcRxRhrdElWf8xtyli+Dzc= github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA= -github.com/libp2p/go-libp2p-testing v0.12.0/go.mod h1:KcGDRXyN7sQCllucn1cOOS+Dmm7ujhfEyXQL5lvkcPg= github.com/libp2p/go-mplex v0.7.0 h1:BDhFZdlk5tbr0oyFq/xv/NPGfjbnrsDam1EvutpBDbY= github.com/libp2p/go-mplex v0.7.0/go.mod h1:rW8ThnRcYWft/Jb2jeORBmPd6xuG3dGxWN/W168L9EU= github.com/libp2p/go-msgio v0.3.0 h1:mf3Z8B1xcFN314sWX+2vOTShIE0Mmn2TXn3YCUQGNj0= @@ -618,7 +609,6 @@ github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= -github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= @@ -702,7 +692,6 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc= -github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg= github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= @@ -838,7 +827,6 @@ github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5P github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= -github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= @@ -959,7 +947,6 @@ go.opentelemetry.io/otel/trace v1.8.0 h1:cSy0DF9eGI5WIfNwZ1q2iUyGj00tGzP24dE1lOl go.opentelemetry.io/otel/trace v1.8.0/go.mod h1:0Bt3PXY8w+3pheS3hQUt+wow8b1ojPaTBoTCh2zIFI4= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= -go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/dig v1.17.0 h1:5Chju+tUvcC+N7N6EV08BJz41UZuO3BmHcN4A287ZLI= go.uber.org/dig v1.17.0/go.mod h1:rTxpf7l5I0eBTlE6/9RL+lDybC7WFwY2QH55ZSjy1mU= go.uber.org/fx v1.20.0 h1:ZMC/pnRvhsthOZh9MZjMq5U8Or3mA9zBSPaLnzs3ihQ= @@ -967,7 +954,6 @@ go.uber.org/fx v1.20.0/go.mod h1:qCUj0btiR3/JnanEr1TYEePfSw6o/4qYJscgvzQ5Ub0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= -go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= @@ -1451,9 +1437,7 @@ modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y= modernc.org/ccgo/v3 v3.16.15 h1:KbDR3ZAVU+wiLyMESPtbtE/Add4elztFyfsWoNTgxS0= modernc.org/ccgo/v3 v3.16.15/go.mod h1:yT7B+/E2m43tmMOT51GMoM98/MtHIcQQSleGnddkUNI= modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= -modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= -modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= modernc.org/libc v1.29.0 h1:tTFRFq69YKCF2QyGNuRUQxKBm1uZZLubf6Cjh/pVHXs= modernc.org/libc v1.29.0/go.mod h1:DaG/4Q3LRRdqpiLyP0C2m1B8ZMGkQ+cCgOIjEtQlYhQ= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= @@ -1467,11 +1451,9 @@ modernc.org/sqlite v1.28.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0 modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY= -modernc.org/tcl v1.15.2/go.mod h1:3+k/ZaEbKrC8ePv8zJWPtBSW0V7Gg9g8rkmhI1Kfs3c= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY= -modernc.org/z v1.7.3/go.mod h1:Ipv4tsdxZRbQyLq9Q1M6gdbkxYzdlrciF2Hi/lS7nWE= pgregory.net/rapid v1.1.0 h1:CMa0sjHSru3puNx+J0MIAuiiEV4N0qj8/cMWGBBCsjw= pgregory.net/rapid v1.1.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= From 0476024af6aadf19ca1a10c30f069061584041c7 Mon Sep 17 00:00:00 2001 From: Tei Im Date: Wed, 17 Apr 2024 10:55:27 -0600 Subject: [PATCH 89/92] Fix build errors --- consensus/misc/eip1559.go | 4 +++- erigon-lib/txpool/pool.go | 4 ++-- eth/stagedsync/stagebuilder.go | 16 +++++++++------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/consensus/misc/eip1559.go b/consensus/misc/eip1559.go index 6de0c2d98c8..f9c6914ddb2 100644 --- a/consensus/misc/eip1559.go +++ b/consensus/misc/eip1559.go @@ -80,7 +80,9 @@ func (f eip1559Calculator) CurrentFees(chainConfig *chain.Config, db kv.Getter) if chainConfig != nil { if currentHeader.BaseFee != nil { - baseFee = CalcBaseFee(chainConfig, currentHeader).Uint64() + // Block time of every OP superchains is 2sec for now. + // Add 2 for next block. TODO: support custom block time for OP chain + baseFee = CalcBaseFee(chainConfig, currentHeader, currentHeader.Time+2).Uint64() } if currentHeader.ExcessBlobGas != nil { diff --git a/erigon-lib/txpool/pool.go b/erigon-lib/txpool/pool.go index 42528794748..7f45751efa2 100644 --- a/erigon-lib/txpool/pool.go +++ b/erigon-lib/txpool/pool.go @@ -1668,8 +1668,8 @@ func (p *TxPool) onSenderStateChange(senderID uint64, senderNonce uint64, sender needBalance := requiredBalance(mt.Tx) - if l1CostFn != nil { - if l1Cost := l1CostFn(mt.Tx); l1Cost != nil { + if p.l1Cost != nil { + if l1Cost := p.l1Cost(mt.Tx); l1Cost != nil { needBalance.Add(needBalance, l1Cost) } } diff --git a/eth/stagedsync/stagebuilder.go b/eth/stagedsync/stagebuilder.go index 4a370f49eee..20b57686304 100644 --- a/eth/stagedsync/stagebuilder.go +++ b/eth/stagedsync/stagebuilder.go @@ -32,11 +32,13 @@ func MiningStages( { ID: stages.MiningCreateBlock, Description: "Mining: add force-txs", - Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, tx kv.RwTx, logger log.Logger) error { - return SpawnMiningForceTxsStage(s, tx, createBlockCfg, ctx.Done()) + Forward: func(firstCycle bool, badBlockUnwind bool, s *StageState, u Unwinder, txc wrap.TxContainer, logger log.Logger) error { + return SpawnMiningForceTxsStage(s, txc.Tx, createBlockCfg, ctx.Done()) }, - Unwind: func(firstCycle bool, u *UnwindState, s *StageState, tx kv.RwTx, logger log.Logger) error { return nil }, - Prune: func(firstCycle bool, u *PruneState, tx kv.RwTx, logger log.Logger) error { return nil }, + Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { + return nil + }, + Prune: func(firstCycle bool, u *PruneState, tx kv.RwTx, logger log.Logger) error { return nil }, }, { ID: stages.MiningCreateBlock, @@ -72,7 +74,7 @@ func MiningStages( return SpawnMiningExecStage(s, txc.Tx, execCfg, ctx.Done(), logger) }, Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { - return UnwindMiningExecutionStage(u, s, txc, ctx, execCfg, logger) + return UnwindMiningExecutionStage(u, s, txc.Tx, ctx, execCfg, logger) }, Prune: func(firstCycle bool, u *PruneState, tx kv.RwTx, logger log.Logger) error { return nil }, }, @@ -83,7 +85,7 @@ func MiningStages( return SpawnHashStateStage(s, txc.Tx, hashStateCfg, ctx, logger) }, Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { - return UnwindHashStateStage(u, s, txc, hashStateCfg, ctx, logger) + return UnwindHashStateStage(u, s, txc.Tx, hashStateCfg, ctx, logger) }, Prune: func(firstCycle bool, u *PruneState, tx kv.RwTx, logger log.Logger) error { return nil }, }, @@ -99,7 +101,7 @@ func MiningStages( return nil }, Unwind: func(firstCycle bool, u *UnwindState, s *StageState, txc wrap.TxContainer, logger log.Logger) error { - return UnwindIntermediateHashesStage(u, s, txc, trieCfg, ctx, logger) + return UnwindIntermediateHashesStage(u, s, txc.Tx, trieCfg, ctx, logger) }, Prune: func(firstCycle bool, u *PruneState, tx kv.RwTx, logger log.Logger) error { return nil }, }, From eb35055b0d45ef0127a73e81e665a5d2ea71491d Mon Sep 17 00:00:00 2001 From: Tei Im Date: Wed, 17 Apr 2024 11:09:00 -0600 Subject: [PATCH 90/92] Fix test build error --- erigon-lib/txpool/pool_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erigon-lib/txpool/pool_test.go b/erigon-lib/txpool/pool_test.go index a93c8176977..e30ecc51187 100644 --- a/erigon-lib/txpool/pool_test.go +++ b/erigon-lib/txpool/pool_test.go @@ -952,7 +952,7 @@ func TestDepositTxValidateTx(t *testing.T) { shanghaiTime := big.NewInt(0) cache := &kvcache.DummyCache{} - pool, err := New(ch, coreDB, cfg, cache, *u256.N1, shanghaiTime, nil, nil, 0, logger) + pool, err := New(ch, coreDB, cfg, cache, *u256.N1, shanghaiTime, big.NewInt(0), nil, fixedgas.DefaultMaxBlobsPerBlock, nil, logger) asrt.NoError(err) ctx := context.Background() tx, err := coreDB.BeginRw(ctx) From 48786205d0f845e30fc27ae54f857f1fb3a153e3 Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Wed, 31 Jan 2024 13:17:41 +0100 Subject: [PATCH 91/92] Updated sepolia fork digest in tests (#9352) --- cl/fork/fork_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cl/fork/fork_test.go b/cl/fork/fork_test.go index 568be1e4dc5..f20fc90c9ac 100644 --- a/cl/fork/fork_test.go +++ b/cl/fork/fork_test.go @@ -66,7 +66,7 @@ func TestSepoliaForkDigest(t *testing.T) { require.NoError(t, err) _, err = ComputeForkId(&beaconCfg, &genesisCfg) require.NoError(t, err) - require.Equal(t, [4]uint8{0x47, 0xeb, 0x72, 0xb3}, digest) + require.Equal(t, [4]uint8{0xd3, 0x1f, 0x61, 0x91}, digest) } // ForkDigestVersion From a383d0c3bd137b116bf1dbe2ed0887f7c68ffb5e Mon Sep 17 00:00:00 2001 From: Tei Im Date: Wed, 17 Apr 2024 11:35:58 -0600 Subject: [PATCH 92/92] Ignore gocritic lint --- eth/stagedsync/bor_heimdall_shared.go | 6 +++--- eth/stagedsync/default_stages.go | 2 +- eth/stagedsync/stage_bor_heimdall.go | 6 +++--- eth/stagedsync/stage_mining_bor_heimdall.go | 2 +- eth/stagedsync/stagebuilder.go | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/eth/stagedsync/bor_heimdall_shared.go b/eth/stagedsync/bor_heimdall_shared.go index cbb213f775c..a4ad936f103 100644 --- a/eth/stagedsync/bor_heimdall_shared.go +++ b/eth/stagedsync/bor_heimdall_shared.go @@ -116,7 +116,7 @@ func fetchRequiredHeimdallSpansIfNeeded( ctx context.Context, toBlockNum uint64, tx kv.RwTx, - cfg BorHeimdallCfg, + cfg BorHeimdallCfg, //nolint:gocritic logPrefix string, logger log.Logger, ) (uint64, error) { @@ -181,7 +181,7 @@ func fetchRequiredHeimdallStateSyncEventsIfNeeded( ctx context.Context, header *types.Header, tx kv.RwTx, - cfg BorHeimdallCfg, + cfg BorHeimdallCfg, //nolint:gocritic logPrefix string, logger log.Logger, lastStateSyncEventIDGetter func() (uint64, error), @@ -205,7 +205,7 @@ func fetchAndWriteHeimdallStateSyncEvents( header *types.Header, lastStateSyncEventID uint64, tx kv.RwTx, - cfg BorHeimdallCfg, + cfg BorHeimdallCfg, //nolint:gocritic logPrefix string, logger log.Logger, ) (uint64, int, time.Duration, error) { diff --git a/eth/stagedsync/default_stages.go b/eth/stagedsync/default_stages.go index e53627bb7c4..95d1077cf8e 100644 --- a/eth/stagedsync/default_stages.go +++ b/eth/stagedsync/default_stages.go @@ -15,7 +15,7 @@ import ( func DefaultStages(ctx context.Context, snapshots SnapshotsCfg, headers HeadersCfg, - borHeimdallCfg BorHeimdallCfg, + borHeimdallCfg BorHeimdallCfg, //nolint:gocritic blockHashCfg BlockHashesCfg, bodies BodiesCfg, senders SendersCfg, diff --git a/eth/stagedsync/stage_bor_heimdall.go b/eth/stagedsync/stage_bor_heimdall.go index 88199f74774..fd561e9d67a 100644 --- a/eth/stagedsync/stage_bor_heimdall.go +++ b/eth/stagedsync/stage_bor_heimdall.go @@ -97,7 +97,7 @@ func BorHeimdallForward( u Unwinder, ctx context.Context, tx kv.RwTx, - cfg BorHeimdallCfg, + cfg BorHeimdallCfg, //nolint:gocritic logger log.Logger, ) (err error) { processStart := time.Now() @@ -574,7 +574,7 @@ func checkBorHeaderExtraData(chr consensus.ChainHeaderReader, header *types.Head return nil } -func BorHeimdallUnwind(u *UnwindState, ctx context.Context, s *StageState, tx kv.RwTx, cfg BorHeimdallCfg) (err error) { +func BorHeimdallUnwind(u *UnwindState, ctx context.Context, s *StageState, tx kv.RwTx, cfg BorHeimdallCfg) (err error) { //nolint:gocritic if cfg.borConfig == nil { return } @@ -647,7 +647,7 @@ func BorHeimdallUnwind(u *UnwindState, ctx context.Context, s *StageState, tx kv return } -func BorHeimdallPrune(s *PruneState, ctx context.Context, tx kv.RwTx, cfg BorHeimdallCfg) (err error) { +func BorHeimdallPrune(s *PruneState, ctx context.Context, tx kv.RwTx, cfg BorHeimdallCfg) (err error) { //nolint:gocritic if cfg.borConfig == nil { return } diff --git a/eth/stagedsync/stage_mining_bor_heimdall.go b/eth/stagedsync/stage_mining_bor_heimdall.go index 4a5d21665d4..0b50919178d 100644 --- a/eth/stagedsync/stage_mining_bor_heimdall.go +++ b/eth/stagedsync/stage_mining_bor_heimdall.go @@ -15,7 +15,7 @@ import ( func MiningBorHeimdallForward( ctx context.Context, - cfg BorHeimdallCfg, + cfg BorHeimdallCfg, //nolint:gocritic stageStage *StageState, unwinder Unwinder, tx kv.RwTx, diff --git a/eth/stagedsync/stagebuilder.go b/eth/stagedsync/stagebuilder.go index 20b57686304..ca2258d0775 100644 --- a/eth/stagedsync/stagebuilder.go +++ b/eth/stagedsync/stagebuilder.go @@ -22,7 +22,7 @@ type ChainEventNotifier interface { func MiningStages( ctx context.Context, createBlockCfg MiningCreateBlockCfg, - borHeimdallCfg BorHeimdallCfg, + borHeimdallCfg BorHeimdallCfg, //nolint:gocritic execCfg MiningExecCfg, hashStateCfg HashStateCfg, trieCfg TrieCfg,