diff --git a/apps/evm/cmd/post_tx_cmd.go b/apps/evm/cmd/post_tx_cmd.go deleted file mode 100644 index 211eadd6fa..0000000000 --- a/apps/evm/cmd/post_tx_cmd.go +++ /dev/null @@ -1,231 +0,0 @@ -package cmd - -import ( - "encoding/hex" - "encoding/json" - "fmt" - "os" - "path/filepath" - "strings" - - "github.com/spf13/cobra" - - evblock "github.com/evstack/ev-node/block" - rollcmd "github.com/evstack/ev-node/pkg/cmd" - rollconf "github.com/evstack/ev-node/pkg/config" - blobrpc "github.com/evstack/ev-node/pkg/da/jsonrpc" - da "github.com/evstack/ev-node/pkg/da/types" - genesispkg "github.com/evstack/ev-node/pkg/genesis" - "github.com/evstack/ev-node/types" -) - -const ( - flagNamespace = "namespace" - flagGasPrice = "gas-price" -) - -// PostTxCmd returns a command to post a signed Ethereum transaction to the DA layer -func PostTxCmd() *cobra.Command { - cobraCmd := &cobra.Command{ - Use: "post-tx", - Short: "Post a signed Ethereum transaction to the DA layer", - Long: `Post a signed Ethereum transaction to the DA layer using the Evolve configuration. - -This command submits a signed Ethereum transaction tzo the configured DA layer for forced inclusion. -The transaction is provided as an argument, which accepts either: - 1. A hex-encoded signed transaction (with or without 0x prefix) - 2. A path to a file containing the hex-encoded transaction - 3. A JSON object with a "raw" field containing the hex-encoded transaction - -The command automatically detects the input format. - -Examples: - # From hex string - evm post-tx 0x02f873... - - # From file - evm post-tx tx.txt - - # From JSON - evm post-tx '{"raw":"0x02f873..."}' -`, - Args: cobra.ExactArgs(1), - RunE: postTxRunE, - } - - // Add evolve config flags - rollconf.AddFlags(cobraCmd) - - // Add command-specific flags - cobraCmd.Flags().String(flagNamespace, "", "DA namespace ID (if not provided, uses config namespace)") - cobraCmd.Flags().Float64(flagGasPrice, -1, "Gas price for DA submission (if not provided, uses config gas price)") - - return cobraCmd -} - -// postTxRunE executes the post-tx command -func postTxRunE(cmd *cobra.Command, args []string) error { - nodeConfig, err := rollcmd.ParseConfig(cmd) - if err != nil { - return err - } - - logger := rollcmd.SetupLogger(nodeConfig.Log) - - txInput := args[0] - if txInput == "" { - return fmt.Errorf("transaction cannot be empty") - } - - var txData []byte - if _, err := os.Stat(txInput); err == nil { - // Input is a file path - txData, err = decodeTxFromFile(txInput) - if err != nil { - return fmt.Errorf("failed to decode transaction from file: %w", err) - } - } else { - // Input is a JSON string - txData, err = decodeTxFromJSON(txInput) - if err != nil { - return fmt.Errorf("failed to decode transaction from JSON: %w", err) - } - } - - if len(txData) == 0 { - return fmt.Errorf("transaction data cannot be empty") - } - - // Get namespace (use flag if provided, otherwise use config) - namespace, _ := cmd.Flags().GetString(flagNamespace) - if namespace == "" { - namespace = nodeConfig.DA.GetForcedInclusionNamespace() - } - - if namespace == "" { - return fmt.Errorf("forced inclusionnamespace cannot be empty") - } - - namespaceBz := da.NamespaceFromString(namespace).Bytes() - - // Get gas price (use flag if provided, otherwise use config) - gasPrice, err := cmd.Flags().GetFloat64(flagGasPrice) - if err != nil { - return fmt.Errorf("failed to get gas-price flag: %w", err) - } - - logger.Info().Str("namespace", namespace).Float64("gas_price", gasPrice).Int("tx_size", len(txData)).Msg("posting transaction to DA layer") - - daClient, err := blobrpc.NewClient( - cmd.Context(), - nodeConfig.DA.Address, - nodeConfig.DA.AuthToken, - "", - ) - if err != nil { - return fmt.Errorf("failed to create DA client: %w", err) - } - - // Submit transaction to DA layer - logger.Info().Msg("submitting transaction to DA layer...") - - blobs := [][]byte{txData} - options := []byte(nodeConfig.DA.SubmitOptions) - - dac := evblock.NewDAClient(daClient, nodeConfig, logger) - result := dac.Submit(cmd.Context(), blobs, gasPrice, namespaceBz, options) - - // Check result - switch result.Code { - case da.StatusSuccess: - logger.Info().Msg("transaction successfully submitted to DA layer") - cmd.Printf("\n✓ Transaction posted successfully\n\n") - cmd.Printf("Namespace: %s\n", namespace) - cmd.Printf("DA Height: %d\n", result.Height) - cmd.Printf("Data Size: %d bytes\n", len(txData)) - - genesisPath := filepath.Join(filepath.Dir(nodeConfig.ConfigPath()), "genesis.json") - genesis, err := genesispkg.LoadGenesis(genesisPath) - if err != nil { - return fmt.Errorf("failed to load genesis for calculating inclusion time estimate: %w", err) - } - - _, epochEnd, _ := types.CalculateEpochBoundaries(result.Height, genesis.DAStartHeight, genesis.DAEpochForcedInclusion) - cmd.Printf( - "DA Blocks until inclusion: %d (at DA height %d)\n", - epochEnd-(result.Height+1), - epochEnd+1, - ) - - cmd.Printf("\n") - return nil - - case da.StatusTooBig: - return fmt.Errorf("transaction too large for DA layer: %s", result.Message) - - case da.StatusNotIncludedInBlock: - return fmt.Errorf("transaction not included in DA block: %s", result.Message) - - case da.StatusAlreadyInMempool: - cmd.Printf("⚠ Transaction already in mempool\n") - if result.Height > 0 { - cmd.Printf(" DA Height: %d\n", result.Height) - } - return nil - - case da.StatusContextCanceled: - return fmt.Errorf("submission canceled: %s", result.Message) - - default: - return fmt.Errorf("DA submission failed (code: %d): %s", result.Code, result.Message) - } -} - -// decodeTxFromFile reads an Ethereum transaction from a file and decodes it to bytes -func decodeTxFromFile(filePath string) ([]byte, error) { - data, err := os.ReadFile(filePath) - if err != nil { - return nil, fmt.Errorf("reading file: %w", err) - } - - return decodeTxFromJSON(string(data)) -} - -// decodeTxFromJSON decodes an Ethereum transaction from various formats to bytes -func decodeTxFromJSON(input string) ([]byte, error) { - input = strings.TrimSpace(input) - - // Try to decode as JSON with "raw" field - var txJSON map[string]any - if err := json.Unmarshal([]byte(input), &txJSON); err == nil { - if rawTx, ok := txJSON["raw"].(string); ok { - return decodeHexTx(rawTx) - } - return nil, fmt.Errorf("JSON must contain 'raw' field with hex-encoded transaction") - } - - // Try to decode as hex string directly - return decodeHexTx(input) -} - -// decodeHexTx decodes a hex-encoded Ethereum transaction -func decodeHexTx(hexStr string) ([]byte, error) { - hexStr = strings.TrimSpace(hexStr) - - // Remove 0x prefix if present - if strings.HasPrefix(hexStr, "0x") || strings.HasPrefix(hexStr, "0X") { - hexStr = hexStr[2:] - } - - // Decode hex string to bytes - txBytes, err := hex.DecodeString(hexStr) - if err != nil { - return nil, fmt.Errorf("decoding hex transaction: %w", err) - } - - if len(txBytes) == 0 { - return nil, fmt.Errorf("decoded transaction is empty") - } - - return txBytes, nil -} diff --git a/apps/evm/server/force_inclusion.go b/apps/evm/server/force_inclusion.go index a9812d9944..1acc3c8d44 100644 --- a/apps/evm/server/force_inclusion.go +++ b/apps/evm/server/force_inclusion.go @@ -8,7 +8,6 @@ import ( "fmt" "io" "net/http" - "strconv" "strings" "time" @@ -175,19 +174,6 @@ func (s *ForceInclusionServer) handleJSONRPC(w http.ResponseWriter, r *http.Requ } } -// handleChainID handles eth_chainId requests -func (s *ForceInclusionServer) handleChainID(w http.ResponseWriter, req *JSONRPCRequest) { - // Convert chain ID string to integer - chainIDInt, err := strconv.ParseUint(s.genesis.ChainID, 10, 64) - if err != nil { - s.writeError(w, req.ID, InternalError, fmt.Sprintf("invalid chain ID: %v", err)) - return - } - // Return the chain ID as a hex string prefixed with 0x - chainID := fmt.Sprintf("0x%x", chainIDInt) - s.writeSuccess(w, req.ID, chainID) -} - // proxyToExecutionRPC forwards unknown RPC methods to the execution RPC endpoint func (s *ForceInclusionServer) proxyToExecutionRPC(w http.ResponseWriter, req *JSONRPCRequest, body []byte) { if s.executionRPCURL == "" { diff --git a/apps/testapp/kv/http_server.go b/apps/testapp/kv/http_server.go index f4e7508abc..d8e789ac8b 100644 --- a/apps/testapp/kv/http_server.go +++ b/apps/testapp/kv/http_server.go @@ -76,11 +76,6 @@ func (hs *HTTPServer) Start(ctx context.Context) error { } } -// Stop shuts down the HTTP server -func (hs *HTTPServer) Stop() error { - return hs.server.Close() -} - // handleTx handles transaction submissions // POST /tx with raw binary data or text in request body // It is recommended to use transactions in the format "key=value" to be consistent diff --git a/node/helpers.go b/node/helpers.go index c24f38ac38..e427631625 100644 --- a/node/helpers.go +++ b/node/helpers.go @@ -23,22 +23,6 @@ const ( Store ) -// MockTester is a mock testing.T -type MockTester struct { -} - -// Fail is used to fail the test -func (m MockTester) Fail() {} - -// FailNow is used to fail the test immediately -func (m MockTester) FailNow() {} - -// Logf is used to log a message to the test logger -func (m MockTester) Logf(format string, args ...any) {} - -// Errorf is used to log an error to the test logger -func (m MockTester) Errorf(format string, args ...any) {} - func waitForFirstBlock(node Node, source Source) error { return waitForAtLeastNBlocks(node, 1, source) } diff --git a/pkg/da/types/types.go b/pkg/da/types/types.go index 24bcceea84..7563e14d43 100644 --- a/pkg/da/types/types.go +++ b/pkg/da/types/types.go @@ -1,8 +1,6 @@ package da import ( - "encoding/binary" - "fmt" "time" ) @@ -73,16 +71,6 @@ type BaseResult struct { Timestamp time.Time } -// SplitID splits an ID into a height and a commitment. -// if len(id) <= 8, it returns 0 and nil. -func SplitID(id []byte) (uint64, []byte, error) { - if len(id) <= 8 { - return 0, nil, fmt.Errorf("invalid ID length: %d", len(id)) - } - commitment := id[8:] - return binary.LittleEndian.Uint64(id[:8]), commitment, nil -} - // SubscriptionEvent is a namespace-agnostic signal that a blob was finalized at // Height on the DA layer. Produced by Subscribe and consumed by DA followers. type SubscriptionEvent struct { diff --git a/pkg/store/kv.go b/pkg/store/kv.go index 3ee23bc2c1..6dccb6ab78 100644 --- a/pkg/store/kv.go +++ b/pkg/store/kv.go @@ -1,13 +1,11 @@ package store import ( - "context" "path/filepath" "strings" ds "github.com/ipfs/go-datastore" ktds "github.com/ipfs/go-datastore/keytransform" - dsq "github.com/ipfs/go-datastore/query" badger4 "github.com/ipfs/go-ds-badger4" ) @@ -30,15 +28,6 @@ func NewEvNodeKVStore(kvStore ds.Batching) ds.Batching { return NewPrefixKVStore(kvStore, EvPrefix) } -// GetPrefixEntries retrieves all entries in the datastore whose keys have the supplied prefix -func GetPrefixEntries(ctx context.Context, store ds.Datastore, prefix string) (dsq.Results, error) { - results, err := store.Query(ctx, dsq.Query{Prefix: prefix}) - if err != nil { - return nil, err - } - return results, nil -} - // GenerateKey creates a key from a slice of string fields, joining them with slashes. func GenerateKey(fields []string) string { // Pre-calculate total size to avoid re-allocation.