prysm-pulse/validator/attester/service.go
Nishant Das cddae7a306
Implement RPC Messaging Between Validators (#475)
* Adding Proto files

* Move to shared package

* adding attestation sub

* gazelle

* attestation check

* proposal finished

* Add in attesters responsibilities

* fixing dependency issues

* adding topics

* refactoring tests

* Adding more tests

* adding more changes

* gazelle

* removing attester p2p

* remove mock

* changing to new proposer model

* changing tests

* making changes

* gazelle

* adding gomock

* adding rpc methods, reverting changes to other proto files

* gazelle and test changes

* adding tests

* adding mocks and tests

* gazelle

* fixing merge issues

* lint

* lint
2018-09-16 09:12:36 +08:00

111 lines
3.1 KiB
Go

// Package attester defines all relevant functionality for a Attester actor
// within Ethereum 2.0.
package attester
import (
"context"
"github.com/ethereum/go-ethereum/event"
"github.com/gogo/protobuf/proto"
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
"github.com/sirupsen/logrus"
blake2b "golang.org/x/crypto/blake2b"
)
var log = logrus.WithField("prefix", "attester")
type rpcClientService interface {
AttesterServiceClient() pb.AttesterServiceClient
}
type assignmentAnnouncer interface {
AttesterAssignmentFeed() *event.Feed
}
// Attester holds functionality required to run a block attester
// in Ethereum 2.0.
type Attester struct {
ctx context.Context
cancel context.CancelFunc
assigner assignmentAnnouncer
rpcClientService rpcClientService
assignmentChan chan *pbp2p.BeaconBlock
shardID uint64
}
// Config options for an attester service.
type Config struct {
AssignmentBuf int
ShardID uint64
Assigner assignmentAnnouncer
Client rpcClientService
}
// NewAttester creates a new attester instance.
func NewAttester(ctx context.Context, cfg *Config) *Attester {
ctx, cancel := context.WithCancel(ctx)
return &Attester{
ctx: ctx,
cancel: cancel,
assigner: cfg.Assigner,
rpcClientService: cfg.Client,
shardID: cfg.ShardID,
assignmentChan: make(chan *pbp2p.BeaconBlock, cfg.AssignmentBuf),
}
}
// Start the main routine for an attester.
func (a *Attester) Start() {
log.Info("Starting service")
client := a.rpcClientService.AttesterServiceClient()
go a.run(a.ctx.Done(), client)
}
// Stop the main loop.
func (a *Attester) Stop() error {
defer a.cancel()
log.Info("Stopping service")
return nil
}
// run the main event loop that listens for an attester assignment.
func (a *Attester) run(done <-chan struct{}, client pb.AttesterServiceClient) {
sub := a.assigner.AttesterAssignmentFeed().Subscribe(a.assignmentChan)
defer sub.Unsubscribe()
for {
select {
case <-done:
log.Debug("Attester context closed, exiting goroutine")
return
case latestBeaconBlock := <-a.assignmentChan:
log.Info("Performing attester responsibility")
data, err := proto.Marshal(latestBeaconBlock)
if err != nil {
log.Errorf("Could not marshal latest beacon block: %v", err)
continue
}
latestBlockHash := blake2b.Sum512(data)
req := &pb.AttestRequest{
Attestation: &pbp2p.AggregatedAttestation{
Slot: latestBeaconBlock.GetSlotNumber(),
ShardId: a.shardID,
ShardBlockHash: latestBlockHash[:], // Is a stub for actual shard blockhash.
AttesterBitfield: []byte{}, // TODO: Need to find which index this attester represents.
AggregateSig: []uint64{}, // TODO: Need Signature verification scheme/library
},
}
res, err := client.AttestHead(a.ctx, req)
if err != nil {
log.Errorf("could not attest head: %v", err)
continue
}
log.Infof("Attestation proposed successfully with hash 0x%x", res.AttestationHash)
}
}
}