Skip to content
Merged
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
14 changes: 14 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"log"
"log/slog"
"net/url"
"os"
"sort"
"strings"
Expand Down Expand Up @@ -59,6 +60,7 @@ var (
testRPCURL string
testELRPCURL string
testTimeout time.Duration
testInsecure bool
portListFlag bool
)

Expand Down Expand Up @@ -507,11 +509,22 @@ var testCmd = &cobra.Command{
Short: "Send a test transaction to the local EL node",
RunE: func(cmd *cobra.Command, args []string) error {
cmd.SilenceUsage = true

ctx := mainctx.Get()
cfg := playground.DefaultTestTxConfig()
cfg.RPCURL = testRPCURL
cfg.ELRPCURL = testELRPCURL
cfg.Timeout = testTimeout
cfg.Insecure = testInsecure

// Suggest --insecure flag if any RPC URL uses https without insecure mode
for _, rpcURL := range []string{cfg.RPCURL, cfg.ELRPCURL} {
if parsed, err := url.Parse(rpcURL); err == nil && parsed.Scheme == "https" && !cfg.Insecure {
color.Yellow("Tip: If using self-signed certificates, consider adding --insecure flag")
break
}
}

return playground.SendTestTransaction(ctx, cfg)
},
}
Expand Down Expand Up @@ -621,6 +634,7 @@ func main() {
testCmd.Flags().StringVar(&testRPCURL, "rpc", "http://localhost:8545", "Target RPC URL for sending transactions")
testCmd.Flags().StringVar(&testELRPCURL, "el-rpc", "", "EL RPC URL for chain queries (default: same as --rpc)")
testCmd.Flags().DurationVar(&testTimeout, "timeout", 2*time.Minute, "Timeout for waiting for transaction receipt")
testCmd.Flags().BoolVar(&testInsecure, "insecure", false, "Skip TLS certificate verification (for self-signed certs)")
rootCmd.AddCommand(testCmd)

if err := rootCmd.Execute(); err != nil {
Expand Down
25 changes: 23 additions & 2 deletions playground/test_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ package playground
import (
"context"
"crypto/ecdsa"
"crypto/tls"
"fmt"
"math/big"
"net/http"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
)

// TestTxConfig holds configuration for the test transaction
Expand All @@ -23,6 +26,7 @@ type TestTxConfig struct {
GasLimit uint64
GasPrice *big.Int
Timeout time.Duration // Timeout for waiting for receipt. If 0, defaults to 2 minutes
Insecure bool // Skip TLS certificate verification
}

// DefaultTestTxConfig returns the default test transaction configuration
Expand Down Expand Up @@ -69,8 +73,25 @@ func SendTestTransaction(ctx context.Context, cfg *TestTxConfig) error {
elRPCURL = cfg.RPCURL
}

// dialRPC connects to an RPC endpoint, optionally skipping TLS verification
dialRPC := func(url string) (*ethclient.Client, error) {
if cfg.Insecure {
httpClient := &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: consider adding a //nolint:gosec or // #nosec G402 comment on the InsecureSkipVerify: true line. Static analysis tools (gosec, staticcheck) will flag this. Adding the annotation makes it clear this is intentional and user-gated behind --insecure.

Suggested change
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, //nolint:gosec // user-requested via --insecure flag

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gosec is enabled in .golangci.yaml and G402 is not excluded, so this line will fail CI. Add a nolint directive:

Suggested change
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, //nolint:gosec // user-requested via --insecure flag

},
}
rpcClient, err := rpc.DialOptions(ctx, url, rpc.WithHTTPClient(httpClient))
if err != nil {
return nil, err
}
return ethclient.NewClient(rpcClient), nil
}
return ethclient.Dial(url)
}

// Connect to the EL RPC endpoint (for chain queries)
elClient, err := ethclient.Dial(elRPCURL)
elClient, err := dialRPC(elRPCURL)
if err != nil {
return fmt.Errorf("failed to connect to EL RPC: %w", err)
}
Expand All @@ -79,7 +100,7 @@ func SendTestTransaction(ctx context.Context, cfg *TestTxConfig) error {
// Connect to the target RPC endpoint (for sending transactions)
var targetClient *ethclient.Client
if cfg.RPCURL != elRPCURL {
targetClient, err = ethclient.Dial(cfg.RPCURL)
targetClient, err = dialRPC(cfg.RPCURL)
if err != nil {
return fmt.Errorf("failed to connect to target RPC: %w", err)
}
Expand Down