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 }