github.com/theQRL/go-zond@v0.2.1/beacon/engine/types.go (about)

     1  // Copyright 2022 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package engine
    18  
    19  import (
    20  	"fmt"
    21  	"math/big"
    22  
    23  	"github.com/theQRL/go-zond/common"
    24  	"github.com/theQRL/go-zond/common/hexutil"
    25  	"github.com/theQRL/go-zond/core/types"
    26  	"github.com/theQRL/go-zond/trie"
    27  )
    28  
    29  //go:generate go run github.com/fjl/gencodec -type PayloadAttributes -field-override payloadAttributesMarshaling -out gen_blockparams.go
    30  
    31  // PayloadAttributes describes the environment context in which a block should
    32  // be built.
    33  type PayloadAttributes struct {
    34  	Timestamp             uint64              `json:"timestamp"             gencodec:"required"`
    35  	Random                common.Hash         `json:"prevRandao"            gencodec:"required"`
    36  	SuggestedFeeRecipient common.Address      `json:"suggestedFeeRecipient" gencodec:"required"`
    37  	Withdrawals           []*types.Withdrawal `json:"withdrawals"`
    38  }
    39  
    40  // JSON type overrides for PayloadAttributes.
    41  type payloadAttributesMarshaling struct {
    42  	Timestamp hexutil.Uint64
    43  }
    44  
    45  //go:generate go run github.com/fjl/gencodec -type ExecutableData -field-override executableDataMarshaling -out gen_ed.go
    46  
    47  // ExecutableData is the data necessary to execute an EL payload.
    48  type ExecutableData struct {
    49  	ParentHash    common.Hash         `json:"parentHash"    gencodec:"required"`
    50  	FeeRecipient  common.Address      `json:"feeRecipient"  gencodec:"required"`
    51  	StateRoot     common.Hash         `json:"stateRoot"     gencodec:"required"`
    52  	ReceiptsRoot  common.Hash         `json:"receiptsRoot"  gencodec:"required"`
    53  	LogsBloom     []byte              `json:"logsBloom"     gencodec:"required"`
    54  	Random        common.Hash         `json:"prevRandao"    gencodec:"required"`
    55  	Number        uint64              `json:"blockNumber"   gencodec:"required"`
    56  	GasLimit      uint64              `json:"gasLimit"      gencodec:"required"`
    57  	GasUsed       uint64              `json:"gasUsed"       gencodec:"required"`
    58  	Timestamp     uint64              `json:"timestamp"     gencodec:"required"`
    59  	ExtraData     []byte              `json:"extraData"     gencodec:"required"`
    60  	BaseFeePerGas *big.Int            `json:"baseFeePerGas" gencodec:"required"`
    61  	BlockHash     common.Hash         `json:"blockHash"     gencodec:"required"`
    62  	Transactions  [][]byte            `json:"transactions"  gencodec:"required"`
    63  	Withdrawals   []*types.Withdrawal `json:"withdrawals"`
    64  }
    65  
    66  // JSON type overrides for executableData.
    67  type executableDataMarshaling struct {
    68  	Number        hexutil.Uint64
    69  	GasLimit      hexutil.Uint64
    70  	GasUsed       hexutil.Uint64
    71  	Timestamp     hexutil.Uint64
    72  	BaseFeePerGas *hexutil.Big
    73  	ExtraData     hexutil.Bytes
    74  	LogsBloom     hexutil.Bytes
    75  	Transactions  []hexutil.Bytes
    76  }
    77  
    78  //go:generate go run github.com/fjl/gencodec -type ExecutionPayloadEnvelope -field-override executionPayloadEnvelopeMarshaling -out gen_epe.go
    79  
    80  type ExecutionPayloadEnvelope struct {
    81  	ExecutionPayload *ExecutableData `json:"executionPayload"  gencodec:"required"`
    82  	BlockValue       *big.Int        `json:"blockValue"  gencodec:"required"`
    83  	Override         bool            `json:"shouldOverrideBuilder"`
    84  }
    85  
    86  // JSON type overrides for ExecutionPayloadEnvelope.
    87  type executionPayloadEnvelopeMarshaling struct {
    88  	BlockValue *hexutil.Big
    89  }
    90  
    91  type PayloadStatusV1 struct {
    92  	Status          string       `json:"status"`
    93  	LatestValidHash *common.Hash `json:"latestValidHash"`
    94  	ValidationError *string      `json:"validationError"`
    95  }
    96  
    97  // PayloadID is an identifier of the payload build process
    98  type PayloadID [8]byte
    99  
   100  func (b PayloadID) String() string {
   101  	return hexutil.Encode(b[:])
   102  }
   103  
   104  func (b PayloadID) MarshalText() ([]byte, error) {
   105  	return hexutil.Bytes(b[:]).MarshalText()
   106  }
   107  
   108  func (b *PayloadID) UnmarshalText(input []byte) error {
   109  	err := hexutil.UnmarshalFixedText("PayloadID", input, b[:])
   110  	if err != nil {
   111  		return fmt.Errorf("invalid payload id %q: %w", input, err)
   112  	}
   113  	return nil
   114  }
   115  
   116  type ForkChoiceResponse struct {
   117  	PayloadStatus PayloadStatusV1 `json:"payloadStatus"`
   118  	PayloadID     *PayloadID      `json:"payloadId"`
   119  }
   120  
   121  type ForkchoiceStateV1 struct {
   122  	HeadBlockHash      common.Hash `json:"headBlockHash"`
   123  	SafeBlockHash      common.Hash `json:"safeBlockHash"`
   124  	FinalizedBlockHash common.Hash `json:"finalizedBlockHash"`
   125  }
   126  
   127  func encodeTransactions(txs []*types.Transaction) [][]byte {
   128  	var enc = make([][]byte, len(txs))
   129  	for i, tx := range txs {
   130  		enc[i], _ = tx.MarshalBinary()
   131  	}
   132  	return enc
   133  }
   134  
   135  func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
   136  	var txs = make([]*types.Transaction, len(enc))
   137  	for i, encTx := range enc {
   138  		var tx types.Transaction
   139  		if err := tx.UnmarshalBinary(encTx); err != nil {
   140  			return nil, fmt.Errorf("invalid transaction %d: %v", i, err)
   141  		}
   142  		txs[i] = &tx
   143  	}
   144  	return txs, nil
   145  }
   146  
   147  // ExecutableDataToBlock constructs a block from executable data.
   148  // It verifies that the following fields:
   149  //
   150  //	len(extraData) <= 32
   151  //
   152  // and that the blockhash of the constructed block matches the parameters. Nil
   153  // Withdrawals value will propagate through the returned block. Empty
   154  // Withdrawals value must be passed via non-nil, length 0 value in params.
   155  func ExecutableDataToBlock(params ExecutableData) (*types.Block, error) {
   156  	txs, err := decodeTransactions(params.Transactions)
   157  	if err != nil {
   158  		return nil, err
   159  	}
   160  	if len(params.ExtraData) > 32 {
   161  		return nil, fmt.Errorf("invalid extradata length: %v", len(params.ExtraData))
   162  	}
   163  	if len(params.LogsBloom) != 256 {
   164  		return nil, fmt.Errorf("invalid logsBloom length: %v", len(params.LogsBloom))
   165  	}
   166  	// Check that baseFeePerGas is not negative or too big
   167  	if params.BaseFeePerGas != nil && (params.BaseFeePerGas.Sign() == -1 || params.BaseFeePerGas.BitLen() > 256) {
   168  		return nil, fmt.Errorf("invalid baseFeePerGas: %v", params.BaseFeePerGas)
   169  	}
   170  	// Only set withdrawalsRoot if it is non-nil. This allows CLs to use
   171  	// ExecutableData before withdrawals are enabled by marshaling
   172  	// Withdrawals as the json null value.
   173  	var withdrawalsRoot *common.Hash
   174  	if params.Withdrawals != nil {
   175  		h := types.DeriveSha(types.Withdrawals(params.Withdrawals), trie.NewStackTrie(nil))
   176  		withdrawalsRoot = &h
   177  	}
   178  	header := &types.Header{
   179  		ParentHash:      params.ParentHash,
   180  		Coinbase:        params.FeeRecipient,
   181  		Root:            params.StateRoot,
   182  		TxHash:          types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)),
   183  		ReceiptHash:     params.ReceiptsRoot,
   184  		Bloom:           types.BytesToBloom(params.LogsBloom),
   185  		Number:          new(big.Int).SetUint64(params.Number),
   186  		GasLimit:        params.GasLimit,
   187  		GasUsed:         params.GasUsed,
   188  		Time:            params.Timestamp,
   189  		BaseFee:         params.BaseFeePerGas,
   190  		Extra:           params.ExtraData,
   191  		Random:          params.Random,
   192  		WithdrawalsHash: withdrawalsRoot,
   193  	}
   194  	block := types.NewBlockWithHeader(header).WithBody(types.Body{Transactions: txs, Withdrawals: params.Withdrawals})
   195  	if block.Hash() != params.BlockHash {
   196  		return nil, fmt.Errorf("blockhash mismatch, want %x, got %x", params.BlockHash, block.Hash())
   197  	}
   198  	return block, nil
   199  }
   200  
   201  // BlockToExecutableData constructs the ExecutableData structure by filling the
   202  // fields from the given block. It assumes the given block is post-merge block.
   203  func BlockToExecutableData(block *types.Block, fees *big.Int) *ExecutionPayloadEnvelope {
   204  	data := &ExecutableData{
   205  		BlockHash:     block.Hash(),
   206  		ParentHash:    block.ParentHash(),
   207  		FeeRecipient:  block.Coinbase(),
   208  		StateRoot:     block.Root(),
   209  		Number:        block.NumberU64(),
   210  		GasLimit:      block.GasLimit(),
   211  		GasUsed:       block.GasUsed(),
   212  		BaseFeePerGas: block.BaseFee(),
   213  		Timestamp:     block.Time(),
   214  		ReceiptsRoot:  block.ReceiptHash(),
   215  		LogsBloom:     block.Bloom().Bytes(),
   216  		Transactions:  encodeTransactions(block.Transactions()),
   217  		Random:        block.Random(),
   218  		ExtraData:     block.Extra(),
   219  		Withdrawals:   block.Withdrawals(),
   220  	}
   221  
   222  	return &ExecutionPayloadEnvelope{ExecutionPayload: data, BlockValue: fees, Override: false}
   223  }
   224  
   225  // ExecutionPayloadBodyV1 is used in the response to GetPayloadBodiesByHashV1 and GetPayloadBodiesByRangeV1
   226  type ExecutionPayloadBodyV1 struct {
   227  	TransactionData []hexutil.Bytes     `json:"transactions"`
   228  	Withdrawals     []*types.Withdrawal `json:"withdrawals"`
   229  }