mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-25 12:57:18 +00:00
700f5fee8c
* 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>
294 lines
15 KiB
Go
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 ðpb.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)
|
|
}
|