Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Snap/merge range and proof #1913

Closed
wants to merge 39 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
5cd826f
updating verify proof range to handle empty proof keys
Jun 7, 2024
3ecb395
test non set proof key - wip
Jun 7, 2024
d2fe491
wip - proof to Path doesn't work
Jun 7, 2024
2cd3157
store the hashes of children in ProofToPath
Jun 8, 2024
3603e28
ProoftoPath update to handle unset proof key
Jun 8, 2024
d8f5811
test - wip
Jun 8, 2024
40a3d04
test - wip
Jun 9, 2024
fb6c899
test passes! :D
Jun 10, 2024
07e99f5
lint
Jun 10, 2024
c0b933a
tidy
Jun 10, 2024
529aef2
fixing tests that broke wip
Jun 10, 2024
ca360e9
build4keyTrie passes again!
Jun 11, 2024
fdf6af2
fixed more tests
Jun 11, 2024
9f9f2fe
fix test wip
Jun 11, 2024
bad7267
fix more tests
Jun 11, 2024
92a98df
fix test -wip
Jun 11, 2024
727801b
fix tests wip
Jun 11, 2024
b4ae2b6
wip
Jun 11, 2024
a123730
all tests passgit add .
Jun 12, 2024
d249186
lint
Jun 12, 2024
21f9453
tidy
Jun 12, 2024
2d7c6e8
tidy logic
Jun 12, 2024
46c7b8a
tidy logic
Jun 12, 2024
0bb2edc
tidy logic
Jun 12, 2024
ce20e08
comment: update getLeftRightHash
Jun 12, 2024
ec2f917
update ProofToPath comment
Jun 12, 2024
dd21cc0
bubble up getLeftRightHash err
Jun 12, 2024
571eb6e
Trie iterate
asdacap Jun 14, 2024
b614c2e
Address comment
asdacap Jun 14, 2024
89cf035
Merge branch 'feature/trie-iterate' into snap/merge-range-and-proof
asdacap Jun 19, 2024
20e2aa0
Snap support
asdacap Jun 20, 2024
faa0884
Finished is needed internally
asdacap Jun 20, 2024
59440ac
Missed a printf
asdacap Jun 20, 2024
35b46d0
Format
asdacap Jun 20, 2024
cb26dd7
Fix lint
asdacap Jun 20, 2024
1454ad5
Update core/trie/key.go
asdacap Jun 25, 2024
d4b4232
Update core/trie/snap_support.go
asdacap Jun 25, 2024
4f4940f
address keys
asdacap Jun 27, 2024
909914d
Fix lint
asdacap Jun 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Snap support
  • Loading branch information
asdacap committed Jun 20, 2024
commit 20e2aa07d4eb8ebe34ae5fea60d4f9b93e5eda05
38 changes: 36 additions & 2 deletions core/trie/key.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@
"bytes"
"encoding/hex"
"errors"
"fmt"

Check failure on line 7 in core/trie/key.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gofumpt`-ed (gofumpt)
"math/big"

"github.com/NethermindEth/juno/core/felt"

Check failure on line 8 in core/trie/key.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gci`-ed with --skip-generated -s standard -s default (gci)
"math/big"

Check failure on line 9 in core/trie/key.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gci`-ed with --skip-generated -s standard -s default (gci)
)

type Key struct {
Expand Down Expand Up @@ -176,3 +175,38 @@

return theint
}

func (k *Key) AppendBitMut(flag bool) {
const LSB = uint8(0x1)
bit := k.len
byteIdx := bit / 8
byteAtIdx := k.bitset[len(k.bitset)-int(byteIdx)-1]
bitIdx := bit % 8

// I'm sure someone will make this nicer
if flag {
byteAtIdx |= LSB << bitIdx
} else {
byteAtIdx &= ^(LSB << bitIdx)
}
asdacap marked this conversation as resolved.
Show resolved Hide resolved

k.len++
k.bitset[len(k.bitset)-int(byteIdx)-1] = byteAtIdx
}

func (k Key) Append(otherKey *Key) Key {
result := NewKey(otherKey.len, otherKey.bitset[:])

// I'm sure someone will make this faster
for i := uint8(0); i < k.len; i++ {
result.AppendBitMut(k.Test(i))
}

return result
}

func (k Key) AppendBit(flag bool) Key {
result := NewKey(0, []byte{})
result.AppendBitMut(flag)
return k.Append(&result)
}
53 changes: 53 additions & 0 deletions core/trie/key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,3 +218,56 @@ func Test_cmp(t *testing.T) {
func numToKey(num int) trie.Key {
return trie.NewKey(8, []byte{byte(num)})
}

func TestKeyAppend(t *testing.T) {
tests := map[string]struct {
Key1 trie.Key
Key2 trie.Key
ExpectedKey trie.Key
}{
"no append": {
Key1: trie.NewKey(1, []byte{0x01}),
Key2: trie.NewKey(0, []byte{0x00}),
ExpectedKey: trie.NewKey(1, []byte{0x01}),
},
"from zero append": {
Key1: trie.NewKey(0, []byte{0x00}),
Key2: trie.NewKey(1, []byte{0x01}),
ExpectedKey: trie.NewKey(1, []byte{0x01}),
},
"append shift": {
Key1: trie.NewKey(1, []byte{0x01}),
Key2: trie.NewKey(7, []byte{0x00}),
ExpectedKey: trie.NewKey(8, []byte{0x80}),
},
"append to a new byte": {
Key1: trie.NewKey(8, []byte{0xff}),
Key2: trie.NewKey(1, []byte{0x01}),
ExpectedKey: trie.NewKey(9, []byte{0x01, 0xff}),
},
"append multi byte": {
Key1: trie.NewKey(11, []byte{0x00, 0xff}), // 000 1111 1111
Key2: trie.NewKey(12, []byte{0x00, 0xff}), // 0000 1111 1111
ExpectedKey: trie.NewKey(23, []byte{0x0f, 0xf0, 0xff}), // 000 1111 1111 0000 1111 1111
},
}

for desc, test := range tests {
t.Run(desc, func(t *testing.T) {
appended := test.Key1.Append(&test.Key2)
assert.Equal(t, test.ExpectedKey, appended)
})
}
}

func TestKeyAppendBit(t *testing.T) {
k1 := trie.NewKey(1, []byte{0x01})
k2 := k1.AppendBit(true)
expected := trie.NewKey(2, []byte{0x03})
assert.Equal(t, k2, expected)

k1 = trie.NewKey(1, []byte{0x00})
k2 = k1.AppendBit(true)
expected = trie.NewKey(2, []byte{0x01})
assert.Equal(t, k2, expected)
}
172 changes: 172 additions & 0 deletions core/trie/snap_support.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
package trie

import (
"fmt"

Check failure on line 4 in core/trie/snap_support.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gci`-ed with --skip-generated -s standard -s default (gci)
"github.com/NethermindEth/juno/core/felt"
)

func (t *Trie) IterateAndGenerateProof(startValue *felt.Felt, consumer func(key, value *felt.Felt) (bool, error)) ([]ProofNode, error) {
var lastKey *felt.Felt

finished, err := t.Iterate(startValue, func(key, value *felt.Felt) (bool, error) {
lastKey = key

return consumer(key, value)
})
if err != nil {
return nil, err

Check warning on line 17 in core/trie/snap_support.go

View check run for this annotation

Codecov / codecov/patch

core/trie/snap_support.go#L17

Added line #L17 was not covered by tests
}

proofset := map[felt.Felt]ProofNode{}

// If start value is null && finished, you dont need to provide any proof at all
if !finished || startValue != nil {
feltBts := startValue.Bytes()
startKey := NewKey(t.height, feltBts[:])
// Yes, the left proof is actually for the start query, not the actual leaf. Very confusing, yea I know. Need to
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean that the left proof is for the start query, and not the actual leaf? I thought the left proof would be for the first key/leaf in the range?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually no. Its a very edge.. edge case. Can't remember at the top of my head why.

// actually check that the server did not skip leafs.
leftProof, err := GetProof(&startKey, t)
if err != nil {
return nil, err

Check warning on line 30 in core/trie/snap_support.go

View check run for this annotation

Codecov / codecov/patch

core/trie/snap_support.go#L30

Added line #L30 was not covered by tests
}
for _, proof := range leftProof {
// Well.. using the trie hash here is kinda slow... but I just need it to work right now.
proofset[*proof.Hash(t.hash)] = proof
}

}

Check failure on line 37 in core/trie/snap_support.go

View workflow job for this annotation

GitHub Actions / lint

unnecessary trailing newline (whitespace)

if !finished && lastKey != nil {
feltBts := lastKey.Bytes()
lastKey := NewKey(t.height, feltBts[:])
rightProof, err := GetProof(&lastKey, t)
if err != nil {
return nil, err

Check warning on line 44 in core/trie/snap_support.go

View check run for this annotation

Codecov / codecov/patch

core/trie/snap_support.go#L44

Added line #L44 was not covered by tests
}

for _, proof := range rightProof {
proofset[*proof.Hash(t.hash)] = proof
}
}

proofs := make([]ProofNode, 0, len(proofset))
for _, node := range proofset {
proofs = append(proofs, node)
}

return proofs, nil
}

func VerifyRange(root, startKey *felt.Felt, keys, values []*felt.Felt, proofs []ProofNode, hash hashFunc) (hasMore bool, valid bool, err error) {

Check failure on line 60 in core/trie/snap_support.go

View workflow job for this annotation

GitHub Actions / lint

paramTypeCombine: func(root, startKey *felt.Felt, keys, values []*felt.Felt, proofs []ProofNode, hash hashFunc) (hasMore bool, valid bool, err error) could be replaced with func(root, startKey *felt.Felt, keys, values []*felt.Felt, proofs []ProofNode, hash hashFunc) (hasMore, valid bool, err error) (gocritic)
proofMap := map[felt.Felt]ProofNode{}
for _, proof := range proofs {
proofHash := proof.Hash(hash)
proofMap[*proofHash] = proof
}

if len(proofMap) == 0 && startKey == nil {
// Special case where the whole trie is sent in one go.
// We just need to completely reconstruct the trie.

tempTrie, err := newTrie(newMemStorage(), 251, hash) //nolint:gomnd

Check failure on line 71 in core/trie/snap_support.go

View workflow job for this annotation

GitHub Actions / lint

shadow: declaration of "err" shadows declaration at line 60 (govet)
if err != nil {
return false, false, err

Check warning on line 73 in core/trie/snap_support.go

View check run for this annotation

Codecov / codecov/patch

core/trie/snap_support.go#L73

Added line #L73 was not covered by tests
}

for i, key := range keys {
_, err := tempTrie.Put(key, values[i])

Check failure on line 77 in core/trie/snap_support.go

View workflow job for this annotation

GitHub Actions / lint

shadow: declaration of "err" shadows declaration at line 71 (govet)
if err != nil {
return false, false, err

Check warning on line 79 in core/trie/snap_support.go

View check run for this annotation

Codecov / codecov/patch

core/trie/snap_support.go#L79

Added line #L79 was not covered by tests
}
}

recalculatedRoot, err := tempTrie.Root()
if err != nil {
return false, false, err

Check warning on line 85 in core/trie/snap_support.go

View check run for this annotation

Codecov / codecov/patch

core/trie/snap_support.go#L85

Added line #L85 was not covered by tests
}

if !root.Equal(recalculatedRoot) {
return false, false, nil
}
fmt.Printf("Its here %s %s\n", root, recalculatedRoot)

return false, true, nil
}

if _, ok := proofMap[*root]; !ok {
// Verification failure, root not included in proof.
return false, false, nil
}

proofKeys := map[felt.Felt]Key{}
err = buildKeys(NewKey(0, []byte{}), root, proofMap, proofKeys, 0)
if err != nil {
return false, false, err

Check warning on line 104 in core/trie/snap_support.go

View check run for this annotation

Codecov / codecov/patch

core/trie/snap_support.go#L104

Added line #L104 was not covered by tests
}

// No idea how this work
/*

Check failure on line 108 in core/trie/snap_support.go

View workflow job for this annotation

GitHub Actions / lint

commentedOutCode: may want to remove commented-out code (gocritic)
proofValuesArray := []*felt.Felt{}
proofKeysArray := []*Key{}
for f, key := range proofKeys {
proofValuesArray = append(proofValuesArray, &f)
proofKeysArray = append(proofKeysArray, &key)
}

VerifyRangeProof(root, keys, values, nil, nil, nil, hash)
*/

hasMoreKeyCheck := startKey
asdacap marked this conversation as resolved.
Show resolved Hide resolved
if len(keys) > 0 {
hasMoreKeyCheck = keys[len(keys)-1]
}

feltBytes := hasMoreKeyCheck.Bytes()
asdacap marked this conversation as resolved.
Show resolved Hide resolved
hasMoreKeyCheckKey := NewKey(251, feltBytes[:])

Check failure on line 125 in core/trie/snap_support.go

View workflow job for this annotation

GitHub Actions / lint

mnd: Magic number: 251, in <argument> detected (gomnd)

// does this actually work on all case?
hasMore = false
for _, key := range proofKeys {
comparison := key.CmpAligned(&hasMoreKeyCheckKey)
if comparison > 0 {
hasMore = true
}
}

return hasMore, true, nil
}

func buildKeys(currentKey Key, currentNode *felt.Felt, proofMap map[felt.Felt]ProofNode, keys map[felt.Felt]Key, depth int) error {
asdacap marked this conversation as resolved.
Show resolved Hide resolved
keys[*currentNode] = currentKey
proofNode, ok := proofMap[*currentNode]
if !ok {
return nil
}

if proofNode.Edge != nil {
chKey := currentKey.Append(proofNode.Edge.Path)
ch := proofNode.Edge.Child
err := buildKeys(chKey, ch, proofMap, keys, depth+1)
if err != nil {
return err

Check warning on line 151 in core/trie/snap_support.go

View check run for this annotation

Codecov / codecov/patch

core/trie/snap_support.go#L151

Added line #L151 was not covered by tests
}
} else {
binary := proofNode.Binary

chKey := currentKey.AppendBit(false)
ch := binary.LeftHash
err := buildKeys(chKey, ch, proofMap, keys, depth+1)
if err != nil {
return err

Check warning on line 160 in core/trie/snap_support.go

View check run for this annotation

Codecov / codecov/patch

core/trie/snap_support.go#L160

Added line #L160 was not covered by tests
}

chKey = currentKey.AppendBit(true)
ch = binary.RightHash
err = buildKeys(chKey, ch, proofMap, keys, depth+1)
if err != nil {
return err

Check warning on line 167 in core/trie/snap_support.go

View check run for this annotation

Codecov / codecov/patch

core/trie/snap_support.go#L167

Added line #L167 was not covered by tests
}
}

return nil
}
Loading
Loading