mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-29 16:13:47 +00:00
* add domain-spec poseidon hash * add warning message for deprecated method * update goimports * update zktrie to v0.6 * fixes for upgrade * resume deletion proof * update alpha genesis since new hash sch eme * dump zktrie to 0.6 * induce genesis block for scroll sepolia network * Update version.go --------- Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com> Co-authored-by: Péter Garamvölgyi <peter@scroll.io>
183 lines
5.1 KiB
Go
183 lines
5.1 KiB
Go
package trie
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
|
|
zktrie "github.com/scroll-tech/zktrie/trie"
|
|
zkt "github.com/scroll-tech/zktrie/types"
|
|
|
|
"github.com/scroll-tech/go-ethereum/ethdb"
|
|
)
|
|
|
|
// Pick Node from its hash directly from database, notice it has different
|
|
// interface with the function of same name in `trie`
|
|
func (t *ZkTrie) TryGetNode(nodeHash *zkt.Hash) (*zktrie.Node, error) {
|
|
if bytes.Equal(nodeHash[:], zkt.HashZero[:]) {
|
|
return zktrie.NewEmptyNode(), nil
|
|
}
|
|
nBytes, err := t.db.Get(nodeHash[:])
|
|
if err == zktrie.ErrKeyNotFound {
|
|
return nil, zktrie.ErrKeyNotFound
|
|
} else if err != nil {
|
|
return nil, err
|
|
}
|
|
return zktrie.NewNodeFromBytes(nBytes)
|
|
}
|
|
|
|
type ProofTracer struct {
|
|
*ZkTrie
|
|
deletionTracer map[zkt.Hash]struct{}
|
|
rawPaths map[string][]*zktrie.Node
|
|
emptyTermPaths map[string][]*zktrie.Node
|
|
}
|
|
|
|
// NewProofTracer create a proof tracer object
|
|
func (t *ZkTrie) NewProofTracer() *ProofTracer {
|
|
return &ProofTracer{
|
|
ZkTrie: t,
|
|
// always consider 0 is "deleted"
|
|
deletionTracer: map[zkt.Hash]struct{}{zkt.HashZero: {}},
|
|
rawPaths: make(map[string][]*zktrie.Node),
|
|
emptyTermPaths: make(map[string][]*zktrie.Node),
|
|
}
|
|
}
|
|
|
|
// Merge merge the input tracer into current and return current tracer
|
|
func (t *ProofTracer) Merge(another *ProofTracer) *ProofTracer {
|
|
|
|
// sanity checking
|
|
if !bytes.Equal(t.Hash().Bytes(), another.Hash().Bytes()) {
|
|
panic("can not merge two proof tracer base on different trie")
|
|
}
|
|
|
|
for k := range another.deletionTracer {
|
|
t.deletionTracer[k] = struct{}{}
|
|
}
|
|
|
|
for k, v := range another.rawPaths {
|
|
t.rawPaths[k] = v
|
|
}
|
|
|
|
for k, v := range another.emptyTermPaths {
|
|
t.emptyTermPaths[k] = v
|
|
}
|
|
|
|
return t
|
|
}
|
|
|
|
// GetDeletionProofs generate current deletionTracer and collect deletion proofs
|
|
// which is possible to be used from all rawPaths, which enabling witness generator
|
|
// to predict the final state root after executing any deletion
|
|
// along any of the rawpath, no matter of the deletion occurs in any position of the mpt ops
|
|
// Note the collected sibling node has no key along with it since witness generator would
|
|
// always decode the node for its purpose
|
|
func (t *ProofTracer) GetDeletionProofs() ([][]byte, error) {
|
|
|
|
retMap := map[zkt.Hash][]byte{}
|
|
|
|
// check each path: reversively, skip the final leaf node
|
|
for _, path := range t.rawPaths {
|
|
|
|
checkPath := path[:len(path)-1]
|
|
for i := len(checkPath); i > 0; i-- {
|
|
n := checkPath[i-1]
|
|
_, deletedL := t.deletionTracer[*n.ChildL]
|
|
_, deletedR := t.deletionTracer[*n.ChildR]
|
|
if deletedL && deletedR {
|
|
nodeHash, _ := n.NodeHash()
|
|
t.deletionTracer[*nodeHash] = struct{}{}
|
|
} else {
|
|
var siblingHash *zkt.Hash
|
|
if deletedL {
|
|
siblingHash = n.ChildR
|
|
} else if deletedR {
|
|
siblingHash = n.ChildL
|
|
}
|
|
if siblingHash != nil {
|
|
sibling, err := t.TryGetNode(siblingHash)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if sibling.Type != zktrie.NodeTypeEmpty_New {
|
|
retMap[*siblingHash] = sibling.Value()
|
|
}
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
var ret [][]byte
|
|
for _, bt := range retMap {
|
|
ret = append(ret, bt)
|
|
}
|
|
|
|
return ret, nil
|
|
|
|
}
|
|
|
|
// MarkDeletion mark a key has been involved into deletion
|
|
func (t *ProofTracer) MarkDeletion(key []byte) {
|
|
if path, existed := t.emptyTermPaths[string(key)]; existed {
|
|
// copy empty node terminated path for final scanning
|
|
t.rawPaths[string(key)] = path
|
|
} else if path, existed = t.rawPaths[string(key)]; existed {
|
|
// sanity check
|
|
leafNode := path[len(path)-1]
|
|
|
|
if leafNode.Type != zktrie.NodeTypeLeaf_New {
|
|
panic("all path recorded in proofTrace should be ended with leafNode")
|
|
}
|
|
|
|
nodeHash, _ := leafNode.NodeHash()
|
|
t.deletionTracer[*nodeHash] = struct{}{}
|
|
}
|
|
}
|
|
|
|
// Prove act the same as zktrie.Prove, while also collect the raw path
|
|
// for collecting deletion proofs in a post-work
|
|
func (t *ProofTracer) Prove(key []byte, fromLevel uint, proofDb ethdb.KeyValueWriter) error {
|
|
var mptPath []*zktrie.Node
|
|
err := t.ZkTrie.ProveWithDeletion(key, fromLevel,
|
|
func(n *zktrie.Node) error {
|
|
nodeHash, err := n.NodeHash()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
switch n.Type {
|
|
case zktrie.NodeTypeLeaf_New:
|
|
preImage := t.GetKey(n.NodeKey.Bytes())
|
|
if len(preImage) > 0 {
|
|
n.KeyPreimage = &zkt.Byte32{}
|
|
copy(n.KeyPreimage[:], preImage)
|
|
}
|
|
case zktrie.NodeTypeBranch_0, zktrie.NodeTypeBranch_1,
|
|
zktrie.NodeTypeBranch_2, zktrie.NodeTypeBranch_3:
|
|
mptPath = append(mptPath, n)
|
|
case zktrie.NodeTypeEmpty_New:
|
|
// empty node is considered as "unhit" but it should be also being added
|
|
// into a temporary slot for possibly being marked as deletion later
|
|
mptPath = append(mptPath, n)
|
|
t.emptyTermPaths[string(key)] = mptPath
|
|
default:
|
|
panic(fmt.Errorf("unexpected node type %d", n.Type))
|
|
}
|
|
|
|
return proofDb.Put(nodeHash[:], n.Value())
|
|
},
|
|
func(n *zktrie.Node, _ *zktrie.Node) {
|
|
// only "hit" path (i.e. the leaf node corresponding the input key can be found)
|
|
// would be add into tracer
|
|
mptPath = append(mptPath, n)
|
|
t.rawPaths[string(key)] = mptPath
|
|
},
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
// we put this special kv pair in db so we can distinguish the type and
|
|
// make suitable Proof
|
|
return proofDb.Put(magicHash, zktrie.ProofMagicBytes())
|
|
}
|