mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 22:07:59 -05:00
Compare commits
13 Commits
trie-debug
...
copyOnWrit
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fac05d4d38 | ||
|
|
a0679c70d3 | ||
|
|
7f53700306 | ||
|
|
3b69f7a196 | ||
|
|
72562dcf3a | ||
|
|
cc23b8311a | ||
|
|
cbe54fe3f9 | ||
|
|
f5afe81b5d | ||
|
|
7ab72d4645 | ||
|
|
9eb968d1ca | ||
|
|
6bb7617a99 | ||
|
|
497bbdbeb5 | ||
|
|
5245c7500f |
13
BUILD.bazel
13
BUILD.bazel
@@ -115,18 +115,19 @@ nogo(
|
||||
"@org_golang_x_tools//go/analysis/passes/assign:go_default_library",
|
||||
"@org_golang_x_tools//go/analysis/passes/inspect:go_default_library",
|
||||
"@org_golang_x_tools//go/analysis/passes/asmdecl:go_default_library",
|
||||
"//tools/analyzers/maligned:go_default_library",
|
||||
"//tools/analyzers/comparesame:go_default_library",
|
||||
"//tools/analyzers/cryptorand:go_default_library",
|
||||
"//tools/analyzers/errcheck:go_default_library",
|
||||
"//tools/analyzers/featureconfig:go_default_library",
|
||||
"//tools/analyzers/comparesame:go_default_library",
|
||||
"//tools/analyzers/shadowpredecl:go_default_library",
|
||||
"//tools/analyzers/nop:go_default_library",
|
||||
"//tools/analyzers/slicedirect:go_default_library",
|
||||
"//tools/analyzers/interfacechecker:go_default_library",
|
||||
"//tools/analyzers/gocognit:go_default_library",
|
||||
"//tools/analyzers/ineffassign:go_default_library",
|
||||
"//tools/analyzers/interfacechecker:go_default_library",
|
||||
"//tools/analyzers/maligned:go_default_library",
|
||||
"//tools/analyzers/nop:go_default_library",
|
||||
"//tools/analyzers/properpermissions:go_default_library",
|
||||
"//tools/analyzers/recursivelock:go_default_library",
|
||||
"//tools/analyzers/shadowpredecl:go_default_library",
|
||||
"//tools/analyzers/slicedirect:go_default_library",
|
||||
"//tools/analyzers/uintcast:go_default_library",
|
||||
] + select({
|
||||
# nogo checks that fail with coverage enabled.
|
||||
|
||||
@@ -407,6 +407,10 @@ func (s *Service) insertFinalizedDeposits(ctx context.Context, fRoot [32]byte) e
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not cast eth1 deposit index")
|
||||
}
|
||||
// The deposit index in the state is always the index of the next deposit
|
||||
// to be included(rather than the last one to be processed). This was most likely
|
||||
// done as the state cannot represent signed integers.
|
||||
eth1DepositIndex -= 1
|
||||
s.cfg.DepositCache.InsertFinalizedDeposits(ctx, int64(eth1DepositIndex))
|
||||
// Deposit proofs are only used during state transition and can be safely removed to save space.
|
||||
if err = s.cfg.DepositCache.PruneProofs(ctx, int64(eth1DepositIndex)); err != nil {
|
||||
|
||||
@@ -1516,7 +1516,7 @@ func TestInsertFinalizedDeposits(t *testing.T) {
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]})
|
||||
gs = gs.Copy()
|
||||
assert.NoError(t, gs.SetEth1Data(ðpb.Eth1Data{DepositCount: 10}))
|
||||
assert.NoError(t, gs.SetEth1DepositIndex(7))
|
||||
assert.NoError(t, gs.SetEth1DepositIndex(8))
|
||||
assert.NoError(t, service.cfg.StateGen.SaveState(ctx, [32]byte{'m', 'o', 'c', 'k'}, gs))
|
||||
zeroSig := [96]byte{}
|
||||
for i := uint64(0); i < uint64(4*params.BeaconConfig().SlotsPerEpoch); i++ {
|
||||
@@ -1555,11 +1555,11 @@ func TestInsertFinalizedDeposits_MultipleFinalizedRoutines(t *testing.T) {
|
||||
service.store.SetFinalizedCheckpt(ðpb.Checkpoint{Root: gRoot[:]})
|
||||
gs = gs.Copy()
|
||||
assert.NoError(t, gs.SetEth1Data(ðpb.Eth1Data{DepositCount: 7}))
|
||||
assert.NoError(t, gs.SetEth1DepositIndex(5))
|
||||
assert.NoError(t, gs.SetEth1DepositIndex(6))
|
||||
assert.NoError(t, service.cfg.StateGen.SaveState(ctx, [32]byte{'m', 'o', 'c', 'k'}, gs))
|
||||
gs2 := gs.Copy()
|
||||
assert.NoError(t, gs2.SetEth1Data(ðpb.Eth1Data{DepositCount: 15}))
|
||||
assert.NoError(t, gs2.SetEth1DepositIndex(12))
|
||||
assert.NoError(t, gs2.SetEth1DepositIndex(13))
|
||||
assert.NoError(t, service.cfg.StateGen.SaveState(ctx, [32]byte{'m', 'o', 'c', 'k', '2'}, gs2))
|
||||
zeroSig := [96]byte{}
|
||||
for i := uint64(0); i < uint64(4*params.BeaconConfig().SlotsPerEpoch); i++ {
|
||||
|
||||
@@ -749,6 +749,85 @@ func TestNonFinalizedDeposits_ReturnsNonFinalizedDepositsUpToBlockNumber(t *test
|
||||
assert.Equal(t, 1, len(deps))
|
||||
}
|
||||
|
||||
func TestFinalizedDeposits_ReturnsTrieCorrectly(t *testing.T) {
|
||||
dc, err := New()
|
||||
require.NoError(t, err)
|
||||
|
||||
generateCtr := func(height uint64, index int64) *ethpb.DepositContainer {
|
||||
return ðpb.DepositContainer{
|
||||
Eth1BlockHeight: height,
|
||||
Deposit: ðpb.Deposit{
|
||||
Data: ðpb.Deposit_Data{
|
||||
PublicKey: bytesutil.PadTo([]byte{uint8(index)}, 48),
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
Signature: make([]byte, 96),
|
||||
},
|
||||
},
|
||||
Index: index,
|
||||
}
|
||||
}
|
||||
|
||||
finalizedDeposits := []*ethpb.DepositContainer{
|
||||
generateCtr(10, 0),
|
||||
generateCtr(11, 1),
|
||||
generateCtr(12, 2),
|
||||
generateCtr(12, 3),
|
||||
generateCtr(13, 4),
|
||||
generateCtr(13, 5),
|
||||
generateCtr(13, 6),
|
||||
generateCtr(14, 7),
|
||||
}
|
||||
dc.deposits = append(finalizedDeposits,
|
||||
generateCtr(15, 8),
|
||||
generateCtr(15, 9),
|
||||
generateCtr(30, 10))
|
||||
trieItems := make([][]byte, 0, len(dc.deposits))
|
||||
for _, dep := range dc.allDeposits(big.NewInt(30)) {
|
||||
depHash, err := dep.Data.HashTreeRoot()
|
||||
assert.NoError(t, err)
|
||||
trieItems = append(trieItems, depHash[:])
|
||||
}
|
||||
depositTrie, err := trie.GenerateTrieFromItems(trieItems, params.BeaconConfig().DepositContractTreeDepth)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Perform this in a non-sensical ordering
|
||||
dc.InsertFinalizedDeposits(context.Background(), 10)
|
||||
dc.InsertFinalizedDeposits(context.Background(), 2)
|
||||
dc.InsertFinalizedDeposits(context.Background(), 3)
|
||||
dc.InsertFinalizedDeposits(context.Background(), 4)
|
||||
|
||||
// Mimick finalized deposit trie fetch.
|
||||
fd := dc.FinalizedDeposits(context.Background())
|
||||
deps := dc.NonFinalizedDeposits(context.Background(), fd.MerkleTrieIndex, big.NewInt(14))
|
||||
insertIndex := fd.MerkleTrieIndex + 1
|
||||
|
||||
for _, dep := range deps {
|
||||
depHash, err := dep.Data.HashTreeRoot()
|
||||
assert.NoError(t, err)
|
||||
if err = fd.Deposits.Insert(depHash[:], int(insertIndex)); err != nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
insertIndex++
|
||||
}
|
||||
dc.InsertFinalizedDeposits(context.Background(), 15)
|
||||
dc.InsertFinalizedDeposits(context.Background(), 15)
|
||||
dc.InsertFinalizedDeposits(context.Background(), 14)
|
||||
|
||||
fd = dc.FinalizedDeposits(context.Background())
|
||||
deps = dc.NonFinalizedDeposits(context.Background(), fd.MerkleTrieIndex, big.NewInt(30))
|
||||
insertIndex = fd.MerkleTrieIndex + 1
|
||||
|
||||
for _, dep := range deps {
|
||||
depHash, err := dep.Data.HashTreeRoot()
|
||||
assert.NoError(t, err)
|
||||
if err = fd.Deposits.Insert(depHash[:], int(insertIndex)); err != nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
insertIndex++
|
||||
}
|
||||
assert.Equal(t, fd.Deposits.NumOfItems(), depositTrie.NumOfItems())
|
||||
}
|
||||
|
||||
func TestPruneProofs_Ok(t *testing.T) {
|
||||
dc, err := New()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -47,14 +47,18 @@ type Config struct {
|
||||
// into the beacon chain database and running services at start up. This service should not be used in production
|
||||
// as it does not have any value other than ease of use for testing purposes.
|
||||
func NewService(ctx context.Context, cfg *Config) *Service {
|
||||
log.Warn("Saving generated genesis state in database for interop testing")
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
|
||||
s := &Service{
|
||||
return &Service{
|
||||
cfg: cfg,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
}
|
||||
}
|
||||
|
||||
// Start initializes the genesis state from configured flags.
|
||||
func (s *Service) Start() {
|
||||
log.Warn("Saving generated genesis state in database for interop testing")
|
||||
|
||||
if s.cfg.GenesisPath != "" {
|
||||
data, err := ioutil.ReadFile(s.cfg.GenesisPath)
|
||||
@@ -69,14 +73,14 @@ func NewService(ctx context.Context, cfg *Config) *Service {
|
||||
if err != nil {
|
||||
log.Fatalf("Could not get state trie: %v", err)
|
||||
}
|
||||
if err := s.saveGenesisState(ctx, genesisTrie); err != nil {
|
||||
if err := s.saveGenesisState(s.ctx, genesisTrie); err != nil {
|
||||
log.Fatalf("Could not save interop genesis state %v", err)
|
||||
}
|
||||
return s
|
||||
return
|
||||
}
|
||||
|
||||
// Save genesis state in db
|
||||
genesisState, _, err := interop.GenerateGenesisState(ctx, s.cfg.GenesisTime, s.cfg.NumValidators)
|
||||
genesisState, _, err := interop.GenerateGenesisState(s.ctx, s.cfg.GenesisTime, s.cfg.NumValidators)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not generate interop genesis state: %v", err)
|
||||
}
|
||||
@@ -92,17 +96,11 @@ func NewService(ctx context.Context, cfg *Config) *Service {
|
||||
if err != nil {
|
||||
log.Fatalf("Could not hash tree root genesis state: %v", err)
|
||||
}
|
||||
go slots.CountdownToGenesis(ctx, time.Unix(int64(s.cfg.GenesisTime), 0), s.cfg.NumValidators, gRoot)
|
||||
go slots.CountdownToGenesis(s.ctx, time.Unix(int64(s.cfg.GenesisTime), 0), s.cfg.NumValidators, gRoot)
|
||||
|
||||
if err := s.saveGenesisState(ctx, genesisTrie); err != nil {
|
||||
if err := s.saveGenesisState(s.ctx, genesisTrie); err != nil {
|
||||
log.Fatalf("Could not save interop genesis state %v", err)
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// Start initializes the genesis state from configured flags.
|
||||
func (_ *Service) Start() {
|
||||
}
|
||||
|
||||
// Stop does nothing.
|
||||
|
||||
@@ -95,6 +95,7 @@ func NewService(ctx context.Context, config *ValidatorMonitorConfig, tracked []t
|
||||
latestPerformance: make(map[types.ValidatorIndex]ValidatorLatestPerformance),
|
||||
aggregatedPerformance: make(map[types.ValidatorIndex]ValidatorAggregatedPerformance),
|
||||
trackedSyncCommitteeIndices: make(map[types.ValidatorIndex][]types.CommitteeIndex),
|
||||
isLogging: false,
|
||||
}
|
||||
for _, idx := range tracked {
|
||||
r.TrackedValidators[idx] = true
|
||||
@@ -117,7 +118,6 @@ func (s *Service) Start() {
|
||||
"ValidatorIndices": tracked,
|
||||
}).Info("Starting service")
|
||||
|
||||
s.isLogging = false
|
||||
stateChannel := make(chan *feed.Event, 1)
|
||||
stateSub := s.config.StateNotifier.StateFeed().Subscribe(stateChannel)
|
||||
|
||||
|
||||
@@ -906,6 +906,7 @@ func (b *BeaconNode) registerDeterminsticGenesisService() error {
|
||||
DepositCache: b.depositCache,
|
||||
GenesisPath: genesisStatePath,
|
||||
})
|
||||
svc.Start()
|
||||
|
||||
// Register genesis state as start-up state when interop mode.
|
||||
// The start-up state gets reused across services.
|
||||
|
||||
@@ -120,11 +120,16 @@ func (s *Service) handleExchangeConfigurationError(err error) {
|
||||
// Logs the terminal total difficulty status.
|
||||
func (s *Service) logTtdStatus(ctx context.Context, ttd *uint256.Int) (bool, error) {
|
||||
latest, err := s.LatestExecutionBlock(ctx)
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.Is(err, hexutil.ErrEmptyString):
|
||||
return false, nil
|
||||
case err != nil:
|
||||
return false, err
|
||||
}
|
||||
if latest == nil {
|
||||
case latest == nil:
|
||||
return false, errors.New("latest block is nil")
|
||||
case latest.TotalDifficulty == "":
|
||||
return false, nil
|
||||
default:
|
||||
}
|
||||
latestTtd, err := hexutil.DecodeBig(latest.TotalDifficulty)
|
||||
if err != nil {
|
||||
|
||||
@@ -190,6 +190,38 @@ func TestService_logTtdStatus(t *testing.T) {
|
||||
require.Equal(t, false, reached)
|
||||
}
|
||||
|
||||
func TestService_logTtdStatus_NotSyncedClient(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
defer func() {
|
||||
require.NoError(t, r.Body.Close())
|
||||
}()
|
||||
|
||||
resp := (*pb.ExecutionBlock)(nil) // Nil response when a client is not synced
|
||||
respJSON := map[string]interface{}{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"result": resp,
|
||||
}
|
||||
require.NoError(t, json.NewEncoder(w).Encode(respJSON))
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
rpcClient, err := rpc.DialHTTP(srv.URL)
|
||||
require.NoError(t, err)
|
||||
defer rpcClient.Close()
|
||||
|
||||
service := &Service{
|
||||
cfg: &config{},
|
||||
}
|
||||
service.rpcClient = rpcClient
|
||||
|
||||
ttd := new(uint256.Int)
|
||||
reached, err := service.logTtdStatus(context.Background(), ttd.SetUint64(24343))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, reached)
|
||||
}
|
||||
|
||||
func emptyPayload() *pb.ExecutionPayload {
|
||||
return &pb.ExecutionPayload{
|
||||
ParentHash: make([]byte, fieldparams.RootLength),
|
||||
|
||||
@@ -413,11 +413,14 @@ func (s *Service) initDepositCaches(ctx context.Context, ctrs []*ethpb.DepositCo
|
||||
// accumulates. we finalize them here before we are ready to receive a block.
|
||||
// Otherwise, the first few blocks will be slower to compute as we will
|
||||
// hold the lock and be busy finalizing the deposits.
|
||||
s.cfg.depositCache.InsertFinalizedDeposits(ctx, int64(currIndex)) // lint:ignore uintcast -- deposit index will not exceed int64 in your lifetime.
|
||||
// The deposit index in the state is always the index of the next deposit
|
||||
// to be included(rather than the last one to be processed). This was most likely
|
||||
// done as the state cannot represent signed integers.
|
||||
actualIndex := int64(currIndex) - 1 // lint:ignore uintcast -- deposit index will not exceed int64 in your lifetime.
|
||||
s.cfg.depositCache.InsertFinalizedDeposits(ctx, actualIndex)
|
||||
// Deposit proofs are only used during state transition and can be safely removed to save space.
|
||||
|
||||
// lint:ignore uintcast -- deposit index will not exceed int64 in your lifetime.
|
||||
if err = s.cfg.depositCache.PruneProofs(ctx, int64(currIndex)); err != nil {
|
||||
if err = s.cfg.depositCache.PruneProofs(ctx, actualIndex); err != nil {
|
||||
return errors.Wrap(err, "could not prune deposit proofs")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -472,7 +472,7 @@ func TestInitDepositCacheWithFinalization_OK(t *testing.T) {
|
||||
require.NoError(t, s.cfg.beaconDB.SaveState(context.Background(), emptyState, headRoot))
|
||||
require.NoError(t, stateGen.SaveState(context.Background(), headRoot, emptyState))
|
||||
s.cfg.stateGen = stateGen
|
||||
require.NoError(t, emptyState.SetEth1DepositIndex(2))
|
||||
require.NoError(t, emptyState.SetEth1DepositIndex(3))
|
||||
|
||||
ctx := context.Background()
|
||||
require.NoError(t, beaconDB.SaveFinalizedCheckpoint(ctx, ðpb.Checkpoint{Epoch: slots.ToEpoch(0), Root: headRoot[:]}))
|
||||
|
||||
@@ -159,12 +159,9 @@ func (vs *Server) depositTrie(ctx context.Context, canonicalEth1Data *ethpb.Eth1
|
||||
|
||||
var depositTrie *trie.SparseMerkleTrie
|
||||
|
||||
log.Infof("eth1 data with hash %#x and count %d at height %d", canonicalEth1Data.BlockHash, canonicalEth1Data.DepositCount, canonicalEth1DataHeight.Uint64())
|
||||
finalizedDeposits := vs.DepositFetcher.FinalizedDeposits(ctx)
|
||||
depositTrie = finalizedDeposits.Deposits
|
||||
log.Infof("deposit trie has number of items of %d at index current index %d", depositTrie.NumOfItems(), finalizedDeposits.MerkleTrieIndex)
|
||||
upToEth1DataDeposits := vs.DepositFetcher.NonFinalizedDeposits(ctx, finalizedDeposits.MerkleTrieIndex, canonicalEth1DataHeight)
|
||||
log.Infof("received %d non finalized deposits", len(upToEth1DataDeposits))
|
||||
insertIndex := finalizedDeposits.MerkleTrieIndex + 1
|
||||
|
||||
for _, dep := range upToEth1DataDeposits {
|
||||
@@ -181,20 +178,7 @@ func (vs *Server) depositTrie(ctx context.Context, canonicalEth1Data *ethpb.Eth1
|
||||
// Log a warning here, as the cached trie is invalid.
|
||||
if !valid {
|
||||
log.Warnf("Cached deposit trie is invalid, rebuilding it now: %v", err)
|
||||
rebuiltTrie, err := vs.rebuildDepositTrie(ctx, canonicalEth1Data, canonicalEth1DataHeight)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
oldItems := depositTrie.Items()
|
||||
newItems := rebuiltTrie.Items()
|
||||
for i, item := range newItems {
|
||||
if i >= len(oldItems) {
|
||||
continue
|
||||
}
|
||||
if !bytes.Equal(item, oldItems[i]) {
|
||||
log.Warnf("Index %d has a different result: wanted %#x but got %#x", i, item, oldItems[i])
|
||||
}
|
||||
}
|
||||
return vs.rebuildDepositTrie(ctx, canonicalEth1Data, canonicalEth1DataHeight)
|
||||
}
|
||||
|
||||
return depositTrie, nil
|
||||
|
||||
@@ -116,21 +116,14 @@ type Config struct {
|
||||
// be registered into a running beacon node.
|
||||
func NewService(ctx context.Context, cfg *Config) *Service {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
return &Service{
|
||||
s := &Service{
|
||||
cfg: cfg,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
incomingAttestation: make(chan *ethpbv1alpha1.Attestation, params.BeaconConfig().DefaultBufferSize),
|
||||
connectedRPCClients: make(map[net.Addr]bool),
|
||||
}
|
||||
}
|
||||
|
||||
// paranoid build time check to ensure ChainInfoFetcher implements required interfaces
|
||||
var _ stategen.CanonicalChecker = blockchain.ChainInfoFetcher(nil)
|
||||
var _ stategen.CurrentSlotter = blockchain.ChainInfoFetcher(nil)
|
||||
|
||||
// Start the gRPC server.
|
||||
func (s *Service) Start() {
|
||||
address := fmt.Sprintf("%s:%s", s.cfg.Host, s.cfg.Port)
|
||||
lis, err := net.Listen("tcp", address)
|
||||
if err != nil {
|
||||
@@ -159,7 +152,6 @@ func (s *Service) Start() {
|
||||
)),
|
||||
grpc.MaxRecvMsgSize(s.cfg.MaxMsgSize),
|
||||
}
|
||||
grpc_prometheus.EnableHandlingTimeHistogram()
|
||||
if s.cfg.CertFlag != "" && s.cfg.KeyFlag != "" {
|
||||
creds, err := credentials.NewServerTLSFromFile(s.cfg.CertFlag, s.cfg.KeyFlag)
|
||||
if err != nil {
|
||||
@@ -173,6 +165,17 @@ func (s *Service) Start() {
|
||||
}
|
||||
s.grpcServer = grpc.NewServer(opts...)
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// paranoid build time check to ensure ChainInfoFetcher implements required interfaces
|
||||
var _ stategen.CanonicalChecker = blockchain.ChainInfoFetcher(nil)
|
||||
var _ stategen.CurrentSlotter = blockchain.ChainInfoFetcher(nil)
|
||||
|
||||
// Start the gRPC server.
|
||||
func (s *Service) Start() {
|
||||
grpc_prometheus.EnableHandlingTimeHistogram()
|
||||
|
||||
var stateCache stategen.CachedGetter
|
||||
if s.cfg.StateGen != nil {
|
||||
stateCache = s.cfg.StateGen.CombinedCache()
|
||||
|
||||
@@ -56,7 +56,7 @@ func NewFieldTrie(field types.FieldIndex, dataType types.DataType, elements inte
|
||||
reference: stateutil.NewRef(1),
|
||||
RWMutex: new(sync.RWMutex),
|
||||
length: length,
|
||||
numOfElems: reflect.Indirect(reflect.ValueOf(elements)).Len(),
|
||||
numOfElems: retrieveLength(elements),
|
||||
}, nil
|
||||
case types.CompositeArray, types.CompressedArray:
|
||||
return &FieldTrie{
|
||||
@@ -66,7 +66,7 @@ func NewFieldTrie(field types.FieldIndex, dataType types.DataType, elements inte
|
||||
reference: stateutil.NewRef(1),
|
||||
RWMutex: new(sync.RWMutex),
|
||||
length: length,
|
||||
numOfElems: reflect.Indirect(reflect.ValueOf(elements)).Len(),
|
||||
numOfElems: retrieveLength(elements),
|
||||
}, nil
|
||||
default:
|
||||
return nil, errors.Errorf("unrecognized data type in field map: %v", reflect.TypeOf(dataType).Name())
|
||||
@@ -97,14 +97,14 @@ func (f *FieldTrie) RecomputeTrie(indices []uint64, elements interface{}) ([32]b
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
f.numOfElems = reflect.Indirect(reflect.ValueOf(elements)).Len()
|
||||
f.numOfElems = retrieveLength(elements)
|
||||
return fieldRoot, nil
|
||||
case types.CompositeArray:
|
||||
fieldRoot, f.fieldLayers, err = stateutil.RecomputeFromLayerVariable(fieldRoots, indices, f.fieldLayers)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
f.numOfElems = reflect.Indirect(reflect.ValueOf(elements)).Len()
|
||||
f.numOfElems = retrieveLength(elements)
|
||||
return stateutil.AddInMixin(fieldRoot, uint64(len(f.fieldLayers[0])))
|
||||
case types.CompressedArray:
|
||||
numOfElems, err := f.field.ElemsInChunk()
|
||||
@@ -133,7 +133,7 @@ func (f *FieldTrie) RecomputeTrie(indices []uint64, elements interface{}) ([32]b
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
f.numOfElems = reflect.Indirect(reflect.ValueOf(elements)).Len()
|
||||
f.numOfElems = retrieveLength(elements)
|
||||
return stateutil.AddInMixin(fieldRoot, uint64(f.numOfElems))
|
||||
default:
|
||||
return [32]byte{}, errors.Errorf("unrecognized data type in field map: %v", reflect.TypeOf(f.dataType).Name())
|
||||
|
||||
@@ -57,9 +57,11 @@ func validateElements(field types.FieldIndex, dataType types.DataType, elements
|
||||
}
|
||||
length *= comLength
|
||||
}
|
||||
val := reflect.Indirect(reflect.ValueOf(elements))
|
||||
if uint64(val.Len()) > length {
|
||||
return errors.Errorf("elements length is larger than expected for field %s: %d > %d", field.String(version.Phase0), val.Len(), length)
|
||||
elemLen := retrieveLength(elements)
|
||||
|
||||
castedLen := int(length) // lint:ignore uintcast- ajhdjhd
|
||||
if elemLen > castedLen {
|
||||
return errors.Errorf("elements length is larger than expected for field %s: %d > %d", field.String(version.Phase0), elemLen, length)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -72,7 +74,7 @@ func fieldConverters(field types.FieldIndex, indices []uint64, elements interfac
|
||||
case [][]byte:
|
||||
return handleByteArrays(val, indices, convertAll)
|
||||
case *customtypes.BlockRoots:
|
||||
return handle32ByteArrays(val[:], indices, convertAll)
|
||||
return handleIndexer(val, indices, convertAll)
|
||||
default:
|
||||
return nil, errors.Errorf("Incorrect type used for block roots")
|
||||
}
|
||||
@@ -90,7 +92,7 @@ func fieldConverters(field types.FieldIndex, indices []uint64, elements interfac
|
||||
case [][]byte:
|
||||
return handleByteArrays(val, indices, convertAll)
|
||||
case *customtypes.RandaoMixes:
|
||||
return handle32ByteArrays(val[:], indices, convertAll)
|
||||
return handleIndexer(val, indices, convertAll)
|
||||
default:
|
||||
return nil, errors.Errorf("Incorrect type used for randao mixes")
|
||||
}
|
||||
@@ -182,6 +184,34 @@ func handle32ByteArrays(val [][32]byte, indices []uint64, convertAll bool) ([][3
|
||||
return roots, nil
|
||||
}
|
||||
|
||||
// handle32ByteArrays computes and returns 32 byte arrays in a slice of root format.
|
||||
func handleIndexer(indexer customtypes.Indexer, indices []uint64, convertAll bool) ([][32]byte, error) {
|
||||
length := len(indices)
|
||||
totalLength := indexer.TotalLength()
|
||||
if convertAll {
|
||||
length = int(totalLength) // lint:ignore uintcast- ajhdjhd
|
||||
}
|
||||
roots := make([][32]byte, 0, length)
|
||||
rootCreator := func(input [32]byte) {
|
||||
roots = append(roots, input)
|
||||
}
|
||||
if convertAll {
|
||||
for i := uint64(0); i < uint64(length); i++ {
|
||||
rootCreator(indexer.RootAtIndex(i))
|
||||
}
|
||||
return roots, nil
|
||||
}
|
||||
if totalLength > 0 {
|
||||
for _, idx := range indices {
|
||||
if idx > totalLength-1 {
|
||||
return nil, fmt.Errorf("index %d greater than number of byte arrays %d", idx, totalLength)
|
||||
}
|
||||
rootCreator(indexer.RootAtIndex(idx))
|
||||
}
|
||||
}
|
||||
return roots, nil
|
||||
}
|
||||
|
||||
// handleValidatorSlice returns the validator indices in a slice of root format.
|
||||
func handleValidatorSlice(val []*ethpb.Validator, indices []uint64, convertAll bool) ([][32]byte, error) {
|
||||
length := len(indices)
|
||||
@@ -348,3 +378,17 @@ func handleBalanceSlice(val, indices []uint64, convertAll bool) ([][32]byte, err
|
||||
}
|
||||
return [][32]byte{}, nil
|
||||
}
|
||||
|
||||
func retrieveLength(elements interface{}) int {
|
||||
elemLen := int(0)
|
||||
elemVal := reflect.ValueOf(elements)
|
||||
if reflect.Indirect(elemVal).Kind() == reflect.Struct {
|
||||
meth := elemVal.MethodByName("TotalLength")
|
||||
ret := meth.Call([]reflect.Value{})
|
||||
elemLen = int(ret[0].Uint()) // lint:ignore uintcast- ajhdjhd
|
||||
} else {
|
||||
val := reflect.Indirect(elemVal)
|
||||
elemLen = val.Len()
|
||||
}
|
||||
return elemLen
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//beacon-chain/state/stateutil:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"@com_github_ferranbt_fastssz//:go_default_library",
|
||||
],
|
||||
|
||||
@@ -2,28 +2,162 @@ package customtypes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sort"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
fssz "github.com/ferranbt/fastssz"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
)
|
||||
|
||||
var _ fssz.HashRoot = (BlockRoots)([fieldparams.BlockRootsLength][32]byte{})
|
||||
var _ fssz.HashRoot = (*BlockRoots)(nil)
|
||||
var _ fssz.Marshaler = (*BlockRoots)(nil)
|
||||
var _ fssz.Unmarshaler = (*BlockRoots)(nil)
|
||||
|
||||
type Indexer interface {
|
||||
RootAtIndex(idx uint64) [32]byte
|
||||
TotalLength() uint64
|
||||
}
|
||||
|
||||
// BlockRoots represents block roots of the beacon state.
|
||||
type BlockRoots [fieldparams.BlockRootsLength][32]byte
|
||||
type BlockRoots struct {
|
||||
baseArray *baseArrayBlockRoots
|
||||
fieldJournal map[uint64][32]byte
|
||||
generation uint64
|
||||
*stateutil.Reference
|
||||
}
|
||||
|
||||
type baseArrayBlockRoots struct {
|
||||
baseArray *[fieldparams.BlockRootsLength][32]byte
|
||||
descendantMap map[uint64][]uintptr
|
||||
*sync.RWMutex
|
||||
*stateutil.Reference
|
||||
}
|
||||
|
||||
type sorter struct {
|
||||
objs [][]uintptr
|
||||
generations []uint64
|
||||
}
|
||||
|
||||
func (s sorter) Len() int {
|
||||
return len(s.generations)
|
||||
}
|
||||
|
||||
func (s sorter) Swap(i, j int) {
|
||||
s.objs[i], s.objs[j] = s.objs[j], s.objs[i]
|
||||
s.generations[i], s.generations[j] = s.generations[j], s.generations[i]
|
||||
}
|
||||
|
||||
func (s sorter) Less(i, j int) bool {
|
||||
return s.generations[i] < s.generations[j]
|
||||
}
|
||||
|
||||
func (b *baseArrayBlockRoots) RootAtIndex(idx uint64) [32]byte {
|
||||
b.RWMutex.RLock()
|
||||
defer b.RWMutex.RUnlock()
|
||||
return b.baseArray[idx]
|
||||
}
|
||||
|
||||
func (b *baseArrayBlockRoots) TotalLength() uint64 {
|
||||
return fieldparams.BlockRootsLength
|
||||
}
|
||||
|
||||
func (b *baseArrayBlockRoots) addGeneration(generation uint64, descendant uintptr) {
|
||||
b.RWMutex.Lock()
|
||||
defer b.RWMutex.Unlock()
|
||||
b.descendantMap[generation] = append(b.descendantMap[generation], descendant)
|
||||
}
|
||||
|
||||
func (b *baseArrayBlockRoots) removeGeneration(generation uint64, descendant uintptr) {
|
||||
b.RWMutex.Lock()
|
||||
defer b.RWMutex.Unlock()
|
||||
ptrVals := b.descendantMap[generation]
|
||||
newVals := []uintptr{}
|
||||
for _, v := range ptrVals {
|
||||
if v == descendant {
|
||||
continue
|
||||
}
|
||||
newVals = append(newVals, v)
|
||||
}
|
||||
b.descendantMap[generation] = newVals
|
||||
}
|
||||
|
||||
func (b *baseArrayBlockRoots) numOfDescendants() uint64 {
|
||||
b.RWMutex.RLock()
|
||||
defer b.RWMutex.RUnlock()
|
||||
return uint64(len(b.descendantMap))
|
||||
}
|
||||
|
||||
func (b *baseArrayBlockRoots) cleanUp() {
|
||||
b.RWMutex.Lock()
|
||||
defer b.RWMutex.Unlock()
|
||||
fmt.Printf("\n cleaning up block roots %d \n ", len(b.descendantMap))
|
||||
listOfObjs := [][]uintptr{}
|
||||
generations := []uint64{}
|
||||
for g, objs := range b.descendantMap {
|
||||
generations = append(generations, g)
|
||||
listOfObjs = append(listOfObjs, objs)
|
||||
}
|
||||
sortedObj := sorter{
|
||||
objs: listOfObjs,
|
||||
generations: generations,
|
||||
}
|
||||
sort.Sort(sortedObj)
|
||||
lastReferencedGen := 0
|
||||
lastRefrencedIdx := 0
|
||||
lastRefPointer := 0
|
||||
for i, g := range sortedObj.generations {
|
||||
for j, o := range sortedObj.objs[i] {
|
||||
|
||||
x := (*BlockRoots)(unsafe.Pointer(o))
|
||||
if x == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
lastReferencedGen = int(g) // lint:ignore uintcast- ajhdjhd
|
||||
lastRefrencedIdx = i
|
||||
lastRefPointer = j
|
||||
break
|
||||
}
|
||||
if lastReferencedGen != 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fmt.Printf("\n block root map %d, %d, %d \n ", lastReferencedGen, lastRefrencedIdx, lastRefPointer)
|
||||
|
||||
br := (*BlockRoots)(unsafe.Pointer(sortedObj.objs[lastRefrencedIdx][lastRefPointer]))
|
||||
for k, v := range br.fieldJournal {
|
||||
b.baseArray[k] = v
|
||||
}
|
||||
sortedObj.generations = sortedObj.generations[lastRefrencedIdx:]
|
||||
sortedObj.objs = sortedObj.objs[lastRefrencedIdx:]
|
||||
|
||||
newMap := make(map[uint64][]uintptr)
|
||||
for i, g := range sortedObj.generations {
|
||||
newMap[g] = sortedObj.objs[i]
|
||||
}
|
||||
b.descendantMap = newMap
|
||||
}
|
||||
|
||||
// HashTreeRoot returns calculated hash root.
|
||||
func (r BlockRoots) HashTreeRoot() ([32]byte, error) {
|
||||
func (r *BlockRoots) HashTreeRoot() ([32]byte, error) {
|
||||
return fssz.HashWithDefaultHasher(r)
|
||||
}
|
||||
|
||||
// HashTreeRootWith hashes a BlockRoots object with a Hasher from the default HasherPool.
|
||||
func (r BlockRoots) HashTreeRootWith(hh *fssz.Hasher) error {
|
||||
func (r *BlockRoots) HashTreeRootWith(hh *fssz.Hasher) error {
|
||||
index := hh.Index()
|
||||
for _, sRoot := range r {
|
||||
hh.Append(sRoot[:])
|
||||
|
||||
for i := uint64(0); i < r.baseArray.TotalLength(); i++ {
|
||||
if val, ok := r.fieldJournal[i]; ok {
|
||||
hh.Append(val[:])
|
||||
continue
|
||||
}
|
||||
rt := r.baseArray.RootAtIndex(i)
|
||||
hh.Append(rt[:])
|
||||
}
|
||||
hh.Merkleize(index)
|
||||
return nil
|
||||
@@ -34,12 +168,13 @@ func (r *BlockRoots) UnmarshalSSZ(buf []byte) error {
|
||||
if len(buf) != r.SizeSSZ() {
|
||||
return fmt.Errorf("expected buffer of length %d received %d", r.SizeSSZ(), len(buf))
|
||||
}
|
||||
r.baseArray.Lock()
|
||||
defer r.baseArray.Unlock()
|
||||
|
||||
var roots BlockRoots
|
||||
for i := range roots {
|
||||
copy(roots[i][:], buf[i*32:(i+1)*32])
|
||||
for i := range r.baseArray.baseArray {
|
||||
copy(r.baseArray.baseArray[i][:], buf[i*32:(i+1)*32])
|
||||
}
|
||||
*r = roots
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -55,10 +190,13 @@ func (r *BlockRoots) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
// MarshalSSZ marshals BlockRoots into a serialized object.
|
||||
func (r *BlockRoots) MarshalSSZ() ([]byte, error) {
|
||||
marshalled := make([]byte, fieldparams.BlockRootsLength*32)
|
||||
for i, r32 := range r {
|
||||
for j, rr := range r32 {
|
||||
marshalled[i*32+j] = rr
|
||||
for i := uint64(0); i < r.baseArray.TotalLength(); i++ {
|
||||
if val, ok := r.fieldJournal[i]; ok {
|
||||
copy(marshalled[i*32:], val[:])
|
||||
continue
|
||||
}
|
||||
rt := r.baseArray.RootAtIndex(i)
|
||||
copy(marshalled[i*32:], rt[:])
|
||||
}
|
||||
return marshalled, nil
|
||||
}
|
||||
@@ -73,10 +211,152 @@ func (r *BlockRoots) Slice() [][]byte {
|
||||
if r == nil {
|
||||
return nil
|
||||
}
|
||||
bRoots := make([][]byte, len(r))
|
||||
for i, root := range r {
|
||||
tmp := root
|
||||
bRoots[i] = tmp[:]
|
||||
bRoots := make([][]byte, r.baseArray.TotalLength())
|
||||
for i := uint64(0); i < r.baseArray.TotalLength(); i++ {
|
||||
if val, ok := r.fieldJournal[i]; ok {
|
||||
bRoots[i] = val[:]
|
||||
continue
|
||||
}
|
||||
rt := r.baseArray.RootAtIndex(i)
|
||||
bRoots[i] = rt[:]
|
||||
}
|
||||
return bRoots
|
||||
}
|
||||
|
||||
// Slice converts a customtypes.BlockRoots object into a 2D byte slice.
|
||||
func (r *BlockRoots) Array() [fieldparams.BlockRootsLength][32]byte {
|
||||
if r == nil {
|
||||
return [fieldparams.BlockRootsLength][32]byte{}
|
||||
}
|
||||
bRoots := [fieldparams.BlockRootsLength][32]byte{}
|
||||
for i := uint64(0); i < r.baseArray.TotalLength(); i++ {
|
||||
if val, ok := r.fieldJournal[i]; ok {
|
||||
bRoots[i] = val
|
||||
continue
|
||||
}
|
||||
rt := r.baseArray.RootAtIndex(i)
|
||||
bRoots[i] = rt
|
||||
}
|
||||
return bRoots
|
||||
}
|
||||
|
||||
func SetFromSlice(slice [][]byte) *BlockRoots {
|
||||
br := &BlockRoots{
|
||||
baseArray: &baseArrayBlockRoots{
|
||||
baseArray: new([fieldparams.BlockRootsLength][32]byte),
|
||||
descendantMap: map[uint64][]uintptr{},
|
||||
RWMutex: new(sync.RWMutex),
|
||||
Reference: stateutil.NewRef(1),
|
||||
},
|
||||
fieldJournal: map[uint64][32]byte{},
|
||||
Reference: stateutil.NewRef(1),
|
||||
}
|
||||
for i, rt := range slice {
|
||||
copy(br.baseArray.baseArray[i][:], rt)
|
||||
}
|
||||
runtime.SetFinalizer(br, blockRootsFinalizer)
|
||||
return br
|
||||
}
|
||||
|
||||
func (r *BlockRoots) SetFromBaseField(field [fieldparams.BlockRootsLength][32]byte) {
|
||||
r.baseArray = &baseArrayBlockRoots{
|
||||
baseArray: &field,
|
||||
descendantMap: map[uint64][]uintptr{},
|
||||
RWMutex: new(sync.RWMutex),
|
||||
Reference: stateutil.NewRef(1),
|
||||
}
|
||||
r.fieldJournal = map[uint64][32]byte{}
|
||||
r.Reference = stateutil.NewRef(1)
|
||||
r.baseArray.addGeneration(0, reflect.ValueOf(r).Pointer())
|
||||
runtime.SetFinalizer(r, blockRootsFinalizer)
|
||||
}
|
||||
|
||||
func (r *BlockRoots) RootAtIndex(idx uint64) [32]byte {
|
||||
if val, ok := r.fieldJournal[idx]; ok {
|
||||
return val
|
||||
}
|
||||
return r.baseArray.RootAtIndex(idx)
|
||||
}
|
||||
|
||||
func (r *BlockRoots) SetRootAtIndex(idx uint64, val [32]byte) {
|
||||
if r.Refs() <= 1 && r.baseArray.Refs() <= 1 {
|
||||
r.baseArray.Lock()
|
||||
r.baseArray.baseArray[idx] = val
|
||||
r.baseArray.Unlock()
|
||||
return
|
||||
}
|
||||
if r.Refs() <= 1 {
|
||||
r.fieldJournal[idx] = val
|
||||
r.baseArray.removeGeneration(r.generation, reflect.ValueOf(r).Pointer())
|
||||
r.generation++
|
||||
r.baseArray.addGeneration(r.generation, reflect.ValueOf(r).Pointer())
|
||||
return
|
||||
}
|
||||
newJournal := make(map[uint64][32]byte)
|
||||
for k, val := range r.fieldJournal {
|
||||
newJournal[k] = val
|
||||
}
|
||||
|
||||
r.fieldJournal = newJournal
|
||||
r.MinusRef()
|
||||
r.Reference = stateutil.NewRef(1)
|
||||
r.fieldJournal[idx] = val
|
||||
r.baseArray.removeGeneration(r.generation, reflect.ValueOf(r).Pointer())
|
||||
r.generation++
|
||||
r.baseArray.addGeneration(r.generation, reflect.ValueOf(r).Pointer())
|
||||
}
|
||||
|
||||
func (r *BlockRoots) Copy() *BlockRoots {
|
||||
r.baseArray.AddRef()
|
||||
r.Reference.AddRef()
|
||||
br := &BlockRoots{
|
||||
baseArray: r.baseArray,
|
||||
fieldJournal: r.fieldJournal,
|
||||
Reference: r.Reference,
|
||||
generation: r.generation,
|
||||
}
|
||||
r.baseArray.addGeneration(r.generation, reflect.ValueOf(br).Pointer())
|
||||
if r.baseArray.numOfDescendants() > 20 {
|
||||
r.baseArray.cleanUp()
|
||||
}
|
||||
runtime.SetFinalizer(br, blockRootsFinalizer)
|
||||
return br
|
||||
}
|
||||
|
||||
func (r *BlockRoots) TotalLength() uint64 {
|
||||
return fieldparams.BlockRootsLength
|
||||
}
|
||||
|
||||
func (r *BlockRoots) IncreaseRef() {
|
||||
r.Reference.AddRef()
|
||||
r.baseArray.Reference.AddRef()
|
||||
}
|
||||
|
||||
func (r *BlockRoots) DecreaseRef() {
|
||||
r.Reference.MinusRef()
|
||||
r.baseArray.Reference.MinusRef()
|
||||
}
|
||||
|
||||
func blockRootsFinalizer(br *BlockRoots) {
|
||||
br.baseArray.Lock()
|
||||
defer br.baseArray.Unlock()
|
||||
ptrVal := reflect.ValueOf(br).Pointer()
|
||||
vals, ok := br.baseArray.descendantMap[br.generation]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
exists := false
|
||||
wantedVals := []uintptr{}
|
||||
for _, v := range vals {
|
||||
if v == ptrVal {
|
||||
exists = true
|
||||
continue
|
||||
}
|
||||
newV := v
|
||||
wantedVals = append(wantedVals, newV)
|
||||
}
|
||||
if !exists {
|
||||
return
|
||||
}
|
||||
br.baseArray.descendantMap[br.generation] = wantedVals
|
||||
}
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
package customtypes
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
)
|
||||
|
||||
func TestBlockRoots_Casting(t *testing.T) {
|
||||
var b [fieldparams.BlockRootsLength][32]byte
|
||||
d := BlockRoots(b)
|
||||
if !reflect.DeepEqual([fieldparams.BlockRootsLength][32]byte(d), b) {
|
||||
t.Errorf("Unequal: %v = %v", d, b)
|
||||
f := SetFromSlice([][]byte{})
|
||||
f.SetFromBaseField(b)
|
||||
if !reflect.DeepEqual(f.Array(), b) {
|
||||
t.Errorf("Unequal: %v = %v", f.Array(), b)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockRoots_UnmarshalSSZ(t *testing.T) {
|
||||
t.Run("Ok", func(t *testing.T) {
|
||||
d := BlockRoots{}
|
||||
d := SetFromSlice([][]byte{})
|
||||
var b [fieldparams.BlockRootsLength][32]byte
|
||||
b[0] = [32]byte{'f', 'o', 'o'}
|
||||
b[1] = [32]byte{'b', 'a', 'r'}
|
||||
@@ -32,8 +33,8 @@ func TestBlockRoots_UnmarshalSSZ(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(b, [fieldparams.BlockRootsLength][32]byte(d)) {
|
||||
t.Errorf("Unequal: %v = %v", b, [fieldparams.BlockRootsLength][32]byte(d))
|
||||
if !reflect.DeepEqual(b, d.Array()) {
|
||||
t.Errorf("Unequal: %v = %v", b, d.Array())
|
||||
}
|
||||
})
|
||||
|
||||
@@ -70,28 +71,47 @@ func TestBlockRoots_MarshalSSZTo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBlockRoots_MarshalSSZ(t *testing.T) {
|
||||
d := BlockRoots{}
|
||||
d[0] = [32]byte{'f', 'o', 'o'}
|
||||
d[1] = [32]byte{'b', 'a', 'r'}
|
||||
d := SetFromSlice([][]byte{})
|
||||
d.IncreaseRef()
|
||||
d.SetRootAtIndex(0, [32]byte{'f', 'o', 'o'})
|
||||
d.IncreaseRef()
|
||||
d.IncreaseRef()
|
||||
d.SetRootAtIndex(1, [32]byte{'b', 'a', 'r'})
|
||||
b, err := d.MarshalSSZ()
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(d[0][:], b[0:32]) {
|
||||
t.Errorf("Unequal: %v = %v", d[0], b[0:32])
|
||||
rt := d.RootAtIndex(0)
|
||||
if !reflect.DeepEqual(rt[:], b[0:32]) {
|
||||
t.Errorf("Unequal: %v = %v", rt, b[0:32])
|
||||
}
|
||||
if !reflect.DeepEqual(d[1][:], b[32:64]) {
|
||||
t.Errorf("Unequal: %v = %v", d[0], b[32:64])
|
||||
rt = d.RootAtIndex(1)
|
||||
if !reflect.DeepEqual(rt[:], b[32:64]) {
|
||||
t.Errorf("Unequal: %v = %v", rt, b[32:64])
|
||||
}
|
||||
d2 := SetFromSlice([][]byte{})
|
||||
err = d2.UnmarshalSSZ(b)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
res, err := d2.MarshalSSZ()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if !bytes.Equal(res, b) {
|
||||
t.Error("unequal")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlockRoots_SizeSSZ(t *testing.T) {
|
||||
d := BlockRoots{}
|
||||
d := SetFromSlice([][]byte{})
|
||||
if d.SizeSSZ() != fieldparams.BlockRootsLength*32 {
|
||||
t.Errorf("Wrong SSZ size. Expected %v vs actual %v", fieldparams.BlockRootsLength*32, d.SizeSSZ())
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
func TestBlockRoots_Slice(t *testing.T) {
|
||||
a, b, c := [32]byte{'a'}, [32]byte{'b'}, [32]byte{'c'}
|
||||
roots := BlockRoots{}
|
||||
@@ -103,3 +123,4 @@ func TestBlockRoots_Slice(t *testing.T) {
|
||||
assert.DeepEqual(t, b[:], slice[10])
|
||||
assert.DeepEqual(t, c[:], slice[100])
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -2,48 +2,77 @@ package customtypes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
fssz "github.com/ferranbt/fastssz"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
)
|
||||
|
||||
var _ fssz.HashRoot = (RandaoMixes)([fieldparams.RandaoMixesLength][32]byte{})
|
||||
var _ fssz.HashRoot = (*RandaoMixes)(nil)
|
||||
var _ fssz.Marshaler = (*RandaoMixes)(nil)
|
||||
var _ fssz.Unmarshaler = (*RandaoMixes)(nil)
|
||||
|
||||
// RandaoMixes represents RANDAO mixes of the beacon state.
|
||||
type RandaoMixes [fieldparams.RandaoMixesLength][32]byte
|
||||
// BlockRoots represents block roots of the beacon state.
|
||||
type RandaoMixes struct {
|
||||
baseArray *baseArrayRandaoMixes
|
||||
fieldJournal map[uint64][32]byte
|
||||
*stateutil.Reference
|
||||
}
|
||||
|
||||
type baseArrayRandaoMixes struct {
|
||||
baseArray *[fieldparams.RandaoMixesLength][32]byte
|
||||
*sync.RWMutex
|
||||
*stateutil.Reference
|
||||
}
|
||||
|
||||
func (b *baseArrayRandaoMixes) RootAtIndex(idx uint64) [32]byte {
|
||||
b.RWMutex.RLock()
|
||||
defer b.RWMutex.RUnlock()
|
||||
return b.baseArray[idx]
|
||||
}
|
||||
|
||||
func (b *baseArrayRandaoMixes) TotalLength() uint64 {
|
||||
return fieldparams.RandaoMixesLength
|
||||
}
|
||||
|
||||
// HashTreeRoot returns calculated hash root.
|
||||
func (r RandaoMixes) HashTreeRoot() ([32]byte, error) {
|
||||
func (r *RandaoMixes) HashTreeRoot() ([32]byte, error) {
|
||||
return fssz.HashWithDefaultHasher(r)
|
||||
}
|
||||
|
||||
// HashTreeRootWith hashes a RandaoMixes object with a Hasher from the default HasherPool.
|
||||
func (r RandaoMixes) HashTreeRootWith(hh *fssz.Hasher) error {
|
||||
// HashTreeRootWith hashes a BlockRoots object with a Hasher from the default HasherPool.
|
||||
func (r *RandaoMixes) HashTreeRootWith(hh *fssz.Hasher) error {
|
||||
index := hh.Index()
|
||||
for _, sRoot := range r {
|
||||
hh.Append(sRoot[:])
|
||||
|
||||
for i := uint64(0); i < r.baseArray.TotalLength(); i++ {
|
||||
if val, ok := r.fieldJournal[i]; ok {
|
||||
hh.Append(val[:])
|
||||
continue
|
||||
}
|
||||
rt := r.baseArray.RootAtIndex(i)
|
||||
hh.Append(rt[:])
|
||||
}
|
||||
hh.Merkleize(index)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalSSZ deserializes the provided bytes buffer into the RandaoMixes object.
|
||||
// UnmarshalSSZ deserializes the provided bytes buffer into the BlockRoots object.
|
||||
func (r *RandaoMixes) UnmarshalSSZ(buf []byte) error {
|
||||
if len(buf) != r.SizeSSZ() {
|
||||
return fmt.Errorf("expected buffer of length %d received %d", r.SizeSSZ(), len(buf))
|
||||
}
|
||||
r.baseArray.Lock()
|
||||
defer r.baseArray.Unlock()
|
||||
|
||||
var roots RandaoMixes
|
||||
for i := range roots {
|
||||
copy(roots[i][:], buf[i*32:(i+1)*32])
|
||||
for i := range r.baseArray.baseArray {
|
||||
copy(r.baseArray.baseArray[i][:], buf[i*32:(i+1)*32])
|
||||
}
|
||||
*r = roots
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalSSZTo marshals RandaoMixes with the provided byte slice.
|
||||
// MarshalSSZTo marshals BlockRoots with the provided byte slice.
|
||||
func (r *RandaoMixes) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
marshalled, err := r.MarshalSSZ()
|
||||
if err != nil {
|
||||
@@ -52,13 +81,16 @@ func (r *RandaoMixes) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
return append(dst, marshalled...), nil
|
||||
}
|
||||
|
||||
// MarshalSSZ marshals RandaoMixes into a serialized object.
|
||||
// MarshalSSZ marshals BlockRoots into a serialized object.
|
||||
func (r *RandaoMixes) MarshalSSZ() ([]byte, error) {
|
||||
marshalled := make([]byte, fieldparams.RandaoMixesLength*32)
|
||||
for i, r32 := range r {
|
||||
for j, rr := range r32 {
|
||||
marshalled[i*32+j] = rr
|
||||
for i := uint64(0); i < r.baseArray.TotalLength(); i++ {
|
||||
if val, ok := r.fieldJournal[i]; ok {
|
||||
copy(marshalled[i*32:], val[:])
|
||||
continue
|
||||
}
|
||||
rt := r.baseArray.RootAtIndex(i)
|
||||
copy(marshalled[i*32:], rt[:])
|
||||
}
|
||||
return marshalled, nil
|
||||
}
|
||||
@@ -68,15 +100,90 @@ func (_ *RandaoMixes) SizeSSZ() int {
|
||||
return fieldparams.RandaoMixesLength * 32
|
||||
}
|
||||
|
||||
// Slice converts a customtypes.RandaoMixes object into a 2D byte slice.
|
||||
// Slice converts a customtypes.BlockRoots object into a 2D byte slice.
|
||||
func (r *RandaoMixes) Slice() [][]byte {
|
||||
if r == nil {
|
||||
return nil
|
||||
}
|
||||
mixes := make([][]byte, len(r))
|
||||
for i, root := range r {
|
||||
tmp := root
|
||||
mixes[i] = tmp[:]
|
||||
bRoots := make([][]byte, r.baseArray.TotalLength())
|
||||
for i := uint64(0); i < r.baseArray.TotalLength(); i++ {
|
||||
if val, ok := r.fieldJournal[i]; ok {
|
||||
bRoots[i] = val[:]
|
||||
continue
|
||||
}
|
||||
rt := r.baseArray.RootAtIndex(i)
|
||||
bRoots[i] = rt[:]
|
||||
}
|
||||
return mixes
|
||||
return bRoots
|
||||
}
|
||||
|
||||
func SetFromSliceRandao(slice [][]byte) *RandaoMixes {
|
||||
br := &RandaoMixes{
|
||||
baseArray: &baseArrayRandaoMixes{
|
||||
baseArray: new([fieldparams.RandaoMixesLength][32]byte),
|
||||
RWMutex: new(sync.RWMutex),
|
||||
Reference: stateutil.NewRef(1),
|
||||
},
|
||||
fieldJournal: map[uint64][32]byte{},
|
||||
Reference: stateutil.NewRef(1),
|
||||
}
|
||||
for i, rt := range slice {
|
||||
copy(br.baseArray.baseArray[i][:], rt)
|
||||
}
|
||||
return br
|
||||
}
|
||||
|
||||
func (r *RandaoMixes) SetFromBaseField(field [fieldparams.RandaoMixesLength][32]byte) {
|
||||
r.baseArray.baseArray = &field
|
||||
}
|
||||
|
||||
func (r *RandaoMixes) RootAtIndex(idx uint64) [32]byte {
|
||||
if val, ok := r.fieldJournal[idx]; ok {
|
||||
return val
|
||||
}
|
||||
return r.baseArray.RootAtIndex(idx)
|
||||
}
|
||||
|
||||
func (r *RandaoMixes) SetRootAtIndex(idx uint64, val [32]byte) {
|
||||
if r.Refs() <= 1 && r.baseArray.Refs() <= 1 {
|
||||
r.baseArray.baseArray[idx] = val
|
||||
return
|
||||
}
|
||||
if r.Refs() <= 1 {
|
||||
r.fieldJournal[idx] = val
|
||||
return
|
||||
}
|
||||
newJournal := make(map[uint64][32]byte)
|
||||
for k, val := range r.fieldJournal {
|
||||
newJournal[k] = val
|
||||
}
|
||||
r.fieldJournal = newJournal
|
||||
r.MinusRef()
|
||||
r.Reference = stateutil.NewRef(1)
|
||||
r.fieldJournal[idx] = val
|
||||
}
|
||||
|
||||
func (r *RandaoMixes) Copy() *RandaoMixes {
|
||||
r.baseArray.AddRef()
|
||||
r.Reference.AddRef()
|
||||
rm := &RandaoMixes{
|
||||
baseArray: r.baseArray,
|
||||
fieldJournal: r.fieldJournal,
|
||||
Reference: r.Reference,
|
||||
}
|
||||
return rm
|
||||
}
|
||||
|
||||
func (r *RandaoMixes) TotalLength() uint64 {
|
||||
return fieldparams.RandaoMixesLength
|
||||
}
|
||||
|
||||
func (r *RandaoMixes) IncreaseRef() {
|
||||
r.Reference.AddRef()
|
||||
r.baseArray.Reference.AddRef()
|
||||
}
|
||||
|
||||
func (r *RandaoMixes) DecreaseRef() {
|
||||
r.Reference.MinusRef()
|
||||
r.baseArray.Reference.MinusRef()
|
||||
}
|
||||
|
||||
@@ -76,8 +76,8 @@ func (b *BeaconState) BlockRootAtIndex(idx uint64) ([]byte, error) {
|
||||
// input index value.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) blockRootAtIndex(idx uint64) ([32]byte, error) {
|
||||
if uint64(len(b.blockRoots)) <= idx {
|
||||
if b.blockRoots.TotalLength() <= idx {
|
||||
return [32]byte{}, fmt.Errorf("index %d out of range", idx)
|
||||
}
|
||||
return b.blockRoots[idx], nil
|
||||
return b.blockRoots.RootAtIndex(idx), nil
|
||||
}
|
||||
|
||||
@@ -37,10 +37,10 @@ func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([]byte, error) {
|
||||
// input index value.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) randaoMixAtIndex(idx uint64) ([32]byte, error) {
|
||||
if uint64(len(b.randaoMixes)) <= idx {
|
||||
if b.randaoMixes.TotalLength() <= idx {
|
||||
return [32]byte{}, fmt.Errorf("index %d out of range", idx)
|
||||
}
|
||||
return b.randaoMixes[idx], nil
|
||||
return b.randaoMixes.RootAtIndex(idx), nil
|
||||
}
|
||||
|
||||
// RandaoMixesLength returns the length of the randao mixes slice.
|
||||
@@ -62,5 +62,5 @@ func (b *BeaconState) randaoMixesLength() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
return len(b.randaoMixes)
|
||||
return int(b.randaoMixes.TotalLength()) // lint:ignore uintcast- ajhdjhd
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
|
||||
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
@@ -25,14 +24,12 @@ func (b *BeaconState) SetBlockRoots(val [][]byte) error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[blockRoots].MinusRef()
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
|
||||
var rootsArr [fieldparams.BlockRootsLength][32]byte
|
||||
for i := 0; i < len(rootsArr); i++ {
|
||||
copy(rootsArr[i][:], val[i])
|
||||
}
|
||||
roots := customtypes.BlockRoots(rootsArr)
|
||||
roots := customtypes.BlockRoots{}
|
||||
roots.SetFromBaseField(rootsArr)
|
||||
b.blockRoots = &roots
|
||||
b.markFieldAsDirty(blockRoots)
|
||||
b.rebuildTrie[blockRoots] = true
|
||||
@@ -42,24 +39,13 @@ func (b *BeaconState) SetBlockRoots(val [][]byte) error {
|
||||
// UpdateBlockRootAtIndex for the beacon state. Updates the block root
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateBlockRootAtIndex(idx uint64, blockRoot [32]byte) error {
|
||||
if uint64(len(b.blockRoots)) <= idx {
|
||||
if b.blockRoots.TotalLength() <= idx {
|
||||
return fmt.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
r := b.blockRoots
|
||||
if ref := b.sharedFieldReferences[blockRoots]; ref.Refs() > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
roots := *b.blockRoots
|
||||
rootsCopy := roots
|
||||
r = &rootsCopy
|
||||
ref.MinusRef()
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
r[idx] = blockRoot
|
||||
b.blockRoots = r
|
||||
b.blockRoots.SetRootAtIndex(idx, blockRoot)
|
||||
|
||||
b.markFieldAsDirty(blockRoots)
|
||||
b.addDirtyIndices(blockRoots, []uint64{idx})
|
||||
|
||||
@@ -3,7 +3,6 @@ package v1
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
)
|
||||
@@ -14,14 +13,12 @@ func (b *BeaconState) SetRandaoMixes(val [][]byte) error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[randaoMixes].MinusRef()
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
|
||||
var mixesArr [fieldparams.RandaoMixesLength][32]byte
|
||||
for i := 0; i < len(mixesArr); i++ {
|
||||
copy(mixesArr[i][:], val[i])
|
||||
}
|
||||
mixes := customtypes.RandaoMixes(mixesArr)
|
||||
mixes := customtypes.RandaoMixes{}
|
||||
mixes.SetFromBaseField(mixesArr)
|
||||
b.randaoMixes = &mixes
|
||||
b.markFieldAsDirty(randaoMixes)
|
||||
b.rebuildTrie[randaoMixes] = true
|
||||
@@ -31,24 +28,13 @@ func (b *BeaconState) SetRandaoMixes(val [][]byte) error {
|
||||
// UpdateRandaoMixesAtIndex for the beacon state. Updates the randao mixes
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val []byte) error {
|
||||
if uint64(len(b.randaoMixes)) <= idx {
|
||||
if b.randaoMixes.TotalLength() <= idx {
|
||||
return errors.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
mixes := b.randaoMixes
|
||||
if refs := b.sharedFieldReferences[randaoMixes].Refs(); refs > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
m := *b.randaoMixes
|
||||
mCopy := m
|
||||
mixes = &mCopy
|
||||
b.sharedFieldReferences[randaoMixes].MinusRef()
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
mixes[idx] = bytesutil.ToBytes32(val)
|
||||
b.randaoMixes = mixes
|
||||
b.randaoMixes.SetRootAtIndex(idx, bytesutil.ToBytes32(val))
|
||||
b.markFieldAsDirty(randaoMixes)
|
||||
b.addDirtyIndices(randaoMixes, []uint64{idx})
|
||||
|
||||
|
||||
@@ -36,10 +36,8 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconState) (state.BeaconState, error)
|
||||
return nil, errors.New("received nil state")
|
||||
}
|
||||
|
||||
var bRoots customtypes.BlockRoots
|
||||
for i, r := range st.BlockRoots {
|
||||
copy(bRoots[i][:], r)
|
||||
}
|
||||
bRoots := customtypes.SetFromSlice(st.BlockRoots)
|
||||
|
||||
var sRoots customtypes.StateRoots
|
||||
for i, r := range st.StateRoots {
|
||||
copy(sRoots[i][:], r)
|
||||
@@ -48,10 +46,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconState) (state.BeaconState, error)
|
||||
for i, r := range st.HistoricalRoots {
|
||||
copy(hRoots[i][:], r)
|
||||
}
|
||||
var mixes customtypes.RandaoMixes
|
||||
for i, m := range st.RandaoMixes {
|
||||
copy(mixes[i][:], m)
|
||||
}
|
||||
mixes := customtypes.SetFromSliceRandao(st.RandaoMixes)
|
||||
|
||||
fieldCount := params.BeaconConfig().BeaconStateFieldCount
|
||||
b := &BeaconState{
|
||||
@@ -60,7 +55,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconState) (state.BeaconState, error)
|
||||
slot: st.Slot,
|
||||
fork: st.Fork,
|
||||
latestBlockHeader: st.LatestBlockHeader,
|
||||
blockRoots: &bRoots,
|
||||
blockRoots: bRoots,
|
||||
stateRoots: &sRoots,
|
||||
historicalRoots: hRoots,
|
||||
eth1Data: st.Eth1Data,
|
||||
@@ -68,7 +63,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconState) (state.BeaconState, error)
|
||||
eth1DepositIndex: st.Eth1DepositIndex,
|
||||
validators: st.Validators,
|
||||
balances: st.Balances,
|
||||
randaoMixes: &mixes,
|
||||
randaoMixes: mixes,
|
||||
slashings: st.Slashings,
|
||||
previousEpochAttestations: st.PreviousEpochAttestations,
|
||||
currentEpochAttestations: st.CurrentEpochAttestations,
|
||||
@@ -99,7 +94,6 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconState) (state.BeaconState, error)
|
||||
// Initialize field reference tracking for shared data.
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[previousEpochAttestations] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[currentEpochAttestations] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[slashings] = stateutil.NewRef(1)
|
||||
@@ -127,9 +121,9 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
slashings: b.slashings,
|
||||
|
||||
// Large arrays, infrequently changed, constant size.
|
||||
blockRoots: b.blockRoots,
|
||||
blockRoots: b.blockRoots.Copy(),
|
||||
stateRoots: b.stateRoots,
|
||||
randaoMixes: b.randaoMixes,
|
||||
randaoMixes: b.randaoMixes.Copy(),
|
||||
previousEpochAttestations: b.previousEpochAttestations,
|
||||
currentEpochAttestations: b.currentEpochAttestations,
|
||||
eth1DataVotes: b.eth1DataVotes,
|
||||
@@ -211,6 +205,9 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
}
|
||||
|
||||
}
|
||||
b.blockRoots.MinusRef()
|
||||
b.randaoMixes.MinusRef()
|
||||
|
||||
for i := 0; i < fieldCount; i++ {
|
||||
field := types.FieldIndex(i)
|
||||
delete(b.stateFieldLeaves, field)
|
||||
|
||||
@@ -76,9 +76,8 @@ func (b *BeaconState) BlockRootAtIndex(idx uint64) ([]byte, error) {
|
||||
// input index value.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) blockRootAtIndex(idx uint64) ([32]byte, error) {
|
||||
if uint64(len(b.blockRoots)) <= idx {
|
||||
if b.blockRoots.TotalLength() <= idx {
|
||||
return [32]byte{}, fmt.Errorf("index %d out of range", idx)
|
||||
}
|
||||
|
||||
return b.blockRoots[idx], nil
|
||||
return b.blockRoots.RootAtIndex(idx), nil
|
||||
}
|
||||
|
||||
@@ -37,11 +37,10 @@ func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([]byte, error) {
|
||||
// input index value.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) randaoMixAtIndex(idx uint64) ([32]byte, error) {
|
||||
if uint64(len(b.randaoMixes)) <= idx {
|
||||
if b.randaoMixes.TotalLength() <= idx {
|
||||
return [32]byte{}, fmt.Errorf("index %d out of range", idx)
|
||||
}
|
||||
|
||||
return b.randaoMixes[idx], nil
|
||||
return b.randaoMixes.RootAtIndex(idx), nil
|
||||
}
|
||||
|
||||
// RandaoMixesLength returns the length of the randao mixes slice.
|
||||
@@ -63,5 +62,5 @@ func (b *BeaconState) randaoMixesLength() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
return len(b.randaoMixes)
|
||||
return int(b.randaoMixes.TotalLength()) // lint:ignore uintcast- ajhdjhd
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
|
||||
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
@@ -25,14 +24,12 @@ func (b *BeaconState) SetBlockRoots(val [][]byte) error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[blockRoots].MinusRef()
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
|
||||
var rootsArr [fieldparams.BlockRootsLength][32]byte
|
||||
for i := 0; i < len(rootsArr); i++ {
|
||||
copy(rootsArr[i][:], val[i])
|
||||
}
|
||||
roots := customtypes.BlockRoots(rootsArr)
|
||||
roots := customtypes.BlockRoots{}
|
||||
roots.SetFromBaseField(rootsArr)
|
||||
b.blockRoots = &roots
|
||||
b.markFieldAsDirty(blockRoots)
|
||||
b.rebuildTrie[blockRoots] = true
|
||||
@@ -42,24 +39,13 @@ func (b *BeaconState) SetBlockRoots(val [][]byte) error {
|
||||
// UpdateBlockRootAtIndex for the beacon state. Updates the block root
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateBlockRootAtIndex(idx uint64, blockRoot [32]byte) error {
|
||||
if uint64(len(b.blockRoots)) <= idx {
|
||||
if b.blockRoots.TotalLength() <= idx {
|
||||
return fmt.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
r := b.blockRoots
|
||||
if ref := b.sharedFieldReferences[blockRoots]; ref.Refs() > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
roots := *b.blockRoots
|
||||
rootsCopy := roots
|
||||
r = &rootsCopy
|
||||
ref.MinusRef()
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
r[idx] = blockRoot
|
||||
b.blockRoots = r
|
||||
b.blockRoots.SetRootAtIndex(idx, blockRoot)
|
||||
|
||||
b.markFieldAsDirty(blockRoots)
|
||||
b.addDirtyIndices(blockRoots, []uint64{idx})
|
||||
|
||||
@@ -3,7 +3,6 @@ package v2
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
)
|
||||
@@ -14,14 +13,12 @@ func (b *BeaconState) SetRandaoMixes(val [][]byte) error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[randaoMixes].MinusRef()
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
|
||||
var mixesArr [fieldparams.RandaoMixesLength][32]byte
|
||||
for i := 0; i < len(mixesArr); i++ {
|
||||
copy(mixesArr[i][:], val[i])
|
||||
}
|
||||
mixes := customtypes.RandaoMixes(mixesArr)
|
||||
mixes := customtypes.RandaoMixes{}
|
||||
mixes.SetFromBaseField(mixesArr)
|
||||
b.randaoMixes = &mixes
|
||||
b.markFieldAsDirty(randaoMixes)
|
||||
b.rebuildTrie[randaoMixes] = true
|
||||
@@ -31,24 +28,13 @@ func (b *BeaconState) SetRandaoMixes(val [][]byte) error {
|
||||
// UpdateRandaoMixesAtIndex for the beacon state. Updates the randao mixes
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val []byte) error {
|
||||
if uint64(len(b.randaoMixes)) <= idx {
|
||||
if b.randaoMixes.TotalLength() <= idx {
|
||||
return errors.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
mixes := b.randaoMixes
|
||||
if refs := b.sharedFieldReferences[randaoMixes].Refs(); refs > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
m := *b.randaoMixes
|
||||
mCopy := m
|
||||
mixes = &mCopy
|
||||
b.sharedFieldReferences[randaoMixes].MinusRef()
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
mixes[idx] = bytesutil.ToBytes32(val)
|
||||
b.randaoMixes = mixes
|
||||
b.randaoMixes.SetRootAtIndex(idx, bytesutil.ToBytes32(val))
|
||||
b.markFieldAsDirty(randaoMixes)
|
||||
b.addDirtyIndices(randaoMixes, []uint64{idx})
|
||||
|
||||
|
||||
@@ -35,10 +35,8 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateAltair) (*BeaconState, error
|
||||
return nil, errors.New("received nil state")
|
||||
}
|
||||
|
||||
var bRoots customtypes.BlockRoots
|
||||
for i, r := range st.BlockRoots {
|
||||
bRoots[i] = bytesutil.ToBytes32(r)
|
||||
}
|
||||
bRoots := customtypes.SetFromSlice(st.BlockRoots)
|
||||
|
||||
var sRoots customtypes.StateRoots
|
||||
for i, r := range st.StateRoots {
|
||||
sRoots[i] = bytesutil.ToBytes32(r)
|
||||
@@ -47,10 +45,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateAltair) (*BeaconState, error
|
||||
for i, r := range st.HistoricalRoots {
|
||||
hRoots[i] = bytesutil.ToBytes32(r)
|
||||
}
|
||||
var mixes customtypes.RandaoMixes
|
||||
for i, m := range st.RandaoMixes {
|
||||
mixes[i] = bytesutil.ToBytes32(m)
|
||||
}
|
||||
mixes := customtypes.SetFromSliceRandao(st.RandaoMixes)
|
||||
|
||||
fieldCount := params.BeaconConfig().BeaconStateAltairFieldCount
|
||||
b := &BeaconState{
|
||||
@@ -59,7 +54,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateAltair) (*BeaconState, error
|
||||
slot: st.Slot,
|
||||
fork: st.Fork,
|
||||
latestBlockHeader: st.LatestBlockHeader,
|
||||
blockRoots: &bRoots,
|
||||
blockRoots: bRoots,
|
||||
stateRoots: &sRoots,
|
||||
historicalRoots: hRoots,
|
||||
eth1Data: st.Eth1Data,
|
||||
@@ -67,7 +62,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateAltair) (*BeaconState, error
|
||||
eth1DepositIndex: st.Eth1DepositIndex,
|
||||
validators: st.Validators,
|
||||
balances: st.Balances,
|
||||
randaoMixes: &mixes,
|
||||
randaoMixes: mixes,
|
||||
slashings: st.Slashings,
|
||||
previousEpochParticipation: st.PreviousEpochParticipation,
|
||||
currentEpochParticipation: st.CurrentEpochParticipation,
|
||||
@@ -101,7 +96,6 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateAltair) (*BeaconState, error
|
||||
// Initialize field reference tracking for shared data.
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[previousEpochParticipationBits] = stateutil.NewRef(1) // New in Altair.
|
||||
b.sharedFieldReferences[currentEpochParticipationBits] = stateutil.NewRef(1) // New in Altair.
|
||||
b.sharedFieldReferences[slashings] = stateutil.NewRef(1)
|
||||
@@ -128,9 +122,9 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
eth1DepositIndex: b.eth1DepositIndex,
|
||||
|
||||
// Large arrays, infrequently changed, constant size.
|
||||
blockRoots: b.blockRoots,
|
||||
blockRoots: b.blockRoots.Copy(),
|
||||
stateRoots: b.stateRoots,
|
||||
randaoMixes: b.randaoMixes,
|
||||
randaoMixes: b.randaoMixes.Copy(),
|
||||
slashings: b.slashings,
|
||||
eth1DataVotes: b.eth1DataVotes,
|
||||
|
||||
@@ -215,6 +209,8 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
b.stateFieldLeaves[field].FieldReference().MinusRef()
|
||||
}
|
||||
}
|
||||
b.blockRoots.DecreaseRef()
|
||||
b.randaoMixes.DecreaseRef()
|
||||
for i := 0; i < fieldCount; i++ {
|
||||
field := types.FieldIndex(i)
|
||||
delete(b.stateFieldLeaves, field)
|
||||
|
||||
@@ -76,9 +76,8 @@ func (b *BeaconState) BlockRootAtIndex(idx uint64) ([]byte, error) {
|
||||
// input index value.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) blockRootAtIndex(idx uint64) ([32]byte, error) {
|
||||
if uint64(len(b.blockRoots)) <= idx {
|
||||
if b.blockRoots.TotalLength() <= idx {
|
||||
return [32]byte{}, fmt.Errorf("index %d out of range", idx)
|
||||
}
|
||||
|
||||
return b.blockRoots[idx], nil
|
||||
return b.blockRoots.RootAtIndex(idx), nil
|
||||
}
|
||||
|
||||
@@ -37,11 +37,10 @@ func (b *BeaconState) RandaoMixAtIndex(idx uint64) ([]byte, error) {
|
||||
// input index value.
|
||||
// This assumes that a lock is already held on BeaconState.
|
||||
func (b *BeaconState) randaoMixAtIndex(idx uint64) ([32]byte, error) {
|
||||
if uint64(len(b.randaoMixes)) <= idx {
|
||||
if b.randaoMixes.TotalLength() <= idx {
|
||||
return [32]byte{}, fmt.Errorf("index %d out of range", idx)
|
||||
}
|
||||
|
||||
return b.randaoMixes[idx], nil
|
||||
return b.randaoMixes.RootAtIndex(idx), nil
|
||||
}
|
||||
|
||||
// RandaoMixesLength returns the length of the randao mixes slice.
|
||||
@@ -63,5 +62,5 @@ func (b *BeaconState) randaoMixesLength() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
return len(b.randaoMixes)
|
||||
return int(b.randaoMixes.TotalLength()) // lint:ignore uintcast- ajhdjhd
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
|
||||
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1"
|
||||
)
|
||||
@@ -25,14 +24,12 @@ func (b *BeaconState) SetBlockRoots(val [][]byte) error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[blockRoots].MinusRef()
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
|
||||
var rootsArr [fieldparams.BlockRootsLength][fieldparams.RootLength]byte
|
||||
for i := 0; i < len(rootsArr); i++ {
|
||||
copy(rootsArr[i][:], val[i])
|
||||
}
|
||||
roots := customtypes.BlockRoots(rootsArr)
|
||||
roots := customtypes.BlockRoots{}
|
||||
roots.SetFromBaseField(rootsArr)
|
||||
b.blockRoots = &roots
|
||||
b.markFieldAsDirty(blockRoots)
|
||||
b.rebuildTrie[blockRoots] = true
|
||||
@@ -42,24 +39,13 @@ func (b *BeaconState) SetBlockRoots(val [][]byte) error {
|
||||
// UpdateBlockRootAtIndex for the beacon state. Updates the block root
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateBlockRootAtIndex(idx uint64, blockRoot [32]byte) error {
|
||||
if uint64(len(b.blockRoots)) <= idx {
|
||||
if b.blockRoots.TotalLength() <= idx {
|
||||
return fmt.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
r := b.blockRoots
|
||||
if ref := b.sharedFieldReferences[blockRoots]; ref.Refs() > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
roots := *b.blockRoots
|
||||
rootsCopy := roots
|
||||
r = &rootsCopy
|
||||
ref.MinusRef()
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
r[idx] = blockRoot
|
||||
b.blockRoots = r
|
||||
b.blockRoots.SetRootAtIndex(idx, blockRoot)
|
||||
|
||||
b.markFieldAsDirty(blockRoots)
|
||||
b.addDirtyIndices(blockRoots, []uint64{idx})
|
||||
|
||||
@@ -3,7 +3,6 @@ package v3
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
customtypes "github.com/prysmaticlabs/prysm/beacon-chain/state/state-native/custom-types"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
)
|
||||
@@ -14,14 +13,12 @@ func (b *BeaconState) SetRandaoMixes(val [][]byte) error {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.sharedFieldReferences[randaoMixes].MinusRef()
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
|
||||
var mixesArr [fieldparams.RandaoMixesLength][fieldparams.RootLength]byte
|
||||
var mixesArr [fieldparams.RandaoMixesLength][32]byte
|
||||
for i := 0; i < len(mixesArr); i++ {
|
||||
copy(mixesArr[i][:], val[i])
|
||||
}
|
||||
mixes := customtypes.RandaoMixes(mixesArr)
|
||||
mixes := customtypes.RandaoMixes{}
|
||||
mixes.SetFromBaseField(mixesArr)
|
||||
b.randaoMixes = &mixes
|
||||
b.markFieldAsDirty(randaoMixes)
|
||||
b.rebuildTrie[randaoMixes] = true
|
||||
@@ -31,24 +28,13 @@ func (b *BeaconState) SetRandaoMixes(val [][]byte) error {
|
||||
// UpdateRandaoMixesAtIndex for the beacon state. Updates the randao mixes
|
||||
// at a specific index to a new value.
|
||||
func (b *BeaconState) UpdateRandaoMixesAtIndex(idx uint64, val []byte) error {
|
||||
if uint64(len(b.randaoMixes)) <= idx {
|
||||
if b.randaoMixes.TotalLength() <= idx {
|
||||
return errors.Errorf("invalid index provided %d", idx)
|
||||
}
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
mixes := b.randaoMixes
|
||||
if refs := b.sharedFieldReferences[randaoMixes].Refs(); refs > 1 {
|
||||
// Copy elements in underlying array by reference.
|
||||
m := *b.randaoMixes
|
||||
mCopy := m
|
||||
mixes = &mCopy
|
||||
b.sharedFieldReferences[randaoMixes].MinusRef()
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
mixes[idx] = bytesutil.ToBytes32(val)
|
||||
b.randaoMixes = mixes
|
||||
b.randaoMixes.SetRootAtIndex(idx, bytesutil.ToBytes32(val))
|
||||
b.markFieldAsDirty(randaoMixes)
|
||||
b.addDirtyIndices(randaoMixes, []uint64{idx})
|
||||
|
||||
|
||||
@@ -36,10 +36,8 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateBellatrix) (state.BeaconStat
|
||||
return nil, errors.New("received nil state")
|
||||
}
|
||||
|
||||
var bRoots customtypes.BlockRoots
|
||||
for i, r := range st.BlockRoots {
|
||||
bRoots[i] = bytesutil.ToBytes32(r)
|
||||
}
|
||||
bRoots := customtypes.SetFromSlice(st.BlockRoots)
|
||||
|
||||
var sRoots customtypes.StateRoots
|
||||
for i, r := range st.StateRoots {
|
||||
sRoots[i] = bytesutil.ToBytes32(r)
|
||||
@@ -48,10 +46,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateBellatrix) (state.BeaconStat
|
||||
for i, r := range st.HistoricalRoots {
|
||||
hRoots[i] = bytesutil.ToBytes32(r)
|
||||
}
|
||||
var mixes customtypes.RandaoMixes
|
||||
for i, m := range st.RandaoMixes {
|
||||
mixes[i] = bytesutil.ToBytes32(m)
|
||||
}
|
||||
mixes := customtypes.SetFromSliceRandao(st.RandaoMixes)
|
||||
|
||||
fieldCount := params.BeaconConfig().BeaconStateBellatrixFieldCount
|
||||
b := &BeaconState{
|
||||
@@ -60,7 +55,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateBellatrix) (state.BeaconStat
|
||||
slot: st.Slot,
|
||||
fork: st.Fork,
|
||||
latestBlockHeader: st.LatestBlockHeader,
|
||||
blockRoots: &bRoots,
|
||||
blockRoots: bRoots,
|
||||
stateRoots: &sRoots,
|
||||
historicalRoots: hRoots,
|
||||
eth1Data: st.Eth1Data,
|
||||
@@ -68,7 +63,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateBellatrix) (state.BeaconStat
|
||||
eth1DepositIndex: st.Eth1DepositIndex,
|
||||
validators: st.Validators,
|
||||
balances: st.Balances,
|
||||
randaoMixes: &mixes,
|
||||
randaoMixes: mixes,
|
||||
slashings: st.Slashings,
|
||||
previousEpochParticipation: st.PreviousEpochParticipation,
|
||||
currentEpochParticipation: st.CurrentEpochParticipation,
|
||||
@@ -101,9 +96,7 @@ func InitializeFromProtoUnsafe(st *ethpb.BeaconStateBellatrix) (state.BeaconStat
|
||||
}
|
||||
|
||||
// Initialize field reference tracking for shared data.
|
||||
b.sharedFieldReferences[randaoMixes] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[stateRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[blockRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[previousEpochParticipationBits] = stateutil.NewRef(1) // New in Altair.
|
||||
b.sharedFieldReferences[currentEpochParticipationBits] = stateutil.NewRef(1) // New in Altair.
|
||||
b.sharedFieldReferences[slashings] = stateutil.NewRef(1)
|
||||
@@ -130,9 +123,9 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
eth1DepositIndex: b.eth1DepositIndex,
|
||||
|
||||
// Large arrays, infrequently changed, constant size.
|
||||
randaoMixes: b.randaoMixes,
|
||||
randaoMixes: b.randaoMixes.Copy(),
|
||||
stateRoots: b.stateRoots,
|
||||
blockRoots: b.blockRoots,
|
||||
blockRoots: b.blockRoots.Copy(),
|
||||
slashings: b.slashings,
|
||||
eth1DataVotes: b.eth1DataVotes,
|
||||
|
||||
@@ -208,6 +201,7 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
state.StateCount.Inc()
|
||||
// Finalizer runs when dst is being destroyed in garbage collection.
|
||||
runtime.SetFinalizer(dst, func(b *BeaconState) {
|
||||
@@ -217,6 +211,9 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
b.stateFieldLeaves[field].FieldReference().MinusRef()
|
||||
}
|
||||
}
|
||||
b.blockRoots.DecreaseRef()
|
||||
b.randaoMixes.DecreaseRef()
|
||||
|
||||
for i := 0; i < fieldCount; i++ {
|
||||
field := types.FieldIndex(i)
|
||||
delete(b.stateFieldLeaves, field)
|
||||
|
||||
@@ -49,30 +49,29 @@ type Service struct {
|
||||
synced *abool.AtomicBool
|
||||
chainStarted *abool.AtomicBool
|
||||
counter *ratecounter.RateCounter
|
||||
genesisChan chan time.Time
|
||||
}
|
||||
|
||||
// NewService configures the initial sync service responsible for bringing the node up to the
|
||||
// latest head of the blockchain.
|
||||
func NewService(ctx context.Context, cfg *Config) *Service {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
s := &Service{
|
||||
return &Service{
|
||||
cfg: cfg,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
synced: abool.New(),
|
||||
chainStarted: abool.New(),
|
||||
counter: ratecounter.NewRateCounter(counterSeconds * time.Second),
|
||||
genesisChan: make(chan time.Time),
|
||||
}
|
||||
go s.waitForStateInitialization()
|
||||
return s
|
||||
}
|
||||
|
||||
// Start the initial sync service.
|
||||
func (s *Service) Start() {
|
||||
// Wait for state initialized event.
|
||||
genesis := <-s.genesisChan
|
||||
genesis, err := s.waitForStateInitialization()
|
||||
if err != nil {
|
||||
log.WithError(err).Fatal("Failed to wait for state initialization.")
|
||||
return
|
||||
}
|
||||
if genesis.IsZero() {
|
||||
log.Debug("Exiting Initial Sync Service")
|
||||
return
|
||||
@@ -180,9 +179,10 @@ func (s *Service) waitForMinimumPeers() {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Return error
|
||||
// waitForStateInitialization makes sure that beacon node is ready to be accessed: it is either
|
||||
// already properly configured or system waits up until state initialized event is triggered.
|
||||
func (s *Service) waitForStateInitialization() {
|
||||
func (s *Service) waitForStateInitialization() (time.Time, error) {
|
||||
// Wait for state to be initialized.
|
||||
stateChannel := make(chan *feed.Event, 1)
|
||||
stateSub := s.cfg.StateNotifier.StateFeed().Subscribe(stateChannel)
|
||||
@@ -198,19 +198,14 @@ func (s *Service) waitForStateInitialization() {
|
||||
continue
|
||||
}
|
||||
log.WithField("starttime", data.StartTime).Debug("Received state initialized event")
|
||||
s.genesisChan <- data.StartTime
|
||||
return
|
||||
return data.StartTime, nil
|
||||
}
|
||||
case <-s.ctx.Done():
|
||||
log.Debug("Context closed, exiting goroutine")
|
||||
// Send a zero time in the event we are exiting.
|
||||
s.genesisChan <- time.Time{}
|
||||
return
|
||||
return time.Time{}, errors.New("context closed, exiting goroutine")
|
||||
case err := <-stateSub.Err():
|
||||
log.WithError(err).Error("Subscription to state notifier failed")
|
||||
// Send a zero time in the event we are exiting.
|
||||
s.genesisChan <- time.Time{}
|
||||
return
|
||||
return time.Time{}, errors.Wrap(err, "subscription to state notifier failed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,11 +168,7 @@ func TestService_InitStartStop(t *testing.T) {
|
||||
Chain: mc,
|
||||
StateNotifier: notifier,
|
||||
})
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
assert.NotNil(t, s)
|
||||
if tt.methodRuns != nil {
|
||||
tt.methodRuns(notifier.StateFeed())
|
||||
}
|
||||
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
@@ -181,6 +177,11 @@ func TestService_InitStartStop(t *testing.T) {
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
if tt.methodRuns != nil {
|
||||
tt.methodRuns(notifier.StateFeed())
|
||||
}
|
||||
|
||||
go func() {
|
||||
// Allow to exit from test (on no head loop waiting for head is started).
|
||||
// In most tests, this is redundant, as Start() already exited.
|
||||
@@ -207,7 +208,6 @@ func TestService_waitForStateInitialization(t *testing.T) {
|
||||
synced: abool.New(),
|
||||
chainStarted: abool.New(),
|
||||
counter: ratecounter.NewRateCounter(counterSeconds * time.Second),
|
||||
genesisChan: make(chan time.Time),
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -221,9 +221,8 @@ func TestService_waitForStateInitialization(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
go s.waitForStateInitialization()
|
||||
currTime := <-s.genesisChan
|
||||
assert.Equal(t, true, currTime.IsZero())
|
||||
_, err := s.waitForStateInitialization()
|
||||
assert.ErrorContains(t, "context closed", err)
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
@@ -236,8 +235,6 @@ func TestService_waitForStateInitialization(t *testing.T) {
|
||||
t.Fatalf("Test should have exited by now, timed out")
|
||||
}
|
||||
assert.LogsContain(t, hook, "Waiting for state to be initialized")
|
||||
assert.LogsContain(t, hook, "Context closed, exiting goroutine")
|
||||
assert.LogsDoNotContain(t, hook, "Subscription to state notifier failed")
|
||||
})
|
||||
|
||||
t.Run("no state and state init event received", func(t *testing.T) {
|
||||
@@ -251,8 +248,9 @@ func TestService_waitForStateInitialization(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
go s.waitForStateInitialization()
|
||||
receivedGenesisTime = <-s.genesisChan
|
||||
var err error
|
||||
receivedGenesisTime, err = s.waitForStateInitialization()
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, false, receivedGenesisTime.IsZero())
|
||||
wg.Done()
|
||||
}()
|
||||
@@ -281,7 +279,6 @@ func TestService_waitForStateInitialization(t *testing.T) {
|
||||
assert.LogsContain(t, hook, "Event feed data is not type *statefeed.InitializedData")
|
||||
assert.LogsContain(t, hook, "Waiting for state to be initialized")
|
||||
assert.LogsContain(t, hook, "Received state initialized event")
|
||||
assert.LogsDoNotContain(t, hook, "Context closed, exiting goroutine")
|
||||
})
|
||||
|
||||
t.Run("no state and state init event received and service start", func(t *testing.T) {
|
||||
@@ -296,7 +293,8 @@ func TestService_waitForStateInitialization(t *testing.T) {
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
s.waitForStateInitialization()
|
||||
_, err := s.waitForStateInitialization()
|
||||
require.NoError(t, err)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
@@ -321,7 +319,6 @@ func TestService_waitForStateInitialization(t *testing.T) {
|
||||
}
|
||||
assert.LogsContain(t, hook, "Waiting for state to be initialized")
|
||||
assert.LogsContain(t, hook, "Received state initialized event")
|
||||
assert.LogsDoNotContain(t, hook, "Context closed, exiting goroutine")
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -154,6 +154,7 @@ func NewService(ctx context.Context, opts ...Option) *Service {
|
||||
}
|
||||
r.subHandler = newSubTopicHandler()
|
||||
r.rateLimiter = newRateLimiter(r.cfg.p2p)
|
||||
r.initCaches()
|
||||
|
||||
go r.registerHandlers()
|
||||
go r.verifierRoutine()
|
||||
@@ -163,8 +164,6 @@ func NewService(ctx context.Context, opts ...Option) *Service {
|
||||
|
||||
// Start the regular sync service.
|
||||
func (s *Service) Start() {
|
||||
s.initCaches()
|
||||
|
||||
s.cfg.p2p.AddConnectionHandler(s.reValidatePeer, s.sendGoodbye)
|
||||
s.cfg.p2p.AddDisconnectionHandler(func(_ context.Context, _ peer.ID) error {
|
||||
// no-op
|
||||
|
||||
@@ -63,7 +63,10 @@ container_image(
|
||||
container_bundle(
|
||||
name = "image_bundle",
|
||||
images = {
|
||||
"gcr.io/prysmaticlabs/prysm/beacon-chain:trie-debug": ":image_with_creation_time",
|
||||
"gcr.io/prysmaticlabs/prysm/beacon-chain:latest": ":image_with_creation_time",
|
||||
"gcr.io/prysmaticlabs/prysm/beacon-chain:{DOCKER_TAG}": ":image_with_creation_time",
|
||||
"index.docker.io/prysmaticlabs/prysm-beacon-chain:latest": ":image_with_creation_time",
|
||||
"index.docker.io/prysmaticlabs/prysm-beacon-chain:{DOCKER_TAG}": ":image_with_creation_time",
|
||||
},
|
||||
tags = ["manual"],
|
||||
visibility = ["//beacon-chain:__pkg__"],
|
||||
|
||||
@@ -28,7 +28,6 @@ var Commands = &cli.Command{
|
||||
flags.WalletPasswordFileFlag,
|
||||
flags.DeletePublicKeysFlag,
|
||||
features.Mainnet,
|
||||
features.PyrmontTestnet,
|
||||
features.PraterTestnet,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
@@ -62,7 +61,6 @@ var Commands = &cli.Command{
|
||||
flags.GrpcRetriesFlag,
|
||||
flags.GrpcRetryDelayFlag,
|
||||
features.Mainnet,
|
||||
features.PyrmontTestnet,
|
||||
features.PraterTestnet,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
@@ -93,7 +91,6 @@ var Commands = &cli.Command{
|
||||
flags.BackupPublicKeysFlag,
|
||||
flags.BackupPasswordFile,
|
||||
features.Mainnet,
|
||||
features.PyrmontTestnet,
|
||||
features.PraterTestnet,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
@@ -121,7 +118,6 @@ var Commands = &cli.Command{
|
||||
flags.AccountPasswordFileFlag,
|
||||
flags.ImportPrivateKeyFileFlag,
|
||||
features.Mainnet,
|
||||
features.PyrmontTestnet,
|
||||
features.PraterTestnet,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
@@ -155,7 +151,6 @@ var Commands = &cli.Command{
|
||||
flags.GrpcRetryDelayFlag,
|
||||
flags.ExitAllFlag,
|
||||
features.Mainnet,
|
||||
features.PyrmontTestnet,
|
||||
features.PraterTestnet,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
|
||||
@@ -22,7 +22,6 @@ var Commands = &cli.Command{
|
||||
cmd.DataDirFlag,
|
||||
flags.SlashingProtectionExportDirFlag,
|
||||
features.Mainnet,
|
||||
features.PyrmontTestnet,
|
||||
features.PraterTestnet,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
@@ -47,7 +46,6 @@ var Commands = &cli.Command{
|
||||
cmd.DataDirFlag,
|
||||
flags.SlashingProtectionJSONFileFlag,
|
||||
features.Mainnet,
|
||||
features.PyrmontTestnet,
|
||||
features.PraterTestnet,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
|
||||
@@ -34,7 +34,6 @@ var Commands = &cli.Command{
|
||||
flags.Mnemonic25thWordFileFlag,
|
||||
flags.SkipMnemonic25thWordCheckFlag,
|
||||
features.Mainnet,
|
||||
features.PyrmontTestnet,
|
||||
features.PraterTestnet,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
@@ -64,7 +63,6 @@ var Commands = &cli.Command{
|
||||
flags.RemoteSignerKeyPathFlag,
|
||||
flags.RemoteSignerCACertPathFlag,
|
||||
features.Mainnet,
|
||||
features.PyrmontTestnet,
|
||||
features.PraterTestnet,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
@@ -93,7 +91,6 @@ var Commands = &cli.Command{
|
||||
flags.Mnemonic25thWordFileFlag,
|
||||
flags.SkipMnemonic25thWordCheckFlag,
|
||||
features.Mainnet,
|
||||
features.PyrmontTestnet,
|
||||
features.PraterTestnet,
|
||||
cmd.AcceptTosFlag,
|
||||
}),
|
||||
|
||||
@@ -35,9 +35,6 @@ const disabledFeatureFlag = "Disabled feature flag"
|
||||
|
||||
// Flags is a struct to represent which features the client will perform on runtime.
|
||||
type Flags struct {
|
||||
// Testnet Flags.
|
||||
PyrmontTestnet bool // PyrmontTestnet defines the flag through which we can enable the node to run on the Pyrmont testnet.
|
||||
|
||||
// Feature related flags.
|
||||
RemoteSlasherProtection bool // RemoteSlasherProtection utilizes a beacon node with --slasher mode for validator slashing protection.
|
||||
WriteSSZStateTransitions bool // WriteSSZStateTransitions to tmp directory.
|
||||
@@ -121,13 +118,8 @@ func InitWithReset(c *Flags) func() {
|
||||
}
|
||||
|
||||
// configureTestnet sets the config according to specified testnet flag
|
||||
func configureTestnet(ctx *cli.Context, cfg *Flags) {
|
||||
if ctx.Bool(PyrmontTestnet.Name) {
|
||||
log.Warn("Running on Pyrmont Testnet")
|
||||
params.UsePyrmontConfig()
|
||||
params.UsePyrmontNetworkConfig()
|
||||
cfg.PyrmontTestnet = true
|
||||
} else if ctx.Bool(PraterTestnet.Name) {
|
||||
func configureTestnet(ctx *cli.Context) {
|
||||
if ctx.Bool(PraterTestnet.Name) {
|
||||
log.Warn("Running on the Prater Testnet")
|
||||
params.UsePraterConfig()
|
||||
params.UsePraterNetworkConfig()
|
||||
@@ -145,7 +137,7 @@ func ConfigureBeaconChain(ctx *cli.Context) {
|
||||
if ctx.Bool(devModeFlag.Name) {
|
||||
enableDevModeFlags(ctx)
|
||||
}
|
||||
configureTestnet(ctx, cfg)
|
||||
configureTestnet(ctx)
|
||||
|
||||
if ctx.Bool(writeSSZStateTransitionsFlag.Name) {
|
||||
logEnabled(writeSSZStateTransitionsFlag)
|
||||
@@ -240,7 +232,7 @@ func ConfigureBeaconChain(ctx *cli.Context) {
|
||||
func ConfigureValidator(ctx *cli.Context) {
|
||||
complainOnDeprecatedFlags(ctx)
|
||||
cfg := &Flags{}
|
||||
configureTestnet(ctx, cfg)
|
||||
configureTestnet(ctx)
|
||||
if ctx.Bool(enableExternalSlasherProtectionFlag.Name) {
|
||||
log.Fatal(
|
||||
"Remote slashing protection has currently been disabled in Prysm due to safety concerns. " +
|
||||
|
||||
@@ -11,41 +11,41 @@ import (
|
||||
func TestInitFeatureConfig(t *testing.T) {
|
||||
defer Init(&Flags{})
|
||||
cfg := &Flags{
|
||||
PyrmontTestnet: true,
|
||||
EnablePeerScorer: true,
|
||||
}
|
||||
Init(cfg)
|
||||
c := Get()
|
||||
assert.Equal(t, true, c.PyrmontTestnet)
|
||||
assert.Equal(t, true, c.EnablePeerScorer)
|
||||
|
||||
// Reset back to false for the follow up tests.
|
||||
cfg = &Flags{PyrmontTestnet: false}
|
||||
cfg = &Flags{RemoteSlasherProtection: false}
|
||||
Init(cfg)
|
||||
}
|
||||
|
||||
func TestInitWithReset(t *testing.T) {
|
||||
defer Init(&Flags{})
|
||||
Init(&Flags{
|
||||
PyrmontTestnet: true,
|
||||
EnablePeerScorer: true,
|
||||
})
|
||||
assert.Equal(t, true, Get().PyrmontTestnet)
|
||||
assert.Equal(t, true, Get().EnablePeerScorer)
|
||||
|
||||
// Overwrite previously set value (value that didn't come by default).
|
||||
resetCfg := InitWithReset(&Flags{
|
||||
PyrmontTestnet: false,
|
||||
EnablePeerScorer: false,
|
||||
})
|
||||
assert.Equal(t, false, Get().PyrmontTestnet)
|
||||
assert.Equal(t, false, Get().EnablePeerScorer)
|
||||
|
||||
// Reset must get to previously set configuration (not to default config values).
|
||||
resetCfg()
|
||||
assert.Equal(t, true, Get().PyrmontTestnet)
|
||||
assert.Equal(t, true, Get().EnablePeerScorer)
|
||||
}
|
||||
|
||||
func TestConfigureBeaconConfig(t *testing.T) {
|
||||
app := cli.App{}
|
||||
set := flag.NewFlagSet("test", 0)
|
||||
set.Bool(PyrmontTestnet.Name, true, "test")
|
||||
set.Bool(enablePeerScorer.Name, true, "test")
|
||||
context := cli.NewContext(&app, set, nil)
|
||||
ConfigureBeaconChain(context)
|
||||
c := Get()
|
||||
assert.Equal(t, true, c.PyrmontTestnet)
|
||||
assert.Equal(t, true, c.EnablePeerScorer)
|
||||
}
|
||||
|
||||
@@ -70,6 +70,11 @@ var (
|
||||
Usage: deprecatedUsage,
|
||||
Hidden: true,
|
||||
}
|
||||
deprecatedPyrmontTestnet = &cli.BoolFlag{
|
||||
Name: "pyrmont",
|
||||
Usage: deprecatedUsage,
|
||||
Hidden: true,
|
||||
}
|
||||
)
|
||||
|
||||
var deprecatedFlags = []cli.Flag{
|
||||
@@ -84,4 +89,5 @@ var deprecatedFlags = []cli.Flag{
|
||||
deprecatedDisableNextSlotStateCache,
|
||||
deprecatedAttestationAggregationStrategy,
|
||||
deprecatedForceOptMaxCoverAggregationStategy,
|
||||
deprecatedPyrmontTestnet,
|
||||
}
|
||||
|
||||
@@ -7,11 +7,6 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// PyrmontTestnet flag for the multiclient Ethereum consensus testnet.
|
||||
PyrmontTestnet = &cli.BoolFlag{
|
||||
Name: "pyrmont",
|
||||
Usage: "This defines the flag through which we can run on the Pyrmont Multiclient Testnet",
|
||||
}
|
||||
// PraterTestnet flag for the multiclient Ethereum consensus testnet.
|
||||
PraterTestnet = &cli.BoolFlag{
|
||||
Name: "prater",
|
||||
@@ -149,6 +144,7 @@ var devModeFlags = []cli.Flag{
|
||||
enablePeerScorer,
|
||||
enableVecHTR,
|
||||
enableForkChoiceDoublyLinkedTree,
|
||||
enableNativeState,
|
||||
}
|
||||
|
||||
// ValidatorFlags contains a list of all the feature flags that apply to the validator client.
|
||||
@@ -156,7 +152,6 @@ var ValidatorFlags = append(deprecatedFlags, []cli.Flag{
|
||||
writeWalletPasswordOnWebOnboarding,
|
||||
enableExternalSlasherProtectionFlag,
|
||||
disableAttestingHistoryDBCache,
|
||||
PyrmontTestnet,
|
||||
PraterTestnet,
|
||||
Mainnet,
|
||||
dynamicKeyReloadDebounceInterval,
|
||||
@@ -175,7 +170,6 @@ var BeaconChainFlags = append(deprecatedFlags, []cli.Flag{
|
||||
devModeFlag,
|
||||
writeSSZStateTransitionsFlag,
|
||||
disableGRPCConnectionLogging,
|
||||
PyrmontTestnet,
|
||||
PraterTestnet,
|
||||
Mainnet,
|
||||
enablePeerScorer,
|
||||
|
||||
@@ -13,7 +13,6 @@ go_library(
|
||||
"network_config.go",
|
||||
"testnet_e2e_config.go",
|
||||
"testnet_prater_config.go",
|
||||
"testnet_pyrmont_config.go",
|
||||
"testutils.go",
|
||||
"values.go",
|
||||
],
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
package params
|
||||
|
||||
import "math"
|
||||
|
||||
// UsePyrmontNetworkConfig uses the Pyrmont specific
|
||||
// network config.
|
||||
func UsePyrmontNetworkConfig() {
|
||||
cfg := BeaconNetworkConfig().Copy()
|
||||
cfg.ContractDeploymentBlock = 3743587
|
||||
cfg.BootstrapNodes = []string{
|
||||
"enr:-Ku4QOA5OGWObY8ep_x35NlGBEj7IuQULTjkgxC_0G1AszqGEA0Wn2RNlyLFx9zGTNB1gdFBA6ZDYxCgIza1uJUUOj4Dh2F0dG5ldHOIAAAAAAAAAACEZXRoMpDVTPWXAAAgCf__________gmlkgnY0gmlwhDQPSjiJc2VjcDI1NmsxoQM6yTQB6XGWYJbI7NZFBjp4Yb9AYKQPBhVrfUclQUobb4N1ZHCCIyg",
|
||||
"enr:-Ku4QOksdA2tabOGrfOOr6NynThMoio6Ggka2oDPqUuFeWCqcRM2alNb8778O_5bK95p3EFt0cngTUXm2H7o1jkSJ_8Dh2F0dG5ldHOIAAAAAAAAAACEZXRoMpDVTPWXAAAgCf__________gmlkgnY0gmlwhDaa13aJc2VjcDI1NmsxoQKdNQJvnohpf0VO0ZYCAJxGjT0uwJoAHbAiBMujGjK0SoN1ZHCCIyg",
|
||||
}
|
||||
OverrideBeaconNetworkConfig(cfg)
|
||||
}
|
||||
|
||||
// UsePyrmontConfig sets the main beacon chain
|
||||
// config for Pyrmont.
|
||||
func UsePyrmontConfig() {
|
||||
beaconConfig = PyrmontConfig()
|
||||
}
|
||||
|
||||
// PyrmontConfig defines the config for the
|
||||
// Pyrmont testnet.
|
||||
func PyrmontConfig() *BeaconChainConfig {
|
||||
cfg := MainnetConfig().Copy()
|
||||
cfg.MinGenesisTime = 1605700800
|
||||
cfg.GenesisDelay = 432000
|
||||
cfg.ConfigName = ConfigNames[Pyrmont]
|
||||
cfg.GenesisForkVersion = []byte{0x00, 0x00, 0x20, 0x09}
|
||||
cfg.AltairForkVersion = []byte{0x01, 0x00, 0x20, 0x09}
|
||||
cfg.AltairForkEpoch = 61650
|
||||
cfg.BellatrixForkVersion = []byte{0x02, 0x00, 0x20, 0x09}
|
||||
cfg.BellatrixForkEpoch = math.MaxUint64
|
||||
cfg.ShardingForkVersion = []byte{0x03, 0x00, 0x20, 0x09}
|
||||
cfg.ShardingForkEpoch = math.MaxUint64
|
||||
cfg.SecondsPerETH1Block = 14
|
||||
cfg.DepositChainID = 5
|
||||
cfg.DepositNetworkID = 5
|
||||
cfg.DepositContractAddress = "0x8c5fecdC472E27Bc447696F431E425D02dd46a8c"
|
||||
cfg.InitializeForkSchedule()
|
||||
return cfg
|
||||
}
|
||||
@@ -12,7 +12,6 @@ const (
|
||||
Mainnet ConfigName = iota
|
||||
Minimal
|
||||
EndToEnd
|
||||
Pyrmont
|
||||
Prater
|
||||
EndToEndMainnet
|
||||
)
|
||||
@@ -33,7 +32,6 @@ var ConfigNames = map[ConfigName]string{
|
||||
Mainnet: "mainnet",
|
||||
Minimal: "minimal",
|
||||
EndToEnd: "end-to-end",
|
||||
Pyrmont: "pyrmont",
|
||||
Prater: "prater",
|
||||
EndToEndMainnet: "end-to-end-mainnet",
|
||||
}
|
||||
@@ -42,7 +40,6 @@ var ConfigNames = map[ConfigName]string{
|
||||
var KnownConfigs = map[ConfigName]func() *BeaconChainConfig{
|
||||
Mainnet: MainnetConfig,
|
||||
Prater: PraterConfig,
|
||||
Pyrmont: PyrmontConfig,
|
||||
Minimal: MinimalSpecConfig,
|
||||
EndToEnd: E2ETestConfig,
|
||||
EndToEndMainnet: E2EMainnetTestConfig,
|
||||
|
||||
7
deps.bzl
7
deps.bzl
@@ -3756,6 +3756,13 @@ def prysm_deps():
|
||||
sum = "h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=",
|
||||
version = "v2.3.0",
|
||||
)
|
||||
go_repository(
|
||||
name = "com_github_uudashr_gocognit",
|
||||
importpath = "github.com/uudashr/gocognit",
|
||||
sum = "h1:rrSex7oHr3/pPLQ0xoWq108XMU8s678FJcQ+aSfOHa4=",
|
||||
version = "v1.0.5",
|
||||
)
|
||||
|
||||
go_repository(
|
||||
name = "com_github_valyala_bytebufferpool",
|
||||
importpath = "github.com/valyala/bytebufferpool",
|
||||
|
||||
1
go.mod
1
go.mod
@@ -77,6 +77,7 @@ require (
|
||||
github.com/trailofbits/go-mutexasserts v0.0.0-20200708152505-19999e7d3cef
|
||||
github.com/tyler-smith/go-bip39 v1.1.0
|
||||
github.com/urfave/cli/v2 v2.3.0
|
||||
github.com/uudashr/gocognit v1.0.5
|
||||
github.com/wealdtech/go-bytesutil v1.1.1
|
||||
github.com/wealdtech/go-eth2-util v1.6.3
|
||||
github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.3
|
||||
|
||||
3
go.sum
3
go.sum
@@ -1358,6 +1358,8 @@ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijb
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
github.com/uudashr/gocognit v1.0.5 h1:rrSex7oHr3/pPLQ0xoWq108XMU8s678FJcQ+aSfOHa4=
|
||||
github.com/uudashr/gocognit v1.0.5/go.mod h1:wgYz0mitoKOTysqxTDMOUXg+Jb5SvtihkfmugIZYpEA=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
@@ -1804,6 +1806,7 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w=
|
||||
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"unsafeptr": {
|
||||
"exclude_files": {
|
||||
"beacon-chain/state/state-native/custom-types/block_roots.go": "Needed for field management operations",
|
||||
"external/.*": "Unsafe third party code",
|
||||
"rules_go_work-.*": "Third party code"
|
||||
}
|
||||
@@ -170,5 +171,13 @@
|
||||
"rules_go_work-.*": "Third party code",
|
||||
".*_test\\.go": "Tests are ok"
|
||||
}
|
||||
},
|
||||
"gocognit": {
|
||||
"exclude_files": {
|
||||
"external/.*": "Third party code",
|
||||
"rules_go_work-.*": "Third party code",
|
||||
".*\\.pb.*.go": "Generated code is ok",
|
||||
".*generated\\.ssz\\.go": "Generated code is ok"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/config/params"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
@@ -173,6 +174,13 @@ func TestJsonMarshalUnmarshal(t *testing.T) {
|
||||
require.DeepEqual(t, [][]byte{[]byte("hi")}, payloadPb.Transactions)
|
||||
require.DeepEqual(t, [][]byte{[]byte("bye")}, payloadPb.Uncles)
|
||||
})
|
||||
t.Run("nil execution block", func(t *testing.T) {
|
||||
jsonPayload := (*enginev1.ExecutionBlock)(nil)
|
||||
enc, err := json.Marshal(jsonPayload)
|
||||
require.NoError(t, err)
|
||||
payloadPb := &enginev1.ExecutionBlock{}
|
||||
require.ErrorIs(t, hexutil.ErrEmptyString, json.Unmarshal(enc, payloadPb))
|
||||
})
|
||||
}
|
||||
|
||||
func TestPayloadIDBytes_MarshalUnmarshalJSON(t *testing.T) {
|
||||
|
||||
14
tools/analyzers/gocognit/BUILD.bazel
Normal file
14
tools/analyzers/gocognit/BUILD.bazel
Normal file
@@ -0,0 +1,14 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["analyzer.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/tools/analyzers/gocognit",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"@com_github_uudashr_gocognit//:go_default_library",
|
||||
"@org_golang_x_tools//go/analysis:go_default_library",
|
||||
"@org_golang_x_tools//go/analysis/passes/inspect:go_default_library",
|
||||
"@org_golang_x_tools//go/ast/inspector:go_default_library",
|
||||
],
|
||||
)
|
||||
BIN
tools/analyzers/gocognit/CognitiveComplexity.pdf
Normal file
BIN
tools/analyzers/gocognit/CognitiveComplexity.pdf
Normal file
Binary file not shown.
195
tools/analyzers/gocognit/README.md
Normal file
195
tools/analyzers/gocognit/README.md
Normal file
@@ -0,0 +1,195 @@
|
||||
> Copied from https://github.com/uudashr/gocognit/blob/5bf67146515e79acd2a8d5728deafa9d91ad48db/README.md
|
||||
> License: MIT
|
||||
|
||||
[](https://godoc.org/github.com/uudashr/gocognit)
|
||||
# Gocognit
|
||||
Gocognit calculates cognitive complexities of functions in Go source code. A measurement of how hard does the code is intuitively to understand.
|
||||
|
||||
## Understanding the complexity
|
||||
|
||||
Given code using `if` statement,
|
||||
```go
|
||||
func GetWords(number int) string {
|
||||
if number == 1 { // +1
|
||||
return "one"
|
||||
} else if number == 2 { // +1
|
||||
return "a couple"
|
||||
} else if number == 3 { // +1
|
||||
return "a few"
|
||||
} else { // +1
|
||||
return "lots"
|
||||
}
|
||||
} // Cognitive complexity = 4
|
||||
```
|
||||
|
||||
Above code can be refactored using `switch` statement,
|
||||
```go
|
||||
func GetWords(number int) string {
|
||||
switch number { // +1
|
||||
case 1:
|
||||
return "one"
|
||||
case 2:
|
||||
return "a couple"
|
||||
case 3:
|
||||
return "a few"
|
||||
default:
|
||||
return "lots"
|
||||
}
|
||||
} // Cognitive complexity = 1
|
||||
```
|
||||
|
||||
As you see above codes are the same, but the second code are easier to understand, that is why the cognitive complexity score are lower compare to the first one.
|
||||
|
||||
## Comparison with cyclometic complexity
|
||||
|
||||
### Example 1
|
||||
#### Cyclometic complexity
|
||||
```go
|
||||
func GetWords(number int) string { // +1
|
||||
switch number {
|
||||
case 1: // +1
|
||||
return "one"
|
||||
case 2: // +1
|
||||
return "a couple"
|
||||
case 3: // +1
|
||||
return "a few"
|
||||
default:
|
||||
return "lots"
|
||||
}
|
||||
} // Cyclomatic complexity = 4
|
||||
```
|
||||
|
||||
#### Cognitive complexity
|
||||
```go
|
||||
func GetWords(number int) string {
|
||||
switch number { // +1
|
||||
case 1:
|
||||
return "one"
|
||||
case 2:
|
||||
return "a couple"
|
||||
case 3:
|
||||
return "a few"
|
||||
default:
|
||||
return "lots"
|
||||
}
|
||||
} // Cognitive complexity = 1
|
||||
```
|
||||
|
||||
Cognitive complexity give lower score compare to cyclomatic complexity.
|
||||
|
||||
### Example 2
|
||||
#### Cyclomatic complexity
|
||||
```go
|
||||
func SumOfPrimes(max int) int { // +1
|
||||
var total int
|
||||
|
||||
OUT:
|
||||
for i := 1; i < max; i++ { // +1
|
||||
for j := 2; j < i; j++ { // +1
|
||||
if i%j == 0 { // +1
|
||||
continue OUT
|
||||
}
|
||||
}
|
||||
total += i
|
||||
}
|
||||
|
||||
return total
|
||||
} // Cyclomatic complexity = 4
|
||||
```
|
||||
|
||||
#### Cognitive complexity
|
||||
```go
|
||||
func SumOfPrimes(max int) int {
|
||||
var total int
|
||||
|
||||
OUT:
|
||||
for i := 1; i < max; i++ { // +1
|
||||
for j := 2; j < i; j++ { // +2 (nesting = 1)
|
||||
if i%j == 0 { // +3 (nesting = 2)
|
||||
continue OUT // +1
|
||||
}
|
||||
}
|
||||
total += i
|
||||
}
|
||||
|
||||
return total
|
||||
} // Cognitive complexity = 7
|
||||
```
|
||||
|
||||
Cognitive complexity give higher score compare to cyclomatic complexity.
|
||||
|
||||
## Rules
|
||||
|
||||
The cognitive complexity of a function is calculated according to the
|
||||
following rules:
|
||||
> Note: these rules are specific for Go, please see the [original whitepaper](./CognitiveComplexity.pdf) for more complete reference.
|
||||
|
||||
### Increments
|
||||
There is an increment for each of the following:
|
||||
1. `if`, `else if`, `else`
|
||||
2. `switch`, `select`
|
||||
3. `for`
|
||||
4. `goto` LABEL, `break` LABEL, `continue` LABEL
|
||||
5. sequence of binary logical operators
|
||||
6. each method in a recursion cycle
|
||||
|
||||
### Nesting level
|
||||
The following structures increment the nesting level:
|
||||
1. `if`, `else if`, `else`
|
||||
2. `switch`, `select`
|
||||
3. `for`
|
||||
4. function literal or lambda
|
||||
|
||||
### Nesting increments
|
||||
The following structures receive a nesting increment commensurate with their nested depth inside nesting structures:
|
||||
1. `if`
|
||||
2. `switch`, `select`
|
||||
3. `for`
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
$ go install github.com/uudashr/gocognit/cmd/gocognit@latest
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
$ go get github.com/uudashr/gocognit/cmd/gocognit
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
$ gocognit
|
||||
Calculate cognitive complexities of Go functions.
|
||||
Usage:
|
||||
gocognit [flags] <Go file or directory> ...
|
||||
Flags:
|
||||
-over N show functions with complexity > N only and
|
||||
return exit code 1 if the set is non-empty
|
||||
-top N show the top N most complex functions only
|
||||
-avg show the average complexity over all functions,
|
||||
not depending on whether -over or -top are set
|
||||
The output fields for each line are:
|
||||
<complexity> <package> <function> <file:row:column>
|
||||
```
|
||||
|
||||
Examples:
|
||||
|
||||
```
|
||||
$ gocognit .
|
||||
$ gocognit main.go
|
||||
$ gocognit -top 10 src/
|
||||
$ gocognit -over 25 docker
|
||||
$ gocognit -avg .
|
||||
```
|
||||
|
||||
The output fields for each line are:
|
||||
```
|
||||
<complexity> <package> <function> <file:row:column>
|
||||
```
|
||||
|
||||
## Related project
|
||||
- [Gocyclo](https://github.com/fzipp/gocyclo) where the code are based on.
|
||||
- [Cognitive Complexity: A new way of measuring understandability](./CognitiveComplexity.pdf) white paper by G. Ann Campbell.
|
||||
90
tools/analyzers/gocognit/analyzer.go
Normal file
90
tools/analyzers/gocognit/analyzer.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package gocognit
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
|
||||
"github.com/uudashr/gocognit"
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/passes/inspect"
|
||||
"golang.org/x/tools/go/ast/inspector"
|
||||
)
|
||||
|
||||
// Doc explaining the tool.
|
||||
const Doc = "Tool to ensure go code does not have high cognitive complexity."
|
||||
|
||||
// Analyzer runs static analysis.
|
||||
var Analyzer = &analysis.Analyzer{
|
||||
Name: "gocognit",
|
||||
Doc: Doc,
|
||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||
Run: run,
|
||||
}
|
||||
|
||||
// Recommended thresholds according to the 2008 presentation titled
|
||||
// "Software Quality Metrics to Identify Risk" by Thomas McCabe Jr.
|
||||
//
|
||||
// 1 - 10 Simple procedure, little risk
|
||||
// 11 - 20 More complex, moderate risk
|
||||
// 21 - 50 Complex, high risk
|
||||
// > 50 Untestable code, very high risk
|
||||
//
|
||||
// This threshold should be lowered to 50 over time.
|
||||
const over = 130
|
||||
|
||||
func run(pass *analysis.Pass) (interface{}, error) {
|
||||
inspect, ok := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
||||
if !ok {
|
||||
return nil, errors.New("analyzer is not type *inspector.Inspector")
|
||||
}
|
||||
|
||||
nodeFilter := []ast.Node{
|
||||
(*ast.FuncDecl)(nil),
|
||||
}
|
||||
inspect.Preorder(nodeFilter, func(n ast.Node) {
|
||||
fnDecl, ok := n.(*ast.FuncDecl)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
fnName := funcName(fnDecl)
|
||||
fnComplexity := gocognit.Complexity(fnDecl)
|
||||
|
||||
if fnComplexity > over {
|
||||
pass.Reportf(fnDecl.Pos(), "cognitive complexity %d of func %s is high (> %d)", fnComplexity, fnName, over)
|
||||
}
|
||||
})
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// funcName returns the name representation of a function or method:
|
||||
// "(Type).Name" for methods or simply "Name" for functions.
|
||||
//
|
||||
// Copied from https://github.com/uudashr/gocognit/blob/5bf67146515e79acd2a8d5728deafa9d91ad48db/gocognit.go
|
||||
// License: MIT
|
||||
func funcName(fn *ast.FuncDecl) string {
|
||||
if fn.Recv != nil {
|
||||
if fn.Recv.NumFields() > 0 {
|
||||
typ := fn.Recv.List[0].Type
|
||||
return fmt.Sprintf("(%s).%s", recvString(typ), fn.Name)
|
||||
}
|
||||
}
|
||||
return fn.Name.Name
|
||||
}
|
||||
|
||||
// recvString returns a string representation of recv of the
|
||||
// form "T", "*T", or "BADRECV" (if not a proper receiver type).
|
||||
//
|
||||
// Copied from https://github.com/uudashr/gocognit/blob/5bf67146515e79acd2a8d5728deafa9d91ad48db/gocognit.go
|
||||
// License: MIT
|
||||
func recvString(recv ast.Expr) string {
|
||||
switch t := recv.(type) {
|
||||
case *ast.Ident:
|
||||
return t.Name
|
||||
case *ast.StarExpr:
|
||||
return "*" + recvString(t.X)
|
||||
}
|
||||
return "BADRECV"
|
||||
}
|
||||
@@ -7,7 +7,7 @@ Flags:
|
||||
-beacon string
|
||||
gRPC address of the Prysm beacon node (default "127.0.0.1:4000")
|
||||
-genesis uint
|
||||
Genesis time. mainnet=1606824023, prater=1616508000, pyrmont=1605722407 (default 1606824023)
|
||||
Genesis time. mainnet=1606824023, prater=1616508000 (default 1606824023)
|
||||
```
|
||||
|
||||
Usage:
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
|
||||
var (
|
||||
beacon = flag.String("beacon", "127.0.0.1:4000", "gRPC address of the Prysm beacon node")
|
||||
genesis = flag.Uint64("genesis", 1606824023, "Genesis time. mainnet=1606824023, prater=1616508000, pyrmont=1605722407")
|
||||
genesis = flag.Uint64("genesis", 1606824023, "Genesis time. mainnet=1606824023, prater=1616508000")
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
@@ -276,9 +276,7 @@ func displayExitInfo(rawExitedKeys [][]byte, trimmedExitedKeys []string) {
|
||||
urlFormattedPubKeys := make([]string, len(rawExitedKeys))
|
||||
for i, key := range rawExitedKeys {
|
||||
var baseUrl string
|
||||
if params.BeaconConfig().ConfigName == params.ConfigNames[params.Pyrmont] {
|
||||
baseUrl = "https://pyrmont.beaconcha.in/validator/"
|
||||
} else if params.BeaconConfig().ConfigName == params.ConfigNames[params.Prater] {
|
||||
if params.BeaconConfig().ConfigName == params.ConfigNames[params.Prater] {
|
||||
baseUrl = "https://prater.beaconcha.in/validator/"
|
||||
} else {
|
||||
baseUrl = "https://beaconcha.in/validator/"
|
||||
|
||||
@@ -101,7 +101,7 @@ type Config struct {
|
||||
// registry.
|
||||
func NewValidatorService(ctx context.Context, cfg *Config) (*ValidatorService, error) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
return &ValidatorService{
|
||||
s := &ValidatorService{
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
endpoint: cfg.Endpoint,
|
||||
@@ -124,34 +124,35 @@ func NewValidatorService(ctx context.Context, cfg *Config) (*ValidatorService, e
|
||||
logDutyCountDown: cfg.LogDutyCountDown,
|
||||
Web3SignerConfig: cfg.Web3SignerConfig,
|
||||
feeRecipientConfig: cfg.FeeRecipientConfig,
|
||||
}, nil
|
||||
}
|
||||
|
||||
dialOpts := ConstructDialOptions(
|
||||
s.maxCallRecvMsgSize,
|
||||
s.withCert,
|
||||
s.grpcRetries,
|
||||
s.grpcRetryDelay,
|
||||
)
|
||||
if dialOpts == nil {
|
||||
return s, nil
|
||||
}
|
||||
|
||||
s.ctx = grpcutil.AppendHeaders(ctx, s.grpcHeaders)
|
||||
|
||||
conn, err := grpc.DialContext(ctx, s.endpoint, dialOpts...)
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
if s.withCert != "" {
|
||||
log.Info("Established secure gRPC connection")
|
||||
}
|
||||
s.conn = conn
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// Start the validator service. Launches the main go routine for the validator
|
||||
// client.
|
||||
func (v *ValidatorService) Start() {
|
||||
dialOpts := ConstructDialOptions(
|
||||
v.maxCallRecvMsgSize,
|
||||
v.withCert,
|
||||
v.grpcRetries,
|
||||
v.grpcRetryDelay,
|
||||
)
|
||||
if dialOpts == nil {
|
||||
return
|
||||
}
|
||||
|
||||
v.ctx = grpcutil.AppendHeaders(v.ctx, v.grpcHeaders)
|
||||
|
||||
conn, err := grpc.DialContext(v.ctx, v.endpoint, dialOpts...)
|
||||
if err != nil {
|
||||
log.Errorf("Could not dial endpoint: %s, %v", v.endpoint, err)
|
||||
return
|
||||
}
|
||||
if v.withCert != "" {
|
||||
log.Info("Established secure gRPC connection")
|
||||
}
|
||||
|
||||
v.conn = conn
|
||||
cache, err := ristretto.NewCache(&ristretto.Config{
|
||||
NumCounters: 1920, // number of keys to track.
|
||||
MaxCost: 192, // maximum cost of cache, 1 item = 1 cost.
|
||||
|
||||
@@ -2,7 +2,6 @@ package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -33,36 +32,11 @@ func TestStop_CancelsContext(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLifecycle(t *testing.T) {
|
||||
func TestNew_Insecure(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
// Use canceled context so that the run function exits immediately..
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
validatorService := &ValidatorService{
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
endpoint: "merkle tries",
|
||||
withCert: "alice.crt",
|
||||
}
|
||||
validatorService.Start()
|
||||
require.NoError(t, validatorService.Stop(), "Could not stop service")
|
||||
require.LogsContain(t, hook, "Stopping service")
|
||||
}
|
||||
|
||||
func TestLifecycle_Insecure(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
// Use canceled context so that the run function exits immediately.
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
validatorService := &ValidatorService{
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
endpoint: "merkle tries",
|
||||
}
|
||||
validatorService.Start()
|
||||
_, err := NewValidatorService(context.Background(), &Config{})
|
||||
require.NoError(t, err)
|
||||
require.LogsContain(t, hook, "You are using an insecure gRPC connection")
|
||||
require.NoError(t, validatorService.Stop(), "Could not stop service")
|
||||
require.LogsContain(t, hook, "Stopping service")
|
||||
}
|
||||
|
||||
func TestStatus_NoConnectionError(t *testing.T) {
|
||||
@@ -72,9 +46,7 @@ func TestStatus_NoConnectionError(t *testing.T) {
|
||||
|
||||
func TestStart_GrpcHeaders(t *testing.T) {
|
||||
hook := logTest.NewGlobal()
|
||||
// Use canceled context so that the run function exits immediately.
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
ctx := context.Background()
|
||||
for input, output := range map[string][]string{
|
||||
"should-break": {},
|
||||
"key=value": {"key", "value"},
|
||||
@@ -87,13 +59,9 @@ func TestStart_GrpcHeaders(t *testing.T) {
|
||||
"Authorization", "this is a valid value",
|
||||
},
|
||||
} {
|
||||
validatorService := &ValidatorService{
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
endpoint: "merkle tries",
|
||||
grpcHeaders: strings.Split(input, ","),
|
||||
}
|
||||
validatorService.Start()
|
||||
cfg := &Config{GrpcHeadersFlag: input}
|
||||
validatorService, err := NewValidatorService(ctx, cfg)
|
||||
require.NoError(t, err)
|
||||
md, _ := metadata.FromOutgoingContext(validatorService.ctx)
|
||||
if input == "should-break" {
|
||||
require.LogsContain(t, hook, "Incorrect gRPC header flag format. Skipping should-break")
|
||||
|
||||
@@ -46,7 +46,7 @@ func TestServer_GetBeaconNodeConnection(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
want := &pb.NodeConnectionResponse{
|
||||
BeaconNodeEndpoint: endpoint,
|
||||
Connected: false,
|
||||
Connected: true,
|
||||
Syncing: false,
|
||||
GenesisTime: uint64(time.Unix(0, 0).Unix()),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user