github.com/iotexproject/iotex-core@v1.14.1-rc1/blockchain/block/header.go (about)

     1  // Copyright (c) 2019 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package block
     7  
     8  import (
     9  	"time"
    10  
    11  	"github.com/iotexproject/go-pkgs/bloom"
    12  	"github.com/iotexproject/go-pkgs/crypto"
    13  	"github.com/iotexproject/go-pkgs/hash"
    14  	"github.com/iotexproject/iotex-proto/golang/iotextypes"
    15  	"github.com/pkg/errors"
    16  	"go.uber.org/zap"
    17  	"google.golang.org/protobuf/proto"
    18  	"google.golang.org/protobuf/types/known/timestamppb"
    19  
    20  	"github.com/iotexproject/iotex-core/pkg/log"
    21  	"github.com/iotexproject/iotex-core/pkg/util/byteutil"
    22  )
    23  
    24  // Header defines the struct of block header
    25  // make sure the variable type and order of this struct is same as "BlockHeaderPb" in blockchain.pb.go
    26  type Header struct {
    27  	version          uint32            // version
    28  	height           uint64            // block height
    29  	timestamp        time.Time         // propose timestamp
    30  	prevBlockHash    hash.Hash256      // hash of previous block
    31  	txRoot           hash.Hash256      // merkle root of all transactions
    32  	deltaStateDigest hash.Hash256      // digest of state change by this block
    33  	receiptRoot      hash.Hash256      // root of receipt trie
    34  	logsBloom        bloom.BloomFilter // bloom filter for all contract events in this block
    35  	blockSig         []byte            // block signature
    36  	pubkey           crypto.PublicKey  // block producer's public key
    37  }
    38  
    39  // Errors
    40  var (
    41  	ErrTxRootMismatch      = errors.New("transaction merkle root does not match")
    42  	ErrDeltaStateMismatch  = errors.New("delta state digest doesn't match")
    43  	ErrReceiptRootMismatch = errors.New("receipt root hash does not match")
    44  )
    45  
    46  // Version returns the version of this block.
    47  func (h *Header) Version() uint32 { return h.version }
    48  
    49  // Height returns the height of this block.
    50  func (h *Header) Height() uint64 { return h.height }
    51  
    52  // Timestamp returns the Timestamp of this block.
    53  func (h *Header) Timestamp() time.Time { return h.timestamp }
    54  
    55  // PrevHash returns the hash of prev block.
    56  func (h *Header) PrevHash() hash.Hash256 { return h.prevBlockHash }
    57  
    58  // TxRoot returns the hash of all actions in this block.
    59  func (h *Header) TxRoot() hash.Hash256 { return h.txRoot }
    60  
    61  // DeltaStateDigest returns the delta sate digest after applying this block.
    62  func (h *Header) DeltaStateDigest() hash.Hash256 { return h.deltaStateDigest }
    63  
    64  // PublicKey returns the public key of this header.
    65  func (h *Header) PublicKey() crypto.PublicKey { return h.pubkey }
    66  
    67  // ReceiptRoot returns the receipt root after apply this block
    68  func (h *Header) ReceiptRoot() hash.Hash256 { return h.receiptRoot }
    69  
    70  // HashBlock return the hash of this block (actually hash of block header)
    71  func (h *Header) HashBlock() hash.Hash256 { return h.HashHeader() }
    72  
    73  // LogsBloomfilter return the bloom filter for all contract log events
    74  func (h *Header) LogsBloomfilter() bloom.BloomFilter { return h.logsBloom }
    75  
    76  // Proto returns BlockHeader proto.
    77  func (h *Header) Proto() *iotextypes.BlockHeader {
    78  	header := iotextypes.BlockHeader{
    79  		Core: h.BlockHeaderCoreProto(),
    80  	}
    81  
    82  	if h.height > 0 {
    83  		header.ProducerPubkey = h.pubkey.Bytes()
    84  		header.Signature = h.blockSig
    85  	}
    86  	return &header
    87  }
    88  
    89  // BlockHeaderCoreProto returns BlockHeaderCore proto.
    90  func (h *Header) BlockHeaderCoreProto() *iotextypes.BlockHeaderCore {
    91  	ts := timestamppb.New(h.timestamp)
    92  	header := iotextypes.BlockHeaderCore{
    93  		Version:          h.version,
    94  		Height:           h.height,
    95  		Timestamp:        ts,
    96  		PrevBlockHash:    h.prevBlockHash[:],
    97  		TxRoot:           h.txRoot[:],
    98  		DeltaStateDigest: h.deltaStateDigest[:],
    99  		ReceiptRoot:      h.receiptRoot[:],
   100  	}
   101  	if h.logsBloom != nil {
   102  		header.LogsBloom = h.logsBloom.Bytes()
   103  	}
   104  	return &header
   105  }
   106  
   107  // LoadFromBlockHeaderProto loads from protobuf
   108  func (h *Header) LoadFromBlockHeaderProto(pb *iotextypes.BlockHeader) error {
   109  	if err := h.loadFromBlockHeaderCoreProto(pb.GetCore()); err != nil {
   110  		return err
   111  	}
   112  	sig := pb.GetSignature()
   113  	h.blockSig = make([]byte, len(sig))
   114  	copy(h.blockSig, sig)
   115  	pubKey, err := crypto.BytesToPublicKey(pb.GetProducerPubkey())
   116  	if err != nil {
   117  		return err
   118  	}
   119  	h.pubkey = pubKey
   120  	return nil
   121  }
   122  
   123  func (h *Header) loadFromBlockHeaderCoreProto(pb *iotextypes.BlockHeaderCore) error {
   124  	h.version = pb.GetVersion()
   125  	h.height = pb.GetHeight()
   126  	if err := pb.GetTimestamp().CheckValid(); err != nil {
   127  		return err
   128  	}
   129  	ts := pb.GetTimestamp().AsTime()
   130  	h.timestamp = ts
   131  	copy(h.prevBlockHash[:], pb.GetPrevBlockHash())
   132  	copy(h.txRoot[:], pb.GetTxRoot())
   133  	copy(h.deltaStateDigest[:], pb.GetDeltaStateDigest())
   134  	copy(h.receiptRoot[:], pb.GetReceiptRoot())
   135  	var err error
   136  	if pb.GetLogsBloom() != nil {
   137  		h.logsBloom, err = bloom.NewBloomFilterLegacy(2048, 3)
   138  		if err != nil {
   139  			return err
   140  		}
   141  		if err = h.logsBloom.FromBytes(pb.GetLogsBloom()); err != nil {
   142  			return err
   143  		}
   144  	}
   145  	return err
   146  }
   147  
   148  // SerializeCore returns byte stream for header core.
   149  func (h *Header) SerializeCore() []byte {
   150  	return byteutil.Must(proto.Marshal(h.BlockHeaderCoreProto()))
   151  }
   152  
   153  // Serialize returns the serialized byte stream of the block header
   154  func (h *Header) Serialize() ([]byte, error) {
   155  	return proto.Marshal(h.Proto())
   156  }
   157  
   158  // Deserialize loads from the serialized byte stream
   159  func (h *Header) Deserialize(buf []byte) error {
   160  	pb := &iotextypes.BlockHeader{}
   161  	if err := proto.Unmarshal(buf, pb); err != nil {
   162  		return err
   163  	}
   164  	return h.LoadFromBlockHeaderProto(pb)
   165  }
   166  
   167  // HashHeader hashes the header
   168  func (h *Header) HashHeader() hash.Hash256 {
   169  	s, _ := h.Serialize()
   170  	return hash.Hash256b(s)
   171  }
   172  
   173  // HashHeaderCore hahes the header core.
   174  func (h *Header) HashHeaderCore() hash.Hash256 {
   175  	return hash.Hash256b(h.SerializeCore())
   176  }
   177  
   178  // VerifySignature verifies the signature saved in block header
   179  func (h *Header) VerifySignature() bool {
   180  	hash := h.HashHeaderCore()
   181  
   182  	if h.pubkey == nil {
   183  		return false
   184  	}
   185  	return h.pubkey.Verify(hash[:], h.blockSig)
   186  }
   187  
   188  // VerifyDeltaStateDigest verifies the delta state digest in header
   189  func (h *Header) VerifyDeltaStateDigest(digest hash.Hash256) bool {
   190  	return h.deltaStateDigest == digest
   191  }
   192  
   193  // VerifyReceiptRoot verifies the receipt root in header
   194  func (h *Header) VerifyReceiptRoot(root hash.Hash256) bool {
   195  	return h.receiptRoot == root
   196  }
   197  
   198  // VerifyTransactionRoot verifies the delta state digest in header
   199  func (h *Header) VerifyTransactionRoot(root hash.Hash256) bool {
   200  	return h.txRoot == root
   201  }
   202  
   203  // ProducerAddress returns the address of producer
   204  func (h *Header) ProducerAddress() string {
   205  	addr := h.pubkey.Address()
   206  	return addr.String()
   207  }
   208  
   209  // HeaderLogger returns a new logger with block header fields' value.
   210  func (h *Header) HeaderLogger(l *zap.Logger) *zap.Logger {
   211  	return l.With(zap.Uint32("version", h.version),
   212  		zap.Uint64("height", h.height),
   213  		zap.String("timestamp", h.timestamp.String()),
   214  		log.Hex("prevBlockHash", h.prevBlockHash[:]),
   215  		log.Hex("txRoot", h.txRoot[:]),
   216  		log.Hex("receiptRoot", h.receiptRoot[:]),
   217  		log.Hex("deltaStateDigest", h.deltaStateDigest[:]),
   218  	)
   219  }