-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Add Balance Field Trie #9793
Add Balance Field Trie #9793
Changes from 13 commits
314954e
b13bfa0
a8d1e68
1d4fbdb
f2b8cd3
1735505
46752eb
4593126
7b631cb
4978f49
5ae2eed
6847e95
e33972f
9ebe1da
79e9a87
01d1693
3f3cf35
cd9e950
bcea951
401ca3e
24829a7
fcfbc7e
14d23af
3949195
75e6c5e
81c1d8c
bb1f088
89dbb21
e52be54
88189e2
852715d
7c55600
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 | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,13 +1,15 @@ | ||||||||||||||||||
package fieldtrie | ||||||||||||||||||
|
||||||||||||||||||
import ( | ||||||||||||||||||
"encoding/binary" | ||||||||||||||||||
"fmt" | ||||||||||||||||||
"reflect" | ||||||||||||||||||
|
||||||||||||||||||
"github.com/pkg/errors" | ||||||||||||||||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil" | ||||||||||||||||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/types" | ||||||||||||||||||
"github.com/prysmaticlabs/prysm/crypto/hash" | ||||||||||||||||||
"github.com/prysmaticlabs/prysm/encoding/ssz" | ||||||||||||||||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" | ||||||||||||||||||
"github.com/prysmaticlabs/prysm/runtime/version" | ||||||||||||||||||
) | ||||||||||||||||||
|
@@ -60,6 +62,13 @@ func fieldConverters(field types.FieldIndex, indices []uint64, elements interfac | |||||||||||||||||
reflect.TypeOf([]*ethpb.PendingAttestation{}).Name(), reflect.TypeOf(elements).Name()) | ||||||||||||||||||
} | ||||||||||||||||||
return handlePendingAttestation(val, indices, convertAll) | ||||||||||||||||||
case types.Balances: | ||||||||||||||||||
val, ok := elements.([]uint64) | ||||||||||||||||||
if !ok { | ||||||||||||||||||
return nil, errors.Errorf("Wanted type of %v but got %v", | ||||||||||||||||||
reflect.TypeOf([]uint64{}).Name(), reflect.TypeOf(elements).Name()) | ||||||||||||||||||
} | ||||||||||||||||||
return handleBalanceSlice(val, indices, convertAll) | ||||||||||||||||||
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. outside the scope of this PR, I'm noticing that the scope of these helpers is really inconsistent. |
||||||||||||||||||
default: | ||||||||||||||||||
return [][32]byte{}, errors.Errorf("got unsupported type of %v", reflect.TypeOf(elements).Name()) | ||||||||||||||||||
} | ||||||||||||||||||
|
@@ -141,3 +150,47 @@ func handlePendingAttestation(val []*ethpb.PendingAttestation, indices []uint64, | |||||||||||||||||
} | ||||||||||||||||||
return roots, nil | ||||||||||||||||||
} | ||||||||||||||||||
|
||||||||||||||||||
func handleBalanceSlice(val []uint64, indices []uint64, convertAll bool) ([][32]byte, error) { | ||||||||||||||||||
rkapka marked this conversation as resolved.
Show resolved
Hide resolved
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 function needs tests. |
||||||||||||||||||
if convertAll { | ||||||||||||||||||
balancesMarshaling := make([][]byte, 0) | ||||||||||||||||||
for i := 0; i < len(val); i++ { | ||||||||||||||||||
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. nitpick: i feel like we should prefer:
or in this case, since you aren't using the actual index:
just because it "scans" faster when reading code. |
||||||||||||||||||
balanceBuf := make([]byte, 8) | ||||||||||||||||||
binary.LittleEndian.PutUint64(balanceBuf, val[i]) | ||||||||||||||||||
balancesMarshaling = append(balancesMarshaling, balanceBuf) | ||||||||||||||||||
} | ||||||||||||||||||
balancesChunks, err := ssz.PackByChunk(balancesMarshaling) | ||||||||||||||||||
if err != nil { | ||||||||||||||||||
return [][32]byte{}, errors.Wrap(err, "could not pack balances into chunks") | ||||||||||||||||||
} | ||||||||||||||||||
return balancesChunks, nil | ||||||||||||||||||
} | ||||||||||||||||||
if len(val) > 0 { | ||||||||||||||||||
numOfElems, err := types.Balances.CompressedLength() | ||||||||||||||||||
if err != nil { | ||||||||||||||||||
return nil, err | ||||||||||||||||||
} | ||||||||||||||||||
roots := [][32]byte{} | ||||||||||||||||||
for _, idx := range indices { | ||||||||||||||||||
// We split the indexes into their relevant groups. Balances | ||||||||||||||||||
// are compressed according to 4 values -> 1 chunk. | ||||||||||||||||||
startIdx := idx / numOfElems | ||||||||||||||||||
startGroup := startIdx * numOfElems | ||||||||||||||||||
chunk := [32]byte{} | ||||||||||||||||||
sizeOfElem := len(chunk) / int(numOfElems) | ||||||||||||||||||
rkapka marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||
for i, j := 0, startGroup; j < startGroup+numOfElems; i, j = i+sizeOfElem, j+1 { | ||||||||||||||||||
wantedVal := uint64(0) | ||||||||||||||||||
// We only select from a field value, if the | ||||||||||||||||||
// index exists in our element list. If it doesn't | ||||||||||||||||||
// we assume a zero value. | ||||||||||||||||||
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.
Suggested change
|
||||||||||||||||||
if int(j) < len(val) { | ||||||||||||||||||
rkapka marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||
wantedVal = val[j] | ||||||||||||||||||
} | ||||||||||||||||||
binary.LittleEndian.PutUint64(chunk[i:i+sizeOfElem], wantedVal) | ||||||||||||||||||
} | ||||||||||||||||||
roots = append(roots, chunk) | ||||||||||||||||||
} | ||||||||||||||||||
return roots, nil | ||||||||||||||||||
} | ||||||||||||||||||
return [][32]byte{}, nil | ||||||||||||||||||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -1,6 +1,7 @@ | ||||||
package types | ||||||
|
||||||
import ( | ||||||
"github.com/pkg/errors" | ||||||
"github.com/prysmaticlabs/prysm/runtime/version" | ||||||
) | ||||||
|
||||||
|
@@ -18,6 +19,10 @@ const ( | |||||
// CompositeArray represents a variable length array with | ||||||
// a non primitive type. | ||||||
CompositeArray | ||||||
// CompressedArray represents a variable length array which | ||||||
// can pack multiple elements into a leaf of the underlying | ||||||
// trie. | ||||||
CompressedArray | ||||||
) | ||||||
|
||||||
// String returns the name of the field index. | ||||||
|
@@ -82,6 +87,17 @@ func (f FieldIndex) String(stateVersion int) string { | |||||
} | ||||||
} | ||||||
|
||||||
// CompressedLength returns the compressed length of the type(number of | ||||||
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.
Suggested change
|
||||||
// elements that are able to be packed). | ||||||
func (f FieldIndex) CompressedLength() (uint64, error) { | ||||||
switch f { | ||||||
case Balances: | ||||||
return 4, nil | ||||||
default: | ||||||
return 0, errors.Errorf("field %d doesn't support element compression", f) | ||||||
} | ||||||
} | ||||||
|
||||||
// Below we define a set of useful enum values for the field | ||||||
// indices of the beacon state. For example, genesisTime is the | ||||||
// 0th field of the beacon state. This is helpful when we are | ||||||
|
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.
Not part of this change set, but why do embed a
*sync.RWMutex
vs async.RWMutex
? A RWMutex is usable as its zero value, so does not require initialization, whereas using a pointer type requires explicit initialization and risks nil pointers. So I assume the intent is for copies of the state trie share the same lock?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.
that is correct , the tries are shared between different states so the lock must be shared correctly too.