Skip to content

Commit

Permalink
Update go-boost-utils and type upgrades (ethereum#72)
Browse files Browse the repository at this point in the history
* Update go-boost-utils and type upgrades

* fix tests

* linting

* merge conflicts
  • Loading branch information
avalonche authored Jun 12, 2023
1 parent b6a6dd3 commit b6e031b
Show file tree
Hide file tree
Showing 19 changed files with 435 additions and 311 deletions.
19 changes: 13 additions & 6 deletions beacon/engine/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,12 @@ import (
"fmt"
"math/big"

"github.com/attestantio/go-eth2-client/spec/bellatrix"
"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/trie"

boostTypes "github.com/flashbots/go-boost-utils/types"
)

//go:generate go run github.com/fjl/gencodec -type PayloadAttributes -field-override payloadAttributesMarshaling -out gen_blockparams.go
Expand Down Expand Up @@ -241,8 +240,8 @@ type ExecutionPayloadBodyV1 struct {
Withdrawals []*types.Withdrawal `json:"withdrawals"`
}

func ExecutionPayloadToBlock(payload *boostTypes.ExecutionPayload) (*types.Block, error) {
// TODO: separate decode function to avoid allocating twice
func ExecutionPayloadToBlock(payload *bellatrix.ExecutionPayload) (*types.Block, error) {
// TODO: consolidate this into one function that handles all forks
transactionBytes := make([][]byte, len(payload.Transactions))
for i, txHexBytes := range payload.Transactions {
transactionBytes[i] = txHexBytes[:]
Expand All @@ -252,6 +251,14 @@ func ExecutionPayloadToBlock(payload *boostTypes.ExecutionPayload) (*types.Block
return nil, err
}

// base fee per gas is stored little-endian but we need it
// big-endian for big.Int.
var baseFeePerGasBytes [32]byte
for i := 0; i < 32; i++ {
baseFeePerGasBytes[i] = payload.BaseFeePerGas[32-1-i]
}
baseFeePerGas := new(big.Int).SetBytes(baseFeePerGasBytes[:])

header := &types.Header{
ParentHash: common.Hash(payload.ParentHash),
UncleHash: types.EmptyUncleHash,
Expand All @@ -265,9 +272,9 @@ func ExecutionPayloadToBlock(payload *boostTypes.ExecutionPayload) (*types.Block
GasLimit: payload.GasLimit,
GasUsed: payload.GasUsed,
Time: payload.Timestamp,
BaseFee: payload.BaseFeePerGas.BigInt(),
BaseFee: baseFeePerGas,
Extra: payload.ExtraData,
MixDigest: common.Hash(payload.Random),
MixDigest: common.Hash(payload.PrevRandao),
}
block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */)
return block, nil
Expand Down
108 changes: 44 additions & 64 deletions builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,22 @@ import (
"sync"
"time"

bellatrixapi "github.com/attestantio/go-builder-client/api/bellatrix"
capellaapi "github.com/attestantio/go-builder-client/api/capella"
apiv1 "github.com/attestantio/go-builder-client/api/v1"
"github.com/attestantio/go-eth2-client/spec/bellatrix"
"github.com/attestantio/go-eth2-client/spec/capella"
"github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/ethereum/go-ethereum/beacon/engine"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
blockvalidation "github.com/ethereum/go-ethereum/eth/block-validation"
"github.com/ethereum/go-ethereum/flashbotsextra"
"github.com/ethereum/go-ethereum/log"
"github.com/flashbots/go-boost-utils/bls"
"github.com/flashbots/go-boost-utils/ssz"
boostTypes "github.com/flashbots/go-boost-utils/types"
"github.com/flashbots/go-boost-utils/utils"
"github.com/holiman/uint256"
"golang.org/x/time/rate"
)
Expand All @@ -39,12 +41,12 @@ type PubkeyHex string

type ValidatorData struct {
Pubkey PubkeyHex
FeeRecipient boostTypes.Address
FeeRecipient bellatrix.ExecutionAddress
GasLimit uint64
}

type IRelay interface {
SubmitBlock(msg *boostTypes.BuilderSubmitBlockRequest, vd ValidatorData) error
SubmitBlock(msg *bellatrixapi.SubmitBlockRequest, vd ValidatorData) error
SubmitBlockCapella(msg *capellaapi.SubmitBlockRequest, vd ValidatorData) error
GetValidatorForSlot(nextSlot uint64) (ValidatorData, error)
Config() RelayConfig
Expand All @@ -67,8 +69,8 @@ type Builder struct {
validator *blockvalidation.BlockValidationAPI
beaconClient IBeaconClient
builderSecretKey *bls.SecretKey
builderPublicKey boostTypes.PublicKey
builderSigningDomain boostTypes.Domain
builderPublicKey phase0.BLSPubKey
builderSigningDomain phase0.Domain
builderResubmitInterval time.Duration

limiter *rate.Limiter
Expand All @@ -86,7 +88,7 @@ type BuilderArgs struct {
sk *bls.SecretKey
ds flashbotsextra.IDatabaseService
relay IRelay
builderSigningDomain boostTypes.Domain
builderSigningDomain phase0.Domain
builderBlockResubmitInterval time.Duration
eth IEthereumService
dryRun bool
Expand All @@ -97,10 +99,15 @@ type BuilderArgs struct {
limiter *rate.Limiter
}

func NewBuilder(args BuilderArgs) *Builder {
pkBytes := bls.PublicKeyFromSecretKey(args.sk).Compress()
pk := boostTypes.PublicKey{}
pk.FromSlice(pkBytes)
func NewBuilder(args BuilderArgs) (*Builder, error) {
blsPk, err := bls.PublicKeyFromSecretKey(args.sk)
if err != nil {
return nil, err
}
pk, err := utils.BlsPublicKeyToPublicKey(blsPk)
if err != nil {
return nil, err
}

if args.limiter == nil {
args.limiter = rate.NewLimiter(rate.Every(RateLimitIntervalDefault), RateLimitBurstDefault)
Expand Down Expand Up @@ -129,7 +136,7 @@ func NewBuilder(args BuilderArgs) *Builder {
slotCtxCancel: slotCtxCancel,

stop: make(chan struct{}, 1),
}
}, nil
}

func (b *Builder) Start() error {
Expand Down Expand Up @@ -185,7 +192,7 @@ func (b *Builder) Stop() error {

func (b *Builder) onSealedBlock(block *types.Block, blockValue *big.Int, ordersClosedAt, sealedAt time.Time,
commitedBundles, allBundles []types.SimulatedBundle, usedSbundles []types.UsedSBundle,
proposerPubkey boostTypes.PublicKey, vd ValidatorData, attrs *types.BuilderPayloadAttributes) error {
proposerPubkey phase0.BLSPubKey, vd ValidatorData, attrs *types.BuilderPayloadAttributes) error {
if b.eth.Config().IsShanghai(block.Time()) {
if err := b.submitCapellaBlock(block, blockValue, ordersClosedAt, sealedAt, commitedBundles, allBundles, usedSbundles, proposerPubkey, vd, attrs); err != nil {
return err
Expand All @@ -204,22 +211,21 @@ func (b *Builder) onSealedBlock(block *types.Block, blockValue *big.Int, ordersC

func (b *Builder) submitBellatrixBlock(block *types.Block, blockValue *big.Int, ordersClosedAt, sealedAt time.Time,
commitedBundles, allBundles []types.SimulatedBundle, usedSbundles []types.UsedSBundle,
proposerPubkey boostTypes.PublicKey, vd ValidatorData, attrs *types.BuilderPayloadAttributes) error {
proposerPubkey phase0.BLSPubKey, vd ValidatorData, attrs *types.BuilderPayloadAttributes) error {
executableData := engine.BlockToExecutableData(block, blockValue)
payload, err := executableDataToExecutionPayload(executableData.ExecutionPayload)
if err != nil {
log.Error("could not format execution payload", "err", err)
return err
}

value := new(boostTypes.U256Str)
err = value.FromBig(blockValue)
if err != nil {
log.Error("could not set block value", "err", err)
value, overflow := uint256.FromBig(blockValue)
if overflow {
log.Error("could not set block value due to value overflow")
return err
}

blockBidMsg := boostTypes.BidTrace{
blockBidMsg := apiv1.BidTrace{
Slot: attrs.Slot,
ParentHash: payload.ParentHash,
BlockHash: payload.BlockHash,
Expand All @@ -228,23 +234,23 @@ func (b *Builder) submitBellatrixBlock(block *types.Block, blockValue *big.Int,
ProposerFeeRecipient: vd.FeeRecipient,
GasLimit: executableData.ExecutionPayload.GasLimit,
GasUsed: executableData.ExecutionPayload.GasUsed,
Value: *value,
Value: value,
}

signature, err := boostTypes.SignMessage(&blockBidMsg, b.builderSigningDomain, b.builderSecretKey)
signature, err := ssz.SignMessage(&blockBidMsg, b.builderSigningDomain, b.builderSecretKey)
if err != nil {
log.Error("could not sign builder bid", "err", err)
return err
}

blockSubmitReq := boostTypes.BuilderSubmitBlockRequest{
blockSubmitReq := bellatrixapi.SubmitBlockRequest{
Signature: signature,
Message: &blockBidMsg,
ExecutionPayload: payload,
}

if b.dryRun {
err = b.validator.ValidateBuilderSubmissionV1(&blockvalidation.BuilderBlockValidationRequest{BuilderSubmitBlockRequest: blockSubmitReq, RegisteredGasLimit: vd.GasLimit})
err = b.validator.ValidateBuilderSubmissionV1(&blockvalidation.BuilderBlockValidationRequest{SubmitBlockRequest: blockSubmitReq, RegisteredGasLimit: vd.GasLimit})
if err != nil {
log.Error("could not validate bellatrix block", "err", err)
}
Expand All @@ -264,7 +270,7 @@ func (b *Builder) submitBellatrixBlock(block *types.Block, blockValue *big.Int,

func (b *Builder) submitCapellaBlock(block *types.Block, blockValue *big.Int, ordersClosedAt, sealedAt time.Time,
commitedBundles, allBundles []types.SimulatedBundle, usedSbundles []types.UsedSBundle,
proposerPubkey boostTypes.PublicKey, vd ValidatorData, attrs *types.BuilderPayloadAttributes) error {
proposerPubkey phase0.BLSPubKey, vd ValidatorData, attrs *types.BuilderPayloadAttributes) error {
executableData := engine.BlockToExecutableData(block, blockValue)
payload, err := executableDataToCapellaExecutionPayload(executableData.ExecutionPayload)
if err != nil {
Expand All @@ -282,28 +288,22 @@ func (b *Builder) submitCapellaBlock(block *types.Block, blockValue *big.Int, or
Slot: attrs.Slot,
ParentHash: payload.ParentHash,
BlockHash: payload.BlockHash,
BuilderPubkey: phase0.BLSPubKey(b.builderPublicKey),
ProposerPubkey: phase0.BLSPubKey(proposerPubkey),
ProposerFeeRecipient: bellatrix.ExecutionAddress(vd.FeeRecipient),
BuilderPubkey: b.builderPublicKey,
ProposerPubkey: proposerPubkey,
ProposerFeeRecipient: vd.FeeRecipient,
GasLimit: executableData.ExecutionPayload.GasLimit,
GasUsed: executableData.ExecutionPayload.GasUsed,
Value: value,
}

boostBidTrace, err := convertBidTrace(blockBidMsg)
if err != nil {
log.Error("could not convert bid trace", "err", err)
return err
}

signature, err := boostTypes.SignMessage(&blockBidMsg, b.builderSigningDomain, b.builderSecretKey)
signature, err := ssz.SignMessage(&blockBidMsg, b.builderSigningDomain, b.builderSecretKey)
if err != nil {
log.Error("could not sign builder bid", "err", err)
return err
}

blockSubmitReq := capellaapi.SubmitBlockRequest{
Signature: phase0.BLSSignature(signature),
Signature: signature,
Message: &blockBidMsg,
ExecutionPayload: payload,
}
Expand All @@ -314,7 +314,7 @@ func (b *Builder) submitCapellaBlock(block *types.Block, blockValue *big.Int, or
log.Error("could not validate block for capella", "err", err)
}
} else {
go b.ds.ConsumeBuiltBlock(block, blockValue, ordersClosedAt, sealedAt, commitedBundles, allBundles, usedSbundles, &boostBidTrace)
go b.ds.ConsumeBuiltBlock(block, blockValue, ordersClosedAt, sealedAt, commitedBundles, allBundles, usedSbundles, &blockBidMsg)
err = b.relay.SubmitBlockCapella(&blockSubmitReq, vd)
if err != nil {
log.Error("could not submit capella block", "err", err, "#commitedBundles", len(commitedBundles))
Expand All @@ -339,7 +339,7 @@ func (b *Builder) OnPayloadAttribute(attrs *types.BuilderPayloadAttributes) erro
attrs.SuggestedFeeRecipient = [20]byte(vd.FeeRecipient)
attrs.GasLimit = vd.GasLimit

proposerPubkey, err := boostTypes.HexToPubkey(string(vd.Pubkey))
proposerPubkey, err := utils.HexToPubkey(string(vd.Pubkey))
if err != nil {
return fmt.Errorf("could not parse pubkey (%s) - %w", vd.Pubkey, err)
}
Expand Down Expand Up @@ -384,7 +384,7 @@ type blockQueueEntry struct {
usedSbundles []types.UsedSBundle
}

func (b *Builder) runBuildingJob(slotCtx context.Context, proposerPubkey boostTypes.PublicKey, vd ValidatorData, attrs *types.BuilderPayloadAttributes) {
func (b *Builder) runBuildingJob(slotCtx context.Context, proposerPubkey phase0.BLSPubKey, vd ValidatorData, attrs *types.BuilderPayloadAttributes) {
ctx, cancel := context.WithTimeout(slotCtx, 12*time.Second)
defer cancel()

Expand Down Expand Up @@ -471,10 +471,10 @@ func (b *Builder) runBuildingJob(slotCtx context.Context, proposerPubkey boostTy
})
}

func executableDataToExecutionPayload(data *engine.ExecutableData) (*boostTypes.ExecutionPayload, error) {
transactionData := make([]hexutil.Bytes, len(data.Transactions))
func executableDataToExecutionPayload(data *engine.ExecutableData) (*bellatrix.ExecutionPayload, error) {
transactionData := make([]bellatrix.Transaction, len(data.Transactions))
for i, tx := range data.Transactions {
transactionData[i] = hexutil.Bytes(tx)
transactionData[i] = bellatrix.Transaction(tx)
}

baseFeePerGas := new(boostTypes.U256Str)
Expand All @@ -483,13 +483,13 @@ func executableDataToExecutionPayload(data *engine.ExecutableData) (*boostTypes.
return nil, err
}

return &boostTypes.ExecutionPayload{
return &bellatrix.ExecutionPayload{
ParentHash: [32]byte(data.ParentHash),
FeeRecipient: [20]byte(data.FeeRecipient),
StateRoot: [32]byte(data.StateRoot),
ReceiptsRoot: [32]byte(data.ReceiptsRoot),
LogsBloom: boostTypes.Bloom(types.BytesToBloom(data.LogsBloom)),
Random: [32]byte(data.Random),
LogsBloom: types.BytesToBloom(data.LogsBloom),
PrevRandao: [32]byte(data.Random),
BlockNumber: data.Number,
GasLimit: data.GasLimit,
GasUsed: data.GasUsed,
Expand Down Expand Up @@ -528,7 +528,7 @@ func executableDataToCapellaExecutionPayload(data *engine.ExecutableData) (*cape
FeeRecipient: [20]byte(data.FeeRecipient),
StateRoot: [32]byte(data.StateRoot),
ReceiptsRoot: [32]byte(data.ReceiptsRoot),
LogsBloom: boostTypes.Bloom(types.BytesToBloom(data.LogsBloom)),
LogsBloom: types.BytesToBloom(data.LogsBloom),
PrevRandao: [32]byte(data.Random),
BlockNumber: data.Number,
GasLimit: data.GasLimit,
Expand All @@ -541,23 +541,3 @@ func executableDataToCapellaExecutionPayload(data *engine.ExecutableData) (*cape
Withdrawals: withdrawalData,
}, nil
}

func convertBidTrace(bidTrace apiv1.BidTrace) (boostTypes.BidTrace, error) {
value := new(boostTypes.U256Str)
err := value.FromBig(bidTrace.Value.ToBig())
if err != nil {
return boostTypes.BidTrace{}, err
}

return boostTypes.BidTrace{
Slot: bidTrace.Slot,
ParentHash: boostTypes.Hash(bidTrace.ParentHash),
BlockHash: boostTypes.Hash(bidTrace.BlockHash),
BuilderPubkey: boostTypes.PublicKey(bidTrace.BuilderPubkey),
ProposerPubkey: boostTypes.PublicKey(bidTrace.ProposerPubkey),
ProposerFeeRecipient: boostTypes.Address(bidTrace.ProposerFeeRecipient),
GasLimit: bidTrace.GasLimit,
GasUsed: bidTrace.GasUsed,
Value: *value,
}, nil
}
Loading

0 comments on commit b6e031b

Please sign in to comment.