Skip to content

Commit f91e86a

Browse files
joroshibasteezeburgernoot
authored
Adding features to mempool to support our pre-ordered txs (#2)
* Adding features to mempool to support our pre-ordered txs * Add framing for gRPC to execute blocks * Remove public engine API call * Fix circular dependencies * Updated to use new Init, and fill out starting attributes * Add clear astriaordered, cleanup * readme fix * add bash and jq to final docker image * make txpool interface * no more panics, update DoBlock to also update state + store block * cleanup * set post-merge at genesis * cleanup * doc update * remove txpool interface changes * cleanup * cleanup * build and push images wih tags defined by git tags * build for multiple architectures. use docker-metadata action for semver * add push: true * only build arm for git tags/releases --------- Co-authored-by: Jesse Snyder <jessetsnyder@gmail.com> Co-authored-by: elizabeth <elizabethjbinks@gmail.com>
1 parent 5ec91e0 commit f91e86a

File tree

15 files changed

+607
-143
lines changed

15 files changed

+607
-143
lines changed
Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,59 @@
11
name: Build and Publish Docker image
2+
3+
# Trigger on pushes to astria branch, new semantic version tags, and pull request updates
24
on:
35
workflow_dispatch:
46
push:
57
branches:
6-
- astria # Running this job only for astria branch
8+
- "astria"
9+
tags:
10+
- "v[0-9]+.[0-9]+.[0-9]+"
11+
- "v[0-9]+.[0-9]+.[0-9]+-alpha.[0-9]+"
12+
- "v[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+"
13+
- "v[0-9]+.[0-9]+.[0-9]+-rc[0-9]+"
14+
# trigger on pull request updates when target is `astria` branch
15+
pull_request:
16+
branches:
17+
- "astria"
18+
719
jobs:
820
build-and-publish-latest:
921
runs-on: ubuntu-latest
1022
steps:
11-
- uses: actions/checkout@v2 # Checking out the repo
23+
# Checking out the repo
24+
- uses: actions/checkout@v2
25+
# Setting up Go
1226
- uses: actions/setup-go@v4
1327
with:
1428
go-version: "^1.20.x" # The Go version to download (if necessary) and use.
1529
- run: go version
1630

31+
# https://github.com/docker/setup-qemu-action
32+
- name: Set up QEMU
33+
uses: docker/setup-qemu-action@v1
34+
# https://github.com/docker/setup-buildx-action
35+
- name: Set up Docker Buildx
36+
id: buildx
37+
uses: docker/setup-buildx-action@v1
1738
- name: Log in to registry
1839
run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u $ --password-stdin
19-
20-
# TODO - build for amd64 and arm64?
21-
# FIXME - version needs to be autoincrement, probably from git tags?
22-
- name: Build latest Docker image
23-
run: |
24-
docker build \
25-
--build-arg COMMIT=${GITHUB_SHA} \
26-
--build-arg VERSION=0.1 \
27-
--build-arg BUILDNUM=${GITHUB_RUN_NUMBER} \
28-
--tag ghcr.io/astriaorg/go-ethereum:latest .
29-
- name: Push latest Docker image
30-
run: docker push ghcr.io/astriaorg/go-ethereum:latest
40+
# Generate correct tabs and labels
41+
- name: Docker metadata
42+
id: metadata
43+
uses: docker/metadata-action@v4
44+
with:
45+
images: |
46+
ghcr.io/astriaorg/go-ethereum
47+
tags: |
48+
type=ref,event=pr
49+
type=semver,pattern={{major}}.{{minor}}.{{patch}}
50+
type=sha
51+
- name: Build and push
52+
uses: docker/build-push-action@v2
53+
with:
54+
context: .
55+
# It takes over 30 minutes to build the arm image right now, so we only build it on tags which is what we use for releases.
56+
platforms: ${{ contains(github.ref, 'refs/tags/v') && 'linux/amd64,linux/arm64' || 'linux/amd64' }}
57+
push: true
58+
tags: ${{ steps.metadata.outputs.tags }}
59+
labels: ${{ steps.metadata.outputs.labels }}

Dockerfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ RUN cd /go-ethereum && go run build/ci.go install -static ./cmd/geth
2020
FROM alpine:latest
2121

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

2529
# Astria - add 50051 for GRPC

cmd/geth/config.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"github.com/ethereum/go-ethereum/cmd/utils"
3434
"github.com/ethereum/go-ethereum/eth/downloader"
3535
"github.com/ethereum/go-ethereum/eth/ethconfig"
36+
"github.com/ethereum/go-ethereum/grpc/execution"
3637
"github.com/ethereum/go-ethereum/internal/ethapi"
3738
"github.com/ethereum/go-ethereum/internal/flags"
3839
"github.com/ethereum/go-ethereum/internal/version"
@@ -174,7 +175,8 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
174175

175176
// Configure gRPC if requested.
176177
if ctx.IsSet(utils.GRPCEnabledFlag.Name) {
177-
utils.RegisterGRPCService(stack, backend, &cfg.Node)
178+
service := execution.NewExecutionServiceServer(eth)
179+
utils.RegisterGRPCService(stack, service, &cfg.Node)
178180
}
179181

180182
// Add the Ethereum Stats daemon if requested.

cmd/utils/flags.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import (
5757
"github.com/ethereum/go-ethereum/ethdb/remotedb"
5858
"github.com/ethereum/go-ethereum/ethstats"
5959
"github.com/ethereum/go-ethereum/graphql"
60+
executionv1 "github.com/ethereum/go-ethereum/grpc/gen/proto/execution/v1"
6061
"github.com/ethereum/go-ethereum/internal/ethapi"
6162
"github.com/ethereum/go-ethereum/internal/flags"
6263
"github.com/ethereum/go-ethereum/les"
@@ -2042,9 +2043,7 @@ func RegisterEthService(stack *node.Node, cfg *ethconfig.Config) (ethapi.Backend
20422043
Fatalf("Failed to create the LES server: %v", err)
20432044
}
20442045
}
2045-
if err := ethcatalyst.Register(stack, backend); err != nil {
2046-
Fatalf("Failed to register the Engine API service: %v", err)
2047-
}
2046+
20482047
stack.RegisterAPIs(tracers.APIs(backend.APIBackend))
20492048
return backend.APIBackend, backend
20502049
}
@@ -2066,8 +2065,8 @@ func RegisterGraphQLService(stack *node.Node, backend ethapi.Backend, filterSyst
20662065

20672066
// RegisterGRPCService adds the gRPC API to the node.
20682067
// It was done this way so that our grpc execution server can access the ethapi.Backend
2069-
func RegisterGRPCService(stack *node.Node, backend ethapi.Backend, cfg *node.Config) {
2070-
if err := node.NewGRPCServerHandler(stack, backend, cfg); err != nil {
2068+
func RegisterGRPCService(stack *node.Node, execServer executionv1.ExecutionServiceServer, cfg *node.Config) {
2069+
if err := node.NewGRPCServerHandler(stack, execServer, cfg); err != nil {
20712070
Fatalf("Failed to register the gRPC service: %v", err)
20722071
}
20732072
}

consensus/ethash/consensus.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,6 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainHeaderReader, header, pa
281281
}
282282
// Verify the block's difficulty based on its timestamp and parent's difficulty
283283
expected := ethash.CalcDifficulty(chain, header.Time, parent)
284-
285284
if expected.Cmp(header.Difficulty) != 0 {
286285
return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, expected)
287286
}

core/txpool/txpool.go

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ type TxPool struct {
259259
pendingNonces *noncer // Pending state tracking virtual nonces
260260
currentMaxGas uint64 // Current gas limit for transaction caps
261261

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

@@ -926,6 +927,108 @@ func (pool *TxPool) AddLocal(tx *types.Transaction) error {
926927
return errs[0]
927928
}
928929

930+
func (pool *TxPool) SetAstriaOrdered(rawTxs [][]byte) {
931+
txs := []*types.Transaction{}
932+
for idx, rawTx := range rawTxs {
933+
tx := new(types.Transaction)
934+
err := tx.UnmarshalBinary(rawTx)
935+
if err != nil {
936+
log.Warn("failed to unmarshal raw astria tx bytes", rawTx, "at index", idx, "error:", err)
937+
continue
938+
}
939+
940+
err = pool.astriaValidate(tx)
941+
if err != nil {
942+
log.Warn("astria tx failed validation at index", idx, "error:", err)
943+
continue
944+
}
945+
946+
txs = append(txs, tx)
947+
}
948+
949+
pool.astria = newAstriaOrdered(types.Transactions(txs))
950+
}
951+
952+
func (pool *TxPool) ClearAstriaOrdered() {
953+
if pool.astria == nil {
954+
return
955+
}
956+
pool.astria.clear()
957+
}
958+
959+
func (pool *TxPool) AstriaOrdered() *types.Transactions {
960+
// sus but whatever
961+
if pool.astria == nil {
962+
return &types.Transactions{}
963+
}
964+
return &pool.astria.txs
965+
}
966+
967+
// validateTx checks whether a transaction is valid according to the consensus
968+
// rules and adheres to some heuristic limits of the local node (price and size).
969+
func (pool *TxPool) astriaValidate(tx *types.Transaction) error {
970+
// Accept only legacy transactions until EIP-2718/2930 activates.
971+
if !pool.eip2718 && tx.Type() != types.LegacyTxType {
972+
return core.ErrTxTypeNotSupported
973+
}
974+
// Reject dynamic fee transactions until EIP-1559 activates.
975+
if !pool.eip1559 && tx.Type() == types.DynamicFeeTxType {
976+
return core.ErrTxTypeNotSupported
977+
}
978+
// Reject transactions over defined size to prevent DOS attacks
979+
if tx.Size() > txMaxSize {
980+
return ErrOversizedData
981+
}
982+
// Check whether the init code size has been exceeded.
983+
if pool.shanghai && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize {
984+
return fmt.Errorf("%w: code size %v limit %v", core.ErrMaxInitCodeSizeExceeded, len(tx.Data()), params.MaxInitCodeSize)
985+
}
986+
// Transactions can't be negative. This may never happen using RLP decoded
987+
// transactions but may occur if you create a transaction using the RPC.
988+
if tx.Value().Sign() < 0 {
989+
return ErrNegativeValue
990+
}
991+
// Ensure the transaction doesn't exceed the current block limit gas.
992+
if pool.currentMaxGas < tx.Gas() {
993+
return ErrGasLimit
994+
}
995+
// Sanity check for extremely large numbers
996+
if tx.GasFeeCap().BitLen() > 256 {
997+
return core.ErrFeeCapVeryHigh
998+
}
999+
if tx.GasTipCap().BitLen() > 256 {
1000+
return core.ErrTipVeryHigh
1001+
}
1002+
// Ensure gasFeeCap is greater than or equal to gasTipCap.
1003+
if tx.GasFeeCapIntCmp(tx.GasTipCap()) < 0 {
1004+
return core.ErrTipAboveFeeCap
1005+
}
1006+
// Make sure the transaction is signed properly.
1007+
from, err := types.Sender(pool.signer, tx)
1008+
if err != nil {
1009+
return ErrInvalidSender
1010+
}
1011+
// Ensure the transaction adheres to nonce ordering
1012+
if pool.currentState.GetNonce(from) > tx.Nonce() {
1013+
return core.ErrNonceTooLow
1014+
}
1015+
// Transactor should have enough funds to cover the costs
1016+
// cost == V + GP * GL
1017+
balance := pool.currentState.GetBalance(from)
1018+
if balance.Cmp(tx.Cost()) < 0 {
1019+
return core.ErrInsufficientFunds
1020+
}
1021+
// Ensure the transaction has more gas than the basic tx fee.
1022+
intrGas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil, true, pool.istanbul, pool.shanghai)
1023+
if err != nil {
1024+
return err
1025+
}
1026+
if tx.Gas() < intrGas {
1027+
return core.ErrIntrinsicGas
1028+
}
1029+
return nil
1030+
}
1031+
9291032
// AddRemotes enqueues a batch of transactions into the pool if they are valid. If the
9301033
// senders are not among the locally tracked ones, full pricing constraints will apply.
9311034
//
@@ -1647,6 +1750,20 @@ func (a addressesByHeartbeat) Len() int { return len(a) }
16471750
func (a addressesByHeartbeat) Less(i, j int) bool { return a[i].heartbeat.Before(a[j].heartbeat) }
16481751
func (a addressesByHeartbeat) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
16491752

1753+
type astriaOrdered struct {
1754+
txs types.Transactions
1755+
}
1756+
1757+
func newAstriaOrdered(txs types.Transactions) *astriaOrdered {
1758+
return &astriaOrdered{
1759+
txs: txs,
1760+
}
1761+
}
1762+
1763+
func (ao *astriaOrdered) clear() {
1764+
ao.txs = *&types.Transactions{}
1765+
}
1766+
16501767
// accountSet is simply a set of addresses to check for existence, and a signer
16511768
// capable of deriving addresses from transactions.
16521769
type accountSet struct {

genesis.json

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
{
22
"config": {
3-
"chainId": 1337,
4-
"homesteadBlock": 0,
5-
"eip150Block": 0,
6-
"eip155Block": 0,
7-
"eip158Block": 0,
8-
"byzantiumBlock": 0,
9-
"constantinopleBlock": 0,
10-
"petersburgBlock": 0,
11-
"istanbulBlock": 0,
12-
"berlinBlock": 0,
13-
"londonBlock": 0,
14-
"ethash": {}
15-
},
16-
"difficulty": "10000",
17-
"gasLimit": "8000000",
18-
"alloc": {
19-
"0x46B77EFDFB20979E1C29ec98DcE73e3eCbF64102": { "balance": "300000000000000000000" }
20-
}
21-
}
3+
"chainId": 1337,
4+
"homesteadBlock": 0,
5+
"eip150Block": 0,
6+
"eip155Block": 0,
7+
"eip158Block": 0,
8+
"byzantiumBlock": 0,
9+
"constantinopleBlock": 0,
10+
"petersburgBlock": 0,
11+
"istanbulBlock": 0,
12+
"berlinBlock": 0,
13+
"londonBlock": 0,
14+
"terminalTotalDifficulty": 0,
15+
"ethash": {}
16+
},
17+
"difficulty": "10000000",
18+
"gasLimit": "8000000",
19+
"alloc": {
20+
"0x46B77EFDFB20979E1C29ec98DcE73e3eCbF64102": { "balance": "300000000000000000000" }
21+
}
22+
}

grpc/README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ brew install leveldb
88
# build geth
99
make geth
1010

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

15+
See [private_network.md](../private_network.md) for running a local geth node.
16+
1517
### Running with remote Docker image:
1618
```bash
1719
docker run --rm \

0 commit comments

Comments
 (0)