mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
cmd/evm: Add t8n server
This commit is contained in:
parent
1a79f8fe58
commit
cfd7e06e6b
6 changed files with 292 additions and 118 deletions
|
|
@ -154,4 +154,13 @@ var (
|
||||||
Usage: "sets the verbosity level",
|
Usage: "sets the verbosity level",
|
||||||
Value: 3,
|
Value: 3,
|
||||||
}
|
}
|
||||||
|
PortFlag = &cli.IntFlag{
|
||||||
|
Name: "port",
|
||||||
|
Usage: "port to listen on",
|
||||||
|
Value: 0,
|
||||||
|
}
|
||||||
|
UnixSocketFlag = &cli.StringFlag{
|
||||||
|
Name: "unix-socket",
|
||||||
|
Usage: "File path to the unix socket to use",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ func Transaction(ctx *cli.Context) error {
|
||||||
return NewError(ErrorJson, fmt.Errorf("failed unmarshalling stdin: %v", err))
|
return NewError(ErrorJson, fmt.Errorf("failed unmarshalling stdin: %v", err))
|
||||||
}
|
}
|
||||||
// Decode the body of already signed transactions
|
// Decode the body of already signed transactions
|
||||||
body = common.FromHex(inputData.TxRlp)
|
body = inputData.TxRlp
|
||||||
} else {
|
} else {
|
||||||
// Read input from file
|
// Read input from file
|
||||||
inFile, err := os.Open(txStr)
|
inFile, err := os.Open(txStr)
|
||||||
|
|
|
||||||
|
|
@ -17,13 +17,20 @@
|
||||||
package t8ntool
|
package t8ntool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
|
@ -74,21 +81,102 @@ var (
|
||||||
_ cli.ExitCoder = (*NumberedError)(nil)
|
_ cli.ExitCoder = (*NumberedError)(nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type tracerFn func(baseDir string) func(txIndex int, txHash common.Hash) (*tracers.Tracer, io.WriteCloser, error)
|
||||||
|
|
||||||
type input struct {
|
type input struct {
|
||||||
Alloc types.GenesisAlloc `json:"alloc,omitempty"`
|
Alloc types.GenesisAlloc `json:"alloc,omitempty"`
|
||||||
Env *stEnv `json:"env,omitempty"`
|
Env *stEnv `json:"env,omitempty"`
|
||||||
Txs []*txWithKey `json:"txs,omitempty"`
|
Txs []*txWithKey `json:"txs,omitempty"`
|
||||||
TxRlp string `json:"txsRlp,omitempty"`
|
TxRlp hexutil.Bytes `json:"txsRlp,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func Transition(ctx *cli.Context) error {
|
func (i *input) prestate() Prestate {
|
||||||
var getTracer = func(txIndex int, txHash common.Hash) (*tracers.Tracer, io.WriteCloser, error) { return nil, nil, nil }
|
return Prestate{
|
||||||
|
Pre: i.Alloc,
|
||||||
|
Env: *i.Env,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
baseDir, err := createBasedir(ctx)
|
func (i *input) txIterator(chainConfig *params.ChainConfig) (txIterator, error) {
|
||||||
|
if len(i.TxRlp) > 0 {
|
||||||
|
// Decode the body of already signed transactions
|
||||||
|
return newRlpTxIterator(i.TxRlp), nil
|
||||||
|
}
|
||||||
|
// We may have to sign the transactions.
|
||||||
|
signer := types.LatestSignerForChainID(chainConfig.ChainID)
|
||||||
|
txs, err := signUnsignedTransactions(i.Txs, signer)
|
||||||
|
return newSliceTxIterator(txs), err
|
||||||
|
}
|
||||||
|
|
||||||
|
type stateReq struct {
|
||||||
|
Fork string `json:"fork,omitempty"`
|
||||||
|
ChainID int64 `json:"chainid,omitempty"`
|
||||||
|
Reward int64 `json:"reward,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type transitionRequest struct {
|
||||||
|
Input input `json:"input,omitempty"`
|
||||||
|
State stateReq `json:"state,omitempty"`
|
||||||
|
BaseDir string `json:"baseDir,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type transitionRequestOutput struct {
|
||||||
|
Result *ExecutionResult `json:"result"`
|
||||||
|
Alloc Alloc `json:"alloc"`
|
||||||
|
Body hexutil.Bytes `json:"body"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *transitionRequest) process(tracerGenFn tracerFn) (*transitionRequestOutput, error) {
|
||||||
|
baseDir, err := createBasedirFromString(r.BaseDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return NewError(ErrorIO, fmt.Errorf("failed creating output basedir: %v", err))
|
return nil, fmt.Errorf("failed creating output basedir: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prestate := r.Input.prestate()
|
||||||
|
vmConfig := vm.Config{}
|
||||||
|
// Construct the chainconfig
|
||||||
|
var chainConfig *params.ChainConfig
|
||||||
|
if cConf, extraEips, err := tests.GetChainConfig(r.State.Fork); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed constructing chain configuration: %v", err)
|
||||||
|
} else {
|
||||||
|
chainConfig = cConf
|
||||||
|
vmConfig.ExtraEips = extraEips
|
||||||
|
}
|
||||||
|
// Set the chain id
|
||||||
|
chainConfig.ChainID = big.NewInt(r.State.ChainID)
|
||||||
|
|
||||||
|
txIt, err := r.Input.txIterator(chainConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed loading transactions: %v", err)
|
||||||
|
}
|
||||||
|
if err := applyLondonChecks(&prestate.Env, chainConfig); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed applying London checks: %v", err)
|
||||||
|
}
|
||||||
|
if err := applyShanghaiChecks(&prestate.Env, chainConfig); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed applying Shanghai checks: %v", err)
|
||||||
|
}
|
||||||
|
if err := applyMergeChecks(&prestate.Env, chainConfig); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed applying Merge checks: %v", err)
|
||||||
|
}
|
||||||
|
if err := applyCancunChecks(&prestate.Env, chainConfig); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed applying Cancun checks: %v", err)
|
||||||
|
}
|
||||||
|
// Run the test and aggregate the result
|
||||||
|
s, result, body, err := prestate.Apply(vmConfig, chainConfig, txIt, r.State.Reward, tracerGenFn(baseDir))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed applying prestate: %v", err)
|
||||||
|
}
|
||||||
|
// Dump the execution result
|
||||||
|
collector := make(Alloc)
|
||||||
|
s.DumpToCollector(collector, nil)
|
||||||
|
return &transitionRequestOutput{
|
||||||
|
Result: result,
|
||||||
|
Alloc: collector,
|
||||||
|
Body: body,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func tracerGenerator(ctx *cli.Context) tracerFn {
|
||||||
if ctx.Bool(TraceFlag.Name) { // JSON opcode tracing
|
if ctx.Bool(TraceFlag.Name) { // JSON opcode tracing
|
||||||
// Configure the EVM logger
|
// Configure the EVM logger
|
||||||
logConfig := &logger.Config{
|
logConfig := &logger.Config{
|
||||||
|
|
@ -97,67 +185,85 @@ func Transition(ctx *cli.Context) error {
|
||||||
EnableReturnData: ctx.Bool(TraceEnableReturnDataFlag.Name),
|
EnableReturnData: ctx.Bool(TraceEnableReturnDataFlag.Name),
|
||||||
Debug: true,
|
Debug: true,
|
||||||
}
|
}
|
||||||
getTracer = func(txIndex int, txHash common.Hash) (*tracers.Tracer, io.WriteCloser, error) {
|
enableCallFrames := ctx.Bool(TraceEnableCallFramesFlag.Name)
|
||||||
traceFile, err := os.Create(filepath.Join(baseDir, fmt.Sprintf("trace-%d-%v.jsonl", txIndex, txHash.String())))
|
return func(baseDir string) func(txIndex int, txHash common.Hash) (*tracers.Tracer, io.WriteCloser, error) {
|
||||||
if err != nil {
|
return func(txIndex int, txHash common.Hash) (*tracers.Tracer, io.WriteCloser, error) {
|
||||||
return nil, nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
|
traceFile, err := os.Create(filepath.Join(baseDir, fmt.Sprintf("trace-%d-%v.jsonl", txIndex, txHash.String())))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
|
||||||
|
}
|
||||||
|
var l *tracing.Hooks
|
||||||
|
if enableCallFrames {
|
||||||
|
l = logger.NewJSONLoggerWithCallFrames(logConfig, traceFile)
|
||||||
|
} else {
|
||||||
|
l = logger.NewJSONLogger(logConfig, traceFile)
|
||||||
|
}
|
||||||
|
tracer := &tracers.Tracer{
|
||||||
|
Hooks: l,
|
||||||
|
// jsonLogger streams out result to file.
|
||||||
|
GetResult: func() (json.RawMessage, error) { return nil, nil },
|
||||||
|
Stop: func(err error) {},
|
||||||
|
}
|
||||||
|
return tracer, traceFile, nil
|
||||||
}
|
}
|
||||||
var l *tracing.Hooks
|
|
||||||
if ctx.Bool(TraceEnableCallFramesFlag.Name) {
|
|
||||||
l = logger.NewJSONLoggerWithCallFrames(logConfig, traceFile)
|
|
||||||
} else {
|
|
||||||
l = logger.NewJSONLogger(logConfig, traceFile)
|
|
||||||
}
|
|
||||||
tracer := &tracers.Tracer{
|
|
||||||
Hooks: l,
|
|
||||||
// jsonLogger streams out result to file.
|
|
||||||
GetResult: func() (json.RawMessage, error) { return nil, nil },
|
|
||||||
Stop: func(err error) {},
|
|
||||||
}
|
|
||||||
return tracer, traceFile, nil
|
|
||||||
}
|
}
|
||||||
} else if ctx.IsSet(TraceTracerFlag.Name) {
|
} else if ctx.IsSet(TraceTracerFlag.Name) {
|
||||||
var config json.RawMessage
|
var config json.RawMessage
|
||||||
if ctx.IsSet(TraceTracerConfigFlag.Name) {
|
if ctx.IsSet(TraceTracerConfigFlag.Name) {
|
||||||
config = []byte(ctx.String(TraceTracerConfigFlag.Name))
|
config = []byte(ctx.String(TraceTracerConfigFlag.Name))
|
||||||
}
|
}
|
||||||
getTracer = func(txIndex int, txHash common.Hash) (*tracers.Tracer, io.WriteCloser, error) {
|
tracerStr := ctx.String(TraceTracerFlag.Name)
|
||||||
traceFile, err := os.Create(filepath.Join(baseDir, fmt.Sprintf("trace-%d-%v.json", txIndex, txHash.String())))
|
return func(baseDir string) func(txIndex int, txHash common.Hash) (*tracers.Tracer, io.WriteCloser, error) {
|
||||||
if err != nil {
|
return func(txIndex int, txHash common.Hash) (*tracers.Tracer, io.WriteCloser, error) {
|
||||||
return nil, nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
|
traceFile, err := os.Create(filepath.Join(baseDir, fmt.Sprintf("trace-%d-%v.json", txIndex, txHash.String())))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, NewError(ErrorIO, fmt.Errorf("failed creating trace-file: %v", err))
|
||||||
|
}
|
||||||
|
tracer, err := tracers.DefaultDirectory.New(tracerStr, nil, config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, NewError(ErrorConfig, fmt.Errorf("failed instantiating tracer: %w", err))
|
||||||
|
}
|
||||||
|
return tracer, traceFile, nil
|
||||||
}
|
}
|
||||||
tracer, err := tracers.DefaultDirectory.New(ctx.String(TraceTracerFlag.Name), nil, config)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, NewError(ErrorConfig, fmt.Errorf("failed instantiating tracer: %w", err))
|
|
||||||
}
|
|
||||||
return tracer, traceFile, nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Default to no tracing
|
||||||
|
return func(baseDir string) func(txIndex int, txHash common.Hash) (*tracers.Tracer, io.WriteCloser, error) {
|
||||||
|
return func(txIndex int, txHash common.Hash) (*tracers.Tracer, io.WriteCloser, error) {
|
||||||
|
return nil, nil, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Transition(ctx *cli.Context) error {
|
||||||
// We need to load three things: alloc, env and transactions. May be either in
|
// We need to load three things: alloc, env and transactions. May be either in
|
||||||
// stdin input or in files.
|
// stdin input or in files.
|
||||||
// Check if anything needs to be read from stdin
|
// Check if anything needs to be read from stdin
|
||||||
var (
|
var (
|
||||||
prestate Prestate
|
|
||||||
txIt txIterator // txs to apply
|
|
||||||
allocStr = ctx.String(InputAllocFlag.Name)
|
allocStr = ctx.String(InputAllocFlag.Name)
|
||||||
|
envStr = ctx.String(InputEnvFlag.Name)
|
||||||
envStr = ctx.String(InputEnvFlag.Name)
|
txStr = ctx.String(InputTxsFlag.Name)
|
||||||
txStr = ctx.String(InputTxsFlag.Name)
|
|
||||||
inputData = &input{}
|
|
||||||
)
|
)
|
||||||
|
request := transitionRequest{
|
||||||
|
BaseDir: ctx.String(OutputBasedir.Name),
|
||||||
|
State: stateReq{
|
||||||
|
Fork: ctx.String(ForknameFlag.Name),
|
||||||
|
ChainID: ctx.Int64(ChainIDFlag.Name),
|
||||||
|
Reward: ctx.Int64(RewardFlag.Name),
|
||||||
|
},
|
||||||
|
}
|
||||||
// Figure out the prestate alloc
|
// Figure out the prestate alloc
|
||||||
if allocStr == stdinSelector || envStr == stdinSelector || txStr == stdinSelector {
|
if allocStr == stdinSelector || envStr == stdinSelector || txStr == stdinSelector {
|
||||||
decoder := json.NewDecoder(os.Stdin)
|
decoder := json.NewDecoder(os.Stdin)
|
||||||
if err := decoder.Decode(inputData); err != nil {
|
if err := decoder.Decode(&request.Input); err != nil {
|
||||||
return NewError(ErrorJson, fmt.Errorf("failed unmarshalling stdin: %v", err))
|
return NewError(ErrorJson, fmt.Errorf("failed unmarshalling stdin: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if allocStr != stdinSelector {
|
if allocStr != stdinSelector {
|
||||||
if err := readFile(allocStr, "alloc", &inputData.Alloc); err != nil {
|
if err := readFile(allocStr, "alloc", &request.Input.Alloc); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prestate.Pre = inputData.Alloc
|
|
||||||
|
|
||||||
// Set the block environment
|
// Set the block environment
|
||||||
if envStr != stdinSelector {
|
if envStr != stdinSelector {
|
||||||
|
|
@ -165,46 +271,116 @@ func Transition(ctx *cli.Context) error {
|
||||||
if err := readFile(envStr, "env", &env); err != nil {
|
if err := readFile(envStr, "env", &env); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
inputData.Env = &env
|
request.Input.Env = &env
|
||||||
}
|
}
|
||||||
prestate.Env = *inputData.Env
|
|
||||||
|
|
||||||
vmConfig := vm.Config{}
|
// Load the transactions from file if needed
|
||||||
// Construct the chainconfig
|
if txStr != stdinSelector {
|
||||||
var chainConfig *params.ChainConfig
|
data, err := os.ReadFile(txStr)
|
||||||
if cConf, extraEips, err := tests.GetChainConfig(ctx.String(ForknameFlag.Name)); err != nil {
|
if err != nil {
|
||||||
return NewError(ErrorConfig, fmt.Errorf("failed constructing chain configuration: %v", err))
|
return NewError(ErrorIO, fmt.Errorf("failed reading txs file: %v", err))
|
||||||
} else {
|
}
|
||||||
chainConfig = cConf
|
if strings.HasSuffix(txStr, ".rlp") { // A file containing an rlp list
|
||||||
vmConfig.ExtraEips = extraEips
|
err = json.Unmarshal(data, &request.Input.TxRlp)
|
||||||
|
} else {
|
||||||
|
err = json.Unmarshal(data, &request.Input.Txs)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed unmarshalling txs-file: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Set the chain id
|
|
||||||
chainConfig.ChainID = big.NewInt(ctx.Int64(ChainIDFlag.Name))
|
|
||||||
|
|
||||||
if txIt, err = loadTransactions(txStr, inputData, prestate.Env, chainConfig); err != nil {
|
result, err := request.process(tracerGenerator(ctx))
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := applyLondonChecks(&prestate.Env, chainConfig); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := applyShanghaiChecks(&prestate.Env, chainConfig); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := applyMergeChecks(&prestate.Env, chainConfig); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := applyCancunChecks(&prestate.Env, chainConfig); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// Run the test and aggregate the result
|
|
||||||
s, result, body, err := prestate.Apply(vmConfig, chainConfig, txIt, ctx.Int64(RewardFlag.Name), getTracer)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Dump the execution result
|
return dispatchOutput(ctx, request.BaseDir, result.Result, result.Alloc, result.Body)
|
||||||
collector := make(Alloc)
|
}
|
||||||
s.DumpToCollector(collector, nil)
|
|
||||||
return dispatchOutput(ctx, baseDir, result, collector, body)
|
func TransitionServer(ctx *cli.Context) error {
|
||||||
|
// Start the server
|
||||||
|
server := &transitionServer{
|
||||||
|
port: ctx.Int(PortFlag.Name),
|
||||||
|
unixSocket: ctx.String(UnixSocketFlag.Name),
|
||||||
|
tracerGenFn: tracerGenerator(ctx),
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := server.start(); err != nil {
|
||||||
|
return NewError(ErrorIO, fmt.Errorf("failed starting server: %v", err))
|
||||||
|
}
|
||||||
|
log.Info("Started server", "port", server.port)
|
||||||
|
|
||||||
|
// Wait for a signal to shutdown
|
||||||
|
done := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(done, os.Interrupt, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
<-done
|
||||||
|
|
||||||
|
log.Info("Shutting down server")
|
||||||
|
if err := server.shutdown(); err != nil {
|
||||||
|
return NewError(ErrorIO, fmt.Errorf("failed shutting down server: %v", err))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type transitionServer struct {
|
||||||
|
port int
|
||||||
|
unixSocket string
|
||||||
|
tracerGenFn tracerFn
|
||||||
|
httpSrv *http.Server
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *transitionServer) start() error {
|
||||||
|
// start the HTTP listener
|
||||||
|
var (
|
||||||
|
listener net.Listener
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if server.unixSocket != "" {
|
||||||
|
listener, err = net.Listen("unix", server.unixSocket)
|
||||||
|
} else {
|
||||||
|
listener, err = net.Listen("tcp", fmt.Sprintf(":%d", server.port))
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bundle and start the HTTP server
|
||||||
|
server.httpSrv = &http.Server{
|
||||||
|
Handler: server,
|
||||||
|
}
|
||||||
|
go server.httpSrv.Serve(listener)
|
||||||
|
if server.unixSocket == "" {
|
||||||
|
server.port = listener.Addr().(*net.TCPAddr).Port
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *transitionServer) shutdown() error {
|
||||||
|
if server.httpSrv == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return server.httpSrv.Shutdown(context.Background())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (server *transitionServer) ServeHTTP(res http.ResponseWriter, req *http.Request) {
|
||||||
|
reqStartTime := time.Now()
|
||||||
|
decoder := json.NewDecoder(req.Body)
|
||||||
|
var request transitionRequest
|
||||||
|
// Parse this from the http request
|
||||||
|
if err := decoder.Decode(&request); err != nil {
|
||||||
|
http.Error(res, fmt.Sprintf("failed unmarshalling request: %v", err), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
output, err := request.process(server.tracerGenFn)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(res, fmt.Sprintf("failed processing request: %v", err), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the http response
|
||||||
|
res.Header().Set("Content-Type", "application/json")
|
||||||
|
json.NewEncoder(res).Encode(output)
|
||||||
|
log.Info("Processed request", "duration", time.Since(reqStartTime))
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyLondonChecks(env *stEnv, chainConfig *params.ChainConfig) error {
|
func applyLondonChecks(env *stEnv, chainConfig *params.ChainConfig) error {
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,10 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -112,37 +108,6 @@ func signUnsignedTransactions(txs []*txWithKey, signer types.Signer) (types.Tran
|
||||||
return signedTxs, nil
|
return signedTxs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadTransactions(txStr string, inputData *input, env stEnv, chainConfig *params.ChainConfig) (txIterator, error) {
|
|
||||||
var txsWithKeys []*txWithKey
|
|
||||||
if txStr != stdinSelector {
|
|
||||||
data, err := os.ReadFile(txStr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, NewError(ErrorIO, fmt.Errorf("failed reading txs file: %v", err))
|
|
||||||
}
|
|
||||||
if strings.HasSuffix(txStr, ".rlp") { // A file containing an rlp list
|
|
||||||
var body hexutil.Bytes
|
|
||||||
if err := json.Unmarshal(data, &body); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return newRlpTxIterator(body), nil
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(data, &txsWithKeys); err != nil {
|
|
||||||
return nil, NewError(ErrorJson, fmt.Errorf("failed unmarshalling txs-file: %v", err))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if len(inputData.TxRlp) > 0 {
|
|
||||||
// Decode the body of already signed transactions
|
|
||||||
return newRlpTxIterator(common.FromHex(inputData.TxRlp)), nil
|
|
||||||
}
|
|
||||||
// JSON encoded transactions
|
|
||||||
txsWithKeys = inputData.Txs
|
|
||||||
}
|
|
||||||
// We may have to sign the transactions.
|
|
||||||
signer := types.LatestSignerForChainID(chainConfig.ChainID)
|
|
||||||
txs, err := signUnsignedTransactions(txsWithKeys, signer)
|
|
||||||
return newSliceTxIterator(txs), err
|
|
||||||
}
|
|
||||||
|
|
||||||
type txIterator interface {
|
type txIterator interface {
|
||||||
// Next returns true until EOF
|
// Next returns true until EOF
|
||||||
Next() bool
|
Next() bool
|
||||||
|
|
|
||||||
|
|
@ -40,15 +40,20 @@ func readFile(path, desc string, dest interface{}) error {
|
||||||
|
|
||||||
// createBasedir makes sure the basedir exists, if user specified one.
|
// createBasedir makes sure the basedir exists, if user specified one.
|
||||||
func createBasedir(ctx *cli.Context) (string, error) {
|
func createBasedir(ctx *cli.Context) (string, error) {
|
||||||
baseDir := ""
|
|
||||||
if ctx.IsSet(OutputBasedir.Name) {
|
if ctx.IsSet(OutputBasedir.Name) {
|
||||||
if base := ctx.String(OutputBasedir.Name); len(base) > 0 {
|
base := ctx.String(OutputBasedir.Name)
|
||||||
err := os.MkdirAll(base, 0755) // //rw-r--r--
|
return createBasedirFromString(base)
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
baseDir = base
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return baseDir, nil
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createBasedirFromString(baseDirPath string) (string, error) {
|
||||||
|
if len(baseDirPath) > 0 {
|
||||||
|
err := os.MkdirAll(baseDirPath, 0755) // //rw-r--r--
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return baseDirPath, nil
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,24 @@ var stateTransitionCommand = &cli.Command{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var stateTransitionServerCommand = &cli.Command{
|
||||||
|
Name: "transition-server",
|
||||||
|
Aliases: []string{"t8n-server"},
|
||||||
|
Usage: "Instantiates a server that accepts requests for full state transition",
|
||||||
|
Action: t8ntool.TransitionServer,
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
t8ntool.TraceFlag,
|
||||||
|
t8ntool.TraceTracerFlag,
|
||||||
|
t8ntool.TraceTracerConfigFlag,
|
||||||
|
t8ntool.TraceEnableMemoryFlag,
|
||||||
|
t8ntool.TraceDisableStackFlag,
|
||||||
|
t8ntool.TraceEnableReturnDataFlag,
|
||||||
|
t8ntool.TraceEnableCallFramesFlag,
|
||||||
|
t8ntool.PortFlag,
|
||||||
|
t8ntool.UnixSocketFlag,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
var transactionCommand = &cli.Command{
|
var transactionCommand = &cli.Command{
|
||||||
Name: "transaction",
|
Name: "transaction",
|
||||||
Aliases: []string{"t9n"},
|
Aliases: []string{"t9n"},
|
||||||
|
|
@ -233,6 +251,7 @@ func init() {
|
||||||
blockTestCommand,
|
blockTestCommand,
|
||||||
stateTestCommand,
|
stateTestCommand,
|
||||||
stateTransitionCommand,
|
stateTransitionCommand,
|
||||||
|
stateTransitionServerCommand,
|
||||||
transactionCommand,
|
transactionCommand,
|
||||||
blockBuilderCommand,
|
blockBuilderCommand,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue