github.com/mit-dci/lit@v0.0.0-20221102210550-8c3d3b49f2ce/btcutil/blockchain/chainio.go (about) 1 // Copyright (c) 2015-2016 The btcsuite developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package blockchain 6 7 import ( 8 "bytes" 9 "encoding/binary" 10 "fmt" 11 "math/big" 12 "sort" 13 14 "github.com/mit-dci/lit/btcutil" 15 "github.com/mit-dci/lit/btcutil/chaincfg/chainhash" 16 "github.com/mit-dci/lit/btcutil/database" 17 "github.com/mit-dci/lit/wire" 18 ) 19 20 var ( 21 // hashIndexBucketName is the name of the db bucket used to house to the 22 // block hash -> block height index. 23 hashIndexBucketName = []byte("hashidx") 24 25 // heightIndexBucketName is the name of the db bucket used to house to 26 // the block height -> block hash index. 27 heightIndexBucketName = []byte("heightidx") 28 29 // chainStateKeyName is the name of the db key used to store the best 30 // chain state. 31 chainStateKeyName = []byte("chainstate") 32 33 // spendJournalBucketName is the name of the db bucket used to house 34 // transactions outputs that are spent in each block. 35 spendJournalBucketName = []byte("spendjournal") 36 37 // utxoSetBucketName is the name of the db bucket used to house the 38 // unspent transaction output set. 39 utxoSetBucketName = []byte("utxoset") 40 41 // byteOrder is the preferred byte order used for serializing numeric 42 // fields for storage in the database. 43 byteOrder = binary.LittleEndian 44 ) 45 46 // errNotInMainChain signifies that a block hash or height that is not in the 47 // main chain was requested. 48 type errNotInMainChain string 49 50 // Error implements the error interface. 51 func (e errNotInMainChain) Error() string { 52 return string(e) 53 } 54 55 // isNotInMainChainErr returns whether or not the passed error is an 56 // errNotInMainChain error. 57 func isNotInMainChainErr(err error) bool { 58 _, ok := err.(errNotInMainChain) 59 return ok 60 } 61 62 // errDeserialize signifies that a problem was encountered when deserializing 63 // data. 64 type errDeserialize string 65 66 // Error implements the error interface. 67 func (e errDeserialize) Error() string { 68 return string(e) 69 } 70 71 // isDeserializeErr returns whether or not the passed error is an errDeserialize 72 // error. 73 func isDeserializeErr(err error) bool { 74 _, ok := err.(errDeserialize) 75 return ok 76 } 77 78 // ----------------------------------------------------------------------------- 79 // The transaction spend journal consists of an entry for each block connected 80 // to the main chain which contains the transaction outputs the block spends 81 // serialized such that the order is the reverse of the order they were spent. 82 // 83 // This is required because reorganizing the chain necessarily entails 84 // disconnecting blocks to get back to the point of the fork which implies 85 // unspending all of the transaction outputs that each block previously spent. 86 // Since the utxo set, by definition, only contains unspent transaction outputs, 87 // the spent transaction outputs must be resurrected from somewhere. There is 88 // more than one way this could be done, however this is the most straight 89 // forward method that does not require having a transaction index and unpruned 90 // blockchain. 91 // 92 // NOTE: This format is NOT self describing. The additional details such as 93 // the number of entries (transaction inputs) are expected to come from the 94 // block itself and the utxo set. The rationale in doing this is to save a 95 // significant amount of space. This is also the reason the spent outputs are 96 // serialized in the reverse order they are spent because later transactions 97 // are allowed to spend outputs from earlier ones in the same block. 98 // 99 // The serialized format is: 100 // 101 // [<header code><version><compressed txout>],... 102 // 103 // Field Type Size 104 // header code VLQ variable 105 // version VLQ variable 106 // compressed txout 107 // compressed amount VLQ variable 108 // compressed script []byte variable 109 // 110 // The serialized header code format is: 111 // bit 0 - containing transaction is a coinbase 112 // bits 1-x - height of the block that contains the spent txout 113 // 114 // NOTE: The header code and version are only encoded when the spent txout was 115 // the final unspent output of the containing transaction. Otherwise, the 116 // header code will be 0 and the version is not serialized at all. This is 117 // done because that information is only needed when the utxo set no longer 118 // has it. 119 // 120 // Example 1: 121 // From block 170 in main blockchain. 122 // 123 // 1301320511db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5c 124 // <><><------------------------------------------------------------------> 125 // | | | 126 // | version compressed txout 127 // header code 128 // 129 // - header code: 0x13 (coinbase, height 9) 130 // - transaction version: 1 131 // - compressed txout 0: 132 // - 0x32: VLQ-encoded compressed amount for 5000000000 (50 BTC) 133 // - 0x05: special script type pay-to-pubkey 134 // - 0x11...5c: x-coordinate of the pubkey 135 // 136 // Example 2: 137 // Adapted from block 100025 in main blockchain. 138 // 139 // 0091f20f006edbc6c4d31bae9f1ccc38538a114bf42de65e868b99700186c64700b2fb57eadf61e106a100a7445a8c3f67898841ec 140 // <><----------------------------------------------><----><><----------------------------------------------> 141 // | | | | | 142 // | compressed txout | version compressed txout 143 // header code header code 144 // 145 // - Last spent output: 146 // - header code: 0x00 (was not the final unspent output for containing tx) 147 // - transaction version: Nothing since header code is 0 148 // - compressed txout: 149 // - 0x91f20f: VLQ-encoded compressed amount for 34405000000 (344.05 BTC) 150 // - 0x00: special script type pay-to-pubkey-hash 151 // - 0x6e...86: pubkey hash 152 // - Second to last spent output: 153 // - header code: 0x8b9970 (not coinbase, height 100024) 154 // - transaction version: 1 155 // - compressed txout: 156 // - 0x86c647: VLQ-encoded compressed amount for 13761000000 (137.61 BTC) 157 // - 0x00: special script type pay-to-pubkey-hash 158 // - 0xb2...ec: pubkey hash 159 // ----------------------------------------------------------------------------- 160 161 // spentTxOut contains a spent transaction output and potentially additional 162 // contextual information such as whether or not it was contained in a coinbase 163 // transaction, the version of the transaction it was contained in, and which 164 // block height the containing transaction was included in. As described in 165 // the comments above, the additional contextual information will only be valid 166 // when this spent txout is spending the last unspent output of the containing 167 // transaction. 168 type spentTxOut struct { 169 compressed bool // The amount and public key script are compressed. 170 version int32 // The version of creating tx. 171 amount int64 // The amount of the output. 172 pkScript []byte // The public key script for the output. 173 174 // These fields are only set when this is spending the final output of 175 // the creating tx. 176 height int32 // Height of the the block containing the creating tx. 177 isCoinBase bool // Whether creating tx is a coinbase. 178 } 179 180 // spentTxOutHeaderCode returns the calculated header code to be used when 181 // serializing the provided stxo entry. 182 func spentTxOutHeaderCode(stxo *spentTxOut) uint64 { 183 // The header code is 0 when there is no height set for the stxo. 184 if stxo.height == 0 { 185 return 0 186 } 187 188 // As described in the serialization format comments, the header code 189 // encodes the height shifted over one bit and the coinbase flag in the 190 // lowest bit. 191 headerCode := uint64(stxo.height) << 1 192 if stxo.isCoinBase { 193 headerCode |= 0x01 194 } 195 196 return headerCode 197 } 198 199 // spentTxOutSerializeSize returns the number of bytes it would take to 200 // serialize the passed stxo according to the format described above. 201 func spentTxOutSerializeSize(stxo *spentTxOut) int { 202 headerCode := spentTxOutHeaderCode(stxo) 203 size := serializeSizeVLQ(headerCode) 204 if headerCode != 0 { 205 size += serializeSizeVLQ(uint64(stxo.version)) 206 } 207 return size + compressedTxOutSize(uint64(stxo.amount), stxo.pkScript, 208 stxo.version, stxo.compressed) 209 } 210 211 // putSpentTxOut serializes the passed stxo according to the format described 212 // above directly into the passed target byte slice. The target byte slice must 213 // be at least large enough to handle the number of bytes returned by the 214 // spentTxOutSerializeSize function or it will panic. 215 func putSpentTxOut(target []byte, stxo *spentTxOut) int { 216 headerCode := spentTxOutHeaderCode(stxo) 217 offset := putVLQ(target, headerCode) 218 if headerCode != 0 { 219 offset += putVLQ(target[offset:], uint64(stxo.version)) 220 } 221 return offset + putCompressedTxOut(target[offset:], uint64(stxo.amount), 222 stxo.pkScript, stxo.version, stxo.compressed) 223 } 224 225 // decodeSpentTxOut decodes the passed serialized stxo entry, possibly followed 226 // by other data, into the passed stxo struct. It returns the number of bytes 227 // read. 228 // 229 // Since the serialized stxo entry does not contain the height, version, or 230 // coinbase flag of the containing transaction when it still has utxos, the 231 // caller is responsible for passing in the containing transaction version in 232 // that case. The provided version is ignore when it is serialized as a part of 233 // the stxo. 234 // 235 // An error will be returned if the version is not serialized as a part of the 236 // stxo and is also not provided to the function. 237 func decodeSpentTxOut(serialized []byte, stxo *spentTxOut, txVersion int32) (int, error) { 238 // Ensure there are bytes to decode. 239 if len(serialized) == 0 { 240 return 0, errDeserialize("no serialized bytes") 241 } 242 243 // Deserialize the header code. 244 code, offset := deserializeVLQ(serialized) 245 if offset >= len(serialized) { 246 return offset, errDeserialize("unexpected end of data after " + 247 "header code") 248 } 249 250 // Decode the header code and deserialize the containing transaction 251 // version if needed. 252 // 253 // Bit 0 indicates containing transaction is a coinbase. 254 // Bits 1-x encode height of containing transaction. 255 if code != 0 { 256 version, bytesRead := deserializeVLQ(serialized[offset:]) 257 offset += bytesRead 258 if offset >= len(serialized) { 259 return offset, errDeserialize("unexpected end of data " + 260 "after version") 261 } 262 263 stxo.isCoinBase = code&0x01 != 0 264 stxo.height = int32(code >> 1) 265 stxo.version = int32(version) 266 } else { 267 // Ensure a tx version was specified if the stxo did not encode 268 // it. This should never happen unless there is database 269 // corruption or this function is being called without the 270 // proper state. 271 if txVersion == 0 { 272 return offset, AssertError("decodeSpentTxOut called " + 273 "without a containing tx version when the " + 274 "serialized stxo that does not encode the " + 275 "version") 276 } 277 stxo.version = txVersion 278 } 279 280 // Decode the compressed txout. 281 compAmount, compScript, bytesRead, err := decodeCompressedTxOut( 282 serialized[offset:], stxo.version) 283 offset += bytesRead 284 if err != nil { 285 return offset, errDeserialize(fmt.Sprintf("unable to decode "+ 286 "txout: %v", err)) 287 } 288 stxo.amount = int64(compAmount) 289 stxo.pkScript = compScript 290 stxo.compressed = true 291 return offset, nil 292 } 293 294 // deserializeSpendJournalEntry decodes the passed serialized byte slice into a 295 // slice of spent txouts according to the format described in detail above. 296 // 297 // Since the serialization format is not self describing, as noted in the 298 // format comments, this function also requires the transactions that spend the 299 // txouts and a utxo view that contains any remaining existing utxos in the 300 // transactions referenced by the inputs to the passed transasctions. 301 func deserializeSpendJournalEntry(serialized []byte, txns []*wire.MsgTx, view *UtxoViewpoint) ([]spentTxOut, error) { 302 // Calculate the total number of stxos. 303 var numStxos int 304 for _, tx := range txns { 305 numStxos += len(tx.TxIn) 306 } 307 308 // When a block has no spent txouts there is nothing to serialize. 309 if len(serialized) == 0 { 310 // Ensure the block actually has no stxos. This should never 311 // happen unless there is database corruption or an empty entry 312 // erroneously made its way into the database. 313 if numStxos != 0 { 314 return nil, AssertError(fmt.Sprintf("mismatched spend "+ 315 "journal serialization - no serialization for "+ 316 "expected %d stxos", numStxos)) 317 } 318 319 return nil, nil 320 } 321 322 // Loop backwards through all transactions so everything is read in 323 // reverse order to match the serialization order. 324 stxoIdx := numStxos - 1 325 stxoInFlight := make(map[chainhash.Hash]int) 326 offset := 0 327 stxos := make([]spentTxOut, numStxos) 328 for txIdx := len(txns) - 1; txIdx > -1; txIdx-- { 329 tx := txns[txIdx] 330 331 // Loop backwards through all of the transaction inputs and read 332 // the associated stxo. 333 for txInIdx := len(tx.TxIn) - 1; txInIdx > -1; txInIdx-- { 334 txIn := tx.TxIn[txInIdx] 335 stxo := &stxos[stxoIdx] 336 stxoIdx-- 337 338 // Get the transaction version for the stxo based on 339 // whether or not it should be serialized as a part of 340 // the stxo. Recall that it is only serialized when the 341 // stxo spends the final utxo of a transaction. Since 342 // they are deserialized in reverse order, this means 343 // the first time an entry for a given containing tx is 344 // encountered that is not already in the utxo view it 345 // must have been the final spend and thus the extra 346 // data will be serialized with the stxo. Otherwise, 347 // the version must be pulled from the utxo entry. 348 // 349 // Since the view is not actually modified as the stxos 350 // are read here and it's possible later entries 351 // reference earlier ones, an inflight map is maintained 352 // to detect this case and pull the tx version from the 353 // entry that contains the version information as just 354 // described. 355 var txVersion int32 356 originHash := &txIn.PreviousOutPoint.Hash 357 entry := view.LookupEntry(originHash) 358 if entry != nil { 359 txVersion = entry.Version() 360 } else if idx, ok := stxoInFlight[*originHash]; ok { 361 txVersion = stxos[idx].version 362 } else { 363 stxoInFlight[*originHash] = stxoIdx + 1 364 } 365 366 n, err := decodeSpentTxOut(serialized[offset:], stxo, 367 txVersion) 368 offset += n 369 if err != nil { 370 return nil, errDeserialize(fmt.Sprintf("unable "+ 371 "to decode stxo for %v: %v", 372 txIn.PreviousOutPoint, err)) 373 } 374 } 375 } 376 377 return stxos, nil 378 } 379 380 // serializeSpendJournalEntry serializes all of the passed spent txouts into a 381 // single byte slice according to the format described in detail above. 382 func serializeSpendJournalEntry(stxos []spentTxOut) []byte { 383 if len(stxos) == 0 { 384 return nil 385 } 386 387 // Calculate the size needed to serialize the entire journal entry. 388 var size int 389 for i := range stxos { 390 size += spentTxOutSerializeSize(&stxos[i]) 391 } 392 serialized := make([]byte, size) 393 394 // Serialize each individual stxo directly into the slice in reverse 395 // order one after the other. 396 var offset int 397 for i := len(stxos) - 1; i > -1; i-- { 398 offset += putSpentTxOut(serialized[offset:], &stxos[i]) 399 } 400 401 return serialized 402 } 403 404 // dbFetchSpendJournalEntry fetches the spend journal entry for the passed 405 // block and deserializes it into a slice of spent txout entries. The provided 406 // view MUST have the utxos referenced by all of the transactions available for 407 // the passed block since that information is required to reconstruct the spent 408 // txouts. 409 func dbFetchSpendJournalEntry(dbTx database.Tx, block *btcutil.Block, view *UtxoViewpoint) ([]spentTxOut, error) { 410 // Exclude the coinbase transaction since it can't spend anything. 411 spendBucket := dbTx.Metadata().Bucket(spendJournalBucketName) 412 serialized := spendBucket.Get(block.Hash()[:]) 413 blockTxns := block.MsgBlock().Transactions[1:] 414 stxos, err := deserializeSpendJournalEntry(serialized, blockTxns, view) 415 if err != nil { 416 // Ensure any deserialization errors are returned as database 417 // corruption errors. 418 if isDeserializeErr(err) { 419 return nil, database.Error{ 420 ErrorCode: database.ErrCorruption, 421 Description: fmt.Sprintf("corrupt spend "+ 422 "information for %v: %v", block.Hash(), 423 err), 424 } 425 } 426 427 return nil, err 428 } 429 430 return stxos, nil 431 } 432 433 // dbPutSpendJournalEntry uses an existing database transaction to update the 434 // spend journal entry for the given block hash using the provided slice of 435 // spent txouts. The spent txouts slice must contain an entry for every txout 436 // the transactions in the block spend in the order they are spent. 437 func dbPutSpendJournalEntry(dbTx database.Tx, blockHash *chainhash.Hash, stxos []spentTxOut) error { 438 spendBucket := dbTx.Metadata().Bucket(spendJournalBucketName) 439 serialized := serializeSpendJournalEntry(stxos) 440 return spendBucket.Put(blockHash[:], serialized) 441 } 442 443 // dbRemoveSpendJournalEntry uses an existing database transaction to remove the 444 // spend journal entry for the passed block hash. 445 func dbRemoveSpendJournalEntry(dbTx database.Tx, blockHash *chainhash.Hash) error { 446 spendBucket := dbTx.Metadata().Bucket(spendJournalBucketName) 447 return spendBucket.Delete(blockHash[:]) 448 } 449 450 // ----------------------------------------------------------------------------- 451 // The unspent transaction output (utxo) set consists of an entry for each 452 // transaction which contains a utxo serialized using a format that is highly 453 // optimized to reduce space using domain specific compression algorithms. This 454 // format is a slightly modified version of the format used in Bitcoin Core. 455 // 456 // The serialized format is: 457 // 458 // <version><height><header code><unspentness bitmap>[<compressed txouts>,...] 459 // 460 // Field Type Size 461 // version VLQ variable 462 // block height VLQ variable 463 // header code VLQ variable 464 // unspentness bitmap []byte variable 465 // compressed txouts 466 // compressed amount VLQ variable 467 // compressed script []byte variable 468 // 469 // The serialized header code format is: 470 // bit 0 - containing transaction is a coinbase 471 // bit 1 - output zero is unspent 472 // bit 2 - output one is unspent 473 // bits 3-x - number of bytes in unspentness bitmap. When both bits 1 and 2 474 // are unset, it encodes N-1 since there must be at least one unspent 475 // output. 476 // 477 // The rationale for the header code scheme is as follows: 478 // - Transactions which only pay to a single output and a change output are 479 // extremely common, thus an extra byte for the unspentness bitmap can be 480 // avoided for them by encoding those two outputs in the low order bits. 481 // - Given it is encoded as a VLQ which can encode values up to 127 with a 482 // single byte, that leaves 4 bits to represent the number of bytes in the 483 // unspentness bitmap while still only consuming a single byte for the 484 // header code. In other words, an unspentness bitmap with up to 120 485 // transaction outputs can be encoded with a single-byte header code. 486 // This covers the vast majority of transactions. 487 // - Encoding N-1 bytes when both bits 1 and 2 are unset allows an additional 488 // 8 outpoints to be encoded before causing the header code to require an 489 // additional byte. 490 // 491 // Example 1: 492 // From tx in main blockchain: 493 // Blk 1, 0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098 494 // 495 // 010103320496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52 496 // <><><><------------------------------------------------------------------> 497 // | | \--------\ | 498 // | height | compressed txout 0 499 // version header code 500 // 501 // - version: 1 502 // - height: 1 503 // - header code: 0x03 (coinbase, output zero unspent, 0 bytes of unspentness) 504 // - unspentness: Nothing since it is zero bytes 505 // - compressed txout 0: 506 // - 0x32: VLQ-encoded compressed amount for 5000000000 (50 BTC) 507 // - 0x04: special script type pay-to-pubkey 508 // - 0x96...52: x-coordinate of the pubkey 509 // 510 // Example 2: 511 // From tx in main blockchain: 512 // Blk 113931, 4a16969aa4764dd7507fc1de7f0baa4850a246de90c45e59a3207f9a26b5036f 513 // 514 // 0185f90b0a011200e2ccd6ec7c6e2e581349c77e067385fa8236bf8a800900b8025be1b3efc63b0ad48e7f9f10e87544528d58 515 // <><----><><><------------------------------------------><--------------------------------------------> 516 // | | | \-------------------\ | | 517 // version | \--------\ unspentness | compressed txout 2 518 // height header code compressed txout 0 519 // 520 // - version: 1 521 // - height: 113931 522 // - header code: 0x0a (output zero unspent, 1 byte in unspentness bitmap) 523 // - unspentness: [0x01] (bit 0 is set, so output 0+2 = 2 is unspent) 524 // NOTE: It's +2 since the first two outputs are encoded in the header code 525 // - compressed txout 0: 526 // - 0x12: VLQ-encoded compressed amount for 20000000 (0.2 BTC) 527 // - 0x00: special script type pay-to-pubkey-hash 528 // - 0xe2...8a: pubkey hash 529 // - compressed txout 2: 530 // - 0x8009: VLQ-encoded compressed amount for 15000000 (0.15 BTC) 531 // - 0x00: special script type pay-to-pubkey-hash 532 // - 0xb8...58: pubkey hash 533 // 534 // Example 3: 535 // From tx in main blockchain: 536 // Blk 338156, 1b02d1c8cfef60a189017b9a420c682cf4a0028175f2f563209e4ff61c8c3620 537 // 538 // 0193d06c100000108ba5b9e763011dd46a006572d820e448e12d2bbb38640bc718e6 539 // <><----><><----><--------------------------------------------------> 540 // | | | \-----------------\ | 541 // version | \--------\ unspentness | 542 // height header code compressed txout 22 543 // 544 // - version: 1 545 // - height: 338156 546 // - header code: 0x10 (2+1 = 3 bytes in unspentness bitmap) 547 // NOTE: It's +1 since neither bit 1 nor 2 are set, so N-1 is encoded. 548 // - unspentness: [0x00 0x00 0x10] (bit 20 is set, so output 20+2 = 22 is unspent) 549 // NOTE: It's +2 since the first two outputs are encoded in the header code 550 // - compressed txout 22: 551 // - 0x8ba5b9e763: VLQ-encoded compressed amount for 366875659 (3.66875659 BTC) 552 // - 0x01: special script type pay-to-script-hash 553 // - 0x1d...e6: script hash 554 // ----------------------------------------------------------------------------- 555 556 // utxoEntryHeaderCode returns the calculated header code to be used when 557 // serializing the provided utxo entry and the number of bytes needed to encode 558 // the unspentness bitmap. 559 func utxoEntryHeaderCode(entry *UtxoEntry, highestOutputIndex uint32) (uint64, int, error) { 560 // The first two outputs are encoded separately, so offset the index 561 // accordingly to calculate the correct number of bytes needed to encode 562 // up to the highest unspent output index. 563 numBitmapBytes := int((highestOutputIndex + 6) / 8) 564 565 // As previously described, one less than the number of bytes is encoded 566 // when both output 0 and 1 are spent because there must be at least one 567 // unspent output. Adjust the number of bytes to encode accordingly and 568 // encode the value by shifting it over 3 bits. 569 output0Unspent := !entry.IsOutputSpent(0) 570 output1Unspent := !entry.IsOutputSpent(1) 571 var numBitmapBytesAdjustment int 572 if !output0Unspent && !output1Unspent { 573 if numBitmapBytes == 0 { 574 return 0, 0, AssertError("attempt to serialize utxo " + 575 "header for fully spent transaction") 576 } 577 numBitmapBytesAdjustment = 1 578 } 579 headerCode := uint64(numBitmapBytes-numBitmapBytesAdjustment) << 3 580 581 // Set the coinbase, output 0, and output 1 bits in the header code 582 // accordingly. 583 if entry.isCoinBase { 584 headerCode |= 0x01 // bit 0 585 } 586 if output0Unspent { 587 headerCode |= 0x02 // bit 1 588 } 589 if output1Unspent { 590 headerCode |= 0x04 // bit 2 591 } 592 593 return headerCode, numBitmapBytes, nil 594 } 595 596 // serializeUtxoEntry returns the entry serialized to a format that is suitable 597 // for long-term storage. The format is described in detail above. 598 func serializeUtxoEntry(entry *UtxoEntry) ([]byte, error) { 599 // Fully spent entries have no serialization. 600 if entry.IsFullySpent() { 601 return nil, nil 602 } 603 604 // Determine the output order by sorting the sparse output index keys. 605 outputOrder := make([]int, 0, len(entry.sparseOutputs)) 606 for outputIndex := range entry.sparseOutputs { 607 outputOrder = append(outputOrder, int(outputIndex)) 608 } 609 sort.Ints(outputOrder) 610 611 // Encode the header code and determine the number of bytes the 612 // unspentness bitmap needs. 613 highIndex := uint32(outputOrder[len(outputOrder)-1]) 614 headerCode, numBitmapBytes, err := utxoEntryHeaderCode(entry, highIndex) 615 if err != nil { 616 return nil, err 617 } 618 619 // Calculate the size needed to serialize the entry. 620 size := serializeSizeVLQ(uint64(entry.version)) + 621 serializeSizeVLQ(uint64(entry.blockHeight)) + 622 serializeSizeVLQ(headerCode) + numBitmapBytes 623 for _, outputIndex := range outputOrder { 624 out := entry.sparseOutputs[uint32(outputIndex)] 625 if out.spent { 626 continue 627 } 628 size += compressedTxOutSize(uint64(out.amount), out.pkScript, 629 entry.version, out.compressed) 630 } 631 632 // Serialize the version, block height of the containing transaction, 633 // and header code. 634 serialized := make([]byte, size) 635 offset := putVLQ(serialized, uint64(entry.version)) 636 offset += putVLQ(serialized[offset:], uint64(entry.blockHeight)) 637 offset += putVLQ(serialized[offset:], headerCode) 638 639 // Serialize the unspentness bitmap. 640 for i := uint32(0); i < uint32(numBitmapBytes); i++ { 641 unspentBits := byte(0) 642 for j := uint32(0); j < 8; j++ { 643 // The first 2 outputs are encoded via the header code, 644 // so adjust the output index accordingly. 645 if !entry.IsOutputSpent(2 + i*8 + j) { 646 unspentBits |= 1 << uint8(j) 647 } 648 } 649 serialized[offset] = unspentBits 650 offset++ 651 } 652 653 // Serialize the compressed unspent transaction outputs. Outputs that 654 // are already compressed are serialized without modifications. 655 for _, outputIndex := range outputOrder { 656 out := entry.sparseOutputs[uint32(outputIndex)] 657 if out.spent { 658 continue 659 } 660 661 offset += putCompressedTxOut(serialized[offset:], 662 uint64(out.amount), out.pkScript, entry.version, 663 out.compressed) 664 } 665 666 return serialized, nil 667 } 668 669 // deserializeUtxoEntry decodes a utxo entry from the passed serialized byte 670 // slice into a new UtxoEntry using a format that is suitable for long-term 671 // storage. The format is described in detail above. 672 func deserializeUtxoEntry(serialized []byte) (*UtxoEntry, error) { 673 // Deserialize the version. 674 version, bytesRead := deserializeVLQ(serialized) 675 offset := bytesRead 676 if offset >= len(serialized) { 677 return nil, errDeserialize("unexpected end of data after version") 678 } 679 680 // Deserialize the block height. 681 blockHeight, bytesRead := deserializeVLQ(serialized[offset:]) 682 offset += bytesRead 683 if offset >= len(serialized) { 684 return nil, errDeserialize("unexpected end of data after height") 685 } 686 687 // Deserialize the header code. 688 code, bytesRead := deserializeVLQ(serialized[offset:]) 689 offset += bytesRead 690 if offset >= len(serialized) { 691 return nil, errDeserialize("unexpected end of data after header") 692 } 693 694 // Decode the header code. 695 // 696 // Bit 0 indicates whether the containing transaction is a coinbase. 697 // Bit 1 indicates output 0 is unspent. 698 // Bit 2 indicates output 1 is unspent. 699 // Bits 3-x encodes the number of non-zero unspentness bitmap bytes that 700 // follow. When both output 0 and 1 are spent, it encodes N-1. 701 isCoinBase := code&0x01 != 0 702 output0Unspent := code&0x02 != 0 703 output1Unspent := code&0x04 != 0 704 numBitmapBytes := code >> 3 705 if !output0Unspent && !output1Unspent { 706 numBitmapBytes++ 707 } 708 709 // Ensure there are enough bytes left to deserialize the unspentness 710 // bitmap. 711 if uint64(len(serialized[offset:])) < numBitmapBytes { 712 return nil, errDeserialize("unexpected end of data for " + 713 "unspentness bitmap") 714 } 715 716 // Create a new utxo entry with the details deserialized above to house 717 // all of the utxos. 718 entry := newUtxoEntry(int32(version), isCoinBase, int32(blockHeight)) 719 720 // Add sparse output for unspent outputs 0 and 1 as needed based on the 721 // details provided by the header code. 722 var outputIndexes []uint32 723 if output0Unspent { 724 outputIndexes = append(outputIndexes, 0) 725 } 726 if output1Unspent { 727 outputIndexes = append(outputIndexes, 1) 728 } 729 730 // Decode the unspentness bitmap adding a sparse output for each unspent 731 // output. 732 for i := uint32(0); i < uint32(numBitmapBytes); i++ { 733 unspentBits := serialized[offset] 734 for j := uint32(0); j < 8; j++ { 735 if unspentBits&0x01 != 0 { 736 // The first 2 outputs are encoded via the 737 // header code, so adjust the output number 738 // accordingly. 739 outputNum := 2 + i*8 + j 740 outputIndexes = append(outputIndexes, outputNum) 741 } 742 unspentBits >>= 1 743 } 744 offset++ 745 } 746 747 // Decode and add all of the utxos. 748 for i, outputIndex := range outputIndexes { 749 // Decode the next utxo. The script and amount fields of the 750 // utxo output are left compressed so decompression can be 751 // avoided on those that are not accessed. This is done since 752 // it is quite common for a redeeming transaction to only 753 // reference a single utxo from a referenced transaction. 754 compAmount, compScript, bytesRead, err := decodeCompressedTxOut( 755 serialized[offset:], int32(version)) 756 if err != nil { 757 return nil, errDeserialize(fmt.Sprintf("unable to "+ 758 "decode utxo at index %d: %v", i, err)) 759 } 760 offset += bytesRead 761 762 entry.sparseOutputs[outputIndex] = &utxoOutput{ 763 spent: false, 764 compressed: true, 765 pkScript: compScript, 766 amount: int64(compAmount), 767 } 768 } 769 770 return entry, nil 771 } 772 773 // dbFetchUtxoEntry uses an existing database transaction to fetch all unspent 774 // outputs for the provided Bitcoin transaction hash from the utxo set. 775 // 776 // When there is no entry for the provided hash, nil will be returned for the 777 // both the entry and the error. 778 func dbFetchUtxoEntry(dbTx database.Tx, hash *chainhash.Hash) (*UtxoEntry, error) { 779 // Fetch the unspent transaction output information for the passed 780 // transaction hash. Return now when there is no entry. 781 utxoBucket := dbTx.Metadata().Bucket(utxoSetBucketName) 782 serializedUtxo := utxoBucket.Get(hash[:]) 783 if serializedUtxo == nil { 784 return nil, nil 785 } 786 787 // A non-nil zero-length entry means there is an entry in the database 788 // for a fully spent transaction which should never be the case. 789 if len(serializedUtxo) == 0 { 790 return nil, AssertError(fmt.Sprintf("database contains entry "+ 791 "for fully spent tx %v", hash)) 792 } 793 794 // Deserialize the utxo entry and return it. 795 entry, err := deserializeUtxoEntry(serializedUtxo) 796 if err != nil { 797 // Ensure any deserialization errors are returned as database 798 // corruption errors. 799 if isDeserializeErr(err) { 800 return nil, database.Error{ 801 ErrorCode: database.ErrCorruption, 802 Description: fmt.Sprintf("corrupt utxo entry "+ 803 "for %v: %v", hash, err), 804 } 805 } 806 807 return nil, err 808 } 809 810 return entry, nil 811 } 812 813 // dbPutUtxoView uses an existing database transaction to update the utxo set 814 // in the database based on the provided utxo view contents and state. In 815 // particular, only the entries that have been marked as modified are written 816 // to the database. 817 func dbPutUtxoView(dbTx database.Tx, view *UtxoViewpoint) error { 818 utxoBucket := dbTx.Metadata().Bucket(utxoSetBucketName) 819 for txHashIter, entry := range view.entries { 820 // No need to update the database if the entry was not modified. 821 if entry == nil || !entry.modified { 822 continue 823 } 824 825 // Serialize the utxo entry without any entries that have been 826 // spent. 827 serialized, err := serializeUtxoEntry(entry) 828 if err != nil { 829 return err 830 } 831 832 // Make a copy of the hash because the iterator changes on each 833 // loop iteration and thus slicing it directly would cause the 834 // data to change out from under the put/delete funcs below. 835 txHash := txHashIter 836 837 // Remove the utxo entry if it is now fully spent. 838 if serialized == nil { 839 if err := utxoBucket.Delete(txHash[:]); err != nil { 840 return err 841 } 842 843 continue 844 } 845 846 // At this point the utxo entry is not fully spent, so store its 847 // serialization in the database. 848 err = utxoBucket.Put(txHash[:], serialized) 849 if err != nil { 850 return err 851 } 852 } 853 854 return nil 855 } 856 857 // ----------------------------------------------------------------------------- 858 // The block index consists of two buckets with an entry for every block in the 859 // main chain. One bucket is for the hash to height mapping and the other is 860 // for the height to hash mapping. 861 // 862 // The serialized format for values in the hash to height bucket is: 863 // <height> 864 // 865 // Field Type Size 866 // height uint32 4 bytes 867 // 868 // The serialized format for values in the height to hash bucket is: 869 // <hash> 870 // 871 // Field Type Size 872 // hash chainhash.Hash chainhash.HashSize 873 // ----------------------------------------------------------------------------- 874 875 // dbPutBlockIndex uses an existing database transaction to update or add the 876 // block index entries for the hash to height and height to hash mappings for 877 // the provided values. 878 func dbPutBlockIndex(dbTx database.Tx, hash *chainhash.Hash, height int32) error { 879 // Serialize the height for use in the index entries. 880 var serializedHeight [4]byte 881 byteOrder.PutUint32(serializedHeight[:], uint32(height)) 882 883 // Add the block hash to height mapping to the index. 884 meta := dbTx.Metadata() 885 hashIndex := meta.Bucket(hashIndexBucketName) 886 if err := hashIndex.Put(hash[:], serializedHeight[:]); err != nil { 887 return err 888 } 889 890 // Add the block height to hash mapping to the index. 891 heightIndex := meta.Bucket(heightIndexBucketName) 892 return heightIndex.Put(serializedHeight[:], hash[:]) 893 } 894 895 // dbRemoveBlockIndex uses an existing database transaction remove block index 896 // entries from the hash to height and height to hash mappings for the provided 897 // values. 898 func dbRemoveBlockIndex(dbTx database.Tx, hash *chainhash.Hash, height int32) error { 899 // Remove the block hash to height mapping. 900 meta := dbTx.Metadata() 901 hashIndex := meta.Bucket(hashIndexBucketName) 902 if err := hashIndex.Delete(hash[:]); err != nil { 903 return err 904 } 905 906 // Remove the block height to hash mapping. 907 var serializedHeight [4]byte 908 byteOrder.PutUint32(serializedHeight[:], uint32(height)) 909 heightIndex := meta.Bucket(heightIndexBucketName) 910 return heightIndex.Delete(serializedHeight[:]) 911 } 912 913 // dbFetchHeightByHash uses an existing database transaction to retrieve the 914 // height for the provided hash from the index. 915 func dbFetchHeightByHash(dbTx database.Tx, hash *chainhash.Hash) (int32, error) { 916 meta := dbTx.Metadata() 917 hashIndex := meta.Bucket(hashIndexBucketName) 918 serializedHeight := hashIndex.Get(hash[:]) 919 if serializedHeight == nil { 920 str := fmt.Sprintf("block %s is not in the main chain", hash) 921 return 0, errNotInMainChain(str) 922 } 923 924 return int32(byteOrder.Uint32(serializedHeight)), nil 925 } 926 927 // dbFetchHashByHeight uses an existing database transaction to retrieve the 928 // hash for the provided height from the index. 929 func dbFetchHashByHeight(dbTx database.Tx, height int32) (*chainhash.Hash, error) { 930 var serializedHeight [4]byte 931 byteOrder.PutUint32(serializedHeight[:], uint32(height)) 932 933 meta := dbTx.Metadata() 934 heightIndex := meta.Bucket(heightIndexBucketName) 935 hashBytes := heightIndex.Get(serializedHeight[:]) 936 if hashBytes == nil { 937 str := fmt.Sprintf("no block at height %d exists", height) 938 return nil, errNotInMainChain(str) 939 } 940 941 var hash chainhash.Hash 942 copy(hash[:], hashBytes) 943 return &hash, nil 944 } 945 946 // ----------------------------------------------------------------------------- 947 // The best chain state consists of the best block hash and height, the total 948 // number of transactions up to and including those in the best block, and the 949 // accumulated work sum up to and including the best block. 950 // 951 // The serialized format is: 952 // 953 // <block hash><block height><total txns><work sum length><work sum> 954 // 955 // Field Type Size 956 // block hash chainhash.Hash chainhash.HashSize 957 // block height uint32 4 bytes 958 // total txns uint64 8 bytes 959 // work sum length uint32 4 bytes 960 // work sum big.Int work sum length 961 // ----------------------------------------------------------------------------- 962 963 // bestChainState represents the data to be stored the database for the current 964 // best chain state. 965 type bestChainState struct { 966 hash chainhash.Hash 967 height uint32 968 totalTxns uint64 969 workSum *big.Int 970 } 971 972 // serializeBestChainState returns the serialization of the passed block best 973 // chain state. This is data to be stored in the chain state bucket. 974 func serializeBestChainState(state bestChainState) []byte { 975 // Calculate the full size needed to serialize the chain state. 976 workSumBytes := state.workSum.Bytes() 977 workSumBytesLen := uint32(len(workSumBytes)) 978 serializedLen := chainhash.HashSize + 4 + 8 + 4 + workSumBytesLen 979 980 // Serialize the chain state. 981 serializedData := make([]byte, serializedLen) 982 copy(serializedData[0:chainhash.HashSize], state.hash[:]) 983 offset := uint32(chainhash.HashSize) 984 byteOrder.PutUint32(serializedData[offset:], state.height) 985 offset += 4 986 byteOrder.PutUint64(serializedData[offset:], state.totalTxns) 987 offset += 8 988 byteOrder.PutUint32(serializedData[offset:], workSumBytesLen) 989 offset += 4 990 copy(serializedData[offset:], workSumBytes) 991 return serializedData[:] 992 } 993 994 // deserializeBestChainState deserializes the passed serialized best chain 995 // state. This is data stored in the chain state bucket and is updated after 996 // every block is connected or disconnected form the main chain. 997 // block. 998 func deserializeBestChainState(serializedData []byte) (bestChainState, error) { 999 // Ensure the serialized data has enough bytes to properly deserialize 1000 // the hash, height, total transactions, and work sum length. 1001 if len(serializedData) < chainhash.HashSize+16 { 1002 return bestChainState{}, database.Error{ 1003 ErrorCode: database.ErrCorruption, 1004 Description: "corrupt best chain state", 1005 } 1006 } 1007 1008 state := bestChainState{} 1009 copy(state.hash[:], serializedData[0:chainhash.HashSize]) 1010 offset := uint32(chainhash.HashSize) 1011 state.height = byteOrder.Uint32(serializedData[offset : offset+4]) 1012 offset += 4 1013 state.totalTxns = byteOrder.Uint64(serializedData[offset : offset+8]) 1014 offset += 8 1015 workSumBytesLen := byteOrder.Uint32(serializedData[offset : offset+4]) 1016 offset += 4 1017 1018 // Ensure the serialized data has enough bytes to deserialize the work 1019 // sum. 1020 if uint32(len(serializedData[offset:])) < workSumBytesLen { 1021 return bestChainState{}, database.Error{ 1022 ErrorCode: database.ErrCorruption, 1023 Description: "corrupt best chain state", 1024 } 1025 } 1026 workSumBytes := serializedData[offset : offset+workSumBytesLen] 1027 state.workSum = new(big.Int).SetBytes(workSumBytes) 1028 1029 return state, nil 1030 } 1031 1032 // dbPutBestState uses an existing database transaction to update the best chain 1033 // state with the given parameters. 1034 func dbPutBestState(dbTx database.Tx, snapshot *BestState, workSum *big.Int) error { 1035 // Serialize the current best chain state. 1036 serializedData := serializeBestChainState(bestChainState{ 1037 hash: *snapshot.Hash, 1038 height: uint32(snapshot.Height), 1039 totalTxns: snapshot.TotalTxns, 1040 workSum: workSum, 1041 }) 1042 1043 // Store the current best chain state into the database. 1044 return dbTx.Metadata().Put(chainStateKeyName, serializedData) 1045 } 1046 1047 // createChainState initializes both the database and the chain state to the 1048 // genesis block. This includes creating the necessary buckets and inserting 1049 // the genesis block, so it must only be called on an uninitialized database. 1050 func (b *BlockChain) createChainState() error { 1051 // Create a new node from the genesis block and set it as the best node. 1052 genesisBlock := btcutil.NewBlock(b.chainParams.GenesisBlock) 1053 header := &genesisBlock.MsgBlock().Header 1054 node := newBlockNode(header, genesisBlock.Hash(), 0) 1055 node.inMainChain = true 1056 b.bestNode = node 1057 1058 // Add the new node to the index which is used for faster lookups. 1059 b.index[*node.hash] = node 1060 1061 // Initialize the state related to the best block. Since it is the 1062 // genesis block, use its timestamp for the median time. 1063 numTxns := uint64(len(genesisBlock.MsgBlock().Transactions)) 1064 blockSize := uint64(genesisBlock.MsgBlock().SerializeSize()) 1065 blockWeight := uint64(GetBlockWeight(genesisBlock)) 1066 b.stateSnapshot = newBestState(b.bestNode, blockSize, blockWeight, 1067 numTxns, numTxns, b.bestNode.timestamp) 1068 1069 // Create the initial the database chain state including creating the 1070 // necessary index buckets and inserting the genesis block. 1071 err := b.db.Update(func(dbTx database.Tx) error { 1072 // Create the bucket that houses the chain block hash to height 1073 // index. 1074 meta := dbTx.Metadata() 1075 _, err := meta.CreateBucket(hashIndexBucketName) 1076 if err != nil { 1077 return err 1078 } 1079 1080 // Create the bucket that houses the chain block height to hash 1081 // index. 1082 _, err = meta.CreateBucket(heightIndexBucketName) 1083 if err != nil { 1084 return err 1085 } 1086 1087 // Create the bucket that houses the spend journal data. 1088 _, err = meta.CreateBucket(spendJournalBucketName) 1089 if err != nil { 1090 return err 1091 } 1092 1093 // Create the bucket that houses the utxo set. Note that the 1094 // genesis block coinbase transaction is intentionally not 1095 // inserted here since it is not spendable by consensus rules. 1096 _, err = meta.CreateBucket(utxoSetBucketName) 1097 if err != nil { 1098 return err 1099 } 1100 1101 // Add the genesis block hash to height and height to hash 1102 // mappings to the index. 1103 err = dbPutBlockIndex(dbTx, b.bestNode.hash, b.bestNode.height) 1104 if err != nil { 1105 return err 1106 } 1107 1108 // Store the current best chain state into the database. 1109 err = dbPutBestState(dbTx, b.stateSnapshot, b.bestNode.workSum) 1110 if err != nil { 1111 return err 1112 } 1113 1114 // Store the genesis block into the database. 1115 return dbTx.StoreBlock(genesisBlock) 1116 }) 1117 return err 1118 } 1119 1120 // initChainState attempts to load and initialize the chain state from the 1121 // database. When the db does not yet contain any chain state, both it and the 1122 // chain state are initialized to the genesis block. 1123 func (b *BlockChain) initChainState() error { 1124 // Attempt to load the chain state from the database. 1125 var isStateInitialized bool 1126 err := b.db.View(func(dbTx database.Tx) error { 1127 // Fetch the stored chain state from the database metadata. 1128 // When it doesn't exist, it means the database hasn't been 1129 // initialized for use with chain yet, so break out now to allow 1130 // that to happen under a writable database transaction. 1131 serializedData := dbTx.Metadata().Get(chainStateKeyName) 1132 if serializedData == nil { 1133 return nil 1134 } 1135 state, err := deserializeBestChainState(serializedData) 1136 if err != nil { 1137 return err 1138 } 1139 1140 // Load the raw block bytes for the best block. 1141 blockBytes, err := dbTx.FetchBlock(&state.hash) 1142 if err != nil { 1143 return err 1144 } 1145 var block wire.MsgBlock 1146 err = block.Deserialize(bytes.NewReader(blockBytes)) 1147 if err != nil { 1148 return err 1149 } 1150 1151 // Create a new node and set it as the best node. The preceding 1152 // nodes will be loaded on demand as needed. 1153 header := &block.Header 1154 node := newBlockNode(header, &state.hash, int32(state.height)) 1155 node.inMainChain = true 1156 node.workSum = state.workSum 1157 b.bestNode = node 1158 1159 // Add the new node to the indices for faster lookups. 1160 prevHash := node.parentHash 1161 b.index[*node.hash] = node 1162 b.depNodes[*prevHash] = append(b.depNodes[*prevHash], node) 1163 1164 // Calculate the median time for the block. 1165 medianTime, err := b.calcPastMedianTime(node) 1166 if err != nil { 1167 return err 1168 } 1169 1170 // Initialize the state related to the best block. 1171 blockSize := uint64(len(blockBytes)) 1172 blockWeight := uint64(GetBlockWeight(btcutil.NewBlock(&block))) 1173 numTxns := uint64(len(block.Transactions)) 1174 b.stateSnapshot = newBestState(b.bestNode, blockSize, blockWeight, 1175 numTxns, state.totalTxns, medianTime) 1176 isStateInitialized = true 1177 1178 return nil 1179 }) 1180 if err != nil { 1181 return err 1182 } 1183 1184 // There is nothing more to do if the chain state was initialized. 1185 if isStateInitialized { 1186 return nil 1187 } 1188 1189 // At this point the database has not already been initialized, so 1190 // initialize both it and the chain state to the genesis block. 1191 return b.createChainState() 1192 } 1193 1194 // dbFetchHeaderByHash uses an existing database transaction to retrieve the 1195 // block header for the provided hash. 1196 func dbFetchHeaderByHash(dbTx database.Tx, hash *chainhash.Hash) (*wire.BlockHeader, error) { 1197 headerBytes, err := dbTx.FetchBlockHeader(hash) 1198 if err != nil { 1199 return nil, err 1200 } 1201 1202 var header wire.BlockHeader 1203 err = header.Deserialize(bytes.NewReader(headerBytes)) 1204 if err != nil { 1205 return nil, err 1206 } 1207 1208 return &header, nil 1209 } 1210 1211 // dbFetchHeaderByHeight uses an existing database transaction to retrieve the 1212 // block header for the provided height. 1213 func dbFetchHeaderByHeight(dbTx database.Tx, height int32) (*wire.BlockHeader, error) { 1214 hash, err := dbFetchHashByHeight(dbTx, height) 1215 if err != nil { 1216 return nil, err 1217 } 1218 1219 return dbFetchHeaderByHash(dbTx, hash) 1220 } 1221 1222 // dbFetchBlockByHash uses an existing database transaction to retrieve the raw 1223 // block for the provided hash, deserialize it, retrieve the appropriate height 1224 // from the index, and return a btcutil.Block with the height set. 1225 func dbFetchBlockByHash(dbTx database.Tx, hash *chainhash.Hash) (*btcutil.Block, error) { 1226 // First find the height associated with the provided hash in the index. 1227 blockHeight, err := dbFetchHeightByHash(dbTx, hash) 1228 if err != nil { 1229 return nil, err 1230 } 1231 1232 // Load the raw block bytes from the database. 1233 blockBytes, err := dbTx.FetchBlock(hash) 1234 if err != nil { 1235 return nil, err 1236 } 1237 1238 // Create the encapsulated block and set the height appropriately. 1239 block, err := btcutil.NewBlockFromBytes(blockBytes) 1240 if err != nil { 1241 return nil, err 1242 } 1243 block.SetHeight(blockHeight) 1244 1245 return block, nil 1246 } 1247 1248 // dbFetchBlockByHeight uses an existing database transaction to retrieve the 1249 // raw block for the provided height, deserialize it, and return a btcutil.Block 1250 // with the height set. 1251 func dbFetchBlockByHeight(dbTx database.Tx, height int32) (*btcutil.Block, error) { 1252 // First find the hash associated with the provided height in the index. 1253 hash, err := dbFetchHashByHeight(dbTx, height) 1254 if err != nil { 1255 return nil, err 1256 } 1257 1258 // Load the raw block bytes from the database. 1259 blockBytes, err := dbTx.FetchBlock(hash) 1260 if err != nil { 1261 return nil, err 1262 } 1263 1264 // Create the encapsulated block and set the height appropriately. 1265 block, err := btcutil.NewBlockFromBytes(blockBytes) 1266 if err != nil { 1267 return nil, err 1268 } 1269 block.SetHeight(height) 1270 1271 return block, nil 1272 } 1273 1274 // dbMainChainHasBlock uses an existing database transaction to return whether 1275 // or not the main chain contains the block identified by the provided hash. 1276 func dbMainChainHasBlock(dbTx database.Tx, hash *chainhash.Hash) bool { 1277 hashIndex := dbTx.Metadata().Bucket(hashIndexBucketName) 1278 return hashIndex.Get(hash[:]) != nil 1279 } 1280 1281 // MainChainHasBlock returns whether or not the block with the given hash is in 1282 // the main chain. 1283 // 1284 // This function is safe for concurrent access. 1285 func (b *BlockChain) MainChainHasBlock(hash *chainhash.Hash) (bool, error) { 1286 var exists bool 1287 err := b.db.View(func(dbTx database.Tx) error { 1288 exists = dbMainChainHasBlock(dbTx, hash) 1289 return nil 1290 }) 1291 return exists, err 1292 } 1293 1294 // BlockHeightByHash returns the height of the block with the given hash in the 1295 // main chain. 1296 // 1297 // This function is safe for concurrent access. 1298 func (b *BlockChain) BlockHeightByHash(hash *chainhash.Hash) (int32, error) { 1299 var height int32 1300 err := b.db.View(func(dbTx database.Tx) error { 1301 var err error 1302 height, err = dbFetchHeightByHash(dbTx, hash) 1303 return err 1304 }) 1305 return height, err 1306 } 1307 1308 // BlockHashByHeight returns the hash of the block at the given height in the 1309 // main chain. 1310 // 1311 // This function is safe for concurrent access. 1312 func (b *BlockChain) BlockHashByHeight(blockHeight int32) (*chainhash.Hash, error) { 1313 var hash *chainhash.Hash 1314 err := b.db.View(func(dbTx database.Tx) error { 1315 var err error 1316 hash, err = dbFetchHashByHeight(dbTx, blockHeight) 1317 return err 1318 }) 1319 return hash, err 1320 } 1321 1322 // BlockByHeight returns the block at the given height in the main chain. 1323 // 1324 // This function is safe for concurrent access. 1325 func (b *BlockChain) BlockByHeight(blockHeight int32) (*btcutil.Block, error) { 1326 var block *btcutil.Block 1327 err := b.db.View(func(dbTx database.Tx) error { 1328 var err error 1329 block, err = dbFetchBlockByHeight(dbTx, blockHeight) 1330 return err 1331 }) 1332 return block, err 1333 } 1334 1335 // BlockByHash returns the block from the main chain with the given hash with 1336 // the appropriate chain height set. 1337 // 1338 // This function is safe for concurrent access. 1339 func (b *BlockChain) BlockByHash(hash *chainhash.Hash) (*btcutil.Block, error) { 1340 var block *btcutil.Block 1341 err := b.db.View(func(dbTx database.Tx) error { 1342 var err error 1343 block, err = dbFetchBlockByHash(dbTx, hash) 1344 return err 1345 }) 1346 return block, err 1347 } 1348 1349 // HeightRange returns a range of block hashes for the given start and end 1350 // heights. It is inclusive of the start height and exclusive of the end 1351 // height. The end height will be limited to the current main chain height. 1352 // 1353 // This function is safe for concurrent access. 1354 func (b *BlockChain) HeightRange(startHeight, endHeight int32) ([]chainhash.Hash, error) { 1355 // Ensure requested heights are sane. 1356 if startHeight < 0 { 1357 return nil, fmt.Errorf("start height of fetch range must not "+ 1358 "be less than zero - got %d", startHeight) 1359 } 1360 if endHeight < startHeight { 1361 return nil, fmt.Errorf("end height of fetch range must not "+ 1362 "be less than the start height - got start %d, end %d", 1363 startHeight, endHeight) 1364 } 1365 1366 // There is nothing to do when the start and end heights are the same, 1367 // so return now to avoid the chain lock and a database transaction. 1368 if startHeight == endHeight { 1369 return nil, nil 1370 } 1371 1372 // Grab a lock on the chain to prevent it from changing due to a reorg 1373 // while building the hashes. 1374 b.chainLock.RLock() 1375 defer b.chainLock.RUnlock() 1376 1377 // When the requested start height is after the most recent best chain 1378 // height, there is nothing to do. 1379 latestHeight := b.bestNode.height 1380 if startHeight > latestHeight { 1381 return nil, nil 1382 } 1383 1384 // Limit the ending height to the latest height of the chain. 1385 if endHeight > latestHeight+1 { 1386 endHeight = latestHeight + 1 1387 } 1388 1389 // Fetch as many as are available within the specified range. 1390 var hashList []chainhash.Hash 1391 err := b.db.View(func(dbTx database.Tx) error { 1392 hashes := make([]chainhash.Hash, 0, endHeight-startHeight) 1393 for i := startHeight; i < endHeight; i++ { 1394 hash, err := dbFetchHashByHeight(dbTx, i) 1395 if err != nil { 1396 return err 1397 } 1398 hashes = append(hashes, *hash) 1399 } 1400 1401 // Set the list to be returned to the constructed list. 1402 hashList = hashes 1403 return nil 1404 }) 1405 return hashList, err 1406 }