diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 3d3994b57b..905fe70825 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -119,7 +119,7 @@ func NewSimulatedBackendChain(database ethdb.Database, blockchain *core.BlockCha filterBackend := &filterBackend{database, blockchain, backend} backend.filterSystem = filters.NewFilterSystem(filterBackend, filters.Config{}) backend.events = filters.NewEventSystem(backend.filterSystem, false) - + header := backend.blockchain.CurrentBlock() block := backend.blockchain.GetBlock(header.Hash(), header.Number.Uint64()) diff --git a/builder/beacon_client.go b/builder/beacon_client.go index bb97ebfa6c..f3122e2758 100644 --- a/builder/beacon_client.go +++ b/builder/beacon_client.go @@ -1,6 +1,7 @@ package builder import ( + "context" "encoding/json" "errors" "fmt" @@ -10,11 +11,23 @@ import ( "sync" "time" + "github.com/attestantio/go-eth2-client/spec/capella" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" + "github.com/r3labs/sse" + "golang.org/x/exp/slices" ) +type IBeaconClient interface { + isValidator(pubkey PubkeyHex) bool + getProposerForNextSlot(requestedSlot uint64) (PubkeyHex, error) + SubscribeToPayloadAttributesEvents(payloadAttrC chan types.BuilderPayloadAttributes) + Start() error + Stop() +} + type testBeaconClient struct { validator *ValidatorPrivateData slot uint64 @@ -30,8 +43,110 @@ func (b *testBeaconClient) isValidator(pubkey PubkeyHex) bool { func (b *testBeaconClient) getProposerForNextSlot(requestedSlot uint64) (PubkeyHex, error) { return PubkeyHex(hexutil.Encode(b.validator.Pk)), nil } -func (b *testBeaconClient) Start() error { - return nil + +func (b *testBeaconClient) SubscribeToPayloadAttributesEvents(payloadAttrC chan types.BuilderPayloadAttributes) { +} + +func (b *testBeaconClient) Start() error { return nil } + +type NilBeaconClient struct{} + +func (b *NilBeaconClient) isValidator(pubkey PubkeyHex) bool { + return false +} + +func (b *NilBeaconClient) getProposerForNextSlot(requestedSlot uint64) (PubkeyHex, error) { + return PubkeyHex(""), nil +} + +func (b *NilBeaconClient) SubscribeToPayloadAttributesEvents(payloadAttrC chan types.BuilderPayloadAttributes) { +} + +func (b *NilBeaconClient) Start() error { return nil } + +func (b *NilBeaconClient) Stop() {} + +type MultiBeaconClient struct { + clients []*BeaconClient + closeCh chan struct{} +} + +func NewMultiBeaconClient(endpoints []string, slotsInEpoch uint64, secondsInSlot uint64) *MultiBeaconClient { + clients := []*BeaconClient{} + for _, endpoint := range endpoints { + client := NewBeaconClient(endpoint, slotsInEpoch, secondsInSlot) + clients = append(clients, client) + } + + return &MultiBeaconClient{ + clients: clients, + closeCh: make(chan struct{}), + } +} + +func (m *MultiBeaconClient) isValidator(pubkey PubkeyHex) bool { + for _, c := range m.clients { + // Pick the first one, always true + return c.isValidator(pubkey) + } + + return false +} + +func (m *MultiBeaconClient) getProposerForNextSlot(requestedSlot uint64) (PubkeyHex, error) { + var allErrs error + for _, c := range m.clients { + pk, err := c.getProposerForNextSlot(requestedSlot) + if err != nil { + allErrs = errors.Join(allErrs, err) + continue + } + + return pk, nil + } + return PubkeyHex(""), allErrs +} + +func payloadAttributesMatch(l types.BuilderPayloadAttributes, r types.BuilderPayloadAttributes) bool { + if l.Timestamp != r.Timestamp || + l.Random != r.Random || + l.SuggestedFeeRecipient != r.SuggestedFeeRecipient || + l.Slot != r.Slot || + l.HeadHash != r.HeadHash || + l.GasLimit != r.GasLimit { + return false + } + + if !slices.Equal(l.Withdrawals, r.Withdrawals) { + return false + } + + return true +} + +func (m *MultiBeaconClient) SubscribeToPayloadAttributesEvents(payloadAttrC chan types.BuilderPayloadAttributes) { + for _, c := range m.clients { + go c.SubscribeToPayloadAttributesEvents(payloadAttrC) + } +} + +func (m *MultiBeaconClient) Start() error { + var allErrs error + for _, c := range m.clients { + err := c.Start() + if err != nil { + allErrs = errors.Join(allErrs, err) + } + } + return allErrs +} + +func (m *MultiBeaconClient) Stop() { + for _, c := range m.clients { + c.Stop() + } + + close(m.closeCh) } type BeaconClient struct { @@ -42,21 +157,24 @@ type BeaconClient struct { mu sync.Mutex slotProposerMap map[uint64]PubkeyHex - closeCh chan struct{} + ctx context.Context + cancelFn context.CancelFunc } func NewBeaconClient(endpoint string, slotsInEpoch uint64, secondsInSlot uint64) *BeaconClient { + ctx, cancelFn := context.WithCancel(context.Background()) return &BeaconClient{ endpoint: endpoint, slotsInEpoch: slotsInEpoch, secondsInSlot: secondsInSlot, slotProposerMap: make(map[uint64]PubkeyHex), - closeCh: make(chan struct{}), + ctx: ctx, + cancelFn: cancelFn, } } func (b *BeaconClient) Stop() { - close(b.closeCh) + b.cancelFn() } func (b *BeaconClient) isValidator(pubkey PubkeyHex) bool { @@ -109,7 +227,7 @@ func (b *BeaconClient) UpdateValidatorMapForever() { defer timer.Stop() for true { select { - case <-b.closeCh: + case <-b.ctx.Done(): return case <-timer.C: } @@ -154,6 +272,70 @@ func (b *BeaconClient) UpdateValidatorMapForever() { } } +// PayloadAttributesEvent represents the data of a payload_attributes event +// {"version": "capella", "data": {"proposer_index": "123", "proposal_slot": "10", "parent_block_number": "9", "parent_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "parent_block_hash": "0x9a2fefd2fdb57f74993c7780ea5b9030d2897b615b89f808011ca5aebed54eaf", "payload_attributes": {"timestamp": "123456", "prev_randao": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", "suggested_fee_recipient": "0x0000000000000000000000000000000000000000", "withdrawals": [{"index": "5", "validator_index": "10", "address": "0x0000000000000000000000000000000000000000", "amount": "15640"}]}}} +type PayloadAttributesEvent struct { + Version string `json:"version"` + Data PayloadAttributesEventData `json:"data"` +} + +type PayloadAttributesEventData struct { + ProposalSlot uint64 `json:"proposal_slot,string"` + ParentBlockHash common.Hash `json:"parent_block_hash"` + PayloadAttributes PayloadAttributes `json:"payload_attributes"` +} + +type PayloadAttributes struct { + Timestamp uint64 `json:"timestamp,string"` + PrevRandao common.Hash `json:"prev_randao"` + SuggestedFeeRecipient common.Address `json:"suggested_fee_recipient"` + Withdrawals []*capella.Withdrawal `json:"withdrawals"` +} + +// SubscribeToPayloadAttributesEvents subscribes to payload attributes events to validate fields such as prevrandao and withdrawals +func (b *BeaconClient) SubscribeToPayloadAttributesEvents(payloadAttrC chan types.BuilderPayloadAttributes) { + payloadAttributesResp := new(PayloadAttributesEvent) + + eventsURL := fmt.Sprintf("%s/eth/v1/events?topics=payload_attributes", b.endpoint) + log.Info("subscribing to payload_attributes events") + + for { + client := sse.NewClient(eventsURL) + err := client.SubscribeRawWithContext(b.ctx, func(msg *sse.Event) { + err := json.Unmarshal(msg.Data, payloadAttributesResp) + if err != nil { + log.Error("could not unmarshal payload_attributes event", "err", err) + } else { + // convert capella.Withdrawal to types.Withdrawal + var withdrawals []*types.Withdrawal + for _, w := range payloadAttributesResp.Data.PayloadAttributes.Withdrawals { + withdrawals = append(withdrawals, &types.Withdrawal{ + Index: uint64(w.Index), + Validator: uint64(w.ValidatorIndex), + Address: common.Address(w.Address), + Amount: uint64(w.Amount), + }) + } + + data := types.BuilderPayloadAttributes{ + Slot: payloadAttributesResp.Data.ProposalSlot, + HeadHash: payloadAttributesResp.Data.ParentBlockHash, + Timestamp: hexutil.Uint64(payloadAttributesResp.Data.PayloadAttributes.Timestamp), + Random: payloadAttributesResp.Data.PayloadAttributes.PrevRandao, + SuggestedFeeRecipient: payloadAttributesResp.Data.PayloadAttributes.SuggestedFeeRecipient, + Withdrawals: withdrawals, + } + payloadAttrC <- data + } + }) + if err != nil { + log.Error("failed to subscribe to payload_attributes events", "err", err) + time.Sleep(1 * time.Second) + } + log.Warn("beaconclient SubscribeRaw ended, reconnecting") + } +} + func fetchCurrentSlot(endpoint string) (uint64, error) { headerRes := &struct { Data []struct { diff --git a/builder/builder.go b/builder/builder.go index 3bcd005865..52d87141c5 100644 --- a/builder/builder.go +++ b/builder/builder.go @@ -37,13 +37,6 @@ type ValidatorData struct { GasLimit uint64 } -type IBeaconClient interface { - isValidator(pubkey PubkeyHex) bool - getProposerForNextSlot(requestedSlot uint64) (PubkeyHex, error) - Start() error - Stop() -} - type IRelay interface { SubmitBlock(msg *boostTypes.BuilderSubmitBlockRequest, vd ValidatorData) error SubmitBlockCapella(msg *capellaapi.SubmitBlockRequest, vd ValidatorData) error @@ -64,6 +57,7 @@ type Builder struct { eth IEthereumService dryRun bool validator *blockvalidation.BlockValidationAPI + beaconClient IBeaconClient builderSecretKey *bls.SecretKey builderPublicKey boostTypes.PublicKey builderSigningDomain boostTypes.Domain @@ -75,9 +69,11 @@ type Builder struct { slotAttrs []types.BuilderPayloadAttributes slotCtx context.Context slotCtxCancel context.CancelFunc + + stop chan struct{} } -func NewBuilder(sk *bls.SecretKey, ds flashbotsextra.IDatabaseService, relay IRelay, builderSigningDomain boostTypes.Domain, eth IEthereumService, dryRun bool, validator *blockvalidation.BlockValidationAPI) *Builder { +func NewBuilder(sk *bls.SecretKey, ds flashbotsextra.IDatabaseService, relay IRelay, builderSigningDomain boostTypes.Domain, eth IEthereumService, dryRun bool, validator *blockvalidation.BlockValidationAPI, beaconClient IBeaconClient) *Builder { pkBytes := bls.PublicKeyFromSecretKey(sk).Compress() pk := boostTypes.PublicKey{} pk.FromSlice(pkBytes) @@ -89,6 +85,7 @@ func NewBuilder(sk *bls.SecretKey, ds flashbotsextra.IDatabaseService, relay IRe eth: eth, dryRun: dryRun, validator: validator, + beaconClient: beaconClient, builderSecretKey: sk, builderPublicKey: pk, builderSigningDomain: builderSigningDomain, @@ -97,14 +94,42 @@ func NewBuilder(sk *bls.SecretKey, ds flashbotsextra.IDatabaseService, relay IRe slot: 0, slotCtx: slotCtx, slotCtxCancel: slotCtxCancel, + + stop: make(chan struct{}, 1), } } func (b *Builder) Start() error { + // Start regular payload attributes updates + go func() { + c := make(chan types.BuilderPayloadAttributes) + go b.beaconClient.SubscribeToPayloadAttributesEvents(c) + + currentSlot := uint64(0) + + for { + select { + case <-b.stop: + return + case payloadAttributes := <-c: + // Right now we are building only on a single head. This might change in the future! + if payloadAttributes.Slot < currentSlot { + continue + } else if payloadAttributes.Slot == currentSlot { + b.OnPayloadAttribute(&payloadAttributes) + } else if payloadAttributes.Slot > currentSlot { + currentSlot = payloadAttributes.Slot + b.OnPayloadAttribute(&payloadAttributes) + } + } + } + }() + return b.relay.Start() } func (b *Builder) Stop() error { + close(b.stop) return nil } @@ -277,18 +302,19 @@ func (b *Builder) OnPayloadAttribute(attrs *types.BuilderPayloadAttributes) erro b.slotMu.Lock() defer b.slotMu.Unlock() - if b.slot != attrs.Slot { - if b.slotCtxCancel != nil { - b.slotCtxCancel() - } + // Forcibly cancel previous building job, build on top of reorgable blocks as this is the behaviour relays expect. + // This will change in the future - slotCtx, slotCtxCancel := context.WithTimeout(context.Background(), 12*time.Second) - b.slot = attrs.Slot - b.slotAttrs = nil - b.slotCtx = slotCtx - b.slotCtxCancel = slotCtxCancel + if b.slotCtxCancel != nil { + b.slotCtxCancel() } + slotCtx, slotCtxCancel := context.WithTimeout(context.Background(), 12*time.Second) + b.slot = attrs.Slot + b.slotAttrs = nil + b.slotCtx = slotCtx + b.slotCtxCancel = slotCtxCancel + for _, currentAttrs := range b.slotAttrs { if attrs.Equal(¤tAttrs) { log.Debug("ignoring known payload attribute", "slot", attrs.Slot, "hash", attrs.HeadHash) diff --git a/builder/builder_test.go b/builder/builder_test.go index c2b9648865..4f6d1168c0 100644 --- a/builder/builder_test.go +++ b/builder/builder_test.go @@ -73,7 +73,7 @@ func TestOnPayloadAttributes(t *testing.T) { testEthService := &testEthereumService{synced: true, testExecutableData: testExecutableData, testBlock: testBlock, testBlockValue: big.NewInt(10)} - builder := NewBuilder(sk, flashbotsextra.NilDbService{}, &testRelay, bDomain, testEthService, false, nil) + builder := NewBuilder(sk, flashbotsextra.NilDbService{}, &testRelay, bDomain, testEthService, false, nil, &testBeacon) builder.Start() defer builder.Stop() diff --git a/builder/config.go b/builder/config.go index cc445d5efc..f9f2bba5b3 100644 --- a/builder/config.go +++ b/builder/config.go @@ -14,7 +14,7 @@ type Config struct { GenesisForkVersion string `toml:",omitempty"` BellatrixForkVersion string `toml:",omitempty"` GenesisValidatorsRoot string `toml:",omitempty"` - BeaconEndpoint string `toml:",omitempty"` + BeaconEndpoints []string `toml:",omitempty"` RemoteRelayEndpoint string `toml:",omitempty"` SecondaryRemoteRelayEndpoints []string `toml:",omitempty"` ValidationBlocklist string `toml:",omitempty"` @@ -35,7 +35,7 @@ var DefaultConfig = Config{ GenesisForkVersion: "0x00000000", BellatrixForkVersion: "0x02000000", GenesisValidatorsRoot: "0x0000000000000000000000000000000000000000000000000000000000000000", - BeaconEndpoint: "http://127.0.0.1:5052", + BeaconEndpoints: []string{"http://127.0.0.1:5052"}, RemoteRelayEndpoint: "", SecondaryRemoteRelayEndpoints: nil, ValidationBlocklist: "", diff --git a/builder/local_relay_test.go b/builder/local_relay_test.go index fcc292fba6..232ad307b3 100644 --- a/builder/local_relay_test.go +++ b/builder/local_relay_test.go @@ -32,7 +32,7 @@ func newTestBackend(t *testing.T, forkchoiceData *engine.ExecutableData, block * beaconClient := &testBeaconClient{validator: validator} localRelay := NewLocalRelay(sk, beaconClient, bDomain, cDomain, ForkData{}, true) ethService := &testEthereumService{synced: true, testExecutableData: forkchoiceData, testBlock: block, testBlockValue: blockValue} - backend := NewBuilder(sk, flashbotsextra.NilDbService{}, localRelay, bDomain, ethService, false, nil) + backend := NewBuilder(sk, flashbotsextra.NilDbService{}, localRelay, bDomain, ethService, false, nil, beaconClient) // service := NewService("127.0.0.1:31545", backend) backend.limiter = rate.NewLimiter(rate.Inf, 0) diff --git a/builder/service.go b/builder/service.go index b49a0edf29..a315553212 100644 --- a/builder/service.go +++ b/builder/service.go @@ -120,7 +120,14 @@ func Register(stack *node.Node, backend *eth.Ethereum, cfg *Config) error { copy(bellatrixForkVersion[:], bellatrixForkVersionBytes[:4]) proposerSigningDomain := boostTypes.ComputeDomain(boostTypes.DomainTypeBeaconProposer, bellatrixForkVersion, genesisValidatorsRoot) - beaconClient := NewBeaconClient(cfg.BeaconEndpoint, cfg.SlotsInEpoch, cfg.SecondsInSlot) + var beaconClient IBeaconClient + if len(cfg.BeaconEndpoints) == 0 { + beaconClient = &NilBeaconClient{} + } else if len(cfg.BeaconEndpoints) == 1 { + beaconClient = NewBeaconClient(cfg.BeaconEndpoints[0], cfg.SlotsInEpoch, cfg.SecondsInSlot) + } else { + beaconClient = NewMultiBeaconClient(cfg.BeaconEndpoints, cfg.SlotsInEpoch, cfg.SecondsInSlot) + } var localRelay *LocalRelay if cfg.EnableLocalRelay { @@ -196,7 +203,7 @@ func Register(stack *node.Node, backend *eth.Ethereum, cfg *Config) error { return errors.New("incorrect builder API secret key provided") } - builderBackend := NewBuilder(builderSk, ds, relay, builderSigningDomain, ethereumService, cfg.DryRun, validator) + builderBackend := NewBuilder(builderSk, ds, relay, builderSigningDomain, ethereumService, cfg.DryRun, validator, beaconClient) builderService := NewService(cfg.ListenAddr, localRelay, builderBackend) stack.RegisterAPIs([]rpc.API{ diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 5c592ee09d..24a9395cf0 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -171,7 +171,7 @@ var ( utils.BuilderGenesisForkVersion, utils.BuilderBellatrixForkVersion, utils.BuilderGenesisValidatorsRoot, - utils.BuilderBeaconEndpoint, + utils.BuilderBeaconEndpoints, utils.BuilderRemoteRelayEndpoint, utils.BuilderSecondaryRemoteRelayEndpoints, } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 2c318ecb20..973580de76 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -778,10 +778,10 @@ var ( Value: "0x0000000000000000000000000000000000000000000000000000000000000000", Category: flags.BuilderCategory, } - BuilderBeaconEndpoint = &cli.StringFlag{ - Name: "builder.beacon_endpoint", - Usage: "Beacon endpoint to connect to for beacon chain data", - EnvVars: []string{"BUILDER_BEACON_ENDPOINT"}, + BuilderBeaconEndpoints = &cli.StringFlag{ + Name: "builder.beacon_endpoints", + Usage: "Comma separated list of beacon endpoints to connect to for beacon chain data", + EnvVars: []string{"BUILDER_BEACON_ENDPOINTS"}, Value: "http://127.0.0.1:5052", Category: flags.BuilderCategory, } @@ -1608,7 +1608,7 @@ func SetBuilderConfig(ctx *cli.Context, cfg *builder.Config) { cfg.GenesisForkVersion = ctx.String(BuilderGenesisForkVersion.Name) cfg.BellatrixForkVersion = ctx.String(BuilderBellatrixForkVersion.Name) cfg.GenesisValidatorsRoot = ctx.String(BuilderGenesisValidatorsRoot.Name) - cfg.BeaconEndpoint = ctx.String(BuilderBeaconEndpoint.Name) + cfg.BeaconEndpoints = strings.Split(ctx.String(BuilderBeaconEndpoints.Name), ",") cfg.RemoteRelayEndpoint = ctx.String(BuilderRemoteRelayEndpoint.Name) cfg.SecondaryRemoteRelayEndpoints = strings.Split(ctx.String(BuilderSecondaryRemoteRelayEndpoints.Name), ",") cfg.ValidationBlocklist = ctx.String(BuilderBlockValidationBlacklistSourceFilePath.Name) diff --git a/consensus/ethash/flashbots_api.go b/consensus/ethash/flashbots_api.go index 527d2a4435..2c814c29db 100644 --- a/consensus/ethash/flashbots_api.go +++ b/consensus/ethash/flashbots_api.go @@ -10,11 +10,12 @@ type FlashbotsAPI struct { // GetWork returns a work package for external miner. // // The work package consists of 5 strings: -// result[0] - 32 bytes hex encoded current block header pow-hash -// result[1] - 32 bytes hex encoded seed hash used for DAG -// result[2] - 32 bytes hex encoded boundary condition ("target"), 2^256/difficulty -// result[3] - hex encoded block number -// result[4] - hex encoded profit generated from this block +// +// result[0] - 32 bytes hex encoded current block header pow-hash +// result[1] - 32 bytes hex encoded seed hash used for DAG +// result[2] - 32 bytes hex encoded boundary condition ("target"), 2^256/difficulty +// result[3] - hex encoded block number +// result[4] - hex encoded profit generated from this block func (api *FlashbotsAPI) GetWork() ([5]string, error) { if api.ethash.remote == nil { return [5]string{}, errors.New("not supported") diff --git a/consensus/ethash/sealer.go b/consensus/ethash/sealer.go index e13142a173..04c3addf8a 100644 --- a/consensus/ethash/sealer.go +++ b/consensus/ethash/sealer.go @@ -340,11 +340,12 @@ func (s *remoteSealer) loop() { // makeWork creates a work package for external miner. // // The work package consists of 5 strings: -// result[0], 32 bytes hex encoded current block header pow-hash -// result[1], 32 bytes hex encoded seed hash used for DAG -// result[2], 32 bytes hex encoded boundary condition ("target"), 2^256/difficulty -// result[3], hex encoded block number -// result[4], hex encoded profit generated from this block, if present +// +// result[0], 32 bytes hex encoded current block header pow-hash +// result[1], 32 bytes hex encoded seed hash used for DAG +// result[2], 32 bytes hex encoded boundary condition ("target"), 2^256/difficulty +// result[3], hex encoded block number +// result[4], hex encoded profit generated from this block, if present func (s *remoteSealer) makeWork(block *types.Block, profit *big.Int) { hash := s.ethash.SealHash(block.Header()) s.currentWork[0] = hash.Hex() diff --git a/core/block_validator.go b/core/block_validator.go index 562b464620..a04dc44954 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -81,7 +81,7 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error { // Withdrawals are not allowed prior to shanghai fork return fmt.Errorf("withdrawals present in block body") } - + if !v.bc.HasBlockAndState(block.ParentHash(), block.NumberU64()-1) { if !v.bc.HasBlock(block.ParentHash(), block.NumberU64()-1) { return consensus.ErrUnknownAncestor diff --git a/core/txpool/txpool_test.go b/core/txpool/txpool_test.go index d6d4e0cb3c..2062c22f6b 100644 --- a/core/txpool/txpool_test.go +++ b/core/txpool/txpool_test.go @@ -2447,7 +2447,7 @@ func TestSlotCount(t *testing.T) { func TestBundleCancellations(t *testing.T) { // Create the pool to test the status retrievals with statedb, _ := state.New(common.Hash{}, state.NewDatabase(rawdb.NewMemoryDatabase()), nil) - blockchain := &testBlockChain{100, statedb, new(event.Feed)} + blockchain := newTestBlockChain(100, statedb, new(event.Feed)) pool := NewTxPool(testTxPoolConfig, params.TestChainConfig, blockchain) fetcher := &mockFetcher{make(map[int64]error), make(map[int64][]types.LatestUuidBundle)} @@ -2509,7 +2509,7 @@ func TestBundleCancellations(t *testing.T) { require.Equal(t, []types.MevBundle{bundle01_uuid1_signer1}, cr.Value) fetcher.resps[1] = []types.LatestUuidBundle{ - types.LatestUuidBundle{ + { Uuid: bundle03_uuid1_signer1.Uuid, SigningAddress: bundle03_uuid1_signer1.SigningAddress, BundleHash: bundle03_uuid1_signer1.Hash, diff --git a/eth/block-validation/api_test.go b/eth/block-validation/api_test.go index 3e2a2c9949..3263b20ba0 100644 --- a/eth/block-validation/api_test.go +++ b/eth/block-validation/api_test.go @@ -127,7 +127,7 @@ func TestValidateBuilderSubmissionV1(t *testing.T) { // Test tx from blacklisted address api.accessVerifier = &AccessVerifier{ blacklistedAddresses: map[common.Address]struct{}{ - testAddr: struct{}{}, + testAddr: {}, }, } require.ErrorContains(t, api.ValidateBuilderSubmissionV1(blockRequest), "transaction from blacklisted address 0x71562b71999873DB5b286dF957af199Ec94617F7") @@ -135,7 +135,7 @@ func TestValidateBuilderSubmissionV1(t *testing.T) { // Test tx to blacklisted address api.accessVerifier = &AccessVerifier{ blacklistedAddresses: map[common.Address]struct{}{ - common.Address{0x16}: struct{}{}, + {0x16}: {}, }, } require.ErrorContains(t, api.ValidateBuilderSubmissionV1(blockRequest), "transaction to blacklisted address 0x1600000000000000000000000000000000000000") @@ -421,8 +421,8 @@ func TestBlacklistLoad(t *testing.T) { require.NoError(t, err) require.NotNil(t, av) require.EqualValues(t, av.blacklistedAddresses, map[common.Address]struct{}{ - common.Address{0x13}: struct{}{}, - common.Address{0x14}: struct{}{}, + {0x13}: {}, + {0x14}: {}, }) require.NoError(t, av.verifyTraces(logger.NewAccessListTracer(nil, common.Address{}, common.Address{}, nil))) diff --git a/ethclient/gethclient/gethclient_test.go b/ethclient/gethclient/gethclient_test.go index a9637d182f..dce7cc61d1 100644 --- a/ethclient/gethclient/gethclient_test.go +++ b/ethclient/gethclient/gethclient_test.go @@ -366,17 +366,17 @@ func testCallContract(t *testing.T, client *rpc.Client) { func TestOverrideAccountMarshal(t *testing.T) { om := map[common.Address]OverrideAccount{ - common.Address{0x11}: OverrideAccount{ + {0x11}: { // Zero-valued nonce is not overriddden, but simply dropped by the encoder. Nonce: 0, }, - common.Address{0xaa}: OverrideAccount{ + {0xaa}: { Nonce: 5, }, - common.Address{0xbb}: OverrideAccount{ + {0xbb}: { Code: []byte{1}, }, - common.Address{0xcc}: OverrideAccount{ + {0xcc}: { // 'code', 'balance', 'state' should be set when input is // a non-nil but empty value. Code: []byte{}, diff --git a/flashbotsextra/database_test.go b/flashbotsextra/database_test.go index 6d2aef96e6..8c7071b54d 100644 --- a/flashbotsextra/database_test.go +++ b/flashbotsextra/database_test.go @@ -53,7 +53,7 @@ func TestDatabaseBlockInsertion(t *testing.T) { Txs: types.Transactions{types.NewTransaction(uint64(50), common.Address{0x60}, big.NewInt(19), uint64(67), big.NewInt(43), []byte{})}, BlockNumber: big.NewInt(12), MinTimestamp: uint64(1000000), - RevertingTxHashes: []common.Hash{common.Hash{0x10, 0x17}}, + RevertingTxHashes: []common.Hash{{0x10, 0x17}}, Hash: common.Hash{0x09, 0x78}, }, } @@ -67,7 +67,7 @@ func TestDatabaseBlockInsertion(t *testing.T) { Txs: types.Transactions{types.NewTransaction(uint64(51), common.Address{0x61}, big.NewInt(109), uint64(167), big.NewInt(433), []byte{})}, BlockNumber: big.NewInt(12), MinTimestamp: uint64(1000020), - RevertingTxHashes: []common.Hash{common.Hash{0x11, 0x17}}, + RevertingTxHashes: []common.Hash{{0x11, 0x17}}, Hash: common.Hash{0x10, 0x78}, }, } @@ -84,7 +84,7 @@ func TestDatabaseBlockInsertion(t *testing.T) { Txs: types.Transactions{types.NewTransaction(uint64(51), common.Address{0x62}, big.NewInt(20), uint64(68), big.NewInt(44), []byte{})}, BlockNumber: big.NewInt(12), MinTimestamp: uint64(1000021), - RevertingTxHashes: []common.Hash{common.Hash{0x10, 0x18}}, + RevertingTxHashes: []common.Hash{{0x10, 0x18}}, Hash: common.Hash{0x09, 0x79}, }, } @@ -98,7 +98,7 @@ func TestDatabaseBlockInsertion(t *testing.T) { Txs: types.Transactions{types.NewTransaction(uint64(52), common.Address{0x62}, big.NewInt(110), uint64(168), big.NewInt(434), []byte{})}, BlockNumber: big.NewInt(12), MinTimestamp: uint64(1000022), - RevertingTxHashes: []common.Hash{common.Hash{0x11, 0x19}}, + RevertingTxHashes: []common.Hash{{0x11, 0x19}}, Hash: common.Hash{0x10, 0x80}, }, } diff --git a/go.mod b/go.mod index 33d44e8464..d895f228d8 100644 --- a/go.mod +++ b/go.mod @@ -76,6 +76,8 @@ require ( gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce ) +require gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect + require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3 // indirect @@ -125,6 +127,7 @@ require ( github.com/prometheus/common v0.39.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7 // indirect + github.com/r3labs/sse v0.0.0-20210224172625-26fe804710bc github.com/rogpeppe/go-internal v1.9.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sirupsen/logrus v1.9.0 // indirect diff --git a/go.sum b/go.sum index b49fa68a01..3c071087ad 100644 --- a/go.sum +++ b/go.sum @@ -595,6 +595,8 @@ github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7 h1:0tVE4 github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7/go.mod h1:wmuf/mdK4VMD+jA9ThwcUKjg3a2XWM9cVfFYjDyY4j4= github.com/prysmaticlabs/gohashtree v0.0.1-alpha.0.20220714111606-acbb2962fb48 h1:cSo6/vk8YpvkLbk9v3FO97cakNmUoxwi2KMP8hd5WIw= github.com/prysmaticlabs/gohashtree v0.0.1-alpha.0.20220714111606-acbb2962fb48/go.mod h1:4pWaT30XoEx1j8KNJf3TV+E3mQkaufn7mf+jRNb/Fuk= +github.com/r3labs/sse v0.0.0-20210224172625-26fe804710bc h1:zAsgcP8MhzAbhMnB1QQ2O7ZhWYVGYSR2iVcjzQuPV+o= +github.com/r3labs/sse v0.0.0-20210224172625-26fe804710bc/go.mod h1:S8xSOnV3CgpNrWd0GQ/OoQfMtlg2uPRSuTzcSGrzwK8= github.com/r3labs/sse/v2 v2.7.4/go.mod h1:hUrYMKfu9WquG9MyI0r6TKiNH+6Sw/QPKm2YbNbU5g8= github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -1065,6 +1067,7 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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= diff --git a/metrics/config.go b/metrics/config.go index f0e5a7be2b..3bfce0f4e5 100644 --- a/metrics/config.go +++ b/metrics/config.go @@ -20,7 +20,7 @@ package metrics type Config struct { Enabled bool `toml:",omitempty"` EnabledExpensive bool `toml:",omitempty"` - EnabledBuilder bool `toml:",omitempty"` + EnabledBuilder bool `toml:",omitempty"` HTTP string `toml:",omitempty"` Port int `toml:",omitempty"` EnableInfluxDB bool `toml:",omitempty"` diff --git a/miner/algo_common.go b/miner/algo_common.go index 1a4edd9d7b..45b572b2be 100644 --- a/miner/algo_common.go +++ b/miner/algo_common.go @@ -154,7 +154,7 @@ func (envDiff *environmentDiff) commitTx(tx *types.Transaction, chData chainData receipt, newState, err := applyTransactionWithBlacklist(signer, chData.chainConfig, chData.chain, coinbase, envDiff.gasPool, envDiff.state, header, tx, &header.GasUsed, *chData.chain.GetVMConfig(), chData.blacklist) - envDiff.state = newState + envDiff.state = newState if err != nil { switch { case errors.Is(err, core.ErrGasLimitReached): diff --git a/miner/bundle_cache_test.go b/miner/bundle_cache_test.go index 77de101af6..0f4bf1159b 100644 --- a/miner/bundle_cache_test.go +++ b/miner/bundle_cache_test.go @@ -22,8 +22,8 @@ func TestBundleCacheEntry(t *testing.T) { t.Errorf("found bundle in empty cache: %s", successBundle) } - bundles := []types.MevBundle{types.MevBundle{Hash: failingBundle}, types.MevBundle{Hash: successBundle}} - simResult := []*types.SimulatedBundle{nil, &types.SimulatedBundle{OriginalBundle: bundles[1]}} + bundles := []types.MevBundle{{Hash: failingBundle}, {Hash: successBundle}} + simResult := []*types.SimulatedBundle{nil, {OriginalBundle: bundles[1]}} entry.UpdateSimulatedBundles(simResult, bundles) sim, found = entry.GetSimulatedBundle(failingBundle) diff --git a/miner/multi_worker.go b/miner/multi_worker.go index d651135b6b..04e846f29b 100644 --- a/miner/multi_worker.go +++ b/miner/multi_worker.go @@ -99,12 +99,12 @@ func (w *multiWorker) buildPayload(args *BuildPayloadArgs) (*Payload, error) { for _, worker := range w.workers { var err error empty, _, err = worker.getSealingBlock(args.Parent, args.Timestamp, args.FeeRecipient, args.GasLimit, args.Random, args.Withdrawals, true, nil) - if err != nil { + if err != nil { log.Error("could not start async block construction", "isFlashbotsWorker", worker.flashbots.isFlashbots, "#bundles", worker.flashbots.maxMergedBundles) continue - } + } break - } + } if empty == nil { return nil, errors.New("no worker could build an empty block") @@ -133,7 +133,7 @@ func (w *multiWorker) buildPayload(args *BuildPayloadArgs) (*Payload, error) { } }(w) } - + go payload.resolveBestFullPayload(workerPayloads) return payload, nil diff --git a/miner/payload_building_test.go b/miner/payload_building_test.go index cf72b70ac6..e98f6999cc 100644 --- a/miner/payload_building_test.go +++ b/miner/payload_building_test.go @@ -85,48 +85,48 @@ func TestBuildPayload(t *testing.T) { func TestPayloadId(t *testing.T) { ids := make(map[string]int) for i, tt := range []*BuildPayloadArgs{ - &BuildPayloadArgs{ + { Parent: common.Hash{1}, Timestamp: 1, Random: common.Hash{0x1}, FeeRecipient: common.Address{0x1}, }, // Different parent - &BuildPayloadArgs{ + { Parent: common.Hash{2}, Timestamp: 1, Random: common.Hash{0x1}, FeeRecipient: common.Address{0x1}, }, // Different timestamp - &BuildPayloadArgs{ + { Parent: common.Hash{2}, Timestamp: 2, Random: common.Hash{0x1}, FeeRecipient: common.Address{0x1}, }, // Different Random - &BuildPayloadArgs{ + { Parent: common.Hash{2}, Timestamp: 2, Random: common.Hash{0x2}, FeeRecipient: common.Address{0x1}, }, // Different fee-recipient - &BuildPayloadArgs{ + { Parent: common.Hash{2}, Timestamp: 2, Random: common.Hash{0x2}, FeeRecipient: common.Address{0x2}, }, // Different withdrawals (non-empty) - &BuildPayloadArgs{ + { Parent: common.Hash{2}, Timestamp: 2, Random: common.Hash{0x2}, FeeRecipient: common.Address{0x2}, Withdrawals: []*types.Withdrawal{ - &types.Withdrawal{ + { Index: 0, Validator: 0, Address: common.Address{}, @@ -135,13 +135,13 @@ func TestPayloadId(t *testing.T) { }, }, // Different withdrawals (non-empty) - &BuildPayloadArgs{ + { Parent: common.Hash{2}, Timestamp: 2, Random: common.Hash{0x2}, FeeRecipient: common.Address{0x2}, Withdrawals: []*types.Withdrawal{ - &types.Withdrawal{ + { Index: 2, Validator: 0, Address: common.Address{}, diff --git a/miner/worker.go b/miner/worker.go index 5fa9c63ccb..fdf43b25ba 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -1020,7 +1020,7 @@ func (w *worker) commitBundle(env *environment, txs types.Transactions, interrup if interrupt != nil { if signal := atomic.LoadInt32(interrupt); signal != commitInterruptNone { return signalToErr(signal) - } + } } // If we don't have enough gas for any further transactions discard the block // since not all bundles of the were applied