Skip to content

Commit

Permalink
Prevent worker from unintentionally double-spending UTXOs
Browse files Browse the repository at this point in the history
  • Loading branch information
jdowning100 committed Sep 27, 2024
1 parent af90db3 commit 08f51c7
Showing 1 changed file with 13 additions and 16 deletions.
29 changes: 13 additions & 16 deletions core/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -1531,7 +1531,7 @@ func (w *worker) processQiTx(tx *types.Transaction, env *environment, parent *ty

addresses := make(map[common.AddressBytes]struct{})
totalQitIn := big.NewInt(0)
utxosDelete := make(map[types.OutPoint]*types.UtxoEntry)
utxosDeleteHashes := make([]common.Hash, 0, len(tx.TxIn()))
inputs := make(map[uint]uint64)
for _, txIn := range tx.TxIn() {
utxo := rawdb.GetUTXO(w.workerDb, txIn.PreviousOutPoint.TxHash, txIn.PreviousOutPoint.Index)
Expand All @@ -1557,15 +1557,20 @@ func (w *worker) processQiTx(tx *types.Transaction, env *environment, parent *ty
}
addresses[common.AddressBytes(utxo.Address)] = struct{}{}
totalQitIn.Add(totalQitIn, types.Denominations[denomination])
utxosDelete[txIn.PreviousOutPoint] = utxo
utxoHash := types.UTXOHash(txIn.PreviousOutPoint.TxHash, txIn.PreviousOutPoint.Index, utxo)
if _, exists := env.deletedUtxos[utxoHash]; exists {
return fmt.Errorf("tx %032x double spends UTXO %032x:%d", tx.Hash(), txIn.PreviousOutPoint.TxHash, txIn.PreviousOutPoint.Index)
}
env.deletedUtxos[utxoHash] = struct{}{}
utxosDeleteHashes = append(utxosDeleteHashes, utxoHash)
inputs[uint(denomination)]++
}
var ETXRCount int
var ETXPCount int
etxs := make([]*types.ExternalTx, 0)
totalQitOut := big.NewInt(0)
totalConvertQitOut := big.NewInt(0)
utxosCreate := make(map[types.OutPoint]*types.UtxoEntry)
utxosCreateHashes := make([]common.Hash, 0, len(tx.TxOut()))
conversion := false
var convertAddress common.Address
outputs := make(map[uint]uint64)
Expand Down Expand Up @@ -1650,7 +1655,7 @@ func (w *worker) processQiTx(tx *types.Transaction, env *environment, parent *ty
} else {
// This output creates a normal UTXO
utxo := types.NewUtxoEntry(&txOut)
utxosCreate[types.OutPoint{TxHash: tx.Hash(), Index: uint16(txOutIdx)}] = utxo
utxosCreateHashes = append(utxosCreateHashes, types.UTXOHash(tx.Hash(), uint16(txOutIdx), utxo))
}
}
// Ensure the transaction does not spend more than its inputs.
Expand Down Expand Up @@ -1708,18 +1713,10 @@ func (w *worker) processQiTx(tx *types.Transaction, env *environment, parent *ty
}
env.txs = append(env.txs, tx)
env.utxoFees.Add(env.utxoFees, txFeeInQit)
for outpoint, utxo := range utxosDelete {
utxoHash := types.UTXOHash(outpoint.TxHash, outpoint.Index, utxo)
if _, exists := env.deletedUtxos[utxoHash]; exists {
return fmt.Errorf("tx %032x double spends UTXO %032x:%d", tx.Hash(), outpoint.TxHash, outpoint.Index)
}
env.deletedUtxos[utxoHash] = struct{}{}
env.utxosDelete = append(env.utxosDelete, utxoHash)
}
for outPoint, utxo := range utxosCreate {
utxoHash := types.UTXOHash(outPoint.TxHash, outPoint.Index, utxo)
env.utxosCreate = append(env.utxosCreate, utxoHash)
}

env.utxosDelete = append(env.utxosDelete, utxosDeleteHashes...)
env.utxosCreate = append(env.utxosCreate, utxosCreateHashes...)

if err := CheckDenominations(inputs, outputs); err != nil {
return err
}
Expand Down

0 comments on commit 08f51c7

Please sign in to comment.