diff --git a/cmd/wazero/wazero.go b/cmd/wazero/wazero.go index 08a7d9a468..6c08bd8a62 100644 --- a/cmd/wazero/wazero.go +++ b/cmd/wazero/wazero.go @@ -210,13 +210,17 @@ func doRun(args []string, stdOut io.Writer, stdErr logging.Writer) int { } // TODO: maybe better usage description? - var stylusTracePath string - flags.StringVar(&stylusTracePath, "stylus", "", - "Imports the EVM hook functions and mocks their IO according the result of debug_traceTransaction in the path provided.") + var stylusTxHash string + flags.StringVar(&stylusTxHash, "stylus", "", + "Imports the EVM hook functions and mocks their IO using debug_traceTransaction for the given transaction hash.") + + var stylusRpcUrl string + flags.StringVar(&stylusRpcUrl, "stylus-rpc", "http://localhost:8547", + "RPC endpoint used when fetching Stylus traces.") var traceDir string flags.StringVar(&traceDir, "trace-dir", "", - "Directory where to save the trace record. If empty - no trace is produced. Default \"\".") + "Directory where to save the trace record. If empty - no trace is produced. (default \"\")") cacheDir := cacheDirFlag(flags) @@ -342,9 +346,9 @@ func doRun(args []string, stdOut io.Writer, stdErr logging.Writer) int { traceRecordPtr = &traceRecord } - var stylusState *stylus.StylusTrace - if stylusTracePath != "" { - stylusState, err = stylus.Instantiate(ctx, rt, stylusTracePath, traceRecordPtr) + var stylusState *stylus.StylusState + if stylusTxHash != "" { + stylusState, err = stylus.Instantiate(ctx, rt, stylusRpcUrl, stylusTxHash, traceRecordPtr) if err != nil { fmt.Fprintf(stdErr, "error reading stylus trace: %v\n", err) return 1 @@ -382,7 +386,7 @@ func doRun(args []string, stdOut io.Writer, stdErr logging.Writer) int { return 1 } - if stylusTracePath != "" { + if stylusTxHash != "" { arg, err := stylusState.GetEntrypointArg() if err != nil { fmt.Fprintf(stdErr, "error reading stylus entrypoint argument: %v\n", err) diff --git a/internal/stylus/json_rpc.go b/internal/stylus/json_rpc.go new file mode 100644 index 0000000000..8d85cdd97e --- /dev/null +++ b/internal/stylus/json_rpc.go @@ -0,0 +1,66 @@ +package stylus + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" +) + +type RpcClient struct { + url string + id int +} + +func NewRpcClient(url string) *RpcClient { + return &RpcClient{url: url, id: 0} +} + +func (client *RpcClient) Request(method string, params any) (json.RawMessage, error) { + data, err := json.Marshal(rpcRequest{ + Jsonrpc: "2.0", + Method: method, + Params: params, + Id: client.id, + }) + if err != nil { + return nil, err + } + client.id++ + + resp, err := http.Post(client.url, "application/json", bytes.NewBuffer(data)) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + var rpcResp rpcResponse + if err := json.NewDecoder(resp.Body).Decode(&rpcResp); err != nil { + return nil, err + } + + if rpcResp.Error != nil { + return nil, fmt.Errorf("JSON RPC returned error: %v", *rpcResp.Error) + } + + return rpcResp.Result, nil +} + +type rpcRequest struct { + Jsonrpc string `json:"jsonrpc"` + Method string `json:"method"` + Params interface{} `json:"params,omitempty"` + Id int `json:"id"` +} + +type rpcResponse struct { + Jsonrpc string `json:"jsonrpc"` + Result json.RawMessage `json:"result,omitempty"` + Error *rpcError `json:"error,omitempty"` + Id int `json:"id"` +} + +type rpcError struct { + Code int `json:"code"` + Message string `json:"message"` +} diff --git a/internal/stylus/stylus.go b/internal/stylus/stylus.go index 6a8ae247c9..82ddb22aab 100644 --- a/internal/stylus/stylus.go +++ b/internal/stylus/stylus.go @@ -3,30 +3,125 @@ package stylus import ( "context" "encoding/json" - "os" + "fmt" "github.com/metacraft-labs/trace_record" "github.com/tetratelabs/wazero" ) -func Instantiate(ctx context.Context, r wazero.Runtime, stylusTracePath string, record *trace_record.TraceRecord) (*StylusTrace, error) { - stylusTraceJson, err := os.ReadFile(stylusTracePath) +func Instantiate(ctx context.Context, r wazero.Runtime, rpcUrl string, txHash string, record *trace_record.TraceRecord) (result *StylusState, err error) { + rpcClient := NewRpcClient(rpcUrl) + + result = &StylusState{} + + result.txHash = txHash + + reciept, err := rpcClient.requestTxReciept(txHash) if err != nil { - return nil, err + return + } + + if reciept.To == nil { + err = fmt.Errorf("the \"to\" of the transaction is null") + return } - stylusState := StylusTrace{} + result.address = *reciept.To + result.blockNumber = reciept.BlockNumber + result.blockHash = reciept.BlockHash + result.txIndex = reciept.TransactionIndex - if err := json.Unmarshal(stylusTraceJson, &stylusState.events); err != nil { - return nil, err + result.evmEvents, err = rpcClient.requestDebugTraceTransaction(txHash) + if err != nil { + return } + _, _ = rpcClient.requestAlteredStorageInBlockBeforeTransaction(result.blockHash, result.txIndex, result.address) + moduleBuilder := r.NewHostModuleBuilder("vm_hooks") - moduleBuilder = exportSylusFunctions(moduleBuilder, &stylusState, record) + moduleBuilder = exportSylusFunctions(moduleBuilder, result, record) if _, err := moduleBuilder.Instantiate(ctx); err != nil { return nil, err } - return &stylusState, nil + return +} + +type TxReceipt struct { + BlockNumber string `json:"blockNumber"` + BlockHash string `json:"blockHash"` + To *string `json:"to"` + TransactionIndex string `json:"transactionIndex"` +} + +func (client *RpcClient) requestTxReciept(txHash string) (result TxReceipt, err error) { + rawTx, err := client.Request("eth_getTransactionReceipt", []interface{}{txHash}) + if err != nil { + return + } + + if err = json.Unmarshal(rawTx, &result); err != nil { + return + } + + return +} + +func (client *RpcClient) requestDebugTraceTransaction(txHash string) ([]evmEvent, error) { + rawJson, err := client.Request( + "debug_traceTransaction", + []interface{}{ + txHash, + struct { + Tracer string `json:"tracer"` + }{ + Tracer: "stylusTracer", + }, + }, + ) + + if err != nil { + return nil, err + } + + var res []evmEvent + json.Unmarshal(rawJson, &res) + + return res, nil +} + +func (client *RpcClient) requestAlteredStorageInBlockBeforeTransaction(blockHash string, txIndex string, address string) (interface{}, error) { + fmt.Printf("%#v\n", []interface{}{ + blockHash, + 1, + address, + "0x0000000000000000000000000000000000000000000000000000000000000000", + 4096, // TODO: discuss if this is enough + }) + rawJson, err := client.Request( + "debug_storageRangeAt", + []interface{}{ + blockHash, + 1, + address, + "0x0000000000000000000000000000000000000000000000000000000000000000", + 4096, // TODO: discuss if this is enough + }, + ) + + if err != nil { + fmt.Printf("FAIL: %v\n", err) + return nil, err + } + + tmp, err := json.Marshal(rawJson) + + fmt.Printf("OK: %s\n", string(tmp)) + + if err != nil { + return nil, err + } + + return rawJson, nil } diff --git a/internal/stylus/stylus_funcs.go b/internal/stylus/stylus_funcs.go index 56c7bed2b0..eedb4a41e6 100644 --- a/internal/stylus/stylus_funcs.go +++ b/internal/stylus/stylus_funcs.go @@ -12,7 +12,7 @@ import ( // exportFunc reduces boilerplate for building Stylus host hooks. It fetches the // next event and forwards it to fn. -func exportFunc(mb wazero.HostModuleBuilder, trace *StylusTrace, name string, +func exportFunc(mb wazero.HostModuleBuilder, trace *StylusState, name string, params, results []api.ValueType, fn func(m api.Module, stack []uint64, event evmEvent)) wazero.HostModuleBuilder { return mb.NewFunctionBuilder(). @@ -28,7 +28,7 @@ func exportFunc(mb wazero.HostModuleBuilder, trace *StylusTrace, name string, ).Export(name) } -func exportSylusFunctions(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportSylusFunctions(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { result := mb result = exportReadArgs(result, trace, record) result = exportWriteResult(result, trace, record) @@ -71,7 +71,7 @@ func exportSylusFunctions(mb wazero.HostModuleBuilder, trace *StylusTrace, recor // TODO: what happens when gas or ink runs out // TODO: add record logs for events -func exportReadArgs(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportReadArgs(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "read_args", []api.ValueType{api.ValueTypeI32}, []api.ValueType{}, func(m api.Module, stack []uint64, event evmEvent) { @@ -83,7 +83,7 @@ func exportReadArgs(mb wazero.HostModuleBuilder, trace *StylusTrace, record *tra }) } -func exportWriteResult(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportWriteResult(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "write_result", []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}, func(m api.Module, stack []uint64, event evmEvent) { @@ -96,7 +96,7 @@ func exportWriteResult(mb wazero.HostModuleBuilder, trace *StylusTrace, record * }) } -func exportReadReturnData(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportReadReturnData(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "read_return_data", []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}, @@ -110,7 +110,7 @@ func exportReadReturnData(mb wazero.HostModuleBuilder, trace *StylusTrace, recor }) } -func exportCreate2(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportCreate2(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "create2", []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}, func(m api.Module, stack []uint64, event evmEvent) { @@ -132,7 +132,7 @@ func exportCreate2(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trac }) } -func exportCreate1(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportCreate1(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "create1", []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}, func(m api.Module, stack []uint64, event evmEvent) { @@ -152,7 +152,7 @@ func exportCreate1(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trac }) } -func exportAccountBalance(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportAccountBalance(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "account_balance", []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}, func(m api.Module, stack []uint64, event evmEvent) { @@ -167,7 +167,7 @@ func exportAccountBalance(mb wazero.HostModuleBuilder, trace *StylusTrace, recor }) } -func exportAccountCode(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportAccountCode(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "account_code", []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}, @@ -184,7 +184,7 @@ func exportAccountCode(mb wazero.HostModuleBuilder, trace *StylusTrace, record * }) } -func exportAccountCodeSize(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportAccountCodeSize(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "account_code_size", []api.ValueType{api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}, @@ -200,7 +200,7 @@ func exportAccountCodeSize(mb wazero.HostModuleBuilder, trace *StylusTrace, reco }) } -func exportAccountCodehash(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportAccountCodehash(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "account_codehash", []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}, func(m api.Module, stack []uint64, event evmEvent) { @@ -215,7 +215,7 @@ func exportAccountCodehash(mb wazero.HostModuleBuilder, trace *StylusTrace, reco }) } -func exportReturnDataSize(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportReturnDataSize(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "return_data_size", []api.ValueType{}, []api.ValueType{api.ValueTypeI32}, func(m api.Module, stack []uint64, event evmEvent) { @@ -227,7 +227,7 @@ func exportReturnDataSize(mb wazero.HostModuleBuilder, trace *StylusTrace, recor }) } -func exportContractAddress(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportContractAddress(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "contract_address", []api.ValueType{api.ValueTypeI32}, []api.ValueType{}, func(m api.Module, stack []uint64, event evmEvent) { @@ -239,7 +239,7 @@ func exportContractAddress(mb wazero.HostModuleBuilder, trace *StylusTrace, reco }) } -func exportMsgReentrant(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportMsgReentrant(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "msg_reentrant", []api.ValueType{}, []api.ValueType{api.ValueTypeI32}, func(m api.Module, stack []uint64, event evmEvent) { @@ -251,7 +251,7 @@ func exportMsgReentrant(mb wazero.HostModuleBuilder, trace *StylusTrace, record }) } -func exportMsgSender(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportMsgSender(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "msg_sender", []api.ValueType{api.ValueTypeI32}, []api.ValueType{}, func(m api.Module, stack []uint64, event evmEvent) { @@ -263,7 +263,7 @@ func exportMsgSender(mb wazero.HostModuleBuilder, trace *StylusTrace, record *tr }) } -func exportMsgValue(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportMsgValue(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "msg_value", []api.ValueType{api.ValueTypeI32}, []api.ValueType{}, func(m api.Module, stack []uint64, event evmEvent) { @@ -275,7 +275,7 @@ func exportMsgValue(mb wazero.HostModuleBuilder, trace *StylusTrace, record *tra }) } -func exportTxInkPrice(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportTxInkPrice(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "tx_ink_price", []api.ValueType{}, []api.ValueType{api.ValueTypeI32}, func(m api.Module, stack []uint64, event evmEvent) { @@ -287,7 +287,7 @@ func exportTxInkPrice(mb wazero.HostModuleBuilder, trace *StylusTrace, record *t }) } -func exportTxGasPrice(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportTxGasPrice(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "tx_gas_price", []api.ValueType{api.ValueTypeI32}, []api.ValueType{}, func(m api.Module, stack []uint64, event evmEvent) { @@ -299,7 +299,7 @@ func exportTxGasPrice(mb wazero.HostModuleBuilder, trace *StylusTrace, record *t }) } -func exportTxOrigin(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportTxOrigin(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "tx_origin", []api.ValueType{api.ValueTypeI32}, []api.ValueType{}, func(m api.Module, stack []uint64, event evmEvent) { @@ -311,7 +311,7 @@ func exportTxOrigin(mb wazero.HostModuleBuilder, trace *StylusTrace, record *tra }) } -func exportNativeKeccak256(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportNativeKeccak256(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "native_keccak256", []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}, func(m api.Module, stack []uint64, event evmEvent) { @@ -327,7 +327,7 @@ func exportNativeKeccak256(mb wazero.HostModuleBuilder, trace *StylusTrace, reco }) } -func exportStorageCacheBytes32(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportStorageCacheBytes32(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "storage_cache_bytes32", []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}, func(m api.Module, stack []uint64, event evmEvent) { @@ -344,7 +344,7 @@ func exportStorageCacheBytes32(mb wazero.HostModuleBuilder, trace *StylusTrace, }) } -func exportStorageLoadBytes32(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportStorageLoadBytes32(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "storage_load_bytes32", []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}, func(m api.Module, stack []uint64, event evmEvent) { @@ -359,7 +359,7 @@ func exportStorageLoadBytes32(mb wazero.HostModuleBuilder, trace *StylusTrace, r }) } -func exportStorageFlushCache(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportStorageFlushCache(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "storage_flush_cache", []api.ValueType{api.ValueTypeI32}, []api.ValueType{}, func(m api.Module, stack []uint64, event evmEvent) { @@ -370,7 +370,7 @@ func exportStorageFlushCache(mb wazero.HostModuleBuilder, trace *StylusTrace, re }) } -func exportEmitLog(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportEmitLog(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "emit_log", []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}, func(m api.Module, stack []uint64, event evmEvent) { @@ -385,7 +385,7 @@ func exportEmitLog(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trac }) } -func exportCallContract(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportCallContract(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "call_contract", []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI64, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}, @@ -407,7 +407,7 @@ func exportCallContract(mb wazero.HostModuleBuilder, trace *StylusTrace, record }) } -func exportDelegateCallContract(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportDelegateCallContract(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "delegate_call_contract", []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI64, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}, @@ -427,7 +427,7 @@ func exportDelegateCallContract(mb wazero.HostModuleBuilder, trace *StylusTrace, }) } -func exportStaticCallContract(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportStaticCallContract(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "static_call_contract", []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI64, api.ValueTypeI32}, []api.ValueType{api.ValueTypeI32}, @@ -447,7 +447,7 @@ func exportStaticCallContract(mb wazero.HostModuleBuilder, trace *StylusTrace, r }) } -func exportBlockBasefee(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportBlockBasefee(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "block_basefee", []api.ValueType{api.ValueTypeI32}, []api.ValueType{}, func(m api.Module, stack []uint64, event evmEvent) { @@ -459,7 +459,7 @@ func exportBlockBasefee(mb wazero.HostModuleBuilder, trace *StylusTrace, record }) } -func exportChainid(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportChainid(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "chainid", []api.ValueType{}, []api.ValueType{api.ValueTypeI64}, func(m api.Module, stack []uint64, event evmEvent) { @@ -471,7 +471,7 @@ func exportChainid(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trac }) } -func exportBlockCoinbase(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportBlockCoinbase(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "block_coinbase", []api.ValueType{api.ValueTypeI32}, []api.ValueType{}, func(m api.Module, stack []uint64, event evmEvent) { @@ -483,7 +483,7 @@ func exportBlockCoinbase(mb wazero.HostModuleBuilder, trace *StylusTrace, record }) } -func exportBlockGasLimit(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportBlockGasLimit(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "block_gas_limit", []api.ValueType{}, []api.ValueType{api.ValueTypeI64}, func(m api.Module, stack []uint64, event evmEvent) { @@ -495,7 +495,7 @@ func exportBlockGasLimit(mb wazero.HostModuleBuilder, trace *StylusTrace, record }) } -func exportBlockNumber(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportBlockNumber(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "block_number", []api.ValueType{}, []api.ValueType{api.ValueTypeI64}, func(m api.Module, stack []uint64, event evmEvent) { @@ -507,7 +507,7 @@ func exportBlockNumber(mb wazero.HostModuleBuilder, trace *StylusTrace, record * }) } -func exportBlockTimestamp(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportBlockTimestamp(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "block_timestamp", []api.ValueType{}, []api.ValueType{api.ValueTypeI64}, func(m api.Module, stack []uint64, event evmEvent) { @@ -519,7 +519,7 @@ func exportBlockTimestamp(mb wazero.HostModuleBuilder, trace *StylusTrace, recor }) } -func exportPayForMemoryGrow(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportPayForMemoryGrow(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "pay_for_memory_grow", []api.ValueType{api.ValueTypeI32}, []api.ValueType{}, func(m api.Module, stack []uint64, event evmEvent) { @@ -530,7 +530,7 @@ func exportPayForMemoryGrow(mb wazero.HostModuleBuilder, trace *StylusTrace, rec }) } -func exportEvmGasLeft(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportEvmGasLeft(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "evm_gas_left", []api.ValueType{}, []api.ValueType{api.ValueTypeI64}, func(m api.Module, stack []uint64, event evmEvent) { @@ -542,7 +542,7 @@ func exportEvmGasLeft(mb wazero.HostModuleBuilder, trace *StylusTrace, record *t }) } -func exportEvmInkLeft(mb wazero.HostModuleBuilder, trace *StylusTrace, record *trace_record.TraceRecord) wazero.HostModuleBuilder { +func exportEvmInkLeft(mb wazero.HostModuleBuilder, trace *StylusState, record *trace_record.TraceRecord) wazero.HostModuleBuilder { return exportFunc(mb, trace, "evm_ink_left", []api.ValueType{}, []api.ValueType{api.ValueTypeI64}, func(m api.Module, stack []uint64, event evmEvent) { diff --git a/internal/stylus/stylus_trace.go b/internal/stylus/stylus_trace.go index a4650080fc..32f885a707 100644 --- a/internal/stylus/stylus_trace.go +++ b/internal/stylus/stylus_trace.go @@ -62,29 +62,37 @@ func (e *evmEvent) UnmarshalJSON(data []byte) error { return nil } -type StylusTrace struct { - events []evmEvent - current int +type StylusState struct { + txHash string + address string + blockNumber string + blockHash string + txIndex string + + evmEvents []evmEvent + currentEvent int + + storageSlots map[string][]byte } -func (st *StylusTrace) nextEvent(event string) (evmEvent, error) { - fmt.Printf("Current event requested: %v (%v/%v)\n", event, st.current+1, len(st.events)) +func (st *StylusState) nextEvent(event string) (evmEvent, error) { + fmt.Printf("Current event requested: %v (%v/%v)\n", event, st.currentEvent+1, len(st.evmEvents)) // TODO: maybe validate arguments? - if st.current >= len(st.events) { + if st.currentEvent >= len(st.evmEvents) { return evmEvent{}, fmt.Errorf("no next stylus event") } - res := st.events[st.current] + res := st.evmEvents[st.currentEvent] if res.name != event { return evmEvent{}, fmt.Errorf("mismatched event types: expected %v but found %v", event, res.name) } - st.current++ + st.currentEvent++ return res, nil } -func (st *StylusTrace) GetEntrypointArg() (uint64, error) { +func (st *StylusState) GetEntrypointArg() (uint64, error) { event, err := st.nextEvent("user_entrypoint") if err != nil { return 0, err @@ -94,7 +102,7 @@ func (st *StylusTrace) GetEntrypointArg() (uint64, error) { return uint64(arg), err } -func (st *StylusTrace) GetReturnedValue() (uint64, error) { +func (st *StylusState) GetReturnedValue() (uint64, error) { event, err := st.nextEvent("user_returned") if err != nil { return 0, err