Allow tx inputs to use txns earlier in same block.
It is acceptable for a transaction input in a block to reference the output of another transaction in the same block only if the referenced transaction comes before the transaction referencing it.
This commit is contained in:
parent
e82c97be3b
commit
c3b330e42d
1 changed files with 23 additions and 12 deletions
35
txlookup.go
35
txlookup.go
|
@ -193,16 +193,17 @@ func (b *BlockChain) fetchTxList(node *blockNode, txList []*btcwire.ShaHash) (ma
|
||||||
// for more details on what the point of view entails.
|
// for more details on what the point of view entails.
|
||||||
func (b *BlockChain) fetchInputTransactions(node *blockNode, block *btcutil.Block) (map[btcwire.ShaHash]*txData, error) {
|
func (b *BlockChain) fetchInputTransactions(node *blockNode, block *btcutil.Block) (map[btcwire.ShaHash]*txData, error) {
|
||||||
// Build a map of in-flight transactions because some of the inputs in
|
// Build a map of in-flight transactions because some of the inputs in
|
||||||
// this block could be referencing other transactions in this block
|
// this block could be referencing other transactions earlier in this
|
||||||
// which are not yet in the chain.
|
// block which are not yet in the chain.
|
||||||
txInFlight := map[btcwire.ShaHash]*btcwire.MsgTx{}
|
txInFlight := map[btcwire.ShaHash]int{}
|
||||||
for i, tx := range block.MsgBlock().Transactions {
|
transactions := block.MsgBlock().Transactions
|
||||||
|
for i := range transactions {
|
||||||
// Get transaction hash. It's safe to ignore the error since
|
// Get transaction hash. It's safe to ignore the error since
|
||||||
// it's already cached in the nominal code path and the only
|
// it's already cached in the nominal code path and the only
|
||||||
// way it can fail is if the index is out of range which is
|
// way it can fail is if the index is out of range which is
|
||||||
// impossible here.
|
// impossible here.
|
||||||
txHash, _ := block.TxSha(i)
|
txHash, _ := block.TxSha(i)
|
||||||
txInFlight[*txHash] = tx
|
txInFlight[*txHash] = i
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loop through all of the transaction inputs (except for the coinbase
|
// Loop through all of the transaction inputs (except for the coinbase
|
||||||
|
@ -210,7 +211,7 @@ func (b *BlockChain) fetchInputTransactions(node *blockNode, block *btcutil.Bloc
|
||||||
// what is already known (in-flight).
|
// what is already known (in-flight).
|
||||||
var txNeededList []*btcwire.ShaHash
|
var txNeededList []*btcwire.ShaHash
|
||||||
txStore := make(map[btcwire.ShaHash]*txData)
|
txStore := make(map[btcwire.ShaHash]*txData)
|
||||||
for _, tx := range block.MsgBlock().Transactions[1:] {
|
for i, tx := range transactions[1:] {
|
||||||
for _, txIn := range tx.TxIn {
|
for _, txIn := range tx.TxIn {
|
||||||
// Add an entry to the transaction store for the needed
|
// Add an entry to the transaction store for the needed
|
||||||
// transaction with it set to missing by default.
|
// transaction with it set to missing by default.
|
||||||
|
@ -218,13 +219,23 @@ func (b *BlockChain) fetchInputTransactions(node *blockNode, block *btcutil.Bloc
|
||||||
txD := &txData{hash: originHash, err: btcdb.TxShaMissing}
|
txD := &txData{hash: originHash, err: btcdb.TxShaMissing}
|
||||||
txStore[*originHash] = txD
|
txStore[*originHash] = txD
|
||||||
|
|
||||||
// The transaction is already in-flight, so update the
|
// It is acceptable for a transaction input to reference
|
||||||
// transaction store acccordingly. Otherwise, we need
|
// the output of another transaction in this block only
|
||||||
// it.
|
// if the referenced transaction comes before the
|
||||||
if tx, ok := txInFlight[*originHash]; ok {
|
// current one in this block. Update the transaction
|
||||||
txD.tx = tx
|
// store acccordingly when this is the case. Otherwise,
|
||||||
|
// we still need the transaction.
|
||||||
|
//
|
||||||
|
// NOTE: The >= is correct here because i is one less
|
||||||
|
// than the actual position of the transaction within
|
||||||
|
// the block due to skipping the coinbase.
|
||||||
|
if inFlightIndex, ok := txInFlight[*originHash]; ok &&
|
||||||
|
i >= inFlightIndex {
|
||||||
|
|
||||||
|
originTx := transactions[inFlightIndex]
|
||||||
|
txD.tx = originTx
|
||||||
txD.blockHeight = node.height
|
txD.blockHeight = node.height
|
||||||
txD.spent = make([]bool, len(tx.TxOut))
|
txD.spent = make([]bool, len(originTx.TxOut))
|
||||||
txD.err = nil
|
txD.err = nil
|
||||||
} else {
|
} else {
|
||||||
txNeededList = append(txNeededList, originHash)
|
txNeededList = append(txNeededList, originHash)
|
||||||
|
|
Loading…
Add table
Reference in a new issue