Files
prysm/beacon-chain/rpc/eth/rewards/service.go
Radosław Kapka 4c47756aed HTTP endpoints cleanup (#13251)
* remove validation package

* structs cleanup

* merge with apimiddleware removal

* more validation and Bls capitalization

* builder test fix

* use strconv for uint->str conversions

* use DecodeHexWithLength

* use exact param names

* rename http package to httputil

* change conversions to fmt.Sprintf

* handle query paramsd and route variables

* spans and receiver name

* split structs, move bytes helper

* missing ok check

* fix reference to indexed failure

* errors fixup

* add godoc to helper

* fix BLS casing and chainhead ref

* review

* fix import in tests

* gzl
2023-12-08 20:37:20 +00:00

125 lines
4.9 KiB
Go

package rewards
import (
"context"
"net/http"
"strconv"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/altair"
coreblocks "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/validators"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stategen"
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
"github.com/prysmaticlabs/prysm/v4/network/httputil"
)
// BlockRewardsFetcher is a interface that provides access to reward related responses
type BlockRewardsFetcher interface {
GetBlockRewardsData(context.Context, interfaces.ReadOnlySignedBeaconBlock) (*BlockRewards, *httputil.DefaultErrorJson)
GetStateForRewards(context.Context, interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, *httputil.DefaultErrorJson)
}
// BlockRewardService implements BlockRewardsFetcher and can be declared to access the underlying functions
type BlockRewardService struct {
Replayer stategen.ReplayerBuilder
}
// GetBlockRewardsData returns the BlockRewards Object which is used for the BlockRewardsResponse and ProduceBlockV3
func (rs *BlockRewardService) GetBlockRewardsData(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) (*BlockRewards, *httputil.DefaultErrorJson) {
st, httpErr := rs.GetStateForRewards(ctx, blk)
if httpErr != nil {
return nil, httpErr
}
proposerIndex := blk.Block().ProposerIndex()
initBalance, err := st.BalanceAtIndex(proposerIndex)
if err != nil {
return nil, &httputil.DefaultErrorJson{
Message: "Could not get proposer's balance: " + err.Error(),
Code: http.StatusInternalServerError,
}
}
st, err = altair.ProcessAttestationsNoVerifySignature(ctx, st, blk)
if err != nil {
return nil, &httputil.DefaultErrorJson{
Message: "Could not get attestation rewards: " + err.Error(),
Code: http.StatusInternalServerError,
}
}
attBalance, err := st.BalanceAtIndex(proposerIndex)
if err != nil {
return nil, &httputil.DefaultErrorJson{
Message: "Could not get proposer's balance: " + err.Error(),
Code: http.StatusInternalServerError,
}
}
st, err = coreblocks.ProcessAttesterSlashings(ctx, st, blk.Block().Body().AttesterSlashings(), validators.SlashValidator)
if err != nil {
return nil, &httputil.DefaultErrorJson{
Message: "Could not get attester slashing rewards: " + err.Error(),
Code: http.StatusInternalServerError,
}
}
attSlashingsBalance, err := st.BalanceAtIndex(proposerIndex)
if err != nil {
return nil, &httputil.DefaultErrorJson{
Message: "Could not get proposer's balance: " + err.Error(),
Code: http.StatusInternalServerError,
}
}
st, err = coreblocks.ProcessProposerSlashings(ctx, st, blk.Block().Body().ProposerSlashings(), validators.SlashValidator)
if err != nil {
return nil, &httputil.DefaultErrorJson{
Message: "Could not get proposer slashing rewards: " + err.Error(),
Code: http.StatusInternalServerError,
}
}
proposerSlashingsBalance, err := st.BalanceAtIndex(proposerIndex)
if err != nil {
return nil, &httputil.DefaultErrorJson{
Message: "Could not get proposer's balance: " + err.Error(),
Code: http.StatusInternalServerError,
}
}
sa, err := blk.Block().Body().SyncAggregate()
if err != nil {
return nil, &httputil.DefaultErrorJson{
Message: "Could not get sync aggregate: " + err.Error(),
Code: http.StatusInternalServerError,
}
}
var syncCommitteeReward uint64
_, syncCommitteeReward, err = altair.ProcessSyncAggregate(ctx, st, sa)
if err != nil {
return nil, &httputil.DefaultErrorJson{
Message: "Could not get sync aggregate rewards: " + err.Error(),
Code: http.StatusInternalServerError,
}
}
return &BlockRewards{
ProposerIndex: strconv.FormatUint(uint64(proposerIndex), 10),
Total: strconv.FormatUint(proposerSlashingsBalance-initBalance+syncCommitteeReward, 10),
Attestations: strconv.FormatUint(attBalance-initBalance, 10),
SyncAggregate: strconv.FormatUint(syncCommitteeReward, 10),
ProposerSlashings: strconv.FormatUint(proposerSlashingsBalance-attSlashingsBalance, 10),
AttesterSlashings: strconv.FormatUint(attSlashingsBalance-attBalance, 10),
}, nil
}
// GetStateForRewards returns the state replayed up to the block's slot
func (rs *BlockRewardService) GetStateForRewards(ctx context.Context, blk interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, *httputil.DefaultErrorJson) {
// We want to run several block processing functions that update the proposer's balance.
// This will allow us to calculate proposer rewards for each operation (atts, slashings etc).
// To do this, we replay the state up to the block's slot, but before processing the block.
st, err := rs.Replayer.ReplayerForSlot(blk.Block().Slot()-1).ReplayToSlot(ctx, blk.Block().Slot())
if err != nil {
return nil, &httputil.DefaultErrorJson{
Message: "Could not get state: " + err.Error(),
Code: http.StatusInternalServerError,
}
}
return st, nil
}