github.com/cryptotooltop/go-ethereum@v0.0.0-20231103184714-151d1922f3e5/trie/zkproof/writer.go (about)

     1  package zkproof
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"math/big"
     8  
     9  	zktrie "github.com/scroll-tech/zktrie/trie"
    10  	zkt "github.com/scroll-tech/zktrie/types"
    11  
    12  	"github.com/scroll-tech/go-ethereum/common"
    13  	"github.com/scroll-tech/go-ethereum/common/hexutil"
    14  	"github.com/scroll-tech/go-ethereum/core/types"
    15  	"github.com/scroll-tech/go-ethereum/ethdb/memorydb"
    16  	"github.com/scroll-tech/go-ethereum/log"
    17  	"github.com/scroll-tech/go-ethereum/trie"
    18  )
    19  
    20  type proofList [][]byte
    21  
    22  func (n *proofList) Put(key []byte, value []byte) error {
    23  	*n = append(*n, value)
    24  	return nil
    25  }
    26  
    27  func (n *proofList) Delete(key []byte) error {
    28  	panic("not supported")
    29  }
    30  
    31  func addressToKey(addr common.Address) *zkt.Hash {
    32  	var preImage zkt.Byte32
    33  	copy(preImage[:], addr.Bytes())
    34  
    35  	h, err := preImage.Hash()
    36  	if err != nil {
    37  		log.Error("hash failure", "preImage", hexutil.Encode(preImage[:]))
    38  		return nil
    39  	}
    40  	return zkt.NewHashFromBigInt(h)
    41  }
    42  
    43  // resume the proof bytes into db and return the leaf node
    44  func resumeProofs(proof []hexutil.Bytes, db *memorydb.Database) *zktrie.Node {
    45  	for _, buf := range proof {
    46  
    47  		n, err := zktrie.DecodeSMTProof(buf)
    48  		if err != nil {
    49  			log.Warn("decode proof string fail", "error", err)
    50  		} else if n != nil {
    51  			hash, err := n.NodeHash()
    52  			if err != nil {
    53  				log.Warn("node has no valid node hash", "error", err)
    54  			} else {
    55  				//notice: must consistent with trie/merkletree.go
    56  				bt := hash[:]
    57  				db.Put(bt, buf)
    58  				if n.Type == zktrie.NodeTypeLeaf_New || n.Type == zktrie.NodeTypeEmpty_New {
    59  					return n
    60  				}
    61  			}
    62  		}
    63  
    64  	}
    65  
    66  	return nil
    67  }
    68  
    69  // we have a trick here which suppose the proof array include all middle nodes along the
    70  // whole path in sequence, from root to leaf
    71  func decodeProofForMPTPath(proof proofList, path *SMTPath) {
    72  
    73  	var lastNode *zktrie.Node
    74  	keyPath := big.NewInt(0)
    75  	path.KeyPathPart = (*hexutil.Big)(keyPath)
    76  
    77  	keyCounter := big.NewInt(1)
    78  
    79  	for _, buf := range proof {
    80  		n, err := zktrie.DecodeSMTProof(buf)
    81  		if err != nil {
    82  			log.Warn("decode proof string fail", "error", err)
    83  		} else if n != nil {
    84  			hash, err := n.NodeHash()
    85  			if err != nil {
    86  				log.Warn("node has no valid node hash", "error", err)
    87  				return
    88  			}
    89  			if lastNode == nil {
    90  				// notice: use little-endian represent inside Hash ([:] or Byte32())
    91  				path.Root = hash[:]
    92  			} else {
    93  				if bytes.Equal(hash[:], lastNode.ChildL[:]) {
    94  					path.Path = append(path.Path, SMTPathNode{
    95  						Value:   hash[:],
    96  						Sibling: lastNode.ChildR[:],
    97  					})
    98  				} else if bytes.Equal(hash[:], lastNode.ChildR[:]) {
    99  					path.Path = append(path.Path, SMTPathNode{
   100  						Value:   hash[:],
   101  						Sibling: lastNode.ChildL[:],
   102  					})
   103  					keyPath.Add(keyPath, keyCounter)
   104  				} else {
   105  					panic("Unexpected proof form")
   106  				}
   107  				keyCounter.Mul(keyCounter, big.NewInt(2))
   108  			}
   109  			switch n.Type {
   110  			case zktrie.NodeTypeBranch_0, zktrie.NodeTypeBranch_1, zktrie.NodeTypeBranch_2, zktrie.NodeTypeBranch_3:
   111  				lastNode = n
   112  			case zktrie.NodeTypeLeaf_New:
   113  				vhash, _ := n.ValueHash()
   114  				path.Leaf = &SMTPathNode{
   115  					//here we just return the inner represent of hash (little endian, reversed byte order to common hash)
   116  					Value:   vhash[:],
   117  					Sibling: n.NodeKey[:],
   118  				}
   119  				//sanity check
   120  				keyPart := keyPath.Bytes()
   121  				for i, b := range keyPart {
   122  					ri := len(keyPart) - i
   123  					cb := path.Leaf.Sibling[ri-1] //notice the output is little-endian
   124  					if b&cb != b {
   125  						panic(fmt.Errorf("path key not match: part is %x but key is %x", keyPart, []byte(path.Leaf.Sibling[:])))
   126  					}
   127  				}
   128  
   129  				return
   130  			case zktrie.NodeTypeEmpty_New:
   131  				return
   132  			default:
   133  				panic(fmt.Errorf("unknown node type %d", n.Type))
   134  			}
   135  		}
   136  	}
   137  
   138  	panic("Unexpected finished here")
   139  }
   140  
   141  type zktrieProofWriter struct {
   142  	db                  *trie.ZktrieDatabase
   143  	tracingZktrie       *trie.ZkTrie
   144  	tracingStorageTries map[common.Address]*trie.ZkTrie
   145  	tracingAccounts     map[common.Address]*types.StateAccount
   146  }
   147  
   148  func (wr *zktrieProofWriter) TracingAccounts() map[common.Address]*types.StateAccount {
   149  	return wr.tracingAccounts
   150  }
   151  
   152  func NewZkTrieProofWriter(storage *types.StorageTrace) (*zktrieProofWriter, error) {
   153  
   154  	underlayerDb := memorydb.New()
   155  	zkDb := trie.NewZktrieDatabase(underlayerDb)
   156  
   157  	accounts := make(map[common.Address]*types.StateAccount)
   158  
   159  	// resuming proof bytes to underlayerDb
   160  	for addrs, proof := range storage.Proofs {
   161  		if n := resumeProofs(proof, underlayerDb); n != nil {
   162  			addr := common.HexToAddress(addrs)
   163  			if n.Type == zktrie.NodeTypeEmpty_New {
   164  				accounts[addr] = nil
   165  			} else if acc, err := types.UnmarshalStateAccount(n.Data()); err == nil {
   166  				if bytes.Equal(n.NodeKey[:], addressToKey(addr)[:]) {
   167  					accounts[addr] = acc
   168  				} else {
   169  					// should still mark the address as being trace (data not existed yet)
   170  					accounts[addr] = nil
   171  				}
   172  
   173  			} else {
   174  				return nil, fmt.Errorf("decode account bytes fail: %s, raw data [%x]", err, n.Data())
   175  			}
   176  
   177  		} else {
   178  			return nil, fmt.Errorf("can not resume proof for address %s", addrs)
   179  		}
   180  	}
   181  
   182  	storages := make(map[common.Address]*trie.ZkTrie)
   183  
   184  	for addrs, stgLists := range storage.StorageProofs {
   185  
   186  		addr := common.HexToAddress(addrs)
   187  		accState, existed := accounts[addr]
   188  		if !existed {
   189  			// trace is malformed but currently we just warn about that
   190  			log.Warn("no account state found for this addr, mal records", "address", addrs)
   191  			continue
   192  		} else if accState == nil {
   193  			// create an empty zktrie for uninit address
   194  			storages[addr], _ = trie.NewZkTrie(common.Hash{}, zkDb)
   195  			continue
   196  		}
   197  
   198  		for keys, proof := range stgLists {
   199  
   200  			if n := resumeProofs(proof, underlayerDb); n != nil {
   201  				var err error
   202  				storages[addr], err = trie.NewZkTrie(accState.Root, zkDb)
   203  				if err != nil {
   204  					return nil, fmt.Errorf("zktrie create failure for storage in addr <%s>: %s, (root %s)", addrs, err, accState.Root)
   205  				}
   206  
   207  			} else {
   208  				return nil, fmt.Errorf("can not resume proof for storage %s@%s", keys, addrs)
   209  			}
   210  
   211  		}
   212  	}
   213  
   214  	for _, delProof := range storage.DeletionProofs {
   215  
   216  		n, err := zktrie.DecodeSMTProof(delProof)
   217  		if err != nil {
   218  			log.Warn("decode delproof string fail", "error", err, "node", delProof)
   219  		} else if n != nil {
   220  			hash, err := n.NodeHash()
   221  			if err != nil {
   222  				log.Warn("node has no valid node hash", "error", err)
   223  			} else {
   224  				//notice: must consistent with trie/merkletree.go
   225  				bt := hash[:]
   226  				underlayerDb.Put(bt, delProof)
   227  			}
   228  		}
   229  	}
   230  
   231  	zktrie, err := trie.NewZkTrie(
   232  		storage.RootBefore,
   233  		trie.NewZktrieDatabase(underlayerDb),
   234  	)
   235  	if err != nil {
   236  		return nil, fmt.Errorf("zktrie create failure: %s", err)
   237  	}
   238  
   239  	// sanity check
   240  	if !bytes.Equal(zktrie.Hash().Bytes(), storage.RootBefore.Bytes()) {
   241  		return nil, fmt.Errorf("unmatch init trie hash: expected %x but has %x", storage.RootBefore.Bytes(), zktrie.Hash().Bytes())
   242  	}
   243  
   244  	return &zktrieProofWriter{
   245  		db:                  zkDb,
   246  		tracingZktrie:       zktrie,
   247  		tracingAccounts:     accounts,
   248  		tracingStorageTries: storages,
   249  	}, nil
   250  }
   251  
   252  const (
   253  	posSSTOREBefore = 0
   254  	posCREATE       = 0
   255  	posCREATEAfter  = 1
   256  	posCALL         = 2
   257  	posSTATICCALL   = 0
   258  
   259  	// posSELFDESTRUCT = 2
   260  )
   261  
   262  func getAccountState(l *types.StructLogRes, pos int) *types.AccountWrapper {
   263  	if exData := l.ExtraData; exData == nil {
   264  		return nil
   265  	} else if len(exData.StateList) < pos {
   266  		return nil
   267  	} else {
   268  		return exData.StateList[pos]
   269  	}
   270  }
   271  
   272  func copyAccountState(st *types.AccountWrapper) *types.AccountWrapper {
   273  
   274  	var stg *types.StorageWrapper
   275  	if st.Storage != nil {
   276  		stg = &types.StorageWrapper{
   277  			Key:   st.Storage.Key,
   278  			Value: st.Storage.Value,
   279  		}
   280  	}
   281  
   282  	return &types.AccountWrapper{
   283  		Nonce:            st.Nonce,
   284  		Balance:          (*hexutil.Big)(big.NewInt(0).Set(st.Balance.ToInt())),
   285  		KeccakCodeHash:   st.KeccakCodeHash,
   286  		PoseidonCodeHash: st.PoseidonCodeHash,
   287  		CodeSize:         st.CodeSize,
   288  		Address:          st.Address,
   289  		Storage:          stg,
   290  	}
   291  }
   292  
   293  func isDeletedAccount(state *types.AccountWrapper) bool {
   294  	return state.Nonce == 0 && bytes.Equal(state.KeccakCodeHash.Bytes(), common.Hash{}.Bytes())
   295  }
   296  
   297  func getAccountDataFromLogState(state *types.AccountWrapper) *types.StateAccount {
   298  
   299  	if isDeletedAccount(state) {
   300  		return nil
   301  	}
   302  
   303  	return &types.StateAccount{
   304  		Nonce:            state.Nonce,
   305  		Balance:          (*big.Int)(state.Balance),
   306  		KeccakCodeHash:   state.KeccakCodeHash.Bytes(),
   307  		PoseidonCodeHash: state.PoseidonCodeHash.Bytes(),
   308  		CodeSize:         state.CodeSize,
   309  		// Root omitted intentionally
   310  	}
   311  }
   312  
   313  // for sanity check
   314  func verifyAccount(addr common.Address, data *types.StateAccount, leaf *SMTPathNode) error {
   315  
   316  	if leaf == nil {
   317  		if data != nil {
   318  			return fmt.Errorf("path has no corresponding leaf for account")
   319  		} else {
   320  			return nil
   321  		}
   322  	}
   323  
   324  	addrKey := addressToKey(addr)
   325  	if !bytes.Equal(addrKey[:], leaf.Sibling) {
   326  		if data != nil {
   327  			return fmt.Errorf("unmatch leaf node in address: %s", addr)
   328  		}
   329  	} else if data != nil {
   330  		arr, flag := data.MarshalFields()
   331  		h, err := zkt.HandlingElemsAndByte32(flag, arr)
   332  		//log.Info("sanity check acc before", "addr", addr.String(), "key", leaf.Sibling.Text(16), "hash", h.Text(16))
   333  
   334  		if err != nil {
   335  			return fmt.Errorf("fail to hash account: %v", err)
   336  		}
   337  		if !bytes.Equal(h[:], leaf.Value) {
   338  			return fmt.Errorf("unmatch data in leaf for address %s", addr)
   339  		}
   340  	}
   341  	return nil
   342  }
   343  
   344  // for sanity check
   345  func verifyStorage(key *zkt.Byte32, data *zkt.Byte32, leaf *SMTPathNode) error {
   346  
   347  	emptyData := bytes.Equal(data[:], common.Hash{}.Bytes())
   348  
   349  	if leaf == nil {
   350  		if !emptyData {
   351  			return fmt.Errorf("path has no corresponding leaf for storage")
   352  		} else {
   353  			return nil
   354  		}
   355  	}
   356  
   357  	keyHash, err := key.Hash()
   358  	if err != nil {
   359  		return err
   360  	}
   361  
   362  	if !bytes.Equal(zkt.NewHashFromBigInt(keyHash)[:], leaf.Sibling) {
   363  		if !emptyData {
   364  			return fmt.Errorf("unmatch leaf node in storage: %x", key[:])
   365  		}
   366  	} else {
   367  		h, err := data.Hash()
   368  		//log.Info("sanity check acc before", "addr", addr.String(), "key", leaf.Sibling.Text(16), "hash", h.Text(16))
   369  
   370  		if err != nil {
   371  			return fmt.Errorf("fail to hash data: %v", err)
   372  		}
   373  		if !bytes.Equal(zkt.NewHashFromBigInt(h)[:], leaf.Value) {
   374  			return fmt.Errorf("unmatch data in leaf for storage %x", key[:])
   375  		}
   376  	}
   377  	return nil
   378  }
   379  
   380  // update traced account state, and return the corresponding trace object which
   381  // is still opened for more infos
   382  // the updated accData state is obtained by a closure which enable it being derived from current status
   383  func (w *zktrieProofWriter) traceAccountUpdate(addr common.Address, updateAccData func(*types.StateAccount) *types.StateAccount) (*StorageTrace, error) {
   384  
   385  	out := new(StorageTrace)
   386  	//account trie
   387  	out.Address = addr.Bytes()
   388  	out.AccountPath = [2]*SMTPath{{}, {}}
   389  	//fill dummy
   390  	out.AccountUpdate = [2]*StateAccount{}
   391  
   392  	accDataBefore, existed := w.tracingAccounts[addr]
   393  	if !existed {
   394  		//sanity check
   395  		panic(fmt.Errorf("code do not add initialized status for account %s", addr))
   396  	}
   397  
   398  	var proof proofList
   399  	s_key, _ := zkt.ToSecureKeyBytes(addr.Bytes())
   400  	if err := w.tracingZktrie.Prove(s_key.Bytes(), 0, &proof); err != nil {
   401  		return nil, fmt.Errorf("prove BEFORE state fail: %s", err)
   402  	}
   403  
   404  	decodeProofForMPTPath(proof, out.AccountPath[0])
   405  	if err := verifyAccount(addr, accDataBefore, out.AccountPath[0].Leaf); err != nil {
   406  		panic(fmt.Errorf("code fail to trace account status correctly: %s", err))
   407  	}
   408  	if accDataBefore != nil {
   409  		// we have ensured the nBefore has a key corresponding to the query one
   410  		out.AccountKey = out.AccountPath[0].Leaf.Sibling
   411  		out.AccountUpdate[0] = &StateAccount{
   412  			Nonce:            int(accDataBefore.Nonce),
   413  			Balance:          (*hexutil.Big)(big.NewInt(0).Set(accDataBefore.Balance)),
   414  			KeccakCodeHash:   accDataBefore.KeccakCodeHash,
   415  			PoseidonCodeHash: accDataBefore.PoseidonCodeHash,
   416  			CodeSize:         accDataBefore.CodeSize,
   417  		}
   418  	}
   419  
   420  	accData := updateAccData(accDataBefore)
   421  	if accData != nil {
   422  		out.AccountUpdate[1] = &StateAccount{
   423  			Nonce:            int(accData.Nonce),
   424  			Balance:          (*hexutil.Big)(big.NewInt(0).Set(accData.Balance)),
   425  			KeccakCodeHash:   accData.KeccakCodeHash,
   426  			PoseidonCodeHash: accData.PoseidonCodeHash,
   427  			CodeSize:         accData.CodeSize,
   428  		}
   429  	}
   430  
   431  	if accData != nil {
   432  		if err := w.tracingZktrie.TryUpdateAccount(addr.Bytes32(), accData); err != nil {
   433  			return nil, fmt.Errorf("update zktrie account state fail: %s", err)
   434  		}
   435  		w.tracingAccounts[addr] = accData
   436  	} else if accDataBefore != nil {
   437  		if err := w.tracingZktrie.TryDelete(addr.Bytes32()); err != nil {
   438  			return nil, fmt.Errorf("delete zktrie account state fail: %s", err)
   439  		}
   440  		w.tracingAccounts[addr] = nil
   441  	} // notice if both before/after is nil, we do not touch zktrie
   442  
   443  	proof = proofList{}
   444  	if err := w.tracingZktrie.Prove(s_key.Bytes(), 0, &proof); err != nil {
   445  		return nil, fmt.Errorf("prove AFTER state fail: %s", err)
   446  	}
   447  
   448  	decodeProofForMPTPath(proof, out.AccountPath[1])
   449  	if err := verifyAccount(addr, accData, out.AccountPath[1].Leaf); err != nil {
   450  		panic(fmt.Errorf("state AFTER has no valid account: %s", err))
   451  	}
   452  	if accData != nil {
   453  		if out.AccountKey == nil {
   454  			out.AccountKey = out.AccountPath[1].Leaf.Sibling[:]
   455  		}
   456  		//now accountKey must has been filled
   457  	}
   458  
   459  	// notice we have change that no leaf (account data) exist in either before or after,
   460  	// for that case we had to calculate the nodeKey here
   461  	if out.AccountKey == nil {
   462  		word := zkt.NewByte32FromBytesPaddingZero(addr.Bytes())
   463  		k, err := word.Hash()
   464  		if err != nil {
   465  			panic(fmt.Errorf("unexpected hash error for address: %s", err))
   466  		}
   467  		kHash := zkt.NewHashFromBigInt(k)
   468  		out.AccountKey = hexutil.Bytes(kHash[:])
   469  	}
   470  
   471  	return out, nil
   472  }
   473  
   474  // update traced storage state, and return the corresponding trace object
   475  func (w *zktrieProofWriter) traceStorageUpdate(addr common.Address, key, value []byte) (*StorageTrace, error) {
   476  
   477  	trie := w.tracingStorageTries[addr]
   478  	if trie == nil {
   479  		return nil, fmt.Errorf("no trace storage trie for %s", addr)
   480  	}
   481  
   482  	statePath := [2]*SMTPath{{}, {}}
   483  	stateUpdate := [2]*StateStorage{}
   484  
   485  	storeKey := zkt.NewByte32FromBytesPaddingZero(common.BytesToHash(key).Bytes())
   486  	storeValueBefore := trie.Get(storeKey[:])
   487  	storeValue := zkt.NewByte32FromBytes(value)
   488  	valZero := zkt.Byte32{}
   489  
   490  	if storeValueBefore != nil && !bytes.Equal(storeValueBefore[:], common.Hash{}.Bytes()) {
   491  		stateUpdate[0] = &StateStorage{
   492  			Key:   storeKey.Bytes(),
   493  			Value: storeValueBefore,
   494  		}
   495  	}
   496  
   497  	var storageBeforeProof, storageAfterProof proofList
   498  	s_key, _ := zkt.ToSecureKeyBytes(storeKey.Bytes())
   499  	if err := trie.Prove(s_key.Bytes(), 0, &storageBeforeProof); err != nil {
   500  		return nil, fmt.Errorf("prove BEFORE storage state fail: %s", err)
   501  	}
   502  
   503  	decodeProofForMPTPath(storageBeforeProof, statePath[0])
   504  	if err := verifyStorage(storeKey, zkt.NewByte32FromBytes(storeValueBefore), statePath[0].Leaf); err != nil {
   505  		panic(fmt.Errorf("storage BEFORE has no valid data: %s (%v)", err, statePath[0]))
   506  	}
   507  
   508  	if !bytes.Equal(storeValue.Bytes(), common.Hash{}.Bytes()) {
   509  		if err := trie.TryUpdate(storeKey.Bytes(), storeValue.Bytes()); err != nil {
   510  			return nil, fmt.Errorf("update zktrie storage fail: %s", err)
   511  		}
   512  		stateUpdate[1] = &StateStorage{
   513  			Key:   storeKey.Bytes(),
   514  			Value: storeValue.Bytes(),
   515  		}
   516  	} else {
   517  		if err := trie.TryDelete(storeKey.Bytes()); err != nil {
   518  			return nil, fmt.Errorf("delete zktrie storage fail: %s", err)
   519  		}
   520  	}
   521  
   522  	if err := trie.Prove(s_key.Bytes(), 0, &storageAfterProof); err != nil {
   523  		return nil, fmt.Errorf("prove AFTER storage state fail: %s", err)
   524  	}
   525  	decodeProofForMPTPath(storageAfterProof, statePath[1])
   526  	if err := verifyStorage(storeKey, storeValue, statePath[1].Leaf); err != nil {
   527  		panic(fmt.Errorf("storage AFTER has no valid data: %s (%v)", err, statePath[1]))
   528  	}
   529  
   530  	out, err := w.traceAccountUpdate(addr,
   531  		func(acc *types.StateAccount) *types.StateAccount {
   532  			if acc == nil {
   533  				// in case we read an unexist account
   534  				if !bytes.Equal(valZero.Bytes(), value) {
   535  					panic(fmt.Errorf("write to an unexist account [%s] which is not allowed", addr))
   536  				}
   537  				return nil
   538  			}
   539  
   540  			//sanity check
   541  			if accRootFromState := zkt.ReverseByteOrder(statePath[0].Root); !bytes.Equal(acc.Root[:], accRootFromState) {
   542  				panic(fmt.Errorf("unexpected storage root before: [%s] vs [%x]", acc.Root, accRootFromState))
   543  			}
   544  			return &types.StateAccount{
   545  				Nonce:            acc.Nonce,
   546  				Balance:          acc.Balance,
   547  				Root:             common.BytesToHash(zkt.ReverseByteOrder(statePath[1].Root)),
   548  				KeccakCodeHash:   acc.KeccakCodeHash,
   549  				PoseidonCodeHash: acc.PoseidonCodeHash,
   550  				CodeSize:         acc.CodeSize,
   551  			}
   552  		})
   553  	if err != nil {
   554  		return nil, fmt.Errorf("update account %s in SSTORE fail: %s", addr, err)
   555  	}
   556  
   557  	if stateUpdate[1] != nil {
   558  		out.StateKey = statePath[1].Leaf.Sibling
   559  	} else if stateUpdate[0] != nil {
   560  		out.StateKey = statePath[0].Leaf.Sibling
   561  	} else {
   562  		// it occurs when we are handling SLOAD with non-exist value
   563  		// still no pretty idea, had to touch the internal behavior in zktrie ....
   564  		if h, err := storeKey.Hash(); err != nil {
   565  			return nil, fmt.Errorf("hash storekey fail: %s", err)
   566  		} else {
   567  			out.StateKey = zkt.NewHashFromBigInt(h)[:]
   568  		}
   569  		stateUpdate[1] = &StateStorage{
   570  			Key:   storeKey.Bytes(),
   571  			Value: valZero.Bytes(),
   572  		}
   573  		stateUpdate[0] = stateUpdate[1]
   574  	}
   575  
   576  	out.StatePath = statePath
   577  	out.StateUpdate = stateUpdate
   578  	return out, nil
   579  }
   580  
   581  func (w *zktrieProofWriter) HandleNewState(accountState *types.AccountWrapper) (*StorageTrace, error) {
   582  
   583  	if accountState.Storage != nil {
   584  		storeAddr := hexutil.MustDecode(accountState.Storage.Key)
   585  		storeValue := hexutil.MustDecode(accountState.Storage.Value)
   586  		return w.traceStorageUpdate(accountState.Address, storeAddr, storeValue)
   587  	} else {
   588  
   589  		var stateRoot common.Hash
   590  		accData := getAccountDataFromLogState(accountState)
   591  
   592  		out, err := w.traceAccountUpdate(accountState.Address, func(accBefore *types.StateAccount) *types.StateAccount {
   593  			if accBefore != nil {
   594  				stateRoot = accBefore.Root
   595  			}
   596  			// we need to restore stateRoot from before
   597  			if accData != nil {
   598  				accData.Root = stateRoot
   599  			}
   600  			return accData
   601  		})
   602  		if err != nil {
   603  			return nil, fmt.Errorf("update account state %s fail: %s", accountState.Address, err)
   604  		}
   605  
   606  		hash := zkt.NewHashFromBytes(stateRoot[:])
   607  		out.CommonStateRoot = hash[:]
   608  		return out, nil
   609  	}
   610  
   611  }
   612  
   613  func handleLogs(od opOrderer, currentContract common.Address, logs []*types.StructLogRes) {
   614  	logStack := []int{0}
   615  	contractStack := map[int]common.Address{}
   616  	callEnterAddress := currentContract
   617  
   618  	// now trace every OP which could cause changes on state:
   619  	for i, sLog := range logs {
   620  
   621  		//trace log stack by depth rather than scanning specified op
   622  		if sl := len(logStack); sl < sLog.Depth {
   623  			logStack = append(logStack, i)
   624  			//update currentContract according to previous op
   625  			contractStack[sl] = currentContract
   626  			currentContract = callEnterAddress
   627  
   628  		} else if sl > sLog.Depth {
   629  			logStack = logStack[:sl-1]
   630  			currentContract = contractStack[sLog.Depth]
   631  			resumePos := logStack[len(logStack)-1]
   632  			calledLog := logs[resumePos]
   633  
   634  			//no need to handle fail calling
   635  			if calledLog.ExtraData != nil {
   636  				if !calledLog.ExtraData.CallFailed {
   637  					//reentry the last log which "cause" the calling, some handling may needed
   638  					switch calledLog.Op {
   639  					case "CREATE", "CREATE2":
   640  						//addr, accDataBefore := getAccountDataFromProof(calledLog, posCALLBefore)
   641  						od.absorb(getAccountState(calledLog, posCREATEAfter))
   642  					}
   643  				} else {
   644  					od.readonly(false)
   645  				}
   646  			}
   647  
   648  		} else {
   649  			logStack[sl-1] = i
   650  		}
   651  		//sanity check
   652  		if len(logStack) != sLog.Depth {
   653  			panic("tracking log stack failure")
   654  		}
   655  		callEnterAddress = currentContract
   656  
   657  		//check extra status for current op if it is a call
   658  		if extraData := sLog.ExtraData; extraData != nil {
   659  			if extraData.CallFailed || len(sLog.ExtraData.Caller) < 2 {
   660  				// no enough caller data (2) is being capture indicate we are in an immediate failure
   661  				// i.e. it fail before stack entry (like no enough balance for a "call with value"),
   662  				// or we just not handle this calling op correctly yet
   663  
   664  				// for a failed option, now we just purpose nothing happens (FIXME: it is inconsentent with mpt_table)
   665  				// except for CREATE, for which the callee's nonce would be increased
   666  				switch sLog.Op {
   667  				case "CREATE", "CREATE2":
   668  					st := copyAccountState(extraData.Caller[0])
   669  					st.Nonce += 1
   670  					od.absorb(st)
   671  				}
   672  			}
   673  
   674  			if extraData.CallFailed {
   675  				od.readonly(true)
   676  			}
   677  			// now trace caller's status first
   678  			if caller := extraData.Caller; len(caller) >= 2 {
   679  				od.absorb(caller[1])
   680  			}
   681  		}
   682  
   683  		switch sLog.Op {
   684  		case "SELFDESTRUCT":
   685  			// NOTE: this op code has been disabled so we treat it as nothing now
   686  
   687  			//in SELFDESTRUCT, a call on target address is made so the balance would be updated
   688  			//in the last item
   689  			//stateTarget := getAccountState(sLog, posSELFDESTRUCT)
   690  			//od.absorb(stateTarget)
   691  			//then build an "deleted state", only address and other are default
   692  			//od.absorb(&types.AccountWrapper{Address: currentContract})
   693  
   694  		case "CREATE", "CREATE2":
   695  			// notice in immediate failure we have no enough tracing in extraData
   696  			if len(sLog.ExtraData.StateList) >= 2 {
   697  				state := getAccountState(sLog, posCREATE)
   698  				od.absorb(state)
   699  				//update contract to CREATE addr
   700  				callEnterAddress = state.Address
   701  			}
   702  
   703  		case "CALL", "CALLCODE":
   704  			// notice in immediate failure we have no enough tracing in extraData
   705  			if len(sLog.ExtraData.StateList) >= 3 {
   706  				state := getAccountState(sLog, posCALL)
   707  				od.absorb(state)
   708  				callEnterAddress = state.Address
   709  			}
   710  		case "STATICCALL":
   711  			//static call has no update on target address (and no immediate failure?)
   712  			callEnterAddress = getAccountState(sLog, posSTATICCALL).Address
   713  		case "DELEGATECALL":
   714  
   715  		case "SLOAD":
   716  			accountState := getAccountState(sLog, posSSTOREBefore)
   717  			od.absorbStorage(accountState, nil)
   718  		case "SSTORE":
   719  			log.Debug("build SSTORE", "pc", sLog.Pc, "key", sLog.Stack[len(sLog.Stack)-1])
   720  			accountState := copyAccountState(getAccountState(sLog, posSSTOREBefore))
   721  			// notice the log only provide the value BEFORE store and it is not suitable for our protocol,
   722  			// here we change it into value AFTER update
   723  			before := accountState.Storage
   724  			accountState.Storage = &types.StorageWrapper{
   725  				Key:   sLog.Stack[len(sLog.Stack)-1],
   726  				Value: sLog.Stack[len(sLog.Stack)-2],
   727  			}
   728  			od.absorbStorage(accountState, before)
   729  
   730  		default:
   731  		}
   732  	}
   733  }
   734  
   735  func HandleTx(od opOrderer, txResult *types.ExecutionResult) {
   736  
   737  	// the from state is read before tx is handled and nonce is added, we combine both
   738  	preTxSt := copyAccountState(txResult.From)
   739  	preTxSt.Nonce += 1
   740  	od.absorb(preTxSt)
   741  
   742  	if txResult.Failed {
   743  		od.readonly(true)
   744  	}
   745  
   746  	var toAddr common.Address
   747  	if state := txResult.AccountCreated; state != nil {
   748  		od.absorb(state)
   749  		toAddr = state.Address
   750  	} else {
   751  		toAddr = txResult.To.Address
   752  	}
   753  
   754  	handleLogs(od, toAddr, txResult.StructLogs)
   755  	if txResult.Failed {
   756  		od.readonly(false)
   757  	}
   758  
   759  	for _, state := range txResult.AccountsAfter {
   760  		// special case: for suicide, the state has been captured in SELFDESTRUCT
   761  		// and we skip it here
   762  		if isDeletedAccount(state) {
   763  			log.Debug("skip suicide address", "address", state.Address)
   764  			continue
   765  		}
   766  
   767  		od.absorb(state)
   768  	}
   769  
   770  }
   771  
   772  const defaultOrdererScheme = MPTWitnessRWTbl
   773  
   774  var usedOrdererScheme = defaultOrdererScheme
   775  
   776  func SetOrderScheme(t MPTWitnessType) { usedOrdererScheme = t }
   777  
   778  // HandleBlockTrace only for backward compatibility
   779  func HandleBlockTrace(block *types.BlockTrace) ([]*StorageTrace, error) {
   780  	return HandleBlockTraceEx(block, usedOrdererScheme)
   781  }
   782  
   783  func HandleBlockTraceEx(block *types.BlockTrace, ordererScheme MPTWitnessType) ([]*StorageTrace, error) {
   784  
   785  	writer, err := NewZkTrieProofWriter(block.StorageTrace)
   786  	if err != nil {
   787  		return nil, err
   788  	}
   789  
   790  	var od opOrderer
   791  	switch ordererScheme {
   792  	case MPTWitnessNothing:
   793  		panic("should not come here when scheme is 0")
   794  	case MPTWitnessNatural:
   795  		od = &simpleOrderer{}
   796  	case MPTWitnessRWTbl:
   797  		od = NewRWTblOrderer(writer.tracingAccounts)
   798  	default:
   799  		return nil, fmt.Errorf("unrecognized scheme %d", ordererScheme)
   800  	}
   801  
   802  	for _, tx := range block.ExecutionResults {
   803  		HandleTx(od, tx)
   804  	}
   805  
   806  	// notice some coinbase addr (like all zero) is in fact not exist and should not be update
   807  	// TODO: not a good solution, just for patch ...
   808  	if coinbaseData := writer.tracingAccounts[block.Coinbase.Address]; coinbaseData != nil {
   809  		od.absorb(block.Coinbase)
   810  	}
   811  
   812  	opDisp := od.end_absorb()
   813  	var outTrace []*StorageTrace
   814  
   815  	for op := opDisp.next(); op != nil; op = opDisp.next() {
   816  		trace, err := writer.HandleNewState(op)
   817  		if err != nil {
   818  			return nil, err
   819  		}
   820  		outTrace = append(outTrace, trace)
   821  	}
   822  
   823  	finalHash := writer.tracingZktrie.Hash()
   824  	if !bytes.Equal(finalHash.Bytes(), block.StorageTrace.RootAfter.Bytes()) {
   825  		return outTrace, fmt.Errorf("unmatch hash: [%x] vs [%x]", finalHash.Bytes(), block.StorageTrace.RootAfter.Bytes())
   826  	}
   827  
   828  	return outTrace, nil
   829  
   830  }
   831  
   832  func FillBlockTraceForMPTWitness(order MPTWitnessType, block *types.BlockTrace) error {
   833  
   834  	if order == MPTWitnessNothing {
   835  		return nil
   836  	}
   837  
   838  	trace, err := HandleBlockTraceEx(block, order)
   839  	if err != nil {
   840  		return err
   841  	}
   842  
   843  	msg, err := json.Marshal(trace)
   844  	if err != nil {
   845  		return err
   846  	}
   847  
   848  	rawmsg := json.RawMessage(msg)
   849  
   850  	block.MPTWitness = &rawmsg
   851  	return nil
   852  }