github.com/bcskill/bcschain/v3@v3.4.9-beta2/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/bcskill/bcschain/v3/common" 25 "github.com/bcskill/bcschain/v3/core/types" 26 "github.com/bcskill/bcschain/v3/ethdb" 27 "github.com/bcskill/bcschain/v3/log" 28 "github.com/bcskill/bcschain/v3/params" 29 "github.com/bcskill/bcschain/v3/rlp" 30 ) 31 32 // ReadCanonicalHash retrieves the hash assigned to a canonical block number. 33 func ReadCanonicalHash(db common.Database, number uint64) common.Hash { 34 k := numKey(number) 35 var data []byte 36 Must("get canonical hash", func() (err error) { 37 data, err = db.GlobalTable().Get(k) 38 if err == common.ErrNotFound { 39 data, err = db.HeaderTable().Get(k) 40 if err == common.ErrNotFound { 41 err = nil 42 } 43 if err != nil { 44 // Move to global for faster future lookup. 45 perr := db.GlobalTable().Put(k, data) 46 if perr != nil { 47 log.Warn("Failed to put canonical hash to global table", "number", number, "err", perr) 48 } else { 49 // Can ignore ErrImmutableSegment errors here. 50 if derr := db.HeaderTable().Delete(k); err != nil && err != ethdb.ErrImmutableSegment { 51 log.Warn("Failed to delete canonical hash from header table", "number", number, "err", derr) 52 } 53 } 54 } 55 } 56 return 57 }) 58 if len(data) == 0 { 59 return common.Hash{} 60 } 61 return common.BytesToHash(data) 62 } 63 64 // WriteCanonicalHash stores the hash assigned to a canonical block number. 65 func WriteCanonicalHash(db common.Database, hash common.Hash, number uint64) { 66 Must("put canonical hash", func() error { 67 return db.GlobalTable().Put(numKey(number), hash.Bytes()) 68 }) 69 } 70 71 // DeleteCanonicalHash removes the number to hash canonical mapping. 72 func DeleteCanonicalHash(db common.Database, number uint64) { 73 k := numKey(number) 74 Must("delete canonical hash", func() error { 75 if err := db.HeaderTable().Delete(k); err != nil && err != ethdb.ErrImmutableSegment { 76 log.Warn("Failed to delete canonical hash from header table", "number", number, "err", err) 77 return err 78 } else if err == ethdb.ErrImmutableSegment { 79 // Cannot tolerate ErrImmutableSegment errors here, but this shouldn't happen in practice. 80 log.Crit("Unable to delete canonical hash from immutable segment. Database may not be recoverable.", "number", number, "err", err) 81 } 82 return db.GlobalTable().Delete(k) 83 }) 84 } 85 86 // ReadHeaderNumber returns the header number assigned to a hash. 87 func ReadHeaderNumber(db DatabaseReader, hash common.Hash) *uint64 { 88 var data []byte 89 Must("get header number", func() (err error) { 90 data, err = db.Get(hashKey(blockHashPrefix, hash)) 91 if err == common.ErrNotFound { 92 err = nil 93 } 94 return 95 }) 96 if len(data) != 8 { 97 return nil 98 } 99 number := binary.BigEndian.Uint64(data) 100 return &number 101 } 102 103 // ReadHeadHeaderHash retrieves the hash of the current canonical head header. 104 func ReadHeadHeaderHash(db DatabaseReader) common.Hash { 105 var data []byte 106 Must("get head header hash", func() (err error) { 107 data, err = db.Get(headHeaderKey) 108 if err == common.ErrNotFound { 109 err = nil 110 } 111 return 112 }) 113 if len(data) == 0 { 114 return common.Hash{} 115 } 116 return common.BytesToHash(data) 117 } 118 119 // WriteHeadHeaderHash stores the hash of the current canonical head header. 120 func WriteHeadHeaderHash(db DatabaseWriter, hash common.Hash) { 121 Must("put head header hash", func() error { 122 return db.Put(headHeaderKey, hash.Bytes()) 123 }) 124 } 125 126 // ReadHeadBlockHash retrieves the hash of the current canonical head block. 127 func ReadHeadBlockHash(db DatabaseReader) common.Hash { 128 var data []byte 129 Must("get head block hash", func() (err error) { 130 data, err = db.Get(headBlockKey) 131 if err == common.ErrNotFound { 132 err = nil 133 } 134 return 135 }) 136 if len(data) == 0 { 137 return common.Hash{} 138 } 139 return common.BytesToHash(data) 140 } 141 142 // WriteHeadBlockHash stores the head block's hash. 143 func WriteHeadBlockHash(db DatabaseWriter, hash common.Hash) { 144 Must("put head block hash", func() error { 145 return db.Put(headBlockKey, hash.Bytes()) 146 }) 147 } 148 149 // ReadHeadFastBlockHash retrieves the hash of the current fast-sync head block. 150 func ReadHeadFastBlockHash(db DatabaseReader) common.Hash { 151 var data []byte 152 Must("get fast head block hash", func() (err error) { 153 data, err = db.Get(headFastBlockKey) 154 if err == common.ErrNotFound { 155 err = nil 156 } 157 return 158 }) 159 if len(data) == 0 { 160 return common.Hash{} 161 } 162 return common.BytesToHash(data) 163 } 164 165 // WriteHeadFastBlockHash stores the hash of the current fast-sync head block. 166 func WriteHeadFastBlockHash(db DatabaseWriter, hash common.Hash) { 167 Must("put fast head block hash", func() error { 168 return db.Put(headFastBlockKey, hash.Bytes()) 169 }) 170 } 171 172 // ReadFastTrieProgress retrieves the number of tries nodes fast synced to allow 173 // reporting correct numbers across restarts. 174 func ReadFastTrieProgress(db DatabaseReader) uint64 { 175 var data []byte 176 Must("get fast trie progress", func() (err error) { 177 data, err = db.Get(fastTrieProgressKey) 178 if err == common.ErrNotFound { 179 err = nil 180 } 181 return 182 }) 183 if len(data) == 0 { 184 return 0 185 } 186 return new(big.Int).SetBytes(data).Uint64() 187 } 188 189 // WriteFastTrieProgress stores the fast sync trie process counter to support 190 // retrieving it across restarts. 191 func WriteFastTrieProgress(db DatabaseWriter, count uint64) { 192 Must("put fast trie progress", func() error { 193 return db.Put(fastTrieProgressKey, new(big.Int).SetUint64(count).Bytes()) 194 }) 195 } 196 197 // ReadHeaderRLP retrieves a block header in its raw RLP database encoding. 198 func ReadHeaderRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue { 199 var data []byte 200 Must("get header", func() (err error) { 201 data, err = db.Get(numHashKey(headerPrefix, number, hash)) 202 if err == common.ErrNotFound { 203 err = nil 204 } 205 return 206 }) 207 return data 208 } 209 210 // HasHeader verifies the existence of a block header corresponding to the hash. 211 func HasHeader(db DatabaseReader, hash common.Hash, number uint64) bool { 212 var has bool 213 Must("has header", func() (err error) { 214 has, err = db.Has(numHashKey(headerPrefix, number, hash)) 215 if err == common.ErrNotFound { 216 err = nil 217 } 218 return 219 }) 220 return has 221 } 222 223 // ReadHeader retrieves the block header corresponding to the hash. 224 func ReadHeader(db DatabaseReader, hash common.Hash, number uint64) *types.Header { 225 data := ReadHeaderRLP(db, hash, number) 226 if len(data) == 0 { 227 return nil 228 } 229 header := new(types.Header) 230 if err := rlp.Decode(bytes.NewReader(data), header); err != nil { 231 log.Error("Invalid block header RLP", "hash", hash, "err", err) 232 return nil 233 } 234 return header 235 } 236 237 // WriteHeader stores a block header into the database and also stores the hash- 238 // to-number mapping. 239 func WriteHeader(global, headerTable common.Putter, header *types.Header) { 240 data, err := rlp.EncodeToBytes(header) 241 if err != nil { 242 log.Crit("Failed to encode header", "err", err) 243 return 244 } 245 hash := header.Hash() 246 num := header.Number.Uint64() 247 encNum := encodeBlockNumber(num) 248 Must("put hash to number mapping", func() error { 249 return global.Put(hashKey(blockHashPrefix, hash), encNum) 250 }) 251 Must("put header", func() error { 252 return headerTable.Put(numHashKey(headerPrefix, num, hash), data) 253 }) 254 } 255 256 // DeleteHeader removes all block header data associated with a hash. 257 func DeleteHeader(global, headerTable common.Deleter, hash common.Hash, number uint64) { 258 Must("delete header", func() error { 259 return global.Delete(hashKey(blockHashPrefix, hash)) 260 }) 261 Must("delete header hash to number mapping", func() error { 262 return headerTable.Delete(numHashKey(headerPrefix, number, hash)) 263 }) 264 } 265 266 // ReadBodyRLP retrieves the block body (transactions and uncles) in RLP encoding. 267 func ReadBodyRLP(db DatabaseReader, hash common.Hash, number uint64) rlp.RawValue { 268 var data []byte 269 Must("read body", func() (err error) { 270 data, err = db.Get(numHashKey(bodyPrefix, number, hash)) 271 if err == common.ErrNotFound { 272 err = nil 273 } 274 return 275 }) 276 return data 277 } 278 279 // WriteBodyRLP stores an RLP encoded block body into the database. 280 func WriteBodyRLP(db DatabaseWriter, hash common.Hash, number uint64, rlp rlp.RawValue) { 281 Must("write body", func() error { 282 return db.Put(numHashKey(bodyPrefix, number, hash), rlp) 283 }) 284 } 285 286 // HasBody verifies the existence of a block body corresponding to the hash. 287 func HasBody(db DatabaseReader, hash common.Hash, number uint64) bool { 288 var has bool 289 Must("has body", func() (err error) { 290 has, err = db.Has(numHashKey(bodyPrefix, number, hash)) 291 if err == common.ErrNotFound { 292 err = nil 293 } 294 return 295 }) 296 return has 297 } 298 299 // ReadBody retrieves the block body corresponding to the hash. 300 func ReadBody(db DatabaseReader, hash common.Hash, number uint64) *types.Body { 301 data := ReadBodyRLP(db, hash, number) 302 if len(data) == 0 { 303 return nil 304 } 305 body := new(types.Body) 306 if err := rlp.Decode(bytes.NewReader(data), body); err != nil { 307 log.Error("Invalid block body RLP", "hash", hash, "err", err) 308 return nil 309 } 310 return body 311 } 312 313 // WriteBody stores a block body into the database. 314 func WriteBody(db DatabaseWriter, hash common.Hash, number uint64, body *types.Body) { 315 data, err := rlp.EncodeToBytes(body) 316 if err != nil { 317 log.Crit("Failed to RLP encode body", "err", err) 318 } 319 WriteBodyRLP(db, hash, number, data) 320 } 321 322 // DeleteBody removes all block body data associated with a hash. 323 func DeleteBody(db DatabaseDeleter, hash common.Hash, number uint64) { 324 Must("delete block body", func() error { 325 return db.Delete(numHashKey(bodyPrefix, number, hash)) 326 }) 327 } 328 329 // ReadTd retrieves a block's total difficulty corresponding to the hash. 330 func ReadTd(db DatabaseReader, hash common.Hash, number uint64) *big.Int { 331 var data []byte 332 Must("read total difficulty", func() (err error) { 333 data, err = db.Get(tdKey(number, hash)) 334 if err == common.ErrNotFound { 335 err = nil 336 } 337 return 338 }) 339 if len(data) == 0 { 340 return nil 341 } 342 td := new(big.Int) 343 if err := rlp.Decode(bytes.NewReader(data), td); err != nil { 344 log.Error("Invalid block total difficulty RLP", "hash", hash, "err", err) 345 return nil 346 } 347 return td 348 } 349 350 // WriteTd stores the total difficulty of a block into the database. 351 func WriteTd(db DatabaseWriter, hash common.Hash, number uint64, td *big.Int) { 352 data, err := rlp.EncodeToBytes(td) 353 if err != nil { 354 log.Crit("Failed to RLP encode block total difficulty", "err", err) 355 } 356 Must("put total difficulty", func() error { 357 return db.Put(tdKey(number, hash), data) 358 }) 359 } 360 361 // DeleteTd removes all block total difficulty data associated with a hash. 362 func DeleteTd(db DatabaseDeleter, hash common.Hash, number uint64) { 363 Must("delete total difficulty", func() error { 364 return db.Delete(tdKey(number, hash)) 365 }) 366 } 367 368 // ReadRawReceipts retrieves all the transaction receipts belonging to a block. 369 // The receipt metadata fields are not guaranteed to be populated, so they 370 // should not be used. Use ReadReceipts instead if the metadata is needed. 371 func ReadRawReceipts(db DatabaseReader, hash common.Hash, number uint64) types.Receipts { 372 // Retrieve the flattened receipt slice 373 var data []byte 374 Must("get receipts", func() (err error) { 375 data, err = db.Get(numHashKey(blockReceiptsPrefix, number, hash)) 376 if err == common.ErrNotFound { 377 err = nil 378 } 379 return 380 }) 381 if len(data) == 0 { 382 return nil 383 } 384 // Convert the receipts from their storage form to their internal representation 385 var receipts types.ReceiptsForStorage 386 if err := rlp.DecodeBytes(data, &receipts); err != nil { 387 log.Error("Invalid receipt array RLP", "hash", hash, "err", err) 388 return nil 389 } 390 return types.Receipts(receipts) 391 } 392 393 // ReadReceipts retrieves all the transaction receipts belonging to a block, including 394 // its corresponding metadata fields. If it is unable to populate these metadata 395 // fields then nil is returned. 396 // 397 // The current implementation populates these metadata fields by reading the receipts' 398 // corresponding block body, so if the block body is not found it will return nil even 399 // if the receipt itself is stored. 400 func ReadReceipts(db common.Database, hash common.Hash, number uint64, config *params.ChainConfig) types.Receipts { 401 // We're deriving many fields from the block body, retrieve beside the receipt 402 receipts := ReadRawReceipts(db.ReceiptTable(), hash, number) 403 if receipts == nil { 404 return nil 405 } 406 body := ReadBody(db.BodyTable(), hash, number) 407 if body == nil { 408 log.Error("Missing body but have receipt", "hash", hash, "number", number) 409 return nil 410 } 411 if err := receipts.DeriveFields(config, hash, number, body.Transactions); err != nil { 412 log.Error("Failed to derive block receipts fields", "hash", hash, "number", number, "err", err) 413 return nil 414 } 415 return receipts 416 } 417 418 // WriteReceipts stores all the transaction receipts belonging to a block. 419 func WriteReceipts(db DatabaseWriter, hash common.Hash, number uint64, receipts types.Receipts) { 420 // Convert the receipts into their storage form and serialize them 421 bytes, err := rlp.EncodeToBytes((types.ReceiptsForStorage)(receipts)) 422 if err != nil { 423 log.Crit("Failed to encode block receipts", "err", err) 424 } 425 // Store the flattened receipt slice 426 Must("put receipts", func() error { 427 return db.Put(numHashKey(blockReceiptsPrefix, number, hash), bytes) 428 }) 429 } 430 431 // DeleteReceipts removes all receipt data associated with a block hash. 432 func DeleteReceipts(db DatabaseDeleter, hash common.Hash, number uint64) { 433 Must("delete receipts", func() error { 434 return db.Delete(numHashKey(blockReceiptsPrefix, number, hash)) 435 }) 436 } 437 438 // ReadBlock retrieves an entire block corresponding to the hash, assembling it 439 // back from the stored header and body. If either the header or body could not 440 // be retrieved nil is returned. 441 // 442 // Note, due to concurrent download of header and block body the header and thus 443 // canonical hash can be stored in the database but the body data not (yet). 444 func ReadBlock(db common.Database, hash common.Hash, number uint64) *types.Block { 445 header := ReadHeader(db.HeaderTable(), hash, number) 446 if header == nil { 447 return nil 448 } 449 body := ReadBody(db.BodyTable(), hash, number) 450 if body == nil { 451 return nil 452 } 453 return types.NewBlockWith(header, body) 454 } 455 456 // WriteBlock serializes a block into the database, header and body separately. 457 func WriteBlock(db common.Database, block *types.Block) { 458 WriteBody(db.BodyTable(), block.Hash(), block.NumberU64(), block.Body()) 459 WriteHeader(db.GlobalTable(), db.HeaderTable(), block.Header()) 460 } 461 462 // DeleteBlock removes all block data associated with a hash. 463 func DeleteBlock(db common.Database, hash common.Hash, number uint64) { 464 DeleteReceipts(db.ReceiptTable(), hash, number) 465 DeleteHeader(db.GlobalTable(), db.HeaderTable(), hash, number) 466 DeleteBody(db.BodyTable(), hash, number) 467 DeleteTd(db.GlobalTable(), hash, number) 468 } 469 470 // FindCommonAncestor returns the last common ancestor of two block headers 471 func FindCommonAncestor(db DatabaseReader, a, b *types.Header) *types.Header { 472 for bn := b.Number.Uint64(); a.Number.Uint64() > bn; { 473 a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1) 474 if a == nil { 475 return nil 476 } 477 } 478 for an := a.Number.Uint64(); an < b.Number.Uint64(); { 479 b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1) 480 if b == nil { 481 return nil 482 } 483 } 484 for a.Hash() != b.Hash() { 485 a = ReadHeader(db, a.ParentHash, a.Number.Uint64()-1) 486 if a == nil { 487 return nil 488 } 489 b = ReadHeader(db, b.ParentHash, b.Number.Uint64()-1) 490 if b == nil { 491 return nil 492 } 493 } 494 return a 495 }