mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 07:58:22 -05:00
Better receiver names in validator and slasher modules (#8296)
* validator * slasher * rename db to s for store Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
This commit is contained in:
@@ -15,12 +15,12 @@ var syncStatusPollingInterval = time.Duration(params.BeaconConfig().SecondsPerSl
|
||||
|
||||
// ChainHead requests the latest beacon chain head
|
||||
// from a beacon node via gRPC.
|
||||
func (bs *Service) ChainHead(
|
||||
func (s *Service) ChainHead(
|
||||
ctx context.Context,
|
||||
) (*ethpb.ChainHead, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beaconclient.ChainHead")
|
||||
defer span.End()
|
||||
res, err := bs.beaconClient.GetChainHead(ctx, &ptypes.Empty{})
|
||||
res, err := s.beaconClient.GetChainHead(ctx, &ptypes.Empty{})
|
||||
if err != nil || res == nil {
|
||||
return nil, errors.Wrap(err, "Could not retrieve chain head or got nil chain head")
|
||||
}
|
||||
@@ -29,29 +29,29 @@ func (bs *Service) ChainHead(
|
||||
|
||||
// GenesisValidatorsRoot requests or fetch from memory the beacon chain genesis
|
||||
// validators root via gRPC.
|
||||
func (bs *Service) GenesisValidatorsRoot(
|
||||
func (s *Service) GenesisValidatorsRoot(
|
||||
ctx context.Context,
|
||||
) ([]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "beaconclient.GenesisValidatorsRoot")
|
||||
defer span.End()
|
||||
|
||||
if bs.genesisValidatorRoot == nil {
|
||||
res, err := bs.nodeClient.GetGenesis(ctx, &ptypes.Empty{})
|
||||
if s.genesisValidatorRoot == nil {
|
||||
res, err := s.nodeClient.GetGenesis(ctx, &ptypes.Empty{})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not retrieve genesis data")
|
||||
}
|
||||
if res == nil {
|
||||
return nil, errors.Wrap(err, "nil genesis data")
|
||||
}
|
||||
bs.genesisValidatorRoot = res.GenesisValidatorsRoot
|
||||
s.genesisValidatorRoot = res.GenesisValidatorsRoot
|
||||
}
|
||||
return bs.genesisValidatorRoot, nil
|
||||
return s.genesisValidatorRoot, nil
|
||||
}
|
||||
|
||||
// Poll the beacon node every syncStatusPollingInterval until the node
|
||||
// is no longer syncing.
|
||||
func (bs *Service) querySyncStatus(ctx context.Context) {
|
||||
status, err := bs.nodeClient.GetSyncStatus(ctx, &ptypes.Empty{})
|
||||
func (s *Service) querySyncStatus(ctx context.Context) {
|
||||
status, err := s.nodeClient.GetSyncStatus(ctx, &ptypes.Empty{})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not fetch sync status")
|
||||
}
|
||||
@@ -65,7 +65,7 @@ func (bs *Service) querySyncStatus(ctx context.Context) {
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
status, err := bs.nodeClient.GetSyncStatus(ctx, &ptypes.Empty{})
|
||||
status, err := s.nodeClient.GetSyncStatus(ctx, &ptypes.Empty{})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not fetch sync status")
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
// RequestHistoricalAttestations requests all indexed attestations for a
|
||||
// given epoch from a beacon node via gRPC.
|
||||
func (bs *Service) RequestHistoricalAttestations(
|
||||
func (s *Service) RequestHistoricalAttestations(
|
||||
ctx context.Context,
|
||||
epoch uint64,
|
||||
) ([]*ethpb.IndexedAttestation, error) {
|
||||
@@ -26,7 +26,7 @@ func (bs *Service) RequestHistoricalAttestations(
|
||||
if res == nil {
|
||||
res = ðpb.ListIndexedAttestationsResponse{}
|
||||
}
|
||||
res, err = bs.beaconClient.ListIndexedAttestations(ctx, ðpb.ListIndexedAttestationsRequest{
|
||||
res, err = s.beaconClient.ListIndexedAttestations(ctx, ðpb.ListIndexedAttestationsRequest{
|
||||
QueryFilter: ðpb.ListIndexedAttestationsRequest_Epoch{
|
||||
Epoch: epoch,
|
||||
},
|
||||
|
||||
@@ -24,10 +24,10 @@ var reconnectPeriod = 5 * time.Second
|
||||
// ReceiveBlocks starts a gRPC client stream listener to obtain
|
||||
// blocks from the beacon node. Upon receiving a block, the service
|
||||
// broadcasts it to a feed for other services in slasher to subscribe to.
|
||||
func (bs *Service) ReceiveBlocks(ctx context.Context) {
|
||||
func (s *Service) ReceiveBlocks(ctx context.Context) {
|
||||
ctx, span := trace.StartSpan(ctx, "beaconclient.ReceiveBlocks")
|
||||
defer span.End()
|
||||
stream, err := bs.beaconClient.StreamBlocks(ctx, ðpb.StreamBlocksRequest{} /* Prefers unverified block to catch slashing */)
|
||||
stream, err := s.beaconClient.StreamBlocks(ctx, ðpb.StreamBlocksRequest{} /* Prefers unverified block to catch slashing */)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to retrieve blocks stream")
|
||||
return
|
||||
@@ -48,12 +48,12 @@ func (bs *Service) ReceiveBlocks(ctx context.Context) {
|
||||
switch e.Code() {
|
||||
case codes.Canceled, codes.Internal, codes.Unavailable:
|
||||
log.WithError(err).Infof("Trying to restart connection. rpc status: %v", e.Code())
|
||||
err = bs.restartBeaconConnection(ctx)
|
||||
err = s.restartBeaconConnection(ctx)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not restart beacon connection")
|
||||
return
|
||||
}
|
||||
stream, err = bs.beaconClient.StreamBlocks(ctx, ðpb.StreamBlocksRequest{} /* Prefers unverified block to catch slashing */)
|
||||
stream, err = s.beaconClient.StreamBlocks(ctx, ðpb.StreamBlocksRequest{} /* Prefers unverified block to catch slashing */)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not restart block stream")
|
||||
return
|
||||
@@ -83,23 +83,23 @@ func (bs *Service) ReceiveBlocks(ctx context.Context) {
|
||||
"root": fmt.Sprintf("%#x...", root[:8]),
|
||||
}).Info("Received block from beacon node")
|
||||
// We send the received block over the block feed.
|
||||
bs.blockFeed.Send(res)
|
||||
s.blockFeed.Send(res)
|
||||
}
|
||||
}
|
||||
|
||||
// ReceiveAttestations starts a gRPC client stream listener to obtain
|
||||
// attestations from the beacon node. Upon receiving an attestation, the service
|
||||
// broadcasts it to a feed for other services in slasher to subscribe to.
|
||||
func (bs *Service) ReceiveAttestations(ctx context.Context) {
|
||||
func (s *Service) ReceiveAttestations(ctx context.Context) {
|
||||
ctx, span := trace.StartSpan(ctx, "beaconclient.ReceiveAttestations")
|
||||
defer span.End()
|
||||
stream, err := bs.beaconClient.StreamIndexedAttestations(ctx, &ptypes.Empty{})
|
||||
stream, err := s.beaconClient.StreamIndexedAttestations(ctx, &ptypes.Empty{})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Failed to retrieve attestations stream")
|
||||
return
|
||||
}
|
||||
|
||||
go bs.collectReceivedAttestations(ctx)
|
||||
go s.collectReceivedAttestations(ctx)
|
||||
for {
|
||||
res, err := stream.Recv()
|
||||
// If the stream is closed, we stop the loop.
|
||||
@@ -117,12 +117,12 @@ func (bs *Service) ReceiveAttestations(ctx context.Context) {
|
||||
switch e.Code() {
|
||||
case codes.Canceled, codes.Internal, codes.Unavailable:
|
||||
log.WithError(err).Infof("Trying to restart connection. rpc status: %v", e.Code())
|
||||
err = bs.restartBeaconConnection(ctx)
|
||||
err = s.restartBeaconConnection(ctx)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not restart beacon connection")
|
||||
return
|
||||
}
|
||||
stream, err = bs.beaconClient.StreamIndexedAttestations(ctx, &ptypes.Empty{})
|
||||
stream, err = s.beaconClient.StreamIndexedAttestations(ctx, &ptypes.Empty{})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not restart attestation stream")
|
||||
return
|
||||
@@ -140,11 +140,11 @@ func (bs *Service) ReceiveAttestations(ctx context.Context) {
|
||||
if res == nil {
|
||||
continue
|
||||
}
|
||||
bs.receivedAttestationsBuffer <- res
|
||||
s.receivedAttestationsBuffer <- res
|
||||
}
|
||||
}
|
||||
|
||||
func (bs *Service) collectReceivedAttestations(ctx context.Context) {
|
||||
func (s *Service) collectReceivedAttestations(ctx context.Context) {
|
||||
ctx, span := trace.StartSpan(ctx, "beaconclient.collectReceivedAttestations")
|
||||
defer span.End()
|
||||
|
||||
@@ -156,13 +156,13 @@ func (bs *Service) collectReceivedAttestations(ctx context.Context) {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
if len(atts) > 0 {
|
||||
bs.collectedAttestationsBuffer <- atts
|
||||
s.collectedAttestationsBuffer <- atts
|
||||
atts = []*ethpb.IndexedAttestation{}
|
||||
}
|
||||
case att := <-bs.receivedAttestationsBuffer:
|
||||
case att := <-s.receivedAttestationsBuffer:
|
||||
atts = append(atts, att)
|
||||
case collectedAtts := <-bs.collectedAttestationsBuffer:
|
||||
if err := bs.slasherDB.SaveIndexedAttestations(ctx, collectedAtts); err != nil {
|
||||
case collectedAtts := <-s.collectedAttestationsBuffer:
|
||||
if err := s.slasherDB.SaveIndexedAttestations(ctx, collectedAtts); err != nil {
|
||||
log.WithError(err).Error("Could not save indexed attestation")
|
||||
continue
|
||||
}
|
||||
@@ -178,7 +178,7 @@ func (bs *Service) collectReceivedAttestations(ctx context.Context) {
|
||||
"slot": att.Data.Slot,
|
||||
"indices": att.AttestingIndices,
|
||||
}).Debug("Sending attestation to detection service")
|
||||
bs.attestationFeed.Send(att)
|
||||
s.attestationFeed.Send(att)
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return
|
||||
@@ -186,18 +186,18 @@ func (bs *Service) collectReceivedAttestations(ctx context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
func (bs *Service) restartBeaconConnection(ctx context.Context) error {
|
||||
func (s *Service) restartBeaconConnection(ctx context.Context) error {
|
||||
ticker := time.NewTicker(reconnectPeriod)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
if bs.conn.GetState() == connectivity.TransientFailure || bs.conn.GetState() == connectivity.Idle {
|
||||
log.Debugf("Connection status %v", bs.conn.GetState())
|
||||
if s.conn.GetState() == connectivity.TransientFailure || s.conn.GetState() == connectivity.Idle {
|
||||
log.Debugf("Connection status %v", s.conn.GetState())
|
||||
log.Info("Beacon node is still down")
|
||||
continue
|
||||
}
|
||||
status, err := bs.nodeClient.GetSyncStatus(ctx, &ptypes.Empty{})
|
||||
status, err := s.nodeClient.GetSyncStatus(ctx, &ptypes.Empty{})
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not fetch sync status")
|
||||
continue
|
||||
|
||||
@@ -104,36 +104,36 @@ func NewService(ctx context.Context, cfg *Config) (*Service, error) {
|
||||
|
||||
// BlockFeed returns a feed other services in slasher can subscribe to
|
||||
// blocks received via the beacon node through gRPC.
|
||||
func (bs *Service) BlockFeed() *event.Feed {
|
||||
return bs.blockFeed
|
||||
func (s *Service) BlockFeed() *event.Feed {
|
||||
return s.blockFeed
|
||||
}
|
||||
|
||||
// AttestationFeed returns a feed other services in slasher can subscribe to
|
||||
// attestations received via the beacon node through gRPC.
|
||||
func (bs *Service) AttestationFeed() *event.Feed {
|
||||
return bs.attestationFeed
|
||||
func (s *Service) AttestationFeed() *event.Feed {
|
||||
return s.attestationFeed
|
||||
}
|
||||
|
||||
// ClientReadyFeed returns a feed other services in slasher can subscribe to
|
||||
// to indicate when the gRPC connection is ready.
|
||||
func (bs *Service) ClientReadyFeed() *event.Feed {
|
||||
return bs.clientFeed
|
||||
func (s *Service) ClientReadyFeed() *event.Feed {
|
||||
return s.clientFeed
|
||||
}
|
||||
|
||||
// Stop the beacon client service by closing the gRPC connection.
|
||||
func (bs *Service) Stop() error {
|
||||
bs.cancel()
|
||||
func (s *Service) Stop() error {
|
||||
s.cancel()
|
||||
log.Info("Stopping service")
|
||||
if bs.conn != nil {
|
||||
return bs.conn.Close()
|
||||
if s.conn != nil {
|
||||
return s.conn.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Status returns an error if there exists a gRPC connection error
|
||||
// in the service.
|
||||
func (bs *Service) Status() error {
|
||||
if bs.conn == nil {
|
||||
func (s *Service) Status() error {
|
||||
if s.conn == nil {
|
||||
return errors.New("no connection to beacon RPC")
|
||||
}
|
||||
return nil
|
||||
@@ -143,10 +143,10 @@ func (bs *Service) Status() error {
|
||||
// a gRPC client connection with a beacon node, listening for
|
||||
// streamed blocks/attestations, and submitting slashing operations
|
||||
// after they are detected by other services in the slasher.
|
||||
func (bs *Service) Start() {
|
||||
func (s *Service) Start() {
|
||||
var dialOpt grpc.DialOption
|
||||
if bs.cert != "" {
|
||||
creds, err := credentials.NewClientTLSFromFile(bs.cert, "")
|
||||
if s.cert != "" {
|
||||
creds, err := credentials.NewClientTLSFromFile(s.cert, "")
|
||||
if err != nil {
|
||||
log.Errorf("Could not get valid credentials: %v", err)
|
||||
}
|
||||
@@ -173,27 +173,27 @@ func (bs *Service) Start() {
|
||||
grpcutils.LogGRPCRequests,
|
||||
)),
|
||||
}
|
||||
conn, err := grpc.DialContext(bs.ctx, bs.provider, beaconOpts...)
|
||||
conn, err := grpc.DialContext(s.ctx, s.provider, beaconOpts...)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not dial endpoint: %s, %v", bs.provider, err)
|
||||
log.Fatalf("Could not dial endpoint: %s, %v", s.provider, err)
|
||||
}
|
||||
bs.beaconDialOptions = beaconOpts
|
||||
s.beaconDialOptions = beaconOpts
|
||||
log.Info("Successfully started gRPC connection")
|
||||
bs.conn = conn
|
||||
bs.beaconClient = ethpb.NewBeaconChainClient(bs.conn)
|
||||
bs.nodeClient = ethpb.NewNodeClient(bs.conn)
|
||||
s.conn = conn
|
||||
s.beaconClient = ethpb.NewBeaconChainClient(s.conn)
|
||||
s.nodeClient = ethpb.NewNodeClient(s.conn)
|
||||
|
||||
// We poll for the sync status of the beacon node until it is fully synced.
|
||||
bs.querySyncStatus(bs.ctx)
|
||||
s.querySyncStatus(s.ctx)
|
||||
|
||||
// We notify other services in slasher that the beacon client is ready
|
||||
// and the connection is active.
|
||||
bs.clientFeed.Send(true)
|
||||
s.clientFeed.Send(true)
|
||||
|
||||
// We register subscribers for any detected proposer/attester slashings
|
||||
// in the slasher services that we can submit to the beacon node
|
||||
// as they are found.
|
||||
go bs.subscribeDetectedProposerSlashings(bs.ctx, bs.proposerSlashingsChan)
|
||||
go bs.subscribeDetectedAttesterSlashings(bs.ctx, bs.attesterSlashingsChan)
|
||||
go s.subscribeDetectedProposerSlashings(s.ctx, s.proposerSlashingsChan)
|
||||
go s.subscribeDetectedAttesterSlashings(s.ctx, s.attesterSlashingsChan)
|
||||
|
||||
}
|
||||
|
||||
@@ -15,15 +15,15 @@ import (
|
||||
// slashing objects from the slasher runtime. Upon receiving
|
||||
// a proposer slashing from the feed, we submit the object to the
|
||||
// connected beacon node via a client RPC.
|
||||
func (bs *Service) subscribeDetectedProposerSlashings(ctx context.Context, ch chan *ethpb.ProposerSlashing) {
|
||||
func (s *Service) subscribeDetectedProposerSlashings(ctx context.Context, ch chan *ethpb.ProposerSlashing) {
|
||||
ctx, span := trace.StartSpan(ctx, "beaconclient.submitProposerSlashing")
|
||||
defer span.End()
|
||||
sub := bs.proposerSlashingsFeed.Subscribe(ch)
|
||||
sub := s.proposerSlashingsFeed.Subscribe(ch)
|
||||
defer sub.Unsubscribe()
|
||||
for {
|
||||
select {
|
||||
case slashing := <-ch:
|
||||
if _, err := bs.beaconClient.SubmitProposerSlashing(ctx, slashing); err != nil {
|
||||
if _, err := s.beaconClient.SubmitProposerSlashing(ctx, slashing); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
case <-sub.Err():
|
||||
@@ -40,17 +40,17 @@ func (bs *Service) subscribeDetectedProposerSlashings(ctx context.Context, ch ch
|
||||
// slashing objects from the slasher runtime. Upon receiving an
|
||||
// attester slashing from the feed, we submit the object to the
|
||||
// connected beacon node via a client RPC.
|
||||
func (bs *Service) subscribeDetectedAttesterSlashings(ctx context.Context, ch chan *ethpb.AttesterSlashing) {
|
||||
func (s *Service) subscribeDetectedAttesterSlashings(ctx context.Context, ch chan *ethpb.AttesterSlashing) {
|
||||
ctx, span := trace.StartSpan(ctx, "beaconclient.submitAttesterSlashing")
|
||||
defer span.End()
|
||||
sub := bs.attesterSlashingsFeed.Subscribe(ch)
|
||||
sub := s.attesterSlashingsFeed.Subscribe(ch)
|
||||
defer sub.Unsubscribe()
|
||||
for {
|
||||
select {
|
||||
case slashing := <-ch:
|
||||
if slashing != nil && slashing.Attestation_1 != nil && slashing.Attestation_2 != nil {
|
||||
slashableIndices := sliceutil.IntersectionUint64(slashing.Attestation_1.AttestingIndices, slashing.Attestation_2.AttestingIndices)
|
||||
_, err := bs.beaconClient.SubmitAttesterSlashing(ctx, slashing)
|
||||
_, err := s.beaconClient.SubmitAttesterSlashing(ctx, slashing)
|
||||
if err == nil {
|
||||
log.WithFields(logrus.Fields{
|
||||
"sourceEpoch": slashing.Attestation_1.Data.Source.Epoch,
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
// FindOrGetPublicKeys gets public keys from cache or request validators public
|
||||
// keys from a beacon node via gRPC.
|
||||
func (bs *Service) FindOrGetPublicKeys(
|
||||
func (s *Service) FindOrGetPublicKeys(
|
||||
ctx context.Context,
|
||||
validatorIndices []uint64,
|
||||
) (map[uint64][]byte, error) {
|
||||
@@ -20,7 +20,7 @@ func (bs *Service) FindOrGetPublicKeys(
|
||||
validators := make(map[uint64][]byte, len(validatorIndices))
|
||||
notFound := 0
|
||||
for _, validatorIdx := range validatorIndices {
|
||||
pub, exists := bs.publicKeyCache.Get(validatorIdx)
|
||||
pub, exists := s.publicKeyCache.Get(validatorIdx)
|
||||
if exists {
|
||||
validators[validatorIdx] = pub
|
||||
continue
|
||||
@@ -42,7 +42,7 @@ func (bs *Service) FindOrGetPublicKeys(
|
||||
if notFound == 0 {
|
||||
return validators, nil
|
||||
}
|
||||
vc, err := bs.beaconClient.ListValidators(ctx, ðpb.ListValidatorsRequest{
|
||||
vc, err := s.beaconClient.ListValidators(ctx, ðpb.ListValidatorsRequest{
|
||||
Indices: validatorIndices,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -50,7 +50,7 @@ func (bs *Service) FindOrGetPublicKeys(
|
||||
}
|
||||
for _, v := range vc.ValidatorList {
|
||||
validators[v.Index] = v.Validator.PublicKey
|
||||
bs.publicKeyCache.Set(v.Index, v.Validator.PublicKey)
|
||||
s.publicKeyCache.Set(v.Index, v.Validator.PublicKey)
|
||||
}
|
||||
log.Tracef(
|
||||
"Retrieved validators id public key map: %v",
|
||||
|
||||
@@ -37,11 +37,11 @@ func unmarshalAttSlashings(encoded [][]byte) ([]*ethpb.AttesterSlashing, error)
|
||||
|
||||
// AttesterSlashings accepts a status and returns all slashings with this status.
|
||||
// returns empty []*ethpb.AttesterSlashing if no slashing has been found with this status.
|
||||
func (db *Store) AttesterSlashings(ctx context.Context, status types.SlashingStatus) ([]*ethpb.AttesterSlashing, error) {
|
||||
func (s *Store) AttesterSlashings(ctx context.Context, status types.SlashingStatus) ([]*ethpb.AttesterSlashing, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.AttesterSlashings")
|
||||
defer span.End()
|
||||
encoded := make([][]byte, 0)
|
||||
err := db.view(func(tx *bolt.Tx) error {
|
||||
err := s.view(func(tx *bolt.Tx) error {
|
||||
c := tx.Bucket(slashingBucket).Cursor()
|
||||
prefix := encodeType(types.SlashingType(types.Attestation))
|
||||
for k, v := c.Seek(prefix); k != nil && bytes.HasPrefix(k, prefix); k, v = c.Next() {
|
||||
@@ -58,14 +58,14 @@ func (db *Store) AttesterSlashings(ctx context.Context, status types.SlashingSta
|
||||
}
|
||||
|
||||
// DeleteAttesterSlashing deletes an attester slashing proof from db.
|
||||
func (db *Store) DeleteAttesterSlashing(ctx context.Context, attesterSlashing *ethpb.AttesterSlashing) error {
|
||||
func (s *Store) DeleteAttesterSlashing(ctx context.Context, attesterSlashing *ethpb.AttesterSlashing) error {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.deleteAttesterSlashing")
|
||||
defer span.End()
|
||||
root, err := hashutil.HashProto(attesterSlashing)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to get hash root of attesterSlashing")
|
||||
}
|
||||
return db.update(func(tx *bolt.Tx) error {
|
||||
return s.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(slashingBucket)
|
||||
k := encodeTypeRoot(types.SlashingType(types.Attestation), root)
|
||||
if err != nil {
|
||||
@@ -79,7 +79,7 @@ func (db *Store) DeleteAttesterSlashing(ctx context.Context, attesterSlashing *e
|
||||
}
|
||||
|
||||
// HasAttesterSlashing returns true and slashing status if a slashing is found in the db.
|
||||
func (db *Store) HasAttesterSlashing(ctx context.Context, slashing *ethpb.AttesterSlashing) (bool, types.SlashingStatus, error) {
|
||||
func (s *Store) HasAttesterSlashing(ctx context.Context, slashing *ethpb.AttesterSlashing) (bool, types.SlashingStatus, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.HasAttesterSlashing")
|
||||
defer span.End()
|
||||
var status types.SlashingStatus
|
||||
@@ -89,7 +89,7 @@ func (db *Store) HasAttesterSlashing(ctx context.Context, slashing *ethpb.Attest
|
||||
return found, status, errors.Wrap(err, "failed to get hash root of attesterSlashing")
|
||||
}
|
||||
key := encodeTypeRoot(types.SlashingType(types.Attestation), root)
|
||||
err = db.view(func(tx *bolt.Tx) error {
|
||||
err = s.view(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(slashingBucket)
|
||||
enc := b.Get(key)
|
||||
if enc != nil {
|
||||
@@ -102,7 +102,7 @@ func (db *Store) HasAttesterSlashing(ctx context.Context, slashing *ethpb.Attest
|
||||
}
|
||||
|
||||
// SaveAttesterSlashing accepts a slashing proof and its status and writes it to disk.
|
||||
func (db *Store) SaveAttesterSlashing(ctx context.Context, status types.SlashingStatus, slashing *ethpb.AttesterSlashing) error {
|
||||
func (s *Store) SaveAttesterSlashing(ctx context.Context, status types.SlashingStatus, slashing *ethpb.AttesterSlashing) error {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.SaveAttesterSlashing")
|
||||
defer span.End()
|
||||
enc, err := proto.Marshal(slashing)
|
||||
@@ -114,7 +114,7 @@ func (db *Store) SaveAttesterSlashing(ctx context.Context, status types.Slashing
|
||||
return err
|
||||
}
|
||||
key := encodeTypeRoot(types.SlashingType(types.Attestation), root)
|
||||
return db.update(func(tx *bolt.Tx) error {
|
||||
return s.update(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(slashingBucket)
|
||||
e := b.Put(key, append([]byte{byte(status)}, enc...))
|
||||
return e
|
||||
@@ -122,7 +122,7 @@ func (db *Store) SaveAttesterSlashing(ctx context.Context, status types.Slashing
|
||||
}
|
||||
|
||||
// SaveAttesterSlashings accepts a slice of slashing proof and its status and writes it to disk.
|
||||
func (db *Store) SaveAttesterSlashings(ctx context.Context, status types.SlashingStatus, slashings []*ethpb.AttesterSlashing) error {
|
||||
func (s *Store) SaveAttesterSlashings(ctx context.Context, status types.SlashingStatus, slashings []*ethpb.AttesterSlashing) error {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.SaveAttesterSlashings")
|
||||
defer span.End()
|
||||
enc := make([][]byte, len(slashings))
|
||||
@@ -140,7 +140,7 @@ func (db *Store) SaveAttesterSlashings(ctx context.Context, status types.Slashin
|
||||
key[i] = encodeTypeRoot(types.SlashingType(types.Attestation), root)
|
||||
}
|
||||
|
||||
return db.update(func(tx *bolt.Tx) error {
|
||||
return s.update(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(slashingBucket)
|
||||
for i := 0; i < len(enc); i++ {
|
||||
e := b.Put(key[i], append([]byte{byte(status)}, enc[i]...))
|
||||
@@ -153,11 +153,11 @@ func (db *Store) SaveAttesterSlashings(ctx context.Context, status types.Slashin
|
||||
}
|
||||
|
||||
// GetLatestEpochDetected returns the latest detected epoch from db.
|
||||
func (db *Store) GetLatestEpochDetected(ctx context.Context) (uint64, error) {
|
||||
func (s *Store) GetLatestEpochDetected(ctx context.Context) (uint64, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.GetLatestEpochDetected")
|
||||
defer span.End()
|
||||
var epoch uint64
|
||||
err := db.view(func(tx *bolt.Tx) error {
|
||||
err := s.view(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(slashingBucket)
|
||||
enc := b.Get([]byte(latestEpochKey))
|
||||
if enc == nil {
|
||||
@@ -171,10 +171,10 @@ func (db *Store) GetLatestEpochDetected(ctx context.Context) (uint64, error) {
|
||||
}
|
||||
|
||||
// SetLatestEpochDetected sets the latest slashing detected epoch in db.
|
||||
func (db *Store) SetLatestEpochDetected(ctx context.Context, epoch uint64) error {
|
||||
func (s *Store) SetLatestEpochDetected(ctx context.Context, epoch uint64) error {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.SetLatestEpochDetected")
|
||||
defer span.End()
|
||||
return db.update(func(tx *bolt.Tx) error {
|
||||
return s.update(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(slashingBucket)
|
||||
err := b.Put([]byte(latestEpochKey), bytesutil.Bytes8(epoch))
|
||||
return err
|
||||
|
||||
@@ -27,11 +27,11 @@ func unmarshalBlockHeader(ctx context.Context, enc []byte) (*ethpb.SignedBeaconB
|
||||
|
||||
// BlockHeaders accepts an slot and validator id and returns the corresponding block header array.
|
||||
// Returns nil if the block header for those values does not exist.
|
||||
func (db *Store) BlockHeaders(ctx context.Context, slot, validatorID uint64) ([]*ethpb.SignedBeaconBlockHeader, error) {
|
||||
func (s *Store) BlockHeaders(ctx context.Context, slot, validatorID uint64) ([]*ethpb.SignedBeaconBlockHeader, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.BlockHeaders")
|
||||
defer span.End()
|
||||
var blockHeaders []*ethpb.SignedBeaconBlockHeader
|
||||
err := db.view(func(tx *bolt.Tx) error {
|
||||
err := s.view(func(tx *bolt.Tx) error {
|
||||
c := tx.Bucket(historicBlockHeadersBucket).Cursor()
|
||||
prefix := encodeSlotValidatorID(slot, validatorID)
|
||||
for k, v := c.Seek(prefix); k != nil && bytes.HasPrefix(k, prefix); k, v = c.Next() {
|
||||
@@ -47,12 +47,12 @@ func (db *Store) BlockHeaders(ctx context.Context, slot, validatorID uint64) ([]
|
||||
}
|
||||
|
||||
// HasBlockHeader accepts a slot and validator id and returns true if the block header exists.
|
||||
func (db *Store) HasBlockHeader(ctx context.Context, slot, validatorID uint64) bool {
|
||||
func (s *Store) HasBlockHeader(ctx context.Context, slot, validatorID uint64) bool {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.HasBlockHeader")
|
||||
defer span.End()
|
||||
prefix := encodeSlotValidatorID(slot, validatorID)
|
||||
var hasBlockHeader bool
|
||||
if err := db.view(func(tx *bolt.Tx) error {
|
||||
if err := s.view(func(tx *bolt.Tx) error {
|
||||
c := tx.Bucket(historicBlockHeadersBucket).Cursor()
|
||||
for k, _ := c.Seek(prefix); k != nil && bytes.HasPrefix(k, prefix); k, _ = c.Next() {
|
||||
hasBlockHeader = true
|
||||
@@ -68,7 +68,7 @@ func (db *Store) HasBlockHeader(ctx context.Context, slot, validatorID uint64) b
|
||||
}
|
||||
|
||||
// SaveBlockHeader accepts a block header and writes it to disk.
|
||||
func (db *Store) SaveBlockHeader(ctx context.Context, blockHeader *ethpb.SignedBeaconBlockHeader) error {
|
||||
func (s *Store) SaveBlockHeader(ctx context.Context, blockHeader *ethpb.SignedBeaconBlockHeader) error {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.SaveBlockHeader")
|
||||
defer span.End()
|
||||
epoch := helpers.SlotToEpoch(blockHeader.Header.Slot)
|
||||
@@ -78,7 +78,7 @@ func (db *Store) SaveBlockHeader(ctx context.Context, blockHeader *ethpb.SignedB
|
||||
return errors.Wrap(err, "failed to encode block")
|
||||
}
|
||||
|
||||
err = db.update(func(tx *bolt.Tx) error {
|
||||
err = s.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(historicBlockHeadersBucket)
|
||||
if err := bucket.Put(key, enc); err != nil {
|
||||
return errors.Wrap(err, "failed to include block header in the historical bucket")
|
||||
@@ -92,17 +92,17 @@ func (db *Store) SaveBlockHeader(ctx context.Context, blockHeader *ethpb.SignedB
|
||||
|
||||
// Prune block header history every 10th epoch.
|
||||
if epoch%params.BeaconConfig().PruneSlasherStoragePeriod == 0 {
|
||||
return db.PruneBlockHistory(ctx, epoch, params.BeaconConfig().WeakSubjectivityPeriod)
|
||||
return s.PruneBlockHistory(ctx, epoch, params.BeaconConfig().WeakSubjectivityPeriod)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteBlockHeader deletes a block header using the slot and validator id.
|
||||
func (db *Store) DeleteBlockHeader(ctx context.Context, blockHeader *ethpb.SignedBeaconBlockHeader) error {
|
||||
func (s *Store) DeleteBlockHeader(ctx context.Context, blockHeader *ethpb.SignedBeaconBlockHeader) error {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.DeleteBlockHeader")
|
||||
defer span.End()
|
||||
key := encodeSlotValidatorIDSig(blockHeader.Header.Slot, blockHeader.Header.ProposerIndex, blockHeader.Signature)
|
||||
return db.update(func(tx *bolt.Tx) error {
|
||||
return s.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(historicBlockHeadersBucket)
|
||||
if err := bucket.Delete(key); err != nil {
|
||||
return errors.Wrap(err, "failed to delete the block header from historical bucket")
|
||||
@@ -112,7 +112,7 @@ func (db *Store) DeleteBlockHeader(ctx context.Context, blockHeader *ethpb.Signe
|
||||
}
|
||||
|
||||
// PruneBlockHistory leaves only records younger then history size.
|
||||
func (db *Store) PruneBlockHistory(ctx context.Context, currentEpoch, pruningEpochAge uint64) error {
|
||||
func (s *Store) PruneBlockHistory(ctx context.Context, currentEpoch, pruningEpochAge uint64) error {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.pruneBlockHistory")
|
||||
defer span.End()
|
||||
pruneTill := int64(currentEpoch) - int64(pruningEpochAge)
|
||||
@@ -120,7 +120,7 @@ func (db *Store) PruneBlockHistory(ctx context.Context, currentEpoch, pruningEpo
|
||||
return nil
|
||||
}
|
||||
pruneTillSlot := uint64(pruneTill) * params.BeaconConfig().SlotsPerEpoch
|
||||
return db.update(func(tx *bolt.Tx) error {
|
||||
return s.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(historicBlockHeadersBucket)
|
||||
c := tx.Bucket(historicBlockHeadersBucket).Cursor()
|
||||
for k, _ := c.First(); k != nil && bytesutil.FromBytes8(k[:8]) <= pruneTillSlot; k, _ = c.Next() {
|
||||
|
||||
@@ -11,11 +11,11 @@ import (
|
||||
)
|
||||
|
||||
// ChainHead retrieves the persisted chain head from the database accordingly.
|
||||
func (db *Store) ChainHead(ctx context.Context) (*ethpb.ChainHead, error) {
|
||||
func (s *Store) ChainHead(ctx context.Context) (*ethpb.ChainHead, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.ChainHead")
|
||||
defer span.End()
|
||||
var res *ethpb.ChainHead
|
||||
if err := db.update(func(tx *bolt.Tx) error {
|
||||
if err := s.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(chainDataBucket)
|
||||
enc := bucket.Get([]byte(chainHeadKey))
|
||||
if enc == nil {
|
||||
@@ -30,17 +30,17 @@ func (db *Store) ChainHead(ctx context.Context) (*ethpb.ChainHead, error) {
|
||||
}
|
||||
|
||||
// SaveChainHead accepts a beacon chain head object and persists it to the DB.
|
||||
func (db *Store) SaveChainHead(ctx context.Context, head *ethpb.ChainHead) error {
|
||||
func (s *Store) SaveChainHead(ctx context.Context, head *ethpb.ChainHead) error {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.SaveChainHead")
|
||||
defer span.End()
|
||||
enc, err := proto.Marshal(head)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to encode chain head")
|
||||
}
|
||||
return db.update(func(tx *bolt.Tx) error {
|
||||
return s.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(chainDataBucket)
|
||||
if err := bucket.Put([]byte(chainHeadKey), enc); err != nil {
|
||||
return errors.Wrap(err, "failed to save chain head to db")
|
||||
return errors.Wrap(err, "failed to save chain head to s")
|
||||
}
|
||||
return err
|
||||
})
|
||||
|
||||
@@ -37,17 +37,17 @@ func persistHighestAttestationCacheOnEviction(db *Store) func(key interface{}, v
|
||||
}
|
||||
|
||||
// EnableHighestAttestationCache used to enable or disable highest attestation cache in tests.
|
||||
func (db *Store) EnableHighestAttestationCache(enable bool) {
|
||||
db.highestAttCacheEnabled = enable
|
||||
func (s *Store) EnableHighestAttestationCache(enable bool) {
|
||||
s.highestAttCacheEnabled = enable
|
||||
}
|
||||
|
||||
// HighestAttestation returns the highest calculated attestation for a validatorID
|
||||
func (db *Store) HighestAttestation(ctx context.Context, validatorID uint64) (*slashpb.HighestAttestation, error) {
|
||||
func (s *Store) HighestAttestation(ctx context.Context, validatorID uint64) (*slashpb.HighestAttestation, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "SlasherDB.HighestAttestation")
|
||||
defer span.End()
|
||||
|
||||
if db.highestAttCacheEnabled {
|
||||
h, ok := db.highestAttestationCache.Get(highestAttSetkey(validatorID))
|
||||
if s.highestAttCacheEnabled {
|
||||
h, ok := s.highestAttestationCache.Get(highestAttSetkey(validatorID))
|
||||
if ok && h[validatorID] != nil {
|
||||
return h[validatorID], nil
|
||||
}
|
||||
@@ -55,7 +55,7 @@ func (db *Store) HighestAttestation(ctx context.Context, validatorID uint64) (*s
|
||||
|
||||
key := highestAttSetkeyBytes(validatorID)
|
||||
var highestAtt *slashpb.HighestAttestation
|
||||
err := db.view(func(tx *bolt.Tx) error {
|
||||
err := s.view(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(highestAttestationBucket)
|
||||
if enc := b.Get(key); enc != nil {
|
||||
set := map[uint64]*slashpb.HighestAttestation{}
|
||||
@@ -72,18 +72,18 @@ func (db *Store) HighestAttestation(ctx context.Context, validatorID uint64) (*s
|
||||
}
|
||||
|
||||
// SaveHighestAttestation saves highest attestation for a validatorID.
|
||||
func (db *Store) SaveHighestAttestation(ctx context.Context, highest *slashpb.HighestAttestation) error {
|
||||
func (s *Store) SaveHighestAttestation(ctx context.Context, highest *slashpb.HighestAttestation) error {
|
||||
ctx, span := trace.StartSpan(ctx, "SlasherDB.SaveHighestAttestation")
|
||||
defer span.End()
|
||||
|
||||
if db.highestAttCacheEnabled {
|
||||
db.highestAttestationCache.Set(highestAttSetkey(highest.ValidatorId), highest)
|
||||
if s.highestAttCacheEnabled {
|
||||
s.highestAttestationCache.Set(highestAttSetkey(highest.ValidatorId), highest)
|
||||
return nil
|
||||
}
|
||||
|
||||
key := highestAttSetkeyBytes(highest.ValidatorId)
|
||||
set := map[uint64]*slashpb.HighestAttestation{}
|
||||
err := db.view(func(tx *bolt.Tx) error {
|
||||
err := s.view(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(highestAttestationBucket)
|
||||
if enc := b.Get(key); enc != nil {
|
||||
err := json.Unmarshal(enc, &set)
|
||||
@@ -102,10 +102,10 @@ func (db *Store) SaveHighestAttestation(ctx context.Context, highest *slashpb.Hi
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to marshal")
|
||||
}
|
||||
err = db.update(func(tx *bolt.Tx) error {
|
||||
err = s.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(highestAttestationBucket)
|
||||
if err := bucket.Put(key, enc); err != nil {
|
||||
return errors.Wrap(err, "failed to add highest attestation to slasher db.")
|
||||
return errors.Wrap(err, "failed to add highest attestation to slasher s.")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -26,12 +26,12 @@ func unmarshalIndexedAttestation(ctx context.Context, enc []byte) (*ethpb.Indexe
|
||||
// IndexedAttestationsForTarget accepts a target epoch and returns a list of
|
||||
// indexed attestations.
|
||||
// Returns nil if the indexed attestation does not exist with that target epoch.
|
||||
func (db *Store) IndexedAttestationsForTarget(ctx context.Context, targetEpoch uint64) ([]*ethpb.IndexedAttestation, error) {
|
||||
func (s *Store) IndexedAttestationsForTarget(ctx context.Context, targetEpoch uint64) ([]*ethpb.IndexedAttestation, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.IndexedAttestationsForTarget")
|
||||
defer span.End()
|
||||
var idxAtts []*ethpb.IndexedAttestation
|
||||
key := bytesutil.Bytes8(targetEpoch)
|
||||
err := db.view(func(tx *bolt.Tx) error {
|
||||
err := s.view(func(tx *bolt.Tx) error {
|
||||
c := tx.Bucket(historicIndexedAttestationsBucket).Cursor()
|
||||
for k, enc := c.Seek(key); k != nil && bytes.Equal(k[:8], key); k, enc = c.Next() {
|
||||
idxAtt, err := unmarshalIndexedAttestation(ctx, enc)
|
||||
@@ -47,12 +47,12 @@ func (db *Store) IndexedAttestationsForTarget(ctx context.Context, targetEpoch u
|
||||
|
||||
// IndexedAttestationsWithPrefix accepts a target epoch and signature bytes to find all attestations with the requested prefix.
|
||||
// Returns nil if the indexed attestation does not exist with that target epoch.
|
||||
func (db *Store) IndexedAttestationsWithPrefix(ctx context.Context, targetEpoch uint64, sigBytes []byte) ([]*ethpb.IndexedAttestation, error) {
|
||||
func (s *Store) IndexedAttestationsWithPrefix(ctx context.Context, targetEpoch uint64, sigBytes []byte) ([]*ethpb.IndexedAttestation, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.IndexedAttestationsWithPrefix")
|
||||
defer span.End()
|
||||
var idxAtts []*ethpb.IndexedAttestation
|
||||
key := encodeEpochSig(targetEpoch, sigBytes)
|
||||
err := db.view(func(tx *bolt.Tx) error {
|
||||
err := s.view(func(tx *bolt.Tx) error {
|
||||
c := tx.Bucket(historicIndexedAttestationsBucket).Cursor()
|
||||
for k, enc := c.Seek(key); k != nil && bytes.Equal(k[:len(key)], key); k, enc = c.Next() {
|
||||
idxAtt, err := unmarshalIndexedAttestation(ctx, enc)
|
||||
@@ -67,13 +67,13 @@ func (db *Store) IndexedAttestationsWithPrefix(ctx context.Context, targetEpoch
|
||||
}
|
||||
|
||||
// HasIndexedAttestation accepts an attestation and returns true if it exists in the DB.
|
||||
func (db *Store) HasIndexedAttestation(ctx context.Context, att *ethpb.IndexedAttestation) (bool, error) {
|
||||
func (s *Store) HasIndexedAttestation(ctx context.Context, att *ethpb.IndexedAttestation) (bool, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.HasIndexedAttestation")
|
||||
defer span.End()
|
||||
key := encodeEpochSig(att.Data.Target.Epoch, att.Signature)
|
||||
var hasAttestation bool
|
||||
// #nosec G104
|
||||
err := db.view(func(tx *bolt.Tx) error {
|
||||
err := s.view(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(historicIndexedAttestationsBucket)
|
||||
enc := bucket.Get(key)
|
||||
if enc == nil {
|
||||
@@ -87,7 +87,7 @@ func (db *Store) HasIndexedAttestation(ctx context.Context, att *ethpb.IndexedAt
|
||||
}
|
||||
|
||||
// SaveIndexedAttestation accepts an indexed attestation and writes it to the DB.
|
||||
func (db *Store) SaveIndexedAttestation(ctx context.Context, idxAttestation *ethpb.IndexedAttestation) error {
|
||||
func (s *Store) SaveIndexedAttestation(ctx context.Context, idxAttestation *ethpb.IndexedAttestation) error {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.SaveIndexedAttestation")
|
||||
defer span.End()
|
||||
key := encodeEpochSig(idxAttestation.Data.Target.Epoch, idxAttestation.Signature)
|
||||
@@ -95,9 +95,9 @@ func (db *Store) SaveIndexedAttestation(ctx context.Context, idxAttestation *eth
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to marshal")
|
||||
}
|
||||
err = db.update(func(tx *bolt.Tx) error {
|
||||
err = s.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(historicIndexedAttestationsBucket)
|
||||
// if data is in db skip put and index functions
|
||||
// if data is in s skip put and index functions
|
||||
val := bucket.Get(key)
|
||||
if val != nil {
|
||||
return nil
|
||||
@@ -112,7 +112,7 @@ func (db *Store) SaveIndexedAttestation(ctx context.Context, idxAttestation *eth
|
||||
}
|
||||
|
||||
// SaveIndexedAttestations accepts multiple indexed attestations and writes them to the DB.
|
||||
func (db *Store) SaveIndexedAttestations(ctx context.Context, idxAttestations []*ethpb.IndexedAttestation) error {
|
||||
func (s *Store) SaveIndexedAttestations(ctx context.Context, idxAttestations []*ethpb.IndexedAttestation) error {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.SaveIndexedAttestations")
|
||||
defer span.End()
|
||||
keys := make([][]byte, len(idxAttestations))
|
||||
@@ -126,10 +126,10 @@ func (db *Store) SaveIndexedAttestations(ctx context.Context, idxAttestations []
|
||||
marshaledAtts[i] = enc
|
||||
}
|
||||
|
||||
err := db.update(func(tx *bolt.Tx) error {
|
||||
err := s.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(historicIndexedAttestationsBucket)
|
||||
for i, key := range keys {
|
||||
// if data is in db skip put and index functions
|
||||
// if data is in s skip put and index functions
|
||||
val := bucket.Get(key)
|
||||
if val != nil {
|
||||
continue
|
||||
@@ -144,11 +144,11 @@ func (db *Store) SaveIndexedAttestations(ctx context.Context, idxAttestations []
|
||||
}
|
||||
|
||||
// DeleteIndexedAttestation deletes a indexed attestation using the slot and its root as keys in their respective buckets.
|
||||
func (db *Store) DeleteIndexedAttestation(ctx context.Context, idxAttestation *ethpb.IndexedAttestation) error {
|
||||
func (s *Store) DeleteIndexedAttestation(ctx context.Context, idxAttestation *ethpb.IndexedAttestation) error {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.DeleteIndexedAttestation")
|
||||
defer span.End()
|
||||
key := encodeEpochSig(idxAttestation.Data.Target.Epoch, idxAttestation.Signature)
|
||||
return db.update(func(tx *bolt.Tx) error {
|
||||
return s.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(historicIndexedAttestationsBucket)
|
||||
enc := bucket.Get(key)
|
||||
if enc == nil {
|
||||
@@ -162,7 +162,7 @@ func (db *Store) DeleteIndexedAttestation(ctx context.Context, idxAttestation *e
|
||||
}
|
||||
|
||||
// PruneAttHistory removes all attestations from the DB older than the pruning epoch age.
|
||||
func (db *Store) PruneAttHistory(ctx context.Context, currentEpoch, pruningEpochAge uint64) error {
|
||||
func (s *Store) PruneAttHistory(ctx context.Context, currentEpoch, pruningEpochAge uint64) error {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.pruneAttHistory")
|
||||
defer span.End()
|
||||
pruneFromEpoch := int64(currentEpoch) - int64(pruningEpochAge)
|
||||
@@ -170,7 +170,7 @@ func (db *Store) PruneAttHistory(ctx context.Context, currentEpoch, pruningEpoch
|
||||
return nil
|
||||
}
|
||||
|
||||
return db.update(func(tx *bolt.Tx) error {
|
||||
return s.update(func(tx *bolt.Tx) error {
|
||||
attBucket := tx.Bucket(historicIndexedAttestationsBucket)
|
||||
c := tx.Bucket(historicIndexedAttestationsBucket).Cursor()
|
||||
max := bytesutil.Bytes8(uint64(pruneFromEpoch))
|
||||
@@ -185,11 +185,11 @@ func (db *Store) PruneAttHistory(ctx context.Context, currentEpoch, pruningEpoch
|
||||
|
||||
// LatestIndexedAttestationsTargetEpoch returns latest target epoch in db
|
||||
// returns 0 if there is no indexed attestations in db.
|
||||
func (db *Store) LatestIndexedAttestationsTargetEpoch(ctx context.Context) (uint64, error) {
|
||||
func (s *Store) LatestIndexedAttestationsTargetEpoch(ctx context.Context) (uint64, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.LatestIndexedAttestationsTargetEpoch")
|
||||
defer span.End()
|
||||
var lt uint64
|
||||
err := db.view(func(tx *bolt.Tx) error {
|
||||
err := s.view(func(tx *bolt.Tx) error {
|
||||
c := tx.Bucket(historicIndexedAttestationsBucket).Cursor()
|
||||
k, _ := c.Last()
|
||||
if k == nil {
|
||||
|
||||
@@ -42,43 +42,43 @@ type Config struct {
|
||||
}
|
||||
|
||||
// Close closes the underlying boltdb database.
|
||||
func (db *Store) Close() error {
|
||||
db.flatSpanCache.Purge()
|
||||
db.highestAttestationCache.Purge()
|
||||
return db.db.Close()
|
||||
func (s *Store) Close() error {
|
||||
s.flatSpanCache.Purge()
|
||||
s.highestAttestationCache.Purge()
|
||||
return s.db.Close()
|
||||
}
|
||||
|
||||
// RemoveOldestFromCache clears the oldest key out of the cache only if the cache is at max capacity.
|
||||
func (db *Store) RemoveOldestFromCache(ctx context.Context) uint64 {
|
||||
func (s *Store) RemoveOldestFromCache(ctx context.Context) uint64 {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.removeOldestFromCache")
|
||||
defer span.End()
|
||||
epochRemoved := db.flatSpanCache.PruneOldest()
|
||||
epochRemoved := s.flatSpanCache.PruneOldest()
|
||||
return epochRemoved
|
||||
}
|
||||
|
||||
// ClearSpanCache clears the spans cache.
|
||||
func (db *Store) ClearSpanCache() {
|
||||
db.flatSpanCache.Purge()
|
||||
func (s *Store) ClearSpanCache() {
|
||||
s.flatSpanCache.Purge()
|
||||
}
|
||||
|
||||
func (db *Store) update(fn func(*bolt.Tx) error) error {
|
||||
return db.db.Update(fn)
|
||||
func (s *Store) update(fn func(*bolt.Tx) error) error {
|
||||
return s.db.Update(fn)
|
||||
}
|
||||
func (db *Store) view(fn func(*bolt.Tx) error) error {
|
||||
return db.db.View(fn)
|
||||
func (s *Store) view(fn func(*bolt.Tx) error) error {
|
||||
return s.db.View(fn)
|
||||
}
|
||||
|
||||
// ClearDB removes any previously stored data at the configured data directory.
|
||||
func (db *Store) ClearDB() error {
|
||||
if _, err := os.Stat(db.databasePath); os.IsNotExist(err) {
|
||||
func (s *Store) ClearDB() error {
|
||||
if _, err := os.Stat(s.databasePath); os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
return os.Remove(filepath.Join(db.databasePath, DatabaseFileName))
|
||||
return os.Remove(filepath.Join(s.databasePath, DatabaseFileName))
|
||||
}
|
||||
|
||||
// DatabasePath at which this database writes files.
|
||||
func (db *Store) DatabasePath() string {
|
||||
return db.databasePath
|
||||
func (s *Store) DatabasePath() string {
|
||||
return s.databasePath
|
||||
}
|
||||
|
||||
func createBuckets(tx *bolt.Tx, buckets ...[]byte) error {
|
||||
@@ -146,9 +146,9 @@ func NewKVStore(dirPath string, cfg *Config) (*Store, error) {
|
||||
}
|
||||
|
||||
// Size returns the db size in bytes.
|
||||
func (db *Store) Size() (int64, error) {
|
||||
func (s *Store) Size() (int64, error) {
|
||||
var size int64
|
||||
err := db.db.View(func(tx *bolt.Tx) error {
|
||||
err := s.db.View(func(tx *bolt.Tx) error {
|
||||
size = tx.Size()
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -38,11 +38,11 @@ func unmarshalProposerSlashingArray(ctx context.Context, encoded [][]byte) ([]*e
|
||||
}
|
||||
|
||||
// ProposalSlashingsByStatus returns all the proposal slashing proofs with a certain status.
|
||||
func (db *Store) ProposalSlashingsByStatus(ctx context.Context, status types.SlashingStatus) ([]*ethpb.ProposerSlashing, error) {
|
||||
func (s *Store) ProposalSlashingsByStatus(ctx context.Context, status types.SlashingStatus) ([]*ethpb.ProposerSlashing, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.ProposalSlashingsByStatus")
|
||||
defer span.End()
|
||||
encoded := make([][]byte, 0)
|
||||
err := db.view(func(tx *bolt.Tx) error {
|
||||
err := s.view(func(tx *bolt.Tx) error {
|
||||
c := tx.Bucket(slashingBucket).Cursor()
|
||||
prefix := encodeType(types.SlashingType(types.Proposal))
|
||||
for k, v := c.Seek(prefix); k != nil && bytes.HasPrefix(k, prefix); k, v = c.Next() {
|
||||
@@ -59,14 +59,14 @@ func (db *Store) ProposalSlashingsByStatus(ctx context.Context, status types.Sla
|
||||
}
|
||||
|
||||
// DeleteProposerSlashing deletes a proposer slashing proof.
|
||||
func (db *Store) DeleteProposerSlashing(ctx context.Context, slashing *ethpb.ProposerSlashing) error {
|
||||
func (s *Store) DeleteProposerSlashing(ctx context.Context, slashing *ethpb.ProposerSlashing) error {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.deleteProposerSlashing")
|
||||
defer span.End()
|
||||
root, err := hashutil.HashProto(slashing)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to get hash root of proposerSlashing")
|
||||
}
|
||||
err = db.update(func(tx *bolt.Tx) error {
|
||||
err = s.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(slashingBucket)
|
||||
k := encodeTypeRoot(types.SlashingType(types.Proposal), root)
|
||||
if err := bucket.Delete(k); err != nil {
|
||||
@@ -78,7 +78,7 @@ func (db *Store) DeleteProposerSlashing(ctx context.Context, slashing *ethpb.Pro
|
||||
}
|
||||
|
||||
// HasProposerSlashing returns the slashing key if it is found in db.
|
||||
func (db *Store) HasProposerSlashing(ctx context.Context, slashing *ethpb.ProposerSlashing) (bool, types.SlashingStatus, error) {
|
||||
func (s *Store) HasProposerSlashing(ctx context.Context, slashing *ethpb.ProposerSlashing) (bool, types.SlashingStatus, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.HasProposerSlashing")
|
||||
defer span.End()
|
||||
var status types.SlashingStatus
|
||||
@@ -89,7 +89,7 @@ func (db *Store) HasProposerSlashing(ctx context.Context, slashing *ethpb.Propos
|
||||
}
|
||||
key := encodeTypeRoot(types.SlashingType(types.Proposal), root)
|
||||
|
||||
err = db.view(func(tx *bolt.Tx) error {
|
||||
err = s.view(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(slashingBucket)
|
||||
enc := b.Get(key)
|
||||
if enc != nil {
|
||||
@@ -102,7 +102,7 @@ func (db *Store) HasProposerSlashing(ctx context.Context, slashing *ethpb.Propos
|
||||
}
|
||||
|
||||
// SaveProposerSlashing accepts a proposer slashing and its status header and writes it to disk.
|
||||
func (db *Store) SaveProposerSlashing(ctx context.Context, status types.SlashingStatus, slashing *ethpb.ProposerSlashing) error {
|
||||
func (s *Store) SaveProposerSlashing(ctx context.Context, status types.SlashingStatus, slashing *ethpb.ProposerSlashing) error {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.SaveProposerSlashing")
|
||||
defer span.End()
|
||||
enc, err := proto.Marshal(slashing)
|
||||
@@ -114,7 +114,7 @@ func (db *Store) SaveProposerSlashing(ctx context.Context, status types.Slashing
|
||||
return err
|
||||
}
|
||||
key := encodeTypeRoot(types.SlashingType(types.Proposal), root)
|
||||
return db.update(func(tx *bolt.Tx) error {
|
||||
return s.update(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(slashingBucket)
|
||||
e := b.Put(key, append([]byte{byte(status)}, enc...))
|
||||
return e
|
||||
@@ -122,7 +122,7 @@ func (db *Store) SaveProposerSlashing(ctx context.Context, status types.Slashing
|
||||
}
|
||||
|
||||
// SaveProposerSlashings accepts a slice of slashing proof and its status and writes it to disk.
|
||||
func (db *Store) SaveProposerSlashings(ctx context.Context, status types.SlashingStatus, slashings []*ethpb.ProposerSlashing) error {
|
||||
func (s *Store) SaveProposerSlashings(ctx context.Context, status types.SlashingStatus, slashings []*ethpb.ProposerSlashing) error {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.SaveProposerSlashings")
|
||||
defer span.End()
|
||||
encSlashings := make([][]byte, len(slashings))
|
||||
@@ -140,7 +140,7 @@ func (db *Store) SaveProposerSlashings(ctx context.Context, status types.Slashin
|
||||
keys[i] = encodeTypeRoot(types.SlashingType(types.Proposal), root)
|
||||
}
|
||||
|
||||
return db.update(func(tx *bolt.Tx) error {
|
||||
return s.update(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(slashingBucket)
|
||||
for i := 0; i < len(keys); i++ {
|
||||
err := b.Put(keys[i], append([]byte{byte(status)}, encSlashings[i]...))
|
||||
|
||||
@@ -68,15 +68,15 @@ func persistFlatSpanMapsOnEviction(db *Store) func(key interface{}, value interf
|
||||
// for slashing detection.
|
||||
// Returns span byte array, and error in case of db error.
|
||||
// returns empty byte array if no entry for this epoch exists in db.
|
||||
func (db *Store) EpochSpans(_ context.Context, epoch uint64, fromCache bool) (*types.EpochStore, error) {
|
||||
func (s *Store) EpochSpans(_ context.Context, epoch uint64, fromCache bool) (*types.EpochStore, error) {
|
||||
// Get from the cache if it exists or is requested, if not, go to DB.
|
||||
if fromCache && db.flatSpanCache.Has(epoch) || db.flatSpanCache.Has(epoch) {
|
||||
spans, _ := db.flatSpanCache.Get(epoch)
|
||||
if fromCache && s.flatSpanCache.Has(epoch) || s.flatSpanCache.Has(epoch) {
|
||||
spans, _ := s.flatSpanCache.Get(epoch)
|
||||
return spans, nil
|
||||
}
|
||||
|
||||
var copiedSpans []byte
|
||||
err := db.view(func(tx *bolt.Tx) error {
|
||||
err := s.view(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(validatorsMinMaxSpanBucketNew)
|
||||
if b == nil {
|
||||
return nil
|
||||
@@ -96,23 +96,23 @@ func (db *Store) EpochSpans(_ context.Context, epoch uint64, fromCache bool) (*t
|
||||
}
|
||||
|
||||
// SaveEpochSpans accepts a epoch and span byte array and writes it to disk.
|
||||
func (db *Store) SaveEpochSpans(ctx context.Context, epoch uint64, es *types.EpochStore, toCache bool) error {
|
||||
func (s *Store) SaveEpochSpans(ctx context.Context, epoch uint64, es *types.EpochStore, toCache bool) error {
|
||||
if len(es.Bytes())%int(types.SpannerEncodedLength) != 0 {
|
||||
return types.ErrWrongSize
|
||||
}
|
||||
// Also prune indexed attestations older then weak subjectivity period.
|
||||
if err := db.setObservedEpochs(ctx, epoch); err != nil {
|
||||
if err := s.setObservedEpochs(ctx, epoch); err != nil {
|
||||
return err
|
||||
}
|
||||
// Saving to the cache if it exists so cache and DB never conflict.
|
||||
if toCache || db.flatSpanCache.Has(epoch) {
|
||||
db.flatSpanCache.Set(epoch, es)
|
||||
if toCache || s.flatSpanCache.Has(epoch) {
|
||||
s.flatSpanCache.Set(epoch, es)
|
||||
}
|
||||
if toCache {
|
||||
return nil
|
||||
}
|
||||
|
||||
return db.update(func(tx *bolt.Tx) error {
|
||||
return s.update(func(tx *bolt.Tx) error {
|
||||
b, err := tx.CreateBucketIfNotExists(validatorsMinMaxSpanBucketNew)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -122,27 +122,27 @@ func (db *Store) SaveEpochSpans(ctx context.Context, epoch uint64, es *types.Epo
|
||||
}
|
||||
|
||||
// CacheLength returns the number of cached items.
|
||||
func (db *Store) CacheLength(ctx context.Context) int {
|
||||
func (s *Store) CacheLength(ctx context.Context) int {
|
||||
ctx, span := trace.StartSpan(ctx, "slasherDB.CacheLength")
|
||||
defer span.End()
|
||||
length := db.flatSpanCache.Length()
|
||||
length := s.flatSpanCache.Length()
|
||||
log.Debugf("Span cache length %d", length)
|
||||
return length
|
||||
}
|
||||
|
||||
// EnableSpanCache used to enable or disable span map cache in tests.
|
||||
func (db *Store) EnableSpanCache(enable bool) {
|
||||
db.spanCacheEnabled = enable
|
||||
func (s *Store) EnableSpanCache(enable bool) {
|
||||
s.spanCacheEnabled = enable
|
||||
}
|
||||
|
||||
func (db *Store) setObservedEpochs(ctx context.Context, epoch uint64) error {
|
||||
func (s *Store) setObservedEpochs(ctx context.Context, epoch uint64) error {
|
||||
var err error
|
||||
if epoch > highestObservedEpoch {
|
||||
slasherHighestObservedEpoch.Set(float64(epoch))
|
||||
highestObservedEpoch = epoch
|
||||
// Prune block header history every PruneSlasherStoragePeriod epoch.
|
||||
if highestObservedEpoch%params.BeaconConfig().PruneSlasherStoragePeriod == 0 {
|
||||
if err = db.PruneAttHistory(ctx, epoch, params.BeaconConfig().WeakSubjectivityPeriod); err != nil {
|
||||
if err = s.PruneAttHistory(ctx, epoch, params.BeaconConfig().WeakSubjectivityPeriod); err != nil {
|
||||
return errors.Wrap(err, "failed to prune indexed attestations store")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,11 +11,11 @@ import (
|
||||
|
||||
// ValidatorPubKey accepts validator id and returns the corresponding pubkey.
|
||||
// Returns nil if the pubkey for this validator id does not exist.
|
||||
func (db *Store) ValidatorPubKey(ctx context.Context, validatorID uint64) ([]byte, error) {
|
||||
func (s *Store) ValidatorPubKey(ctx context.Context, validatorID uint64) ([]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "SlasherDB.ValidatorPubKey")
|
||||
defer span.End()
|
||||
var pk []byte
|
||||
err := db.view(func(tx *bolt.Tx) error {
|
||||
err := s.view(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket(validatorsPublicKeysBucket)
|
||||
pk = b.Get(bytesutil.Bytes4(validatorID))
|
||||
return nil
|
||||
@@ -24,14 +24,14 @@ func (db *Store) ValidatorPubKey(ctx context.Context, validatorID uint64) ([]byt
|
||||
}
|
||||
|
||||
// SavePubKey accepts a validator id and its public key and writes it to disk.
|
||||
func (db *Store) SavePubKey(ctx context.Context, validatorID uint64, pubKey []byte) error {
|
||||
func (s *Store) SavePubKey(ctx context.Context, validatorID uint64, pubKey []byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "SlasherDB.SavePubKey")
|
||||
defer span.End()
|
||||
err := db.update(func(tx *bolt.Tx) error {
|
||||
err := s.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(validatorsPublicKeysBucket)
|
||||
key := bytesutil.Bytes4(validatorID)
|
||||
if err := bucket.Put(key, pubKey); err != nil {
|
||||
return errors.Wrap(err, "failed to add validator public key to slasher db.")
|
||||
return errors.Wrap(err, "failed to add validator public key to slasher s.")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@@ -39,10 +39,10 @@ func (db *Store) SavePubKey(ctx context.Context, validatorID uint64, pubKey []by
|
||||
}
|
||||
|
||||
// DeletePubKey deletes a public key of a validator id.
|
||||
func (db *Store) DeletePubKey(ctx context.Context, validatorID uint64) error {
|
||||
func (s *Store) DeletePubKey(ctx context.Context, validatorID uint64) error {
|
||||
ctx, span := trace.StartSpan(ctx, "SlasherDB.DeletePubKey")
|
||||
defer span.End()
|
||||
return db.update(func(tx *bolt.Tx) error {
|
||||
return s.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(validatorsPublicKeysBucket)
|
||||
key := bytesutil.Bytes4(validatorID)
|
||||
if err := bucket.Delete(key); err != nil {
|
||||
|
||||
@@ -24,20 +24,20 @@ const (
|
||||
UseDB = false
|
||||
)
|
||||
|
||||
func (status SlashingStatus) String() string {
|
||||
func (s SlashingStatus) String() string {
|
||||
names := [...]string{
|
||||
"Unknown",
|
||||
"Active",
|
||||
"Included",
|
||||
"Reverted"}
|
||||
|
||||
if status < Active || status > Reverted {
|
||||
if s < Active || s > Reverted {
|
||||
return "Unknown"
|
||||
}
|
||||
// return the name of a SlashingStatus
|
||||
// constant from the names array
|
||||
// above.
|
||||
return names[status]
|
||||
return names[s]
|
||||
}
|
||||
|
||||
// SlashingType enum like type of slashing proof.
|
||||
@@ -51,14 +51,14 @@ const (
|
||||
)
|
||||
|
||||
// String returns the string representation of the status SlashingType.
|
||||
func (status SlashingType) String() string {
|
||||
func (t SlashingType) String() string {
|
||||
names := [...]string{
|
||||
"Proposal",
|
||||
"Attestation",
|
||||
}
|
||||
|
||||
if status < Active || status > Reverted {
|
||||
if t < Active || t > Reverted {
|
||||
return "Unknown"
|
||||
}
|
||||
return names[status]
|
||||
return names[t]
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ type MockSpanDetector struct{}
|
||||
// epoch equal to or greater than 6, it will "detect" a surrounded vote for the target epoch + 1.
|
||||
// If the target epoch is greater than 12, it will "detect" a surrounding vote for target epoch - 1.
|
||||
// Lastly, if it has a target epoch less than 6, it will "detect" a double vote for the target epoch.
|
||||
func (s *MockSpanDetector) DetectSlashingsForAttestation(
|
||||
func (m *MockSpanDetector) DetectSlashingsForAttestation(
|
||||
_ context.Context,
|
||||
att *ethpb.IndexedAttestation,
|
||||
) ([]*types.DetectionResult, error) {
|
||||
@@ -58,21 +58,21 @@ func (s *MockSpanDetector) DetectSlashingsForAttestation(
|
||||
|
||||
// SpanForEpochByValidator returns the specific min-max span for a
|
||||
// validator index in a given epoch.
|
||||
func (s *MockSpanDetector) SpanForEpochByValidator(_ context.Context, _, _ uint64) (types.Span, error) {
|
||||
func (m *MockSpanDetector) SpanForEpochByValidator(_ context.Context, _, _ uint64) (types.Span, error) {
|
||||
return types.Span{MinSpan: 0, MaxSpan: 0, SigBytes: [2]byte{}, HasAttested: false}, nil
|
||||
}
|
||||
|
||||
// ValidatorSpansByEpoch returns a list of all validator spans in a given epoch.
|
||||
func (s *MockSpanDetector) ValidatorSpansByEpoch(_ context.Context, _ uint64) map[uint64]types.Span {
|
||||
func (m *MockSpanDetector) ValidatorSpansByEpoch(_ context.Context, _ uint64) map[uint64]types.Span {
|
||||
return make(map[uint64]types.Span)
|
||||
}
|
||||
|
||||
// DeleteValidatorSpansByEpoch mocks the delete spans by epoch function.
|
||||
func (s *MockSpanDetector) DeleteValidatorSpansByEpoch(_ context.Context, _, _ uint64) error {
|
||||
func (m *MockSpanDetector) DeleteValidatorSpansByEpoch(_ context.Context, _, _ uint64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateSpans is a mock for updating the spans for a given attestation..
|
||||
func (s *MockSpanDetector) UpdateSpans(_ context.Context, _ *ethpb.IndexedAttestation) error {
|
||||
func (m *MockSpanDetector) UpdateSpans(_ context.Context, _ *ethpb.IndexedAttestation) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -37,11 +37,11 @@ type DetectionResult struct {
|
||||
}
|
||||
|
||||
// Marshal the result into bytes, used for removing duplicates.
|
||||
func (result *DetectionResult) Marshal() []byte {
|
||||
numBytes := bytesutil.ToBytes(result.SlashableEpoch, 8)
|
||||
func (r *DetectionResult) Marshal() []byte {
|
||||
numBytes := bytesutil.ToBytes(r.SlashableEpoch, 8)
|
||||
var resultBytes []byte
|
||||
resultBytes = append(resultBytes, uint8(result.Kind))
|
||||
resultBytes = append(resultBytes, result.SigBytes[:]...)
|
||||
resultBytes = append(resultBytes, uint8(r.Kind))
|
||||
resultBytes = append(resultBytes, r.SigBytes[:]...)
|
||||
resultBytes = append(resultBytes, numBytes...)
|
||||
return resultBytes
|
||||
}
|
||||
@@ -75,18 +75,18 @@ func UnmarshalSpan(enc []byte) (Span, error) {
|
||||
|
||||
// Marshal converts the span struct into a flattened byte array.
|
||||
// Note: This is a very often used function, so it is as optimized as possible.
|
||||
func (span Span) Marshal() []byte {
|
||||
func (s Span) Marshal() []byte {
|
||||
var attested byte = 0
|
||||
if span.HasAttested {
|
||||
if s.HasAttested {
|
||||
attested = 1
|
||||
}
|
||||
return []byte{
|
||||
byte(span.MinSpan),
|
||||
byte(span.MinSpan >> 8),
|
||||
byte(span.MaxSpan),
|
||||
byte(span.MaxSpan >> 8),
|
||||
span.SigBytes[0],
|
||||
span.SigBytes[1],
|
||||
byte(s.MinSpan),
|
||||
byte(s.MinSpan >> 8),
|
||||
byte(s.MaxSpan),
|
||||
byte(s.MaxSpan >> 8),
|
||||
s.SigBytes[0],
|
||||
s.SigBytes[1],
|
||||
attested,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,13 +18,13 @@ import (
|
||||
)
|
||||
|
||||
// DetectAttesterSlashings detects double, surround and surrounding attestation offences given an attestation.
|
||||
func (ds *Service) DetectAttesterSlashings(
|
||||
func (s *Service) DetectAttesterSlashings(
|
||||
ctx context.Context,
|
||||
att *ethpb.IndexedAttestation,
|
||||
) ([]*ethpb.AttesterSlashing, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "detection.DetectAttesterSlashings")
|
||||
defer span.End()
|
||||
results, err := ds.minMaxSpanDetector.DetectSlashingsForAttestation(ctx, att)
|
||||
results, err := s.minMaxSpanDetector.DetectSlashingsForAttestation(ctx, att)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -33,7 +33,7 @@ func (ds *Service) DetectAttesterSlashings(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
resultsToAtts, err := ds.mapResultsToAtts(ctx, results)
|
||||
resultsToAtts, err := s.mapResultsToAtts(ctx, results)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -44,12 +44,12 @@ func (ds *Service) DetectAttesterSlashings(
|
||||
var slashing *ethpb.AttesterSlashing
|
||||
switch result.Kind {
|
||||
case types.DoubleVote:
|
||||
slashing, err = ds.detectDoubleVote(ctx, resultsToAtts[resultKey], att, result)
|
||||
slashing, err = s.detectDoubleVote(ctx, resultsToAtts[resultKey], att, result)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not detect double votes on attestation")
|
||||
}
|
||||
case types.SurroundVote:
|
||||
slashing, err = ds.detectSurroundVotes(ctx, resultsToAtts[resultKey], att, result)
|
||||
slashing, err = s.detectSurroundVotes(ctx, resultsToAtts[resultKey], att, result)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not detect surround votes on attestation")
|
||||
}
|
||||
@@ -73,7 +73,7 @@ func (ds *Service) DetectAttesterSlashings(
|
||||
}
|
||||
}
|
||||
if len(slashings) > 0 {
|
||||
if err := ds.slasherDB.SaveAttesterSlashings(ctx, status.Active, slashings); err != nil {
|
||||
if err := s.slasherDB.SaveAttesterSlashings(ctx, status.Active, slashings); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -81,13 +81,13 @@ func (ds *Service) DetectAttesterSlashings(
|
||||
}
|
||||
|
||||
// UpdateSpans passthrough function that updates span maps given an indexed attestation.
|
||||
func (ds *Service) UpdateSpans(ctx context.Context, att *ethpb.IndexedAttestation) error {
|
||||
return ds.minMaxSpanDetector.UpdateSpans(ctx, att)
|
||||
func (s *Service) UpdateSpans(ctx context.Context, att *ethpb.IndexedAttestation) error {
|
||||
return s.minMaxSpanDetector.UpdateSpans(ctx, att)
|
||||
}
|
||||
|
||||
// detectDoubleVote cross references the passed in attestation with the bloom filter maintained
|
||||
// for every epoch for the validator in order to determine if it is a double vote.
|
||||
func (ds *Service) detectDoubleVote(
|
||||
func (s *Service) detectDoubleVote(
|
||||
_ context.Context,
|
||||
possibleAtts []*ethpb.IndexedAttestation,
|
||||
incomingAtt *ethpb.IndexedAttestation,
|
||||
@@ -122,7 +122,7 @@ func (ds *Service) detectDoubleVote(
|
||||
|
||||
// detectSurroundVotes cross references the passed in attestation with the requested validator's
|
||||
// voting history in order to detect any possible surround votes.
|
||||
func (ds *Service) detectSurroundVotes(
|
||||
func (s *Service) detectSurroundVotes(
|
||||
ctx context.Context,
|
||||
possibleAtts []*ethpb.IndexedAttestation,
|
||||
incomingAtt *ethpb.IndexedAttestation,
|
||||
@@ -168,17 +168,17 @@ func (ds *Service) detectSurroundVotes(
|
||||
}
|
||||
|
||||
// DetectDoubleProposals checks if the given signed beacon block is a slashable offense and returns the slashing.
|
||||
func (ds *Service) DetectDoubleProposals(ctx context.Context, incomingBlock *ethpb.SignedBeaconBlockHeader) (*ethpb.ProposerSlashing, error) {
|
||||
return ds.proposalsDetector.DetectDoublePropose(ctx, incomingBlock)
|
||||
func (s *Service) DetectDoubleProposals(ctx context.Context, incomingBlock *ethpb.SignedBeaconBlockHeader) (*ethpb.ProposerSlashing, error) {
|
||||
return s.proposalsDetector.DetectDoublePropose(ctx, incomingBlock)
|
||||
}
|
||||
|
||||
// DetectDoubleProposeNoUpdate checks if the given beacon block header is a slashable offense.
|
||||
func (ds *Service) DetectDoubleProposeNoUpdate(ctx context.Context, incomingBlock *ethpb.BeaconBlockHeader) (bool, error) {
|
||||
return ds.proposalsDetector.DetectDoubleProposeNoUpdate(ctx, incomingBlock)
|
||||
func (s *Service) DetectDoubleProposeNoUpdate(ctx context.Context, incomingBlock *ethpb.BeaconBlockHeader) (bool, error) {
|
||||
return s.proposalsDetector.DetectDoubleProposeNoUpdate(ctx, incomingBlock)
|
||||
}
|
||||
|
||||
// mapResultsToAtts handles any duplicate detections by ensuring they reuse the same pool of attestations, instead of re-checking the DB for the same data.
|
||||
func (ds *Service) mapResultsToAtts(ctx context.Context, results []*types.DetectionResult) (map[[32]byte][]*ethpb.IndexedAttestation, error) {
|
||||
func (s *Service) mapResultsToAtts(ctx context.Context, results []*types.DetectionResult) (map[[32]byte][]*ethpb.IndexedAttestation, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "detection.mapResultsToAtts")
|
||||
defer span.End()
|
||||
resultsToAtts := make(map[[32]byte][]*ethpb.IndexedAttestation)
|
||||
@@ -187,7 +187,7 @@ func (ds *Service) mapResultsToAtts(ctx context.Context, results []*types.Detect
|
||||
if _, ok := resultsToAtts[resultKey]; ok {
|
||||
continue
|
||||
}
|
||||
matchingAtts, err := ds.slasherDB.IndexedAttestationsWithPrefix(ctx, result.SlashableEpoch, result.SigBytes[:])
|
||||
matchingAtts, err := s.slasherDB.IndexedAttestationsWithPrefix(ctx, result.SlashableEpoch, result.SigBytes[:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -212,9 +212,9 @@ func isDoubleVote(incomingAtt, prevAtt *ethpb.IndexedAttestation) bool {
|
||||
}
|
||||
|
||||
// UpdateHighestAttestation updates to the db the highest source and target attestations for a each validator.
|
||||
func (ds *Service) UpdateHighestAttestation(ctx context.Context, att *ethpb.IndexedAttestation) error {
|
||||
func (s *Service) UpdateHighestAttestation(ctx context.Context, att *ethpb.IndexedAttestation) error {
|
||||
for _, idx := range att.AttestingIndices {
|
||||
h, err := ds.slasherDB.HighestAttestation(ctx, idx)
|
||||
h, err := s.slasherDB.HighestAttestation(ctx, idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -238,7 +238,7 @@ func (ds *Service) UpdateHighestAttestation(ctx context.Context, att *ethpb.Inde
|
||||
|
||||
// If it's not a new instance of HighestAttestation, changing it will also change the cached instance.
|
||||
if update {
|
||||
if err := ds.slasherDB.SaveHighestAttestation(ctx, h); err != nil {
|
||||
if err := s.slasherDB.SaveHighestAttestation(ctx, h); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +18,10 @@ import (
|
||||
// block objects from a notifier interface. Upon receiving
|
||||
// a signed beacon block from the feed, we run proposer slashing
|
||||
// detection on the block.
|
||||
func (ds *Service) detectIncomingBlocks(ctx context.Context, ch chan *ethpb.SignedBeaconBlock) {
|
||||
func (s *Service) detectIncomingBlocks(ctx context.Context, ch chan *ethpb.SignedBeaconBlock) {
|
||||
ctx, span := trace.StartSpan(ctx, "detection.detectIncomingBlocks")
|
||||
defer span.End()
|
||||
sub := ds.notifier.BlockFeed().Subscribe(ch)
|
||||
sub := s.notifier.BlockFeed().Subscribe(ch)
|
||||
defer sub.Unsubscribe()
|
||||
for {
|
||||
select {
|
||||
@@ -31,12 +31,12 @@ func (ds *Service) detectIncomingBlocks(ctx context.Context, ch chan *ethpb.Sign
|
||||
log.WithError(err).Error("Could not get block header from block")
|
||||
continue
|
||||
}
|
||||
slashing, err := ds.proposalsDetector.DetectDoublePropose(ctx, signedBlkHdr)
|
||||
slashing, err := s.proposalsDetector.DetectDoublePropose(ctx, signedBlkHdr)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not perform detection on block header")
|
||||
continue
|
||||
}
|
||||
ds.submitProposerSlashing(ctx, slashing)
|
||||
s.submitProposerSlashing(ctx, slashing)
|
||||
case <-sub.Err():
|
||||
log.Error("Subscriber closed, exiting goroutine")
|
||||
return
|
||||
@@ -51,27 +51,27 @@ func (ds *Service) detectIncomingBlocks(ctx context.Context, ch chan *ethpb.Sign
|
||||
// attestation objects from a notifier interface. Upon receiving
|
||||
// an attestation from the feed, we run surround vote and double vote
|
||||
// detection on the attestation.
|
||||
func (ds *Service) detectIncomingAttestations(ctx context.Context, ch chan *ethpb.IndexedAttestation) {
|
||||
func (s *Service) detectIncomingAttestations(ctx context.Context, ch chan *ethpb.IndexedAttestation) {
|
||||
ctx, span := trace.StartSpan(ctx, "detection.detectIncomingAttestations")
|
||||
defer span.End()
|
||||
sub := ds.notifier.AttestationFeed().Subscribe(ch)
|
||||
sub := s.notifier.AttestationFeed().Subscribe(ch)
|
||||
defer sub.Unsubscribe()
|
||||
for {
|
||||
select {
|
||||
case indexedAtt := <-ch:
|
||||
slashings, err := ds.DetectAttesterSlashings(ctx, indexedAtt)
|
||||
slashings, err := s.DetectAttesterSlashings(ctx, indexedAtt)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not detect attester slashings")
|
||||
continue
|
||||
}
|
||||
if len(slashings) < 1 {
|
||||
if err := ds.minMaxSpanDetector.UpdateSpans(ctx, indexedAtt); err != nil {
|
||||
if err := s.minMaxSpanDetector.UpdateSpans(ctx, indexedAtt); err != nil {
|
||||
log.WithError(err).Error("Could not update spans")
|
||||
}
|
||||
}
|
||||
ds.submitAttesterSlashings(ctx, slashings)
|
||||
s.submitAttesterSlashings(ctx, slashings)
|
||||
|
||||
if err := ds.UpdateHighestAttestation(ctx, indexedAtt); err != nil {
|
||||
if err := s.UpdateHighestAttestation(ctx, indexedAtt); err != nil {
|
||||
log.WithError(err).Error("Could not update highest attestation")
|
||||
}
|
||||
case <-sub.Err():
|
||||
|
||||
@@ -26,13 +26,13 @@ func NewProposeDetector(db db.Database) *ProposeDetector {
|
||||
}
|
||||
|
||||
// DetectDoublePropose detects double proposals given a block by looking in the db.
|
||||
func (dd *ProposeDetector) DetectDoublePropose(
|
||||
func (d *ProposeDetector) DetectDoublePropose(
|
||||
ctx context.Context,
|
||||
incomingBlk *ethpb.SignedBeaconBlockHeader,
|
||||
) (*ethpb.ProposerSlashing, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "detector.DetectDoublePropose")
|
||||
defer span.End()
|
||||
headersFromIdx, err := dd.slasherDB.BlockHeaders(ctx, incomingBlk.Header.Slot, incomingBlk.Header.ProposerIndex)
|
||||
headersFromIdx, err := d.slasherDB.BlockHeaders(ctx, incomingBlk.Header.Slot, incomingBlk.Header.ProposerIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -41,12 +41,12 @@ func (dd *ProposeDetector) DetectDoublePropose(
|
||||
continue
|
||||
}
|
||||
ps := ðpb.ProposerSlashing{Header_1: incomingBlk, Header_2: blockHeader}
|
||||
if err := dd.slasherDB.SaveProposerSlashing(ctx, status.Active, ps); err != nil {
|
||||
if err := d.slasherDB.SaveProposerSlashing(ctx, status.Active, ps); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ps, nil
|
||||
}
|
||||
if err := dd.slasherDB.SaveBlockHeader(ctx, incomingBlk); err != nil {
|
||||
if err := d.slasherDB.SaveBlockHeader(ctx, incomingBlk); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, nil
|
||||
@@ -54,13 +54,13 @@ func (dd *ProposeDetector) DetectDoublePropose(
|
||||
|
||||
// DetectDoubleProposeNoUpdate detects double proposals for a given block header by db search
|
||||
// without storing the incoming block to db.
|
||||
func (dd *ProposeDetector) DetectDoubleProposeNoUpdate(
|
||||
func (d *ProposeDetector) DetectDoubleProposeNoUpdate(
|
||||
ctx context.Context,
|
||||
incomingBlk *ethpb.BeaconBlockHeader,
|
||||
) (bool, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "detector.DetectDoubleProposeNoUpdate")
|
||||
defer span.End()
|
||||
headersFromIdx, err := dd.slasherDB.BlockHeaders(ctx, incomingBlk.Slot, incomingBlk.ProposerIndex)
|
||||
headersFromIdx, err := d.slasherDB.BlockHeaders(ctx, incomingBlk.Slot, incomingBlk.ProposerIndex)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -96,58 +96,58 @@ func NewService(ctx context.Context, cfg *Config) *Service {
|
||||
}
|
||||
|
||||
// Stop the notifier service.
|
||||
func (ds *Service) Stop() error {
|
||||
ds.cancel()
|
||||
func (s *Service) Stop() error {
|
||||
s.cancel()
|
||||
log.Info("Stopping service")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Status returns an error if detection service is not ready yet.
|
||||
func (ds *Service) Status() error {
|
||||
if ds.status == Ready {
|
||||
func (s *Service) Status() error {
|
||||
if s.status == Ready {
|
||||
return nil
|
||||
}
|
||||
return errors.New(ds.status.String())
|
||||
return errors.New(s.status.String())
|
||||
}
|
||||
|
||||
// Start the detection service runtime.
|
||||
func (ds *Service) Start() {
|
||||
func (s *Service) Start() {
|
||||
// We wait for the gRPC beacon client to be ready and the beacon node
|
||||
// to be fully synced before proceeding.
|
||||
ds.status = Started
|
||||
s.status = Started
|
||||
ch := make(chan bool)
|
||||
sub := ds.notifier.ClientReadyFeed().Subscribe(ch)
|
||||
ds.status = Syncing
|
||||
sub := s.notifier.ClientReadyFeed().Subscribe(ch)
|
||||
s.status = Syncing
|
||||
<-ch
|
||||
sub.Unsubscribe()
|
||||
|
||||
if ds.historicalDetection {
|
||||
if s.historicalDetection {
|
||||
// The detection service runs detection on all historical
|
||||
// chain data since genesis.
|
||||
ds.status = HistoricalDetection
|
||||
ds.detectHistoricalChainData(ds.ctx)
|
||||
s.status = HistoricalDetection
|
||||
s.detectHistoricalChainData(s.ctx)
|
||||
}
|
||||
ds.status = Ready
|
||||
s.status = Ready
|
||||
// We listen to a stream of blocks and attestations from the beacon node.
|
||||
go ds.beaconClient.ReceiveBlocks(ds.ctx)
|
||||
go ds.beaconClient.ReceiveAttestations(ds.ctx)
|
||||
go s.beaconClient.ReceiveBlocks(s.ctx)
|
||||
go s.beaconClient.ReceiveAttestations(s.ctx)
|
||||
// We subscribe to incoming blocks from the beacon node via
|
||||
// our gRPC client to keep detecting slashable offenses.
|
||||
go ds.detectIncomingBlocks(ds.ctx, ds.blocksChan)
|
||||
go ds.detectIncomingAttestations(ds.ctx, ds.attsChan)
|
||||
go s.detectIncomingBlocks(s.ctx, s.blocksChan)
|
||||
go s.detectIncomingAttestations(s.ctx, s.attsChan)
|
||||
}
|
||||
|
||||
func (ds *Service) detectHistoricalChainData(ctx context.Context) {
|
||||
func (s *Service) detectHistoricalChainData(ctx context.Context) {
|
||||
ctx, span := trace.StartSpan(ctx, "detection.detectHistoricalChainData")
|
||||
defer span.End()
|
||||
// We fetch both the latest persisted chain head in our DB as well
|
||||
// as the current chain head from the beacon node via gRPC.
|
||||
latestStoredHead, err := ds.slasherDB.ChainHead(ctx)
|
||||
latestStoredHead, err := s.slasherDB.ChainHead(ctx)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not retrieve chain head from DB")
|
||||
return
|
||||
}
|
||||
currentChainHead, err := ds.chainFetcher.ChainHead(ctx)
|
||||
currentChainHead, err := s.chainFetcher.ChainHead(ctx)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Cannot retrieve chain head from beacon node")
|
||||
return
|
||||
@@ -168,12 +168,12 @@ func (ds *Service) detectHistoricalChainData(ctx context.Context) {
|
||||
log.WithError(err).Errorf("Could not fetch attestations for epoch: %d", epoch)
|
||||
return
|
||||
}
|
||||
indexedAtts, err := ds.beaconClient.RequestHistoricalAttestations(ctx, epoch)
|
||||
indexedAtts, err := s.beaconClient.RequestHistoricalAttestations(ctx, epoch)
|
||||
if err != nil {
|
||||
log.WithError(err).Errorf("Could not fetch attestations for epoch: %d", epoch)
|
||||
return
|
||||
}
|
||||
if err := ds.slasherDB.SaveIndexedAttestations(ctx, indexedAtts); err != nil {
|
||||
if err := s.slasherDB.SaveIndexedAttestations(ctx, indexedAtts); err != nil {
|
||||
log.WithError(err).Error("could not save indexed attestations")
|
||||
return
|
||||
}
|
||||
@@ -183,30 +183,30 @@ func (ds *Service) detectHistoricalChainData(ctx context.Context) {
|
||||
log.WithError(ctx.Err()).Error("context has been canceled, ending detection")
|
||||
return
|
||||
}
|
||||
slashings, err := ds.DetectAttesterSlashings(ctx, att)
|
||||
slashings, err := s.DetectAttesterSlashings(ctx, att)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Could not detect attester slashings")
|
||||
continue
|
||||
}
|
||||
if len(slashings) < 1 {
|
||||
if err := ds.minMaxSpanDetector.UpdateSpans(ctx, att); err != nil {
|
||||
if err := s.minMaxSpanDetector.UpdateSpans(ctx, att); err != nil {
|
||||
log.WithError(err).Error("Could not update spans")
|
||||
}
|
||||
}
|
||||
ds.submitAttesterSlashings(ctx, slashings)
|
||||
s.submitAttesterSlashings(ctx, slashings)
|
||||
|
||||
if err := ds.UpdateHighestAttestation(ctx, att); err != nil {
|
||||
if err := s.UpdateHighestAttestation(ctx, att); err != nil {
|
||||
log.WithError(err).Errorf("Could not update highest attestation")
|
||||
}
|
||||
}
|
||||
latestStoredHead = ðpb.ChainHead{HeadEpoch: epoch}
|
||||
if err := ds.slasherDB.SaveChainHead(ctx, latestStoredHead); err != nil {
|
||||
if err := s.slasherDB.SaveChainHead(ctx, latestStoredHead); err != nil {
|
||||
log.WithError(err).Error("Could not persist chain head to disk")
|
||||
}
|
||||
storedEpoch = epoch
|
||||
ds.slasherDB.RemoveOldestFromCache(ctx)
|
||||
s.slasherDB.RemoveOldestFromCache(ctx)
|
||||
if epoch == currentChainHead.HeadEpoch-1 {
|
||||
currentChainHead, err = ds.chainFetcher.ChainHead(ctx)
|
||||
currentChainHead, err = s.chainFetcher.ChainHead(ctx)
|
||||
if err != nil {
|
||||
log.WithError(err).Error("Cannot retrieve chain head from beacon node")
|
||||
return
|
||||
@@ -219,15 +219,15 @@ func (ds *Service) detectHistoricalChainData(ctx context.Context) {
|
||||
log.Infof("Completed slashing detection on historical chain data up to epoch %d", storedEpoch)
|
||||
}
|
||||
|
||||
func (ds *Service) submitAttesterSlashings(ctx context.Context, slashings []*ethpb.AttesterSlashing) {
|
||||
func (s *Service) submitAttesterSlashings(ctx context.Context, slashings []*ethpb.AttesterSlashing) {
|
||||
ctx, span := trace.StartSpan(ctx, "detection.submitAttesterSlashings")
|
||||
defer span.End()
|
||||
for i := 0; i < len(slashings); i++ {
|
||||
ds.attesterSlashingsFeed.Send(slashings[i])
|
||||
s.attesterSlashingsFeed.Send(slashings[i])
|
||||
}
|
||||
}
|
||||
|
||||
func (ds *Service) submitProposerSlashing(ctx context.Context, slashing *ethpb.ProposerSlashing) {
|
||||
func (s *Service) submitProposerSlashing(ctx context.Context, slashing *ethpb.ProposerSlashing) {
|
||||
ctx, span := trace.StartSpan(ctx, "detection.submitProposerSlashing")
|
||||
defer span.End()
|
||||
if slashing != nil && slashing.Header_1 != nil && slashing.Header_2 != nil {
|
||||
@@ -237,6 +237,6 @@ func (ds *Service) submitProposerSlashing(ctx context.Context, slashing *ethpb.P
|
||||
"proposerIdxHeader1": slashing.Header_1.Header.ProposerIndex,
|
||||
"proposerIdxHeader2": slashing.Header_2.Header.ProposerIndex,
|
||||
}).Info("Found a proposer slashing! Submitting to beacon node")
|
||||
ds.proposerSlashingsFeed.Send(slashing)
|
||||
s.proposerSlashingsFeed.Send(slashing)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,24 +113,24 @@ func NewSlasherNode(cliCtx *cli.Context) (*SlasherNode, error) {
|
||||
}
|
||||
|
||||
// Start the slasher and kick off every registered service.
|
||||
func (s *SlasherNode) Start() {
|
||||
s.lock.Lock()
|
||||
s.services.StartAll()
|
||||
s.lock.Unlock()
|
||||
func (n *SlasherNode) Start() {
|
||||
n.lock.Lock()
|
||||
n.services.StartAll()
|
||||
n.lock.Unlock()
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"version": version.GetVersion(),
|
||||
}).Info("Starting slasher client")
|
||||
|
||||
stop := s.stop
|
||||
stop := n.stop
|
||||
go func() {
|
||||
sigc := make(chan os.Signal, 1)
|
||||
signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM)
|
||||
defer signal.Stop(sigc)
|
||||
<-sigc
|
||||
log.Info("Got interrupt, shutting down...")
|
||||
debug.Exit(s.cliCtx) // Ensure trace and CPU profile data are flushed.
|
||||
go s.Close()
|
||||
debug.Exit(n.cliCtx) // Ensure trace and CPU profile data are flushed.
|
||||
go n.Close()
|
||||
for i := 10; i > 0; i-- {
|
||||
<-sigc
|
||||
if i > 1 {
|
||||
@@ -145,46 +145,46 @@ func (s *SlasherNode) Start() {
|
||||
}
|
||||
|
||||
// Close handles graceful shutdown of the system.
|
||||
func (s *SlasherNode) Close() {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
func (n *SlasherNode) Close() {
|
||||
n.lock.Lock()
|
||||
defer n.lock.Unlock()
|
||||
|
||||
log.Info("Stopping hash slinging slasher")
|
||||
s.cancel()
|
||||
s.services.StopAll()
|
||||
if err := s.db.Close(); err != nil {
|
||||
n.cancel()
|
||||
n.services.StopAll()
|
||||
if err := n.db.Close(); err != nil {
|
||||
log.Errorf("Failed to close database: %v", err)
|
||||
}
|
||||
close(s.stop)
|
||||
close(n.stop)
|
||||
}
|
||||
|
||||
func (s *SlasherNode) registerPrometheusService(cliCtx *cli.Context) error {
|
||||
func (n *SlasherNode) registerPrometheusService(cliCtx *cli.Context) error {
|
||||
var additionalHandlers []prometheus.Handler
|
||||
if cliCtx.IsSet(cmd.EnableBackupWebhookFlag.Name) {
|
||||
additionalHandlers = append(
|
||||
additionalHandlers,
|
||||
prometheus.Handler{
|
||||
Path: "/db/backup",
|
||||
Handler: backuputil.BackupHandler(s.db, cliCtx.String(cmd.BackupWebhookOutputDir.Name)),
|
||||
Handler: backuputil.BackupHandler(n.db, cliCtx.String(cmd.BackupWebhookOutputDir.Name)),
|
||||
},
|
||||
)
|
||||
}
|
||||
service := prometheus.NewService(
|
||||
fmt.Sprintf("%s:%d", s.cliCtx.String(cmd.MonitoringHostFlag.Name), s.cliCtx.Int(flags.MonitoringPortFlag.Name)),
|
||||
s.services,
|
||||
fmt.Sprintf("%s:%d", n.cliCtx.String(cmd.MonitoringHostFlag.Name), n.cliCtx.Int(flags.MonitoringPortFlag.Name)),
|
||||
n.services,
|
||||
additionalHandlers...,
|
||||
)
|
||||
logrus.AddHook(prometheus.NewLogrusCollector())
|
||||
return s.services.RegisterService(service)
|
||||
return n.services.RegisterService(service)
|
||||
}
|
||||
|
||||
func (s *SlasherNode) startDB() error {
|
||||
baseDir := s.cliCtx.String(cmd.DataDirFlag.Name)
|
||||
clearDB := s.cliCtx.Bool(cmd.ClearDB.Name)
|
||||
forceClearDB := s.cliCtx.Bool(cmd.ForceClearDB.Name)
|
||||
func (n *SlasherNode) startDB() error {
|
||||
baseDir := n.cliCtx.String(cmd.DataDirFlag.Name)
|
||||
clearDB := n.cliCtx.Bool(cmd.ClearDB.Name)
|
||||
forceClearDB := n.cliCtx.Bool(cmd.ForceClearDB.Name)
|
||||
dbPath := path.Join(baseDir, kv.SlasherDbDirName)
|
||||
spanCacheSize := s.cliCtx.Int(flags.SpanCacheSize.Name)
|
||||
highestAttCacheSize := s.cliCtx.Int(flags.HighestAttCacheSize.Name)
|
||||
spanCacheSize := n.cliCtx.Int(flags.SpanCacheSize.Name)
|
||||
highestAttCacheSize := n.cliCtx.Int(flags.HighestAttCacheSize.Name)
|
||||
cfg := &kv.Config{SpanCacheSize: spanCacheSize, HighestAttestationCacheSize: highestAttCacheSize}
|
||||
log.Infof("Span cache size has been set to: %d", spanCacheSize)
|
||||
d, err := db.NewDB(dbPath, cfg)
|
||||
@@ -215,69 +215,69 @@ func (s *SlasherNode) startDB() error {
|
||||
}
|
||||
}
|
||||
log.WithField("database-path", baseDir).Info("Checking DB")
|
||||
s.db = d
|
||||
n.db = d
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *SlasherNode) registerBeaconClientService() error {
|
||||
beaconCert := s.cliCtx.String(flags.BeaconCertFlag.Name)
|
||||
beaconProvider := s.cliCtx.String(flags.BeaconRPCProviderFlag.Name)
|
||||
func (n *SlasherNode) registerBeaconClientService() error {
|
||||
beaconCert := n.cliCtx.String(flags.BeaconCertFlag.Name)
|
||||
beaconProvider := n.cliCtx.String(flags.BeaconRPCProviderFlag.Name)
|
||||
if beaconProvider == "" {
|
||||
beaconProvider = flags.BeaconRPCProviderFlag.Value
|
||||
}
|
||||
|
||||
bs, err := beaconclient.NewService(s.ctx, &beaconclient.Config{
|
||||
bs, err := beaconclient.NewService(n.ctx, &beaconclient.Config{
|
||||
BeaconCert: beaconCert,
|
||||
SlasherDB: s.db,
|
||||
SlasherDB: n.db,
|
||||
BeaconProvider: beaconProvider,
|
||||
AttesterSlashingsFeed: s.attesterSlashingsFeed,
|
||||
ProposerSlashingsFeed: s.proposerSlashingsFeed,
|
||||
AttesterSlashingsFeed: n.attesterSlashingsFeed,
|
||||
ProposerSlashingsFeed: n.proposerSlashingsFeed,
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to initialize beacon client")
|
||||
}
|
||||
return s.services.RegisterService(bs)
|
||||
return n.services.RegisterService(bs)
|
||||
}
|
||||
|
||||
func (s *SlasherNode) registerDetectionService() error {
|
||||
func (n *SlasherNode) registerDetectionService() error {
|
||||
var bs *beaconclient.Service
|
||||
if err := s.services.FetchService(&bs); err != nil {
|
||||
if err := n.services.FetchService(&bs); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ds := detection.NewService(s.ctx, &detection.Config{
|
||||
ds := detection.NewService(n.ctx, &detection.Config{
|
||||
Notifier: bs,
|
||||
SlasherDB: s.db,
|
||||
SlasherDB: n.db,
|
||||
BeaconClient: bs,
|
||||
ChainFetcher: bs,
|
||||
AttesterSlashingsFeed: s.attesterSlashingsFeed,
|
||||
ProposerSlashingsFeed: s.proposerSlashingsFeed,
|
||||
HistoricalDetection: s.cliCtx.Bool(flags.EnableHistoricalDetectionFlag.Name),
|
||||
AttesterSlashingsFeed: n.attesterSlashingsFeed,
|
||||
ProposerSlashingsFeed: n.proposerSlashingsFeed,
|
||||
HistoricalDetection: n.cliCtx.Bool(flags.EnableHistoricalDetectionFlag.Name),
|
||||
})
|
||||
return s.services.RegisterService(ds)
|
||||
return n.services.RegisterService(ds)
|
||||
}
|
||||
|
||||
func (s *SlasherNode) registerRPCService() error {
|
||||
func (n *SlasherNode) registerRPCService() error {
|
||||
var detectionService *detection.Service
|
||||
if err := s.services.FetchService(&detectionService); err != nil {
|
||||
if err := n.services.FetchService(&detectionService); err != nil {
|
||||
return err
|
||||
}
|
||||
var bs *beaconclient.Service
|
||||
if err := s.services.FetchService(&bs); err != nil {
|
||||
if err := n.services.FetchService(&bs); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
host := s.cliCtx.String(flags.RPCHost.Name)
|
||||
port := s.cliCtx.String(flags.RPCPort.Name)
|
||||
cert := s.cliCtx.String(flags.CertFlag.Name)
|
||||
key := s.cliCtx.String(flags.KeyFlag.Name)
|
||||
rpcService := rpc.NewService(s.ctx, &rpc.Config{
|
||||
host := n.cliCtx.String(flags.RPCHost.Name)
|
||||
port := n.cliCtx.String(flags.RPCPort.Name)
|
||||
cert := n.cliCtx.String(flags.CertFlag.Name)
|
||||
key := n.cliCtx.String(flags.KeyFlag.Name)
|
||||
rpcService := rpc.NewService(n.ctx, &rpc.Config{
|
||||
Host: host,
|
||||
Port: port,
|
||||
CertFlag: cert,
|
||||
KeyFlag: key,
|
||||
Detector: detectionService,
|
||||
SlasherDB: s.db,
|
||||
SlasherDB: n.db,
|
||||
BeaconClient: bs,
|
||||
})
|
||||
|
||||
return s.services.RegisterService(rpcService)
|
||||
return n.services.RegisterService(rpcService)
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ type Server struct {
|
||||
}
|
||||
|
||||
// HighestAttestations returns the highest observed attestation source and epoch for a given validator id.
|
||||
func (ss *Server) HighestAttestations(ctx context.Context, req *slashpb.HighestAttestationRequest) (*slashpb.HighestAttestationResponse, error) {
|
||||
func (s *Server) HighestAttestations(ctx context.Context, req *slashpb.HighestAttestationRequest) (*slashpb.HighestAttestationResponse, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "history.HighestAttestations")
|
||||
defer span.End()
|
||||
|
||||
@@ -43,7 +43,7 @@ func (ss *Server) HighestAttestations(ctx context.Context, req *slashpb.HighestA
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
|
||||
res, err := ss.slasherDB.HighestAttestation(ctx, id)
|
||||
res, err := s.slasherDB.HighestAttestation(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -63,7 +63,7 @@ func (ss *Server) HighestAttestations(ctx context.Context, req *slashpb.HighestA
|
||||
|
||||
// IsSlashableAttestation returns an attester slashing if the attestation submitted
|
||||
// is a slashable vote.
|
||||
func (ss *Server) IsSlashableAttestation(ctx context.Context, req *ethpb.IndexedAttestation) (*slashpb.AttesterSlashingResponse, error) {
|
||||
func (s *Server) IsSlashableAttestation(ctx context.Context, req *ethpb.IndexedAttestation) (*slashpb.AttesterSlashingResponse, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "detection.IsSlashableAttestation")
|
||||
defer span.End()
|
||||
|
||||
@@ -91,7 +91,7 @@ func (ss *Server) IsSlashableAttestation(ctx context.Context, req *ethpb.Indexed
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gvr, err := ss.beaconClient.GenesisValidatorsRoot(ctx)
|
||||
gvr, err := s.beaconClient.GenesisValidatorsRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -104,7 +104,7 @@ func (ss *Server) IsSlashableAttestation(ctx context.Context, req *ethpb.Indexed
|
||||
return nil, err
|
||||
}
|
||||
indices := req.AttestingIndices
|
||||
pkMap, err := ss.beaconClient.FindOrGetPublicKeys(ctx, indices)
|
||||
pkMap, err := s.beaconClient.FindOrGetPublicKeys(ctx, indices)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -123,19 +123,19 @@ func (ss *Server) IsSlashableAttestation(ctx context.Context, req *ethpb.Indexed
|
||||
return nil, status.Errorf(codes.Internal, "could not verify indexed attestation signature: %v: %v", req, err)
|
||||
}
|
||||
|
||||
ss.attestationLock.Lock()
|
||||
defer ss.attestationLock.Unlock()
|
||||
s.attestationLock.Lock()
|
||||
defer s.attestationLock.Unlock()
|
||||
|
||||
slashings, err := ss.detector.DetectAttesterSlashings(ctx, req)
|
||||
slashings, err := s.detector.DetectAttesterSlashings(ctx, req)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "could not detect attester slashings for attestation: %v: %v", req, err)
|
||||
}
|
||||
if len(slashings) < 1 {
|
||||
if err := ss.slasherDB.SaveIndexedAttestation(ctx, req); err != nil {
|
||||
if err := s.slasherDB.SaveIndexedAttestation(ctx, req); err != nil {
|
||||
log.WithError(err).Error("Could not save indexed attestation")
|
||||
return nil, status.Errorf(codes.Internal, "could not save indexed attestation: %v: %v", req, err)
|
||||
}
|
||||
if err := ss.detector.UpdateSpans(ctx, req); err != nil {
|
||||
if err := s.detector.UpdateSpans(ctx, req); err != nil {
|
||||
log.WithError(err).Error("could not update spans")
|
||||
return nil, status.Errorf(codes.Internal, "failed to update spans: %v: %v", req, err)
|
||||
}
|
||||
@@ -147,7 +147,7 @@ func (ss *Server) IsSlashableAttestation(ctx context.Context, req *ethpb.Indexed
|
||||
|
||||
// IsSlashableBlock returns an proposer slashing if the block submitted
|
||||
// is a double proposal.
|
||||
func (ss *Server) IsSlashableBlock(ctx context.Context, req *ethpb.SignedBeaconBlockHeader) (*slashpb.ProposerSlashingResponse, error) {
|
||||
func (s *Server) IsSlashableBlock(ctx context.Context, req *ethpb.SignedBeaconBlockHeader) (*slashpb.ProposerSlashingResponse, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "detection.IsSlashableBlock")
|
||||
defer span.End()
|
||||
|
||||
@@ -165,7 +165,7 @@ func (ss *Server) IsSlashableBlock(ctx context.Context, req *ethpb.SignedBeaconB
|
||||
if req.Signature == nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "nil signature provided")
|
||||
}
|
||||
gvr, err := ss.beaconClient.GenesisValidatorsRoot(ctx)
|
||||
gvr, err := s.beaconClient.GenesisValidatorsRoot(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -178,7 +178,7 @@ func (ss *Server) IsSlashableBlock(ctx context.Context, req *ethpb.SignedBeaconB
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pkMap, err := ss.beaconClient.FindOrGetPublicKeys(ctx, []uint64{req.Header.ProposerIndex})
|
||||
pkMap, err := s.beaconClient.FindOrGetPublicKeys(ctx, []uint64{req.Header.ProposerIndex})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -189,10 +189,10 @@ func (ss *Server) IsSlashableBlock(ctx context.Context, req *ethpb.SignedBeaconB
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ss.proposeLock.Lock()
|
||||
defer ss.proposeLock.Unlock()
|
||||
s.proposeLock.Lock()
|
||||
defer s.proposeLock.Unlock()
|
||||
|
||||
slashing, err := ss.detector.DetectDoubleProposals(ctx, req)
|
||||
slashing, err := s.detector.DetectDoubleProposals(ctx, req)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "could not detect proposer slashing for block: %v: %v", req, err)
|
||||
}
|
||||
@@ -208,9 +208,9 @@ func (ss *Server) IsSlashableBlock(ctx context.Context, req *ethpb.SignedBeaconB
|
||||
|
||||
// IsSlashableAttestationNoUpdate returns true if the attestation submitted
|
||||
// is a slashable vote (no db update is being done).
|
||||
func (ss *Server) IsSlashableAttestationNoUpdate(ctx context.Context, req *ethpb.IndexedAttestation) (*slashpb.Slashable, error) {
|
||||
func (s *Server) IsSlashableAttestationNoUpdate(ctx context.Context, req *ethpb.IndexedAttestation) (*slashpb.Slashable, error) {
|
||||
sl := &slashpb.Slashable{}
|
||||
slashings, err := ss.detector.DetectAttesterSlashings(ctx, req)
|
||||
slashings, err := s.detector.DetectAttesterSlashings(ctx, req)
|
||||
if err != nil {
|
||||
return sl, status.Errorf(codes.Internal, "could not detect attester slashings for attestation: %v: %v", req, err)
|
||||
}
|
||||
@@ -223,9 +223,9 @@ func (ss *Server) IsSlashableAttestationNoUpdate(ctx context.Context, req *ethpb
|
||||
|
||||
// IsSlashableBlockNoUpdate returns true if the block submitted
|
||||
// is slashable (no db update is being done).
|
||||
func (ss *Server) IsSlashableBlockNoUpdate(ctx context.Context, req *ethpb.BeaconBlockHeader) (*slashpb.Slashable, error) {
|
||||
func (s *Server) IsSlashableBlockNoUpdate(ctx context.Context, req *ethpb.BeaconBlockHeader) (*slashpb.Slashable, error) {
|
||||
sl := &slashpb.Slashable{}
|
||||
slash, err := ss.detector.DetectDoubleProposeNoUpdate(ctx, req)
|
||||
slash, err := s.detector.DetectDoubleProposeNoUpdate(ctx, req)
|
||||
if err != nil {
|
||||
return sl, status.Errorf(codes.Internal, "could not detect proposer slashing for block: %v: %v", req, err)
|
||||
}
|
||||
|
||||
@@ -22,47 +22,47 @@ type Wallet struct {
|
||||
}
|
||||
|
||||
// AccountNames --
|
||||
func (m *Wallet) AccountNames() ([]string, error) {
|
||||
m.lock.RLock()
|
||||
defer m.lock.RUnlock()
|
||||
func (w *Wallet) AccountNames() ([]string, error) {
|
||||
w.lock.RLock()
|
||||
defer w.lock.RUnlock()
|
||||
names := make([]string, 0)
|
||||
for name := range m.AccountPasswords {
|
||||
for name := range w.AccountPasswords {
|
||||
names = append(names, name)
|
||||
}
|
||||
return names, nil
|
||||
}
|
||||
|
||||
// AccountsDir --
|
||||
func (m *Wallet) AccountsDir() string {
|
||||
return m.InnerAccountsDir
|
||||
func (w *Wallet) AccountsDir() string {
|
||||
return w.InnerAccountsDir
|
||||
}
|
||||
|
||||
// Exists --
|
||||
func (m *Wallet) Exists() (bool, error) {
|
||||
return len(m.Directories) > 0, nil
|
||||
func (w *Wallet) Exists() (bool, error) {
|
||||
return len(w.Directories) > 0, nil
|
||||
}
|
||||
|
||||
// Password --
|
||||
func (m *Wallet) Password() string {
|
||||
return m.WalletPassword
|
||||
func (w *Wallet) Password() string {
|
||||
return w.WalletPassword
|
||||
}
|
||||
|
||||
// WriteFileAtPath --
|
||||
func (m *Wallet) WriteFileAtPath(_ context.Context, pathName, fileName string, data []byte) error {
|
||||
m.lock.Lock()
|
||||
defer m.lock.Unlock()
|
||||
if m.Files[pathName] == nil {
|
||||
m.Files[pathName] = make(map[string][]byte)
|
||||
func (w *Wallet) WriteFileAtPath(_ context.Context, pathName, fileName string, data []byte) error {
|
||||
w.lock.Lock()
|
||||
defer w.lock.Unlock()
|
||||
if w.Files[pathName] == nil {
|
||||
w.Files[pathName] = make(map[string][]byte)
|
||||
}
|
||||
m.Files[pathName][fileName] = data
|
||||
w.Files[pathName][fileName] = data
|
||||
return nil
|
||||
}
|
||||
|
||||
// ReadFileAtPath --
|
||||
func (m *Wallet) ReadFileAtPath(_ context.Context, pathName, fileName string) ([]byte, error) {
|
||||
m.lock.RLock()
|
||||
defer m.lock.RUnlock()
|
||||
for f, v := range m.Files[pathName] {
|
||||
func (w *Wallet) ReadFileAtPath(_ context.Context, pathName, fileName string) ([]byte, error) {
|
||||
w.lock.RLock()
|
||||
defer w.lock.RUnlock()
|
||||
for f, v := range w.Files[pathName] {
|
||||
if strings.Contains(fileName, f) {
|
||||
return v, nil
|
||||
}
|
||||
@@ -71,6 +71,6 @@ func (m *Wallet) ReadFileAtPath(_ context.Context, pathName, fileName string) ([
|
||||
}
|
||||
|
||||
// InitializeKeymanager --
|
||||
func (m *Wallet) InitializeKeymanager(_ context.Context) (keymanager.IKeymanager, error) {
|
||||
func (w *Wallet) InitializeKeymanager(_ context.Context) (keymanager.IKeymanager, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
@@ -51,11 +51,11 @@ var (
|
||||
|
||||
// CheckSlashableAttestation verifies an incoming attestation is
|
||||
// not a double vote for a validator public key nor a surround vote.
|
||||
func (store *Store) CheckSlashableAttestation(
|
||||
func (s *Store) CheckSlashableAttestation(
|
||||
ctx context.Context, pubKey [48]byte, signingRoot [32]byte, att *ethpb.IndexedAttestation,
|
||||
) (SlashingKind, error) {
|
||||
var slashKind SlashingKind
|
||||
err := store.view(func(tx *bolt.Tx) error {
|
||||
err := s.view(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(pubKeysBucket)
|
||||
pkBucket := bucket.Bucket(pubKey[:])
|
||||
if pkBucket == nil {
|
||||
@@ -128,10 +128,10 @@ func (store *Store) CheckSlashableAttestation(
|
||||
|
||||
// SaveAttestationForPubKey saves an attestation for a validator public
|
||||
// key for local validator slashing protection.
|
||||
func (store *Store) SaveAttestationForPubKey(
|
||||
func (s *Store) SaveAttestationForPubKey(
|
||||
ctx context.Context, pubKey [48]byte, signingRoot [32]byte, att *ethpb.IndexedAttestation,
|
||||
) error {
|
||||
store.batchedAttestationsChan <- &attestationRecord{
|
||||
s.batchedAttestationsChan <- &attestationRecord{
|
||||
pubKey: pubKey,
|
||||
source: att.Data.Source.Epoch,
|
||||
target: att.Data.Target.Epoch,
|
||||
@@ -144,7 +144,7 @@ func (store *Store) SaveAttestationForPubKey(
|
||||
// to prevent blocking the sender from notifying us of the result.
|
||||
responseChan := make(chan saveAttestationsResponse, 1)
|
||||
defer close(responseChan)
|
||||
sub := store.batchAttestationsFlushedFeed.Subscribe(responseChan)
|
||||
sub := s.batchAttestationsFlushedFeed.Subscribe(responseChan)
|
||||
defer sub.Unsubscribe()
|
||||
res := <-responseChan
|
||||
return res.err
|
||||
@@ -156,25 +156,25 @@ func (store *Store) SaveAttestationForPubKey(
|
||||
// Based on whichever comes first, this function then proceeds
|
||||
// to flush the attestations to the DB all at once in a single boltDB
|
||||
// transaction for efficiency. Then, batched attestations slice is emptied out.
|
||||
func (store *Store) batchAttestationWrites(ctx context.Context) {
|
||||
func (s *Store) batchAttestationWrites(ctx context.Context) {
|
||||
ticker := time.NewTicker(attestationBatchWriteInterval)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case v := <-store.batchedAttestationsChan:
|
||||
store.batchedAttestations = append(store.batchedAttestations, v)
|
||||
if len(store.batchedAttestations) == attestationBatchCapacity {
|
||||
case v := <-s.batchedAttestationsChan:
|
||||
s.batchedAttestations = append(s.batchedAttestations, v)
|
||||
if len(s.batchedAttestations) == attestationBatchCapacity {
|
||||
log.WithField("numRecords", attestationBatchCapacity).Debug(
|
||||
"Reached max capacity of batched attestation records, flushing to DB",
|
||||
)
|
||||
store.flushAttestationRecords(ctx)
|
||||
s.flushAttestationRecords(ctx)
|
||||
}
|
||||
case <-ticker.C:
|
||||
if len(store.batchedAttestations) > 0 {
|
||||
log.WithField("numRecords", len(store.batchedAttestations)).Debug(
|
||||
if len(s.batchedAttestations) > 0 {
|
||||
log.WithField("numRecords", len(s.batchedAttestations)).Debug(
|
||||
"Batched attestation records write interval reached, flushing to DB",
|
||||
)
|
||||
store.flushAttestationRecords(ctx)
|
||||
s.flushAttestationRecords(ctx)
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return
|
||||
@@ -186,17 +186,17 @@ func (store *Store) batchAttestationWrites(ctx context.Context) {
|
||||
// and resets the list of batched attestations for future writes.
|
||||
// This function notifies all subscribers for flushed attestations
|
||||
// of the result of the save operation.
|
||||
func (store *Store) flushAttestationRecords(ctx context.Context) {
|
||||
err := store.saveAttestationRecords(ctx, store.batchedAttestations)
|
||||
func (s *Store) flushAttestationRecords(ctx context.Context) {
|
||||
err := s.saveAttestationRecords(ctx, s.batchedAttestations)
|
||||
// If there was no error, we reset the batched attestations slice.
|
||||
if err == nil {
|
||||
log.Debug("Successfully flushed batched attestations to DB")
|
||||
store.batchedAttestations = make([]*attestationRecord, 0, attestationBatchCapacity)
|
||||
s.batchedAttestations = make([]*attestationRecord, 0, attestationBatchCapacity)
|
||||
}
|
||||
// Forward the error, if any, to all subscribers via an event feed.
|
||||
// We use a struct wrapper around the error as the event feed
|
||||
// cannot handle sending a raw `nil` in case there is no error.
|
||||
store.batchAttestationsFlushedFeed.Send(saveAttestationsResponse{
|
||||
s.batchAttestationsFlushedFeed.Send(saveAttestationsResponse{
|
||||
err: err,
|
||||
})
|
||||
}
|
||||
@@ -204,10 +204,10 @@ func (store *Store) flushAttestationRecords(ctx context.Context) {
|
||||
// Saves a list of attestation records to the database in a single boltDB
|
||||
// transaction to minimize write lock contention compared to doing them
|
||||
// all in individual, isolated boltDB transactions.
|
||||
func (store *Store) saveAttestationRecords(ctx context.Context, atts []*attestationRecord) error {
|
||||
func (s *Store) saveAttestationRecords(ctx context.Context, atts []*attestationRecord) error {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.saveAttestationRecords")
|
||||
defer span.End()
|
||||
return store.update(func(tx *bolt.Tx) error {
|
||||
return s.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(pubKeysBucket)
|
||||
for _, att := range atts {
|
||||
pkBucket, err := bucket.CreateBucketIfNotExists(att.pubKey[:])
|
||||
@@ -285,12 +285,12 @@ func (store *Store) saveAttestationRecords(ctx context.Context, atts []*attestat
|
||||
}
|
||||
|
||||
// AttestedPublicKeys retrieves all public keys in our attestation history bucket.
|
||||
func (store *Store) AttestedPublicKeys(ctx context.Context) ([][48]byte, error) {
|
||||
func (s *Store) AttestedPublicKeys(ctx context.Context) ([][48]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.AttestedPublicKeys")
|
||||
defer span.End()
|
||||
var err error
|
||||
attestedPublicKeys := make([][48]byte, 0)
|
||||
err = store.view(func(tx *bolt.Tx) error {
|
||||
err = s.view(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(deprecatedAttestationHistoryBucket)
|
||||
return bucket.ForEach(func(key []byte, _ []byte) error {
|
||||
pubKeyBytes := [48]byte{}
|
||||
@@ -304,13 +304,13 @@ func (store *Store) AttestedPublicKeys(ctx context.Context) ([][48]byte, error)
|
||||
|
||||
// LowestSignedSourceEpoch returns the lowest signed source epoch for a validator public key.
|
||||
// If no data exists, returning 0 is a sensible default.
|
||||
func (store *Store) LowestSignedSourceEpoch(ctx context.Context, publicKey [48]byte) (uint64, error) {
|
||||
func (s *Store) LowestSignedSourceEpoch(ctx context.Context, publicKey [48]byte) (uint64, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.LowestSignedSourceEpoch")
|
||||
defer span.End()
|
||||
|
||||
var err error
|
||||
var lowestSignedSourceEpoch uint64
|
||||
err = store.view(func(tx *bolt.Tx) error {
|
||||
err = s.view(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(lowestSignedSourceBucket)
|
||||
lowestSignedSourceBytes := bucket.Get(publicKey[:])
|
||||
// 8 because bytesutil.BytesToUint64BigEndian will return 0 if input is less than 8 bytes.
|
||||
@@ -325,13 +325,13 @@ func (store *Store) LowestSignedSourceEpoch(ctx context.Context, publicKey [48]b
|
||||
|
||||
// LowestSignedTargetEpoch returns the lowest signed target epoch for a validator public key.
|
||||
// If no data exists, returning 0 is a sensible default.
|
||||
func (store *Store) LowestSignedTargetEpoch(ctx context.Context, publicKey [48]byte) (uint64, error) {
|
||||
func (s *Store) LowestSignedTargetEpoch(ctx context.Context, publicKey [48]byte) (uint64, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.LowestSignedTargetEpoch")
|
||||
defer span.End()
|
||||
|
||||
var err error
|
||||
var lowestSignedTargetEpoch uint64
|
||||
err = store.view(func(tx *bolt.Tx) error {
|
||||
err = s.view(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(lowestSignedTargetBucket)
|
||||
lowestSignedTargetBytes := bucket.Get(publicKey[:])
|
||||
// 8 because bytesutil.BytesToUint64BigEndian will return 0 if input is less than 8 bytes.
|
||||
|
||||
@@ -44,30 +44,30 @@ type Store struct {
|
||||
}
|
||||
|
||||
// Close closes the underlying boltdb database.
|
||||
func (store *Store) Close() error {
|
||||
prometheus.Unregister(createBoltCollector(store.db))
|
||||
return store.db.Close()
|
||||
func (s *Store) Close() error {
|
||||
prometheus.Unregister(createBoltCollector(s.db))
|
||||
return s.db.Close()
|
||||
}
|
||||
|
||||
func (store *Store) update(fn func(*bolt.Tx) error) error {
|
||||
return store.db.Update(fn)
|
||||
func (s *Store) update(fn func(*bolt.Tx) error) error {
|
||||
return s.db.Update(fn)
|
||||
}
|
||||
func (store *Store) view(fn func(*bolt.Tx) error) error {
|
||||
return store.db.View(fn)
|
||||
func (s *Store) view(fn func(*bolt.Tx) error) error {
|
||||
return s.db.View(fn)
|
||||
}
|
||||
|
||||
// ClearDB removes any previously stored data at the configured data directory.
|
||||
func (store *Store) ClearDB() error {
|
||||
if _, err := os.Stat(store.databasePath); os.IsNotExist(err) {
|
||||
func (s *Store) ClearDB() error {
|
||||
if _, err := os.Stat(s.databasePath); os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
prometheus.Unregister(createBoltCollector(store.db))
|
||||
return os.Remove(filepath.Join(store.databasePath, ProtectionDbFileName))
|
||||
prometheus.Unregister(createBoltCollector(s.db))
|
||||
return os.Remove(filepath.Join(s.databasePath, ProtectionDbFileName))
|
||||
}
|
||||
|
||||
// DatabasePath at which this database writes files.
|
||||
func (store *Store) DatabasePath() string {
|
||||
return store.databasePath
|
||||
func (s *Store) DatabasePath() string {
|
||||
return s.databasePath
|
||||
}
|
||||
|
||||
func createBuckets(tx *bolt.Tx, buckets ...[]byte) error {
|
||||
@@ -146,8 +146,8 @@ func NewKVStore(ctx context.Context, dirPath string, pubKeys [][48]byte) (*Store
|
||||
}
|
||||
|
||||
// UpdatePublicKeysBuckets for a specified list of keys.
|
||||
func (store *Store) UpdatePublicKeysBuckets(pubKeys [][48]byte) error {
|
||||
return store.update(func(tx *bolt.Tx) error {
|
||||
func (s *Store) UpdatePublicKeysBuckets(pubKeys [][48]byte) error {
|
||||
return s.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(historicProposalsBucket)
|
||||
for _, pubKey := range pubKeys {
|
||||
if _, err := bucket.CreateBucketIfNotExists(pubKey[:]); err != nil {
|
||||
@@ -159,9 +159,9 @@ func (store *Store) UpdatePublicKeysBuckets(pubKeys [][48]byte) error {
|
||||
}
|
||||
|
||||
// Size returns the db size in bytes.
|
||||
func (store *Store) Size() (int64, error) {
|
||||
func (s *Store) Size() (int64, error) {
|
||||
var size int64
|
||||
err := store.db.View(func(tx *bolt.Tx) error {
|
||||
err := s.db.View(func(tx *bolt.Tx) error {
|
||||
size = tx.Size()
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -29,21 +29,21 @@ type deprecatedHistoryData struct {
|
||||
// deprecatedEncodedAttestingHistory encapsulated history data.
|
||||
type deprecatedEncodedAttestingHistory []byte
|
||||
|
||||
func (hd deprecatedEncodedAttestingHistory) assertSize() error {
|
||||
if hd == nil || len(hd) < minimalSize {
|
||||
return fmt.Errorf("encapsulated data size: %d is smaller then minimal size: %d", len(hd), minimalSize)
|
||||
func (dh deprecatedEncodedAttestingHistory) assertSize() error {
|
||||
if dh == nil || len(dh) < minimalSize {
|
||||
return fmt.Errorf("encapsulated data size: %d is smaller then minimal size: %d", len(dh), minimalSize)
|
||||
}
|
||||
if (len(hd)-minimalSize)%historySize != 0 {
|
||||
return fmt.Errorf("encapsulated data size: %d is not a multiple of entry size: %d", len(hd), historySize)
|
||||
if (len(dh)-minimalSize)%historySize != 0 {
|
||||
return fmt.Errorf("encapsulated data size: %d is not a multiple of entry size: %d", len(dh), historySize)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *deprecatedHistoryData) isEmpty() bool {
|
||||
if h == (*deprecatedHistoryData)(nil) {
|
||||
func (dhd *deprecatedHistoryData) isEmpty() bool {
|
||||
if dhd == (*deprecatedHistoryData)(nil) {
|
||||
return true
|
||||
}
|
||||
if h.Source == params.BeaconConfig().FarFutureEpoch {
|
||||
if dhd.Source == params.BeaconConfig().FarFutureEpoch {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -73,53 +73,53 @@ func newDeprecatedAttestingHistory(target uint64) deprecatedEncodedAttestingHist
|
||||
return enc
|
||||
}
|
||||
|
||||
func (hd deprecatedEncodedAttestingHistory) getLatestEpochWritten(ctx context.Context) (uint64, error) {
|
||||
if err := hd.assertSize(); err != nil {
|
||||
func (dh deprecatedEncodedAttestingHistory) getLatestEpochWritten(ctx context.Context) (uint64, error) {
|
||||
if err := dh.assertSize(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return bytesutil.FromBytes8(hd[:latestEpochWrittenSize]), nil
|
||||
return bytesutil.FromBytes8(dh[:latestEpochWrittenSize]), nil
|
||||
}
|
||||
|
||||
func (hd deprecatedEncodedAttestingHistory) setLatestEpochWritten(ctx context.Context, latestEpochWritten uint64) (deprecatedEncodedAttestingHistory, error) {
|
||||
if err := hd.assertSize(); err != nil {
|
||||
func (dh deprecatedEncodedAttestingHistory) setLatestEpochWritten(ctx context.Context, latestEpochWritten uint64) (deprecatedEncodedAttestingHistory, error) {
|
||||
if err := dh.assertSize(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(hd[:latestEpochWrittenSize], bytesutil.Uint64ToBytesLittleEndian(latestEpochWritten))
|
||||
return hd, nil
|
||||
copy(dh[:latestEpochWrittenSize], bytesutil.Uint64ToBytesLittleEndian(latestEpochWritten))
|
||||
return dh, nil
|
||||
}
|
||||
|
||||
func (hd deprecatedEncodedAttestingHistory) getTargetData(ctx context.Context, target uint64) (*deprecatedHistoryData, error) {
|
||||
if err := hd.assertSize(); err != nil {
|
||||
func (dh deprecatedEncodedAttestingHistory) getTargetData(ctx context.Context, target uint64) (*deprecatedHistoryData, error) {
|
||||
if err := dh.assertSize(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Cursor for the location to read target epoch from.
|
||||
// Modulus of target epoch X weak subjectivity period in order to have maximum size to the encapsulated data array.
|
||||
cursor := (target%params.BeaconConfig().WeakSubjectivityPeriod)*historySize + latestEpochWrittenSize
|
||||
if uint64(len(hd)) < cursor+historySize {
|
||||
if uint64(len(dh)) < cursor+historySize {
|
||||
return nil, nil
|
||||
}
|
||||
history := &deprecatedHistoryData{}
|
||||
history.Source = bytesutil.FromBytes8(hd[cursor : cursor+sourceSize])
|
||||
history.Source = bytesutil.FromBytes8(dh[cursor : cursor+sourceSize])
|
||||
sr := make([]byte, 32)
|
||||
copy(sr, hd[cursor+sourceSize:cursor+historySize])
|
||||
copy(sr, dh[cursor+sourceSize:cursor+historySize])
|
||||
history.SigningRoot = sr
|
||||
return history, nil
|
||||
}
|
||||
|
||||
func (hd deprecatedEncodedAttestingHistory) setTargetData(ctx context.Context, target uint64, historyData *deprecatedHistoryData) (deprecatedEncodedAttestingHistory, error) {
|
||||
if err := hd.assertSize(); err != nil {
|
||||
func (dh deprecatedEncodedAttestingHistory) setTargetData(ctx context.Context, target uint64, historyData *deprecatedHistoryData) (deprecatedEncodedAttestingHistory, error) {
|
||||
if err := dh.assertSize(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Cursor for the location to write target epoch to.
|
||||
// Modulus of target epoch X weak subjectivity period in order to have maximum size to the encapsulated data array.
|
||||
cursor := latestEpochWrittenSize + (target%params.BeaconConfig().WeakSubjectivityPeriod)*historySize
|
||||
|
||||
if uint64(len(hd)) < cursor+historySize {
|
||||
ext := make([]byte, cursor+historySize-uint64(len(hd)))
|
||||
hd = append(hd, ext...)
|
||||
if uint64(len(dh)) < cursor+historySize {
|
||||
ext := make([]byte, cursor+historySize-uint64(len(dh)))
|
||||
dh = append(dh, ext...)
|
||||
}
|
||||
copy(hd[cursor:cursor+sourceSize], bytesutil.Uint64ToBytesLittleEndian(historyData.Source))
|
||||
copy(hd[cursor+sourceSize:cursor+sourceSize+signingRootSize], historyData.SigningRoot)
|
||||
copy(dh[cursor:cursor+sourceSize], bytesutil.Uint64ToBytesLittleEndian(historyData.Source))
|
||||
copy(dh[cursor+sourceSize:cursor+sourceSize+signingRootSize], historyData.SigningRoot)
|
||||
|
||||
return hd, nil
|
||||
return dh, nil
|
||||
}
|
||||
|
||||
@@ -16,11 +16,11 @@ var migrationOptimalAttesterProtectionKey = []byte("optimal_attester_protection_
|
||||
// stored attesting history as large, 2Mb arrays per validator, we need to perform
|
||||
// this migration differently than the rest, ensuring we perform each expensive bolt
|
||||
// update in its own transaction to prevent having everything on the heap.
|
||||
func (store *Store) migrateOptimalAttesterProtectionUp(ctx context.Context) error {
|
||||
func (s *Store) migrateOptimalAttesterProtectionUp(ctx context.Context) error {
|
||||
publicKeyBytes := make([][]byte, 0)
|
||||
attestingHistoryBytes := make([][]byte, 0)
|
||||
numKeys := 0
|
||||
err := store.db.Update(func(tx *bolt.Tx) error {
|
||||
err := s.db.Update(func(tx *bolt.Tx) error {
|
||||
mb := tx.Bucket(migrationsBucket)
|
||||
if b := mb.Get(migrationOptimalAttesterProtectionKey); bytes.Equal(b, migrationCompleted) {
|
||||
return nil // Migration already completed.
|
||||
@@ -65,7 +65,7 @@ func (store *Store) migrateOptimalAttesterProtectionUp(ctx context.Context) erro
|
||||
for i, publicKey := range publicKeyBytes {
|
||||
var attestingHistory deprecatedEncodedAttestingHistory
|
||||
attestingHistory = attestingHistoryBytes[i]
|
||||
err = store.db.Update(func(tx *bolt.Tx) error {
|
||||
err = s.db.Update(func(tx *bolt.Tx) error {
|
||||
if attestingHistory == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -108,7 +108,7 @@ func (store *Store) migrateOptimalAttesterProtectionUp(ctx context.Context) erro
|
||||
}
|
||||
}
|
||||
|
||||
return store.db.Update(func(tx *bolt.Tx) error {
|
||||
return s.db.Update(func(tx *bolt.Tx) error {
|
||||
mb := tx.Bucket(migrationsBucket)
|
||||
if err := mb.Put(migrationOptimalAttesterProtectionKey, migrationCompleted); err != nil {
|
||||
return err
|
||||
@@ -118,10 +118,10 @@ func (store *Store) migrateOptimalAttesterProtectionUp(ctx context.Context) erro
|
||||
}
|
||||
|
||||
// Migrate attester protection from the more optimal format to the old format in the DB.
|
||||
func (store *Store) migrateOptimalAttesterProtectionDown(ctx context.Context) error {
|
||||
func (s *Store) migrateOptimalAttesterProtectionDown(ctx context.Context) error {
|
||||
// First we extract the public keys we are migrating down for.
|
||||
pubKeys := make([][48]byte, 0)
|
||||
err := store.view(func(tx *bolt.Tx) error {
|
||||
err := s.view(func(tx *bolt.Tx) error {
|
||||
mb := tx.Bucket(migrationsBucket)
|
||||
if b := mb.Get(migrationOptimalAttesterProtectionKey); b == nil {
|
||||
// Migration has not occurred, meaning data is already in old format
|
||||
@@ -152,7 +152,7 @@ func (store *Store) migrateOptimalAttesterProtectionDown(ctx context.Context) er
|
||||
// from the optimized db schema into maps we can use later.
|
||||
signingRootsByTarget := make(map[uint64][]byte)
|
||||
targetEpochsBySource := make(map[uint64][]uint64)
|
||||
err = store.view(func(tx *bolt.Tx) error {
|
||||
err = s.view(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket(pubKeysBucket)
|
||||
if bkt == nil {
|
||||
return nil
|
||||
@@ -194,7 +194,7 @@ func (store *Store) migrateOptimalAttesterProtectionDown(ctx context.Context) er
|
||||
// Then, we use the data we extracted to recreate the old
|
||||
// attesting history format and for each public key, we save it
|
||||
// to the appropriate bucket.
|
||||
err = store.update(func(tx *bolt.Tx) error {
|
||||
err = s.update(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket(pubKeysBucket)
|
||||
if bkt == nil {
|
||||
return nil
|
||||
@@ -247,7 +247,7 @@ func (store *Store) migrateOptimalAttesterProtectionDown(ctx context.Context) er
|
||||
}
|
||||
|
||||
// Finally, we clear the migration key.
|
||||
return store.update(func(tx *bolt.Tx) error {
|
||||
return s.update(func(tx *bolt.Tx) error {
|
||||
migrationsBkt := tx.Bucket(migrationsBucket)
|
||||
return migrationsBkt.Delete(migrationOptimalAttesterProtectionKey)
|
||||
})
|
||||
|
||||
@@ -24,12 +24,12 @@ type Proposal struct {
|
||||
}
|
||||
|
||||
// ProposedPublicKeys retrieves all public keys in our proposals history bucket.
|
||||
func (store *Store) ProposedPublicKeys(ctx context.Context) ([][48]byte, error) {
|
||||
func (s *Store) ProposedPublicKeys(ctx context.Context) ([][48]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.ProposedPublicKeys")
|
||||
defer span.End()
|
||||
var err error
|
||||
proposedPublicKeys := make([][48]byte, 0)
|
||||
err = store.view(func(tx *bolt.Tx) error {
|
||||
err = s.view(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(historicProposalsBucket)
|
||||
return bucket.ForEach(func(key []byte, _ []byte) error {
|
||||
pubKeyBytes := [48]byte{}
|
||||
@@ -44,14 +44,14 @@ func (store *Store) ProposedPublicKeys(ctx context.Context) ([][48]byte, error)
|
||||
// ProposalHistoryForSlot accepts a validator public key and returns the corresponding signing root as well
|
||||
// as a boolean that tells us if we have a proposal history stored at the slot. It is possible we have proposed
|
||||
// a slot but stored a nil signing root, so the boolean helps give full information.
|
||||
func (store *Store) ProposalHistoryForSlot(ctx context.Context, publicKey [48]byte, slot uint64) ([32]byte, bool, error) {
|
||||
func (s *Store) ProposalHistoryForSlot(ctx context.Context, publicKey [48]byte, slot uint64) ([32]byte, bool, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.ProposalHistoryForSlot")
|
||||
defer span.End()
|
||||
|
||||
var err error
|
||||
var proposalExists bool
|
||||
signingRoot := [32]byte{}
|
||||
err = store.update(func(tx *bolt.Tx) error {
|
||||
err = s.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(historicProposalsBucket)
|
||||
valBucket, err := bucket.CreateBucketIfNotExists(publicKey[:])
|
||||
if err != nil {
|
||||
@@ -71,11 +71,11 @@ func (store *Store) ProposalHistoryForSlot(ctx context.Context, publicKey [48]by
|
||||
// SaveProposalHistoryForSlot saves the proposal history for the requested validator public key.
|
||||
// We also check if the incoming proposal slot is lower than the lowest signed proposal slot
|
||||
// for the validator and override its value on disk.
|
||||
func (store *Store) SaveProposalHistoryForSlot(ctx context.Context, pubKey [48]byte, slot uint64, signingRoot []byte) error {
|
||||
func (s *Store) SaveProposalHistoryForSlot(ctx context.Context, pubKey [48]byte, slot uint64, signingRoot []byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.SaveProposalHistoryForEpoch")
|
||||
defer span.End()
|
||||
|
||||
err := store.update(func(tx *bolt.Tx) error {
|
||||
err := s.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(historicProposalsBucket)
|
||||
valBucket, err := bucket.CreateBucketIfNotExists(pubKey[:])
|
||||
if err != nil {
|
||||
@@ -118,13 +118,13 @@ func (store *Store) SaveProposalHistoryForSlot(ctx context.Context, pubKey [48]b
|
||||
|
||||
// LowestSignedProposal returns the lowest signed proposal slot for a validator public key.
|
||||
// If no data exists, returning 0 is a sensible default.
|
||||
func (store *Store) LowestSignedProposal(ctx context.Context, publicKey [48]byte) (uint64, error) {
|
||||
func (s *Store) LowestSignedProposal(ctx context.Context, publicKey [48]byte) (uint64, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.LowestSignedProposal")
|
||||
defer span.End()
|
||||
|
||||
var err error
|
||||
var lowestSignedProposalSlot uint64
|
||||
err = store.view(func(tx *bolt.Tx) error {
|
||||
err = s.view(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(lowestSignedProposalsBucket)
|
||||
lowestSignedProposalBytes := bucket.Get(publicKey[:])
|
||||
// 8 because bytesutil.BytesToUint64BigEndian will return 0 if input is less than 8 bytes.
|
||||
@@ -139,13 +139,13 @@ func (store *Store) LowestSignedProposal(ctx context.Context, publicKey [48]byte
|
||||
|
||||
// HighestSignedProposal returns the highest signed proposal slot for a validator public key.
|
||||
// If no data exists, returning 0 is a sensible default.
|
||||
func (store *Store) HighestSignedProposal(ctx context.Context, publicKey [48]byte) (uint64, error) {
|
||||
func (s *Store) HighestSignedProposal(ctx context.Context, publicKey [48]byte) (uint64, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "Validator.HighestSignedProposal")
|
||||
defer span.End()
|
||||
|
||||
var err error
|
||||
var highestSignedProposalSlot uint64
|
||||
err = store.view(func(tx *bolt.Tx) error {
|
||||
err = s.view(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(highestSignedProposalsBucket)
|
||||
highestSignedProposalBytes := bucket.Get(publicKey[:])
|
||||
// 8 because bytesutil.BytesToUint64BigEndian will return 0 if input is less than 8 bytes.
|
||||
|
||||
@@ -13,8 +13,8 @@ import (
|
||||
// public key in the public keys bucket and prunes all attestation data
|
||||
// that has target epochs older than the highest weak subjectivity period
|
||||
// in our database. This routine is meant to run on startup.
|
||||
func (store *Store) PruneAttestationsOlderThanCurrentWeakSubjectivity(ctx context.Context) error {
|
||||
return store.update(func(tx *bolt.Tx) error {
|
||||
func (s *Store) PruneAttestationsOlderThanCurrentWeakSubjectivity(ctx context.Context) error {
|
||||
return s.update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(pubKeysBucket)
|
||||
return bucket.ForEach(func(pubKey []byte, _ []byte) error {
|
||||
pkBucket := bucket.Bucket(pubKey)
|
||||
|
||||
@@ -52,7 +52,7 @@ func NewKeymanager(
|
||||
// RecoverAccountsFromMnemonic given a mnemonic phrase, is able to regenerate N accounts
|
||||
// from a derived seed, encrypt them according to the EIP-2334 JSON standard, and write them
|
||||
// to disk. Then, the mnemonic is never stored nor used by the validator.
|
||||
func (dr *Keymanager) RecoverAccountsFromMnemonic(
|
||||
func (km *Keymanager) RecoverAccountsFromMnemonic(
|
||||
ctx context.Context, mnemonic, mnemonicPassphrase string, numAccounts int,
|
||||
) error {
|
||||
seed, err := seedFromMnemonic(mnemonic, mnemonicPassphrase)
|
||||
@@ -71,44 +71,44 @@ func (dr *Keymanager) RecoverAccountsFromMnemonic(
|
||||
privKeys[i] = privKey.Marshal()
|
||||
pubKeys[i] = privKey.PublicKey().Marshal()
|
||||
}
|
||||
return dr.importedKM.ImportKeypairs(ctx, privKeys, pubKeys)
|
||||
return km.importedKM.ImportKeypairs(ctx, privKeys, pubKeys)
|
||||
}
|
||||
|
||||
// ExtractKeystores retrieves the secret keys for specified public keys
|
||||
// in the function input, encrypts them using the specified password,
|
||||
// and returns their respective EIP-2335 keystores.
|
||||
func (dr *Keymanager) ExtractKeystores(
|
||||
func (km *Keymanager) ExtractKeystores(
|
||||
ctx context.Context, publicKeys []bls.PublicKey, password string,
|
||||
) ([]*keymanager.Keystore, error) {
|
||||
return dr.importedKM.ExtractKeystores(ctx, publicKeys, password)
|
||||
return km.importedKM.ExtractKeystores(ctx, publicKeys, password)
|
||||
}
|
||||
|
||||
// ValidatingAccountNames for the derived keymanager.
|
||||
func (dr *Keymanager) ValidatingAccountNames(_ context.Context) ([]string, error) {
|
||||
return dr.importedKM.ValidatingAccountNames()
|
||||
func (km *Keymanager) ValidatingAccountNames(_ context.Context) ([]string, error) {
|
||||
return km.importedKM.ValidatingAccountNames()
|
||||
}
|
||||
|
||||
// Sign signs a message using a validator key.
|
||||
func (dr *Keymanager) Sign(ctx context.Context, req *validatorpb.SignRequest) (bls.Signature, error) {
|
||||
return dr.importedKM.Sign(ctx, req)
|
||||
func (km *Keymanager) Sign(ctx context.Context, req *validatorpb.SignRequest) (bls.Signature, error) {
|
||||
return km.importedKM.Sign(ctx, req)
|
||||
}
|
||||
|
||||
// FetchValidatingPublicKeys fetches the list of validating public keys from the keymanager.
|
||||
func (dr *Keymanager) FetchValidatingPublicKeys(ctx context.Context) ([][48]byte, error) {
|
||||
return dr.importedKM.FetchValidatingPublicKeys(ctx)
|
||||
func (km *Keymanager) FetchValidatingPublicKeys(ctx context.Context) ([][48]byte, error) {
|
||||
return km.importedKM.FetchValidatingPublicKeys(ctx)
|
||||
}
|
||||
|
||||
// FetchAllValidatingPublicKeys fetches the list of all public keys (including disabled ones) from the keymanager.
|
||||
func (dr *Keymanager) FetchAllValidatingPublicKeys(ctx context.Context) ([][48]byte, error) {
|
||||
return dr.importedKM.FetchAllValidatingPublicKeys(ctx)
|
||||
func (km *Keymanager) FetchAllValidatingPublicKeys(ctx context.Context) ([][48]byte, error) {
|
||||
return km.importedKM.FetchAllValidatingPublicKeys(ctx)
|
||||
}
|
||||
|
||||
// FetchValidatingPrivateKeys fetches the list of validating private keys from the keymanager.
|
||||
func (dr *Keymanager) FetchValidatingPrivateKeys(ctx context.Context) ([][32]byte, error) {
|
||||
return dr.importedKM.FetchValidatingPrivateKeys(ctx)
|
||||
func (km *Keymanager) FetchValidatingPrivateKeys(ctx context.Context) ([][32]byte, error) {
|
||||
return km.importedKM.FetchValidatingPrivateKeys(ctx)
|
||||
}
|
||||
|
||||
// DeleteAccounts for a derived keymanager.
|
||||
func (dr *Keymanager) DeleteAccounts(ctx context.Context, publicKeys [][]byte) error {
|
||||
return dr.importedKM.DeleteAccounts(ctx, publicKeys)
|
||||
func (km *Keymanager) DeleteAccounts(ctx context.Context, publicKeys [][]byte) error {
|
||||
return km.importedKM.DeleteAccounts(ctx, publicKeys)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
// ExtractKeystores retrieves the secret keys for specified public keys
|
||||
// in the function input, encrypts them using the specified password,
|
||||
// and returns their respective EIP-2335 keystores.
|
||||
func (dr *Keymanager) ExtractKeystores(
|
||||
func (km *Keymanager) ExtractKeystores(
|
||||
_ context.Context, publicKeys []bls.PublicKey, password string,
|
||||
) ([]*keymanager.Keystore, error) {
|
||||
lock.Lock()
|
||||
|
||||
@@ -10,35 +10,35 @@ import (
|
||||
)
|
||||
|
||||
// DisableAccounts disables public keys from the user's wallet.
|
||||
func (dr *Keymanager) DisableAccounts(ctx context.Context, pubKeys [][]byte) error {
|
||||
func (km *Keymanager) DisableAccounts(ctx context.Context, pubKeys [][]byte) error {
|
||||
if pubKeys == nil || len(pubKeys) < 1 {
|
||||
return errors.New("no public keys specified to disable")
|
||||
}
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
for _, pk := range pubKeys {
|
||||
if _, ok := dr.disabledPublicKeys[bytesutil.ToBytes48(pk)]; !ok {
|
||||
dr.disabledPublicKeys[bytesutil.ToBytes48(pk)] = true
|
||||
if _, ok := km.disabledPublicKeys[bytesutil.ToBytes48(pk)]; !ok {
|
||||
km.disabledPublicKeys[bytesutil.ToBytes48(pk)] = true
|
||||
}
|
||||
}
|
||||
return dr.rewriteDisabledKeysToDisk(ctx)
|
||||
return km.rewriteDisabledKeysToDisk(ctx)
|
||||
}
|
||||
|
||||
// EnableAccounts enables public keys from a user's wallet if they are disabled.
|
||||
func (dr *Keymanager) EnableAccounts(ctx context.Context, pubKeys [][]byte) error {
|
||||
func (km *Keymanager) EnableAccounts(ctx context.Context, pubKeys [][]byte) error {
|
||||
if pubKeys == nil || len(pubKeys) < 1 {
|
||||
return errors.New("no public keys specified to enable")
|
||||
}
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
for _, pk := range pubKeys {
|
||||
delete(dr.disabledPublicKeys, bytesutil.ToBytes48(pk))
|
||||
delete(km.disabledPublicKeys, bytesutil.ToBytes48(pk))
|
||||
}
|
||||
return dr.rewriteDisabledKeysToDisk(ctx)
|
||||
return km.rewriteDisabledKeysToDisk(ctx)
|
||||
}
|
||||
|
||||
func (dr *Keymanager) rewriteDisabledKeysToDisk(ctx context.Context) error {
|
||||
encoded, err := dr.wallet.ReadFileAtPath(ctx, AccountsPath, AccountsKeystoreFileName)
|
||||
func (km *Keymanager) rewriteDisabledKeysToDisk(ctx context.Context) error {
|
||||
encoded, err := km.wallet.ReadFileAtPath(ctx, AccountsPath, AccountsKeystoreFileName)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not read keystore file for accounts")
|
||||
}
|
||||
@@ -47,7 +47,7 @@ func (dr *Keymanager) rewriteDisabledKeysToDisk(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
disabledKeysStrings := make([]string, 0)
|
||||
for pk := range dr.disabledPublicKeys {
|
||||
for pk := range km.disabledPublicKeys {
|
||||
disabledKeysStrings = append(disabledKeysStrings, fmt.Sprintf("%x", pk))
|
||||
}
|
||||
keystore.DisabledPublicKeys = disabledKeysStrings
|
||||
@@ -55,7 +55,7 @@ func (dr *Keymanager) rewriteDisabledKeysToDisk(ctx context.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := dr.wallet.WriteFileAtPath(ctx, AccountsPath, AccountsKeystoreFileName, encoded); err != nil {
|
||||
if err := km.wallet.WriteFileAtPath(ctx, AccountsPath, AccountsKeystoreFileName, encoded); err != nil {
|
||||
return errors.Wrap(err, "could not write keystore file for accounts")
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
)
|
||||
|
||||
// ImportKeystores into the imported keymanager from an external source.
|
||||
func (dr *Keymanager) ImportKeystores(
|
||||
func (km *Keymanager) ImportKeystores(
|
||||
ctx context.Context,
|
||||
keystores []*keymanager.Keystore,
|
||||
importsPassword string,
|
||||
@@ -29,7 +29,7 @@ func (dr *Keymanager) ImportKeystores(
|
||||
for i := 0; i < len(keystores); i++ {
|
||||
var privKeyBytes []byte
|
||||
var pubKeyBytes []byte
|
||||
privKeyBytes, pubKeyBytes, importsPassword, err = dr.attemptDecryptKeystore(decryptor, keystores[i], importsPassword)
|
||||
privKeyBytes, pubKeyBytes, importsPassword, err = km.attemptDecryptKeystore(decryptor, keystores[i], importsPassword)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -50,7 +50,7 @@ func (dr *Keymanager) ImportKeystores(
|
||||
}
|
||||
|
||||
// Write the accounts to disk into a single keystore.
|
||||
accountsKeystore, err := dr.CreateAccountsKeystore(ctx, privKeys, pubKeys)
|
||||
accountsKeystore, err := km.CreateAccountsKeystore(ctx, privKeys, pubKeys)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -58,13 +58,13 @@ func (dr *Keymanager) ImportKeystores(
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return dr.wallet.WriteFileAtPath(ctx, AccountsPath, AccountsKeystoreFileName, encodedAccounts)
|
||||
return km.wallet.WriteFileAtPath(ctx, AccountsPath, AccountsKeystoreFileName, encodedAccounts)
|
||||
}
|
||||
|
||||
// ImportKeypairs directly into the keymanager.
|
||||
func (dr *Keymanager) ImportKeypairs(ctx context.Context, privKeys, pubKeys [][]byte) error {
|
||||
func (km *Keymanager) ImportKeypairs(ctx context.Context, privKeys, pubKeys [][]byte) error {
|
||||
// Write the accounts to disk into a single keystore.
|
||||
accountsKeystore, err := dr.CreateAccountsKeystore(ctx, privKeys, pubKeys)
|
||||
accountsKeystore, err := km.CreateAccountsKeystore(ctx, privKeys, pubKeys)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not import account keypairs")
|
||||
}
|
||||
@@ -72,13 +72,13 @@ func (dr *Keymanager) ImportKeypairs(ctx context.Context, privKeys, pubKeys [][]
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not marshal accounts keystore into JSON")
|
||||
}
|
||||
return dr.wallet.WriteFileAtPath(ctx, AccountsPath, AccountsKeystoreFileName, encodedAccounts)
|
||||
return km.wallet.WriteFileAtPath(ctx, AccountsPath, AccountsKeystoreFileName, encodedAccounts)
|
||||
}
|
||||
|
||||
// Retrieves the private key and public key from an EIP-2335 keystore file
|
||||
// by decrypting using a specified password. If the password fails,
|
||||
// it prompts the user for the correct password until it confirms.
|
||||
func (dr *Keymanager) attemptDecryptKeystore(
|
||||
func (km *Keymanager) attemptDecryptKeystore(
|
||||
enc *keystorev4.Encryptor, keystore *keymanager.Keystore, password string,
|
||||
) ([]byte, []byte, string, error) {
|
||||
// Attempt to decrypt the keystore with the specifies password.
|
||||
|
||||
@@ -124,12 +124,12 @@ func NewInteropKeymanager(_ context.Context, offset, numValidatorKeys uint64) (*
|
||||
// SubscribeAccountChanges creates an event subscription for a channel
|
||||
// to listen for public key changes at runtime, such as when new validator accounts
|
||||
// are imported into the keymanager while the validator process is running.
|
||||
func (dr *Keymanager) SubscribeAccountChanges(pubKeysChan chan [][48]byte) event.Subscription {
|
||||
return dr.accountsChangedFeed.Subscribe(pubKeysChan)
|
||||
func (km *Keymanager) SubscribeAccountChanges(pubKeysChan chan [][48]byte) event.Subscription {
|
||||
return km.accountsChangedFeed.Subscribe(pubKeysChan)
|
||||
}
|
||||
|
||||
// ValidatingAccountNames for a imported keymanager.
|
||||
func (dr *Keymanager) ValidatingAccountNames() ([]string, error) {
|
||||
func (km *Keymanager) ValidatingAccountNames() ([]string, error) {
|
||||
lock.RLock()
|
||||
names := make([]string, len(orderedPublicKeys))
|
||||
for i, pubKey := range orderedPublicKeys {
|
||||
@@ -140,9 +140,9 @@ func (dr *Keymanager) ValidatingAccountNames() ([]string, error) {
|
||||
}
|
||||
|
||||
// DisabledPublicKeys returns the currently disabled public keys in the keymanager.
|
||||
func (dr *Keymanager) DisabledPublicKeys() [][]byte {
|
||||
func (km *Keymanager) DisabledPublicKeys() [][]byte {
|
||||
disabledPubKeys := make([][]byte, 0)
|
||||
for pubKey := range dr.disabledPublicKeys {
|
||||
for pubKey := range km.disabledPublicKeys {
|
||||
pubKeyBytes := make([]byte, 48)
|
||||
copy(pubKeyBytes, pubKey[:])
|
||||
disabledPubKeys = append(disabledPubKeys, pubKeyBytes)
|
||||
@@ -152,16 +152,16 @@ func (dr *Keymanager) DisabledPublicKeys() [][]byte {
|
||||
|
||||
// Initialize public and secret key caches that are used to speed up the functions
|
||||
// FetchValidatingPublicKeys and Sign
|
||||
func (dr *Keymanager) initializeKeysCachesFromKeystore() error {
|
||||
func (km *Keymanager) initializeKeysCachesFromKeystore() error {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
count := len(dr.accountsStore.PrivateKeys)
|
||||
count := len(km.accountsStore.PrivateKeys)
|
||||
orderedPublicKeys = make([][48]byte, count)
|
||||
secretKeysCache = make(map[[48]byte]bls.SecretKey, count)
|
||||
for i, publicKey := range dr.accountsStore.PublicKeys {
|
||||
for i, publicKey := range km.accountsStore.PublicKeys {
|
||||
publicKey48 := bytesutil.ToBytes48(publicKey)
|
||||
orderedPublicKeys[i] = publicKey48
|
||||
secretKey, err := bls.SecretKeyFromBytes(dr.accountsStore.PrivateKeys[i])
|
||||
secretKey, err := bls.SecretKeyFromBytes(km.accountsStore.PrivateKeys[i])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to initialize keys caches from account keystore")
|
||||
}
|
||||
@@ -171,11 +171,11 @@ func (dr *Keymanager) initializeKeysCachesFromKeystore() error {
|
||||
}
|
||||
|
||||
// DeleteAccounts takes in public keys and removes the accounts entirely. This includes their disk keystore and cached keystore.
|
||||
func (dr *Keymanager) DeleteAccounts(ctx context.Context, publicKeys [][]byte) error {
|
||||
func (km *Keymanager) DeleteAccounts(ctx context.Context, publicKeys [][]byte) error {
|
||||
for _, publicKey := range publicKeys {
|
||||
var index int
|
||||
var found bool
|
||||
for i, pubKey := range dr.accountsStore.PublicKeys {
|
||||
for i, pubKey := range km.accountsStore.PublicKeys {
|
||||
if bytes.Equal(pubKey, publicKey) {
|
||||
index = i
|
||||
found = true
|
||||
@@ -185,12 +185,12 @@ func (dr *Keymanager) DeleteAccounts(ctx context.Context, publicKeys [][]byte) e
|
||||
if !found {
|
||||
return fmt.Errorf("could not find public key %#x", publicKey)
|
||||
}
|
||||
deletedPublicKey := dr.accountsStore.PublicKeys[index]
|
||||
deletedPublicKey := km.accountsStore.PublicKeys[index]
|
||||
accountName := petnames.DeterministicName(deletedPublicKey, "-")
|
||||
dr.accountsStore.PrivateKeys = append(dr.accountsStore.PrivateKeys[:index], dr.accountsStore.PrivateKeys[index+1:]...)
|
||||
dr.accountsStore.PublicKeys = append(dr.accountsStore.PublicKeys[:index], dr.accountsStore.PublicKeys[index+1:]...)
|
||||
km.accountsStore.PrivateKeys = append(km.accountsStore.PrivateKeys[:index], km.accountsStore.PrivateKeys[index+1:]...)
|
||||
km.accountsStore.PublicKeys = append(km.accountsStore.PublicKeys[:index], km.accountsStore.PublicKeys[index+1:]...)
|
||||
|
||||
newStore, err := dr.CreateAccountsKeystore(ctx, dr.accountsStore.PrivateKeys, dr.accountsStore.PublicKeys)
|
||||
newStore, err := km.CreateAccountsKeystore(ctx, km.accountsStore.PrivateKeys, km.accountsStore.PublicKeys)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not rewrite accounts keystore")
|
||||
}
|
||||
@@ -200,7 +200,7 @@ func (dr *Keymanager) DeleteAccounts(ctx context.Context, publicKeys [][]byte) e
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := dr.wallet.WriteFileAtPath(ctx, AccountsPath, AccountsKeystoreFileName, encoded); err != nil {
|
||||
if err := km.wallet.WriteFileAtPath(ctx, AccountsPath, AccountsKeystoreFileName, encoded); err != nil {
|
||||
return errors.Wrap(err, "could not write keystore file for accounts")
|
||||
}
|
||||
|
||||
@@ -208,7 +208,7 @@ func (dr *Keymanager) DeleteAccounts(ctx context.Context, publicKeys [][]byte) e
|
||||
"name": accountName,
|
||||
"publicKey": fmt.Sprintf("%#x", bytesutil.Trunc(deletedPublicKey)),
|
||||
}).Info("Successfully deleted validator account")
|
||||
err = dr.initializeKeysCachesFromKeystore()
|
||||
err = km.initializeKeysCachesFromKeystore()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to initialize keys caches")
|
||||
}
|
||||
@@ -217,7 +217,7 @@ func (dr *Keymanager) DeleteAccounts(ctx context.Context, publicKeys [][]byte) e
|
||||
}
|
||||
|
||||
// FetchValidatingPublicKeys fetches the list of active public keys from the imported account keystores.
|
||||
func (dr *Keymanager) FetchValidatingPublicKeys(ctx context.Context) ([][48]byte, error) {
|
||||
func (km *Keymanager) FetchValidatingPublicKeys(ctx context.Context) ([][48]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "keymanager.FetchValidatingPublicKeys")
|
||||
defer span.End()
|
||||
|
||||
@@ -225,7 +225,7 @@ func (dr *Keymanager) FetchValidatingPublicKeys(ctx context.Context) ([][48]byte
|
||||
keys := orderedPublicKeys
|
||||
result := make([][48]byte, 0)
|
||||
for _, pk := range keys {
|
||||
if _, ok := dr.disabledPublicKeys[pk]; !ok {
|
||||
if _, ok := km.disabledPublicKeys[pk]; !ok {
|
||||
result = append(result, pk)
|
||||
}
|
||||
}
|
||||
@@ -234,7 +234,7 @@ func (dr *Keymanager) FetchValidatingPublicKeys(ctx context.Context) ([][48]byte
|
||||
}
|
||||
|
||||
// FetchAllValidatingPublicKeys fetches the list of all public keys (including disabled ones) from the imported account keystores.
|
||||
func (dr *Keymanager) FetchAllValidatingPublicKeys(ctx context.Context) ([][48]byte, error) {
|
||||
func (km *Keymanager) FetchAllValidatingPublicKeys(ctx context.Context) ([][48]byte, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "keymanager.FetchValidatingPublicKeys")
|
||||
defer span.End()
|
||||
|
||||
@@ -247,16 +247,16 @@ func (dr *Keymanager) FetchAllValidatingPublicKeys(ctx context.Context) ([][48]b
|
||||
}
|
||||
|
||||
// FetchValidatingPrivateKeys fetches the list of private keys from the secret keys cache
|
||||
func (dr *Keymanager) FetchValidatingPrivateKeys(ctx context.Context) ([][32]byte, error) {
|
||||
func (km *Keymanager) FetchValidatingPrivateKeys(ctx context.Context) ([][32]byte, error) {
|
||||
lock.RLock()
|
||||
defer lock.RUnlock()
|
||||
privKeys := make([][32]byte, len(secretKeysCache))
|
||||
pubKeys, err := dr.FetchValidatingPublicKeys(ctx)
|
||||
pubKeys, err := km.FetchValidatingPublicKeys(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not retrieve public keys")
|
||||
}
|
||||
for i, pk := range pubKeys {
|
||||
if _, ok := dr.disabledPublicKeys[pk]; !ok {
|
||||
if _, ok := km.disabledPublicKeys[pk]; !ok {
|
||||
seckey, ok := secretKeysCache[pk]
|
||||
if !ok {
|
||||
return nil, errors.New("Could not fetch private key")
|
||||
@@ -268,7 +268,7 @@ func (dr *Keymanager) FetchValidatingPrivateKeys(ctx context.Context) ([][32]byt
|
||||
}
|
||||
|
||||
// Sign signs a message using a validator key.
|
||||
func (dr *Keymanager) Sign(ctx context.Context, req *validatorpb.SignRequest) (bls.Signature, error) {
|
||||
func (km *Keymanager) Sign(ctx context.Context, req *validatorpb.SignRequest) (bls.Signature, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "keymanager.Sign")
|
||||
defer span.End()
|
||||
|
||||
@@ -285,8 +285,8 @@ func (dr *Keymanager) Sign(ctx context.Context, req *validatorpb.SignRequest) (b
|
||||
return secretKey.Sign(req.SigningRoot), nil
|
||||
}
|
||||
|
||||
func (dr *Keymanager) initializeAccountKeystore(ctx context.Context) error {
|
||||
encoded, err := dr.wallet.ReadFileAtPath(ctx, AccountsPath, AccountsKeystoreFileName)
|
||||
func (km *Keymanager) initializeAccountKeystore(ctx context.Context) error {
|
||||
encoded, err := km.wallet.ReadFileAtPath(ctx, AccountsPath, AccountsKeystoreFileName)
|
||||
if err != nil && strings.Contains(err.Error(), "no files found") {
|
||||
// If there are no keys to initialize at all, just exit.
|
||||
return nil
|
||||
@@ -300,7 +300,7 @@ func (dr *Keymanager) initializeAccountKeystore(ctx context.Context) error {
|
||||
// We extract the validator signing private key from the keystore
|
||||
// by utilizing the password and initialize a new BLS secret key from
|
||||
// its raw bytes.
|
||||
password := dr.wallet.Password()
|
||||
password := km.wallet.Password()
|
||||
decryptor := keystorev4.New()
|
||||
enc, err := decryptor.Decrypt(keystoreFile.Crypto, password)
|
||||
if err != nil && strings.Contains(err.Error(), "invalid checksum") {
|
||||
@@ -319,7 +319,7 @@ func (dr *Keymanager) initializeAccountKeystore(ctx context.Context) error {
|
||||
if len(store.PublicKeys) == 0 {
|
||||
return nil
|
||||
}
|
||||
dr.accountsStore = store
|
||||
km.accountsStore = store
|
||||
|
||||
lock.Lock()
|
||||
for _, pubKey := range keystoreFile.DisabledPublicKeys {
|
||||
@@ -328,10 +328,10 @@ func (dr *Keymanager) initializeAccountKeystore(ctx context.Context) error {
|
||||
lock.Unlock()
|
||||
return err
|
||||
}
|
||||
dr.disabledPublicKeys[bytesutil.ToBytes48(pubKeyBytes)] = true
|
||||
km.disabledPublicKeys[bytesutil.ToBytes48(pubKeyBytes)] = true
|
||||
}
|
||||
lock.Unlock()
|
||||
err = dr.initializeKeysCachesFromKeystore()
|
||||
err = km.initializeKeysCachesFromKeystore()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to initialize keys caches")
|
||||
}
|
||||
@@ -339,7 +339,7 @@ func (dr *Keymanager) initializeAccountKeystore(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// CreateAccountsKeystore creates a new keystore holding the provided keys.
|
||||
func (dr *Keymanager) CreateAccountsKeystore(
|
||||
func (km *Keymanager) CreateAccountsKeystore(
|
||||
_ context.Context,
|
||||
privateKeys, publicKeys [][]byte,
|
||||
) (*AccountsKeystoreRepresentation, error) {
|
||||
@@ -353,17 +353,17 @@ func (dr *Keymanager) CreateAccountsKeystore(
|
||||
"number of private keys and public keys is not equal: %d != %d", len(privateKeys), len(publicKeys),
|
||||
)
|
||||
}
|
||||
if dr.accountsStore == nil {
|
||||
dr.accountsStore = &accountStore{
|
||||
if km.accountsStore == nil {
|
||||
km.accountsStore = &accountStore{
|
||||
PrivateKeys: privateKeys,
|
||||
PublicKeys: publicKeys,
|
||||
}
|
||||
} else {
|
||||
existingPubKeys := make(map[string]bool)
|
||||
existingPrivKeys := make(map[string]bool)
|
||||
for i := 0; i < len(dr.accountsStore.PrivateKeys); i++ {
|
||||
existingPrivKeys[string(dr.accountsStore.PrivateKeys[i])] = true
|
||||
existingPubKeys[string(dr.accountsStore.PublicKeys[i])] = true
|
||||
for i := 0; i < len(km.accountsStore.PrivateKeys); i++ {
|
||||
existingPrivKeys[string(km.accountsStore.PrivateKeys[i])] = true
|
||||
existingPubKeys[string(km.accountsStore.PublicKeys[i])] = true
|
||||
}
|
||||
// We append to the accounts store keys only
|
||||
// if the private/secret key do not already exist, to prevent duplicates.
|
||||
@@ -375,26 +375,26 @@ func (dr *Keymanager) CreateAccountsKeystore(
|
||||
if privKeyExists || pubKeyExists {
|
||||
continue
|
||||
}
|
||||
dr.accountsStore.PublicKeys = append(dr.accountsStore.PublicKeys, pk)
|
||||
dr.accountsStore.PrivateKeys = append(dr.accountsStore.PrivateKeys, sk)
|
||||
km.accountsStore.PublicKeys = append(km.accountsStore.PublicKeys, pk)
|
||||
km.accountsStore.PrivateKeys = append(km.accountsStore.PrivateKeys, sk)
|
||||
}
|
||||
}
|
||||
err = dr.initializeKeysCachesFromKeystore()
|
||||
err = km.initializeKeysCachesFromKeystore()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to initialize keys caches")
|
||||
}
|
||||
encodedStore, err := json.MarshalIndent(dr.accountsStore, "", "\t")
|
||||
encodedStore, err := json.MarshalIndent(km.accountsStore, "", "\t")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cryptoFields, err := encryptor.Encrypt(encodedStore, dr.wallet.Password())
|
||||
cryptoFields, err := encryptor.Encrypt(encodedStore, km.wallet.Password())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not encrypt accounts")
|
||||
}
|
||||
disabledPubKeys := make([]string, 0)
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
for pubKey := range dr.disabledPublicKeys {
|
||||
for pubKey := range km.disabledPublicKeys {
|
||||
disabledPubKeys = append(disabledPubKeys, fmt.Sprintf("%x", pubKey))
|
||||
}
|
||||
return &AccountsKeystoreRepresentation{
|
||||
|
||||
@@ -23,9 +23,9 @@ import (
|
||||
// to load in new keys we observe into our keymanager. This uses the fsnotify
|
||||
// library to listen for file-system changes and debounces these events to
|
||||
// ensure we can handle thousands of events fired in a short time-span.
|
||||
func (dr *Keymanager) listenForAccountChanges(ctx context.Context) {
|
||||
func (km *Keymanager) listenForAccountChanges(ctx context.Context) {
|
||||
debounceFileChangesInterval := featureconfig.Get().KeystoreImportDebounceInterval
|
||||
accountsFilePath := filepath.Join(dr.wallet.AccountsDir(), AccountsPath, AccountsKeystoreFileName)
|
||||
accountsFilePath := filepath.Join(km.wallet.AccountsDir(), AccountsPath, AccountsKeystoreFileName)
|
||||
if !fileutil.FileExists(accountsFilePath) {
|
||||
return
|
||||
}
|
||||
@@ -73,7 +73,7 @@ func (dr *Keymanager) listenForAccountChanges(ctx context.Context) {
|
||||
).Errorf("Could not read valid, EIP-2335 keystore json file at path: %s", ev.Name)
|
||||
return
|
||||
}
|
||||
if err := dr.reloadAccountsFromKeystore(accountsKeystore); err != nil {
|
||||
if err := km.reloadAccountsFromKeystore(accountsKeystore); err != nil {
|
||||
log.WithError(
|
||||
err,
|
||||
).Error("Could not replace the accounts store from keystore file")
|
||||
@@ -95,9 +95,9 @@ func (dr *Keymanager) listenForAccountChanges(ctx context.Context) {
|
||||
|
||||
// Replaces the accounts store struct in the imported keymanager with
|
||||
// the contents of a keystore file by decrypting it with the accounts password.
|
||||
func (dr *Keymanager) reloadAccountsFromKeystore(keystore *AccountsKeystoreRepresentation) error {
|
||||
func (km *Keymanager) reloadAccountsFromKeystore(keystore *AccountsKeystoreRepresentation) error {
|
||||
decryptor := keystorev4.New()
|
||||
encodedAccounts, err := decryptor.Decrypt(keystore.Crypto, dr.wallet.Password())
|
||||
encodedAccounts, err := decryptor.Decrypt(keystore.Crypto, km.wallet.Password())
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not decrypt keystore file")
|
||||
}
|
||||
@@ -108,9 +108,9 @@ func (dr *Keymanager) reloadAccountsFromKeystore(keystore *AccountsKeystoreRepre
|
||||
if len(newAccountsStore.PublicKeys) != len(newAccountsStore.PrivateKeys) {
|
||||
return errors.New("number of public and private keys in keystore do not match")
|
||||
}
|
||||
pubKeys := make([][48]byte, len(dr.accountsStore.PublicKeys))
|
||||
for i := 0; i < len(dr.accountsStore.PrivateKeys); i++ {
|
||||
privKey, err := bls.SecretKeyFromBytes(dr.accountsStore.PrivateKeys[i])
|
||||
pubKeys := make([][48]byte, len(km.accountsStore.PublicKeys))
|
||||
for i := 0; i < len(km.accountsStore.PrivateKeys); i++ {
|
||||
privKey, err := bls.SecretKeyFromBytes(km.accountsStore.PrivateKeys[i])
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not initialize private key")
|
||||
}
|
||||
@@ -128,14 +128,14 @@ func (dr *Keymanager) reloadAccountsFromKeystore(keystore *AccountsKeystoreRepre
|
||||
lock.Unlock()
|
||||
return fmt.Errorf("public key %s has wrong length", pubKey)
|
||||
}
|
||||
dr.disabledPublicKeys[bytesutil.ToBytes48(pubKeyBytes)] = true
|
||||
km.disabledPublicKeys[bytesutil.ToBytes48(pubKeyBytes)] = true
|
||||
}
|
||||
lock.Unlock()
|
||||
dr.accountsStore = newAccountsStore
|
||||
if err := dr.initializeKeysCachesFromKeystore(); err != nil {
|
||||
km.accountsStore = newAccountsStore
|
||||
if err := km.initializeKeysCachesFromKeystore(); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Info("Reloaded validator keys into keymanager")
|
||||
dr.accountsChangedFeed.Send(pubKeys)
|
||||
km.accountsChangedFeed.Send(pubKeys)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -191,13 +191,13 @@ func (opts *KeymanagerOpts) String() string {
|
||||
}
|
||||
|
||||
// KeymanagerOpts for the remote keymanager.
|
||||
func (k *Keymanager) KeymanagerOpts() *KeymanagerOpts {
|
||||
return k.opts
|
||||
func (km *Keymanager) KeymanagerOpts() *KeymanagerOpts {
|
||||
return km.opts
|
||||
}
|
||||
|
||||
// FetchValidatingPublicKeys fetches the list of public keys that should be used to validate with.
|
||||
func (k *Keymanager) FetchValidatingPublicKeys(ctx context.Context) ([][48]byte, error) {
|
||||
resp, err := k.client.ListValidatingPublicKeys(ctx, &ptypes.Empty{})
|
||||
func (km *Keymanager) FetchValidatingPublicKeys(ctx context.Context) ([][48]byte, error) {
|
||||
resp, err := km.client.ListValidatingPublicKeys(ctx, &ptypes.Empty{})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not list accounts from remote server")
|
||||
}
|
||||
@@ -209,13 +209,13 @@ func (k *Keymanager) FetchValidatingPublicKeys(ctx context.Context) ([][48]byte,
|
||||
}
|
||||
|
||||
// FetchAllValidatingPublicKeys fetches the list of all public keys, including disabled ones.
|
||||
func (dr *Keymanager) FetchAllValidatingPublicKeys(ctx context.Context) ([][48]byte, error) {
|
||||
return dr.FetchValidatingPublicKeys(ctx)
|
||||
func (km *Keymanager) FetchAllValidatingPublicKeys(ctx context.Context) ([][48]byte, error) {
|
||||
return km.FetchValidatingPublicKeys(ctx)
|
||||
}
|
||||
|
||||
// Sign signs a message for a validator key via a gRPC request.
|
||||
func (k *Keymanager) Sign(ctx context.Context, req *validatorpb.SignRequest) (bls.Signature, error) {
|
||||
resp, err := k.client.Sign(ctx, req)
|
||||
func (km *Keymanager) Sign(ctx context.Context, req *validatorpb.SignRequest) (bls.Signature, error) {
|
||||
resp, err := km.client.Sign(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -113,17 +113,17 @@ func NewValidatorClient(cliCtx *cli.Context) (*ValidatorClient, error) {
|
||||
}
|
||||
|
||||
// Start every service in the validator client.
|
||||
func (s *ValidatorClient) Start() {
|
||||
s.lock.Lock()
|
||||
func (c *ValidatorClient) Start() {
|
||||
c.lock.Lock()
|
||||
|
||||
log.WithFields(logrus.Fields{
|
||||
"version": version.GetVersion(),
|
||||
}).Info("Starting validator node")
|
||||
|
||||
s.services.StartAll()
|
||||
c.services.StartAll()
|
||||
|
||||
stop := s.stop
|
||||
s.lock.Unlock()
|
||||
stop := c.stop
|
||||
c.lock.Unlock()
|
||||
|
||||
go func() {
|
||||
sigc := make(chan os.Signal, 1)
|
||||
@@ -131,8 +131,8 @@ func (s *ValidatorClient) Start() {
|
||||
defer signal.Stop(sigc)
|
||||
<-sigc
|
||||
log.Info("Got interrupt, shutting down...")
|
||||
debug.Exit(s.cliCtx) // Ensure trace and CPU profile data are flushed.
|
||||
go s.Close()
|
||||
debug.Exit(c.cliCtx) // Ensure trace and CPU profile data are flushed.
|
||||
go c.Close()
|
||||
for i := 10; i > 0; i-- {
|
||||
<-sigc
|
||||
if i > 1 {
|
||||
@@ -147,16 +147,16 @@ func (s *ValidatorClient) Start() {
|
||||
}
|
||||
|
||||
// Close handles graceful shutdown of the system.
|
||||
func (s *ValidatorClient) Close() {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
func (c *ValidatorClient) Close() {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
|
||||
s.services.StopAll()
|
||||
c.services.StopAll()
|
||||
log.Info("Stopping Prysm validator")
|
||||
close(s.stop)
|
||||
close(c.stop)
|
||||
}
|
||||
|
||||
func (s *ValidatorClient) initializeFromCLI(cliCtx *cli.Context) error {
|
||||
func (c *ValidatorClient) initializeFromCLI(cliCtx *cli.Context) error {
|
||||
var keyManager keymanager.IKeymanager
|
||||
var err error
|
||||
if cliCtx.IsSet(flags.InteropNumValidators.Name) {
|
||||
@@ -174,7 +174,7 @@ func (s *ValidatorClient) initializeFromCLI(cliCtx *cli.Context) error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not open wallet")
|
||||
}
|
||||
s.wallet = w
|
||||
c.wallet = w
|
||||
log.WithFields(logrus.Fields{
|
||||
"wallet": w.AccountsDir(),
|
||||
"keymanager-kind": w.KeymanagerKind().String(),
|
||||
@@ -185,8 +185,8 @@ func (s *ValidatorClient) initializeFromCLI(cliCtx *cli.Context) error {
|
||||
}
|
||||
}
|
||||
dataDir := cliCtx.String(flags.WalletDirFlag.Name)
|
||||
if s.wallet != nil {
|
||||
dataDir = s.wallet.AccountsDir()
|
||||
if c.wallet != nil {
|
||||
dataDir = c.wallet.AccountsDir()
|
||||
}
|
||||
if cliCtx.String(cmd.DataDirFlag.Name) != cmd.DefaultDataDir() {
|
||||
dataDir = cliCtx.String(cmd.DataDirFlag.Name)
|
||||
@@ -194,11 +194,11 @@ func (s *ValidatorClient) initializeFromCLI(cliCtx *cli.Context) error {
|
||||
clearFlag := cliCtx.Bool(cmd.ClearDB.Name)
|
||||
forceClearFlag := cliCtx.Bool(cmd.ForceClearDB.Name)
|
||||
if clearFlag || forceClearFlag {
|
||||
if dataDir == "" && s.wallet != nil {
|
||||
dataDir = s.wallet.AccountsDir()
|
||||
if dataDir == "" && c.wallet != nil {
|
||||
dataDir = c.wallet.AccountsDir()
|
||||
if dataDir == "" {
|
||||
log.Fatal(
|
||||
"Could not determine your system's HOME path, please specify a --datadir you wish " +
|
||||
"Could not determine your system'c HOME path, please specify a --datadir you wish " +
|
||||
"to use for your validator data",
|
||||
)
|
||||
}
|
||||
@@ -221,35 +221,35 @@ func (s *ValidatorClient) initializeFromCLI(cliCtx *cli.Context) error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not initialize db")
|
||||
}
|
||||
s.db = valDB
|
||||
c.db = valDB
|
||||
if err := valDB.RunUpMigrations(cliCtx.Context); err != nil {
|
||||
return errors.Wrap(err, "could not run database migration")
|
||||
}
|
||||
if !cliCtx.Bool(cmd.DisableMonitoringFlag.Name) {
|
||||
if err := s.registerPrometheusService(cliCtx); err != nil {
|
||||
if err := c.registerPrometheusService(cliCtx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if featureconfig.Get().SlasherProtection {
|
||||
if err := s.registerSlasherClientService(); err != nil {
|
||||
if err := c.registerSlasherClientService(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := s.registerClientService(keyManager); err != nil {
|
||||
if err := c.registerClientService(keyManager); err != nil {
|
||||
return err
|
||||
}
|
||||
if cliCtx.Bool(flags.EnableRPCFlag.Name) {
|
||||
if err := s.registerRPCService(cliCtx, keyManager); err != nil {
|
||||
if err := c.registerRPCService(cliCtx, keyManager); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.registerRPCGatewayService(cliCtx); err != nil {
|
||||
if err := c.registerRPCGatewayService(cliCtx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ValidatorClient) initializeForWeb(cliCtx *cli.Context) error {
|
||||
func (c *ValidatorClient) initializeForWeb(cliCtx *cli.Context) error {
|
||||
var keyManager keymanager.IKeymanager
|
||||
var err error
|
||||
walletDir := cliCtx.String(flags.WalletDirFlag.Name)
|
||||
@@ -267,7 +267,7 @@ func (s *ValidatorClient) initializeForWeb(cliCtx *cli.Context) error {
|
||||
return errors.Wrap(err, "could not open wallet")
|
||||
}
|
||||
if w != nil {
|
||||
s.wallet = w
|
||||
c.wallet = w
|
||||
log.WithFields(logrus.Fields{
|
||||
"wallet": w.AccountsDir(),
|
||||
"keymanager-kind": w.KeymanagerKind().String(),
|
||||
@@ -278,8 +278,8 @@ func (s *ValidatorClient) initializeForWeb(cliCtx *cli.Context) error {
|
||||
}
|
||||
}
|
||||
dataDir := cliCtx.String(flags.WalletDirFlag.Name)
|
||||
if s.wallet != nil {
|
||||
dataDir = s.wallet.AccountsDir()
|
||||
if c.wallet != nil {
|
||||
dataDir = c.wallet.AccountsDir()
|
||||
}
|
||||
if cliCtx.String(cmd.DataDirFlag.Name) != cmd.DefaultDataDir() {
|
||||
dataDir = cliCtx.String(cmd.DataDirFlag.Name)
|
||||
@@ -292,7 +292,7 @@ func (s *ValidatorClient) initializeForWeb(cliCtx *cli.Context) error {
|
||||
dataDir = cmd.DefaultDataDir()
|
||||
if dataDir == "" {
|
||||
log.Fatal(
|
||||
"Could not determine your system's HOME path, please specify a --datadir you wish " +
|
||||
"Could not determine your system'c HOME path, please specify a --datadir you wish " +
|
||||
"to use for your validator data",
|
||||
)
|
||||
}
|
||||
@@ -307,27 +307,27 @@ func (s *ValidatorClient) initializeForWeb(cliCtx *cli.Context) error {
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not initialize db")
|
||||
}
|
||||
s.db = valDB
|
||||
c.db = valDB
|
||||
if err := valDB.RunUpMigrations(cliCtx.Context); err != nil {
|
||||
return errors.Wrap(err, "could not run database migration")
|
||||
}
|
||||
if !cliCtx.Bool(cmd.DisableMonitoringFlag.Name) {
|
||||
if err := s.registerPrometheusService(cliCtx); err != nil {
|
||||
if err := c.registerPrometheusService(cliCtx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if featureconfig.Get().SlasherProtection {
|
||||
if err := s.registerSlasherClientService(); err != nil {
|
||||
if err := c.registerSlasherClientService(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := s.registerClientService(keyManager); err != nil {
|
||||
if err := c.registerClientService(keyManager); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.registerRPCService(cliCtx, keyManager); err != nil {
|
||||
if err := c.registerRPCService(cliCtx, keyManager); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.registerRPCGatewayService(cliCtx); err != nil {
|
||||
if err := c.registerRPCGatewayService(cliCtx); err != nil {
|
||||
return err
|
||||
}
|
||||
gatewayHost := cliCtx.String(flags.GRPCGatewayHost.Name)
|
||||
@@ -339,55 +339,55 @@ func (s *ValidatorClient) initializeForWeb(cliCtx *cli.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ValidatorClient) registerPrometheusService(cliCtx *cli.Context) error {
|
||||
func (c *ValidatorClient) registerPrometheusService(cliCtx *cli.Context) error {
|
||||
var additionalHandlers []prometheus.Handler
|
||||
if cliCtx.IsSet(cmd.EnableBackupWebhookFlag.Name) {
|
||||
additionalHandlers = append(
|
||||
additionalHandlers,
|
||||
prometheus.Handler{
|
||||
Path: "/db/backup",
|
||||
Handler: backuputil.BackupHandler(s.db, cliCtx.String(cmd.BackupWebhookOutputDir.Name)),
|
||||
Handler: backuputil.BackupHandler(c.db, cliCtx.String(cmd.BackupWebhookOutputDir.Name)),
|
||||
},
|
||||
)
|
||||
}
|
||||
service := prometheus.NewService(
|
||||
fmt.Sprintf("%s:%d", s.cliCtx.String(cmd.MonitoringHostFlag.Name), s.cliCtx.Int(flags.MonitoringPortFlag.Name)),
|
||||
s.services,
|
||||
fmt.Sprintf("%s:%d", c.cliCtx.String(cmd.MonitoringHostFlag.Name), c.cliCtx.Int(flags.MonitoringPortFlag.Name)),
|
||||
c.services,
|
||||
additionalHandlers...,
|
||||
)
|
||||
logrus.AddHook(prometheus.NewLogrusCollector())
|
||||
return s.services.RegisterService(service)
|
||||
return c.services.RegisterService(service)
|
||||
}
|
||||
|
||||
func (s *ValidatorClient) registerClientService(
|
||||
func (c *ValidatorClient) registerClientService(
|
||||
keyManager keymanager.IKeymanager,
|
||||
) error {
|
||||
endpoint := s.cliCtx.String(flags.BeaconRPCProviderFlag.Name)
|
||||
dataDir := s.cliCtx.String(cmd.DataDirFlag.Name)
|
||||
logValidatorBalances := !s.cliCtx.Bool(flags.DisablePenaltyRewardLogFlag.Name)
|
||||
emitAccountMetrics := !s.cliCtx.Bool(flags.DisableAccountMetricsFlag.Name)
|
||||
cert := s.cliCtx.String(flags.CertFlag.Name)
|
||||
graffiti := s.cliCtx.String(flags.GraffitiFlag.Name)
|
||||
maxCallRecvMsgSize := s.cliCtx.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name)
|
||||
grpcRetries := s.cliCtx.Uint(flags.GrpcRetriesFlag.Name)
|
||||
grpcRetryDelay := s.cliCtx.Duration(flags.GrpcRetryDelayFlag.Name)
|
||||
endpoint := c.cliCtx.String(flags.BeaconRPCProviderFlag.Name)
|
||||
dataDir := c.cliCtx.String(cmd.DataDirFlag.Name)
|
||||
logValidatorBalances := !c.cliCtx.Bool(flags.DisablePenaltyRewardLogFlag.Name)
|
||||
emitAccountMetrics := !c.cliCtx.Bool(flags.DisableAccountMetricsFlag.Name)
|
||||
cert := c.cliCtx.String(flags.CertFlag.Name)
|
||||
graffiti := c.cliCtx.String(flags.GraffitiFlag.Name)
|
||||
maxCallRecvMsgSize := c.cliCtx.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name)
|
||||
grpcRetries := c.cliCtx.Uint(flags.GrpcRetriesFlag.Name)
|
||||
grpcRetryDelay := c.cliCtx.Duration(flags.GrpcRetryDelayFlag.Name)
|
||||
var sp *slashing_protection.Service
|
||||
var protector slashing_protection.Protector
|
||||
if err := s.services.FetchService(&sp); err == nil {
|
||||
if err := c.services.FetchService(&sp); err == nil {
|
||||
protector = sp
|
||||
}
|
||||
|
||||
gStruct := &g.Graffiti{}
|
||||
var err error
|
||||
if s.cliCtx.IsSet(flags.GraffitiFileFlag.Name) {
|
||||
n := s.cliCtx.String(flags.GraffitiFileFlag.Name)
|
||||
if c.cliCtx.IsSet(flags.GraffitiFileFlag.Name) {
|
||||
n := c.cliCtx.String(flags.GraffitiFileFlag.Name)
|
||||
gStruct, err = g.ParseGraffitiFile(n)
|
||||
if err != nil {
|
||||
log.WithError(err).Warn("Could not parse graffiti file")
|
||||
}
|
||||
}
|
||||
|
||||
v, err := client.NewValidatorService(s.cliCtx.Context, &client.Config{
|
||||
v, err := client.NewValidatorService(c.cliCtx.Context, &client.Config{
|
||||
Endpoint: endpoint,
|
||||
DataDir: dataDir,
|
||||
KeyManager: keyManager,
|
||||
@@ -398,47 +398,47 @@ func (s *ValidatorClient) registerClientService(
|
||||
GrpcMaxCallRecvMsgSizeFlag: maxCallRecvMsgSize,
|
||||
GrpcRetriesFlag: grpcRetries,
|
||||
GrpcRetryDelay: grpcRetryDelay,
|
||||
GrpcHeadersFlag: s.cliCtx.String(flags.GrpcHeadersFlag.Name),
|
||||
GrpcHeadersFlag: c.cliCtx.String(flags.GrpcHeadersFlag.Name),
|
||||
Protector: protector,
|
||||
ValDB: s.db,
|
||||
UseWeb: s.cliCtx.Bool(flags.EnableWebFlag.Name),
|
||||
WalletInitializedFeed: s.walletInitialized,
|
||||
ValDB: c.db,
|
||||
UseWeb: c.cliCtx.Bool(flags.EnableWebFlag.Name),
|
||||
WalletInitializedFeed: c.walletInitialized,
|
||||
GraffitiStruct: gStruct,
|
||||
LogDutyCountDown: s.cliCtx.Bool(flags.EnableDutyCountDown.Name),
|
||||
LogDutyCountDown: c.cliCtx.Bool(flags.EnableDutyCountDown.Name),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not initialize client service")
|
||||
}
|
||||
return s.services.RegisterService(v)
|
||||
return c.services.RegisterService(v)
|
||||
}
|
||||
func (s *ValidatorClient) registerSlasherClientService() error {
|
||||
endpoint := s.cliCtx.String(flags.SlasherRPCProviderFlag.Name)
|
||||
func (c *ValidatorClient) registerSlasherClientService() error {
|
||||
endpoint := c.cliCtx.String(flags.SlasherRPCProviderFlag.Name)
|
||||
if endpoint == "" {
|
||||
return errors.New("external slasher feature flag is set but no slasher endpoint is configured")
|
||||
|
||||
}
|
||||
cert := s.cliCtx.String(flags.SlasherCertFlag.Name)
|
||||
maxCallRecvMsgSize := s.cliCtx.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name)
|
||||
grpcRetries := s.cliCtx.Uint(flags.GrpcRetriesFlag.Name)
|
||||
grpcRetryDelay := s.cliCtx.Duration(flags.GrpcRetryDelayFlag.Name)
|
||||
sp, err := slashing_protection.NewService(s.cliCtx.Context, &slashing_protection.Config{
|
||||
cert := c.cliCtx.String(flags.SlasherCertFlag.Name)
|
||||
maxCallRecvMsgSize := c.cliCtx.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name)
|
||||
grpcRetries := c.cliCtx.Uint(flags.GrpcRetriesFlag.Name)
|
||||
grpcRetryDelay := c.cliCtx.Duration(flags.GrpcRetryDelayFlag.Name)
|
||||
sp, err := slashing_protection.NewService(c.cliCtx.Context, &slashing_protection.Config{
|
||||
Endpoint: endpoint,
|
||||
CertFlag: cert,
|
||||
GrpcMaxCallRecvMsgSizeFlag: maxCallRecvMsgSize,
|
||||
GrpcRetriesFlag: grpcRetries,
|
||||
GrpcRetryDelay: grpcRetryDelay,
|
||||
GrpcHeadersFlag: s.cliCtx.String(flags.GrpcHeadersFlag.Name),
|
||||
GrpcHeadersFlag: c.cliCtx.String(flags.GrpcHeadersFlag.Name),
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not initialize client service")
|
||||
}
|
||||
return s.services.RegisterService(sp)
|
||||
return c.services.RegisterService(sp)
|
||||
}
|
||||
|
||||
func (s *ValidatorClient) registerRPCService(cliCtx *cli.Context, km keymanager.IKeymanager) error {
|
||||
func (c *ValidatorClient) registerRPCService(cliCtx *cli.Context, km keymanager.IKeymanager) error {
|
||||
var vs *client.ValidatorService
|
||||
if err := s.services.FetchService(&vs); err != nil {
|
||||
if err := c.services.FetchService(&vs); err != nil {
|
||||
return err
|
||||
}
|
||||
validatorGatewayHost := cliCtx.String(flags.GRPCGatewayHost.Name)
|
||||
@@ -449,23 +449,23 @@ func (s *ValidatorClient) registerRPCService(cliCtx *cli.Context, km keymanager.
|
||||
rpcPort := cliCtx.Int(flags.RPCPort.Name)
|
||||
nodeGatewayEndpoint := cliCtx.String(flags.BeaconRPCGatewayProviderFlag.Name)
|
||||
beaconClientEndpoint := cliCtx.String(flags.BeaconRPCProviderFlag.Name)
|
||||
maxCallRecvMsgSize := s.cliCtx.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name)
|
||||
grpcRetries := s.cliCtx.Uint(flags.GrpcRetriesFlag.Name)
|
||||
grpcRetryDelay := s.cliCtx.Duration(flags.GrpcRetryDelayFlag.Name)
|
||||
maxCallRecvMsgSize := c.cliCtx.Int(cmd.GrpcMaxCallRecvMsgSizeFlag.Name)
|
||||
grpcRetries := c.cliCtx.Uint(flags.GrpcRetriesFlag.Name)
|
||||
grpcRetryDelay := c.cliCtx.Duration(flags.GrpcRetryDelayFlag.Name)
|
||||
walletDir := cliCtx.String(flags.WalletDirFlag.Name)
|
||||
grpcHeaders := s.cliCtx.String(flags.GrpcHeadersFlag.Name)
|
||||
clientCert := s.cliCtx.String(flags.CertFlag.Name)
|
||||
grpcHeaders := c.cliCtx.String(flags.GrpcHeadersFlag.Name)
|
||||
clientCert := c.cliCtx.String(flags.CertFlag.Name)
|
||||
server := rpc.NewServer(cliCtx.Context, &rpc.Config{
|
||||
ValDB: s.db,
|
||||
ValDB: c.db,
|
||||
Host: rpcHost,
|
||||
Port: fmt.Sprintf("%d", rpcPort),
|
||||
WalletInitializedFeed: s.walletInitialized,
|
||||
WalletInitializedFeed: c.walletInitialized,
|
||||
ValidatorService: vs,
|
||||
SyncChecker: vs,
|
||||
GenesisFetcher: vs,
|
||||
NodeGatewayEndpoint: nodeGatewayEndpoint,
|
||||
WalletDir: walletDir,
|
||||
Wallet: s.wallet,
|
||||
Wallet: c.wallet,
|
||||
Keymanager: km,
|
||||
ValidatorGatewayHost: validatorGatewayHost,
|
||||
ValidatorGatewayPort: validatorGatewayPort,
|
||||
@@ -478,10 +478,10 @@ func (s *ValidatorClient) registerRPCService(cliCtx *cli.Context, km keymanager.
|
||||
ClientGrpcHeaders: strings.Split(grpcHeaders, ","),
|
||||
ClientWithCert: clientCert,
|
||||
})
|
||||
return s.services.RegisterService(server)
|
||||
return c.services.RegisterService(server)
|
||||
}
|
||||
|
||||
func (s *ValidatorClient) registerRPCGatewayService(cliCtx *cli.Context) error {
|
||||
func (c *ValidatorClient) registerRPCGatewayService(cliCtx *cli.Context) error {
|
||||
gatewayHost := cliCtx.String(flags.GRPCGatewayHost.Name)
|
||||
if gatewayHost != flags.DefaultGatewayHost {
|
||||
log.WithField("web-host", gatewayHost).Warn(
|
||||
@@ -501,7 +501,7 @@ func (s *ValidatorClient) registerRPCGatewayService(cliCtx *cli.Context) error {
|
||||
gatewayAddress,
|
||||
allowedOrigins,
|
||||
)
|
||||
return s.services.RegisterService(gatewaySrv)
|
||||
return c.services.RegisterService(gatewaySrv)
|
||||
}
|
||||
|
||||
func clearDB(ctx context.Context, dataDir string, force bool) error {
|
||||
|
||||
Reference in New Issue
Block a user