Skip to content

Commit 1e50ea2

Browse files
author
Paweł Nowosielski
committed
getProof rpc method
1 parent 1786cb3 commit 1e50ea2

File tree

13 files changed

+816
-119
lines changed

13 files changed

+816
-119
lines changed

blockchain/pending.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package blockchain
22

33
import (
4+
"errors"
5+
46
"github.com/NethermindEth/juno/core"
57
"github.com/NethermindEth/juno/core/felt"
8+
"github.com/NethermindEth/juno/core/trie"
69
)
710

811
type Pending struct {
@@ -65,3 +68,25 @@ func (p *PendingState) Class(classHash *felt.Felt) (*core.DeclaredClass, error)
6568

6669
return p.head.Class(classHash)
6770
}
71+
72+
// Note[pnowosie]: Maybe extending StateReader with the following methods was not a good idea?
73+
func (p *PendingState) ClassTrie() (*trie.Trie, func() error, error) {
74+
return nil, nopCloser, errFeatureNotImplemented
75+
}
76+
77+
func (p *PendingState) StorageTrie() (*trie.Trie, func() error, error) {
78+
return nil, nopCloser, errFeatureNotImplemented
79+
}
80+
81+
func (p *PendingState) StorageTrieForAddr(*felt.Felt) (*trie.Trie, error) {
82+
return nil, errFeatureNotImplemented
83+
}
84+
85+
func (p *PendingState) StateAndClassRoot() (*felt.Felt, *felt.Felt, error) {
86+
return nil, nil, errFeatureNotImplemented
87+
}
88+
89+
var (
90+
errFeatureNotImplemented = errors.New("feature not implemented for a historical state")
91+
nopCloser = func() error { return nil }
92+
)

core/state.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ type StateReader interface {
4242
ContractNonce(addr *felt.Felt) (*felt.Felt, error)
4343
ContractStorage(addr, key *felt.Felt) (*felt.Felt, error)
4444
Class(classHash *felt.Felt) (*DeclaredClass, error)
45+
46+
// NOTE: Not a best way to add them here - it assumes current state and atm cannot be implemented for hitsrical states
47+
ClassTrie() (*trie.Trie, func() error, error)
48+
StorageTrie() (*trie.Trie, func() error, error)
49+
StorageTrieForAddr(addr *felt.Felt) (*trie.Trie, error)
50+
StateAndClassRoot() (*felt.Felt, *felt.Felt, error)
4551
}
4652

4753
type State struct {
@@ -129,6 +135,18 @@ func (s *State) storage() (*trie.Trie, func() error, error) {
129135
return s.globalTrie(db.StateTrie, trie.NewTriePedersen)
130136
}
131137

138+
func (s *State) StorageTrie() (*trie.Trie, func() error, error) {
139+
return s.storage()
140+
}
141+
142+
func (s *State) ClassTrie() (*trie.Trie, func() error, error) {
143+
return s.classesTrie()
144+
}
145+
146+
func (s *State) StorageTrieForAddr(addr *felt.Felt) (*trie.Trie, error) {
147+
return storage(addr, s.txn)
148+
}
149+
132150
func (s *State) classesTrie() (*trie.Trie, func() error, error) {
133151
return s.globalTrie(db.ClassesTrie, trie.NewTriePoseidon)
134152
}
@@ -721,3 +739,35 @@ func (s *State) buildReverseDiff(blockNumber uint64, diff *StateDiff) (*StateDif
721739

722740
return &reversed, nil
723741
}
742+
743+
func (s *State) StateAndClassRoot() (*felt.Felt, *felt.Felt, error) {
744+
var storageRoot, classesRoot *felt.Felt
745+
746+
sStorage, closer, err := s.storage()
747+
if err != nil {
748+
return nil, nil, err
749+
}
750+
751+
if storageRoot, err = sStorage.Root(); err != nil {
752+
return nil, nil, err
753+
}
754+
755+
if err = closer(); err != nil {
756+
return nil, nil, err
757+
}
758+
759+
classes, closer, err := s.classesTrie()
760+
if err != nil {
761+
return nil, nil, err
762+
}
763+
764+
if classesRoot, err = classes.Root(); err != nil {
765+
return nil, nil, err
766+
}
767+
768+
if err = closer(); err != nil {
769+
return nil, nil, err
770+
}
771+
772+
return storageRoot, classesRoot, nil
773+
}

core/state_snapshot.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"errors"
55

66
"github.com/NethermindEth/juno/core/felt"
7+
"github.com/NethermindEth/juno/core/trie"
78
"github.com/NethermindEth/juno/db"
89
)
910

@@ -87,3 +88,25 @@ func (s *stateSnapshot) Class(classHash *felt.Felt) (*DeclaredClass, error) {
8788
}
8889
return declaredClass, nil
8990
}
91+
92+
// Note[pnowosie]: Maybe extending StateReader with the following methods was not a good idea?
93+
func (s *stateSnapshot) ClassTrie() (*trie.Trie, func() error, error) {
94+
return nil, nopCloser, errFeatureNotImplemented
95+
}
96+
97+
func (s *stateSnapshot) StorageTrie() (*trie.Trie, func() error, error) {
98+
return nil, nopCloser, errFeatureNotImplemented
99+
}
100+
101+
func (s *stateSnapshot) StorageTrieForAddr(*felt.Felt) (*trie.Trie, error) {
102+
return nil, errFeatureNotImplemented
103+
}
104+
105+
func (s *stateSnapshot) StateAndClassRoot() (*felt.Felt, *felt.Felt, error) {
106+
return nil, nil, errFeatureNotImplemented
107+
}
108+
109+
var (
110+
errFeatureNotImplemented = errors.New("feature not implemented for a historical state")
111+
nopCloser = func() error { return nil }
112+
)

core/trie/key.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ func (k *Key) SubKey(n uint8) (*Key, error) {
2828
if n > k.len {
2929
return nil, errors.New(fmt.Sprint("cannot subtract key of length %i from key of length %i", n, k.len))
3030
}
31+
if n == k.len {
32+
return &Key{}, nil
33+
}
3134

3235
newKey := &Key{len: n}
3336
copy(newKey.bitset[:], k.bitset[len(k.bitset)-int((k.len+7)/8):]) //nolint:mnd

core/trie/node.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type Node struct {
1818
}
1919

2020
// Hash calculates the hash of a [Node]
21-
func (n *Node) Hash(path *Key, hashFunc hashFunc) *felt.Felt {
21+
func (n *Node) Hash(path *Key, hashFunc HashFunc) *felt.Felt {
2222
if path.Len() == 0 {
2323
// we have to deference the Value, since the Node can released back
2424
// to the NodePool and be reused anytime
@@ -33,7 +33,7 @@ func (n *Node) Hash(path *Key, hashFunc hashFunc) *felt.Felt {
3333
}
3434

3535
// Hash calculates the hash of a [Node]
36-
func (n *Node) HashFromParent(parnetKey, nodeKey *Key, hashFunc hashFunc) *felt.Felt {
36+
func (n *Node) HashFromParent(parnetKey, nodeKey *Key, hashFunc HashFunc) *felt.Felt {
3737
path := path(nodeKey, parnetKey)
3838
return n.Hash(&path, hashFunc)
3939
}

core/trie/proof.go

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ var (
1313
)
1414

1515
type ProofNode interface {
16-
Hash(hash hashFunc) *felt.Felt
16+
Hash(hash HashFunc) *felt.Felt
1717
Len() uint8
1818
PrettyPrint()
1919
}
@@ -23,7 +23,7 @@ type Binary struct {
2323
RightHash *felt.Felt
2424
}
2525

26-
func (b *Binary) Hash(hash hashFunc) *felt.Felt {
26+
func (b *Binary) Hash(hash HashFunc) *felt.Felt {
2727
return hash(b.LeftHash, b.RightHash)
2828
}
2929

@@ -42,7 +42,7 @@ type Edge struct {
4242
Path *Key // path from parent to child
4343
}
4444

45-
func (e *Edge) Hash(hash hashFunc) *felt.Felt {
45+
func (e *Edge) Hash(hash HashFunc) *felt.Felt {
4646
length := make([]byte, len(e.Path.bitset))
4747
length[len(e.Path.bitset)-1] = e.Path.len
4848
pathFelt := e.Path.Felt()
@@ -54,6 +54,11 @@ func (e *Edge) Len() uint8 {
5454
return e.Path.Len()
5555
}
5656

57+
func (e *Edge) PathInt() uint64 {
58+
f := e.Path.Felt()
59+
return f.Uint64()
60+
}
61+
5762
func (e *Edge) PrettyPrint() {
5863
fmt.Printf(" Edge:\n")
5964
fmt.Printf(" Child: %v\n", e.Child)
@@ -199,7 +204,7 @@ func traverseNodes(currNode ProofNode, path *[]ProofNode, nodeHashes map[felt.Fe
199204
// merges paths in the specified order [commonNodes..., leftNodes..., rightNodes...]
200205
// ordering of the merged path is not important
201206
// since SplitProofPath can discover the left and right paths using the merged path and the rootHash
202-
func MergeProofPaths(leftPath, rightPath []ProofNode, hash hashFunc) ([]ProofNode, *felt.Felt, error) {
207+
func MergeProofPaths(leftPath, rightPath []ProofNode, hash HashFunc) ([]ProofNode, *felt.Felt, error) {
203208
merged := []ProofNode{}
204209
minLen := min(len(leftPath), len(rightPath))
205210

@@ -236,7 +241,7 @@ func MergeProofPaths(leftPath, rightPath []ProofNode, hash hashFunc) ([]ProofNod
236241
// SplitProofPath splits the merged proof path into two paths (left and right), which were merged before
237242
// it first validates that the merged path is not circular, the split happens at most once and rootHash exists
238243
// then calls traverseNodes to split the path to left and right paths
239-
func SplitProofPath(mergedPath []ProofNode, rootHash *felt.Felt, hash hashFunc) ([]ProofNode, []ProofNode, error) {
244+
func SplitProofPath(mergedPath []ProofNode, rootHash *felt.Felt, hash HashFunc) ([]ProofNode, []ProofNode, error) {
240245
commonPath := []ProofNode{}
241246
leftPath := []ProofNode{}
242247
rightPath := []ProofNode{}
@@ -316,7 +321,7 @@ func GetProof(key *Key, tri *Trie) ([]ProofNode, error) {
316321

317322
// verifyProof checks if `leafPath` leads from `root` to `leafHash` along the `proofNodes`
318323
// https://github.com/eqlabs/pathfinder/blob/main/crates/merkle-tree/src/tree.rs#L2006
319-
func VerifyProof(root *felt.Felt, key *Key, value *felt.Felt, proofs []ProofNode, hash hashFunc) bool {
324+
func VerifyProof(root *felt.Felt, key *Key, value *felt.Felt, proofs []ProofNode, hash HashFunc) bool {
320325
expectedHash := root
321326
remainingPath := NewKey(key.len, key.bitset[:])
322327
for i, proofNode := range proofs {
@@ -345,7 +350,7 @@ func VerifyProof(root *felt.Felt, key *Key, value *felt.Felt, proofs []ProofNode
345350
return true
346351
}
347352

348-
if !proofNode.Path.Equal(subKey) {
353+
if !proofNode.Path.Equal(subKey) && !subKey.Equal(&Key{}) {
349354
return false
350355
}
351356
expectedHash = proofNode.Child
@@ -363,7 +368,7 @@ func VerifyProof(root *felt.Felt, key *Key, value *felt.Felt, proofs []ProofNode
363368
// and therefore it's hash won't match the expected root.
364369
// ref: https://github.com/ethereum/go-ethereum/blob/v1.14.3/trie/proof.go#L484
365370
func VerifyRangeProof(root *felt.Felt, keys, values []*felt.Felt, proofKeys [2]*Key, proofValues [2]*felt.Felt,
366-
proofs [2][]ProofNode, hash hashFunc,
371+
proofs [2][]ProofNode, hash HashFunc,
367372
) (bool, error) {
368373
// Step 0: checks
369374
if len(keys) != len(values) {
@@ -440,7 +445,7 @@ func ensureMonotonicIncreasing(proofKeys [2]*Key, keys []*felt.Felt) error {
440445
}
441446

442447
// compressNode determines if the node needs compressed, and if so, the len needed to arrive at the next key
443-
func compressNode(idx int, proofNodes []ProofNode, hashF hashFunc) (int, uint8, error) {
448+
func compressNode(idx int, proofNodes []ProofNode, hashF HashFunc) (int, uint8, error) {
444449
parent := proofNodes[idx]
445450

446451
if idx == len(proofNodes)-1 {
@@ -474,7 +479,7 @@ func compressNode(idx int, proofNodes []ProofNode, hashF hashFunc) (int, uint8,
474479
}
475480

476481
func assignChild(i, compressedParent int, parentNode *Node,
477-
nilKey, leafKey, parentKey *Key, proofNodes []ProofNode, hashF hashFunc,
482+
nilKey, leafKey, parentKey *Key, proofNodes []ProofNode, hashF HashFunc,
478483
) (*Key, error) {
479484
childInd := i + compressedParent + 1
480485
childKey, err := getChildKey(childInd, parentKey, leafKey, nilKey, proofNodes, hashF)
@@ -494,7 +499,7 @@ func assignChild(i, compressedParent int, parentNode *Node,
494499
// ProofToPath returns a set of storage nodes from the root to the end of the proof path.
495500
// The storage nodes will have the hashes of the children, but only the key of the child
496501
// along the path outlined by the proof.
497-
func ProofToPath(proofNodes []ProofNode, leafKey *Key, hashF hashFunc) ([]StorageNode, error) {
502+
func ProofToPath(proofNodes []ProofNode, leafKey *Key, hashF HashFunc) ([]StorageNode, error) {
498503
pathNodes := []StorageNode{}
499504

500505
// Child keys that can't be derived are set to nilKey, so that we can store the node
@@ -552,7 +557,7 @@ func ProofToPath(proofNodes []ProofNode, leafKey *Key, hashF hashFunc) ([]Storag
552557
return pathNodes, nil
553558
}
554559

555-
func skipNode(pNode ProofNode, pathNodes []StorageNode, hashF hashFunc) bool {
560+
func skipNode(pNode ProofNode, pathNodes []StorageNode, hashF HashFunc) bool {
556561
lastNode := pathNodes[len(pathNodes)-1].node
557562
noLeftMatch, noRightMatch := false, false
558563
if lastNode.LeftHash != nil && !pNode.Hash(hashF).Equal(lastNode.LeftHash) {
@@ -607,7 +612,7 @@ func getParentKey(idx int, compressedParentOffset uint8, leafKey *Key,
607612
return crntKey, err
608613
}
609614

610-
func getChildKey(childIdx int, crntKey, leafKey, nilKey *Key, proofNodes []ProofNode, hashF hashFunc) (*Key, error) {
615+
func getChildKey(childIdx int, crntKey, leafKey, nilKey *Key, proofNodes []ProofNode, hashF HashFunc) (*Key, error) {
611616
if childIdx > len(proofNodes)-1 {
612617
return nilKey, nil
613618
}

core/trie/trie.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
"github.com/NethermindEth/juno/db"
1414
)
1515

16-
type hashFunc func(*felt.Felt, *felt.Felt) *felt.Felt
16+
type HashFunc func(*felt.Felt, *felt.Felt) *felt.Felt
1717

1818
// Trie is a dense Merkle Patricia Trie (i.e., all internal nodes have two children).
1919
//
@@ -37,7 +37,7 @@ type Trie struct {
3737
rootKey *Key
3838
maxKey *felt.Felt
3939
storage *Storage
40-
hash hashFunc
40+
hash HashFunc
4141

4242
dirtyNodes []*Key
4343
rootKeyIsDirty bool
@@ -53,7 +53,7 @@ func NewTriePoseidon(storage *Storage, height uint8) (*Trie, error) {
5353
return newTrie(storage, height, crypto.Poseidon)
5454
}
5555

56-
func newTrie(storage *Storage, height uint8, hash hashFunc) (*Trie, error) {
56+
func newTrie(storage *Storage, height uint8, hash HashFunc) (*Trie, error) {
5757
if height > felt.Bits {
5858
return nil, fmt.Errorf("max trie height is %d, got: %d", felt.Bits, height)
5959
}
@@ -668,6 +668,10 @@ func (t *Trie) RootKey() *Key {
668668
return t.rootKey
669669
}
670670

671+
func (t *Trie) HashFunc() HashFunc {
672+
return t.hash
673+
}
674+
671675
func (t *Trie) Dump() {
672676
t.dump(0, nil)
673677
}

0 commit comments

Comments
 (0)