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:
Radosław Kapka
2021-01-20 15:39:07 +01:00
committed by GitHub
parent 27847ee2fe
commit 4b14fa4317
39 changed files with 635 additions and 635 deletions

View File

@@ -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")
}

View File

@@ -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 = &ethpb.ListIndexedAttestationsResponse{}
}
res, err = bs.beaconClient.ListIndexedAttestations(ctx, &ethpb.ListIndexedAttestationsRequest{
res, err = s.beaconClient.ListIndexedAttestations(ctx, &ethpb.ListIndexedAttestationsRequest{
QueryFilter: &ethpb.ListIndexedAttestationsRequest_Epoch{
Epoch: epoch,
},

View File

@@ -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, &ethpb.StreamBlocksRequest{} /* Prefers unverified block to catch slashing */)
stream, err := s.beaconClient.StreamBlocks(ctx, &ethpb.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, &ethpb.StreamBlocksRequest{} /* Prefers unverified block to catch slashing */)
stream, err = s.beaconClient.StreamBlocks(ctx, &ethpb.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

View File

@@ -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)
}

View File

@@ -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,

View File

@@ -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, &ethpb.ListValidatorsRequest{
vc, err := s.beaconClient.ListValidators(ctx, &ethpb.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",

View File

@@ -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

View File

@@ -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() {

View File

@@ -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
})

View File

@@ -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
})

View File

@@ -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 {

View File

@@ -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
})

View File

@@ -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]...))

View File

@@ -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")
}
}

View File

@@ -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 {

View File

@@ -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]
}

View File

@@ -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
}

View File

@@ -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,
}
}

View File

@@ -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
}
}

View File

@@ -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():

View File

@@ -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 := &ethpb.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
}

View File

@@ -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 = &ethpb.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)
}
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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
}

View File

@@ -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.

View File

@@ -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
})

View File

@@ -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
}

View File

@@ -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)
})

View File

@@ -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.

View File

@@ -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)

View File

@@ -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)
}

View File

@@ -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()

View File

@@ -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

View File

@@ -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.

View File

@@ -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{

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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 {