github.com/klaytn/klaytn@v1.10.2/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  	"sort"
    28  	"sync/atomic"
    29  	"time"
    30  	"unsafe"
    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  	BaseFee *big.Int `json:"baseFeePerGas,omitempty"    rlp:"optional"`
    67  }
    68  
    69  // field type overrides for gencodec
    70  type headerMarshaling struct {
    71  	BlockScore *hexutil.Big
    72  	Number     *hexutil.Big
    73  	GasUsed    hexutil.Uint64
    74  	Time       *hexutil.Big
    75  	TimeFoS    hexutil.Uint
    76  	Extra      hexutil.Bytes
    77  	BaseFee    *hexutil.Big
    78  	Hash       common.Hash `json:"hash"` // adds call to Hash() in MarshalJSON
    79  	Governance hexutil.Bytes
    80  	Vote       hexutil.Bytes
    81  }
    82  
    83  // Hash returns the block hash of the header, which is simply the keccak256 hash of its
    84  // RLP encoding.
    85  func (h *Header) Hash() common.Hash {
    86  	// If the mix digest is equivalent to the predefined Istanbul digest, use Istanbul
    87  	// specific hash calculation.
    88  	if EngineType == Engine_IBFT {
    89  		// Seal is reserved in extra-data. To prove block is signed by the proposer.
    90  		if istanbulHeader := IstanbulFilteredHeader(h, true); istanbulHeader != nil {
    91  			return rlpHash(istanbulHeader)
    92  		}
    93  	}
    94  	return rlpHash(h)
    95  }
    96  
    97  // HashNoNonce returns the hash which is used as input for the proof-of-work search.
    98  func (h *Header) HashNoNonce() common.Hash {
    99  	return rlpHash([]interface{}{
   100  		h.ParentHash,
   101  		h.Rewardbase,
   102  		h.Root,
   103  		h.TxHash,
   104  		h.ReceiptHash,
   105  		h.Bloom,
   106  		h.BlockScore,
   107  		h.Number,
   108  		h.GasUsed,
   109  		h.Time,
   110  		h.TimeFoS,
   111  		h.Extra,
   112  	})
   113  }
   114  
   115  // Size returns the approximate memory used by all internal contents. It is used
   116  // to approximate and limit the memory consumption of various caches.
   117  func (h *Header) Size() common.StorageSize {
   118  	return common.StorageSize(unsafe.Sizeof(*h)) + common.StorageSize(len(h.Extra)+(h.BlockScore.BitLen()+h.Number.BitLen()+h.Time.BitLen())/8)
   119  }
   120  
   121  func (h *Header) Round() byte {
   122  	return byte(h.Extra[IstanbulExtraVanity-1])
   123  }
   124  
   125  func rlpHash(x interface{}) (h common.Hash) {
   126  	hw := sha3.NewKeccak256()
   127  	rlp.Encode(hw, x)
   128  	hw.Sum(h[:0])
   129  	return h
   130  }
   131  
   132  // prefixedRlpHash writes the prefix into the hasher before rlp-encoding the
   133  // given interface. It's used for ethereum typed transactions.
   134  func prefixedRlpHash(prefix byte, x interface{}) (h common.Hash) {
   135  	hw := sha3.NewKeccak256()
   136  	hw.Reset()
   137  	hw.Write([]byte{prefix})
   138  	rlp.Encode(hw, x)
   139  	hw.Sum(h[:0])
   140  	return h
   141  }
   142  
   143  // EmptyBody returns true if there is no additional 'body' to complete the header
   144  // that is: no transactions.
   145  func (h *Header) EmptyBody() bool {
   146  	return h.TxHash == EmptyRootHash(h.Number)
   147  }
   148  
   149  // EmptyReceipts returns true if there are no receipts for this header/block.
   150  func (h *Header) EmptyReceipts() bool {
   151  	return h.ReceiptHash == EmptyRootHash(h.Number)
   152  }
   153  
   154  // Body is a simple (mutable, non-safe) data container for storing and moving
   155  // a block's data contents (transactions) together.
   156  type Body struct {
   157  	Transactions []*Transaction
   158  }
   159  
   160  // Block represents an entire block in the Klaytn blockchain.
   161  type Block struct {
   162  	header       *Header
   163  	transactions Transactions
   164  
   165  	// caches
   166  	hash atomic.Value
   167  	size atomic.Value
   168  
   169  	// Td is used by package blockchain to store the total blockscore
   170  	// of the chain up to and including the block.
   171  	td *big.Int
   172  
   173  	// These fields are used to track inter-peer block relay.
   174  	ReceivedAt   time.Time
   175  	ReceivedFrom interface{}
   176  }
   177  
   178  type Result struct {
   179  	Block *Block
   180  	Round int64
   181  }
   182  
   183  // extblock represents external block encoding used for Klaytn protocol, etc.
   184  type extblock struct {
   185  	Header *Header
   186  	Txs    []*Transaction
   187  }
   188  
   189  // NewBlock creates a new block. The input data is copied,
   190  // changes to header and to the field values will not affect the
   191  // block.
   192  //
   193  // The values of TxHash, ReceiptHash and Bloom in header
   194  // are ignored and set to values derived from the given txs and receipts.
   195  func NewBlock(header *Header, txs []*Transaction, receipts []*Receipt) *Block {
   196  	b := &Block{header: CopyHeader(header), td: new(big.Int)}
   197  
   198  	// TODO: panic if len(txs) != len(receipts)
   199  	if len(txs) == 0 {
   200  		b.header.TxHash = EmptyRootHash(header.Number)
   201  	} else {
   202  		b.header.TxHash = DeriveSha(Transactions(txs), header.Number)
   203  		b.transactions = make(Transactions, len(txs))
   204  		copy(b.transactions, txs)
   205  	}
   206  
   207  	if len(receipts) == 0 {
   208  		b.header.ReceiptHash = EmptyRootHash(header.Number)
   209  	} else {
   210  		b.header.ReceiptHash = DeriveSha(Receipts(receipts), header.Number)
   211  		b.header.Bloom = CreateBloom(receipts)
   212  	}
   213  
   214  	return b
   215  }
   216  
   217  // NewBlockWithHeader creates a block with the given header data. The
   218  // header data is copied, changes to header and to the field values
   219  // will not affect the block.
   220  func NewBlockWithHeader(header *Header) *Block {
   221  	return &Block{header: CopyHeader(header)}
   222  }
   223  
   224  // CopyHeader creates a deep copy of a block header to prevent side effects from
   225  // modifying a header variable.
   226  func CopyHeader(h *Header) *Header {
   227  	cpy := *h
   228  	if cpy.Time = new(big.Int); h.Time != nil {
   229  		cpy.Time.Set(h.Time)
   230  	}
   231  	if cpy.BlockScore = new(big.Int); h.BlockScore != nil {
   232  		cpy.BlockScore.Set(h.BlockScore)
   233  	}
   234  	if cpy.Number = new(big.Int); h.Number != nil {
   235  		cpy.Number.Set(h.Number)
   236  	}
   237  	if h.BaseFee != nil {
   238  		// This field exists after magma hardfork
   239  		cpy.BaseFee = new(big.Int).Set(h.BaseFee)
   240  	}
   241  	if len(h.Extra) > 0 {
   242  		cpy.Extra = make([]byte, len(h.Extra))
   243  		copy(cpy.Extra, h.Extra)
   244  	}
   245  	if len(h.Governance) > 0 {
   246  		cpy.Governance = make([]byte, len(h.Governance))
   247  		copy(cpy.Governance, h.Governance)
   248  	}
   249  	if len(h.Vote) > 0 {
   250  		cpy.Vote = make([]byte, len(h.Vote))
   251  		copy(cpy.Vote, h.Vote)
   252  	}
   253  	return &cpy
   254  }
   255  
   256  // DecodeRLP decodes the Klaytn
   257  func (b *Block) DecodeRLP(s *rlp.Stream) error {
   258  	var eb extblock
   259  	_, size, _ := s.Kind()
   260  	if err := s.Decode(&eb); err != nil {
   261  		return err
   262  	}
   263  	b.header, b.transactions = eb.Header, eb.Txs
   264  	b.size.Store(common.StorageSize(rlp.ListSize(size)))
   265  	return nil
   266  }
   267  
   268  // EncodeRLP serializes a block into the Klaytn RLP block format.
   269  func (b *Block) EncodeRLP(w io.Writer) error {
   270  	return rlp.Encode(w, extblock{
   271  		Header: b.header,
   272  		Txs:    b.transactions,
   273  	})
   274  }
   275  
   276  func (b *Block) Transactions() Transactions { return b.transactions }
   277  
   278  func (b *Block) Transaction(hash common.Hash) *Transaction {
   279  	for _, transaction := range b.transactions {
   280  		if transaction.Hash() == hash {
   281  			return transaction
   282  		}
   283  	}
   284  	return nil
   285  }
   286  
   287  func (b *Block) Number() *big.Int     { return new(big.Int).Set(b.header.Number) }
   288  func (b *Block) GasUsed() uint64      { return b.header.GasUsed }
   289  func (b *Block) BlockScore() *big.Int { return new(big.Int).Set(b.header.BlockScore) }
   290  func (b *Block) Time() *big.Int       { return new(big.Int).Set(b.header.Time) }
   291  func (b *Block) TimeFoS() uint8       { return b.header.TimeFoS }
   292  
   293  func (b *Block) NumberU64() uint64          { return b.header.Number.Uint64() }
   294  func (b *Block) Bloom() Bloom               { return b.header.Bloom }
   295  func (b *Block) Rewardbase() common.Address { return b.header.Rewardbase }
   296  func (b *Block) Root() common.Hash          { return b.header.Root }
   297  func (b *Block) ParentHash() common.Hash    { return b.header.ParentHash }
   298  func (b *Block) TxHash() common.Hash        { return b.header.TxHash }
   299  func (b *Block) ReceiptHash() common.Hash   { return b.header.ReceiptHash }
   300  func (b *Block) Extra() []byte              { return common.CopyBytes(b.header.Extra) }
   301  
   302  func (b *Block) Header() *Header { return CopyHeader(b.header) }
   303  
   304  // Body returns the non-header content of the block.
   305  func (b *Block) Body() *Body { return &Body{b.transactions} }
   306  
   307  func (b *Block) HashNoNonce() common.Hash {
   308  	return b.header.HashNoNonce()
   309  }
   310  
   311  // Size returns the true RLP encoded storage size of the block, either by encoding
   312  // and returning it, or returning a previsouly cached value.
   313  func (b *Block) Size() common.StorageSize {
   314  	if size := b.size.Load(); size != nil {
   315  		return size.(common.StorageSize)
   316  	}
   317  	c := writeCounter(0)
   318  	rlp.Encode(&c, b)
   319  	b.size.Store(common.StorageSize(c))
   320  	return common.StorageSize(c)
   321  }
   322  
   323  type writeCounter common.StorageSize
   324  
   325  func (c *writeCounter) Write(b []byte) (int, error) {
   326  	*c += writeCounter(len(b))
   327  	return len(b), nil
   328  }
   329  
   330  // WithSeal returns a new block with the data from b but the header replaced with
   331  // the sealed one.
   332  func (b *Block) WithSeal(header *Header) *Block {
   333  	cpy := *header
   334  
   335  	return &Block{
   336  		header:       &cpy,
   337  		transactions: b.transactions,
   338  	}
   339  }
   340  
   341  // WithBody returns a new block with the given transactions.
   342  func (b *Block) WithBody(transactions []*Transaction) *Block {
   343  	block := &Block{
   344  		header:       CopyHeader(b.header),
   345  		transactions: make([]*Transaction, len(transactions)),
   346  	}
   347  	copy(block.transactions, transactions)
   348  	return block
   349  }
   350  
   351  // Hash returns the keccak256 hash of b's header.
   352  // The hash is computed on the first call and cached thereafter.
   353  func (b *Block) Hash() common.Hash {
   354  	if hash := b.hash.Load(); hash != nil {
   355  		return hash.(common.Hash)
   356  	}
   357  	v := b.header.Hash()
   358  	b.hash.Store(v)
   359  	return v
   360  }
   361  
   362  func (b *Block) String() string {
   363  	str := fmt.Sprintf(`Block(#%v): Size: %v {
   364  MinerHash: %x
   365  %v
   366  Transactions:
   367  %v
   368  }
   369  `, b.Number(), b.Size(), b.header.HashNoNonce(), b.header, b.transactions)
   370  	return str
   371  }
   372  
   373  func (h *Header) String() string {
   374  	prefix := `Header(%x):
   375  	[`
   376  	strBaseHeader := `
   377  		ParentHash:       %x
   378  		Rewardbase:       %x
   379  		Root:             %x
   380  		TxSha:            %x
   381  		ReceiptSha:       %x
   382  		Bloom:            %x
   383  		BlockScore:       %v
   384  		Number:           %v
   385  		GasUsed:          %v
   386  		Time:             %v
   387  		TimeFoS:          %v
   388  		Extra:            %s
   389  		Governance:       %x
   390  		Vote:             %x
   391  	`
   392  	suffix := `
   393  	]`
   394  	strHeader := ""
   395  	if h.BaseFee != nil {
   396  		strBaseHeader = strBaseHeader + `	BaseFee:          %x
   397  		`
   398  		strHeader = fmt.Sprintf(prefix+strBaseHeader+suffix, 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, h.BaseFee)
   399  	} else {
   400  		strHeader = fmt.Sprintf(prefix+strBaseHeader+suffix, 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)
   401  	}
   402  	return strHeader
   403  }
   404  
   405  type Blocks []*Block
   406  
   407  type BlockBy func(b1, b2 *Block) bool
   408  
   409  func (self BlockBy) Sort(blocks Blocks) {
   410  	bs := blockSorter{
   411  		blocks: blocks,
   412  		by:     self,
   413  	}
   414  	sort.Sort(bs)
   415  }
   416  
   417  type blockSorter struct {
   418  	blocks Blocks
   419  	by     func(b1, b2 *Block) bool
   420  }
   421  
   422  func (self blockSorter) Len() int { return len(self.blocks) }
   423  func (self blockSorter) Swap(i, j int) {
   424  	self.blocks[i], self.blocks[j] = self.blocks[j], self.blocks[i]
   425  }
   426  func (self blockSorter) Less(i, j int) bool { return self.by(self.blocks[i], self.blocks[j]) }
   427  
   428  func Number(b1, b2 *Block) bool { return b1.header.Number.Cmp(b2.header.Number) < 0 }