github.com/klaytn/klaytn@v1.12.1/blockchain/types/block.go (about) 1 // Modifications Copyright 2018 The klaytn Authors 2 // Copyright 2015 The go-ethereum Authors 3 // This file is part of the go-ethereum library. 4 // 5 // The go-ethereum library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU Lesser General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // The go-ethereum library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU Lesser General Public License for more details. 14 // 15 // You should have received a copy of the GNU Lesser General Public License 16 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 // This file is derived from core/types/block.go (2018/06/04). 19 // Modified and improved for the klaytn development. 20 21 package types 22 23 import ( 24 "fmt" 25 "io" 26 "math/big" 27 "reflect" 28 "sort" 29 "sync/atomic" 30 "time" 31 32 "github.com/klaytn/klaytn/common" 33 "github.com/klaytn/klaytn/common/hexutil" 34 "github.com/klaytn/klaytn/crypto/sha3" 35 "github.com/klaytn/klaytn/rlp" 36 ) 37 38 const ( 39 Engine_IBFT int = iota 40 Engine_Clique 41 Engine_Gxhash 42 ) 43 44 var EngineType = Engine_IBFT 45 46 //go:generate gencodec -type Header -field-override headerMarshaling -out gen_header_json.go 47 48 // Header represents a block header in the Klaytn blockchain. 49 type Header struct { 50 ParentHash common.Hash `json:"parentHash" gencodec:"required"` 51 Rewardbase common.Address `json:"reward" gencodec:"required"` 52 Root common.Hash `json:"stateRoot" gencodec:"required"` 53 TxHash common.Hash `json:"transactionsRoot" gencodec:"required"` 54 ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"` 55 Bloom Bloom `json:"logsBloom" gencodec:"required"` 56 BlockScore *big.Int `json:"blockScore" gencodec:"required"` 57 Number *big.Int `json:"number" gencodec:"required"` 58 GasUsed uint64 `json:"gasUsed" gencodec:"required"` 59 Time *big.Int `json:"timestamp" gencodec:"required"` 60 // TimeFoS represents a fraction of a second since `Time`. 61 TimeFoS uint8 `json:"timestampFoS" gencodec:"required"` 62 Extra []byte `json:"extraData" gencodec:"required"` 63 Governance []byte `json:"governanceData" gencodec:"required"` 64 Vote []byte `json:"voteData,omitempty"` 65 66 // Added with Magma hardfork for KIP-71 dynamic fee. 67 BaseFee *big.Int `json:"baseFeePerGas,omitempty" rlp:"optional"` 68 69 // Added with Randao hardfork for KIP-114 RANDAO. 70 RandomReveal []byte `json:"randomReveal,omitempty" rlp:"optional"` // 96 byte BLS signature 71 MixHash []byte `json:"mixHash,omitempty" rlp:"optional"` // 32 byte RANDAO mix 72 73 // New header fields must be added at tail for backward compatibility. 74 } 75 76 // field type overrides for gencodec. When creating gen_header_json.go, 77 // gencodec will recognize headerMarshaling struct and use below types 78 // instead of the default native types. e.g. []byte -> hexutil.Byte 79 type headerMarshaling struct { 80 BlockScore *hexutil.Big 81 Number *hexutil.Big 82 GasUsed hexutil.Uint64 83 Time *hexutil.Big 84 TimeFoS hexutil.Uint 85 Extra hexutil.Bytes 86 BaseFee *hexutil.Big 87 Hash common.Hash `json:"hash"` // adds call to Hash() in MarshalJSON 88 Governance hexutil.Bytes 89 Vote hexutil.Bytes 90 RandomReveal hexutil.Bytes 91 MixHash hexutil.Bytes 92 } 93 94 // Hash returns the block hash of the header, which is simply the keccak256 hash of its 95 // RLP encoding. 96 func (h *Header) Hash() common.Hash { 97 // If the mix digest is equivalent to the predefined Istanbul digest, use Istanbul 98 // specific hash calculation. 99 if EngineType == Engine_IBFT { 100 // Seal is reserved in extra-data. To prove block is signed by the proposer. 101 if istanbulHeader := IstanbulFilteredHeader(h, true); istanbulHeader != nil { 102 return rlpHash(istanbulHeader) 103 } 104 } 105 return rlpHash(h) 106 } 107 108 // HashNoNonce returns the hash which is used as input for the proof-of-work search. 109 func (h *Header) HashNoNonce() common.Hash { 110 return rlpHash([]interface{}{ 111 h.ParentHash, 112 h.Rewardbase, 113 h.Root, 114 h.TxHash, 115 h.ReceiptHash, 116 h.Bloom, 117 h.BlockScore, 118 h.Number, 119 h.GasUsed, 120 h.Time, 121 h.TimeFoS, 122 h.Extra, 123 }) 124 } 125 126 // Size returns the approximate memory used by all internal contents. It is used 127 // to approximate and limit the memory consumption of various caches. 128 func (h *Header) Size() common.StorageSize { 129 constantSize := common.StorageSize(reflect.TypeOf(Header{}).Size()) 130 byteSize := common.StorageSize(len(h.Extra) + len(h.Governance) + len(h.Vote) + len(h.RandomReveal) + len(h.MixHash)) 131 bigIntSize := common.StorageSize((h.BlockScore.BitLen() + h.Number.BitLen() + h.Time.BitLen()) / 8) 132 if h.BaseFee != nil { 133 return constantSize + byteSize + bigIntSize + common.StorageSize(h.BaseFee.BitLen()/8) 134 } else { 135 return constantSize + byteSize + bigIntSize 136 } 137 } 138 139 func (h *Header) Round() byte { 140 return byte(h.Extra[IstanbulExtraVanity-1]) 141 } 142 143 func rlpHash(x interface{}) (h common.Hash) { 144 hw := sha3.NewKeccak256() 145 rlp.Encode(hw, x) 146 hw.Sum(h[:0]) 147 return h 148 } 149 150 // prefixedRlpHash writes the prefix into the hasher before rlp-encoding the 151 // given interface. It's used for ethereum typed transactions. 152 func prefixedRlpHash(prefix byte, x interface{}) (h common.Hash) { 153 hw := sha3.NewKeccak256() 154 hw.Reset() 155 hw.Write([]byte{prefix}) 156 rlp.Encode(hw, x) 157 hw.Sum(h[:0]) 158 return h 159 } 160 161 // EmptyBody returns true if there is no additional 'body' to complete the header 162 // that is: no transactions. 163 func (h *Header) EmptyBody() bool { 164 return h.TxHash == EmptyRootHash(h.Number) 165 } 166 167 // EmptyReceipts returns true if there are no receipts for this header/block. 168 func (h *Header) EmptyReceipts() bool { 169 return h.ReceiptHash == EmptyRootHash(h.Number) 170 } 171 172 // Body is a simple (mutable, non-safe) data container for storing and moving 173 // a block's data contents (transactions) together. 174 type Body struct { 175 Transactions []*Transaction 176 } 177 178 // Block represents an entire block in the Klaytn blockchain. 179 type Block struct { 180 header *Header 181 transactions Transactions 182 183 // caches 184 hash atomic.Value 185 size atomic.Value 186 187 // Td is used by package blockchain to store the total blockscore 188 // of the chain up to and including the block. 189 td *big.Int 190 191 // These fields are used to track inter-peer block relay. 192 ReceivedAt time.Time 193 ReceivedFrom interface{} 194 } 195 196 type Result struct { 197 Block *Block 198 Round int64 199 } 200 201 // extblock represents external block encoding used for Klaytn protocol, etc. 202 type extblock struct { 203 Header *Header 204 Txs []*Transaction 205 } 206 207 // NewBlock creates a new block. The input data is copied, 208 // changes to header and to the field values will not affect the 209 // block. 210 // 211 // The values of TxHash, ReceiptHash and Bloom in header 212 // are ignored and set to values derived from the given txs and receipts. 213 func NewBlock(header *Header, txs []*Transaction, receipts []*Receipt) *Block { 214 b := &Block{header: CopyHeader(header), td: new(big.Int)} 215 216 // TODO: panic if len(txs) != len(receipts) 217 if len(txs) == 0 { 218 b.header.TxHash = EmptyRootHash(header.Number) 219 } else { 220 b.header.TxHash = DeriveSha(Transactions(txs), header.Number) 221 b.transactions = make(Transactions, len(txs)) 222 copy(b.transactions, txs) 223 } 224 225 if len(receipts) == 0 { 226 b.header.ReceiptHash = EmptyRootHash(header.Number) 227 } else { 228 b.header.ReceiptHash = DeriveSha(Receipts(receipts), header.Number) 229 b.header.Bloom = CreateBloom(receipts) 230 } 231 232 return b 233 } 234 235 // NewBlockWithHeader creates a block with the given header data. The 236 // header data is copied, changes to header and to the field values 237 // will not affect the block. 238 func NewBlockWithHeader(header *Header) *Block { 239 return &Block{header: CopyHeader(header)} 240 } 241 242 // CopyHeader creates a deep copy of a block header to prevent side effects from 243 // modifying a header variable. 244 func CopyHeader(h *Header) *Header { 245 cpy := *h 246 if cpy.Time = new(big.Int); h.Time != nil { 247 cpy.Time.Set(h.Time) 248 } 249 if cpy.BlockScore = new(big.Int); h.BlockScore != nil { 250 cpy.BlockScore.Set(h.BlockScore) 251 } 252 if cpy.Number = new(big.Int); h.Number != nil { 253 cpy.Number.Set(h.Number) 254 } 255 if h.BaseFee != nil { 256 // This field exists after magma hardfork 257 cpy.BaseFee = new(big.Int).Set(h.BaseFee) 258 } 259 if len(h.Extra) > 0 { 260 cpy.Extra = make([]byte, len(h.Extra)) 261 copy(cpy.Extra, h.Extra) 262 } 263 if len(h.Governance) > 0 { 264 cpy.Governance = make([]byte, len(h.Governance)) 265 copy(cpy.Governance, h.Governance) 266 } 267 if len(h.Vote) > 0 { 268 cpy.Vote = make([]byte, len(h.Vote)) 269 copy(cpy.Vote, h.Vote) 270 } 271 if len(h.RandomReveal) > 0 { 272 cpy.RandomReveal = make([]byte, len(h.RandomReveal)) 273 copy(cpy.RandomReveal, h.RandomReveal) 274 } 275 if len(h.MixHash) > 0 { 276 cpy.MixHash = make([]byte, len(h.MixHash)) 277 copy(cpy.MixHash, h.MixHash) 278 } 279 return &cpy 280 } 281 282 // DecodeRLP decodes the Klaytn 283 func (b *Block) DecodeRLP(s *rlp.Stream) error { 284 var eb extblock 285 _, size, _ := s.Kind() 286 if err := s.Decode(&eb); err != nil { 287 return err 288 } 289 b.header, b.transactions = eb.Header, eb.Txs 290 b.size.Store(common.StorageSize(rlp.ListSize(size))) 291 return nil 292 } 293 294 // EncodeRLP serializes a block into the Klaytn RLP block format. 295 func (b *Block) EncodeRLP(w io.Writer) error { 296 return rlp.Encode(w, extblock{ 297 Header: b.header, 298 Txs: b.transactions, 299 }) 300 } 301 302 func (b *Block) Transactions() Transactions { return b.transactions } 303 304 func (b *Block) Transaction(hash common.Hash) *Transaction { 305 for _, transaction := range b.transactions { 306 if transaction.Hash() == hash { 307 return transaction 308 } 309 } 310 return nil 311 } 312 313 func (b *Block) Number() *big.Int { return new(big.Int).Set(b.header.Number) } 314 func (b *Block) GasUsed() uint64 { return b.header.GasUsed } 315 func (b *Block) BlockScore() *big.Int { return new(big.Int).Set(b.header.BlockScore) } 316 func (b *Block) Time() *big.Int { return new(big.Int).Set(b.header.Time) } 317 func (b *Block) TimeFoS() uint8 { return b.header.TimeFoS } 318 319 func (b *Block) NumberU64() uint64 { return b.header.Number.Uint64() } 320 func (b *Block) Bloom() Bloom { return b.header.Bloom } 321 func (b *Block) Rewardbase() common.Address { return b.header.Rewardbase } 322 func (b *Block) Root() common.Hash { return b.header.Root } 323 func (b *Block) ParentHash() common.Hash { return b.header.ParentHash } 324 func (b *Block) TxHash() common.Hash { return b.header.TxHash } 325 func (b *Block) ReceiptHash() common.Hash { return b.header.ReceiptHash } 326 func (b *Block) Extra() []byte { return common.CopyBytes(b.header.Extra) } 327 328 func (b *Block) Header() *Header { return CopyHeader(b.header) } 329 330 // Body returns the non-header content of the block. 331 func (b *Block) Body() *Body { return &Body{b.transactions} } 332 333 func (b *Block) HashNoNonce() common.Hash { 334 return b.header.HashNoNonce() 335 } 336 337 // Size returns the true RLP encoded storage size of the block, either by encoding 338 // and returning it, or returning a previsouly cached value. 339 func (b *Block) Size() common.StorageSize { 340 if size := b.size.Load(); size != nil { 341 return size.(common.StorageSize) 342 } 343 c := writeCounter(0) 344 rlp.Encode(&c, b) 345 b.size.Store(common.StorageSize(c)) 346 return common.StorageSize(c) 347 } 348 349 type writeCounter common.StorageSize 350 351 func (c *writeCounter) Write(b []byte) (int, error) { 352 *c += writeCounter(len(b)) 353 return len(b), nil 354 } 355 356 // WithSeal returns a new block with the data from b but the header replaced with 357 // the sealed one. 358 func (b *Block) WithSeal(header *Header) *Block { 359 cpy := *header 360 361 return &Block{ 362 header: &cpy, 363 transactions: b.transactions, 364 } 365 } 366 367 // WithBody returns a new block with the given transactions. 368 func (b *Block) WithBody(transactions []*Transaction) *Block { 369 block := &Block{ 370 header: CopyHeader(b.header), 371 transactions: make([]*Transaction, len(transactions)), 372 } 373 copy(block.transactions, transactions) 374 return block 375 } 376 377 // Hash returns the keccak256 hash of b's header. 378 // The hash is computed on the first call and cached thereafter. 379 func (b *Block) Hash() common.Hash { 380 if hash := b.hash.Load(); hash != nil { 381 return hash.(common.Hash) 382 } 383 v := b.header.Hash() 384 b.hash.Store(v) 385 return v 386 } 387 388 func (b *Block) String() string { 389 str := fmt.Sprintf(`Block(#%v): Size: %v { 390 MinerHash: %x 391 %v 392 Transactions: 393 %v 394 } 395 `, b.Number(), b.Size(), b.header.HashNoNonce(), b.header, b.transactions) 396 return str 397 } 398 399 func (h *Header) String() string { 400 str := fmt.Sprintf(`Header(%x): 401 [ 402 ParentHash: %x 403 Rewardbase: %x 404 Root: %x 405 TxSha: %x 406 ReceiptSha: %x 407 Bloom: %x 408 BlockScore: %v 409 Number: %v 410 GasUsed: %v 411 Time: %v 412 TimeFoS: %v 413 Extra: %x 414 Governance: %x 415 Vote: %x 416 `, 417 h.Hash(), h.ParentHash, h.Rewardbase, h.Root, h.TxHash, h.ReceiptHash, h.Bloom, h.BlockScore, h.Number, h.GasUsed, h.Time, h.TimeFoS, h.Extra, h.Governance, h.Vote) 418 419 if h.BaseFee != nil { 420 str += fmt.Sprintf(" BaseFee: %x\n", h.BaseFee) 421 } 422 if h.RandomReveal != nil { 423 str += fmt.Sprintf(" RandomReveal: %x\n", h.RandomReveal) 424 str += fmt.Sprintf(" MixHash: %x\n", h.MixHash) 425 } 426 427 str += "]" 428 return str 429 } 430 431 type Blocks []*Block 432 433 type BlockBy func(b1, b2 *Block) bool 434 435 func (self BlockBy) Sort(blocks Blocks) { 436 bs := blockSorter{ 437 blocks: blocks, 438 by: self, 439 } 440 sort.Sort(bs) 441 } 442 443 type blockSorter struct { 444 blocks Blocks 445 by func(b1, b2 *Block) bool 446 } 447 448 func (self blockSorter) Len() int { return len(self.blocks) } 449 func (self blockSorter) Swap(i, j int) { 450 self.blocks[i], self.blocks[j] = self.blocks[j], self.blocks[i] 451 } 452 func (self blockSorter) Less(i, j int) bool { return self.by(self.blocks[i], self.blocks[j]) } 453 454 func Number(b1, b2 *Block) bool { return b1.header.Number.Cmp(b2.header.Number) < 0 }