From 4fdb66784271c486d0e409d07519310c9daf7ef5 Mon Sep 17 00:00:00 2001 From: Jesse Snyder Date: Mon, 17 Apr 2023 15:21:12 -0600 Subject: [PATCH 1/4] add and remove tx from geth mempool so forge can deploy a contract --- cmd/utils/flags.go | 26 ++++++++++++++++++++++++++ core/txpool/txpool.go | 8 ++++++++ grpc/execution/server.go | 7 +++++++ internal/ethapi/api.go | 12 +++++++++++- internal/ethapi/metro.go | 14 ++++++++++++-- node/config.go | 5 +++++ node/defaults.go | 5 +++++ 7 files changed, 74 insertions(+), 3 deletions(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index b61a9b78634b..51f87cef539c 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -811,6 +811,20 @@ var ( Category: flags.APICategory, } + // Metro grpc address and port overrides + MetroGRPCHostFlag = &cli.StringFlag{ + Name: "metro.grpc.addr", + Usage: "Metro gRPC server listening interface", + Value: node.DefaultMetroGRPCHost, + Category: flags.APICategory, + } + MetroGRPCPortFlag = &cli.IntFlag{ + Name: "metro.grpc.port", + Usage: "Metro gRPC server listening port", + Value: node.DefaultMetroGRPCPort, + Category: flags.APICategory, + } + // Network Settings MaxPeersFlag = &cli.IntFlag{ Name: "maxpeers", @@ -1243,6 +1257,17 @@ func setGRPC(ctx *cli.Context, cfg *node.Config) { } } +// setMetro creates the Metro RPC listener interface string from the set command +// line flags, returning empty if the Metro endpoint is disabled. +func setMetro(ctx *cli.Context, cfg *node.Config) { + if ctx.IsSet(MetroGRPCHostFlag.Name) { + cfg.MetroGRPCHost = ctx.String(MetroGRPCHostFlag.Name) + } + if ctx.IsSet(MetroGRPCPortFlag.Name) { + cfg.MetroGRPCPort = ctx.Int(MetroGRPCPortFlag.Name) + } +} + // setGraphQL creates the GraphQL listener interface string from the set // command line flags, returning empty if the GraphQL endpoint is disabled. func setGraphQL(ctx *cli.Context, cfg *node.Config) { @@ -1493,6 +1518,7 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { setIPC(ctx, cfg) setHTTP(ctx, cfg) setGRPC(ctx, cfg) + setMetro(ctx, cfg) setGraphQL(ctx, cfg) setWS(ctx, cfg) setNodeUserIdent(ctx, cfg) diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go index 8597f6190f65..c179593e18cc 100644 --- a/core/txpool/txpool.go +++ b/core/txpool/txpool.go @@ -1043,6 +1043,14 @@ func (pool *TxPool) AddRemotesSync(txs []*types.Transaction) []error { return pool.addTxs(txs, false, true) } +// Remove a single transaction from the mempool. +func (pool *TxPool) RemoveTx(hash common.Hash) { + pool.mu.Lock() + defer pool.mu.Unlock() + + pool.removeTx(hash, false) +} + // This is like AddRemotes with a single transaction, but waits for pool reorganization. Tests use this method. func (pool *TxPool) addRemoteSync(tx *types.Transaction) error { errs := pool.AddRemotesSync([]*types.Transaction{tx}) diff --git a/grpc/execution/server.go b/grpc/execution/server.go index 11b7f39e82d0..c94bee5a5f1a 100644 --- a/grpc/execution/server.go +++ b/grpc/execution/server.go @@ -92,6 +92,13 @@ func (s *ExecutionServiceServer) DoBlock(ctx context.Context, req *executionv1.D return nil, fmt.Errorf("failed to insert block into blockchain (n=%d)", n) } + // TODO - remove txs from original mempool + for _, block := range blocks { + for _, tx := range block.Transactions() { + s.eth.TxPool().RemoveTx(tx.Hash()) + } + } + newForkChoice := &engine.ForkchoiceStateV1{ HeadBlockHash: block.Hash(), SafeBlockHash: block.Hash(), diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 8b5d1893a2aa..35528bb5d033 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1577,6 +1577,7 @@ func (s *TransactionAPI) GetTransactionCount(ctx context.Context, address common func (s *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (*RPCTransaction, error) { // Try to return an already finalized transaction tx, blockHash, blockNumber, index, err := s.b.GetTransaction(ctx, hash) + log.Info("GetTransactionByHash", "tx", tx, "blockHash", blockHash, "blockNumber", blockNumber, "index", index, "err", err) if err != nil { return nil, err } @@ -1589,10 +1590,12 @@ func (s *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.H } // No finalized transaction, try to retrieve it from the pool if tx := s.b.GetPoolTransaction(hash); tx != nil { + log.Info("Transaction found in pool", "hash", hash) return NewRPCPendingTransaction(tx, s.b.CurrentHeader(), s.b.ChainConfig()), nil } // Transaction unknown, return as such + log.Info("Transaction not found", "hash", hash) return nil, nil } @@ -1694,12 +1697,19 @@ func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (c return common.Hash{}, errors.New("only replay-protected (EIP-155) transactions allowed over RPC") } + // save transaction in geth mempool as well, so things like forge can look it up + if err := b.SendTx(ctx, tx); err != nil { + return common.Hash{}, err + } + // send to metro instead of eth mempool txBytes, err := tx.MarshalBinary() if err != nil { return common.Hash{}, err } - if err := submitMetroTransaction(txBytes); err != nil { + // FIXME - address should come from cli flags + metro_api := NewMetroAPI("192.167.10.40:9090") + if err := metro_api.SubmitTransaction(txBytes); err != nil { return common.Hash{}, err } diff --git a/internal/ethapi/metro.go b/internal/ethapi/metro.go index 9e8de1efc685..ec9c4342ef20 100644 --- a/internal/ethapi/metro.go +++ b/internal/ethapi/metro.go @@ -2,10 +2,20 @@ package ethapi import ( metrotx "github.com/astriaorg/metro-transactions/tx" + "github.com/ethereum/go-ethereum/log" ) const secondaryChainID = "ethereum" -func submitMetroTransaction(tx []byte) error { - return metrotx.BuildAndSendSecondaryTransaction(metrotx.DefaultGRPCEndpoint, secondaryChainID, tx) +type MetroAPI struct { + endpoint string +} + +func NewMetroAPI(endpoint string) *MetroAPI { + log.Info("NewMetroAPI", "endpoint", endpoint) + return &MetroAPI{endpoint: endpoint} +} + +func (api *MetroAPI) SubmitTransaction(tx []byte) error { + return metrotx.BuildAndSendSecondaryTransaction(api.endpoint, secondaryChainID, tx) } diff --git a/node/config.go b/node/config.go index 6be260efbfcd..a26a89c54e6c 100644 --- a/node/config.go +++ b/node/config.go @@ -195,6 +195,11 @@ type Config struct { // GRPCPort is the TCP port number on which to start the gRPC server. GRPCPort int `toml:",omitempty"` + // MetroGRPCHost is the address of the Metro grpc server. + MetroGRPCHost string `toml:",omitempty"` + // MetroGRPCPort is the port of the Metro grpc server. + MetroGRPCPort int `toml:",omitempty"` + // Logger is a custom logger to use with the p2p.Server. Logger log.Logger `toml:",omitempty"` diff --git a/node/defaults.go b/node/defaults.go index 42c339a0c942..b1a6ea05aa65 100644 --- a/node/defaults.go +++ b/node/defaults.go @@ -36,9 +36,14 @@ const ( DefaultGraphQLPort = 8547 // Default TCP port for the GraphQL server DefaultAuthHost = "localhost" // Default host interface for the authenticated apis DefaultAuthPort = 8551 // Default port for the authenticated apis + // grpc DefaultGRPCHost = "[::1]" // Default host interface for the gRPC server DefaultGRPCPort = 50051 // Default port for the gRPC server + + // metro + DefaultMetroGRPCHost = "127.0.0.1" // Default host interface for the metro gRPC server + DefaultMetroGRPCPort = 9090 // Default port for the metro gRPC server ) var ( From 5e07a48780ff43f90283bd24bef5ee1f5d1bcb41 Mon Sep 17 00:00:00 2001 From: Jesse Snyder Date: Wed, 19 Apr 2023 17:28:42 -0600 Subject: [PATCH 2/4] pass metro addr and port by flag --- cmd/geth/main.go | 6 +++++ cmd/utils/flags.go | 28 ++++++++++-------------- eth/api_backend.go | 5 +++++ eth/ethconfig/config.go | 8 +++++++ grpc/execution/server.go | 2 +- internal/ethapi/api.go | 7 ++---- internal/ethapi/backend.go | 3 +++ internal/ethapi/transaction_args_test.go | 1 + les/api_backend.go | 5 +++++ node/config.go | 5 ----- 10 files changed, 43 insertions(+), 27 deletions(-) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 03c9f29157a6..50e97d7d978c 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -185,6 +185,11 @@ var ( utils.GRPCPortFlag, } + metroFlags = []cli.Flag{ + utils.MetroGRPCHostFlag, + utils.MetroGRPCPortFlag, + } + metricsFlags = []cli.Flag{ utils.MetricsEnabledFlag, utils.MetricsEnabledExpensiveFlag, @@ -248,6 +253,7 @@ func init() { app.Flags = flags.Merge( nodeFlags, rpcFlags, + metroFlags, consoleFlags, debug.Flags, metricsFlags, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 51f87cef539c..c7954b06af7b 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -813,15 +813,15 @@ var ( // Metro grpc address and port overrides MetroGRPCHostFlag = &cli.StringFlag{ - Name: "metro.grpc.addr", + Name: "metro.addr", Usage: "Metro gRPC server listening interface", - Value: node.DefaultMetroGRPCHost, + Value: ethconfig.Defaults.MetroGRPCHost, Category: flags.APICategory, } MetroGRPCPortFlag = &cli.IntFlag{ - Name: "metro.grpc.port", + Name: "metro.port", Usage: "Metro gRPC server listening port", - Value: node.DefaultMetroGRPCPort, + Value: ethconfig.Defaults.MetroGRPCPort, Category: flags.APICategory, } @@ -1257,17 +1257,6 @@ func setGRPC(ctx *cli.Context, cfg *node.Config) { } } -// setMetro creates the Metro RPC listener interface string from the set command -// line flags, returning empty if the Metro endpoint is disabled. -func setMetro(ctx *cli.Context, cfg *node.Config) { - if ctx.IsSet(MetroGRPCHostFlag.Name) { - cfg.MetroGRPCHost = ctx.String(MetroGRPCHostFlag.Name) - } - if ctx.IsSet(MetroGRPCPortFlag.Name) { - cfg.MetroGRPCPort = ctx.Int(MetroGRPCPortFlag.Name) - } -} - // setGraphQL creates the GraphQL listener interface string from the set // command line flags, returning empty if the GraphQL endpoint is disabled. func setGraphQL(ctx *cli.Context, cfg *node.Config) { @@ -1518,7 +1507,6 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { setIPC(ctx, cfg) setHTTP(ctx, cfg) setGRPC(ctx, cfg) - setMetro(ctx, cfg) setGraphQL(ctx, cfg) setWS(ctx, cfg) setNodeUserIdent(ctx, cfg) @@ -1917,6 +1905,14 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { } } + // metro + if ctx.IsSet(MetroGRPCHostFlag.Name) { + cfg.MetroGRPCHost = ctx.String(MetroGRPCHostFlag.Name) + } + if ctx.IsSet(MetroGRPCPortFlag.Name) { + cfg.MetroGRPCPort = ctx.Int(MetroGRPCPortFlag.Name) + } + // Override any default configs for hard coded networks. switch { case ctx.Bool(MainnetFlag.Name): diff --git a/eth/api_backend.go b/eth/api_backend.go index ac160b0736a1..8ed720912495 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -19,6 +19,7 @@ package eth import ( "context" "errors" + "fmt" "math/big" "time" @@ -351,6 +352,10 @@ func (b *EthAPIBackend) UnprotectedAllowed() bool { return b.allowUnprotectedTxs } +func (b *EthAPIBackend) MetroGRPCEndpoint() string { + return fmt.Sprintf("%s:%d", b.eth.config.MetroGRPCHost, b.eth.config.MetroGRPCPort) +} + func (b *EthAPIBackend) RPCGasCap() uint64 { return b.eth.config.RPCGasCap } diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index db686c5d0875..2f64014f5a74 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -90,6 +90,10 @@ var Defaults = Config{ RPCEVMTimeout: 5 * time.Second, GPO: FullNodeGPO, RPCTxFeeCap: 1, // 1 ether + + // Metro GRPC + MetroGRPCHost: "localhost", + MetroGRPCPort: 9090, } func init() { @@ -207,6 +211,10 @@ type Config struct { // OverrideShanghai (TODO: remove after the fork) OverrideShanghai *uint64 `toml:",omitempty"` + + // Metro GRPC Host and Port + MetroGRPCHost string `toml:",omitempty"` + MetroGRPCPort int `toml:",omitempty"` } // CreateConsensusEngine creates a consensus engine for the given chain configuration. diff --git a/grpc/execution/server.go b/grpc/execution/server.go index c94bee5a5f1a..47d2227a1fba 100644 --- a/grpc/execution/server.go +++ b/grpc/execution/server.go @@ -92,7 +92,7 @@ func (s *ExecutionServiceServer) DoBlock(ctx context.Context, req *executionv1.D return nil, fmt.Errorf("failed to insert block into blockchain (n=%d)", n) } - // TODO - remove txs from original mempool + // remove txs from original mempool for _, block := range blocks { for _, tx := range block.Transactions() { s.eth.TxPool().RemoveTx(tx.Hash()) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 35528bb5d033..4c2b5f279093 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1577,7 +1577,6 @@ func (s *TransactionAPI) GetTransactionCount(ctx context.Context, address common func (s *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.Hash) (*RPCTransaction, error) { // Try to return an already finalized transaction tx, blockHash, blockNumber, index, err := s.b.GetTransaction(ctx, hash) - log.Info("GetTransactionByHash", "tx", tx, "blockHash", blockHash, "blockNumber", blockNumber, "index", index, "err", err) if err != nil { return nil, err } @@ -1590,12 +1589,10 @@ func (s *TransactionAPI) GetTransactionByHash(ctx context.Context, hash common.H } // No finalized transaction, try to retrieve it from the pool if tx := s.b.GetPoolTransaction(hash); tx != nil { - log.Info("Transaction found in pool", "hash", hash) return NewRPCPendingTransaction(tx, s.b.CurrentHeader(), s.b.ChainConfig()), nil } // Transaction unknown, return as such - log.Info("Transaction not found", "hash", hash) return nil, nil } @@ -1707,8 +1704,8 @@ func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (c if err != nil { return common.Hash{}, err } - // FIXME - address should come from cli flags - metro_api := NewMetroAPI("192.167.10.40:9090") + + metro_api := NewMetroAPI(b.MetroGRPCEndpoint()) if err := metro_api.SubmitTransaction(txBytes); err != nil { return common.Hash{}, err } diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index 0249c8664d3c..35da9e723471 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -97,6 +97,9 @@ type Backend interface { SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription BloomStatus() (uint64, uint64) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) + + // Metro GRPC endpoint + MetroGRPCEndpoint() string } func GetAPIs(apiBackend Backend) []rpc.API { diff --git a/internal/ethapi/transaction_args_test.go b/internal/ethapi/transaction_args_test.go index 24c15b777560..77c89199512e 100644 --- a/internal/ethapi/transaction_args_test.go +++ b/internal/ethapi/transaction_args_test.go @@ -264,6 +264,7 @@ func (b *backendMock) FeeHistory(ctx context.Context, blockCount uint64, lastBlo func (b *backendMock) ChainDb() ethdb.Database { return nil } func (b *backendMock) AccountManager() *accounts.Manager { return nil } func (b *backendMock) ExtRPCEnabled() bool { return false } +func (b *backendMock) MetroGRPCEndpoint() string { return "" } func (b *backendMock) RPCGasCap() uint64 { return 0 } func (b *backendMock) RPCEVMTimeout() time.Duration { return time.Second } func (b *backendMock) RPCTxFeeCap() float64 { return 0 } diff --git a/les/api_backend.go b/les/api_backend.go index 2d1fccd9ad43..6b1795eae0ad 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -19,6 +19,7 @@ package les import ( "context" "errors" + "fmt" "math/big" "time" @@ -292,6 +293,10 @@ func (b *LesApiBackend) UnprotectedAllowed() bool { return b.allowUnprotectedTxs } +func (b *LesApiBackend) MetroGRPCEndpoint() string { + return fmt.Sprintf("%s:%d", b.eth.config.MetroGRPCHost, b.eth.config.MetroGRPCPort) +} + func (b *LesApiBackend) RPCGasCap() uint64 { return b.eth.config.RPCGasCap } diff --git a/node/config.go b/node/config.go index a26a89c54e6c..6be260efbfcd 100644 --- a/node/config.go +++ b/node/config.go @@ -195,11 +195,6 @@ type Config struct { // GRPCPort is the TCP port number on which to start the gRPC server. GRPCPort int `toml:",omitempty"` - // MetroGRPCHost is the address of the Metro grpc server. - MetroGRPCHost string `toml:",omitempty"` - // MetroGRPCPort is the port of the Metro grpc server. - MetroGRPCPort int `toml:",omitempty"` - // Logger is a custom logger to use with the p2p.Server. Logger log.Logger `toml:",omitempty"` From 210e06c96cb914c34abe8fc6aab28b714b9ff72c Mon Sep 17 00:00:00 2001 From: Jesse Snyder Date: Thu, 20 Apr 2023 08:50:26 -0600 Subject: [PATCH 3/4] fixes from pr feedback --- grpc/execution/server.go | 6 ++---- internal/ethapi/api.go | 4 ++-- node/defaults.go | 4 ---- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/grpc/execution/server.go b/grpc/execution/server.go index 47d2227a1fba..6898a6af164b 100644 --- a/grpc/execution/server.go +++ b/grpc/execution/server.go @@ -93,10 +93,8 @@ func (s *ExecutionServiceServer) DoBlock(ctx context.Context, req *executionv1.D } // remove txs from original mempool - for _, block := range blocks { - for _, tx := range block.Transactions() { - s.eth.TxPool().RemoveTx(tx.Hash()) - } + for _, tx := range block.Transactions() { + s.eth.TxPool().RemoveTx(tx.Hash()) } newForkChoice := &engine.ForkchoiceStateV1{ diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 4c2b5f279093..51412df2549b 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1705,8 +1705,8 @@ func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (c return common.Hash{}, err } - metro_api := NewMetroAPI(b.MetroGRPCEndpoint()) - if err := metro_api.SubmitTransaction(txBytes); err != nil { + metroAPI := NewMetroAPI(b.MetroGRPCEndpoint()) + if err := metroAPI.SubmitTransaction(txBytes); err != nil { return common.Hash{}, err } diff --git a/node/defaults.go b/node/defaults.go index b1a6ea05aa65..a02f85731a28 100644 --- a/node/defaults.go +++ b/node/defaults.go @@ -40,10 +40,6 @@ const ( // grpc DefaultGRPCHost = "[::1]" // Default host interface for the gRPC server DefaultGRPCPort = 50051 // Default port for the gRPC server - - // metro - DefaultMetroGRPCHost = "127.0.0.1" // Default host interface for the metro gRPC server - DefaultMetroGRPCPort = 9090 // Default port for the metro gRPC server ) var ( From f8270b8d855bab4e09ca7192565f64a764f5d139 Mon Sep 17 00:00:00 2001 From: Jesse Snyder Date: Thu, 20 Apr 2023 09:23:45 -0600 Subject: [PATCH 4/4] formatting --- node/defaults.go | 1 - 1 file changed, 1 deletion(-) diff --git a/node/defaults.go b/node/defaults.go index a02f85731a28..42c339a0c942 100644 --- a/node/defaults.go +++ b/node/defaults.go @@ -36,7 +36,6 @@ const ( DefaultGraphQLPort = 8547 // Default TCP port for the GraphQL server DefaultAuthHost = "localhost" // Default host interface for the authenticated apis DefaultAuthPort = 8551 // Default port for the authenticated apis - // grpc DefaultGRPCHost = "[::1]" // Default host interface for the gRPC server DefaultGRPCPort = 50051 // Default port for the gRPC server