|
1 |
| -// Copyright 2020 The go-ethereum Authors |
| 1 | +// Copyright 2022 The go-ethereum Authors |
2 | 2 | // This file is part of the go-ethereum library.
|
3 | 3 | //
|
4 | 4 | // The go-ethereum library is free software: you can redistribute it and/or modify
|
|
14 | 14 | // You should have received a copy of the GNU Lesser General Public License
|
15 | 15 | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
16 | 16 |
|
17 |
| -package catalyst |
| 17 | +package beacon |
18 | 18 |
|
19 | 19 | import (
|
20 | 20 | "fmt"
|
21 | 21 | "math/big"
|
22 | 22 |
|
23 | 23 | "github.com/ethereum/go-ethereum/common"
|
24 | 24 | "github.com/ethereum/go-ethereum/common/hexutil"
|
| 25 | + "github.com/ethereum/go-ethereum/core/types" |
| 26 | + "github.com/ethereum/go-ethereum/trie" |
25 | 27 | )
|
26 | 28 |
|
27 | 29 | //go:generate go run github.com/fjl/gencodec -type PayloadAttributesV1 -field-override payloadAttributesMarshaling -out gen_blockparams.go
|
@@ -121,3 +123,82 @@ type ForkchoiceStateV1 struct {
|
121 | 123 | SafeBlockHash common.Hash `json:"safeBlockHash"`
|
122 | 124 | FinalizedBlockHash common.Hash `json:"finalizedBlockHash"`
|
123 | 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 | +// len(extraData) <= 32 |
| 150 | +// uncleHash = emptyUncleHash |
| 151 | +// difficulty = 0 |
| 152 | +// and that the blockhash of the constructed block matches the parameters. |
| 153 | +func ExecutableDataToBlock(params ExecutableDataV1) (*types.Block, error) { |
| 154 | + txs, err := decodeTransactions(params.Transactions) |
| 155 | + if err != nil { |
| 156 | + return nil, err |
| 157 | + } |
| 158 | + if len(params.ExtraData) > 32 { |
| 159 | + return nil, fmt.Errorf("invalid extradata length: %v", len(params.ExtraData)) |
| 160 | + } |
| 161 | + header := &types.Header{ |
| 162 | + ParentHash: params.ParentHash, |
| 163 | + UncleHash: types.EmptyUncleHash, |
| 164 | + Coinbase: params.FeeRecipient, |
| 165 | + Root: params.StateRoot, |
| 166 | + TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)), |
| 167 | + ReceiptHash: params.ReceiptsRoot, |
| 168 | + Bloom: types.BytesToBloom(params.LogsBloom), |
| 169 | + Difficulty: common.Big0, |
| 170 | + Number: new(big.Int).SetUint64(params.Number), |
| 171 | + GasLimit: params.GasLimit, |
| 172 | + GasUsed: params.GasUsed, |
| 173 | + Time: params.Timestamp, |
| 174 | + BaseFee: params.BaseFeePerGas, |
| 175 | + Extra: params.ExtraData, |
| 176 | + MixDigest: params.Random, |
| 177 | + } |
| 178 | + block := types.NewBlockWithHeader(header).WithBody(txs, nil /* uncles */) |
| 179 | + if block.Hash() != params.BlockHash { |
| 180 | + return nil, fmt.Errorf("blockhash mismatch, want %x, got %x", params.BlockHash, block.Hash()) |
| 181 | + } |
| 182 | + return block, nil |
| 183 | +} |
| 184 | + |
| 185 | +// BlockToExecutableData constructs the executableDataV1 structure by filling the |
| 186 | +// fields from the given block. It assumes the given block is post-merge block. |
| 187 | +func BlockToExecutableData(block *types.Block) *ExecutableDataV1 { |
| 188 | + return &ExecutableDataV1{ |
| 189 | + BlockHash: block.Hash(), |
| 190 | + ParentHash: block.ParentHash(), |
| 191 | + FeeRecipient: block.Coinbase(), |
| 192 | + StateRoot: block.Root(), |
| 193 | + Number: block.NumberU64(), |
| 194 | + GasLimit: block.GasLimit(), |
| 195 | + GasUsed: block.GasUsed(), |
| 196 | + BaseFeePerGas: block.BaseFee(), |
| 197 | + Timestamp: block.Time(), |
| 198 | + ReceiptsRoot: block.ReceiptHash(), |
| 199 | + LogsBloom: block.Bloom().Bytes(), |
| 200 | + Transactions: encodeTransactions(block.Transactions()), |
| 201 | + Random: block.MixDigest(), |
| 202 | + ExtraData: block.Extra(), |
| 203 | + } |
| 204 | +} |
0 commit comments