prysm-pulse/validator/client/beacon-api/propose_beacon_block.go
Dhruv Bodani 700f5fee8c
Add context to beacon API REST implementation (#11847)
* add context to beacon APIs

* add TODO to merge GET and POST methods

* fix linter action

Co-authored-by: kasey <489222+kasey@users.noreply.github.com>
Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
2023-01-06 03:32:13 +00:00

294 lines
15 KiB
Go

package beacon_api
import (
"bytes"
"context"
"encoding/json"
"net/http"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/rpc/apimiddleware"
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
)
func (c beaconApiValidatorClient) proposeBeaconBlock(ctx context.Context, in *ethpb.GenericSignedBeaconBlock) (*ethpb.ProposeResponse, error) {
var consensusVersion string
var beaconBlockRoot [32]byte
var err error
var marshalledSignedBeaconBlockJson []byte
blinded := false
switch blockType := in.Block.(type) {
case *ethpb.GenericSignedBeaconBlock_Phase0:
consensusVersion = "phase0"
beaconBlockRoot, err = blockType.Phase0.Block.HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "failed to compute block root for phase0 beacon block")
}
marshalledSignedBeaconBlockJson, err = marshallBeaconBlockPhase0(blockType.Phase0)
if err != nil {
return nil, errors.Wrap(err, "failed to marshall phase0 beacon block")
}
case *ethpb.GenericSignedBeaconBlock_Altair:
consensusVersion = "altair"
beaconBlockRoot, err = blockType.Altair.Block.HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "failed to compute block root for altair beacon block")
}
marshalledSignedBeaconBlockJson, err = marshallBeaconBlockAltair(blockType.Altair)
if err != nil {
return nil, errors.Wrap(err, "failed to marshall altair beacon block")
}
case *ethpb.GenericSignedBeaconBlock_Bellatrix:
consensusVersion = "bellatrix"
beaconBlockRoot, err = blockType.Bellatrix.Block.HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "failed to compute block root for bellatrix beacon block")
}
marshalledSignedBeaconBlockJson, err = marshallBeaconBlockBellatrix(blockType.Bellatrix)
if err != nil {
return nil, errors.Wrap(err, "failed to marshall bellatrix beacon block")
}
case *ethpb.GenericSignedBeaconBlock_BlindedBellatrix:
blinded = true
consensusVersion = "bellatrix"
beaconBlockRoot, err = blockType.BlindedBellatrix.Block.HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "failed to compute block root for blinded bellatrix beacon block")
}
marshalledSignedBeaconBlockJson, err = marshallBeaconBlockBlindedBellatrix(blockType.BlindedBellatrix)
if err != nil {
return nil, errors.Wrap(err, "failed to marshall blinded bellatrix beacon block")
}
case *ethpb.GenericSignedBeaconBlock_BlindedCapella:
blinded = true
consensusVersion = "capella"
beaconBlockRoot, err = blockType.BlindedCapella.Block.HashTreeRoot()
if err != nil {
return nil, errors.Wrap(err, "failed to compute block root for blinded capella beacon block")
}
marshalledSignedBeaconBlockJson, err = marshallBeaconBlockBlindedCapella(blockType.BlindedCapella)
if err != nil {
return nil, errors.Wrap(err, "failed to marshall blinded capella beacon block")
}
case *ethpb.GenericSignedBeaconBlock_Capella:
return nil, errors.Errorf("Capella blocks are not supported yet")
default:
return nil, errors.Errorf("unsupported block type %T", in.Block)
}
var endpoint string
if blinded {
endpoint = "/eth/v1/beacon/blinded_blocks"
} else {
endpoint = "/eth/v1/beacon/blocks"
}
headers := map[string]string{"Eth-Consensus-Version": consensusVersion}
if httpError, err := c.jsonRestHandler.PostRestJson(ctx, endpoint, headers, bytes.NewBuffer(marshalledSignedBeaconBlockJson), nil); err != nil {
if httpError != nil && httpError.Code == http.StatusAccepted {
// Error 202 means that the block was successfully broadcasted, but validation failed
return nil, errors.Wrap(err, "block was successfully broadcasted but failed validation")
}
return nil, errors.Wrap(err, "failed to send POST data to REST endpoint")
}
return &ethpb.ProposeResponse{BlockRoot: beaconBlockRoot[:]}, nil
}
func marshallBeaconBlockPhase0(block *ethpb.SignedBeaconBlock) ([]byte, error) {
signedBeaconBlockJson := &apimiddleware.SignedBeaconBlockContainerJson{
Signature: hexutil.Encode(block.Signature),
Message: &apimiddleware.BeaconBlockJson{
Body: &apimiddleware.BeaconBlockBodyJson{
Attestations: jsonifyAttestations(block.Block.Body.Attestations),
AttesterSlashings: jsonifyAttesterSlashings(block.Block.Body.AttesterSlashings),
Deposits: jsonifyDeposits(block.Block.Body.Deposits),
Eth1Data: jsonifyEth1Data(block.Block.Body.Eth1Data),
Graffiti: hexutil.Encode(block.Block.Body.Graffiti),
ProposerSlashings: jsonifyProposerSlashings(block.Block.Body.ProposerSlashings),
RandaoReveal: hexutil.Encode(block.Block.Body.RandaoReveal),
VoluntaryExits: jsonifySignedVoluntaryExits(block.Block.Body.VoluntaryExits),
},
ParentRoot: hexutil.Encode(block.Block.ParentRoot),
ProposerIndex: uint64ToString(block.Block.ProposerIndex),
Slot: uint64ToString(block.Block.Slot),
StateRoot: hexutil.Encode(block.Block.StateRoot),
},
}
return json.Marshal(signedBeaconBlockJson)
}
func marshallBeaconBlockAltair(block *ethpb.SignedBeaconBlockAltair) ([]byte, error) {
signedBeaconBlockAltairJson := &apimiddleware.SignedBeaconBlockAltairContainerJson{
Signature: hexutil.Encode(block.Signature),
Message: &apimiddleware.BeaconBlockAltairJson{
ParentRoot: hexutil.Encode(block.Block.ParentRoot),
ProposerIndex: uint64ToString(block.Block.ProposerIndex),
Slot: uint64ToString(block.Block.Slot),
StateRoot: hexutil.Encode(block.Block.StateRoot),
Body: &apimiddleware.BeaconBlockBodyAltairJson{
Attestations: jsonifyAttestations(block.Block.Body.Attestations),
AttesterSlashings: jsonifyAttesterSlashings(block.Block.Body.AttesterSlashings),
Deposits: jsonifyDeposits(block.Block.Body.Deposits),
Eth1Data: jsonifyEth1Data(block.Block.Body.Eth1Data),
Graffiti: hexutil.Encode(block.Block.Body.Graffiti),
ProposerSlashings: jsonifyProposerSlashings(block.Block.Body.ProposerSlashings),
RandaoReveal: hexutil.Encode(block.Block.Body.RandaoReveal),
VoluntaryExits: jsonifySignedVoluntaryExits(block.Block.Body.VoluntaryExits),
SyncAggregate: &apimiddleware.SyncAggregateJson{
SyncCommitteeBits: hexutil.Encode(block.Block.Body.SyncAggregate.SyncCommitteeBits),
SyncCommitteeSignature: hexutil.Encode(block.Block.Body.SyncAggregate.SyncCommitteeSignature),
},
},
},
}
return json.Marshal(signedBeaconBlockAltairJson)
}
func marshallBeaconBlockBellatrix(block *ethpb.SignedBeaconBlockBellatrix) ([]byte, error) {
signedBeaconBlockBellatrixJson := &apimiddleware.SignedBeaconBlockBellatrixContainerJson{
Signature: hexutil.Encode(block.Signature),
Message: &apimiddleware.BeaconBlockBellatrixJson{
ParentRoot: hexutil.Encode(block.Block.ParentRoot),
ProposerIndex: uint64ToString(block.Block.ProposerIndex),
Slot: uint64ToString(block.Block.Slot),
StateRoot: hexutil.Encode(block.Block.StateRoot),
Body: &apimiddleware.BeaconBlockBodyBellatrixJson{
Attestations: jsonifyAttestations(block.Block.Body.Attestations),
AttesterSlashings: jsonifyAttesterSlashings(block.Block.Body.AttesterSlashings),
Deposits: jsonifyDeposits(block.Block.Body.Deposits),
Eth1Data: jsonifyEth1Data(block.Block.Body.Eth1Data),
Graffiti: hexutil.Encode(block.Block.Body.Graffiti),
ProposerSlashings: jsonifyProposerSlashings(block.Block.Body.ProposerSlashings),
RandaoReveal: hexutil.Encode(block.Block.Body.RandaoReveal),
VoluntaryExits: jsonifySignedVoluntaryExits(block.Block.Body.VoluntaryExits),
SyncAggregate: &apimiddleware.SyncAggregateJson{
SyncCommitteeBits: hexutil.Encode(block.Block.Body.SyncAggregate.SyncCommitteeBits),
SyncCommitteeSignature: hexutil.Encode(block.Block.Body.SyncAggregate.SyncCommitteeSignature),
},
ExecutionPayload: &apimiddleware.ExecutionPayloadJson{
BaseFeePerGas: bytesutil.LittleEndianBytesToBigInt(block.Block.Body.ExecutionPayload.BaseFeePerGas).String(),
BlockHash: hexutil.Encode(block.Block.Body.ExecutionPayload.BlockHash),
BlockNumber: uint64ToString(block.Block.Body.ExecutionPayload.BlockNumber),
ExtraData: hexutil.Encode(block.Block.Body.ExecutionPayload.ExtraData),
FeeRecipient: hexutil.Encode(block.Block.Body.ExecutionPayload.FeeRecipient),
GasLimit: uint64ToString(block.Block.Body.ExecutionPayload.GasLimit),
GasUsed: uint64ToString(block.Block.Body.ExecutionPayload.GasUsed),
LogsBloom: hexutil.Encode(block.Block.Body.ExecutionPayload.LogsBloom),
ParentHash: hexutil.Encode(block.Block.Body.ExecutionPayload.ParentHash),
PrevRandao: hexutil.Encode(block.Block.Body.ExecutionPayload.PrevRandao),
ReceiptsRoot: hexutil.Encode(block.Block.Body.ExecutionPayload.ReceiptsRoot),
StateRoot: hexutil.Encode(block.Block.Body.ExecutionPayload.StateRoot),
TimeStamp: uint64ToString(block.Block.Body.ExecutionPayload.Timestamp),
Transactions: jsonifyTransactions(block.Block.Body.ExecutionPayload.Transactions),
},
},
},
}
return json.Marshal(signedBeaconBlockBellatrixJson)
}
func marshallBeaconBlockBlindedBellatrix(block *ethpb.SignedBlindedBeaconBlockBellatrix) ([]byte, error) {
signedBeaconBlockBellatrixJson := &apimiddleware.SignedBlindedBeaconBlockBellatrixContainerJson{
Signature: hexutil.Encode(block.Signature),
Message: &apimiddleware.BlindedBeaconBlockBellatrixJson{
ParentRoot: hexutil.Encode(block.Block.ParentRoot),
ProposerIndex: uint64ToString(block.Block.ProposerIndex),
Slot: uint64ToString(block.Block.Slot),
StateRoot: hexutil.Encode(block.Block.StateRoot),
Body: &apimiddleware.BlindedBeaconBlockBodyBellatrixJson{
Attestations: jsonifyAttestations(block.Block.Body.Attestations),
AttesterSlashings: jsonifyAttesterSlashings(block.Block.Body.AttesterSlashings),
Deposits: jsonifyDeposits(block.Block.Body.Deposits),
Eth1Data: jsonifyEth1Data(block.Block.Body.Eth1Data),
Graffiti: hexutil.Encode(block.Block.Body.Graffiti),
ProposerSlashings: jsonifyProposerSlashings(block.Block.Body.ProposerSlashings),
RandaoReveal: hexutil.Encode(block.Block.Body.RandaoReveal),
VoluntaryExits: jsonifySignedVoluntaryExits(block.Block.Body.VoluntaryExits),
SyncAggregate: &apimiddleware.SyncAggregateJson{
SyncCommitteeBits: hexutil.Encode(block.Block.Body.SyncAggregate.SyncCommitteeBits),
SyncCommitteeSignature: hexutil.Encode(block.Block.Body.SyncAggregate.SyncCommitteeSignature),
},
ExecutionPayloadHeader: &apimiddleware.ExecutionPayloadHeaderJson{
BaseFeePerGas: bytesutil.LittleEndianBytesToBigInt(block.Block.Body.ExecutionPayloadHeader.BaseFeePerGas).String(),
BlockHash: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.BlockHash),
BlockNumber: uint64ToString(block.Block.Body.ExecutionPayloadHeader.BlockNumber),
ExtraData: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.ExtraData),
FeeRecipient: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.FeeRecipient),
GasLimit: uint64ToString(block.Block.Body.ExecutionPayloadHeader.GasLimit),
GasUsed: uint64ToString(block.Block.Body.ExecutionPayloadHeader.GasUsed),
LogsBloom: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.LogsBloom),
ParentHash: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.ParentHash),
PrevRandao: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.PrevRandao),
ReceiptsRoot: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.ReceiptsRoot),
StateRoot: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.StateRoot),
TimeStamp: uint64ToString(block.Block.Body.ExecutionPayloadHeader.Timestamp),
TransactionsRoot: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.TransactionsRoot),
},
},
},
}
return json.Marshal(signedBeaconBlockBellatrixJson)
}
func marshallBeaconBlockBlindedCapella(block *ethpb.SignedBlindedBeaconBlockCapella) ([]byte, error) {
signedBeaconBlockCapellaJson := &apimiddleware.SignedBlindedBeaconBlockCapellaContainerJson{
Signature: hexutil.Encode(block.Signature),
Message: &apimiddleware.BlindedBeaconBlockCapellaJson{
ParentRoot: hexutil.Encode(block.Block.ParentRoot),
ProposerIndex: uint64ToString(block.Block.ProposerIndex),
Slot: uint64ToString(block.Block.Slot),
StateRoot: hexutil.Encode(block.Block.StateRoot),
Body: &apimiddleware.BlindedBeaconBlockBodyCapellaJson{
Attestations: jsonifyAttestations(block.Block.Body.Attestations),
AttesterSlashings: jsonifyAttesterSlashings(block.Block.Body.AttesterSlashings),
Deposits: jsonifyDeposits(block.Block.Body.Deposits),
Eth1Data: jsonifyEth1Data(block.Block.Body.Eth1Data),
Graffiti: hexutil.Encode(block.Block.Body.Graffiti),
ProposerSlashings: jsonifyProposerSlashings(block.Block.Body.ProposerSlashings),
RandaoReveal: hexutil.Encode(block.Block.Body.RandaoReveal),
VoluntaryExits: jsonifySignedVoluntaryExits(block.Block.Body.VoluntaryExits),
SyncAggregate: &apimiddleware.SyncAggregateJson{
SyncCommitteeBits: hexutil.Encode(block.Block.Body.SyncAggregate.SyncCommitteeBits),
SyncCommitteeSignature: hexutil.Encode(block.Block.Body.SyncAggregate.SyncCommitteeSignature),
},
ExecutionPayloadHeader: &apimiddleware.ExecutionPayloadHeaderCapellaJson{
BaseFeePerGas: bytesutil.LittleEndianBytesToBigInt(block.Block.Body.ExecutionPayloadHeader.BaseFeePerGas).String(),
BlockHash: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.BlockHash),
BlockNumber: uint64ToString(block.Block.Body.ExecutionPayloadHeader.BlockNumber),
ExtraData: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.ExtraData),
FeeRecipient: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.FeeRecipient),
GasLimit: uint64ToString(block.Block.Body.ExecutionPayloadHeader.GasLimit),
GasUsed: uint64ToString(block.Block.Body.ExecutionPayloadHeader.GasUsed),
LogsBloom: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.LogsBloom),
ParentHash: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.ParentHash),
PrevRandao: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.PrevRandao),
ReceiptsRoot: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.ReceiptsRoot),
StateRoot: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.StateRoot),
TimeStamp: uint64ToString(block.Block.Body.ExecutionPayloadHeader.Timestamp),
TransactionsRoot: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.TransactionsRoot),
WithdrawalsRoot: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.WithdrawalsRoot),
},
BLSToExecutionChanges: jsonifyBlsToExecutionChanges(block.Block.Body.BlsToExecutionChanges),
},
},
}
return json.Marshal(signedBeaconBlockCapellaJson)
}