prysm-pulse/validator/client/validator_propose.go
Raul Jordan 053038446c
Allow 8 Validator Multinode Cluster to Run Indefinitely (#2050)
* plug forkchoice to blockchain service's block processing

* fixed tests

* more fixes...

* clean ups

* fixed test

* Update beacon-chain/blockchain/block_processing.go

* merged with 2006 and started fixing tests

* remove prints

* fixed tests

* lint

* include ops service

* if there's a skip slot, slot--

* fixed typo

* started working on test

* no fork choice in propose

* bleh, need to fix state generator first

* state gen takes input slot

* feedback

* fixed tests

* preston's feedback

* fmt

* removed extra logging

* add more logs

* fixed validator attest

* builds

* fixed save block

* children fix

* removed verbose logs

* fix fork choice

* right logs

* Add Prometheus Counter for Reorg (#2051)

* fetch every slot (#2052)

* test Fixes

* lint

* only regenerate state if there was a reorg

* better logging

* fixed seed

* better logging

* process skip slots in assignment requests

* fix lint

* disable state root computation

* filter attestations in regular sync

* log important items

* better info logs

* added spans to stategen

* span in stategen

* set validator deadline

* randao stuff

* disable sig verify

* lint

* lint

* save only using historical states

* use new goroutine for handling sync messages

* change default buffer sizes

* better p2p

* rem some useless logs

* lint

* sync tests complete

* complete tests

* tests fixed

* lint

* fix flakey att service

* PR feedback

* undo k8s changes

* Update beacon-chain/blockchain/block_processing.go

* Update beacon-chain/sync/regular_sync.go

* Add feature flag to enable compute state root

* add comment

* gazelle lint fix
2019-03-25 10:21:21 -05:00

128 lines
4.3 KiB
Go

package client
// Validator client proposer functions.
import (
"context"
"encoding/binary"
"fmt"
ptypes "github.com/gogo/protobuf/types"
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
pb "github.com/prysmaticlabs/prysm/proto/beacon/rpc/v1"
"github.com/prysmaticlabs/prysm/shared/forkutil"
"github.com/prysmaticlabs/prysm/shared/hashutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/sirupsen/logrus"
"go.opencensus.io/trace"
)
// ProposeBlock A new beacon block for a given slot. This method collects the
// previous beacon block, any pending deposits, and ETH1 data from the beacon
// chain node to construct the new block. The new block is then processed with
// the state root computation, and finally signed by the validator before being
// sent back to the beacon node for broadcasting.
func (v *validator) ProposeBlock(ctx context.Context, slot uint64) {
if slot == params.BeaconConfig().GenesisSlot {
log.Info("Assigned to genesis slot, skipping proposal")
return
}
ctx, span := trace.StartSpan(ctx, "validator.ProposeBlock")
defer span.End()
log.Info("Performing a beacon block proposal...")
// 1. Fetch data from Beacon Chain node.
// Get current head beacon block.
headBlock, err := v.beaconClient.CanonicalHead(ctx, &ptypes.Empty{})
if err != nil {
log.Errorf("Failed to fetch CanonicalHead: %v", err)
return
}
parentTreeRoot, err := hashutil.HashBeaconBlock(headBlock)
if err != nil {
log.Errorf("Failed to hash parent block: %v", err)
return
}
// Get validator ETH1 deposits which have not been included in the beacon chain.
pDepResp, err := v.beaconClient.PendingDeposits(ctx, &ptypes.Empty{})
if err != nil {
log.Errorf("Failed to get pending pendings: %v", err)
return
}
// Get ETH1 data.
eth1DataResp, err := v.beaconClient.Eth1Data(ctx, &ptypes.Empty{})
if err != nil {
log.Errorf("Failed to get ETH1 data: %v", err)
return
}
// Retrieve the current fork data from the beacon node.
fork, err := v.beaconClient.ForkData(ctx, &ptypes.Empty{})
if err != nil {
log.Errorf("Failed to get fork data from beacon node's state: %v", err)
return
}
// Then, we generate a RandaoReveal by signing the block's slot information using
// the validator's private key.
// epoch_signature = bls_sign(
// privkey=validator.privkey,
// message_hash=int_to_bytes32(slot_to_epoch(block.slot)),
// domain=get_domain(
// fork=fork, # `fork` is the fork object at the slot `block.slot`
// epoch=slot_to_epoch(block.slot),
// domain_type=DOMAIN_RANDAO,
// )
// )
epoch := slot / params.BeaconConfig().SlotsPerEpoch
buf := make([]byte, 32)
binary.LittleEndian.PutUint64(buf, epoch)
domain := forkutil.DomainVersion(fork, epoch, params.BeaconConfig().DomainRandao)
epochSignature := v.key.SecretKey.Sign(buf, domain)
// Fetch pending attestations seen by the beacon node.
attResp, err := v.proposerClient.PendingAttestations(ctx, &pb.PendingAttestationsRequest{
FilterReadyForInclusion: true,
ProposalBlockSlot: slot,
})
if err != nil {
log.Errorf("Failed to fetch pending attestations from the beacon node: %v", err)
return
}
// 2. Construct block.
block := &pbp2p.BeaconBlock{
Slot: slot,
ParentRootHash32: parentTreeRoot[:],
RandaoReveal: epochSignature.Marshal(),
Eth1Data: eth1DataResp.Eth1Data,
Body: &pbp2p.BeaconBlockBody{
Attestations: attResp.PendingAttestations,
ProposerSlashings: nil, // TODO(1438): Add after operations pool
AttesterSlashings: nil, // TODO(1438): Add after operations pool
Deposits: pDepResp.PendingDeposits,
VoluntaryExits: nil, // TODO(1323): Add validator exits
},
}
// 3. Compute state root transition from parent block to the new block.
block.StateRootHash32 = []byte("root")
// 4. Sign the complete block.
// TODO(1366): BLS sign block
block.Signature = nil
// 5. Broadcast to the network via beacon chain node.
blkResp, err := v.proposerClient.ProposeBlock(ctx, block)
if err != nil {
log.WithError(err).Error("Failed to propose block")
return
}
log.WithFields(logrus.Fields{
"blockRoot": fmt.Sprintf("%#x", blkResp.BlockRootHash32),
}).Info("Proposed new beacon block")
log.WithFields(logrus.Fields{
"numAttestations": len(block.Body.Attestations),
"numDeposits": len(block.Body.Deposits),
}).Info("Items included in block")
}