mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-27 07:06:42 +00:00
fix(trace): update proofList struct (#46)
This commit is contained in:
parent
9fb413d702
commit
13ea5c234b
4 changed files with 96 additions and 45 deletions
|
|
@ -1348,18 +1348,25 @@ func (bc *BlockChain) writeBlockResult(state *state.StateDB, block *types.Block,
|
|||
blockResult.BlockTrace = types.NewTraceBlock(bc.chainConfig, block)
|
||||
for i, tx := range block.Transactions() {
|
||||
evmTrace := blockResult.ExecutionResults[i]
|
||||
// Get the sender's address.
|
||||
|
||||
// Get sender's address.
|
||||
from, _ := types.Sender(types.MakeSigner(bc.chainConfig, block.Number()), tx)
|
||||
// Get account's proof.
|
||||
evmTrace.Sender = &types.AccountProofWrapper{
|
||||
Address: from,
|
||||
Nonce: state.GetNonce(from),
|
||||
Balance: state.GetBalance(from),
|
||||
}
|
||||
// Get sender's account proof.
|
||||
proof, err := state.GetProof(from)
|
||||
if err != nil {
|
||||
log.Error("Failed to get proof", "blockNumber", block.NumberU64(), "address", from.String(), "err", err)
|
||||
} else {
|
||||
evmTrace.Proof = make([]string, len(proof))
|
||||
evmTrace.Sender.Proof = make([]string, len(proof))
|
||||
for i := range proof {
|
||||
evmTrace.Proof[i] = hexutil.Encode(proof[i])
|
||||
evmTrace.Sender.Proof[i] = hexutil.Encode(proof[i])
|
||||
}
|
||||
}
|
||||
|
||||
// Contract is called
|
||||
if len(tx.Data()) != 0 && tx.To() != nil {
|
||||
evmTrace.ByteCode = hexutil.Encode(state.GetCode(*tx.To()))
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/scroll-tech/go-ethereum/common"
|
||||
)
|
||||
|
||||
|
|
@ -17,12 +19,12 @@ type ExecutionResult struct {
|
|||
Gas uint64 `json:"gas"`
|
||||
Failed bool `json:"failed"`
|
||||
ReturnValue string `json:"returnValue,omitempty"`
|
||||
// Sender's account proof.
|
||||
Sender *AccountProofWrapper `json:"sender,omitempty"`
|
||||
// It's exist only when tx is a contract call.
|
||||
CodeHash *common.Hash `json:"codeHash,omitempty"`
|
||||
// If it is a contract call, the contract code is returned.
|
||||
ByteCode string `json:"byteCode,omitempty"`
|
||||
// The account's proof.
|
||||
Proof []string `json:"proof,omitempty"`
|
||||
ByteCode string `json:"byteCode,omitempty"`
|
||||
StructLogs []StructLogRes `json:"structLogs"`
|
||||
}
|
||||
|
||||
|
|
@ -42,26 +44,38 @@ type StructLogRes struct {
|
|||
}
|
||||
|
||||
type ExtraData struct {
|
||||
// CREATE | CREATE2: sender address
|
||||
From *common.Address `json:"from,omitempty"`
|
||||
// CREATE: sender nonce
|
||||
Nonce *uint64 `json:"nonce,omitempty"`
|
||||
// CALL | CALLCODE | DELEGATECALL | STATICCALL: [tx.to address’s code, stack.nth_last(1) address’s code]
|
||||
CodeList [][]byte `json:"codeList,omitempty"`
|
||||
// SSTORE | SLOAD: [storageProof]
|
||||
// SELFDESTRUCT: [contract address’s accountProof, stack.nth_last(0) address’s accountProof]
|
||||
// SELFBALANCE: [contract address’s accountProof]
|
||||
// BALANCE | EXTCODEHASH: [stack.nth_last(0) address’s accountProof]
|
||||
// CREATE | CREATE2: [created contract address’s accountProof]
|
||||
// CREATE | CREATE2: [sender's accountProof, created contract address’s accountProof]
|
||||
// CALL | CALLCODE: [caller contract address’s accountProof, stack.nth_last(1) address’s accountProof]
|
||||
ProofList [][]string `json:"proofList,omitempty"`
|
||||
ProofList []*AccountProofWrapper `json:"proofList,omitempty"`
|
||||
}
|
||||
|
||||
type AccountProofWrapper struct {
|
||||
Address common.Address `json:"address,omitempty"`
|
||||
Nonce uint64 `json:"nonce,omitempty"`
|
||||
Balance *big.Int `json:"balance,omitempty"`
|
||||
Proof []string `json:"proof,omitempty"`
|
||||
Storage *StorageProofWrapper `json:"storage,omitempty"` // StorageProofWrapper can be empty if irrelated to storage operation
|
||||
}
|
||||
|
||||
// while key & value can also be retrieved from StructLogRes.Storage,
|
||||
// we still stored in here for roller's processing convenience.
|
||||
type StorageProofWrapper struct {
|
||||
Key string `json:"key,omitempty"`
|
||||
Value string `json:"value,omitempty"`
|
||||
Proof []string `json:"proof,omitempty"`
|
||||
}
|
||||
|
||||
// NewExtraData create, init and return ExtraData
|
||||
func NewExtraData() *ExtraData {
|
||||
return &ExtraData{
|
||||
CodeList: make([][]byte, 0),
|
||||
ProofList: make([][]string, 0),
|
||||
ProofList: make([]*AccountProofWrapper, 0),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -73,7 +87,7 @@ func (e *ExtraData) SealExtraData() *ExtraData {
|
|||
if len(e.ProofList) == 0 {
|
||||
e.ProofList = nil
|
||||
}
|
||||
if e.From == nil && e.Nonce == nil && e.CodeList == nil && e.ProofList == nil {
|
||||
if e.CodeList == nil && e.ProofList == nil {
|
||||
return nil
|
||||
}
|
||||
return e
|
||||
|
|
|
|||
|
|
@ -198,6 +198,12 @@ func (l *StructLogger) CaptureState(pc uint64, op OpCode, gas, cost uint64, scop
|
|||
)
|
||||
l.storage[contract.Address()][address] = value
|
||||
storage = l.storage[contract.Address()].Copy()
|
||||
|
||||
extraData = types.NewExtraData()
|
||||
if err := traceStorageProof(l, scope, extraData); err != nil {
|
||||
log.Warn("Failed to get proof", "contract address", contract.Address().String(), "key", address.String(), "err", err)
|
||||
}
|
||||
|
||||
} else if op == SSTORE && stack.len() >= 2 {
|
||||
// capture SSTORE opcodes and record the written entry in the local storage.
|
||||
var (
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ var (
|
|||
CALLCODE: {traceToAddressCode, traceLastNAddressCode(1), traceCallerProof, traceLastNAddressProof(1)},
|
||||
DELEGATECALL: {traceToAddressCode, traceLastNAddressCode(1)},
|
||||
STATICCALL: {traceToAddressCode, traceLastNAddressCode(1)},
|
||||
CREATE: {traceSenderAddress, traceCreatedContractProof, traceNonce},
|
||||
CREATE2: {traceSenderAddress, traceCreatedContractProof},
|
||||
SSTORE: {traceStorageProof},
|
||||
SLOAD: {traceStorageProof},
|
||||
CREATE: {traceCreatedContractProof}, // sender's wrapped_proof is already recorded in BlockChain.writeBlockResult
|
||||
CREATE2: {traceCreatedContractProof}, // sender's wrapped_proof is already recorded in BlockChain.writeBlockResult
|
||||
SLOAD: {}, // only record state_before, instead of state_after
|
||||
SSTORE: {traceStorageProof}, // record state_after besides state_before
|
||||
SELFDESTRUCT: {traceContractProof, traceLastNAddressProof(0)},
|
||||
SELFBALANCE: {traceContractProof},
|
||||
BALANCE: {traceLastNAddressProof(0)},
|
||||
|
|
@ -52,30 +52,15 @@ func traceLastNAddressCode(n int) traceFunc {
|
|||
}
|
||||
}
|
||||
|
||||
// traceSenderAddress gets sender address
|
||||
func traceSenderAddress(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error {
|
||||
extraData.From = &l.env.Origin
|
||||
return nil
|
||||
}
|
||||
|
||||
// traceNonce gets sender nonce
|
||||
func traceNonce(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error {
|
||||
nonce := l.env.StateDB.GetNonce(l.env.Origin)
|
||||
extraData.Nonce = &nonce
|
||||
return nil
|
||||
}
|
||||
|
||||
// traceStorageProof get contract's storage proof at storage_address
|
||||
func traceStorageProof(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error {
|
||||
if scope.Stack.len() == 0 {
|
||||
return nil
|
||||
}
|
||||
address := common.Hash(scope.Stack.peek().Bytes32())
|
||||
contract := scope.Contract
|
||||
// Get storage proof.
|
||||
storageProof, err := l.env.StateDB.GetStorageProof(contract.Address(), address)
|
||||
key := common.Hash(scope.Stack.peek().Bytes32())
|
||||
proof, err := getWrappedProofForStorage(l, scope.Contract.Address(), key)
|
||||
if err == nil {
|
||||
extraData.ProofList = append(extraData.ProofList, encodeProof(storageProof))
|
||||
extraData.ProofList = append(extraData.ProofList, proof)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
@ -83,9 +68,9 @@ func traceStorageProof(l *StructLogger, scope *ScopeContext, extraData *types.Ex
|
|||
// traceContractProof gets the contract's account proof
|
||||
func traceContractProof(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error {
|
||||
// Get account proof.
|
||||
proof, err := l.env.StateDB.GetProof(scope.Contract.Address())
|
||||
proof, err := getWrappedProofForAddr(l, scope.Contract.Address())
|
||||
if err == nil {
|
||||
extraData.ProofList = append(extraData.ProofList, encodeProof(proof))
|
||||
extraData.ProofList = append(extraData.ProofList, proof)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
@ -101,9 +86,9 @@ func traceCreatedContractProof(l *StructLogger, scope *ScopeContext, extraData *
|
|||
return errors.New("can't get created contract address from stack")
|
||||
}
|
||||
address := common.BytesToAddress(stackvalue.Bytes())
|
||||
proof, err := l.env.StateDB.GetProof(address)
|
||||
proof, err := getWrappedProofForAddr(l, address)
|
||||
if err == nil {
|
||||
extraData.ProofList = append(extraData.ProofList, encodeProof(proof))
|
||||
extraData.ProofList = append(extraData.ProofList, proof)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
@ -117,9 +102,9 @@ func traceLastNAddressProof(n int) traceFunc {
|
|||
}
|
||||
|
||||
address := common.Address(stack.data[stack.len()-1-n].Bytes20())
|
||||
proof, err := l.env.StateDB.GetProof(address)
|
||||
proof, err := getWrappedProofForAddr(l, address)
|
||||
if err == nil {
|
||||
extraData.ProofList = append(extraData.ProofList, encodeProof(proof))
|
||||
extraData.ProofList = append(extraData.ProofList, proof)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
|
@ -128,13 +113,52 @@ func traceLastNAddressProof(n int) traceFunc {
|
|||
// traceCallerProof gets caller address's proof.
|
||||
func traceCallerProof(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error {
|
||||
address := scope.Contract.CallerAddress
|
||||
proof, err := l.env.StateDB.GetProof(address)
|
||||
proof, err := getWrappedProofForAddr(l, address)
|
||||
if err == nil {
|
||||
extraData.ProofList = append(extraData.ProofList, encodeProof(proof))
|
||||
extraData.ProofList = append(extraData.ProofList, proof)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// StorageProofWrapper will be empty
|
||||
func getWrappedProofForAddr(l *StructLogger, address common.Address) (*types.AccountProofWrapper, error) {
|
||||
proof, err := l.env.StateDB.GetProof(address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.AccountProofWrapper{
|
||||
Address: address,
|
||||
Nonce: l.env.StateDB.GetNonce(address),
|
||||
Balance: l.env.StateDB.GetBalance(address),
|
||||
Proof: encodeProof(proof),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getWrappedProofForStorage(l *StructLogger, address common.Address, key common.Hash) (*types.AccountProofWrapper, error) {
|
||||
proof, err := l.env.StateDB.GetProof(address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
storageProof, err := l.env.StateDB.GetStorageProof(address, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.AccountProofWrapper{
|
||||
Address: address,
|
||||
Nonce: l.env.StateDB.GetNonce(address),
|
||||
Balance: l.env.StateDB.GetBalance(address),
|
||||
Proof: encodeProof(proof),
|
||||
Storage: &types.StorageProofWrapper{
|
||||
Key: key.String(),
|
||||
Value: l.env.StateDB.GetState(address, key).String(),
|
||||
Proof: encodeProof(storageProof),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func encodeProof(proof [][]byte) (res []string) {
|
||||
if len(proof) == 0 {
|
||||
return nil
|
||||
|
|
|
|||
Loading…
Reference in a new issue