mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-31 09:03:46 +00:00
146 lines
4.7 KiB
Go
146 lines
4.7 KiB
Go
package vm
|
||
|
||
import (
|
||
"errors"
|
||
|
||
"github.com/scroll-tech/go-ethereum/common"
|
||
"github.com/scroll-tech/go-ethereum/common/hexutil"
|
||
"github.com/scroll-tech/go-ethereum/core/types"
|
||
)
|
||
|
||
type traceFunc func(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error
|
||
|
||
var (
|
||
// OpcodeExecs the map to load opcodes' trace funcs.
|
||
OpcodeExecs = map[OpCode][]traceFunc{
|
||
CALL: {traceToAddressCodeHash, traceLastNAddressCodeHash(1), traceCallerProof, traceLastNAddressProof(1)},
|
||
CALLCODE: {traceToAddressCodeHash, traceLastNAddressCodeHash(1), traceCallerProof, traceLastNAddressProof(1)},
|
||
DELEGATECALL: {traceToAddressCodeHash, traceLastNAddressCodeHash(1)},
|
||
STATICCALL: {traceToAddressCodeHash, traceLastNAddressCodeHash(1)},
|
||
CREATE: {traceSenderAddress, traceCreatedContractProof, traceNonce},
|
||
CREATE2: {traceSenderAddress, traceCreatedContractProof},
|
||
SSTORE: {traceStorageProof},
|
||
SLOAD: {traceStorageProof},
|
||
SELFDESTRUCT: {traceContractProof, traceLastNAddressProof(0)},
|
||
SELFBALANCE: {traceContractProof},
|
||
BALANCE: {traceLastNAddressProof(0)},
|
||
EXTCODEHASH: {traceLastNAddressProof(0)},
|
||
}
|
||
)
|
||
|
||
// traceToAddressCodeHash gets tx.to address’s code_hash
|
||
func traceToAddressCodeHash(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error {
|
||
if l.env.To == nil {
|
||
return nil
|
||
}
|
||
codeHash := l.env.StateDB.GetCodeHash(*l.env.To)
|
||
extraData.CodeHashList = append(extraData.CodeHashList, codeHash)
|
||
return nil
|
||
}
|
||
|
||
// traceLastNAddressCodeHash
|
||
func traceLastNAddressCodeHash(n int) traceFunc {
|
||
return func(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error {
|
||
stack := scope.Stack
|
||
if stack.len() <= n {
|
||
return nil
|
||
}
|
||
address := common.Address(stack.data[stack.len()-1-n].Bytes20())
|
||
codeHash := l.env.StateDB.GetCodeHash(address)
|
||
extraData.CodeHashList = append(extraData.CodeHashList, codeHash)
|
||
return nil
|
||
}
|
||
}
|
||
|
||
// 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)
|
||
if err == nil {
|
||
extraData.ProofList = append(extraData.ProofList, encodeProof(storageProof))
|
||
}
|
||
return err
|
||
}
|
||
|
||
// 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())
|
||
if err == nil {
|
||
extraData.ProofList = append(extraData.ProofList, encodeProof(proof))
|
||
}
|
||
return err
|
||
}
|
||
|
||
/// traceCreatedContractProof get created contract address’s accountProof
|
||
func traceCreatedContractProof(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error {
|
||
stack := scope.Stack
|
||
if stack.len() < 1 {
|
||
return nil
|
||
}
|
||
stackvalue := stack.peek()
|
||
if stackvalue.IsZero() {
|
||
return errors.New("can't get created contract address from stack")
|
||
}
|
||
address := common.BytesToAddress(stackvalue.Bytes())
|
||
proof, err := l.env.StateDB.GetProof(address)
|
||
if err == nil {
|
||
extraData.ProofList = append(extraData.ProofList, encodeProof(proof))
|
||
}
|
||
return err
|
||
}
|
||
|
||
// traceLastNAddressProof returns func about the last N's address proof.
|
||
func traceLastNAddressProof(n int) traceFunc {
|
||
return func(l *StructLogger, scope *ScopeContext, extraData *types.ExtraData) error {
|
||
stack := scope.Stack
|
||
if stack.len() <= n {
|
||
return nil
|
||
}
|
||
|
||
address := common.Address(stack.data[stack.len()-1-n].Bytes20())
|
||
proof, err := l.env.StateDB.GetProof(address)
|
||
if err == nil {
|
||
extraData.ProofList = append(extraData.ProofList, encodeProof(proof))
|
||
}
|
||
return err
|
||
}
|
||
}
|
||
|
||
// 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)
|
||
if err == nil {
|
||
extraData.ProofList = append(extraData.ProofList, encodeProof(proof))
|
||
}
|
||
return err
|
||
}
|
||
|
||
func encodeProof(proof [][]byte) (res []string) {
|
||
if len(proof) == 0 {
|
||
return nil
|
||
}
|
||
for _, node := range proof {
|
||
res = append(res, hexutil.Encode(node))
|
||
}
|
||
return
|
||
}
|