-
Notifications
You must be signed in to change notification settings - Fork 66
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
Use skiplists to save on the bitmap size when compressing leaves #454
base: jsign-type-3
Are you sure you want to change the base?
Changes from 1 commit
5444cd1
f40bb5a
3b15f78
fe8246c
ee9413f
4deabaa
a41ce08
12343ee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -170,6 +170,7 @@ const ( | |
leafType byte = 2 | ||
eoAccountType byte = 3 | ||
singleSlotType byte = 4 | ||
skipListType byte = 8 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is set in bit order, because I'm hoping to mix encodings in the future. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we could change it to 4, no long-term db has been using this. |
||
) | ||
|
||
type ( | ||
|
@@ -1775,35 +1776,42 @@ func (n *LeafNode) serializeLeafWithUncompressedCommitments(cBytes, c1Bytes, c2B | |
bitlist [bitlistSize]byte | ||
isEoA = true | ||
count, lastIdx int | ||
gapcount int | ||
gaps [32]struct { | ||
Skip byte // How many slots to skip before the next range | ||
Count byte // Size of the next range | ||
} | ||
) | ||
for i, v := range n.values { | ||
if v != nil { | ||
count++ | ||
lastIdx = i | ||
gaps[gapcount].Count++ | ||
|
||
setBit(bitlist[:], i) | ||
children = append(children, v...) | ||
if padding := emptyValue[:LeafValueSize-len(v)]; len(padding) != 0 { | ||
children = append(children, padding...) | ||
} | ||
} else { | ||
if gaps[gapcount].Skip == 255 { | ||
panic("empty leaf node") | ||
} | ||
if i > 0 && n.values[i-1] != nil { | ||
gapcount++ | ||
} | ||
gaps[gapcount].Skip++ | ||
} | ||
|
||
// Check for an EOA | ||
if isEoA { | ||
switch i { | ||
case 0: | ||
// Version should be 0 | ||
isEoA = v != nil && bytes.Equal(v, zero32[:]) | ||
case 1: | ||
// Balance should not be nil | ||
// Basic data should not be nil | ||
isEoA = v != nil | ||
case 2: | ||
// Nonce should have its last 24 bytes set to 0 | ||
isEoA = v != nil && bytes.Equal(v[leafNonceSize:], zero24[:]) | ||
case 3: | ||
case 1: | ||
// Code hash should be the empty code hash | ||
isEoA = v != nil && bytes.Equal(v, EmptyCodeHash[:]) | ||
case 4: | ||
// Code size must be 0 | ||
isEoA = v != nil && bytes.Equal(v, zero32[:]) | ||
default: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the EoA fix for Nyota. |
||
// All other values must be nil | ||
isEoA = v == nil | ||
|
@@ -1830,8 +1838,28 @@ func (n *LeafNode) serializeLeafWithUncompressedCommitments(cBytes, c1Bytes, c2B | |
copy(result[leafStemOffset:], n.stem[:StemSize]) | ||
copy(result[leafStemOffset+StemSize:], c1Bytes[:]) | ||
copy(result[leafStemOffset+StemSize+banderwagon.UncompressedSize:], cBytes[:]) | ||
copy(result[leafStemOffset+StemSize+2*banderwagon.UncompressedSize:], n.values[1]) // copy balance | ||
copy(result[leafStemOffset+StemSize+2*banderwagon.UncompressedSize+leafBalanceSize:], n.values[2][:leafNonceSize]) // copy nonce | ||
copy(result[leafStemOffset+StemSize+2*banderwagon.UncompressedSize:], n.values[0]) // copy basic data | ||
case gapcount < 16: | ||
// If there are less than 16 gaps, it's worth using skiplists | ||
result = make([]byte, 1, nodeTypeSize+StemSize+bitlistSize+3*banderwagon.UncompressedSize+len(children)) | ||
result[0] = skipListType | ||
result = append(result, n.stem[:StemSize]...) | ||
result = append(result, cBytes[:]...) | ||
result = append(result, c1Bytes[:]...) | ||
result = append(result, c2Bytes[:]...) | ||
var leafIdx int | ||
for _, gap := range gaps { | ||
if gap.Count == 0 { | ||
break // skip the last gap as nothing follows | ||
} | ||
Comment on lines
+1863
to
+1866
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we do:
and avoid There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not completely, because if |
||
result = append(result, gap.Skip) | ||
leafIdx += int(gap.Skip) | ||
result = append(result, gap.Count) | ||
for i := 0; i < int(gap.Count); i++ { | ||
result = append(result, n.values[leafIdx]...) | ||
leafIdx++ | ||
} | ||
} | ||
default: | ||
result = make([]byte, nodeTypeSize+StemSize+bitlistSize+3*banderwagon.UncompressedSize+len(children)) | ||
result[0] = leafType | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we rename
gapsize
andvalueIdx
torangeSkip
andrangeCount
, as to use the same names in the serializationSkip
andCount
?Using
gap
orrange
worlds can be confusing. Using the same names as the serialization makes easier to understand the both ways of the algorithm.