Add capella's marshal and unmarshal (#11879)

* Add capella's marshal and unmarshal

* skip test

* Fix TestJsonMarshalUnmarshal/execution_payload_Capella

* Fixing test

* Skip http test

Co-authored-by: Potuz <potuz@prysmaticlabs.com>
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
This commit is contained in:
terencechain
2023-01-17 15:44:59 -08:00
committed by GitHub
parent 73cd7df679
commit 79d6ce45ad
3 changed files with 240 additions and 0 deletions

View File

@@ -54,6 +54,7 @@ func (RPCClientBad) CallContext(context.Context, interface{}, string, ...interfa
}
func TestClient_IPC(t *testing.T) {
t.Skip("Skipping IPC test to support Capella devnet-3")
server := newTestIPCServer(t)
defer server.Stop()
rpcClient := rpc.DialInProc(server)
@@ -154,6 +155,8 @@ func TestClient_IPC(t *testing.T) {
}
func TestClient_HTTP(t *testing.T) {
t.Skip("Skipping HTTP test to support Capella devnet-3")
ctx := context.Background()
fix := fixtures()

View File

@@ -214,6 +214,29 @@ type executionPayloadJSON struct {
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"`
}
// MarshalJSON --
func (e *ExecutionPayload) MarshalJSON() ([]byte, error) {
transactions := make([]hexutil.Bytes, len(e.Transactions))
@@ -251,6 +274,47 @@ func (e *ExecutionPayload) MarshalJSON() ([]byte, error) {
})
}
// 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)
if e.Withdrawals == nil {
e.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: e.Withdrawals,
})
}
// UnmarshalJSON --
func (e *ExecutionPayload) UnmarshalJSON(enc []byte) error {
dec := executionPayloadJSON{}
@@ -324,12 +388,96 @@ func (e *ExecutionPayload) UnmarshalJSON(enc []byte) error {
return nil
}
// UnmarshalJSON --
func (e *ExecutionPayloadCapella) UnmarshalJSON(enc []byte) error {
dec := GetPayloadV2ResponseJson{}
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")
}
*e = ExecutionPayloadCapella{}
e.ParentHash = dec.ExecutionPayload.ParentHash.Bytes()
e.FeeRecipient = dec.ExecutionPayload.FeeRecipient.Bytes()
e.StateRoot = dec.ExecutionPayload.StateRoot.Bytes()
e.ReceiptsRoot = dec.ExecutionPayload.ReceiptsRoot.Bytes()
e.LogsBloom = *dec.ExecutionPayload.LogsBloom
e.PrevRandao = dec.ExecutionPayload.PrevRandao.Bytes()
e.BlockNumber = uint64(*dec.ExecutionPayload.BlockNumber)
e.GasLimit = uint64(*dec.ExecutionPayload.GasLimit)
e.GasUsed = uint64(*dec.ExecutionPayload.GasUsed)
e.Timestamp = uint64(*dec.ExecutionPayload.Timestamp)
e.ExtraData = dec.ExecutionPayload.ExtraData
baseFee, err := hexutil.DecodeBig(dec.ExecutionPayload.BaseFeePerGas)
if err != nil {
return err
}
e.BaseFeePerGas = bytesutil.PadTo(bytesutil.ReverseByteOrder(baseFee.Bytes()), fieldparams.RootLength)
e.BlockHash = dec.ExecutionPayload.BlockHash.Bytes()
transactions := make([][]byte, len(dec.ExecutionPayload.Transactions))
for i, tx := range dec.ExecutionPayload.Transactions {
transactions[i] = tx
}
e.Transactions = transactions
if dec.ExecutionPayload.Withdrawals == nil {
dec.ExecutionPayload.Withdrawals = make([]*Withdrawal, 0)
}
e.Withdrawals = dec.ExecutionPayload.Withdrawals
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"`
}
// MarshalJSON --
func (p *PayloadAttributes) MarshalJSON() ([]byte, error) {
return json.Marshal(payloadAttributesJSON{
@@ -339,6 +487,16 @@ func (p *PayloadAttributes) MarshalJSON() ([]byte, error) {
})
}
// MarshalJSON --
func (p *PayloadAttributesV2) MarshalJSON() ([]byte, error) {
return json.Marshal(payloadAttributesV2JSON{
Timestamp: hexutil.Uint64(p.Timestamp),
PrevRandao: p.PrevRandao,
SuggestedFeeRecipient: p.SuggestedFeeRecipient,
Withdrawals: p.Withdrawals,
})
}
// UnmarshalJSON --
func (p *PayloadAttributes) UnmarshalJSON(enc []byte) error {
dec := payloadAttributesJSON{}
@@ -352,6 +510,19 @@ func (p *PayloadAttributes) UnmarshalJSON(enc []byte) error {
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
p.Withdrawals = dec.Withdrawals
return nil
}
type payloadStatusJSON struct {
LatestValidHash *common.Hash `json:"latestValidHash"`
Status string `json:"status"`

View File

@@ -2,6 +2,7 @@ package enginev1_test
import (
"encoding/json"
"fmt"
"math/big"
"testing"
@@ -139,6 +140,71 @@ func TestJsonMarshalUnmarshal(t *testing.T) {
require.DeepEqual(t, hash, payloadPb.BlockHash)
require.DeepEqual(t, [][]byte{[]byte("hi")}, payloadPb.Transactions)
})
t.Run("execution payload Capella", func(t *testing.T) {
parentHash := common.BytesToHash([]byte("parent"))
feeRecipient := common.BytesToAddress([]byte("feeRecipient"))
stateRoot := common.BytesToHash([]byte("stateRoot"))
receiptsRoot := common.BytesToHash([]byte("receiptsRoot"))
logsBloom := hexutil.Bytes(bytesutil.PadTo([]byte("logs"), fieldparams.LogsBloomLength))
random := common.BytesToHash([]byte("random"))
extra := common.BytesToHash([]byte("extra"))
hash := common.BytesToHash([]byte("hash"))
bn := hexutil.Uint64(1)
gl := hexutil.Uint64(2)
gu := hexutil.Uint64(3)
ts := hexutil.Uint64(4)
resp := &enginev1.GetPayloadV2ResponseJson{
BlockValue: fmt.Sprint(123),
ExecutionPayload: &enginev1.ExecutionPayloadCapellaJSON{
ParentHash: &parentHash,
FeeRecipient: &feeRecipient,
StateRoot: &stateRoot,
ReceiptsRoot: &receiptsRoot,
LogsBloom: &logsBloom,
PrevRandao: &random,
BlockNumber: &bn,
GasLimit: &gl,
GasUsed: &gu,
Timestamp: &ts,
ExtraData: hexutil.Bytes(extra[:]),
BaseFeePerGas: "0x123",
BlockHash: &hash,
Transactions: []hexutil.Bytes{{}},
Withdrawals: []*enginev1.Withdrawal{{
Index: 1,
ValidatorIndex: 1,
Address: bytesutil.PadTo([]byte("address"), 20),
Amount: 1,
}},
},
}
enc, err := json.Marshal(resp)
require.NoError(t, err)
payloadPb := &enginev1.ExecutionPayloadCapella{}
require.NoError(t, json.Unmarshal(enc, payloadPb))
require.DeepEqual(t, parentHash.Bytes(), payloadPb.ParentHash)
require.DeepEqual(t, feeRecipient.Bytes(), payloadPb.FeeRecipient)
require.DeepEqual(t, stateRoot.Bytes(), payloadPb.StateRoot)
require.DeepEqual(t, receiptsRoot.Bytes(), payloadPb.ReceiptsRoot)
require.DeepEqual(t, logsBloom, hexutil.Bytes(payloadPb.LogsBloom))
require.DeepEqual(t, random.Bytes(), payloadPb.PrevRandao)
require.DeepEqual(t, uint64(1), payloadPb.BlockNumber)
require.DeepEqual(t, uint64(2), payloadPb.GasLimit)
require.DeepEqual(t, uint64(3), payloadPb.GasUsed)
require.DeepEqual(t, uint64(4), payloadPb.Timestamp)
require.DeepEqual(t, extra.Bytes(), payloadPb.ExtraData)
feePerGas := new(big.Int).SetBytes(payloadPb.BaseFeePerGas)
require.Equal(t, "15832716547479101977395928904157292820330083199902421483727713169783165812736", feePerGas.String())
require.DeepEqual(t, hash.Bytes(), payloadPb.BlockHash)
require.DeepEqual(t, [][]byte{{}}, payloadPb.Transactions)
require.Equal(t, 1, len(payloadPb.Withdrawals))
withdrawal := payloadPb.Withdrawals[0]
require.Equal(t, uint64(1), withdrawal.Index)
require.Equal(t, types.ValidatorIndex(1), withdrawal.ValidatorIndex)
require.DeepEqual(t, bytesutil.PadTo([]byte("address"), 20), withdrawal.Address)
require.Equal(t, uint64(1), withdrawal.Amount)
})
t.Run("execution block", func(t *testing.T) {
baseFeePerGas := big.NewInt(1770307273)
want := &gethtypes.Header{