github.com/intfoundation/intchain@v0.0.0-20220727031208-4316ad31ca73/core/rawdb/accessors_chain.go (about) 1 // Copyright 2018 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package rawdb 18 19 import ( 20 "bytes" 21 "encoding/binary" 22 "math/big" 23 24 "github.com/intfoundation/intchain/common" 25 "github.com/intfoundation/intchain/core/types" 26 "github.com/intfoundation/intchain/intdb" 27 "github.com/intfoundation/intchain/log" 28 "github.com/intfoundation/intchain/rlp" 29 ) 30 31 // ReadCanonicalHash retrieves the hash assigned to a canonical block number. 32 func ReadCanonicalHash(db intdb.Reader, number uint64) common.Hash { 33 data, _ := db.Get(headerHashKey(number)) 34 if len(data) == 0 { 35 return common.Hash{} 36 } 37 return common.BytesToHash(data) 38 } 39 40 // WriteCanonicalHash stores the hash assigned to a canonical block number. 41 func WriteCanonicalHash(db intdb.Writer, hash common.Hash, number uint64) { 42 if err := db.Put(headerHashKey(number), hash.Bytes()); err != nil { 43 log.Crit("Failed to store number to hash mapping", "err", err) 44 } 45 } 46 47 // DeleteCanonicalHash removes the number to hash canonical mapping. 48 func DeleteCanonicalHash(db intdb.Writer, number uint64) { 49 if err := db.Delete(headerHashKey(number)); err != nil { 50 log.Crit("Failed to delete number to hash mapping", "err", err) 51 } 52 } 53 54 // ReadHeaderNumber returns the header number assigned to a hash. 55 func ReadHeaderNumber(db intdb.Reader, hash common.Hash) *uint64 { 56 data, _ := db.Get(headerNumberKey(hash)) 57 if len(data) != 8 { 58 return nil 59 } 60 number := binary.BigEndian.Uint64(data) 61 return &number 62 } 63 64 // ReadHeadHeaderHash retrieves the hash of the current canonical head header. 65 func ReadHeadHeaderHash(db intdb.Reader) common.Hash { 66 data, _ := db.Get(headHeaderKey) 67 if len(data) == 0 { 68 return common.Hash{} 69 } 70 return common.BytesToHash(data) 71 } 72 73 // WriteHeadHeaderHash stores the hash of the current canonical head header. 74 func WriteHeadHeaderHash(db intdb.Writer, hash common.Hash) { 75 if err := db.Put(headHeaderKey, hash.Bytes()); err != nil { 76 log.Crit("Failed to store last header's hash", "err", err) 77 } 78 } 79 80 // ReadHeadBlockHash retrieves the hash of the current canonical head block. 81 func ReadHeadBlockHash(db intdb.Reader) common.Hash { 82 data, _ := db.Get(headBlockKey) 83 if len(data) == 0 { 84 return common.Hash{} 85 } 86 return common.BytesToHash(data) 87 } 88 89 // WriteHeadBlockHash stores the head block's hash. 90 func WriteHeadBlockHash(db intdb.Writer, hash common.Hash) { 91 if err := db.Put(headBlockKey, hash.Bytes()); err != nil { 92 log.Crit("Failed to store last block's hash", "err", err) 93 } 94 } 95 96 // ReadHeadFastBlockHash retrieves the hash of the current fast-sync head block. 97 func ReadHeadFastBlockHash(db intdb.Reader) common.Hash { 98 data, _ := db.Get(headFastBlockKey) 99 if len(data) == 0 { 100 return common.Hash{} 101 } 102 return common.BytesToHash(data) 103 } 104 105 // WriteHeadFastBlockHash stores the hash of the current fast-sync head block. 106 func WriteHeadFastBlockHash(db intdb.Writer, hash common.Hash) { 107 if err := db.Put(headFastBlockKey, hash.Bytes()); err != nil { 108 log.Crit("Failed to store last fast block's hash", "err", err) 109 } 110 } 111 112 // ReadFastTrieProgress retrieves the number of tries nodes fast synced to allow 113 // reporting correct numbers across restarts. 114 func ReadFastTrieProgress(db intdb.Reader) uint64 { 115 data, _ := db.Get(fastTrieProgressKey) 116 if len(data) == 0 { 117 return 0 118 } 119 return new(big.Int).SetBytes(data).Uint64() 120 } 121 122 // WriteFastTrieProgress stores the fast sync trie process counter to support 123 // retrieving it across restarts. 124 func WriteFastTrieProgress(db intdb.Writer, count uint64) { 125 if err := db.Put(fastTrieProgressKey, new(big.Int).SetUint64(count).Bytes()); err != nil { 126 log.Crit("Failed to store fast sync trie progress", "err", err) 127 } 128 } 129 130 // ReadHeaderRLP retrieves a block header in its raw RLP database encoding. 131 func ReadHeaderRLP(db intdb.Reader, hash common.Hash, number uint64) rlp.RawValue { 132 data, _ := db.Get(headerKey(number, hash)) 133 return data 134 } 135 136 // HasHeader verifies the existence of a block header corresponding to the hash. 137 func HasHeader(db intdb.Reader, hash common.Hash, number uint64) bool { 138 if has, err := db.Has(headerKey(number, hash)); !has || err != nil { 139 return false 140 } 141 return true 142 } 143 144 // ReadHeader retrieves the block header corresponding to the hash. 145 func ReadHeader(db intdb.Reader, hash common.Hash, number uint64) *types.Header { 146 data := ReadHeaderRLP(db, hash, number) 147 if len(data) == 0 { 148 return nil 149 } 150 header := new(types.Header) 151 if err := rlp.Decode(bytes.NewReader(data), header); err != nil { 152 log.Error("Invalid block header RLP", "hash", hash, "err", err) 153 return nil 154 } 155 return header 156 } 157 158 // WriteHeader stores a block header into the database and also stores the hash- 159 // to-number mapping. 160 func WriteHeader(db intdb.Writer, header *types.Header) { 161 // Write the hash -> number mapping 162 var ( 163 hash = header.Hash() 164 number = header.Number.Uint64() 165 encoded = encodeBlockNumber(number) 166 ) 167 key := headerNumberKey(hash) 168 if err := db.Put(key, encoded); err != nil { 169 log.Crit("Failed to store hash to number mapping", "err", err) 170 } 171 // Write the encoded header 172 data, err := rlp.EncodeToBytes(header) 173 if err != nil { 174 log.Crit("Failed to RLP encode header", "err", err) 175 } 176 key = headerKey(number, hash) 177 if err := db.Put(key, data); err != nil { 178 log.Crit("Failed to store header", "err", err) 179 } 180 } 181 182 // DeleteHeader removes all block header data associated with a hash. 183 func DeleteHeader(db intdb.Writer, hash common.Hash, number uint64) { 184 deleteHeaderWithoutNumber(db, hash, number) 185 if err := db.Delete(headerNumberKey(hash)); err != nil { 186 log.Crit("Failed to delete hash to number mapping", "err", err) 187 } 188 } 189 190 // deleteHeaderWithoutNumber removes only the block header but does not remove 191 // the hash to number mapping. 192 func deleteHeaderWithoutNumber(db intdb.Writer, hash common.Hash, number uint64) { 193 if err := db.Delete(headerKey(number, hash)); err != nil { 194 log.Crit("Failed to delete header", "err", err) 195 } 196 } 197 198 // ReadBodyRLP retrieves the block body (transactions and uncles) in RLP encoding. 199 func ReadBodyRLP(db intdb.Reader, hash common.Hash, number uint64) rlp.RawValue { 200 data, _ := db.Get(blockBodyKey(number, hash)) 201 return data 202 } 203 204 // WriteBodyRLP stores an RLP encoded block body into the database. 205 func WriteBodyRLP(db intdb.Writer, hash common.Hash, number uint64, rlp rlp.RawValue) { 206 if err := db.Put(blockBodyKey(number, hash), rlp); err != nil { 207 log.Crit("Failed to store block body", "err", err) 208 } 209 } 210 211 // HasBody verifies the existence of a block body corresponding to the hash. 212 func HasBody(db intdb.Reader, hash common.Hash, number uint64) bool { 213 if has, err := db.Has(blockBodyKey(number, hash)); !has || err != nil { 214 return false 215 } 216 return true 217 } 218 219 // ReadBody retrieves the block body corresponding to the hash. 220 func ReadBody(db intdb.Reader, hash common.Hash, number uint64) *types.Body { 221 data := ReadBodyRLP(db, hash, number) 222 if len(data) == 0 { 223 return nil 224 } 225 body := new(types.Body) 226 if err := rlp.Decode(bytes.NewReader(data), body); err != nil { 227 log.Error("Invalid block body RLP", "hash", hash, "err", err) 228 return nil 229 } 230 return body 231 } 232 233 // WriteBody storea a block body into the database. 234 func WriteBody(db intdb.Writer, hash common.Hash, number uint64, body *types.Body) { 235 data, err := rlp.EncodeToBytes(body) 236 if err != nil { 237 log.Crit("Failed to RLP encode body", "err", err) 238 } 239 WriteBodyRLP(db, hash, number, data) 240 } 241 242 // DeleteBody removes all block body data associated with a hash. 243 func DeleteBody(db intdb.Writer, hash common.Hash, number uint64) { 244 if err := db.Delete(blockBodyKey(number, hash)); err != nil { 245 log.Crit("Failed to delete block body", "err", err) 246 } 247 } 248 249 // ReadTdRLP retrieves a block's total difficulty corresponding to the hash in RLP encoding. 250 func ReadTdRLP(db intdb.Reader, hash common.Hash, number uint64) rlp.RawValue { 251 data, _ := db.Get(headerTDKey(number, hash)) 252 return data 253 } 254 255 // ReadTd retrieves a block's total difficulty corresponding to the hash. 256 func ReadTd(db intdb.Reader, hash common.Hash, number uint64) *big.Int { 257 data := ReadTdRLP(db, hash, number) 258 if len(data) == 0 { 259 return nil 260 } 261 td := new(big.Int) 262 if err := rlp.Decode(bytes.NewReader(data), td); err != nil { 263 log.Error("Invalid block total difficulty RLP", "hash", hash, "err", err) 264 return nil 265 } 266 return td 267 } 268 269 // WriteTd stores the total difficulty of a block into the database. 270 func WriteTd(db intdb.Writer, hash common.Hash, number uint64, td *big.Int) { 271 data, err := rlp.EncodeToBytes(td) 272 if err != nil { 273 log.Crit("Failed to RLP encode block total difficulty", "err", err) 274 } 275 if err := db.Put(headerTDKey(number, hash), data); err != nil { 276 log.Crit("Failed to store block total difficulty", "err", err) 277 } 278 } 279 280 // DeleteTd removes all block total difficulty data associated with a hash. 281 func DeleteTd(db intdb.Writer, hash common.Hash, number uint64) { 282 if err := db.Delete(headerTDKey(number, hash)); err != nil { 283 log.Crit("Failed to delete block total difficulty", "err", err) 284 } 285 } 286 287 // HasReceipts verifies the existence of all the transaction receipts belonging 288 // to a block. 289 func HasReceipts(db intdb.Reader, hash common.Hash, number uint64) bool { 290 if has, err := db.Has(blockReceiptsKey(number, hash)); !has || err != nil { 291 return false 292 } 293 return true 294 } 295 296 // ReadReceiptsRLP retrieves all the transaction receipts belonging to a block in RLP encoding. 297 func ReadReceiptsRLP(db intdb.Reader, hash common.Hash, number uint64) rlp.RawValue { 298 data, _ := db.Get(blockReceiptsKey(number, hash)) 299 return data 300 } 301 302 // ReadReceipts retrieves all the transaction receipts belonging to a block. 303 func ReadReceipts(db intdb.Reader, hash common.Hash, number uint64) types.Receipts { 304 // Retrieve the flattened receipt slice 305 data := ReadReceiptsRLP(db, hash, number) 306 if len(data) == 0 { 307 return nil 308 } 309 // Convert the receipts from their storage form to their internal representation 310 storageReceipts := []*types.ReceiptForStorage{} 311 if err := rlp.DecodeBytes(data, &storageReceipts); err != nil { 312 log.Error("Invalid receipt array RLP", "hash", hash, "err", err) 313 return nil 314 } 315 receipts := make(types.Receipts, len(storageReceipts)) 316 logIndex := uint(0) 317 for i, receipt := range storageReceipts { 318 // Assemble deriving fields for log. 319 for _, log := range receipt.Logs { 320 log.TxHash = receipt.TxHash 321 log.BlockHash = hash 322 log.BlockNumber = number 323 log.TxIndex = uint(i) 324 log.Index = logIndex 325 logIndex += 1 326 } 327 receipts[i] = (*types.Receipt)(receipt) 328 receipts[i].BlockHash = hash 329 receipts[i].BlockNumber = big.NewInt(0).SetUint64(number) 330 receipts[i].TransactionIndex = uint(i) 331 } 332 return receipts 333 } 334 335 // WriteReceipts stores all the transaction receipts belonging to a block. 336 func WriteReceipts(db intdb.Writer, hash common.Hash, number uint64, receipts types.Receipts) { 337 // Convert the receipts into their storage form and serialize them 338 storageReceipts := make([]*types.ReceiptForStorage, len(receipts)) 339 for i, receipt := range receipts { 340 storageReceipts[i] = (*types.ReceiptForStorage)(receipt) 341 } 342 bytes, err := rlp.EncodeToBytes(storageReceipts) 343 if err != nil { 344 log.Crit("Failed to encode block receipts", "err", err) 345 } 346 // Store the flattened receipt slice 347 if err := db.Put(blockReceiptsKey(number, hash), bytes); err != nil { 348 log.Crit("Failed to store block receipts", "err", err) 349 } 350 } 351 352 // DeleteReceipts removes all receipt data associated with a block hash. 353 func DeleteReceipts(db intdb.Writer, hash common.Hash, number uint64) { 354 if err := db.Delete(blockReceiptsKey(number, hash)); err != nil { 355 log.Crit("Failed to delete block receipts", "err", err) 356 } 357 } 358 359 // ReadBlock retrieves an entire block corresponding to the hash, assembling it 360 // back from the stored header and body. If either the header or body could not 361 // be retrieved nil is returned. 362 // 363 // Note, due to concurrent download of header and block body the header and thus 364 // canonical hash can be stored in the database but the body data not (yet). 365 func ReadBlock(db intdb.Reader, hash common.Hash, number uint64) *types.Block { 366 header := ReadHeader(db, hash, number) 367 if header == nil { 368 return nil 369 } 370 body := ReadBody(db, hash, number) 371 if body == nil { 372 return nil 373 } 374 return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles) 375 } 376 377 // WriteBlock serializes a block into the database, header and body separately. 378 func WriteBlock(db intdb.Writer, block *types.Block) { 379 WriteBody(db, block.Hash(), block.NumberU64(), block.Body()) 380 WriteHeader(db, block.Header()) 381 } 382 383 // DeleteBlock removes all block data associated with a hash. 384 func DeleteBlock(db intdb.Writer, hash common.Hash, number uint64) { 385 DeleteReceipts(db, hash, number) 386 DeleteHeader(db, hash, number) 387 DeleteBody(db, hash, number) 388 DeleteTd(db, hash, number) 389 } 390 391 // deleteBlockWithoutNumber removes all block data associated with a hash, except 392 // the hash to number mapping. 393 func deleteBlockWithoutNumber(db intdb.Writer, hash common.Hash, number uint64) { 394 DeleteReceipts(db, hash, number) 395 deleteHeaderWithoutNumber(db, hash, number) 396 DeleteBody(db, hash, number) 397 DeleteTd(db, hash, number) 398 } 399 400 // FindCommonAncestor returns the last common ancestor of two block headers 401 func FindCommonAncestor(db intdb.Reader, a, b *types.Header) *types.Header { 402 for bn := b.Number.Uint64(); a.Number.Uint64() > bn; { 403 a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1) 404 if a == nil { 405 return nil 406 } 407 } 408 for an := a.Number.Uint64(); an < b.Number.Uint64(); { 409 b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1) 410 if b == nil { 411 return nil 412 } 413 } 414 for a.Hash() != b.Hash() { 415 a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1) 416 if a == nil { 417 return nil 418 } 419 b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1) 420 if b == nil { 421 return nil 422 } 423 } 424 return a 425 }