diff --git a/wtxmgr/tx.go b/wtxmgr/tx.go index a9b9651..0b232ea 100644 --- a/wtxmgr/tx.go +++ b/wtxmgr/tx.go @@ -405,10 +405,16 @@ func (s *Store) AddCredit(ns walletdb.ReadWriteBucket, rec *TxRecord, block *Blo // duplicate (false). func (s *Store) addCredit(ns walletdb.ReadWriteBucket, rec *TxRecord, block *BlockMeta, index uint32, change bool) (bool, error) { if block == nil { + // If the outpoint that we should mark as credit already exists + // within the store, either as unconfirmed or confirmed, then we + // have nothing left to do and can exit. k := canonicalOutPoint(&rec.Hash, index) if existsRawUnminedCredit(ns, k) != nil { return false, nil } + if existsRawUnspent(ns, k) != nil { + return false, nil + } v := valueUnminedCredit(btcutil.Amount(rec.MsgTx.TxOut[index].Value), change) return true, putRawUnminedCredit(ns, k, v) } diff --git a/wtxmgr/unconfirmed.go b/wtxmgr/unconfirmed.go index 812d2d2..37bf7e1 100644 --- a/wtxmgr/unconfirmed.go +++ b/wtxmgr/unconfirmed.go @@ -14,12 +14,25 @@ import ( // insertMemPoolTx inserts the unmined transaction record. It also marks // previous outputs referenced by the inputs as spent. func (s *Store) insertMemPoolTx(ns walletdb.ReadWriteBucket, rec *TxRecord) error { - v := existsRawUnmined(ns, rec.Hash[:]) - if v != nil { - // TODO: compare serialized txs to ensure this isn't a hash collision? + // Check whether the transaction has already been added to the + // unconfirmed bucket. + if existsRawUnmined(ns, rec.Hash[:]) != nil { + // TODO: compare serialized txs to ensure this isn't a hash + // collision? return nil } + // Since transaction records within the store are keyed by their + // transaction _and_ block confirmation, we'll iterate through the + // transaction's outputs to determine if we've already seen them to + // prevent from adding this transaction to the unconfirmed bucket. + for i := range rec.MsgTx.TxOut { + k := canonicalOutPoint(&rec.Hash, uint32(i)) + if existsRawUnspent(ns, k) != nil { + return nil + } + } + log.Infof("Inserting unconfirmed transaction %v", rec.Hash) v, err := valueTxRecord(rec) if err != nil {