github.com/BlockABC/godash@v0.0.0-20191112120524-f4aa3a32c566/blockchain/chainio.go (about) 1 // Copyright (c) 2015-2016 The btcsuite developers 2 // Copyright (c) 2016 The Dash developers 3 // Use of this source code is governed by an ISC 4 // license that can be found in the LICENSE file. 5 6 package blockchain 7 8 import ( 9 "bytes" 10 "encoding/binary" 11 "fmt" 12 "math/big" 13 "sort" 14 15 "github.com/BlockABC/godash/database" 16 "github.com/BlockABC/godash/wire" 17 "github.com/BlockABC/godashutil" 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[wire.ShaHash]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 *godashutil.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.Sha()[:]) 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.Sha(), 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 *wire.ShaHash, 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 *wire.ShaHash) 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 *wire.ShaHash) (*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 wire.ShaHash wire.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 *wire.ShaHash, 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 *wire.ShaHash, 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 *wire.ShaHash) (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) (*wire.ShaHash, 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 wire.ShaHash 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 wire.ShaHash wire.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 wire.ShaHash 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 := wire.HashSize + 4 + 8 + 4 + workSumBytesLen 979 980 // Serialize the chain state. 981 serializedData := make([]byte, serializedLen) 982 copy(serializedData[0:wire.HashSize], state.hash[:]) 983 offset := uint32(wire.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) < wire.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:wire.HashSize]) 1010 offset := uint32(wire.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 := godashutil.NewBlock(b.chainParams.GenesisBlock) 1053 header := &genesisBlock.MsgBlock().Header 1054 node := newBlockNode(header, genesisBlock.Sha(), 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. 1062 numTxns := uint64(len(genesisBlock.MsgBlock().Transactions)) 1063 blockSize := uint64(genesisBlock.MsgBlock().SerializeSize()) 1064 b.stateSnapshot = newBestState(b.bestNode, blockSize, numTxns, numTxns) 1065 1066 // Create the initial the database chain state including creating the 1067 // necessary index buckets and inserting the genesis block. 1068 err := b.db.Update(func(dbTx database.Tx) error { 1069 // Create the bucket that houses the chain block hash to height 1070 // index. 1071 meta := dbTx.Metadata() 1072 _, err := meta.CreateBucket(hashIndexBucketName) 1073 if err != nil { 1074 return err 1075 } 1076 1077 // Create the bucket that houses the chain block height to hash 1078 // index. 1079 _, err = meta.CreateBucket(heightIndexBucketName) 1080 if err != nil { 1081 return err 1082 } 1083 1084 // Create the bucket that houses the spend journal data. 1085 _, err = meta.CreateBucket(spendJournalBucketName) 1086 if err != nil { 1087 return err 1088 } 1089 1090 // Create the bucket that houses the utxo set. Note that the 1091 // genesis block coinbase transaction is intentionally not 1092 // inserted here since it is not spendable by consensus rules. 1093 _, err = meta.CreateBucket(utxoSetBucketName) 1094 if err != nil { 1095 return err 1096 } 1097 1098 // Add the genesis block hash to height and height to hash 1099 // mappings to the index. 1100 err = dbPutBlockIndex(dbTx, b.bestNode.hash, b.bestNode.height) 1101 if err != nil { 1102 return err 1103 } 1104 1105 // Store the current best chain state into the database. 1106 err = dbPutBestState(dbTx, b.stateSnapshot, b.bestNode.workSum) 1107 if err != nil { 1108 return err 1109 } 1110 1111 // Store the genesis block into the database. 1112 return dbTx.StoreBlock(genesisBlock) 1113 }) 1114 return err 1115 } 1116 1117 // initChainState attempts to load and initialize the chain state from the 1118 // database. When the db does not yet contain any chain state, both it and the 1119 // chain state are initialized to the genesis block. 1120 func (b *BlockChain) initChainState() error { 1121 // Attempt to load the chain state from the database. 1122 var isStateInitialized bool 1123 err := b.db.View(func(dbTx database.Tx) error { 1124 // Fetch the stored chain state from the database metadata. 1125 // When it doesn't exist, it means the database hasn't been 1126 // initialized for use with chain yet, so break out now to allow 1127 // that to happen under a writable database transaction. 1128 serializedData := dbTx.Metadata().Get(chainStateKeyName) 1129 if serializedData == nil { 1130 return nil 1131 } 1132 log.Tracef("Serialized chain state: %x", serializedData) 1133 state, err := deserializeBestChainState(serializedData) 1134 if err != nil { 1135 return err 1136 } 1137 1138 // Load the raw block bytes for the best block. 1139 blockBytes, err := dbTx.FetchBlock(&state.hash) 1140 if err != nil { 1141 return err 1142 } 1143 var block wire.MsgBlock 1144 err = block.Deserialize(bytes.NewReader(blockBytes)) 1145 if err != nil { 1146 return err 1147 } 1148 1149 // Create a new node and set it as the best node. The preceding 1150 // nodes will be loaded on demand as needed. 1151 header := &block.Header 1152 node := newBlockNode(header, &state.hash, int32(state.height)) 1153 node.inMainChain = true 1154 node.workSum = state.workSum 1155 b.bestNode = node 1156 1157 // Add the new node to the indices for faster lookups. 1158 prevHash := node.parentHash 1159 b.index[*node.hash] = node 1160 b.depNodes[*prevHash] = append(b.depNodes[*prevHash], node) 1161 1162 // Initialize the state related to the best block. 1163 blockSize := uint64(len(blockBytes)) 1164 numTxns := uint64(len(block.Transactions)) 1165 b.stateSnapshot = newBestState(b.bestNode, blockSize, numTxns, 1166 state.totalTxns) 1167 1168 isStateInitialized = true 1169 return nil 1170 }) 1171 if err != nil { 1172 return err 1173 } 1174 1175 // There is nothing more to do if the chain state was initialized. 1176 if isStateInitialized { 1177 return nil 1178 } 1179 1180 // At this point the database has not already been initialized, so 1181 // initialize both it and the chain state to the genesis block. 1182 return b.createChainState() 1183 } 1184 1185 // dbFetchHeaderByHash uses an existing database transaction to retrieve the 1186 // block header for the provided hash. 1187 func dbFetchHeaderByHash(dbTx database.Tx, hash *wire.ShaHash) (*wire.BlockHeader, error) { 1188 headerBytes, err := dbTx.FetchBlockHeader(hash) 1189 if err != nil { 1190 return nil, err 1191 } 1192 1193 var header wire.BlockHeader 1194 err = header.Deserialize(bytes.NewReader(headerBytes)) 1195 if err != nil { 1196 return nil, err 1197 } 1198 1199 return &header, nil 1200 } 1201 1202 // dbFetchHeaderByHeight uses an existing database transaction to retrieve the 1203 // block header for the provided height. 1204 func dbFetchHeaderByHeight(dbTx database.Tx, height int32) (*wire.BlockHeader, error) { 1205 hash, err := dbFetchHashByHeight(dbTx, height) 1206 if err != nil { 1207 return nil, err 1208 } 1209 1210 return dbFetchHeaderByHash(dbTx, hash) 1211 } 1212 1213 // dbFetchBlockByHash uses an existing database transaction to retrieve the raw 1214 // block for the provided hash, deserialize it, retrieve the appropriate height 1215 // from the index, and return a godashutil.Block with the height set. 1216 func dbFetchBlockByHash(dbTx database.Tx, hash *wire.ShaHash) (*godashutil.Block, error) { 1217 // First find the height associated with the provided hash in the index. 1218 blockHeight, err := dbFetchHeightByHash(dbTx, hash) 1219 if err != nil { 1220 return nil, err 1221 } 1222 1223 // Load the raw block bytes from the database. 1224 blockBytes, err := dbTx.FetchBlock(hash) 1225 if err != nil { 1226 return nil, err 1227 } 1228 1229 // Create the encapsulated block and set the height appropriately. 1230 block, err := godashutil.NewBlockFromBytes(blockBytes) 1231 if err != nil { 1232 return nil, err 1233 } 1234 block.SetHeight(blockHeight) 1235 1236 return block, nil 1237 } 1238 1239 // dbFetchBlockByHeight uses an existing database transaction to retrieve the 1240 // raw block for the provided height, deserialize it, and return a godashutil.Block 1241 // with the height set. 1242 func dbFetchBlockByHeight(dbTx database.Tx, height int32) (*godashutil.Block, error) { 1243 // First find the hash associated with the provided height in the index. 1244 hash, err := dbFetchHashByHeight(dbTx, height) 1245 if err != nil { 1246 return nil, err 1247 } 1248 1249 // Load the raw block bytes from the database. 1250 blockBytes, err := dbTx.FetchBlock(hash) 1251 if err != nil { 1252 return nil, err 1253 } 1254 1255 // Create the encapsulated block and set the height appropriately. 1256 block, err := godashutil.NewBlockFromBytes(blockBytes) 1257 if err != nil { 1258 return nil, err 1259 } 1260 block.SetHeight(height) 1261 1262 return block, nil 1263 } 1264 1265 // dbMainChainHasBlock uses an existing database transaction to return whether 1266 // or not the main chain contains the block identified by the provided hash. 1267 func dbMainChainHasBlock(dbTx database.Tx, hash *wire.ShaHash) bool { 1268 hashIndex := dbTx.Metadata().Bucket(hashIndexBucketName) 1269 return hashIndex.Get(hash[:]) != nil 1270 } 1271 1272 // MainChainHasBlock returns whether or not the block with the given hash is in 1273 // the main chain. 1274 // 1275 // This function is safe for concurrent access. 1276 func (b *BlockChain) MainChainHasBlock(hash *wire.ShaHash) (bool, error) { 1277 var exists bool 1278 err := b.db.View(func(dbTx database.Tx) error { 1279 exists = dbMainChainHasBlock(dbTx, hash) 1280 return nil 1281 }) 1282 return exists, err 1283 } 1284 1285 // BlockHeightByHash returns the height of the block with the given hash in the 1286 // main chain. 1287 // 1288 // This function is safe for concurrent access. 1289 func (b *BlockChain) BlockHeightByHash(hash *wire.ShaHash) (int32, error) { 1290 var height int32 1291 err := b.db.View(func(dbTx database.Tx) error { 1292 var err error 1293 height, err = dbFetchHeightByHash(dbTx, hash) 1294 return err 1295 }) 1296 return height, err 1297 } 1298 1299 // BlockHashByHeight returns the hash of the block at the given height in the 1300 // main chain. 1301 // 1302 // This function is safe for concurrent access. 1303 func (b *BlockChain) BlockHashByHeight(blockHeight int32) (*wire.ShaHash, error) { 1304 var hash *wire.ShaHash 1305 err := b.db.View(func(dbTx database.Tx) error { 1306 var err error 1307 hash, err = dbFetchHashByHeight(dbTx, blockHeight) 1308 return err 1309 }) 1310 return hash, err 1311 } 1312 1313 // BlockByHeight returns the block at the given height in the main chain. 1314 // 1315 // This function is safe for concurrent access. 1316 func (b *BlockChain) BlockByHeight(blockHeight int32) (*godashutil.Block, error) { 1317 var block *godashutil.Block 1318 err := b.db.View(func(dbTx database.Tx) error { 1319 var err error 1320 block, err = dbFetchBlockByHeight(dbTx, blockHeight) 1321 return err 1322 }) 1323 return block, err 1324 } 1325 1326 // BlockByHash returns the block from the main chain with the given hash with 1327 // the appropriate chain height set. 1328 // 1329 // This function is safe for concurrent access. 1330 func (b *BlockChain) BlockByHash(hash *wire.ShaHash) (*godashutil.Block, error) { 1331 var block *godashutil.Block 1332 err := b.db.View(func(dbTx database.Tx) error { 1333 var err error 1334 block, err = dbFetchBlockByHash(dbTx, hash) 1335 return err 1336 }) 1337 return block, err 1338 } 1339 1340 // HeightRange returns a range of block hashes for the given start and end 1341 // heights. It is inclusive of the start height and exclusive of the end 1342 // height. The end height will be limited to the current main chain height. 1343 // 1344 // This function is safe for concurrent access. 1345 func (b *BlockChain) HeightRange(startHeight, endHeight int32) ([]wire.ShaHash, error) { 1346 // Ensure requested heights are sane. 1347 if startHeight < 0 { 1348 return nil, fmt.Errorf("start height of fetch range must not "+ 1349 "be less than zero - got %d", startHeight) 1350 } 1351 if endHeight < startHeight { 1352 return nil, fmt.Errorf("end height of fetch range must not "+ 1353 "be less than the start height - got start %d, end %d", 1354 startHeight, endHeight) 1355 } 1356 1357 // There is nothing to do when the start and end heights are the same, 1358 // so return now to avoid the chain lock and a database transaction. 1359 if startHeight == endHeight { 1360 return nil, nil 1361 } 1362 1363 // Grab a lock on the chain to prevent it from changing due to a reorg 1364 // while building the hashes. 1365 b.chainLock.RLock() 1366 defer b.chainLock.RUnlock() 1367 1368 // When the requested start height is after the most recent best chain 1369 // height, there is nothing to do. 1370 latestHeight := b.bestNode.height 1371 if startHeight > latestHeight { 1372 return nil, nil 1373 } 1374 1375 // Limit the ending height to the latest height of the chain. 1376 if endHeight > latestHeight+1 { 1377 endHeight = latestHeight + 1 1378 } 1379 1380 // Fetch as many as are available within the specified range. 1381 var hashList []wire.ShaHash 1382 err := b.db.View(func(dbTx database.Tx) error { 1383 hashes := make([]wire.ShaHash, 0, endHeight-startHeight) 1384 for i := startHeight; i < endHeight; i++ { 1385 hash, err := dbFetchHashByHeight(dbTx, i) 1386 if err != nil { 1387 return err 1388 } 1389 hashes = append(hashes, *hash) 1390 } 1391 1392 // Set the list to be returned to the constructed list. 1393 hashList = hashes 1394 return nil 1395 }) 1396 return hashList, err 1397 }