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 }