go-ethereum/core/state/state_prove.go
Ho c913b3e2f1
fix(zktrie): fix deletion proofs and collect them in commiting phase (#263)
* new deletion proof

* complete tracer and test

* extend proof for parallel tracing

* integrating into blocktrace

* lint

* deduplication of deletion proofs

* fix an issue on marking deletion

* fixs since last review

* Update version.go

---------

Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
Co-authored-by: Ubuntu <ubuntu@ip-10-2-9-63.us-west-2.compute.internal>
2023-05-08 15:40:54 +08:00

88 lines
2.5 KiB
Go

package state
import (
"fmt"
zkt "github.com/scroll-tech/zktrie/types"
zktrie "github.com/scroll-tech/go-ethereum/trie"
"github.com/scroll-tech/go-ethereum/common"
"github.com/scroll-tech/go-ethereum/crypto"
"github.com/scroll-tech/go-ethereum/ethdb"
)
type TrieProve interface {
Prove(key []byte, fromLevel uint, proofDb ethdb.KeyValueWriter) error
}
type ZktrieProofTracer struct {
*zktrie.ProofTracer
}
// MarkDeletion overwrite the underlayer method with secure key
func (t ZktrieProofTracer) MarkDeletion(key common.Hash) {
key_s, _ := zkt.ToSecureKeyBytes(key.Bytes())
t.ProofTracer.MarkDeletion(key_s.Bytes())
}
// Merge overwrite underlayer method with proper argument
func (t ZktrieProofTracer) Merge(another ZktrieProofTracer) {
t.ProofTracer.Merge(another.ProofTracer)
}
func (t ZktrieProofTracer) Available() bool {
return t.ProofTracer != nil
}
// NewProofTracer is not in Db interface and used explictily for reading proof in storage trie (not updated by the dirty value)
func (s *StateDB) NewProofTracer(trieS Trie) ZktrieProofTracer {
if s.IsZktrie() {
zkTrie := trieS.(*zktrie.ZkTrie)
if zkTrie == nil {
panic("unexpected trie type for zktrie")
}
return ZktrieProofTracer{zkTrie.NewProofTracer()}
}
return ZktrieProofTracer{}
}
// GetStorageTrieForProof is not in Db interface and used explictily for reading proof in storage trie (not updated by the dirty value)
func (s *StateDB) GetStorageTrieForProof(addr common.Address) (Trie, error) {
// try the trie in stateObject first, else we would create one
stateObject := s.getStateObject(addr)
if stateObject == nil {
// still return a empty trie
addrHash := crypto.Keccak256Hash(addr[:])
dummy_trie, _ := s.db.OpenStorageTrie(addrHash, common.Hash{})
return dummy_trie, nil
}
trie := stateObject.trie
var err error
if trie == nil {
// use a new, temporary trie
trie, err = s.db.OpenStorageTrie(stateObject.addrHash, stateObject.data.Root)
if err != nil {
return nil, fmt.Errorf("can't create storage trie on root %s: %v ", stateObject.data.Root, err)
}
}
return trie, nil
}
// 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) {
var proof proofList
var err error
if s.IsZktrie() {
key_s, _ := zkt.ToSecureKeyBytes(key.Bytes())
err = trieProve.Prove(key_s.Bytes(), 0, &proof)
} else {
err = trieProve.Prove(crypto.Keccak256(key.Bytes()), 0, &proof)
}
return proof, err
}