prysm-pulse/proto/engine/v1/json_marshal_unmarshal.go

910 lines
29 KiB
Go

package enginev1
import (
"encoding/json"
"math/big"
"reflect"
"strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
gethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/pkg/errors"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
"github.com/prysmaticlabs/prysm/v5/runtime/version"
)
// PayloadIDBytes defines a custom type for Payload IDs used by the engine API
// client with proper JSON Marshal and Unmarshal methods to hex.
type PayloadIDBytes [8]byte
// MarshalJSON --
func (b PayloadIDBytes) MarshalJSON() ([]byte, error) {
return json.Marshal(hexutil.Bytes(b[:]))
}
// ExecutionBlock is the response kind received by the eth_getBlockByHash and
// eth_getBlockByNumber endpoints via JSON-RPC.
type ExecutionBlock struct {
Version int
gethtypes.Header
Hash common.Hash `json:"hash"`
Transactions []*gethtypes.Transaction `json:"transactions"`
TotalDifficulty string `json:"totalDifficulty"`
Withdrawals []*Withdrawal `json:"withdrawals"`
}
func (e *ExecutionBlock) MarshalJSON() ([]byte, error) {
decoded := make(map[string]interface{})
encodedHeader, err := e.Header.MarshalJSON()
if err != nil {
return nil, err
}
if err := json.Unmarshal(encodedHeader, &decoded); err != nil {
return nil, err
}
decoded["hash"] = e.Hash.String()
decoded["transactions"] = e.Transactions
decoded["totalDifficulty"] = e.TotalDifficulty
if e.Version == version.Capella {
decoded["withdrawals"] = e.Withdrawals
}
return json.Marshal(decoded)
}
func (e *ExecutionBlock) UnmarshalJSON(enc []byte) error {
type transactionsJson struct {
Transactions []*gethtypes.Transaction `json:"transactions"`
}
type withdrawalsJson struct {
Withdrawals []*withdrawalJSON `json:"withdrawals"`
}
if err := e.Header.UnmarshalJSON(enc); err != nil {
return err
}
decoded := make(map[string]interface{})
if err := json.Unmarshal(enc, &decoded); err != nil {
return err
}
blockHashStr, ok := decoded["hash"].(string)
if !ok {
return errors.New("expected `hash` field in JSON response")
}
decodedHash, err := hexutil.Decode(blockHashStr)
if err != nil {
return err
}
e.Hash = common.BytesToHash(decodedHash)
e.TotalDifficulty, ok = decoded["totalDifficulty"].(string)
if !ok {
return errors.New("expected `totalDifficulty` field in JSON response")
}
rawWithdrawals, ok := decoded["withdrawals"]
if !ok || rawWithdrawals == nil {
e.Version = version.Bellatrix
} else {
e.Version = version.Capella
j := &withdrawalsJson{}
if err := json.Unmarshal(enc, j); err != nil {
return err
}
ws := make([]*Withdrawal, len(j.Withdrawals))
for i, wj := range j.Withdrawals {
ws[i], err = wj.ToWithdrawal()
if err != nil {
return err
}
}
e.Withdrawals = ws
edg, has := decoded["excessBlobGas"]
if has && edg != nil {
e.Version = version.Deneb
}
dgu, has := decoded["blobGasUsed"]
if has && dgu != nil {
e.Version = version.Deneb
}
}
rawTxList, ok := decoded["transactions"]
if !ok || rawTxList == nil {
// Exit early if there are no transactions stored in the json payload.
return nil
}
txsList, ok := rawTxList.([]interface{})
if !ok {
return errors.Errorf("expected transaction list to be of a slice interface type.")
}
for _, tx := range txsList {
// If the transaction is just a hex string, do not attempt to
// unmarshal into a full transaction object.
if txItem, ok := tx.(string); ok && strings.HasPrefix(txItem, "0x") {
return nil
}
}
// If the block contains a list of transactions, we JSON unmarshal
// them into a list of geth transaction objects.
txJson := &transactionsJson{}
if err := json.Unmarshal(enc, txJson); err != nil {
return err
}
e.Transactions = txJson.Transactions
return nil
}
// UnmarshalJSON --
func (b *PayloadIDBytes) UnmarshalJSON(enc []byte) error {
var res [8]byte
if err := hexutil.UnmarshalFixedJSON(reflect.TypeOf(b), enc, res[:]); err != nil {
return err
}
*b = res
return nil
}
type withdrawalJSON struct {
Index *hexutil.Uint64 `json:"index"`
Validator *hexutil.Uint64 `json:"validatorIndex"`
Address *common.Address `json:"address"`
Amount *hexutil.Uint64 `json:"amount"`
}
func (j *withdrawalJSON) ToWithdrawal() (*Withdrawal, error) {
w := &Withdrawal{}
b, err := json.Marshal(j)
if err != nil {
return nil, err
}
if err := w.UnmarshalJSON(b); err != nil {
return nil, err
}
return w, nil
}
func (w *Withdrawal) MarshalJSON() ([]byte, error) {
index := hexutil.Uint64(w.Index)
validatorIndex := hexutil.Uint64(w.ValidatorIndex)
gwei := hexutil.Uint64(w.Amount)
address := common.BytesToAddress(w.Address)
return json.Marshal(withdrawalJSON{
Index: &index,
Validator: &validatorIndex,
Address: &address,
Amount: &gwei,
})
}
func (w *Withdrawal) UnmarshalJSON(enc []byte) error {
dec := withdrawalJSON{}
if err := json.Unmarshal(enc, &dec); err != nil {
return err
}
if dec.Index == nil {
return errors.New("missing withdrawal index")
}
if dec.Validator == nil {
return errors.New("missing validator index")
}
if dec.Amount == nil {
return errors.New("missing withdrawal amount")
}
if dec.Address == nil {
return errors.New("missing execution address")
}
*w = Withdrawal{}
w.Index = uint64(*dec.Index)
w.ValidatorIndex = primitives.ValidatorIndex(*dec.Validator)
w.Amount = uint64(*dec.Amount)
w.Address = dec.Address.Bytes()
return nil
}
type executionPayloadJSON struct {
ParentHash *common.Hash `json:"parentHash"`
FeeRecipient *common.Address `json:"feeRecipient"`
StateRoot *common.Hash `json:"stateRoot"`
ReceiptsRoot *common.Hash `json:"receiptsRoot"`
LogsBloom *hexutil.Bytes `json:"logsBloom"`
PrevRandao *common.Hash `json:"prevRandao"`
BlockNumber *hexutil.Uint64 `json:"blockNumber"`
GasLimit *hexutil.Uint64 `json:"gasLimit"`
GasUsed *hexutil.Uint64 `json:"gasUsed"`
Timestamp *hexutil.Uint64 `json:"timestamp"`
ExtraData hexutil.Bytes `json:"extraData"`
BaseFeePerGas string `json:"baseFeePerGas"`
BlockHash *common.Hash `json:"blockHash"`
Transactions []hexutil.Bytes `json:"transactions"`
}
type GetPayloadV2ResponseJson struct {
ExecutionPayload *ExecutionPayloadCapellaJSON `json:"executionPayload"`
BlockValue string `json:"blockValue"`
}
type ExecutionPayloadCapellaJSON struct {
ParentHash *common.Hash `json:"parentHash"`
FeeRecipient *common.Address `json:"feeRecipient"`
StateRoot *common.Hash `json:"stateRoot"`
ReceiptsRoot *common.Hash `json:"receiptsRoot"`
LogsBloom *hexutil.Bytes `json:"logsBloom"`
PrevRandao *common.Hash `json:"prevRandao"`
BlockNumber *hexutil.Uint64 `json:"blockNumber"`
GasLimit *hexutil.Uint64 `json:"gasLimit"`
GasUsed *hexutil.Uint64 `json:"gasUsed"`
Timestamp *hexutil.Uint64 `json:"timestamp"`
ExtraData hexutil.Bytes `json:"extraData"`
BaseFeePerGas string `json:"baseFeePerGas"`
BlockHash *common.Hash `json:"blockHash"`
Transactions []hexutil.Bytes `json:"transactions"`
Withdrawals []*Withdrawal `json:"withdrawals"`
}
type GetPayloadV3ResponseJson struct {
ExecutionPayload *ExecutionPayloadDenebJSON `json:"executionPayload"`
BlockValue string `json:"blockValue"`
BlobsBundle *BlobBundleJSON `json:"blobsBundle"`
ShouldOverrideBuilder bool `json:"shouldOverrideBuilder"`
}
type ExecutionPayloadDenebJSON struct {
ParentHash *common.Hash `json:"parentHash"`
FeeRecipient *common.Address `json:"feeRecipient"`
StateRoot *common.Hash `json:"stateRoot"`
ReceiptsRoot *common.Hash `json:"receiptsRoot"`
LogsBloom *hexutil.Bytes `json:"logsBloom"`
PrevRandao *common.Hash `json:"prevRandao"`
BlockNumber *hexutil.Uint64 `json:"blockNumber"`
GasLimit *hexutil.Uint64 `json:"gasLimit"`
GasUsed *hexutil.Uint64 `json:"gasUsed"`
Timestamp *hexutil.Uint64 `json:"timestamp"`
ExtraData hexutil.Bytes `json:"extraData"`
BaseFeePerGas string `json:"baseFeePerGas"`
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed"`
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas"`
BlockHash *common.Hash `json:"blockHash"`
Transactions []hexutil.Bytes `json:"transactions"`
Withdrawals []*Withdrawal `json:"withdrawals"`
}
// MarshalJSON --
func (e *ExecutionPayload) MarshalJSON() ([]byte, error) {
transactions := make([]hexutil.Bytes, len(e.Transactions))
for i, tx := range e.Transactions {
transactions[i] = tx
}
baseFee := bytesutil.LittleEndianBytesToBigInt(e.BaseFeePerGas)
baseFeeHex := hexutil.EncodeBig(baseFee)
pHash := common.BytesToHash(e.ParentHash)
sRoot := common.BytesToHash(e.StateRoot)
recRoot := common.BytesToHash(e.ReceiptsRoot)
prevRan := common.BytesToHash(e.PrevRandao)
bHash := common.BytesToHash(e.BlockHash)
blockNum := hexutil.Uint64(e.BlockNumber)
gasLimit := hexutil.Uint64(e.GasLimit)
gasUsed := hexutil.Uint64(e.GasUsed)
timeStamp := hexutil.Uint64(e.Timestamp)
recipient := common.BytesToAddress(e.FeeRecipient)
logsBloom := hexutil.Bytes(e.LogsBloom)
return json.Marshal(executionPayloadJSON{
ParentHash: &pHash,
FeeRecipient: &recipient,
StateRoot: &sRoot,
ReceiptsRoot: &recRoot,
LogsBloom: &logsBloom,
PrevRandao: &prevRan,
BlockNumber: &blockNum,
GasLimit: &gasLimit,
GasUsed: &gasUsed,
Timestamp: &timeStamp,
ExtraData: e.ExtraData,
BaseFeePerGas: baseFeeHex,
BlockHash: &bHash,
Transactions: transactions,
})
}
// MarshalJSON --
func (e *ExecutionPayloadCapella) MarshalJSON() ([]byte, error) {
transactions := make([]hexutil.Bytes, len(e.Transactions))
for i, tx := range e.Transactions {
transactions[i] = tx
}
baseFee := new(big.Int).SetBytes(bytesutil.ReverseByteOrder(e.BaseFeePerGas))
baseFeeHex := hexutil.EncodeBig(baseFee)
pHash := common.BytesToHash(e.ParentHash)
sRoot := common.BytesToHash(e.StateRoot)
recRoot := common.BytesToHash(e.ReceiptsRoot)
prevRan := common.BytesToHash(e.PrevRandao)
bHash := common.BytesToHash(e.BlockHash)
blockNum := hexutil.Uint64(e.BlockNumber)
gasLimit := hexutil.Uint64(e.GasLimit)
gasUsed := hexutil.Uint64(e.GasUsed)
timeStamp := hexutil.Uint64(e.Timestamp)
recipient := common.BytesToAddress(e.FeeRecipient)
logsBloom := hexutil.Bytes(e.LogsBloom)
withdrawals := e.Withdrawals
if withdrawals == nil {
withdrawals = make([]*Withdrawal, 0)
}
return json.Marshal(ExecutionPayloadCapellaJSON{
ParentHash: &pHash,
FeeRecipient: &recipient,
StateRoot: &sRoot,
ReceiptsRoot: &recRoot,
LogsBloom: &logsBloom,
PrevRandao: &prevRan,
BlockNumber: &blockNum,
GasLimit: &gasLimit,
GasUsed: &gasUsed,
Timestamp: &timeStamp,
ExtraData: e.ExtraData,
BaseFeePerGas: baseFeeHex,
BlockHash: &bHash,
Transactions: transactions,
Withdrawals: withdrawals,
})
}
// UnmarshalJSON --
func (e *ExecutionPayload) UnmarshalJSON(enc []byte) error {
dec := executionPayloadJSON{}
if err := json.Unmarshal(enc, &dec); err != nil {
return err
}
if dec.ParentHash == nil {
return errors.New("missing required field 'parentHash' for ExecutionPayload")
}
if dec.FeeRecipient == nil {
return errors.New("missing required field 'feeRecipient' for ExecutionPayload")
}
if dec.StateRoot == nil {
return errors.New("missing required field 'stateRoot' for ExecutionPayload")
}
if dec.ReceiptsRoot == nil {
return errors.New("missing required field 'receiptsRoot' for ExecutableDataV1")
}
if dec.LogsBloom == nil {
return errors.New("missing required field 'logsBloom' for ExecutionPayload")
}
if dec.PrevRandao == nil {
return errors.New("missing required field 'prevRandao' for ExecutionPayload")
}
if dec.ExtraData == nil {
return errors.New("missing required field 'extraData' for ExecutionPayload")
}
if dec.BlockHash == nil {
return errors.New("missing required field 'blockHash' for ExecutionPayload")
}
if dec.Transactions == nil {
return errors.New("missing required field 'transactions' for ExecutionPayload")
}
if dec.BlockNumber == nil {
return errors.New("missing required field 'blockNumber' for ExecutionPayload")
}
if dec.Timestamp == nil {
return errors.New("missing required field 'timestamp' for ExecutionPayload")
}
if dec.GasUsed == nil {
return errors.New("missing required field 'gasUsed' for ExecutionPayload")
}
if dec.GasLimit == nil {
return errors.New("missing required field 'gasLimit' for ExecutionPayload")
}
*e = ExecutionPayload{}
e.ParentHash = dec.ParentHash.Bytes()
e.FeeRecipient = dec.FeeRecipient.Bytes()
e.StateRoot = dec.StateRoot.Bytes()
e.ReceiptsRoot = dec.ReceiptsRoot.Bytes()
e.LogsBloom = *dec.LogsBloom
e.PrevRandao = dec.PrevRandao.Bytes()
e.BlockNumber = uint64(*dec.BlockNumber)
e.GasLimit = uint64(*dec.GasLimit)
e.GasUsed = uint64(*dec.GasUsed)
e.Timestamp = uint64(*dec.Timestamp)
e.ExtraData = dec.ExtraData
baseFee, err := hexutil.DecodeBig(dec.BaseFeePerGas)
if err != nil {
return err
}
e.BaseFeePerGas = bytesutil.PadTo(bytesutil.ReverseByteOrder(baseFee.Bytes()), fieldparams.RootLength)
e.BlockHash = dec.BlockHash.Bytes()
transactions := make([][]byte, len(dec.Transactions))
for i, tx := range dec.Transactions {
transactions[i] = tx
}
e.Transactions = transactions
return nil
}
// UnmarshalJSON --
func (e *ExecutionPayloadCapellaWithValue) UnmarshalJSON(enc []byte) error {
dec := GetPayloadV2ResponseJson{}
if err := json.Unmarshal(enc, &dec); err != nil {
return err
}
if dec.ExecutionPayload == nil {
return errors.New("missing required field 'executionPayload' for ExecutionPayloadWithValue")
}
if dec.ExecutionPayload.ParentHash == nil {
return errors.New("missing required field 'parentHash' for ExecutionPayload")
}
if dec.ExecutionPayload.FeeRecipient == nil {
return errors.New("missing required field 'feeRecipient' for ExecutionPayload")
}
if dec.ExecutionPayload.StateRoot == nil {
return errors.New("missing required field 'stateRoot' for ExecutionPayload")
}
if dec.ExecutionPayload.ReceiptsRoot == nil {
return errors.New("missing required field 'receiptsRoot' for ExecutableDataV1")
}
if dec.ExecutionPayload.LogsBloom == nil {
return errors.New("missing required field 'logsBloom' for ExecutionPayload")
}
if dec.ExecutionPayload.PrevRandao == nil {
return errors.New("missing required field 'prevRandao' for ExecutionPayload")
}
if dec.ExecutionPayload.ExtraData == nil {
return errors.New("missing required field 'extraData' for ExecutionPayload")
}
if dec.ExecutionPayload.BlockHash == nil {
return errors.New("missing required field 'blockHash' for ExecutionPayload")
}
if dec.ExecutionPayload.Transactions == nil {
return errors.New("missing required field 'transactions' for ExecutionPayload")
}
if dec.ExecutionPayload.BlockNumber == nil {
return errors.New("missing required field 'blockNumber' for ExecutionPayload")
}
if dec.ExecutionPayload.Timestamp == nil {
return errors.New("missing required field 'timestamp' for ExecutionPayload")
}
if dec.ExecutionPayload.GasUsed == nil {
return errors.New("missing required field 'gasUsed' for ExecutionPayload")
}
if dec.ExecutionPayload.GasLimit == nil {
return errors.New("missing required field 'gasLimit' for ExecutionPayload")
}
*e = ExecutionPayloadCapellaWithValue{Payload: &ExecutionPayloadCapella{}}
e.Payload.ParentHash = dec.ExecutionPayload.ParentHash.Bytes()
e.Payload.FeeRecipient = dec.ExecutionPayload.FeeRecipient.Bytes()
e.Payload.StateRoot = dec.ExecutionPayload.StateRoot.Bytes()
e.Payload.ReceiptsRoot = dec.ExecutionPayload.ReceiptsRoot.Bytes()
e.Payload.LogsBloom = *dec.ExecutionPayload.LogsBloom
e.Payload.PrevRandao = dec.ExecutionPayload.PrevRandao.Bytes()
e.Payload.BlockNumber = uint64(*dec.ExecutionPayload.BlockNumber)
e.Payload.GasLimit = uint64(*dec.ExecutionPayload.GasLimit)
e.Payload.GasUsed = uint64(*dec.ExecutionPayload.GasUsed)
e.Payload.Timestamp = uint64(*dec.ExecutionPayload.Timestamp)
e.Payload.ExtraData = dec.ExecutionPayload.ExtraData
baseFee, err := hexutil.DecodeBig(dec.ExecutionPayload.BaseFeePerGas)
if err != nil {
return err
}
e.Payload.BaseFeePerGas = bytesutil.PadTo(bytesutil.ReverseByteOrder(baseFee.Bytes()), fieldparams.RootLength)
e.Payload.BlockHash = dec.ExecutionPayload.BlockHash.Bytes()
transactions := make([][]byte, len(dec.ExecutionPayload.Transactions))
for i, tx := range dec.ExecutionPayload.Transactions {
transactions[i] = tx
}
e.Payload.Transactions = transactions
if dec.ExecutionPayload.Withdrawals == nil {
dec.ExecutionPayload.Withdrawals = make([]*Withdrawal, 0)
}
e.Payload.Withdrawals = dec.ExecutionPayload.Withdrawals
v, err := hexutil.DecodeBig(dec.BlockValue)
if err != nil {
return err
}
e.Value = bytesutil.PadTo(bytesutil.ReverseByteOrder(v.Bytes()), fieldparams.RootLength)
return nil
}
type payloadAttributesJSON struct {
Timestamp hexutil.Uint64 `json:"timestamp"`
PrevRandao hexutil.Bytes `json:"prevRandao"`
SuggestedFeeRecipient hexutil.Bytes `json:"suggestedFeeRecipient"`
}
type payloadAttributesV2JSON struct {
Timestamp hexutil.Uint64 `json:"timestamp"`
PrevRandao hexutil.Bytes `json:"prevRandao"`
SuggestedFeeRecipient hexutil.Bytes `json:"suggestedFeeRecipient"`
Withdrawals []*Withdrawal `json:"withdrawals"`
}
type payloadAttributesV3JSON struct {
Timestamp hexutil.Uint64 `json:"timestamp"`
PrevRandao hexutil.Bytes `json:"prevRandao"`
SuggestedFeeRecipient hexutil.Bytes `json:"suggestedFeeRecipient"`
Withdrawals []*Withdrawal `json:"withdrawals"`
ParentBeaconBlockRoot hexutil.Bytes `json:"parentBeaconBlockRoot"`
}
// MarshalJSON --
func (p *PayloadAttributes) MarshalJSON() ([]byte, error) {
return json.Marshal(payloadAttributesJSON{
Timestamp: hexutil.Uint64(p.Timestamp),
PrevRandao: p.PrevRandao,
SuggestedFeeRecipient: p.SuggestedFeeRecipient,
})
}
// MarshalJSON --
func (p *PayloadAttributesV2) MarshalJSON() ([]byte, error) {
withdrawals := p.Withdrawals
if withdrawals == nil {
withdrawals = make([]*Withdrawal, 0)
}
return json.Marshal(payloadAttributesV2JSON{
Timestamp: hexutil.Uint64(p.Timestamp),
PrevRandao: p.PrevRandao,
SuggestedFeeRecipient: p.SuggestedFeeRecipient,
Withdrawals: withdrawals,
})
}
func (p *PayloadAttributesV3) MarshalJSON() ([]byte, error) {
withdrawals := p.Withdrawals
if withdrawals == nil {
withdrawals = make([]*Withdrawal, 0)
}
return json.Marshal(payloadAttributesV3JSON{
Timestamp: hexutil.Uint64(p.Timestamp),
PrevRandao: p.PrevRandao,
SuggestedFeeRecipient: p.SuggestedFeeRecipient,
Withdrawals: withdrawals,
ParentBeaconBlockRoot: p.ParentBeaconBlockRoot,
})
}
// UnmarshalJSON --
func (p *PayloadAttributes) UnmarshalJSON(enc []byte) error {
dec := payloadAttributesJSON{}
if err := json.Unmarshal(enc, &dec); err != nil {
return err
}
*p = PayloadAttributes{}
p.Timestamp = uint64(dec.Timestamp)
p.PrevRandao = dec.PrevRandao
p.SuggestedFeeRecipient = dec.SuggestedFeeRecipient
return nil
}
func (p *PayloadAttributesV2) UnmarshalJSON(enc []byte) error {
dec := payloadAttributesV2JSON{}
if err := json.Unmarshal(enc, &dec); err != nil {
return err
}
*p = PayloadAttributesV2{}
p.Timestamp = uint64(dec.Timestamp)
p.PrevRandao = dec.PrevRandao
p.SuggestedFeeRecipient = dec.SuggestedFeeRecipient
withdrawals := dec.Withdrawals
if withdrawals == nil {
withdrawals = make([]*Withdrawal, 0)
}
p.Withdrawals = withdrawals
return nil
}
func (p *PayloadAttributesV3) UnmarshalJSON(enc []byte) error {
dec := payloadAttributesV3JSON{}
if err := json.Unmarshal(enc, &dec); err != nil {
return err
}
*p = PayloadAttributesV3{}
p.Timestamp = uint64(dec.Timestamp)
p.PrevRandao = dec.PrevRandao
p.SuggestedFeeRecipient = dec.SuggestedFeeRecipient
withdrawals := dec.Withdrawals
if withdrawals == nil {
withdrawals = make([]*Withdrawal, 0)
}
p.Withdrawals = withdrawals
p.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
return nil
}
type payloadStatusJSON struct {
LatestValidHash *common.Hash `json:"latestValidHash"`
Status string `json:"status"`
ValidationError *string `json:"validationError"`
}
// MarshalJSON --
func (p *PayloadStatus) MarshalJSON() ([]byte, error) {
var latestHash *common.Hash
if p.LatestValidHash != nil {
hash := common.Hash(bytesutil.ToBytes32(p.LatestValidHash))
latestHash = &hash
}
return json.Marshal(payloadStatusJSON{
LatestValidHash: latestHash,
Status: p.Status.String(),
ValidationError: &p.ValidationError,
})
}
// UnmarshalJSON --
func (p *PayloadStatus) UnmarshalJSON(enc []byte) error {
dec := payloadStatusJSON{}
if err := json.Unmarshal(enc, &dec); err != nil {
return err
}
*p = PayloadStatus{}
if dec.LatestValidHash != nil {
p.LatestValidHash = dec.LatestValidHash[:]
}
p.Status = PayloadStatus_Status(PayloadStatus_Status_value[dec.Status])
if dec.ValidationError != nil {
p.ValidationError = *dec.ValidationError
}
return nil
}
type forkchoiceStateJSON struct {
HeadBlockHash hexutil.Bytes `json:"headBlockHash"`
SafeBlockHash hexutil.Bytes `json:"safeBlockHash"`
FinalizedBlockHash hexutil.Bytes `json:"finalizedBlockHash"`
}
// MarshalJSON --
func (f *ForkchoiceState) MarshalJSON() ([]byte, error) {
return json.Marshal(forkchoiceStateJSON{
HeadBlockHash: f.HeadBlockHash,
SafeBlockHash: f.SafeBlockHash,
FinalizedBlockHash: f.FinalizedBlockHash,
})
}
// UnmarshalJSON --
func (f *ForkchoiceState) UnmarshalJSON(enc []byte) error {
dec := forkchoiceStateJSON{}
if err := json.Unmarshal(enc, &dec); err != nil {
return err
}
*f = ForkchoiceState{}
f.HeadBlockHash = dec.HeadBlockHash
f.SafeBlockHash = dec.SafeBlockHash
f.FinalizedBlockHash = dec.FinalizedBlockHash
return nil
}
type BlobBundleJSON struct {
Commitments []hexutil.Bytes `json:"commitments"`
Proofs []hexutil.Bytes `json:"proofs"`
Blobs []hexutil.Bytes `json:"blobs"`
}
func (b BlobBundleJSON) ToProto() *BlobsBundle {
return &BlobsBundle{
KzgCommitments: bytesutil.SafeCopy2dHexUtilBytes(b.Commitments),
Proofs: bytesutil.SafeCopy2dHexUtilBytes(b.Proofs),
Blobs: bytesutil.SafeCopy2dHexUtilBytes(b.Blobs),
}
}
// MarshalJSON --
func (e *ExecutionPayloadDeneb) MarshalJSON() ([]byte, error) {
transactions := make([]hexutil.Bytes, len(e.Transactions))
for i, tx := range e.Transactions {
transactions[i] = tx
}
baseFee := new(big.Int).SetBytes(bytesutil.ReverseByteOrder(e.BaseFeePerGas))
baseFeeHex := hexutil.EncodeBig(baseFee)
pHash := common.BytesToHash(e.ParentHash)
sRoot := common.BytesToHash(e.StateRoot)
recRoot := common.BytesToHash(e.ReceiptsRoot)
prevRan := common.BytesToHash(e.PrevRandao)
bHash := common.BytesToHash(e.BlockHash)
blockNum := hexutil.Uint64(e.BlockNumber)
gasLimit := hexutil.Uint64(e.GasLimit)
gasUsed := hexutil.Uint64(e.GasUsed)
timeStamp := hexutil.Uint64(e.Timestamp)
recipient := common.BytesToAddress(e.FeeRecipient)
logsBloom := hexutil.Bytes(e.LogsBloom)
withdrawals := e.Withdrawals
if withdrawals == nil {
withdrawals = make([]*Withdrawal, 0)
}
blobGasUsed := hexutil.Uint64(e.BlobGasUsed)
excessBlobGas := hexutil.Uint64(e.ExcessBlobGas)
return json.Marshal(ExecutionPayloadDenebJSON{
ParentHash: &pHash,
FeeRecipient: &recipient,
StateRoot: &sRoot,
ReceiptsRoot: &recRoot,
LogsBloom: &logsBloom,
PrevRandao: &prevRan,
BlockNumber: &blockNum,
GasLimit: &gasLimit,
GasUsed: &gasUsed,
Timestamp: &timeStamp,
ExtraData: e.ExtraData,
BaseFeePerGas: baseFeeHex,
BlockHash: &bHash,
Transactions: transactions,
Withdrawals: withdrawals,
BlobGasUsed: &blobGasUsed,
ExcessBlobGas: &excessBlobGas,
})
}
func (e *ExecutionPayloadDenebWithValueAndBlobsBundle) UnmarshalJSON(enc []byte) error {
dec := GetPayloadV3ResponseJson{}
if err := json.Unmarshal(enc, &dec); err != nil {
return err
}
if dec.ExecutionPayload.ParentHash == nil {
return errors.New("missing required field 'parentHash' for ExecutionPayload")
}
if dec.ExecutionPayload.FeeRecipient == nil {
return errors.New("missing required field 'feeRecipient' for ExecutionPayload")
}
if dec.ExecutionPayload.StateRoot == nil {
return errors.New("missing required field 'stateRoot' for ExecutionPayload")
}
if dec.ExecutionPayload.ReceiptsRoot == nil {
return errors.New("missing required field 'receiptsRoot' for ExecutableDataV1")
}
if dec.ExecutionPayload.LogsBloom == nil {
return errors.New("missing required field 'logsBloom' for ExecutionPayload")
}
if dec.ExecutionPayload.PrevRandao == nil {
return errors.New("missing required field 'prevRandao' for ExecutionPayload")
}
if dec.ExecutionPayload.ExtraData == nil {
return errors.New("missing required field 'extraData' for ExecutionPayload")
}
if dec.ExecutionPayload.BlockHash == nil {
return errors.New("missing required field 'blockHash' for ExecutionPayload")
}
if dec.ExecutionPayload.Transactions == nil {
return errors.New("missing required field 'transactions' for ExecutionPayload")
}
if dec.ExecutionPayload.BlockNumber == nil {
return errors.New("missing required field 'blockNumber' for ExecutionPayload")
}
if dec.ExecutionPayload.Timestamp == nil {
return errors.New("missing required field 'timestamp' for ExecutionPayload")
}
if dec.ExecutionPayload.GasUsed == nil {
return errors.New("missing required field 'gasUsed' for ExecutionPayload")
}
if dec.ExecutionPayload.GasLimit == nil {
return errors.New("missing required field 'gasLimit' for ExecutionPayload")
}
if dec.ExecutionPayload.BlobGasUsed == nil {
return errors.New("missing required field 'blobGasUsed' for ExecutionPayload")
}
if dec.ExecutionPayload.ExcessBlobGas == nil {
return errors.New("missing required field 'excessBlobGas' for ExecutionPayload")
}
*e = ExecutionPayloadDenebWithValueAndBlobsBundle{Payload: &ExecutionPayloadDeneb{}}
e.Payload.ParentHash = dec.ExecutionPayload.ParentHash.Bytes()
e.Payload.FeeRecipient = dec.ExecutionPayload.FeeRecipient.Bytes()
e.Payload.StateRoot = dec.ExecutionPayload.StateRoot.Bytes()
e.Payload.ReceiptsRoot = dec.ExecutionPayload.ReceiptsRoot.Bytes()
e.Payload.LogsBloom = *dec.ExecutionPayload.LogsBloom
e.Payload.PrevRandao = dec.ExecutionPayload.PrevRandao.Bytes()
e.Payload.BlockNumber = uint64(*dec.ExecutionPayload.BlockNumber)
e.Payload.GasLimit = uint64(*dec.ExecutionPayload.GasLimit)
e.Payload.GasUsed = uint64(*dec.ExecutionPayload.GasUsed)
e.Payload.Timestamp = uint64(*dec.ExecutionPayload.Timestamp)
e.Payload.ExtraData = dec.ExecutionPayload.ExtraData
baseFee, err := hexutil.DecodeBig(dec.ExecutionPayload.BaseFeePerGas)
if err != nil {
return err
}
e.Payload.BaseFeePerGas = bytesutil.PadTo(bytesutil.ReverseByteOrder(baseFee.Bytes()), fieldparams.RootLength)
e.Payload.ExcessBlobGas = uint64(*dec.ExecutionPayload.ExcessBlobGas)
e.Payload.BlobGasUsed = uint64(*dec.ExecutionPayload.BlobGasUsed)
e.Payload.BlockHash = dec.ExecutionPayload.BlockHash.Bytes()
transactions := make([][]byte, len(dec.ExecutionPayload.Transactions))
for i, tx := range dec.ExecutionPayload.Transactions {
transactions[i] = tx
}
e.Payload.Transactions = transactions
if dec.ExecutionPayload.Withdrawals == nil {
dec.ExecutionPayload.Withdrawals = make([]*Withdrawal, 0)
}
e.Payload.Withdrawals = dec.ExecutionPayload.Withdrawals
v, err := hexutil.DecodeBig(dec.BlockValue)
if err != nil {
return err
}
e.Value = bytesutil.PadTo(bytesutil.ReverseByteOrder(v.Bytes()), fieldparams.RootLength)
if dec.BlobsBundle == nil {
return nil
}
e.BlobsBundle = &BlobsBundle{}
commitments := make([][]byte, len(dec.BlobsBundle.Commitments))
for i, kzg := range dec.BlobsBundle.Commitments {
k := kzg
commitments[i] = bytesutil.PadTo(k[:], fieldparams.BLSPubkeyLength)
}
e.BlobsBundle.KzgCommitments = commitments
proofs := make([][]byte, len(dec.BlobsBundle.Proofs))
for i, proof := range dec.BlobsBundle.Proofs {
p := proof
proofs[i] = bytesutil.PadTo(p[:], fieldparams.BLSPubkeyLength)
}
e.BlobsBundle.Proofs = proofs
blobs := make([][]byte, len(dec.BlobsBundle.Blobs))
for i, blob := range dec.BlobsBundle.Blobs {
b := make([]byte, fieldparams.BlobLength)
copy(b, blob)
blobs[i] = b
}
e.BlobsBundle.Blobs = blobs
e.ShouldOverrideBuilder = dec.ShouldOverrideBuilder
return nil
}
type executionPayloadBodyV1JSON struct {
Transactions []hexutil.Bytes `json:"transactions"`
Withdrawals []*Withdrawal `json:"withdrawals"`
}
func (b *ExecutionPayloadBodyV1) MarshalJSON() ([]byte, error) {
transactions := make([]hexutil.Bytes, len(b.Transactions))
for i, tx := range b.Transactions {
transactions[i] = tx
}
if len(b.Withdrawals) == 0 {
b.Withdrawals = make([]*Withdrawal, 0)
}
return json.Marshal(executionPayloadBodyV1JSON{
Transactions: transactions,
Withdrawals: b.Withdrawals,
})
}
func (b *ExecutionPayloadBodyV1) UnmarshalJSON(enc []byte) error {
var decoded *executionPayloadBodyV1JSON
err := json.Unmarshal(enc, &decoded)
if err != nil {
return err
}
if len(decoded.Transactions) == 0 {
b.Transactions = make([][]byte, 0)
}
if len(decoded.Withdrawals) == 0 {
b.Withdrawals = make([]*Withdrawal, 0)
}
transactions := make([][]byte, len(decoded.Transactions))
for i, tx := range decoded.Transactions {
transactions[i] = tx
}
b.Transactions = transactions
b.Withdrawals = decoded.Withdrawals
return nil
}