github.com/dashpay/godash@v0.0.0-20160726055534-e038a21e0e3d/blockchain/indexers/addrindex.go (about) 1 // Copyright (c) 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 indexers 7 8 import ( 9 "errors" 10 "fmt" 11 "sync" 12 13 "github.com/dashpay/godash/blockchain" 14 "github.com/dashpay/godash/chaincfg" 15 "github.com/dashpay/godash/database" 16 "github.com/dashpay/godash/txscript" 17 "github.com/dashpay/godash/wire" 18 "github.com/dashpay/godashutil" 19 ) 20 21 const ( 22 // addrIndexName is the human-readable name for the index. 23 addrIndexName = "address index" 24 25 // level0MaxEntries is the maximum number of transactions that are 26 // stored in level 0 of an address index entry. Subsequent levels store 27 // 2^n * level0MaxEntries entries, or in words, double the maximum of 28 // the previous level. 29 level0MaxEntries = 8 30 31 // addrKeySize is the number of bytes an address key consumes in the 32 // index. It consists of 1 byte address type + 20 bytes hash160. 33 addrKeySize = 1 + 20 34 35 // levelKeySize is the number of bytes a level key in the address index 36 // consumes. It consists of the address key + 1 byte for the level. 37 levelKeySize = addrKeySize + 1 38 39 // levelOffset is the offset in the level key which identifes the level. 40 levelOffset = levelKeySize - 1 41 42 // addrKeyTypePubKeyHash is the address type in an address key which 43 // represents both a pay-to-pubkey-hash and a pay-to-pubkey address. 44 // This is done because both are identical for the purposes of the 45 // address index. 46 addrKeyTypePubKeyHash = 0 47 48 // addrKeyTypeScriptHash is the address type in an address key which 49 // represents a pay-to-script-hash address. This is necessary because 50 // the hash of a pubkey address might be the same as that of a script 51 // hash. 52 addrKeyTypeScriptHash = 1 53 54 // Size of a transaction entry. It consists of 4 bytes block id + 4 55 // bytes offset + 4 bytes length. 56 txEntrySize = 4 + 4 + 4 57 ) 58 59 var ( 60 // addrIndexKey is the key of the address index and the db bucket used 61 // to house it. 62 addrIndexKey = []byte("txbyaddridx") 63 64 // errUnsupportedAddressType is an error that is used to signal an 65 // unsupported address type has been used. 66 errUnsupportedAddressType = errors.New("address type is not supported " + 67 "by the address index") 68 ) 69 70 // ----------------------------------------------------------------------------- 71 // The address index maps addresses referenced in the blockchain to a list of 72 // all the transactions involving that address. Transactions are stored 73 // according to their order of appearance in the blockchain. That is to say 74 // first by block height and then by offset inside the block. It is also 75 // important to note that this implementation requires the transaction index 76 // since it is needed in order to catch up old blocks due to the fact the spent 77 // outputs will already be pruned from the utxo set. 78 // 79 // The approach used to store the index is similar to a log-structured merge 80 // tree (LSM tree) and is thus similar to how leveldb works internally. 81 // 82 // Every address consists of one or more entries identified by a level starting 83 // from 0 where each level holds a maximum number of entries such that each 84 // subsequent level holds double the maximum of the previous one. In equation 85 // form, the number of entries each level holds is 2^n * firstLevelMaxSize. 86 // 87 // New transactions are appended to level 0 until it becomes full at which point 88 // the entire level 0 entry is appended to the level 1 entry and level 0 is 89 // cleared. This process continues until level 1 becomes full at which point it 90 // will be appended to level 2 and cleared and so on. 91 // 92 // The result of this is the lower levels contain newer transactions and the 93 // transactions within each level are ordered from oldest to newest. 94 // 95 // The intent of this approach is to provide a balance between space efficiency 96 // and indexing cost. Storing one entry per transaction would have the lowest 97 // indexing cost, but would waste a lot of space because the same address hash 98 // would be duplicated for every transaction key. On the other hand, storing a 99 // single entry with all transactions would be the most space efficient, but 100 // would cause indexing cost to grow quadratically with the number of 101 // transactions involving the same address. The approach used here provides 102 // logarithmic insertion and retrieval. 103 // 104 // The serialized key format is: 105 // 106 // <addr type><addr hash><level> 107 // 108 // Field Type Size 109 // addr type uint8 1 byte 110 // addr hash hash160 20 bytes 111 // level uint8 1 byte 112 // ----- 113 // Total: 22 bytes 114 // 115 // The serialized value format is: 116 // 117 // [<block id><start offset><tx length>,...] 118 // 119 // Field Type Size 120 // block id uint32 4 bytes 121 // start offset uint32 4 bytes 122 // tx length uint32 4 bytes 123 // ----- 124 // Total: 12 bytes per indexed tx 125 // ----------------------------------------------------------------------------- 126 127 // fetchBlockHashFunc defines a callback function to use in order to convert a 128 // serialized block ID to an associated block hash. 129 type fetchBlockHashFunc func(serializedID []byte) (*wire.ShaHash, error) 130 131 // serializeAddrIndexEntry serializes the provided block id and transaction 132 // location according to the format described in detail above. 133 func serializeAddrIndexEntry(blockID uint32, txLoc wire.TxLoc) []byte { 134 // Serialize the entry. 135 serialized := make([]byte, 12) 136 byteOrder.PutUint32(serialized, blockID) 137 byteOrder.PutUint32(serialized[4:], uint32(txLoc.TxStart)) 138 byteOrder.PutUint32(serialized[8:], uint32(txLoc.TxLen)) 139 return serialized 140 } 141 142 // deserializeAddrIndexEntry decodes the passed serialized byte slice into the 143 // provided region struct according to the format described in detail above and 144 // uses the passed block hash fetching function in order to conver the block ID 145 // to the associated block hash. 146 func deserializeAddrIndexEntry(serialized []byte, region *database.BlockRegion, fetchBlockHash fetchBlockHashFunc) error { 147 // Ensure there are enough bytes to decode. 148 if len(serialized) < txEntrySize { 149 return errDeserialize("unexpected end of data") 150 } 151 152 hash, err := fetchBlockHash(serialized[0:4]) 153 if err != nil { 154 return err 155 } 156 region.Hash = hash 157 region.Offset = byteOrder.Uint32(serialized[4:8]) 158 region.Len = byteOrder.Uint32(serialized[8:12]) 159 return nil 160 } 161 162 // keyForLevel returns the key for a specific address and level in the address 163 // index entry. 164 func keyForLevel(addrKey [addrKeySize]byte, level uint8) [levelKeySize]byte { 165 var key [levelKeySize]byte 166 copy(key[:], addrKey[:]) 167 key[levelOffset] = level 168 return key 169 } 170 171 // dbPutAddrIndexEntry updates the address index to include the provided entry 172 // according to the level-based scheme described in detail above. 173 func dbPutAddrIndexEntry(bucket internalBucket, addrKey [addrKeySize]byte, blockID uint32, txLoc wire.TxLoc) error { 174 // Start with level 0 and its initial max number of entries. 175 curLevel := uint8(0) 176 maxLevelBytes := level0MaxEntries * txEntrySize 177 178 // Simply append the new entry to level 0 and return now when it will 179 // fit. This is the most common path. 180 newData := serializeAddrIndexEntry(blockID, txLoc) 181 level0Key := keyForLevel(addrKey, 0) 182 level0Data := bucket.Get(level0Key[:]) 183 if len(level0Data)+len(newData) <= maxLevelBytes { 184 mergedData := newData 185 if len(level0Data) > 0 { 186 mergedData = make([]byte, len(level0Data)+len(newData)) 187 copy(mergedData, level0Data) 188 copy(mergedData[len(level0Data):], newData) 189 } 190 return bucket.Put(level0Key[:], mergedData) 191 } 192 193 // At this point, level 0 is full, so merge each level into higher 194 // levels as many times as needed to free up level 0. 195 prevLevelData := level0Data 196 for { 197 // Each new level holds twice as much as the previous one. 198 curLevel++ 199 maxLevelBytes *= 2 200 201 // Move to the next level as long as the current level is full. 202 curLevelKey := keyForLevel(addrKey, curLevel) 203 curLevelData := bucket.Get(curLevelKey[:]) 204 if len(curLevelData) == maxLevelBytes { 205 prevLevelData = curLevelData 206 continue 207 } 208 209 // The current level has room for the data in the previous one, 210 // so merge the data from previous level into it. 211 mergedData := prevLevelData 212 if len(curLevelData) > 0 { 213 mergedData = make([]byte, len(curLevelData)+ 214 len(prevLevelData)) 215 copy(mergedData, curLevelData) 216 copy(mergedData[len(curLevelData):], prevLevelData) 217 } 218 err := bucket.Put(curLevelKey[:], mergedData) 219 if err != nil { 220 return err 221 } 222 223 // Move all of the levels before the previous one up a level. 224 for mergeLevel := curLevel - 1; mergeLevel > 0; mergeLevel-- { 225 mergeLevelKey := keyForLevel(addrKey, mergeLevel) 226 prevLevelKey := keyForLevel(addrKey, mergeLevel-1) 227 prevData := bucket.Get(prevLevelKey[:]) 228 err := bucket.Put(mergeLevelKey[:], prevData) 229 if err != nil { 230 return err 231 } 232 } 233 break 234 } 235 236 // Finally, insert the new entry into level 0 now that it is empty. 237 return bucket.Put(level0Key[:], newData) 238 } 239 240 // dbFetchAddrIndexEntries returns block regions for transactions referenced by 241 // the given address key and the number of entries skipped since it could have 242 // been less in the case where there are less total entries than the requested 243 // number of entries to skip. 244 func dbFetchAddrIndexEntries(bucket internalBucket, addrKey [addrKeySize]byte, numToSkip, numRequested uint32, reverse bool, fetchBlockHash fetchBlockHashFunc) ([]database.BlockRegion, uint32, error) { 245 // When the reverse flag is not set, all levels need to be fetched 246 // because numToSkip and numRequested are counted from the oldest 247 // transactions (highest level) and thus the total count is needed. 248 // However, when the reverse flag is set, only enough records to satisfy 249 // the requested amount are needed. 250 var level uint8 251 var serialized []byte 252 for !reverse || len(serialized) < int(numToSkip+numRequested)*txEntrySize { 253 curLevelKey := keyForLevel(addrKey, level) 254 levelData := bucket.Get(curLevelKey[:]) 255 if levelData == nil { 256 // Stop when there are no more levels. 257 break 258 } 259 260 // Higher levels contain older transactions, so prepend them. 261 prepended := make([]byte, len(serialized)+len(levelData)) 262 copy(prepended, levelData) 263 copy(prepended[len(levelData):], serialized) 264 serialized = prepended 265 level++ 266 } 267 268 // When the requested number of entries to skip is larger than the 269 // number available, skip them all and return now with the actual number 270 // skipped. 271 numEntries := uint32(len(serialized) / txEntrySize) 272 if numToSkip >= numEntries { 273 return nil, numEntries, nil 274 } 275 276 // Nothing more to do when there are no requested entries. 277 if numRequested == 0 { 278 return nil, numToSkip, nil 279 } 280 281 // Limit the number to load based on the number of available entries, 282 // the number to skip, and the number requested. 283 numToLoad := numEntries - numToSkip 284 if numToLoad > numRequested { 285 numToLoad = numRequested 286 } 287 288 // Start the offset after all skipped entries and load the calculated 289 // number. 290 results := make([]database.BlockRegion, numToLoad) 291 for i := uint32(0); i < numToLoad; i++ { 292 // Calculate the read offset according to the reverse flag. 293 var offset uint32 294 if reverse { 295 offset = (numEntries - numToSkip - i - 1) * txEntrySize 296 } else { 297 offset = (numToSkip + i) * txEntrySize 298 } 299 300 // Deserialize and populate the result. 301 err := deserializeAddrIndexEntry(serialized[offset:], 302 &results[i], fetchBlockHash) 303 if err != nil { 304 // Ensure any deserialization errors are returned as 305 // database corruption errors. 306 if isDeserializeErr(err) { 307 err = database.Error{ 308 ErrorCode: database.ErrCorruption, 309 Description: fmt.Sprintf("failed to "+ 310 "deserialized address index "+ 311 "for key %x: %v", addrKey, err), 312 } 313 } 314 315 return nil, 0, err 316 } 317 } 318 319 return results, numToSkip, nil 320 } 321 322 // minEntriesToReachLevel returns the minimum number of entries that are 323 // required to reach the given address index level. 324 func minEntriesToReachLevel(level uint8) int { 325 maxEntriesForLevel := level0MaxEntries 326 minRequired := 1 327 for l := uint8(1); l <= level; l++ { 328 minRequired += maxEntriesForLevel 329 maxEntriesForLevel *= 2 330 } 331 return minRequired 332 } 333 334 // maxEntriesForLevel returns the maximum number of entries allowed for the 335 // given address index level. 336 func maxEntriesForLevel(level uint8) int { 337 numEntries := level0MaxEntries 338 for l := level; l > 0; l-- { 339 numEntries *= 2 340 } 341 return numEntries 342 } 343 344 // dbRemoveAddrIndexEntries removes the specified number of entries from from 345 // the address index for the provided key. An assertion error will be returned 346 // if the count exceeds the total number of entries in the index. 347 func dbRemoveAddrIndexEntries(bucket internalBucket, addrKey [addrKeySize]byte, count int) error { 348 // Nothing to do if no entries are being deleted. 349 if count <= 0 { 350 return nil 351 } 352 353 // Make use of a local map to track pending updates and define a closure 354 // to apply it to the database. This is done in order to reduce the 355 // number of database reads and because there is more than one exit 356 // path that needs to apply the updates. 357 pendingUpdates := make(map[uint8][]byte) 358 applyPending := func() error { 359 for level, data := range pendingUpdates { 360 curLevelKey := keyForLevel(addrKey, level) 361 if len(data) == 0 { 362 err := bucket.Delete(curLevelKey[:]) 363 if err != nil { 364 return err 365 } 366 continue 367 } 368 err := bucket.Put(curLevelKey[:], data) 369 if err != nil { 370 return err 371 } 372 } 373 return nil 374 } 375 376 // Loop fowards through the levels while removing entries until the 377 // specified number has been removed. This will potentially result in 378 // entirely empty lower levels which will be backfilled below. 379 var highestLoadedLevel uint8 380 numRemaining := count 381 for level := uint8(0); numRemaining > 0; level++ { 382 // Load the data for the level from the database. 383 curLevelKey := keyForLevel(addrKey, level) 384 curLevelData := bucket.Get(curLevelKey[:]) 385 if len(curLevelData) == 0 && numRemaining > 0 { 386 return AssertError(fmt.Sprintf("dbRemoveAddrIndexEntries "+ 387 "not enough entries for address key %x to "+ 388 "delete %d entries", addrKey, count)) 389 } 390 pendingUpdates[level] = curLevelData 391 highestLoadedLevel = level 392 393 // Delete the entire level as needed. 394 numEntries := len(curLevelData) / txEntrySize 395 if numRemaining >= numEntries { 396 pendingUpdates[level] = nil 397 numRemaining -= numEntries 398 continue 399 } 400 401 // Remove remaining entries to delete from the level. 402 offsetEnd := len(curLevelData) - (numRemaining * txEntrySize) 403 pendingUpdates[level] = curLevelData[:offsetEnd] 404 break 405 } 406 407 // When all elements in level 0 were not removed there is nothing left 408 // to do other than updating the database. 409 if len(pendingUpdates[0]) != 0 { 410 return applyPending() 411 } 412 413 // At this point there are one or more empty levels before the current 414 // level which need to be backfilled and the current level might have 415 // had some entries deleted from it as well. Since all levels after 416 // level 0 are required to either be empty, half full, or completely 417 // full, the current level must be adjusted accordingly by backfilling 418 // each previous levels in a way which satisfies the requirements. Any 419 // entries that are left are assigned to level 0 after the loop as they 420 // are guaranteed to fit by the logic in the loop. In other words, this 421 // effectively squashes all remaining entries in the current level into 422 // the lowest possible levels while following the level rules. 423 // 424 // Note that the level after the current level might also have entries 425 // and gaps are not allowed, so this also keeps track of the lowest 426 // empty level so the code below knows how far to backfill in case it is 427 // required. 428 lowestEmptyLevel := uint8(255) 429 curLevelData := pendingUpdates[highestLoadedLevel] 430 curLevelMaxEntries := maxEntriesForLevel(highestLoadedLevel) 431 for level := highestLoadedLevel; level > 0; level-- { 432 // When there are not enough entries left in the current level 433 // for the number that would be required to reach it, clear the 434 // the current level which effectively moves them all up to the 435 // previous level on the next iteration. Otherwise, there are 436 // are sufficient entries, so update the current level to 437 // contain as many entries as possible while still leaving 438 // enough remaining entries required to reach the level. 439 numEntries := len(curLevelData) / txEntrySize 440 prevLevelMaxEntries := curLevelMaxEntries / 2 441 minPrevRequired := minEntriesToReachLevel(level - 1) 442 if numEntries < prevLevelMaxEntries+minPrevRequired { 443 lowestEmptyLevel = level 444 pendingUpdates[level] = nil 445 } else { 446 // This level can only be completely full or half full, 447 // so choose the appropriate offset to ensure enough 448 // entries remain to reach the level. 449 var offset int 450 if numEntries-curLevelMaxEntries >= minPrevRequired { 451 offset = curLevelMaxEntries * txEntrySize 452 } else { 453 offset = prevLevelMaxEntries * txEntrySize 454 } 455 pendingUpdates[level] = curLevelData[:offset] 456 curLevelData = curLevelData[offset:] 457 } 458 459 curLevelMaxEntries = prevLevelMaxEntries 460 } 461 pendingUpdates[0] = curLevelData 462 if len(curLevelData) == 0 { 463 lowestEmptyLevel = 0 464 } 465 466 // When the highest loaded level is empty, it's possible the level after 467 // it still has data and thus that data needs to be backfilled as well. 468 for len(pendingUpdates[highestLoadedLevel]) == 0 { 469 // When the next level is empty too, the is no data left to 470 // continue backfilling, so there is nothing left to do. 471 // Otherwise, populate the pending updates map with the newly 472 // loaded data and update the highest loaded level accordingly. 473 level := highestLoadedLevel + 1 474 curLevelKey := keyForLevel(addrKey, level) 475 levelData := bucket.Get(curLevelKey[:]) 476 if len(levelData) == 0 { 477 break 478 } 479 pendingUpdates[level] = levelData 480 highestLoadedLevel = level 481 482 // At this point the highest level is not empty, but it might 483 // be half full. When that is the case, move it up a level to 484 // simplify the code below which backfills all lower levels that 485 // are still empty. This also means the current level will be 486 // empty, so the loop will perform another another iteration to 487 // potentially backfill this level with data from the next one. 488 curLevelMaxEntries := maxEntriesForLevel(level) 489 if len(levelData)/txEntrySize != curLevelMaxEntries { 490 pendingUpdates[level] = nil 491 pendingUpdates[level-1] = levelData 492 level-- 493 curLevelMaxEntries /= 2 494 } 495 496 // Backfill all lower levels that are still empty by iteratively 497 // halfing the data until the lowest empty level is filled. 498 for level > lowestEmptyLevel { 499 offset := (curLevelMaxEntries / 2) * txEntrySize 500 pendingUpdates[level] = levelData[:offset] 501 levelData = levelData[offset:] 502 pendingUpdates[level-1] = levelData 503 level-- 504 curLevelMaxEntries /= 2 505 } 506 507 // The lowest possible empty level is now the highest loaded 508 // level. 509 lowestEmptyLevel = highestLoadedLevel 510 } 511 512 // Apply the pending updates. 513 return applyPending() 514 } 515 516 // addrToKey converts known address types to an addrindex key. An error is 517 // returned for unsupported types. 518 func addrToKey(addr godashutil.Address) ([addrKeySize]byte, error) { 519 switch addr := addr.(type) { 520 case *godashutil.AddressPubKeyHash: 521 var result [addrKeySize]byte 522 result[0] = addrKeyTypePubKeyHash 523 copy(result[1:], addr.Hash160()[:]) 524 return result, nil 525 526 case *godashutil.AddressScriptHash: 527 var result [addrKeySize]byte 528 result[0] = addrKeyTypeScriptHash 529 copy(result[1:], addr.Hash160()[:]) 530 return result, nil 531 532 case *godashutil.AddressPubKey: 533 var result [addrKeySize]byte 534 result[0] = addrKeyTypePubKeyHash 535 copy(result[1:], addr.AddressPubKeyHash().Hash160()[:]) 536 return result, nil 537 } 538 539 return [addrKeySize]byte{}, errUnsupportedAddressType 540 } 541 542 // AddrIndex implements a transaction by address index. That is to say, it 543 // supports querying all transactions that reference a given address because 544 // they are either crediting or debiting the address. The returned transactions 545 // are ordered according to their order of appearance in the blockchain. In 546 // other words, first by block height and then by offset inside the block. 547 // 548 // In addition, support is provided for a memory-only index of unconfirmed 549 // transactions such as those which are kept in the memory pool before inclusion 550 // in a block. 551 type AddrIndex struct { 552 // The following fields are set when the instance is created and can't 553 // be changed afterwards, so there is no need to protect them with a 554 // separate mutex. 555 db database.DB 556 chainParams *chaincfg.Params 557 558 // The following fields are used to quickly link transactions and 559 // addresses that have not been included into a block yet when an 560 // address index is being maintained. The are protected by the 561 // unconfirmedLock field. 562 // 563 // The txnsByAddr field is used to keep an index of all transactions 564 // which either create an output to a given address or spend from a 565 // previous output to it keyed by the address. 566 // 567 // The addrsByTx field is essentially the reverse and is used to 568 // keep an index of all addresses which a given transaction involves. 569 // This allows fairly efficient updates when transactions are removed 570 // once they are included into a block. 571 unconfirmedLock sync.RWMutex 572 txnsByAddr map[[addrKeySize]byte]map[wire.ShaHash]*godashutil.Tx 573 addrsByTx map[wire.ShaHash]map[[addrKeySize]byte]struct{} 574 } 575 576 // Ensure the AddrIndex type implements the Indexer interface. 577 var _ Indexer = (*AddrIndex)(nil) 578 579 // Ensure the AddrIndex type implements the NeedsInputser interface. 580 var _ NeedsInputser = (*AddrIndex)(nil) 581 582 // NeedsInputs signals that the index requires the referenced inputs in order 583 // to properly create the index. 584 // 585 // This implements the NeedsInputser interface. 586 func (idx *AddrIndex) NeedsInputs() bool { 587 return true 588 } 589 590 // Init is only provided to satisfy the Indexer interface as there is nothing to 591 // initialize for this index. 592 // 593 // This is part of the Indexer interface. 594 func (idx *AddrIndex) Init() error { 595 // Nothing to do. 596 return nil 597 } 598 599 // Key returns the database key to use for the index as a byte slice. 600 // 601 // This is part of the Indexer interface. 602 func (idx *AddrIndex) Key() []byte { 603 return addrIndexKey 604 } 605 606 // Name returns the human-readable name of the index. 607 // 608 // This is part of the Indexer interface. 609 func (idx *AddrIndex) Name() string { 610 return addrIndexName 611 } 612 613 // Create is invoked when the indexer manager determines the index needs 614 // to be created for the first time. It creates the bucket for the address 615 // index. 616 // 617 // This is part of the Indexer interface. 618 func (idx *AddrIndex) Create(dbTx database.Tx) error { 619 _, err := dbTx.Metadata().CreateBucket(addrIndexKey) 620 return err 621 } 622 623 // writeIndexData represents the address index data to be written for one block. 624 // It consistens of the address mapped to an ordered list of the transactions 625 // that involve the address in block. It is ordered so the transactions can be 626 // stored in the order they appear in the block. 627 type writeIndexData map[[addrKeySize]byte][]int 628 629 // indexPkScript extracts all standard addresses from the passed public key 630 // script and maps each of them to the associated transaction using the passed 631 // map. 632 func (idx *AddrIndex) indexPkScript(data writeIndexData, pkScript []byte, txIdx int) { 633 // Nothing to index if the script is non-standard or otherwise doesn't 634 // contain any addresses. 635 _, addrs, _, err := txscript.ExtractPkScriptAddrs(pkScript, 636 idx.chainParams) 637 if err != nil || len(addrs) == 0 { 638 return 639 } 640 641 for _, addr := range addrs { 642 addrKey, err := addrToKey(addr) 643 if err != nil { 644 // Ignore unsupported address types. 645 continue 646 } 647 648 // Avoid inserting the transaction more than once. Since the 649 // transactions are indexed serially any duplicates will be 650 // indexed in a row, so checking the most recent entry for the 651 // address is enough to detect duplicates. 652 indexedTxns := data[addrKey] 653 numTxns := len(indexedTxns) 654 if numTxns > 0 && indexedTxns[numTxns-1] == txIdx { 655 continue 656 } 657 indexedTxns = append(indexedTxns, txIdx) 658 data[addrKey] = indexedTxns 659 } 660 } 661 662 // indexBlock extract all of the standard addresses from all of the transactions 663 // in the passed block and maps each of them to the assocaited transaction using 664 // the passed map. 665 func (idx *AddrIndex) indexBlock(data writeIndexData, block *godashutil.Block, view *blockchain.UtxoViewpoint) { 666 for txIdx, tx := range block.Transactions() { 667 // Coinbases do not reference any inputs. Since the block is 668 // required to have already gone through full validation, it has 669 // already been proven on the first transaction in the block is 670 // a coinbase. 671 if txIdx != 0 { 672 for _, txIn := range tx.MsgTx().TxIn { 673 // The view should always have the input since 674 // the index contract requires it, however, be 675 // safe and simply ignore any missing entries. 676 origin := &txIn.PreviousOutPoint 677 entry := view.LookupEntry(&origin.Hash) 678 if entry == nil { 679 continue 680 } 681 682 pkScript := entry.PkScriptByIndex(origin.Index) 683 idx.indexPkScript(data, pkScript, txIdx) 684 } 685 } 686 687 for _, txOut := range tx.MsgTx().TxOut { 688 idx.indexPkScript(data, txOut.PkScript, txIdx) 689 } 690 } 691 } 692 693 // ConnectBlock is invoked by the index manager when a new block has been 694 // connected to the main chain. This indexer adds a mapping for each address 695 // the transactions in the block involve. 696 // 697 // This is part of the Indexer interface. 698 func (idx *AddrIndex) ConnectBlock(dbTx database.Tx, block *godashutil.Block, view *blockchain.UtxoViewpoint) error { 699 // The offset and length of the transactions within the serialized 700 // block. 701 txLocs, err := block.TxLoc() 702 if err != nil { 703 return err 704 } 705 706 // Get the internal block ID associated with the block. 707 blockID, err := dbFetchBlockIDByHash(dbTx, block.Sha()) 708 if err != nil { 709 return err 710 } 711 712 // Build all of the address to transaction mappings in a local map. 713 addrsToTxns := make(writeIndexData) 714 idx.indexBlock(addrsToTxns, block, view) 715 716 // Add all of the index entries for each address. 717 addrIdxBucket := dbTx.Metadata().Bucket(addrIndexKey) 718 for addrKey, txIdxs := range addrsToTxns { 719 for _, txIdx := range txIdxs { 720 err := dbPutAddrIndexEntry(addrIdxBucket, addrKey, 721 blockID, txLocs[txIdx]) 722 if err != nil { 723 return err 724 } 725 } 726 } 727 728 return nil 729 } 730 731 // DisconnectBlock is invoked by the index manager when a block has been 732 // disconnected from the main chain. This indexer removes the address mappings 733 // each transaction in the block involve. 734 // 735 // This is part of the Indexer interface. 736 func (idx *AddrIndex) DisconnectBlock(dbTx database.Tx, block *godashutil.Block, view *blockchain.UtxoViewpoint) error { 737 // Build all of the address to transaction mappings in a local map. 738 addrsToTxns := make(writeIndexData) 739 idx.indexBlock(addrsToTxns, block, view) 740 741 // Remove all of the index entries for each address. 742 bucket := dbTx.Metadata().Bucket(addrIndexKey) 743 for addrKey, txIdxs := range addrsToTxns { 744 err := dbRemoveAddrIndexEntries(bucket, addrKey, len(txIdxs)) 745 if err != nil { 746 return err 747 } 748 } 749 750 return nil 751 } 752 753 // TxRegionsForAddress returns a slice of block regions which identify each 754 // transaction that involves the passed address according to the specified 755 // number to skip, number requested, and whether or not the results should be 756 // reversed. It also returns the number actually skipped since it could be less 757 // in the case where there are not enough entries. 758 // 759 // NOTE: These results only include transactions confirmed in blocks. See the 760 // UnconfirmedTxnsForAddress method for obtaining unconfirmed transactions 761 // that involve a given address. 762 // 763 // This function is safe for concurrent access. 764 func (idx *AddrIndex) TxRegionsForAddress(dbTx database.Tx, addr godashutil.Address, numToSkip, numRequested uint32, reverse bool) ([]database.BlockRegion, uint32, error) { 765 addrKey, err := addrToKey(addr) 766 if err != nil { 767 return nil, 0, err 768 } 769 770 var regions []database.BlockRegion 771 var skipped uint32 772 err = idx.db.View(func(dbTx database.Tx) error { 773 // Create closure to lookup the block hash given the ID using 774 // the database transaction. 775 fetchBlockHash := func(id []byte) (*wire.ShaHash, error) { 776 // Deserialize and populate the result. 777 return dbFetchBlockHashBySerializedID(dbTx, id) 778 } 779 780 var err error 781 addrIdxBucket := dbTx.Metadata().Bucket(addrIndexKey) 782 regions, skipped, err = dbFetchAddrIndexEntries(addrIdxBucket, 783 addrKey, numToSkip, numRequested, reverse, 784 fetchBlockHash) 785 return err 786 }) 787 788 return regions, skipped, err 789 } 790 791 // indexUnconfirmedAddresses modifies the unconfirmed (memory-only) address 792 // index to include mappings for the addresses encoded by the passed public key 793 // script to the transaction. 794 // 795 // This function is safe for concurrent access. 796 func (idx *AddrIndex) indexUnconfirmedAddresses(pkScript []byte, tx *godashutil.Tx) { 797 // The error is ignored here since the only reason it can fail is if the 798 // script fails to parse and it was already validated before being 799 // admitted to the mempool. 800 _, addresses, _, _ := txscript.ExtractPkScriptAddrs(pkScript, 801 idx.chainParams) 802 for _, addr := range addresses { 803 // Ignore unsupported address types. 804 addrKey, err := addrToKey(addr) 805 if err != nil { 806 continue 807 } 808 809 // Add a mapping from the address to the transaction. 810 idx.unconfirmedLock.Lock() 811 addrIndexEntry := idx.txnsByAddr[addrKey] 812 if addrIndexEntry == nil { 813 addrIndexEntry = make(map[wire.ShaHash]*godashutil.Tx) 814 idx.txnsByAddr[addrKey] = addrIndexEntry 815 } 816 addrIndexEntry[*tx.Sha()] = tx 817 818 // Add a mapping from the transaction to the address. 819 addrsByTxEntry := idx.addrsByTx[*tx.Sha()] 820 if addrsByTxEntry == nil { 821 addrsByTxEntry = make(map[[addrKeySize]byte]struct{}) 822 idx.addrsByTx[*tx.Sha()] = addrsByTxEntry 823 } 824 addrsByTxEntry[addrKey] = struct{}{} 825 idx.unconfirmedLock.Unlock() 826 } 827 } 828 829 // AddUnconfirmedTx adds all addresses related to the transaction to the 830 // unconfirmed (memory-only) address index. 831 // 832 // NOTE: This transaction MUST have already been validated by the memory pool 833 // before calling this function with it and have all of the inputs available in 834 // the provided utxo view. Failure to do so could result in some or all 835 // addresses not being indexed. 836 // 837 // This function is safe for concurrent access. 838 func (idx *AddrIndex) AddUnconfirmedTx(tx *godashutil.Tx, utxoView *blockchain.UtxoViewpoint) { 839 // Index addresses of all referenced previous transaction outputs. 840 // 841 // The existence checks are elided since this is only called after the 842 // transaction has already been validated and thus all inputs are 843 // already known to exist. 844 for _, txIn := range tx.MsgTx().TxIn { 845 entry := utxoView.LookupEntry(&txIn.PreviousOutPoint.Hash) 846 if entry == nil { 847 // Ignore missing entries. This should never happen 848 // in practice since the function comments specifically 849 // call out all inputs must be available. 850 continue 851 } 852 pkScript := entry.PkScriptByIndex(txIn.PreviousOutPoint.Index) 853 idx.indexUnconfirmedAddresses(pkScript, tx) 854 } 855 856 // Index addresses of all created outputs. 857 for _, txOut := range tx.MsgTx().TxOut { 858 idx.indexUnconfirmedAddresses(txOut.PkScript, tx) 859 } 860 } 861 862 // RemoveUnconfirmedTx removes the passed transaction from the unconfirmed 863 // (memory-only) address index. 864 // 865 // This function is safe for concurrent access. 866 func (idx *AddrIndex) RemoveUnconfirmedTx(hash *wire.ShaHash) { 867 idx.unconfirmedLock.Lock() 868 defer idx.unconfirmedLock.Unlock() 869 870 // Remove all address references to the transaction from the address 871 // index and remove the entry for the address altogether if it no longer 872 // references any transactions. 873 for addrKey := range idx.addrsByTx[*hash] { 874 delete(idx.txnsByAddr[addrKey], *hash) 875 if len(idx.txnsByAddr[addrKey]) == 0 { 876 delete(idx.txnsByAddr, addrKey) 877 } 878 } 879 880 // Remove the entry from the transaction to address lookup map as well. 881 delete(idx.addrsByTx, *hash) 882 } 883 884 // UnconfirmedTxnsForAddress returns all transactions currently in the 885 // unconfirmed (memory-only) address index that involve the passed address. 886 // Unsupported address types are ignored and will result in no results. 887 // 888 // This function is safe for concurrent access. 889 func (idx *AddrIndex) UnconfirmedTxnsForAddress(addr godashutil.Address) []*godashutil.Tx { 890 // Ignore unsupported address types. 891 addrKey, err := addrToKey(addr) 892 if err != nil { 893 return nil 894 } 895 896 // Protect concurrent access. 897 idx.unconfirmedLock.RLock() 898 defer idx.unconfirmedLock.RUnlock() 899 900 // Return a new slice with the results if there are any. This ensures 901 // safe concurrency. 902 if txns, exists := idx.txnsByAddr[addrKey]; exists { 903 addressTxns := make([]*godashutil.Tx, 0, len(txns)) 904 for _, tx := range txns { 905 addressTxns = append(addressTxns, tx) 906 } 907 return addressTxns 908 } 909 910 return nil 911 } 912 913 // NewAddrIndex returns a new instance of an indexer that is used to create a 914 // mapping of all addresses in the blockchain to the respective transactions 915 // that involve them. 916 // 917 // It implements the Indexer interface which plugs into the IndexManager that in 918 // turn is used by the blockchain package. This allows the index to be 919 // seamlessly maintained along with the chain. 920 func NewAddrIndex(db database.DB, chainParams *chaincfg.Params) *AddrIndex { 921 return &AddrIndex{ 922 db: db, 923 chainParams: chainParams, 924 txnsByAddr: make(map[[addrKeySize]byte]map[wire.ShaHash]*godashutil.Tx), 925 addrsByTx: make(map[wire.ShaHash]map[[addrKeySize]byte]struct{}), 926 } 927 } 928 929 // DropAddrIndex drops the address index from the provided database if it 930 // exists. 931 func DropAddrIndex(db database.DB) error { 932 return dropIndex(db, addrIndexKey, addrIndexName) 933 }