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 }