mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-28 07:36:44 +00:00
feat(trace): Add header and upgrade TransactionTrace (#181)
* Add header and upgrade TransactionTrace * Add header * change blockResult struct * rm chainID from TransactionData * Rename blockResult to blockTrace in everywhere * fix comments
This commit is contained in:
parent
f21acfee4a
commit
22963a115d
7 changed files with 88 additions and 134 deletions
|
|
@ -21,9 +21,11 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
// BlockResult contains block execution traces and results required for rollers.
|
||||
type BlockResult struct {
|
||||
BlockTrace *BlockTrace `json:"blockTrace"`
|
||||
// BlockTrace contains block execution traces and results required for rollers.
|
||||
type BlockTrace struct {
|
||||
Coinbase *AccountWrapper `json:"coinbase"`
|
||||
Header *Header `json:"header"`
|
||||
Transactions []*TransactionData `json:"transactions"`
|
||||
StorageTrace *StorageTrace `json:"storageTrace"`
|
||||
ExecutionResults []*ExecutionResult `json:"executionResults"`
|
||||
MPTWitness *json.RawMessage `json:"mptwitness,omitempty"`
|
||||
|
|
|
|||
|
|
@ -4,78 +4,23 @@ import (
|
|||
"math/big"
|
||||
|
||||
"github.com/scroll-tech/go-ethereum/common"
|
||||
"github.com/scroll-tech/go-ethereum/common/hexutil"
|
||||
"github.com/scroll-tech/go-ethereum/params"
|
||||
)
|
||||
|
||||
type BlockTrace struct {
|
||||
Number *hexutil.Big `json:"number"`
|
||||
Hash common.Hash `json:"hash"`
|
||||
GasLimit uint64 `json:"gasLimit"`
|
||||
Difficulty *hexutil.Big `json:"difficulty"`
|
||||
BaseFee *hexutil.Big `json:"baseFee"`
|
||||
Coinbase *AccountWrapper `json:"coinbase"`
|
||||
Time uint64 `json:"time"`
|
||||
Transactions []*TransactionTrace `json:"transactions"`
|
||||
type TransactionData struct {
|
||||
IsCreate bool `json:"isCreate"`
|
||||
From common.Address `json:"from"`
|
||||
*Transaction
|
||||
}
|
||||
|
||||
type TransactionTrace struct {
|
||||
Type uint8 `json:"type"`
|
||||
Nonce uint64 `json:"nonce"`
|
||||
TxHash string `json:"txHash"`
|
||||
Gas uint64 `json:"gas"`
|
||||
GasPrice *hexutil.Big `json:"gasPrice"`
|
||||
From common.Address `json:"from"`
|
||||
To *common.Address `json:"to"`
|
||||
ChainId *hexutil.Big `json:"chainId"`
|
||||
Value *hexutil.Big `json:"value"`
|
||||
Data string `json:"data"`
|
||||
IsCreate bool `json:"isCreate"`
|
||||
V *hexutil.Big `json:"v"`
|
||||
R *hexutil.Big `json:"r"`
|
||||
S *hexutil.Big `json:"s"`
|
||||
}
|
||||
|
||||
// NewTraceBlock supports necessary fields for roller.
|
||||
func NewTraceBlock(config *params.ChainConfig, block *Block, coinbase *AccountWrapper) *BlockTrace {
|
||||
txs := make([]*TransactionTrace, block.Transactions().Len())
|
||||
for i, tx := range block.Transactions() {
|
||||
txs[i] = newTraceTransaction(tx, block.NumberU64(), config)
|
||||
}
|
||||
|
||||
return &BlockTrace{
|
||||
Number: (*hexutil.Big)(block.Number()),
|
||||
Hash: block.Hash(),
|
||||
GasLimit: block.GasLimit(),
|
||||
Difficulty: (*hexutil.Big)(block.Difficulty()),
|
||||
BaseFee: (*hexutil.Big)(block.BaseFee()),
|
||||
Coinbase: coinbase,
|
||||
Time: block.Time(),
|
||||
Transactions: txs,
|
||||
}
|
||||
}
|
||||
|
||||
// newTraceTransaction returns a transaction that will serialize to the trace
|
||||
// NewTraceTransaction returns a transaction that will serialize to the trace
|
||||
// representation, with the given location metadata set (if available).
|
||||
func newTraceTransaction(tx *Transaction, blockNumber uint64, config *params.ChainConfig) *TransactionTrace {
|
||||
func NewTraceTransaction(tx *Transaction, blockNumber uint64, config *params.ChainConfig) *TransactionData {
|
||||
signer := MakeSigner(config, big.NewInt(0).SetUint64(blockNumber))
|
||||
from, _ := Sender(signer, tx)
|
||||
v, r, s := tx.RawSignatureValues()
|
||||
result := &TransactionTrace{
|
||||
Type: tx.Type(),
|
||||
TxHash: tx.Hash().String(),
|
||||
Nonce: tx.Nonce(),
|
||||
ChainId: (*hexutil.Big)(tx.ChainId()),
|
||||
From: from,
|
||||
Gas: tx.Gas(),
|
||||
GasPrice: (*hexutil.Big)(tx.GasPrice()),
|
||||
To: tx.To(),
|
||||
Value: (*hexutil.Big)(tx.Value()),
|
||||
Data: hexutil.Encode(tx.Data()),
|
||||
IsCreate: tx.To() == nil,
|
||||
V: (*hexutil.Big)(v),
|
||||
R: (*hexutil.Big)(r),
|
||||
S: (*hexutil.Big)(s),
|
||||
return &TransactionData{
|
||||
From: from,
|
||||
IsCreate: tx.To() == nil,
|
||||
Transaction: tx,
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import (
|
|||
)
|
||||
|
||||
type TraceBlock interface {
|
||||
GetBlockResultByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, config *TraceConfig) (trace *types.BlockResult, err error)
|
||||
GetBlockTraceByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, config *TraceConfig) (trace *types.BlockTrace, err error)
|
||||
}
|
||||
|
||||
type traceEnv struct {
|
||||
|
|
@ -42,8 +42,8 @@ type traceEnv struct {
|
|||
executionResults []*types.ExecutionResult
|
||||
}
|
||||
|
||||
// GetBlockResultByNumberOrHash replays the block and returns the structured BlockResult by hash or number.
|
||||
func (api *API) GetBlockResultByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, config *TraceConfig) (trace *types.BlockResult, err error) {
|
||||
// GetBlockTraceByNumberOrHash replays the block and returns the structured BlockTrace by hash or number.
|
||||
func (api *API) GetBlockTraceByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, config *TraceConfig) (trace *types.BlockTrace, err error) {
|
||||
var block *types.Block
|
||||
if number, ok := blockNrOrHash.Number(); ok {
|
||||
block, err = api.blockByNumber(ctx, number)
|
||||
|
|
@ -75,7 +75,7 @@ func (api *API) GetBlockResultByNumberOrHash(ctx context.Context, blockNrOrHash
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return api.getBlockResult(block, env)
|
||||
return api.getBlockTrace(block, env)
|
||||
}
|
||||
|
||||
// Make trace environment for current block.
|
||||
|
|
@ -130,7 +130,7 @@ func (api *API) createTraceEnv(ctx context.Context, config *TraceConfig, block *
|
|||
return env, nil
|
||||
}
|
||||
|
||||
func (api *API) getBlockResult(block *types.Block, env *traceEnv) (*types.BlockResult, error) {
|
||||
func (api *API) getBlockTrace(block *types.Block, env *traceEnv) (*types.BlockTrace, error) {
|
||||
// Execute all the transaction contained within the block concurrently
|
||||
var (
|
||||
txs = block.Transactions()
|
||||
|
|
@ -190,7 +190,7 @@ func (api *API) getBlockResult(block *types.Block, env *traceEnv) (*types.BlockR
|
|||
}
|
||||
}
|
||||
|
||||
return api.fillBlockResult(env, block)
|
||||
return api.fillBlockTrace(env, block)
|
||||
}
|
||||
|
||||
func (api *API) getTxResult(env *traceEnv, state *state.StateDB, index int, block *types.Block) error {
|
||||
|
|
@ -328,22 +328,29 @@ func (api *API) getTxResult(env *traceEnv, state *state.StateDB, index int, bloc
|
|||
return nil
|
||||
}
|
||||
|
||||
// Fill blockResult content after all the txs are finished running.
|
||||
func (api *API) fillBlockResult(env *traceEnv, block *types.Block) (*types.BlockResult, error) {
|
||||
// Fill blockTrace content after all the txs are finished running.
|
||||
func (api *API) fillBlockTrace(env *traceEnv, block *types.Block) (*types.BlockTrace, error) {
|
||||
statedb := env.state
|
||||
txs := block.Transactions()
|
||||
coinbase := types.AccountWrapper{
|
||||
Address: env.coinbase,
|
||||
Nonce: statedb.GetNonce(env.coinbase),
|
||||
Balance: (*hexutil.Big)(statedb.GetBalance(env.coinbase)),
|
||||
CodeHash: statedb.GetCodeHash(env.coinbase),
|
||||
|
||||
txs := make([]*types.TransactionData, block.Transactions().Len())
|
||||
for i, tx := range block.Transactions() {
|
||||
txs[i] = types.NewTraceTransaction(tx, block.NumberU64(), api.backend.ChainConfig())
|
||||
}
|
||||
blockResult := &types.BlockResult{
|
||||
BlockTrace: types.NewTraceBlock(api.backend.ChainConfig(), block, &coinbase),
|
||||
|
||||
blockTrace := &types.BlockTrace{
|
||||
Coinbase: &types.AccountWrapper{
|
||||
Address: env.coinbase,
|
||||
Nonce: statedb.GetNonce(env.coinbase),
|
||||
Balance: (*hexutil.Big)(statedb.GetBalance(env.coinbase)),
|
||||
CodeHash: statedb.GetCodeHash(env.coinbase),
|
||||
},
|
||||
Header: block.Header(),
|
||||
StorageTrace: env.StorageTrace,
|
||||
ExecutionResults: env.executionResults,
|
||||
Transactions: txs,
|
||||
}
|
||||
for i, tx := range txs {
|
||||
|
||||
for i, tx := range block.Transactions() {
|
||||
evmTrace := env.executionResults[i]
|
||||
// probably a Contract Call
|
||||
if len(tx.Data()) != 0 && tx.To() != nil {
|
||||
|
|
@ -358,10 +365,10 @@ func (api *API) fillBlockResult(env *traceEnv, block *types.Block) (*types.Block
|
|||
|
||||
// only zktrie model has the ability to get `mptwitness`.
|
||||
if api.backend.ChainConfig().Zktrie {
|
||||
if err := zkproof.FillBlockResultForMPTWitness(zkproof.MPTWitnessType(api.backend.CacheConfig().MPTWitness), blockResult); err != nil {
|
||||
if err := zkproof.FillBlockTraceForMPTWitness(zkproof.MPTWitnessType(api.backend.CacheConfig().MPTWitness), blockTrace); err != nil {
|
||||
log.Error("fill mpt witness fail", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
return blockResult, nil
|
||||
return blockTrace, nil
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -325,21 +325,21 @@ func (ec *Client) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header)
|
|||
return ec.c.EthSubscribe(ctx, ch, "newHeads")
|
||||
}
|
||||
|
||||
// GetBlockResultByHash returns the BlockResult given the block hash.
|
||||
func (ec *Client) GetBlockResultByHash(ctx context.Context, blockHash common.Hash) (*types.BlockResult, error) {
|
||||
blockResult := &types.BlockResult{}
|
||||
return blockResult, ec.c.CallContext(ctx, &blockResult, "scroll_getBlockResultByNumberOrHash", blockHash)
|
||||
// GetBlockTraceByHash returns the BlockTrace given the block hash.
|
||||
func (ec *Client) GetBlockTraceByHash(ctx context.Context, blockHash common.Hash) (*types.BlockTrace, error) {
|
||||
blockTrace := &types.BlockTrace{}
|
||||
return blockTrace, ec.c.CallContext(ctx, &blockTrace, "scroll_getBlockTraceByNumberOrHash", blockHash)
|
||||
}
|
||||
|
||||
// GetBlockResultByNumber returns the BlockResult given the block number.
|
||||
func (ec *Client) GetBlockResultByNumber(ctx context.Context, number *big.Int) (*types.BlockResult, error) {
|
||||
blockResult := &types.BlockResult{}
|
||||
return blockResult, ec.c.CallContext(ctx, &blockResult, "scroll_getBlockResultByNumberOrHash", toBlockNumArg(number))
|
||||
// GetBlockTraceByNumber returns the BlockTrace given the block number.
|
||||
func (ec *Client) GetBlockTraceByNumber(ctx context.Context, number *big.Int) (*types.BlockTrace, error) {
|
||||
blockTrace := &types.BlockTrace{}
|
||||
return blockTrace, ec.c.CallContext(ctx, &blockTrace, "scroll_getBlockTraceByNumberOrHash", toBlockNumArg(number))
|
||||
}
|
||||
|
||||
// SubscribeNewBlockResult subscribes to block execution trace when a new block is created.
|
||||
func (ec *Client) SubscribeNewBlockResult(ctx context.Context, ch chan<- *types.BlockResult) (ethereum.Subscription, error) {
|
||||
return ec.c.EthSubscribe(ctx, ch, "newBlockResult")
|
||||
// SubscribeNewBlockTrace subscribes to block execution trace when a new block is created.
|
||||
func (ec *Client) SubscribeNewBlockTrace(ctx context.Context, ch chan<- *types.BlockTrace) (ethereum.Subscription, error) {
|
||||
return ec.c.EthSubscribe(ctx, ch, "newBlockTrace")
|
||||
}
|
||||
|
||||
// State Access
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ func init() {
|
|||
}
|
||||
}
|
||||
|
||||
func loadStaff(t *testing.T, fname string) *types.BlockResult {
|
||||
func loadStaff(t *testing.T, fname string) *types.BlockTrace {
|
||||
f, err := os.Open(fname)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
@ -33,7 +33,7 @@ func loadStaff(t *testing.T, fname string) *types.BlockResult {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
out := new(types.BlockResult)
|
||||
out := new(types.BlockTrace)
|
||||
|
||||
err = json.Unmarshal(bt, out)
|
||||
if err != nil {
|
||||
|
|
@ -84,7 +84,7 @@ func TestGreeterTx(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
traces, err := zkproof.HandleBlockResult(trace)
|
||||
traces, err := zkproof.HandleBlockTrace(trace)
|
||||
t.Log("traces: ", len(traces))
|
||||
outObj, _ := json.Marshal(traces)
|
||||
t.Log(string(outObj))
|
||||
|
|
@ -95,7 +95,7 @@ func TestGreeterTx(t *testing.T) {
|
|||
|
||||
func TestTokenTx(t *testing.T) {
|
||||
trace := loadStaff(t, "blocktraces/mpt_witness/token.json")
|
||||
traces, err := zkproof.HandleBlockResult(trace)
|
||||
traces, err := zkproof.HandleBlockTrace(trace)
|
||||
outObj, _ := json.Marshal(traces)
|
||||
t.Log(string(outObj))
|
||||
if err != nil {
|
||||
|
|
@ -106,7 +106,7 @@ func TestTokenTx(t *testing.T) {
|
|||
|
||||
func TestCallTx(t *testing.T) {
|
||||
trace := loadStaff(t, "blocktraces/mpt_witness/call.json")
|
||||
traces, err := zkproof.HandleBlockResult(trace)
|
||||
traces, err := zkproof.HandleBlockTrace(trace)
|
||||
outObj, _ := json.Marshal(traces)
|
||||
t.Log(string(outObj))
|
||||
if err != nil {
|
||||
|
|
@ -114,7 +114,7 @@ func TestCallTx(t *testing.T) {
|
|||
}
|
||||
|
||||
trace = loadStaff(t, "blocktraces/mpt_witness/call_edge.json")
|
||||
traces, err = zkproof.HandleBlockResult(trace)
|
||||
traces, err = zkproof.HandleBlockTrace(trace)
|
||||
outObj, _ = json.Marshal(traces)
|
||||
t.Log(string(outObj))
|
||||
if err != nil {
|
||||
|
|
@ -124,7 +124,7 @@ func TestCallTx(t *testing.T) {
|
|||
|
||||
func TestCreateTx(t *testing.T) {
|
||||
trace := loadStaff(t, "blocktraces/mpt_witness/create.json")
|
||||
traces, err := zkproof.HandleBlockResult(trace)
|
||||
traces, err := zkproof.HandleBlockTrace(trace)
|
||||
outObj, _ := json.Marshal(traces)
|
||||
t.Log(string(outObj))
|
||||
if err != nil {
|
||||
|
|
@ -132,7 +132,7 @@ func TestCreateTx(t *testing.T) {
|
|||
}
|
||||
|
||||
trace = loadStaff(t, "blocktraces/mpt_witness/deploy.json")
|
||||
traces, err = zkproof.HandleBlockResult(trace)
|
||||
traces, err = zkproof.HandleBlockTrace(trace)
|
||||
outObj, _ = json.Marshal(traces)
|
||||
t.Log(string(outObj))
|
||||
if err != nil {
|
||||
|
|
@ -143,7 +143,7 @@ func TestCreateTx(t *testing.T) {
|
|||
|
||||
func TestFailedCallTx(t *testing.T) {
|
||||
trace := loadStaff(t, "blocktraces/mpt_witness/fail_call.json")
|
||||
traces, err := zkproof.HandleBlockResult(trace)
|
||||
traces, err := zkproof.HandleBlockTrace(trace)
|
||||
outObj, _ := json.Marshal(traces)
|
||||
t.Log(string(outObj))
|
||||
if err != nil {
|
||||
|
|
@ -151,7 +151,7 @@ func TestFailedCallTx(t *testing.T) {
|
|||
}
|
||||
|
||||
trace = loadStaff(t, "blocktraces/mpt_witness/fail_create.json")
|
||||
traces, err = zkproof.HandleBlockResult(trace)
|
||||
traces, err = zkproof.HandleBlockTrace(trace)
|
||||
outObj, _ = json.Marshal(traces)
|
||||
t.Log(string(outObj))
|
||||
if err != nil {
|
||||
|
|
@ -163,7 +163,7 @@ func TestFailedCallTx(t *testing.T) {
|
|||
//notice: now only work with OP_ORDER=2
|
||||
func TestDeleteTx(t *testing.T) {
|
||||
trace := loadStaff(t, "blocktraces/mpt_witness/delete.json")
|
||||
traces, err := zkproof.HandleBlockResult(trace)
|
||||
traces, err := zkproof.HandleBlockTrace(trace)
|
||||
outObj, _ := json.Marshal(traces)
|
||||
t.Log(string(outObj))
|
||||
if err != nil {
|
||||
|
|
@ -174,7 +174,7 @@ func TestDeleteTx(t *testing.T) {
|
|||
//notice: now only work with OP_ORDER=2
|
||||
func TestDestructTx(t *testing.T) {
|
||||
trace := loadStaff(t, "blocktraces/mpt_witness/destruct.json")
|
||||
traces, err := zkproof.HandleBlockResult(trace)
|
||||
traces, err := zkproof.HandleBlockTrace(trace)
|
||||
outObj, _ := json.Marshal(traces)
|
||||
t.Log(string(outObj))
|
||||
if err != nil {
|
||||
|
|
@ -184,7 +184,7 @@ func TestDestructTx(t *testing.T) {
|
|||
|
||||
func TestMutipleTx(t *testing.T) {
|
||||
trace := loadStaff(t, "blocktraces/mpt_witness/multi_txs.json")
|
||||
traces, err := zkproof.HandleBlockResult(trace)
|
||||
traces, err := zkproof.HandleBlockTrace(trace)
|
||||
outObj, _ := json.Marshal(traces)
|
||||
t.Log(string(outObj))
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ const (
|
|||
posCALL = 2
|
||||
posSTATICCALL = 0
|
||||
|
||||
// posSELFDESTRUCT = 2
|
||||
// posSELFDESTRUCT = 2
|
||||
)
|
||||
|
||||
func getAccountState(l *types.StructLogRes, pos int) *types.AccountWrapper {
|
||||
|
|
@ -737,12 +737,12 @@ var usedOrdererScheme = defaultOrdererScheme
|
|||
|
||||
func SetOrderScheme(t MPTWitnessType) { usedOrdererScheme = t }
|
||||
|
||||
// HandleBlockResult only for backward compatibility
|
||||
func HandleBlockResult(block *types.BlockResult) ([]*StorageTrace, error) {
|
||||
return HandleBlockResultEx(block, usedOrdererScheme)
|
||||
// HandleBlockTrace only for backward compatibility
|
||||
func HandleBlockTrace(block *types.BlockTrace) ([]*StorageTrace, error) {
|
||||
return HandleBlockTraceEx(block, usedOrdererScheme)
|
||||
}
|
||||
|
||||
func HandleBlockResultEx(block *types.BlockResult, ordererScheme MPTWitnessType) ([]*StorageTrace, error) {
|
||||
func HandleBlockTraceEx(block *types.BlockTrace, ordererScheme MPTWitnessType) ([]*StorageTrace, error) {
|
||||
|
||||
writer, err := NewZkTrieProofWriter(block.StorageTrace)
|
||||
if err != nil {
|
||||
|
|
@ -767,8 +767,8 @@ func HandleBlockResultEx(block *types.BlockResult, ordererScheme MPTWitnessType)
|
|||
|
||||
// notice some coinbase addr (like all zero) is in fact not exist and should not be update
|
||||
// TODO: not a good solution, just for patch ...
|
||||
if coinbaseData := writer.tracingAccounts[block.BlockTrace.Coinbase.Address]; coinbaseData != nil {
|
||||
od.absorb(block.BlockTrace.Coinbase)
|
||||
if coinbaseData := writer.tracingAccounts[block.Coinbase.Address]; coinbaseData != nil {
|
||||
od.absorb(block.Coinbase)
|
||||
}
|
||||
|
||||
opDisp := od.end_absorb()
|
||||
|
|
@ -791,13 +791,13 @@ func HandleBlockResultEx(block *types.BlockResult, ordererScheme MPTWitnessType)
|
|||
|
||||
}
|
||||
|
||||
func FillBlockResultForMPTWitness(order MPTWitnessType, block *types.BlockResult) error {
|
||||
func FillBlockTraceForMPTWitness(order MPTWitnessType, block *types.BlockTrace) error {
|
||||
|
||||
if order == MPTWitnessNothing {
|
||||
return nil
|
||||
}
|
||||
|
||||
trace, err := HandleBlockResultEx(block, order)
|
||||
trace, err := HandleBlockTraceEx(block, order)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue