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

MerkleDB Compact Path Bytes #2010

Merged
merged 136 commits into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
136 commits
Select commit Hold shift + click to select a range
ddc21f9
Move Path
dboehm-avalabs Sep 6, 2023
79684fa
lint
dboehm-avalabs Sep 6, 2023
5c23f2a
Revert "lint"
dboehm-avalabs Sep 6, 2023
4c519e5
lint
dboehm-avalabs Sep 6, 2023
6ddb5f3
Update node.go
dboehm-avalabs Sep 6, 2023
d32e984
Update node.go
dboehm-avalabs Sep 6, 2023
8e0f70a
Update mock_db.go
dboehm-avalabs Sep 6, 2023
9b8a7ac
rename
dboehm-avalabs Sep 6, 2023
d29f29d
Revert "rename"
dboehm-avalabs Sep 6, 2023
7405fd1
Update manager.go
dboehm-avalabs Sep 6, 2023
0eebdc6
serialized
dboehm-avalabs Sep 6, 2023
1be212f
Update token_path_test.go
dboehm-avalabs Sep 6, 2023
4708708
fix tokenization
dboehm-avalabs Sep 7, 2023
3c8bd81
Update x/merkledb/paths/token_path.go
dboehm-avalabs Sep 7, 2023
f8e0956
rename
dboehm-avalabs Sep 7, 2023
fced4b6
Merge branch 'TokenPath' of https://github.com/ava-labs/avalanchego i…
dboehm-avalabs Sep 7, 2023
9916612
Merge branch 'dev' into TokenPath
dboehm-avalabs Sep 7, 2023
5c4689b
rename
dboehm-avalabs Sep 7, 2023
2d60599
Update mock_router.go
dboehm-avalabs Sep 7, 2023
e8d4fa5
Update path_test.go
dboehm-avalabs Sep 7, 2023
a9acaf5
Update path.go
dboehm-avalabs Sep 9, 2023
c960b0b
Update path.go
dboehm-avalabs Sep 9, 2023
3c3cedf
Update path.go
dboehm-avalabs Sep 9, 2023
bccec80
Update path.go
dboehm-avalabs Sep 9, 2023
ef251a1
Update path.go
dboehm-avalabs Sep 9, 2023
0ba819c
Update path.go
dboehm-avalabs Sep 9, 2023
faace90
Update path.go
dboehm-avalabs Sep 9, 2023
7948bc1
Update path.go
dboehm-avalabs Sep 10, 2023
5978604
Merge branch 'dev' into TokenPath
dboehm-avalabs Sep 11, 2023
65d2432
Update path.go
dboehm-avalabs Sep 11, 2023
29bf5e2
Merge branch 'TokenPath' of https://github.com/ava-labs/avalanchego i…
dboehm-avalabs Sep 11, 2023
95d5fd7
stash
dboehm-avalabs Sep 11, 2023
5e51a87
stash
dboehm-avalabs Sep 11, 2023
7fdb096
stash
dboehm-avalabs Sep 11, 2023
d17098b
stash
dboehm-avalabs Sep 11, 2023
8813e7a
prevent recalculation of compressed key
dboehm-avalabs Sep 11, 2023
92f6376
Merge branch 'dev' into CompactPath
dboehm-avalabs Sep 13, 2023
770d812
fix merge
dboehm-avalabs Sep 13, 2023
17b679a
fix sync package
dboehm-avalabs Sep 13, 2023
777259a
fix sync package
dboehm-avalabs Sep 13, 2023
8951341
stop using strings.Compare
dboehm-avalabs Sep 15, 2023
de1c398
Add tests, cleanup, comments
dboehm-avalabs Sep 15, 2023
ec5026a
Update path_test.go
dboehm-avalabs Sep 15, 2023
5f12218
Pass Branch Factor around
dboehm-avalabs Sep 15, 2023
d63bd46
Merge branch 'dev' into CompactPath
dboehm-avalabs Sep 15, 2023
563b6a7
Update sync.pb.go
dboehm-avalabs Sep 15, 2023
96f5483
Merge branch 'dev' into CompactPath
dboehm-avalabs Sep 15, 2023
99ac33e
cleanup and branch factor passing
dboehm-avalabs Sep 18, 2023
8eb3a5d
fix codec
dboehm-avalabs Sep 18, 2023
9b220a6
update references to odd lengths
dboehm-avalabs Sep 18, 2023
14f7636
CLEANUP
dboehm-avalabs Sep 18, 2023
4554b94
force branch factor initialization
dboehm-avalabs Sep 18, 2023
e987d54
Update db_server.go
dboehm-avalabs Sep 18, 2023
fe9646b
Merge branch 'dev' into CompactPath
dboehm-avalabs Sep 18, 2023
7a41ae6
Update manager.go
dboehm-avalabs Sep 18, 2023
ce85829
Update trieview.go
dboehm-avalabs Sep 18, 2023
cfe49e5
Avoid constructing the existing child key
dboehm-avalabs Sep 18, 2023
2c44051
Update trieview.go
dboehm-avalabs Sep 18, 2023
83c970f
rewrite
dboehm-avalabs Sep 19, 2023
c129845
Update manager.go
dboehm-avalabs Sep 19, 2023
0e5e506
Undo Length changes
dboehm-avalabs Sep 19, 2023
2135851
comments
dboehm-avalabs Sep 19, 2023
d52f136
Update path_test.go
dboehm-avalabs Sep 19, 2023
8a59a66
Merge branch 'dev' into CompactPath
dboehm-avalabs Sep 19, 2023
58795c9
rename
dboehm-avalabs Sep 19, 2023
76491c2
Update path.go
dboehm-avalabs Sep 19, 2023
ce187e5
Update proof.go
dboehm-avalabs Sep 19, 2023
7f824f8
Update manager.go
dboehm-avalabs Sep 19, 2023
61e904f
Update manager.go
dboehm-avalabs Sep 19, 2023
54646a3
Update view_iterator.go
dboehm-avalabs Sep 19, 2023
6acd618
Merge branch 'dev' into CompactPath
dboehm-avalabs Sep 19, 2023
8a1d7f4
Update codec.go
dboehm-avalabs Sep 20, 2023
f000c17
cleanup
dboehm-avalabs Sep 21, 2023
b7cbe54
Update path.go
dboehm-avalabs Sep 21, 2023
8e5f43a
Update path_test.go
dboehm-avalabs Sep 21, 2023
e83a903
Update path.go
dboehm-avalabs Sep 21, 2023
f2c19d0
Update path.go
dboehm-avalabs Sep 21, 2023
2aff904
comments
dboehm-avalabs Sep 21, 2023
2dbe0ce
comments
dboehm-avalabs Sep 22, 2023
e75ec3a
Update intermediate_node_db_test.go
dboehm-avalabs Sep 22, 2023
c7d624d
Update path_test.go
dboehm-avalabs Sep 22, 2023
07b116f
Update path.go
dboehm-avalabs Sep 22, 2023
0a6abb1
switch
dboehm-avalabs Sep 22, 2023
de831e4
unexport rootkey
dboehm-avalabs Sep 22, 2023
debb633
delete equals
dboehm-avalabs Sep 22, 2023
31f8c37
Update sync_test.go
dboehm-avalabs Sep 22, 2023
2363f1d
MerkleDB Compact Path Bytes Nits (#2075)
Sep 25, 2023
4856b92
add test helper
Sep 26, 2023
28e17c0
nit
Sep 26, 2023
c432ecd
nits
Sep 26, 2023
2639be2
nits
Sep 26, 2023
cea8393
add random branch factor to fuzz tests
Sep 26, 2023
bbe6183
nits
Sep 26, 2023
556d458
nit
Sep 26, 2023
54cad61
nit
Sep 26, 2023
cd8a174
embed pathConfig instead of *pathConfig in Path
Sep 26, 2023
7994d8d
nits
Sep 26, 2023
c948ca2
remove old comment
Sep 26, 2023
eed9bfc
nit
Sep 26, 2023
a537d7a
remove unused exported consts
Sep 26, 2023
341ff39
nit
Sep 26, 2023
b164003
unexport emptyPath
Sep 26, 2023
9d54658
fix tests
dboehm-avalabs Sep 26, 2023
3f927ae
lint
dboehm-avalabs Sep 26, 2023
bd3eb5f
improve tests
dboehm-avalabs Sep 27, 2023
a649fb3
Merge branch 'dev' into CompactPath
dboehm-avalabs Sep 27, 2023
089eeae
Update path.go
dboehm-avalabs Sep 27, 2023
9ff18b1
naming nits
Sep 27, 2023
029b2d6
update Token tests
Sep 27, 2023
757e326
update HasPrefix test
Sep 27, 2023
7c9bce2
remove case in HasPrefix for invalid paths
Sep 27, 2023
9247458
HasPrefix cleanup
Sep 27, 2023
375e99f
Cleanup
dboehm-avalabs Sep 28, 2023
555fc44
Merge branch 'dev' into CompactPath
dboehm-avalabs Sep 28, 2023
c6b1667
add TestPathBytesNeeded
Sep 28, 2023
0c2a6f6
nits
Sep 28, 2023
0972a0f
simplify bytesNeeded
Sep 28, 2023
e35d4ad
appease linter
Sep 28, 2023
6a191da
refactor bitsToShift
Sep 28, 2023
27bdccf
Merge branch 'dev' into CompactPath
Sep 29, 2023
9012fa9
add comment on bitsToShift
Sep 29, 2023
10acfbe
Merge branch 'CompactPath' of github.com:ava-labs/avalanchego into Co…
Sep 29, 2023
a668097
add test
Sep 29, 2023
3e8bf7a
comments
Sep 29, 2023
41ce7d7
cleanup intermediate node key generation
dboehm-avalabs Sep 29, 2023
6953599
comments
Sep 29, 2023
aab1239
Merge branch 'CompactPath' of github.com:ava-labs/avalanchego into Co…
Sep 29, 2023
7bbc862
Merge branch 'dev' into CompactPath
dboehm-avalabs Sep 29, 2023
66a953c
Update path.go
dboehm-avalabs Sep 29, 2023
f2b558b
Update path.go
dboehm-avalabs Sep 29, 2023
ae2cf66
Update path.go
dboehm-avalabs Sep 29, 2023
e687020
Update path.go
dboehm-avalabs Sep 29, 2023
fd2dadd
Update path.go
dboehm-avalabs Sep 29, 2023
1c80e11
fix byte consumption of keys
dboehm-avalabs Sep 29, 2023
923fe61
Merge branch 'CompactPath' of github.com:ava-labs/avalanchego into Co…
Sep 29, 2023
c0292a9
comments
Sep 29, 2023
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
170 changes: 84 additions & 86 deletions proto/pb/sync/sync.pb.go

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions proto/sync/sync.proto
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ message RangeProof {
}

message ProofNode {
SerializedPath key = 1;
Path key = 1;
MaybeBytes value_or_hash = 2;
map<uint32, bytes> children = 3;
}
Expand All @@ -149,8 +149,8 @@ message KeyChange {
MaybeBytes value = 2;
}

message SerializedPath {
uint64 nibble_length = 1;
message Path {
uint64 length = 1;
bytes value = 2;
}

Expand Down
102 changes: 49 additions & 53 deletions x/merkledb/codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"io"
"math"
"sync"
Expand All @@ -22,10 +21,10 @@ const (
falseByte = 0
minVarIntLen = 1
minMaybeByteSliceLen = boolLen
minSerializedPathLen = minVarIntLen
minPathLen = minVarIntLen
minByteSliceLen = minVarIntLen
minDBNodeLen = minMaybeByteSliceLen + minVarIntLen
minChildLen = minVarIntLen + minSerializedPathLen + ids.IDLen + boolLen
minChildLen = minVarIntLen + minPathLen + ids.IDLen + boolLen

estimatedKeyLen = 64
estimatedValueLen = 64
Expand All @@ -42,13 +41,13 @@ var (
trueBytes = []byte{trueByte}
falseBytes = []byte{falseByte}

errTooManyChildren = fmt.Errorf("length of children list is larger than branching factor of %d", NodeBranchFactor)
errChildIndexTooLarge = fmt.Errorf("invalid child index. Must be less than branching factor of %d", NodeBranchFactor)
errLeadingZeroes = errors.New("varint has leading zeroes")
errInvalidBool = errors.New("decoded bool is neither true nor false")
errNonZeroNibblePadding = errors.New("nibbles should be padded with 0s")
errExtraSpace = errors.New("trailing buffer space")
errIntOverflow = errors.New("value overflows int")
errTooManyChildren = errors.New("length of children list is larger than branching factor")
errChildIndexTooLarge = errors.New("invalid child index. Must be less than branching factor")
errLeadingZeroes = errors.New("varint has leading zeroes")
errInvalidBool = errors.New("decoded bool is neither true nor false")
errNonZeroPathPadding = errors.New("path partial byte should be padded with 0s")
errExtraSpace = errors.New("trailing buffer space")
errIntOverflow = errors.New("value overflows int")
)

// encoderDecoder defines the interface needed by merkleDB to marshal
Expand All @@ -60,14 +59,14 @@ type encoderDecoder interface {

type encoder interface {
// Assumes [n] is non-nil.
encodeDBNode(n *dbNode) []byte
encodeDBNode(n *dbNode, factor BranchFactor) []byte
// Assumes [hv] is non-nil.
encodeHashValues(hv *hashValues) []byte
}

type decoder interface {
// Assumes [n] is non-nil.
decodeDBNode(bytes []byte, n *dbNode) error
decodeDBNode(bytes []byte, n *dbNode, factor BranchFactor) error
}

func newCodec() encoderDecoder {
Expand All @@ -88,7 +87,7 @@ type codecImpl struct {
varIntPool sync.Pool
}

func (c *codecImpl) encodeDBNode(n *dbNode) []byte {
func (c *codecImpl) encodeDBNode(n *dbNode, branchFactor BranchFactor) []byte {
var (
numChildren = len(n.children)
// Estimate size of [n] to prevent memory allocations
Expand All @@ -100,11 +99,10 @@ func (c *codecImpl) encodeDBNode(n *dbNode) []byte {
c.encodeUint(buf, uint64(numChildren))
// Note we insert children in order of increasing index
// for determinism.
for index := byte(0); index < NodeBranchFactor; index++ {
if entry, ok := n.children[index]; ok {
for index := 0; BranchFactor(index) < branchFactor; index++ {
if entry, ok := n.children[byte(index)]; ok {
c.encodeUint(buf, uint64(index))
path := entry.compressedPath.Serialize()
c.encodeSerializedPath(buf, path)
c.encodePath(buf, entry.compressedPath)
_, _ = buf.Write(entry.id[:])
c.encodeBool(buf, entry.hasValue)
}
Expand All @@ -123,19 +121,19 @@ func (c *codecImpl) encodeHashValues(hv *hashValues) []byte {
c.encodeUint(buf, uint64(numChildren))

// ensure that the order of entries is consistent
for index := byte(0); index < NodeBranchFactor; index++ {
if entry, ok := hv.Children[index]; ok {
for index := 0; BranchFactor(index) < hv.Key.branchFactor; index++ {
if entry, ok := hv.Children[byte(index)]; ok {
c.encodeUint(buf, uint64(index))
_, _ = buf.Write(entry.id[:])
}
}
c.encodeMaybeByteSlice(buf, hv.Value)
c.encodeSerializedPath(buf, hv.Key)
c.encodePath(buf, hv.Key)

return buf.Bytes()
}

func (c *codecImpl) decodeDBNode(b []byte, n *dbNode) error {
func (c *codecImpl) decodeDBNode(b []byte, n *dbNode, branchFactor BranchFactor) error {
if minDBNodeLen > len(b) {
return io.ErrUnexpectedEOF
}
Expand All @@ -152,25 +150,25 @@ func (c *codecImpl) decodeDBNode(b []byte, n *dbNode) error {
switch {
case err != nil:
return err
case numChildren > NodeBranchFactor:
case numChildren > uint64(branchFactor):
return errTooManyChildren
case numChildren > uint64(src.Len()/minChildLen):
return io.ErrUnexpectedEOF
}

n.children = make(map[byte]child, NodeBranchFactor)
n.children = make(map[byte]child, branchFactor)
var previousChild uint64
for i := uint64(0); i < numChildren; i++ {
index, err := c.decodeUint(src)
if err != nil {
return err
}
if index >= NodeBranchFactor || (i != 0 && index <= previousChild) {
if index >= uint64(branchFactor) || (i != 0 && index <= previousChild) {
return errChildIndexTooLarge
}
previousChild = index

compressedPath, err := c.decodeSerializedPath(src)
compressedPath, err := c.decodePath(src, branchFactor)
if err != nil {
return err
}
Expand All @@ -183,7 +181,7 @@ func (c *codecImpl) decodeDBNode(b []byte, n *dbNode) error {
return err
}
n.children[byte(index)] = child{
compressedPath: compressedPath.deserialize(),
compressedPath: compressedPath,
id: childID,
hasValue: hasValue,
}
Expand Down Expand Up @@ -328,47 +326,45 @@ func (*codecImpl) decodeID(src *bytes.Reader) (ids.ID, error) {
return id, err
}

func (c *codecImpl) encodeSerializedPath(dst *bytes.Buffer, s SerializedPath) {
c.encodeUint(dst, uint64(s.NibbleLength))
_, _ = dst.Write(s.Value)
func (c *codecImpl) encodePath(dst *bytes.Buffer, p Path) {
c.encodeUint(dst, uint64(p.tokensLength))
_, _ = dst.Write(p.Bytes())
}

func (c *codecImpl) decodeSerializedPath(src *bytes.Reader) (SerializedPath, error) {
if minSerializedPathLen > src.Len() {
return SerializedPath{}, io.ErrUnexpectedEOF
func (c *codecImpl) decodePath(src *bytes.Reader, branchFactor BranchFactor) (Path, error) {
if minPathLen > src.Len() {
return Path{}, io.ErrUnexpectedEOF
}

nibbleLength, err := c.decodeUint(src)
length, err := c.decodeUint(src)
if err != nil {
return SerializedPath{}, err
}
if nibbleLength > math.MaxInt {
return SerializedPath{}, errIntOverflow
}

result := SerializedPath{
NibbleLength: int(nibbleLength),
return Path{}, err
}
pathBytesLen := result.NibbleLength >> 1
hasOddLen := result.hasOddLength()
if hasOddLen {
pathBytesLen++
if length > math.MaxInt {
return Path{}, errIntOverflow
}
result := emptyPath(branchFactor)
result.tokensLength = int(length)
pathBytesLen := result.bytesNeeded(result.tokensLength)
if pathBytesLen > src.Len() {
return SerializedPath{}, io.ErrUnexpectedEOF
return Path{}, io.ErrUnexpectedEOF
}
result.Value = make([]byte, pathBytesLen)
if _, err := io.ReadFull(src, result.Value); err != nil {
buffer := make([]byte, pathBytesLen)
if _, err := io.ReadFull(src, buffer); err != nil {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return SerializedPath{}, err
return Path{}, err
}
if hasOddLen {
paddedNibble := result.Value[pathBytesLen-1] & 0x0F
if paddedNibble != 0 {
return SerializedPath{}, errNonZeroNibblePadding
if result.hasPartialByte() {
// Confirm that the padding bits in the partial byte are 0.
// We want to only look at the bits to the right of the last token, which is at index length-1.
// Generate a mask with (8-bitsToShift) 0s followed by bitsToShift 1s.
paddingMask := byte(0xFF >> (8 - result.bitsToShift(result.tokensLength-1)))
if buffer[pathBytesLen-1]&paddingMask != 0 {
return Path{}, errNonZeroPathPadding
}
}
result.value = string(buffer)
return result, nil
}
Loading