mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2025-01-08 03:51:20 +00:00
47a6ac16da
adds a two indexes to the validators cache creates beaconhttp package with many utilities for beacon http endpoint (future support for ssz is baked in) started on some validator endpoints
95 lines
2.7 KiB
Go
95 lines
2.7 KiB
Go
package handler
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/binary"
|
|
"net/http"
|
|
"sync"
|
|
|
|
"github.com/ledgerwatch/erigon/cl/beacon/beaconhttp"
|
|
shuffling2 "github.com/ledgerwatch/erigon/cl/phase1/core/state/shuffling"
|
|
|
|
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
|
)
|
|
|
|
type proposerDuties struct {
|
|
Pubkey libcommon.Bytes48 `json:"pubkey"`
|
|
ValidatorIndex uint64 `json:"validator_index"`
|
|
Slot uint64 `json:"slot"`
|
|
}
|
|
|
|
func (a *ApiHandler) getDutiesProposer(r *http.Request) (*beaconResponse, error) {
|
|
|
|
epoch, err := epochFromRequest(r)
|
|
if err != nil {
|
|
return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, err.Error())
|
|
}
|
|
|
|
if epoch < a.forkchoiceStore.FinalizedCheckpoint().Epoch() {
|
|
return nil, beaconhttp.NewEndpointError(http.StatusBadRequest, "invalid epoch")
|
|
}
|
|
|
|
// We need to compute our duties
|
|
state, cancel := a.syncedData.HeadState()
|
|
defer cancel()
|
|
if state == nil {
|
|
return nil, beaconhttp.NewEndpointError(http.StatusInternalServerError, "beacon node is syncing")
|
|
|
|
}
|
|
|
|
expectedSlot := epoch * a.beaconChainCfg.SlotsPerEpoch
|
|
|
|
duties := make([]proposerDuties, a.beaconChainCfg.SlotsPerEpoch)
|
|
wg := sync.WaitGroup{}
|
|
|
|
for slot := expectedSlot; slot < expectedSlot+a.beaconChainCfg.SlotsPerEpoch; slot++ {
|
|
var proposerIndex uint64
|
|
// Lets do proposer index computation
|
|
mixPosition := (epoch + a.beaconChainCfg.EpochsPerHistoricalVector - a.beaconChainCfg.MinSeedLookahead - 1) %
|
|
a.beaconChainCfg.EpochsPerHistoricalVector
|
|
// Input for the seed hash.
|
|
mix := state.GetRandaoMix(int(mixPosition))
|
|
input := shuffling2.GetSeed(a.beaconChainCfg, mix, epoch, a.beaconChainCfg.DomainBeaconProposer)
|
|
slotByteArray := make([]byte, 8)
|
|
binary.LittleEndian.PutUint64(slotByteArray, slot)
|
|
|
|
// Add slot to the end of the input.
|
|
inputWithSlot := append(input[:], slotByteArray...)
|
|
hash := sha256.New()
|
|
|
|
// Calculate the hash.
|
|
hash.Write(inputWithSlot)
|
|
seed := hash.Sum(nil)
|
|
|
|
indices := state.GetActiveValidatorsIndices(epoch)
|
|
|
|
// Write the seed to an array.
|
|
seedArray := [32]byte{}
|
|
copy(seedArray[:], seed)
|
|
wg.Add(1)
|
|
|
|
// Do it in parallel
|
|
go func(i, slot uint64, indicies []uint64, seedArray [32]byte) {
|
|
defer wg.Done()
|
|
proposerIndex, err = shuffling2.ComputeProposerIndex(state.BeaconState, indices, seedArray)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
var pk libcommon.Bytes48
|
|
pk, err = state.ValidatorPublicKey(int(proposerIndex))
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
duties[i] = proposerDuties{
|
|
Pubkey: pk,
|
|
ValidatorIndex: proposerIndex,
|
|
Slot: slot,
|
|
}
|
|
}(slot-expectedSlot, slot, indices, seedArray)
|
|
}
|
|
wg.Wait()
|
|
|
|
return newBeaconResponse(duties).withFinalized(false).withVersion(a.beaconChainCfg.GetCurrentStateVersion(epoch)), nil
|
|
|
|
}
|