Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Trusted builder MVP #39

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions core/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,7 @@ var (

// ErrBlobTxCreate is returned if a blob transaction has no explicit to field.
ErrBlobTxCreate = errors.New("blob transaction of type create")

// ErrTxReverted is returned if a transaction is reverted.
ErrTxReverted = errors.New("transaction reverted")
)
7 changes: 3 additions & 4 deletions eth/tracers/live/noop.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,12 @@ func (t *noop) OnTxStart(vm *tracing.VMContext, tx *types.Transaction, from comm
}

func (t *noop) OnTxEnd(receipt *types.Receipt, err error) {
}

func (t *noop) OnBlockStart(ev tracing.BlockEvent) {
}

func (t *noop) OnBlockEnd(err error) {
}
func (t *noop) OnBlockStart(ev tracing.BlockEvent) {}

func (t *noop) OnBlockEnd(err error) {}

func (t *noop) OnSkippedBlock(ev tracing.BlockEvent) {}

Expand Down
24 changes: 12 additions & 12 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ module github.com/ethereum/go-ethereum
go 1.21

require (
buf.build/gen/go/astria/execution-apis/grpc/go v1.4.0-20240627184145-202c666b5a8a.2
buf.build/gen/go/astria/execution-apis/protocolbuffers/go v1.34.2-20240723183210-193b02425a52.2
buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240723183210-d00b2a17ea5b.2
buf.build/gen/go/astria/sequencerblock-apis/protocolbuffers/go v1.34.2-20240723183210-414756da3320.2
buf.build/gen/go/astria/composer-apis/protocolbuffers/go v1.34.2-00000000000000-bf2928746fde.2
buf.build/gen/go/astria/execution-apis/grpc/go v1.5.1-00000000000000-cdc3a35f6a0c.1
buf.build/gen/go/astria/execution-apis/protocolbuffers/go v1.34.2-20240801092317-cdc3a35f6a0c.2
buf.build/gen/go/astria/primitives/protocolbuffers/go v1.34.2-20240807170122-b074164339d1.2
buf.build/gen/go/astria/sequencerblock-apis/protocolbuffers/go v1.34.2-20240807170122-24ff5bcd4581.2
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.2.0
github.com/Microsoft/go-winio v0.6.1
github.com/VictoriaMetrics/fastcache v1.12.1
Expand Down Expand Up @@ -72,21 +73,20 @@ require (
github.com/tyler-smith/go-bip39 v1.1.0
github.com/urfave/cli/v2 v2.25.7
go.uber.org/automaxprocs v1.5.2
golang.org/x/crypto v0.22.0
golang.org/x/crypto v0.24.0
golang.org/x/sync v0.7.0
golang.org/x/sys v0.19.0
golang.org/x/text v0.14.0
golang.org/x/sys v0.21.0
golang.org/x/text v0.16.0
golang.org/x/time v0.5.0
golang.org/x/tools v0.20.0
google.golang.org/grpc v1.64.0
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d
google.golang.org/grpc v1.64.1
google.golang.org/protobuf v1.34.2
gopkg.in/natefinch/lumberjack.v2 v2.0.0
gopkg.in/yaml.v3 v3.0.1
)

require (
buf.build/gen/go/astria/protocol-apis/grpc/go v1.4.0-00000000000000-71710707f61c.2 // indirect
buf.build/gen/go/astria/protocol-apis/protocolbuffers/go v1.34.2-20240723183210-71710707f61c.2 // indirect
buf.build/gen/go/astria/composer-apis/grpc/go v1.4.0-20240528191859-5569d2ee7204.1 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.7.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect
github.com/DataDog/zstd v1.4.5 // indirect
Expand Down Expand Up @@ -151,7 +151,7 @@ require (
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/net v0.26.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240318140521-94a12d6c2237 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
Expand Down
91 changes: 40 additions & 51 deletions go.sum

Large diffs are not rendered by default.

152 changes: 131 additions & 21 deletions grpc/execution/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
package execution

import (
composerv1alpha1 "buf.build/gen/go/astria/composer-apis/protocolbuffers/go/astria/composer/v1alpha1"
sequencerblockv1alpha1 "buf.build/gen/go/astria/sequencerblock-apis/protocolbuffers/go/astria/sequencerblock/v1alpha1"
"bytes"
"context"
"crypto/sha256"
"errors"
Expand Down Expand Up @@ -222,11 +225,45 @@ func protoU128ToBigInt(u128 *primitivev1.Uint128) *big.Int {
return lo.Add(lo, hi)
}

func unbundleBuilderBundlePacket(
builderBundlePacket *composerv1alpha1.BuilderBundlePacket,
parentHash []byte,
height uint64,
bridgeAddresses map[string]*params.AstriaBridgeAddressConfig,
bridgeAllowedAssets map[string]struct{},
bridgeSenderAddress common.Address,
) (types.Transactions, error) {
if builderBundlePacket == nil {
return types.Transactions{}, nil
}

builderBundle := builderBundlePacket.GetBundle()
if bytes.Compare(builderBundle.GetParentHash(), parentHash) != 0 {
log.Error("parent hash does not match parent hash of the block", "parentHash", common.BytesToHash(parentHash).Hex(), "bundleParentHash", common.BytesToHash(builderBundlePacket.GetBundle().GetParentHash()).Hex())
return types.Transactions{}, nil
}

// TODO - bundle signature verification

ethTxs := types.Transactions{}
for _, tx := range builderBundlePacket.GetBundle().GetTransactions() {
ethTx, err := validateAndUnmarshalTx(height, tx, bridgeAddresses, bridgeAllowedAssets, bridgeSenderAddress)
if err != nil {
return nil, err
}

ethTxs = append(ethTxs, ethTx)
}

return ethTxs, nil
}

// ExecuteBlock drives deterministic derivation of a rollup block from sequencer
// block data
func (s *ExecutionServiceServerV1Alpha2) ExecuteBlock(ctx context.Context, req *astriaPb.ExecuteBlockRequest) (*astriaPb.Block, error) {
log.Debug("ExecuteBlock called", "prevBlockHash", common.BytesToHash(req.PrevBlockHash), "tx_count", len(req.Transactions), "timestamp", req.Timestamp)
func (s *ExecutionServiceServerV1Alpha2) ExecuteBlock(ctx context.Context, req *astriaPb.ExecuteBlockRequest) (*astriaPb.ExecuteBlockResponse, error) {
log.Info("Trusted Builder ExecuteBlock called", "prevBlockHash", common.BytesToHash(req.PrevBlockHash), "tx_count", len(req.Transactions), "timestamp", req.Timestamp)
executeBlockRequestCount.Inc(1)
log.Info("Mode is set to", "simulateOnly", req.GetSimulateOnly())

s.blockExecutionLock.Lock()
defer s.blockExecutionLock.Unlock()
Expand All @@ -248,18 +285,34 @@ func (s *ExecutionServiceServerV1Alpha2) ExecuteBlock(ctx context.Context, req *
// the height that this block will be at
height := s.bc.CurrentBlock().Number.Uint64() + 1

txsToProcess := types.Transactions{}
for _, tx := range req.Transactions {
unmarshalledTx, err := validateAndUnmarshalSequencerTx(height, tx, s.bridgeAddresses, s.bridgeAllowedAssets, s.bridgeSenderAddress)
if err != nil {
log.Debug("failed to validate sequencer tx, ignoring", "tx", tx, "err", err)
continue
}
txsToProcess = append(txsToProcess, unmarshalledTx)
log.Info("Extracting builder bundle and other txs")
builderBundlePacket, ethTxs, depositTxMapping, err := extractBuilderBundleAndTxs(req.Transactions, height, s.bridgeAddresses, s.bridgeAllowedAssets, s.bridgeSenderAddress)
if err != nil {
log.Error("failed to extract builder bundle and txs", "err", err)
return nil, status.Error(codes.InvalidArgument, "Could not extract builder bundle and txs")
}
if req.GetSimulateOnly() && builderBundlePacket != nil {
return nil, status.Error(codes.InvalidArgument, "bundle simulation is not supported for builder bundle packets")
}
if builderBundlePacket == nil {
log.Info("No builder bundle packet found")
} else {
log.Info("Builder bundle packet found")
log.Info("Unbundling the builder bundle packet", "simulateOnly", req.GetSimulateOnly())
}

tobTxs, err := unbundleBuilderBundlePacket(builderBundlePacket, req.PrevBlockHash, height, s.bridgeAddresses, s.bridgeAllowedAssets, s.bridgeSenderAddress)
if err != nil {
log.Error("failed to unbundle builder bundle packet", "err", err)
return nil, status.Error(codes.InvalidArgument, "Could not unbundle builder bundle packet")
}
if builderBundlePacket != nil {
log.Info("Unbundled the builder bundle packet", "tx_count", len(tobTxs))
}

// This set of ordered TXs on the TxPool is has been configured to be used by
// the Miner when building a payload.
txsToProcess := append(tobTxs, ethTxs...)
log.Info("Total txs to process", "tx_count", len(txsToProcess))

s.eth.TxPool().SetAstriaOrdered(txsToProcess)

// Build a payload to add to the chain
Expand All @@ -269,29 +322,81 @@ func (s *ExecutionServiceServerV1Alpha2) ExecuteBlock(ctx context.Context, req *
Random: common.Hash{},
FeeRecipient: s.nextFeeRecipient,
}
log.Info("Building payload")
payload, err := s.eth.Miner().BuildPayload(payloadAttributes)
if err != nil {
log.Error("failed to build payload", "err", err)
return nil, status.Error(codes.InvalidArgument, "Could not build block with provided txs")
}
log.Info("Built payload!")

// call blockchain.InsertChain to actually execute and write the blocks to
// state
log.Info("Extracting block out of payload!")
block, err := engine.ExecutableDataToBlock(*payload.Resolve().ExecutionPayload, nil, nil)
if err != nil {
log.Error("failed to convert executable data to block", err)
return nil, status.Error(codes.Internal, "failed to execute block")
}
err = s.bc.InsertBlockWithoutSetHead(block)
if err != nil {
log.Error("failed to insert block to chain", "hash", block.Hash(), "prevHash", req.PrevBlockHash, "err", err)
return nil, status.Error(codes.Internal, "failed to insert block to chain")
log.Info("Extracted block out of payload!")

log.Info("Building included_transactions list by removing txs which are in the list of AstriaExcludedTxs")
excludedTransactions := s.eth.TxPool().AstriaExcludedFromBlock()
includedTransactions := make([]*sequencerblockv1alpha1.RollupData, 0, len(block.Transactions()))
log.Info("excluded txs", "count", len(*excludedTransactions))
for _, blockTx := range block.Transactions() {
// ensure blockTx is not in excludedTxs
found := false
for _, tx := range *excludedTransactions {
if tx.Hash() == tx.Hash() {
found = true
log.Error("tx found in excluded txs", "blockTx hash", tx.Hash().Hex())
break
}
}
if found {
// ignore tx which has been excluded
continue
}

if blockTx.Type() == types.DepositTxType {
depositTx, ok := depositTxMapping[blockTx.Hash().Hex()]
if !ok {
log.Error("deposit blockTx not found in depositTxMapping", "blockTx hash", blockTx.Hash().Hex())
return nil, status.Error(codes.Internal, "deposit blockTx not found in depositTxMapping")
}

includedTransactions = append(includedTransactions, &sequencerblockv1alpha1.RollupData{Value: &sequencerblockv1alpha1.RollupData_Deposit{Deposit: depositTx}})

} else {
marshalledTx, err := blockTx.MarshalBinary()
if err != nil {
log.Error("failed to marshal transaction", "err", err)
return nil, status.Error(codes.Internal, "failed to marshal transaction")
}
includedTransactions = append(includedTransactions, &sequencerblockv1alpha1.RollupData{
Value: &sequencerblockv1alpha1.RollupData_SequencedData{SequencedData: marshalledTx},
})
}
}
log.Info("Built included tx list", "count", len(includedTransactions))

// we do not insert the block to the chain if we just want to simulate the transactions
if !req.GetSimulateOnly() {
log.Info("Inserting block to chain")
err = s.bc.InsertBlockWithoutSetHead(block)
if err != nil {
log.Error("failed to insert block to chain", "hash", block.Hash(), "prevHash", req.PrevBlockHash, "err", err)
return nil, status.Error(codes.Internal, "failed to insert block to chain")
}
} else {
log.Info("Skipping inserting block to chain as simulateOnly is set")
}

// remove txs from original mempool
s.eth.TxPool().ClearAstriaOrdered()

res := &astriaPb.Block{
finalBlock := &astriaPb.Block{
Number: uint32(block.NumberU64()),
Hash: block.Hash().Bytes(),
ParentBlockHash: block.ParentHash().Bytes(),
Expand All @@ -300,11 +405,16 @@ func (s *ExecutionServiceServerV1Alpha2) ExecuteBlock(ctx context.Context, req *
},
}

if next, ok := s.bc.Config().AstriaFeeCollectors[res.Number+1]; ok {
if next, ok := s.bc.Config().AstriaFeeCollectors[finalBlock.Number+1]; ok {
s.nextFeeRecipient = next
}

log.Info("ExecuteBlock completed", "block_num", res.Number, "timestamp", res.Timestamp)
res := &astriaPb.ExecuteBlockResponse{
Block: finalBlock,
IncludedTransactions: includedTransactions,
}

log.Info("Trusted Builder ExecuteBlock completed", "block_num", res.GetBlock().Number, "timestamp", res.GetBlock().Timestamp)
totalExecutedTxCount.Inc(int64(len(block.Transactions())))
executeBlockSuccessCount.Inc(1)
return res, nil
Expand Down Expand Up @@ -334,7 +444,7 @@ func (s *ExecutionServiceServerV1Alpha2) GetCommitmentState(ctx context.Context,
BaseCelestiaHeight: celestiaBlock,
}

log.Info("GetCommitmentState completed", "soft_height", res.Soft.Number, "firm_height", res.Firm.Number, "base_celestia_height", res.BaseCelestiaHeight)
log.Debug("GetCommitmentState completed", "soft_height", res.Soft.Number, "firm_height", res.Firm.Number, "base_celestia_height", res.BaseCelestiaHeight)
getCommitmentStateSuccessCount.Inc(1)
s.getCommitmentStateCalled = true
return res, nil
Expand Down Expand Up @@ -410,7 +520,7 @@ func (s *ExecutionServiceServerV1Alpha2) UpdateCommitmentState(ctx context.Conte
s.bc.SetCelestiaFinalized(firmBlock.Header(), req.CommitmentState.BaseCelestiaHeight)
}

log.Info("UpdateCommitmentState completed", "soft_height", softBlock.NumberU64(), "firm_height", firmBlock.NumberU64())
log.Debug("UpdateCommitmentState completed", "soft_height", softBlock.NumberU64(), "firm_height", firmBlock.NumberU64())
softCommitmentHeight.Update(int64(softBlock.NumberU64()))
firmCommitmentHeight.Update(int64(firmBlock.NumberU64()))
updateCommitmentStateSuccessCount.Inc(1)
Expand Down
Loading
Loading