Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(wip) Zz/feat/flattenproof plus txbytxtraces #1025

Draft
wants to merge 26 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
0a0e396
WIP: flatten storageproof
noel2004 Jul 30, 2024
330ad97
WIP: for testing
noel2004 Jul 30, 2024
623cbe2
Merge remote-tracking branch 'origin/develop' into develop
noel2004 Jul 30, 2024
06fdc8c
fix: init map
noel2004 Jul 30, 2024
11a21da
fix lock issue
noel2004 Jul 30, 2024
2238551
add deletion proof
noel2004 Jul 30, 2024
d56e002
Merge remote-tracking branch 'scroll/develop' into feat/flattenproof
noel2004 Aug 3, 2024
7abeb46
fix endian represent of key
noel2004 Aug 3, 2024
84b00d2
add flatten proof for coinbase
noel2004 Aug 4, 2024
49151d4
WIP: preimage for key
noel2004 Aug 7, 2024
4e7a02f
Merge remote-tracking branch 'origin/develop' into feat/flattenproof
noel2004 Aug 7, 2024
8c2611c
key hash records
noel2004 Aug 7, 2024
a290561
Merge remote-tracking branch 'origin/develop' into feat/flattenproof
noel2004 Aug 13, 2024
3a805b4
filter for l2trace
noel2004 Aug 13, 2024
11b45dc
Merge remote-tracking branch 'origin/develop' into feat/flattenproof
noel2004 Aug 21, 2024
2a2b2b8
add union mode
noel2004 Aug 21, 2024
164adae
fix typo
noel2004 Aug 21, 2024
da019ee
fix go imports
noel2004 Aug 21, 2024
a85536a
Merge remote-tracking branch 'origin/develop' into feat/flattenproof
noel2004 Aug 22, 2024
13e46cf
set default format to legacy
noel2004 Aug 22, 2024
7968829
++
omerfirmak Aug 22, 2024
5ec1a25
Merge remote-tracking branch 'origin/omerfirmak/tx-by-tx-tracer' into…
lispc Aug 27, 2024
78e6f64
Merge remote-tracking branch 'origin/develop' into zz/feat/flattenpro…
lispc Sep 5, 2024
903a85a
Merge remote-tracking branch 'origin/develop' into zz/feat/flattenpro…
lispc Sep 6, 2024
e565e14
induce partial trace mode
noel2004 Sep 7, 2024
9ce5c5a
disable trace filter
noel2004 Sep 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions core/state/state_prove.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,18 @@ func (s *StateDB) GetStorageTrieForProof(addr common.Address) (Trie, error) {

// GetSecureTrieProof handle any interface with Prove (should be a Trie in most case) and
// deliver the proof in bytes
func (s *StateDB) GetSecureTrieProof(trieProve TrieProve, key common.Hash) ([][]byte, error) {
func (s *StateDB) GetSecureTrieProof(trieProve TrieProve, key common.Hash) (FullProofList, common.Hash, error) {

var proof proofList
var proof FullProofList
var hash common.Hash
var err error
if s.IsZktrie() {
key_s, _ := zkt.ToSecureKeyBytes(key.Bytes())
err = trieProve.Prove(key_s.Bytes(), 0, &proof)
hash = common.BytesToHash(key_s.Bytes())
err = trieProve.Prove(hash.Bytes(), 0, &proof)
} else {
err = trieProve.Prove(crypto.Keccak256(key.Bytes()), 0, &proof)
hash = common.BytesToHash(crypto.Keccak256(key.Bytes()))
err = trieProve.Prove(hash.Bytes(), 0, &proof)
}
return proof, err
return proof, hash, err
}
48 changes: 47 additions & 1 deletion core/state/statedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,33 @@ func (n *proofList) Delete(key []byte) error {
panic("not supported")
}

type fullProof struct {
Key []byte
Value []byte
}

type FullProofList []fullProof

func (n *FullProofList) Put(key []byte, value []byte) error {
*n = append(*n, fullProof{
Key: key,
Value: value,
})
return nil
}

func (n *FullProofList) Delete(key []byte) error {
panic("not supported")
}

func (n FullProofList) GetData() (out [][]byte) {
out = make([][]byte, 0, len(n))
for _, i := range n {
out = append(out, i.Value)
}
return
}

// StateDB structs within the ethereum protocol are used to store anything
// within the merkle trie. StateDBs take care of caching and storing
// nested states. It's the general query interface to retrieve:
Expand Down Expand Up @@ -343,6 +370,21 @@ func (s *StateDB) GetProofByHash(addrHash common.Hash) ([][]byte, error) {
return proof, err
}

// GetFullProof returns the Merkle proof for a given account, with both node data and key
// also the key for address is provided
func (s *StateDB) GetFullProof(addr common.Address) (FullProofList, common.Hash, error) {
var hash common.Hash
if s.IsZktrie() {
addr_s, _ := zkt.ToSecureKeyBytes(addr.Bytes())
hash = common.BytesToHash(addr_s.Bytes())
} else {
hash = crypto.Keccak256Hash(addr.Bytes())
}
var proof FullProofList
err := s.trie.Prove(hash[:], 0, &proof)
return proof, hash, err
}

func (s *StateDB) GetLiveStateAccount(addr common.Address) *types.StateAccount {
obj, ok := s.stateObjects[addr]
if !ok {
Expand All @@ -361,7 +403,11 @@ func (s *StateDB) GetStorageProof(a common.Address, key common.Hash) ([][]byte,
if trie == nil {
return nil, errors.New("storage trie for requested address does not exist")
}
return s.GetSecureTrieProof(trie, key)
proof, _, err := s.GetSecureTrieProof(trie, key)
if err != nil {
return nil, err
}
return proof.GetData(), nil
}

// GetCommittedState retrieves a value from the given account's committed storage trie.
Expand Down
26 changes: 26 additions & 0 deletions core/types/l2trace.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,37 @@ type StorageTrace struct {
// All storage proofs BEFORE execution
StorageProofs map[string]map[string][]hexutil.Bytes `json:"storageProofs,omitempty"`

// The "flatten" db nodes
FlattenProofs map[common.Hash]hexutil.Bytes `json:"flattenProofs,omitempty"`

// The hash of secured addresses
AddressHashes map[common.Address]common.Hash `json:"addressHashes,omitempty"`
// The hash of secured store key
StoreKeyHashes map[common.Hash]common.Hash `json:"storeKeyHashes,omitempty"`

// Node entries for deletion, no need to distinguish what it is from, just read them
// into the partial db
DeletionProofs []hexutil.Bytes `json:"deletionProofs,omitempty"`
}

func (tr *StorageTrace) ApplyFilter(legacy bool) {
if legacy {
tr.FlattenProofs = nil
tr.AddressHashes = nil
tr.StoreKeyHashes = nil
} else {
for k := range tr.Proofs {
tr.Proofs[k] = []hexutil.Bytes{}
}
for _, st := range tr.StorageProofs {
for k := range st {
st[k] = []hexutil.Bytes{}
}
}
tr.DeletionProofs = []hexutil.Bytes{}
}
}

// ExecutionResult groups all structured logs emitted by the EVM
// while replaying a transaction in debug mode as well as transaction
// execution status, the amount of gas used and the return value
Expand Down
15 changes: 9 additions & 6 deletions core/vm/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,15 @@ func (s Storage) Copy() Storage {

// LogConfig are the configuration options for structured logger the EVM
type LogConfig struct {
EnableMemory bool // enable memory capture
DisableStack bool // disable stack capture
DisableStorage bool // disable storage capture
EnableReturnData bool // enable return data capture
Debug bool // print output during capture end
Limit int // maximum length of output, but zero means unlimited
EnableMemory bool // enable memory capture
DisableStack bool // disable stack capture
DisableStorage bool // disable storage capture
EnableReturnData bool // enable return data capture
Debug bool // print output during capture end
Limit int // maximum length of output, but zero means unlimited
StorageProofFormat *string // format of storage proofs, can be
// "legacy" (use the legacy proof format) or
// "union" (output both flatten and legacy proof)
// Chain overrides, can be used to execute a trace using future fork rules
Overrides *params.ChainConfig `json:"overrides,omitempty"`
}
Expand Down
100 changes: 99 additions & 1 deletion eth/tracers/api_blocktrace.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,14 @@ type TraceBlock interface {
GetTxBlockTraceOnTopOfBlock(ctx context.Context, tx *types.Transaction, blockNrOrHash rpc.BlockNumberOrHash, config *TraceConfig) (*types.BlockTrace, error)
}

type TracerEnv interface {
ResetForPartialTrace(*types.Block) error
GetBlockTrace(*types.Block) (*types.BlockTrace, error)
}

type scrollTracerWrapper interface {
CreateTraceEnvAndGetBlockTrace(*params.ChainConfig, core.ChainContext, consensus.Engine, ethdb.Database, *state.StateDB, *types.Block, *types.Block, bool) (*types.BlockTrace, error)
CreateTraceEnv(*params.ChainConfig, core.ChainContext, consensus.Engine, ethdb.Database, *state.StateDB, *types.Block, *types.Block, bool) (TracerEnv, error)
}

// GetBlockTraceByNumberOrHash replays the block and returns the structured BlockTrace by hash or number.
Expand Down Expand Up @@ -79,8 +85,82 @@ func (api *API) GetTxBlockTraceOnTopOfBlock(ctx context.Context, tx *types.Trans
return api.createTraceEnvAndGetBlockTrace(ctx, config, block)
}

func (api *API) GetTxByTxBlockTrace(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, config *TraceConfig) ([]*types.BlockTrace, error) {
if api.scrollTracerWrapper == nil {
return nil, errNoScrollTracerWrapper
}

// Try to retrieve the specified block
var (
err error
block *types.Block
)
if number, ok := blockNrOrHash.Number(); ok {
block, err = api.blockByNumber(ctx, number)
} else if hash, ok := blockNrOrHash.Hash(); ok {
block, err = api.blockByHash(ctx, hash)
} else {
return nil, errors.New("invalid arguments; neither block number nor hash specified")
}
if err != nil {
return nil, err
}
if block.NumberU64() == 0 {
return nil, errors.New("genesis is not traceable")
}

if config == nil {
config = &TraceConfig{
LogConfig: &vm.LogConfig{
DisableStorage: true,
DisableStack: true,
EnableMemory: false,
EnableReturnData: true,
},
}
} else if config.Tracer != nil {
config.Tracer = nil
log.Warn("Tracer params is unsupported")
}

parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash())
if err != nil {
return nil, err
}
reexec := defaultTraceReexec
if config != nil && config.Reexec != nil {
reexec = *config.Reexec
}
statedb, err := api.backend.StateAtBlock(ctx, parent, reexec, nil, true, true)
if err != nil {
return nil, err
}

chaindb := api.backend.ChainDb()
traces := []*types.BlockTrace{}
traceEnv, err := api.scrollTracerWrapper.CreateTraceEnv(api.backend.ChainConfig(), api.chainContext(ctx), api.backend.Engine(), chaindb, statedb, parent, block, true)
if err != nil {
return nil, err
}
for _, tx := range block.Transactions() {
singleTxBlock := types.NewBlockWithHeader(block.Header()).WithBody([]*types.Transaction{tx}, nil)
if err := traceEnv.ResetForPartialTrace(singleTxBlock); err != nil {
return nil, err
}
trace, err := traceEnv.GetBlockTrace(singleTxBlock)
if err != nil {
return nil, err
}
// trace.StorageTrace.ApplyFilter(false)
traces = append(traces, trace)
}
return traces, nil
}

// Make trace environment for current block, and then get the trace for the block.
func (api *API) createTraceEnvAndGetBlockTrace(ctx context.Context, config *TraceConfig, block *types.Block) (*types.BlockTrace, error) {
legacyStorageTrace := true
unionStorageTrace := false
if config == nil {
config = &TraceConfig{
LogConfig: &vm.LogConfig{
Expand All @@ -95,6 +175,14 @@ func (api *API) createTraceEnvAndGetBlockTrace(ctx context.Context, config *Trac
log.Warn("Tracer params is unsupported")
}

if config.LogConfig != nil && config.StorageProofFormat != nil {
if *config.StorageProofFormat == "flatten" {
legacyStorageTrace = false
} else if *config.StorageProofFormat == "union" {
unionStorageTrace = true
}
}

parent, err := api.blockByNumberAndHash(ctx, rpc.BlockNumber(block.NumberU64()-1), block.ParentHash())
if err != nil {
return nil, err
Expand All @@ -109,5 +197,15 @@ func (api *API) createTraceEnvAndGetBlockTrace(ctx context.Context, config *Trac
}

chaindb := api.backend.ChainDb()
return api.scrollTracerWrapper.CreateTraceEnvAndGetBlockTrace(api.backend.ChainConfig(), api.chainContext(ctx), api.backend.Engine(), chaindb, statedb, parent, block, true)
l2Trace, err := api.scrollTracerWrapper.CreateTraceEnvAndGetBlockTrace(api.backend.ChainConfig(), api.chainContext(ctx), api.backend.Engine(), chaindb, statedb, parent, block, true)
if err != nil {
return nil, err
}
if !unionStorageTrace {
l2Trace.StorageTrace.ApplyFilter(legacyStorageTrace)
for _, st := range l2Trace.TxStorageTraces {
st.ApplyFilter(legacyStorageTrace)
}
}
return l2Trace, nil
}
Loading