github.com/koko1123/flow-go-1@v0.29.6/model/flow/header.go (about) 1 package flow 2 3 import ( 4 "encoding/json" 5 "time" 6 7 "github.com/fxamacker/cbor/v2" 8 "github.com/vmihailenco/msgpack/v4" 9 10 cborcodec "github.com/koko1123/flow-go-1/model/encoding/cbor" 11 "github.com/koko1123/flow-go-1/model/fingerprint" 12 ) 13 14 // Header contains all meta-data for a block, as well as a hash representing 15 // the combined payload of the entire block. It is what consensus nodes agree 16 // on after validating the contents against the payload hash. 17 type Header struct { 18 ChainID ChainID // ChainID is a chain-specific value to prevent replay attacks. 19 20 ParentID Identifier // ParentID is the ID of this block's parent. 21 22 Height uint64 // Height is the height of the parent + 1 23 24 PayloadHash Identifier // PayloadHash is a hash of the payload of this block. 25 26 Timestamp time.Time // Timestamp is the time at which this block was proposed. 27 // The proposer can choose any time, so this should not be trusted as accurate. 28 29 View uint64 // View number at which this block was proposed. 30 31 ParentVoterIndices []byte // a bitvector that represents all the voters for the parent block. 32 33 ParentVoterSigData []byte // aggregated signature over the parent block. Not a single cryptographic 34 // signature since the data represents cryptographic signatures serialized in some way (concatenation or other) 35 // A quorum certificate can be extracted from the header. 36 // This field is the SigData field of the extracted quorum certificate. 37 38 ProposerID Identifier // proposer identifier for the block 39 40 ProposerSigData []byte // signature of the proposer over the new block. Not a single cryptographic 41 // signature since the data represents cryptographic signatures serialized in some way (concatenation or other) 42 } 43 44 // Body returns the immutable part of the block header. 45 func (h Header) Body() interface{} { 46 return struct { 47 ChainID ChainID 48 ParentID Identifier 49 Height uint64 50 PayloadHash Identifier 51 Timestamp uint64 52 View uint64 53 ParentVoterIndices []byte 54 ParentVoterSigData []byte 55 ProposerID Identifier 56 }{ 57 ChainID: h.ChainID, 58 ParentID: h.ParentID, 59 Height: h.Height, 60 PayloadHash: h.PayloadHash, 61 Timestamp: uint64(h.Timestamp.UnixNano()), 62 View: h.View, 63 ParentVoterIndices: h.ParentVoterIndices, 64 ParentVoterSigData: h.ParentVoterSigData, 65 ProposerID: h.ProposerID, 66 } 67 } 68 69 func (h Header) Fingerprint() []byte { 70 return fingerprint.Fingerprint(h.Body()) 71 } 72 73 // ID returns a unique ID to singularly identify the header and its block 74 // within the flow system. 75 func (h Header) ID() Identifier { 76 return MakeID(h) 77 } 78 79 // Checksum returns the checksum of the header. 80 func (h Header) Checksum() Identifier { 81 return MakeID(h) 82 } 83 84 // MarshalJSON makes sure the timestamp is encoded in UTC. 85 func (h Header) MarshalJSON() ([]byte, error) { 86 87 // NOTE: this is just a sanity check to make sure that we don't get 88 // different encodings if someone forgets to use UTC timestamps 89 if h.Timestamp.Location() != time.UTC { 90 h.Timestamp = h.Timestamp.UTC() 91 } 92 93 // we use an alias to avoid endless recursion; the alias will not have the 94 // marshal function and encode like a raw header 95 type Encodable Header 96 return json.Marshal(struct { 97 Encodable 98 ID string 99 }{ 100 Encodable: Encodable(h), 101 ID: h.ID().String(), 102 }) 103 } 104 105 // UnmarshalJSON makes sure the timestamp is decoded in UTC. 106 func (h *Header) UnmarshalJSON(data []byte) error { 107 108 // we use an alias to avoid endless recursion; the alias will not have the 109 // unmarshal function and decode like a raw header 110 type Decodable *Header 111 err := json.Unmarshal(data, Decodable(h)) 112 113 // NOTE: the timezone check is not required for JSON, as it already encodes 114 // timezones, but it doesn't hurt to add it in case someone messes with the 115 // raw encoded format 116 if h.Timestamp.Location() != time.UTC { 117 h.Timestamp = h.Timestamp.UTC() 118 } 119 120 return err 121 } 122 123 // MarshalCBOR makes sure the timestamp is encoded in UTC. 124 func (h Header) MarshalCBOR() ([]byte, error) { 125 126 // NOTE: this is just a sanity check to make sure that we don't get 127 // different encodings if someone forgets to use UTC timestamps 128 if h.Timestamp.Location() != time.UTC { 129 h.Timestamp = h.Timestamp.UTC() 130 } 131 132 // we use an alias to avoid endless recursion; the alias will not have the 133 // marshal function and encode like a raw header 134 type Encodable Header 135 return cborcodec.EncMode.Marshal(Encodable(h)) 136 } 137 138 // UnmarshalCBOR makes sure the timestamp is decoded in UTC. 139 func (h *Header) UnmarshalCBOR(data []byte) error { 140 141 // we use an alias to avoid endless recursion; the alias will not have the 142 // unmarshal function and decode like a raw header 143 // NOTE: for some reason, the pointer alias works for JSON to not recurse, 144 // but msgpack will still recurse; we have to do an extra struct copy here 145 type Decodable Header 146 decodable := Decodable(*h) 147 err := cbor.Unmarshal(data, &decodable) 148 *h = Header(decodable) 149 150 // NOTE: the timezone check is not required for CBOR, as it already encodes 151 // timezones, but it doesn't hurt to add it in case someone messes with the 152 // raw encoded format 153 if h.Timestamp.Location() != time.UTC { 154 h.Timestamp = h.Timestamp.UTC() 155 } 156 157 return err 158 } 159 160 // MarshalMsgpack makes sure the timestamp is encoded in UTC. 161 func (h Header) MarshalMsgpack() ([]byte, error) { 162 163 // NOTE: this is just a sanity check to make sure that we don't get 164 // different encodings if someone forgets to use UTC timestamps 165 if h.Timestamp.Location() != time.UTC { 166 h.Timestamp = h.Timestamp.UTC() 167 } 168 169 // we use an alias to avoid endless recursion; the alias will not have the 170 // marshal function and encode like a raw header 171 type Encodable Header 172 return msgpack.Marshal(Encodable(h)) 173 } 174 175 // UnmarshalMsgpack makes sure the timestamp is decoded in UTC. 176 func (h *Header) UnmarshalMsgpack(data []byte) error { 177 178 // we use an alias to avoid endless recursion; the alias will not have the 179 // unmarshal function and decode like a raw header 180 // NOTE: for some reason, the pointer alias works for JSON to not recurse, 181 // but msgpack will still recurse; we have to do an extra struct copy here 182 type Decodable Header 183 decodable := Decodable(*h) 184 err := msgpack.Unmarshal(data, &decodable) 185 *h = Header(decodable) 186 187 // NOTE: Msgpack unmarshals timestamps with the local timezone, which means 188 // that a block ID would suddenly be different after encoding and decoding 189 // on a machine with non-UTC local time 190 if h.Timestamp.Location() != time.UTC { 191 h.Timestamp = h.Timestamp.UTC() 192 } 193 194 return err 195 }