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

Adding features to mempool to support our pre-ordered txs #2

Merged
merged 21 commits into from
Apr 10, 2023
Merged
Show file tree
Hide file tree
Changes from 13 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
4 changes: 4 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ RUN cd /go-ethereum && go run build/ci.go install -static ./cmd/geth
FROM alpine:latest

RUN apk add --no-cache ca-certificates
# Astria - add bash and jq to support start-geth.sh in conductor
RUN apk add bash jq
# Astria - copy genesis.json so it can be used in start-geth.sh
COPY genesis.json /genesis.json
COPY --from=builder /go-ethereum/build/bin/geth /usr/local/bin/

# Astria - add 50051 for GRPC
Expand Down
4 changes: 3 additions & 1 deletion cmd/geth/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/grpc/execution"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/internal/version"
Expand Down Expand Up @@ -174,7 +175,8 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {

// Configure gRPC if requested.
if ctx.IsSet(utils.GRPCEnabledFlag.Name) {
utils.RegisterGRPCService(stack, backend, &cfg.Node)
service := execution.NewExecutionServiceServer(eth)
utils.RegisterGRPCService(stack, service, &cfg.Node)
}

// Add the Ethereum Stats daemon if requested.
Expand Down
9 changes: 4 additions & 5 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb/remotedb"
"github.com/ethereum/go-ethereum/ethstats"
"github.com/ethereum/go-ethereum/graphql"
executionv1 "github.com/ethereum/go-ethereum/grpc/gen/proto/execution/v1"
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/les"
Expand Down Expand Up @@ -2042,9 +2043,7 @@ func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend
Fatalf("Failed to create the LES server: %v", err)
}
}
if err := ethcatalyst.Register(stack, backend); err != nil {
Fatalf("Failed to register the Engine API service: %v", err)
}

stack.RegisterAPIs(tracers.APIs(backend.APIBackend))
return backend.APIBackend, backend
}
Expand All @@ -2066,8 +2065,8 @@ func RegisterGraphQLService(stack *node.Node, backend ethapi.Backend, filterSyst

// RegisterGRPCService adds the gRPC API to the node.
// It was done this way so that our grpc execution server can access the ethapi.Backend
func RegisterGRPCService(stack *node.Node, backend ethapi.Backend, cfg *node.Config) {
if err := node.NewGRPCServerHandler(stack, backend, cfg); err != nil {
func RegisterGRPCService(stack *node.Node, execServer executionv1.ExecutionServiceServer, cfg *node.Config) {
if err := node.NewGRPCServerHandler(stack, execServer, cfg); err != nil {
Fatalf("Failed to register the gRPC service: %v", err)
}
}
Expand Down
1 change: 0 additions & 1 deletion consensus/ethash/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,6 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, pa
}
// Verify the block's difficulty based on its timestamp and parent's difficulty
expected := ethash.CalcDifficulty(chain, header.Time, parent)

if expected.Cmp(header.Difficulty) != 0 {
return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, expected)
}
Expand Down
118 changes: 118 additions & 0 deletions core/txpool/txpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ type TxPool struct {
pendingNonces *noncer // Pending state tracking virtual nonces
currentMaxGas uint64 // Current gas limit for transaction caps

astria *astriaOrdered
locals *accountSet // Set of local transaction to exempt from eviction rules
journal *journal // Journal of local transaction to back up to disk

Expand Down Expand Up @@ -309,6 +310,7 @@ func NewTxPool(config Config, chainconfig *params.ChainConfig, chain blockChain)
reorgShutdownCh: make(chan struct{}),
initDoneCh: make(chan struct{}),
gasPrice: new(big.Int).SetUint64(config.PriceLimit),
//astriaOrdered: newAstriaOrdered(),
}
pool.locals = newAccountSet(pool.signer)
for _, addr := range config.Locals {
Expand Down Expand Up @@ -926,6 +928,108 @@ func (pool *TxPool) AddLocal(tx *types.Transaction) error {
return errs[0]
}

func (pool *TxPool) SetAstriaOrdered(rawTxs [][]byte) {
txs := []*types.Transaction{}
for idx, rawTx := range rawTxs {
tx := new(types.Transaction)
err := tx.UnmarshalBinary(rawTx)
if err != nil {
log.Warn("failed to unmarshal raw astria tx bytes", rawTx, "at index", idx, "error:", err)
continue
}

err = pool.astriaValidate(tx)
if err != nil {
log.Warn("astria tx failed validation at index", idx, "error:", err)
continue
}

txs = append(txs, tx)
}

pool.astria = newAstriaOrdered(types.Transactions(txs))
}

func (pool *TxPool) ClearAstriaOrdered() {
if pool.astria == nil {
return
}
pool.astria.clear()
}

func (pool *TxPool) AstriaOrdered() *types.Transactions {
// sus but whatever
if pool.astria == nil {
return &types.Transactions{}
}
return &pool.astria.txs
}

// validateTx checks whether a transaction is valid according to the consensus
// rules and adheres to some heuristic limits of the local node (price and size).
func (pool *TxPool) astriaValidate(tx *types.Transaction) error {
// Accept only legacy transactions until EIP-2718/2930 activates.
if !pool.eip2718 && tx.Type() != types.LegacyTxType {
return core.ErrTxTypeNotSupported
}
// Reject dynamic fee transactions until EIP-1559 activates.
if !pool.eip1559 && tx.Type() == types.DynamicFeeTxType {
return core.ErrTxTypeNotSupported
}
// Reject transactions over defined size to prevent DOS attacks
if tx.Size() > txMaxSize {
return ErrOversizedData
}
// Check whether the init code size has been exceeded.
if pool.shanghai && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize {
return fmt.Errorf("%w: code size %v limit %v", core.ErrMaxInitCodeSizeExceeded, len(tx.Data()), params.MaxInitCodeSize)
}
// Transactions can't be negative. This may never happen using RLP decoded
// transactions but may occur if you create a transaction using the RPC.
if tx.Value().Sign() < 0 {
return ErrNegativeValue
}
// Ensure the transaction doesn't exceed the current block limit gas.
if pool.currentMaxGas < tx.Gas() {
return ErrGasLimit
}
// Sanity check for extremely large numbers
if tx.GasFeeCap().BitLen() > 256 {
return core.ErrFeeCapVeryHigh
}
if tx.GasTipCap().BitLen() > 256 {
return core.ErrTipVeryHigh
}
// Ensure gasFeeCap is greater than or equal to gasTipCap.
if tx.GasFeeCapIntCmp(tx.GasTipCap()) < 0 {
return core.ErrTipAboveFeeCap
}
// Make sure the transaction is signed properly.
from, err := types.Sender(pool.signer, tx)
if err != nil {
return ErrInvalidSender
}
// Ensure the transaction adheres to nonce ordering
if pool.currentState.GetNonce(from) > tx.Nonce() {
return core.ErrNonceTooLow
}
// Transactor should have enough funds to cover the costs
// cost == V + GP * GL
balance := pool.currentState.GetBalance(from)
if balance.Cmp(tx.Cost()) < 0 {
return core.ErrInsufficientFunds
}
// Ensure the transaction has more gas than the basic tx fee.
intrGas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, true, pool.istanbul, pool.shanghai)
if err != nil {
return err
}
if tx.Gas() < intrGas {
return core.ErrIntrinsicGas
}
return nil
}

// AddRemotes enqueues a batch of transactions into the pool if they are valid. If the
// senders are not among the locally tracked ones, full pricing constraints will apply.
//
Expand Down Expand Up @@ -1647,6 +1751,20 @@ func (a addressesByHeartbeat) Len() int { return len(a) }
func (a addressesByHeartbeat) Less(i, j int) bool { return a[i].heartbeat.Before(a[j].heartbeat) }
func (a addressesByHeartbeat) Swap(i, j int) { a[i], a[j] = a[j], a[i] }

type astriaOrdered struct {
txs types.Transactions
}

func newAstriaOrdered(txs types.Transactions) *astriaOrdered {
return &astriaOrdered{
txs: txs,
}
}

func (ao *astriaOrdered) clear() {
ao.txs = *&types.Transactions{}
}

// accountSet is simply a set of addresses to check for existence, and a signer
// capable of deriving addresses from transactions.
type accountSet struct {
Expand Down
3 changes: 1 addition & 2 deletions eth/api_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import (
"github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/txpool"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/gasprice"
Expand Down Expand Up @@ -311,7 +310,7 @@ func (b *EthAPIBackend) TxPoolContentFrom(addr common.Address) (types.Transactio
return b.eth.TxPool().ContentFrom(addr)
}

func (b *EthAPIBackend) TxPool() *txpool.TxPool {
func (b *EthAPIBackend) TxPool() TxPool {
return b.eth.TxPool()
}

Expand Down
6 changes: 4 additions & 2 deletions eth/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,14 @@ import (
// Deprecated: use ethconfig.Config instead.
type Config = ethconfig.Config

type TxPool = miner.TxPool

// Ethereum implements the Ethereum full node service.
type Ethereum struct {
config *ethconfig.Config

// Handlers
txPool *txpool.TxPool
txPool TxPool
blockchain *core.BlockChain
handler *handler
ethDialCandidates enode.Iterator
Expand Down Expand Up @@ -468,7 +470,7 @@ func (s *Ethereum) Miner() *miner.Miner { return s.miner }

func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager }
func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain }
func (s *Ethereum) TxPool() *txpool.TxPool { return s.txPool }
func (s *Ethereum) TxPool() TxPool { return s.txPool }
func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux }
func (s *Ethereum) Engine() consensus.Engine { return s.engine }
func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb }
Expand Down
39 changes: 20 additions & 19 deletions genesis.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
{
"config": {
"chainId": 1337,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"berlinBlock": 0,
"londonBlock": 0,
"ethash": {}
},
"difficulty": "10000",
"gasLimit": "8000000",
"alloc": {
"0x46B77EFDFB20979E1C29ec98DcE73e3eCbF64102": { "balance": "300000000000000000000" }
}
}
"chainId": 1337,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"berlinBlock": 0,
"londonBlock": 0,
"terminalTotalDifficulty": 0,
"ethash": {}
},
"difficulty": "10000000",
"gasLimit": "8000000",
"alloc": {
"0x46B77EFDFB20979E1C29ec98DcE73e3eCbF64102": { "balance": "300000000000000000000" }
}
}
6 changes: 4 additions & 2 deletions grpc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ brew install leveldb
# build geth
make geth

# run geth
./build/bin/geth --goerli --grpc --grpc.addr "0.0.0.0" --grpc.port 50051
# generating protobuf files
buf generate buf.build/astria/execution-apis
```

See [private_network.md](../private_network.md) for running a local geth node.

### Running with remote Docker image:
```bash
docker run --rm \
Expand Down
Loading