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 25, 2024
1 parent d576112 commit af90db3
Showing 1 changed file with 37 additions and 30 deletions.
67 changes: 37 additions & 30 deletions core/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,26 +61,27 @@ const (
type environment struct {
signer types.Signer

state *state.StateDB // apply state changes here
ancestors mapset.Set // ancestor set (used for checking uncle parent validity)
family mapset.Set // family set (used for checking uncle invalidity)
tcount int // tx count in cycle
gasPool *types.GasPool // available gas used to pack transactions
coinbase common.Address
etxRLimit int // Remaining number of cross-region ETXs that can be included
etxPLimit int // Remaining number of cross-prime ETXs that can be included
parentOrder *int
wo *types.WorkObject
txs []*types.Transaction
etxs []*types.Transaction
utxoFees *big.Int
quaiFees *big.Int
subManifest types.BlockManifest
receipts []*types.Receipt
uncleMu sync.RWMutex
uncles map[common.Hash]*types.WorkObjectHeader
utxosCreate []common.Hash
utxosDelete []common.Hash
state *state.StateDB // apply state changes here
ancestors mapset.Set // ancestor set (used for checking uncle parent validity)
family mapset.Set // family set (used for checking uncle invalidity)
tcount int // tx count in cycle
gasPool *types.GasPool // available gas used to pack transactions
coinbase common.Address
etxRLimit int // Remaining number of cross-region ETXs that can be included
etxPLimit int // Remaining number of cross-prime ETXs that can be included
parentOrder *int
wo *types.WorkObject
txs []*types.Transaction
etxs []*types.Transaction
utxoFees *big.Int
quaiFees *big.Int
subManifest types.BlockManifest
receipts []*types.Receipt
uncleMu sync.RWMutex
uncles map[common.Hash]*types.WorkObjectHeader
utxosCreate []common.Hash
utxosDelete []common.Hash
deletedUtxos map[common.Hash]struct{}
}

// unclelist returns the contained uncles as the list format.
Expand Down Expand Up @@ -691,15 +692,16 @@ func (w *worker) makeEnv(parent *types.WorkObject, proposedWo *types.WorkObject,
}
// Note the passed coinbase may be different with header.Coinbase.
env := &environment{
signer: types.MakeSigner(w.chainConfig, proposedWo.Number(w.hc.NodeCtx())),
state: state,
coinbase: coinbase,
ancestors: mapset.NewSet(),
family: mapset.NewSet(),
wo: proposedWo,
uncles: make(map[common.Hash]*types.WorkObjectHeader),
etxRLimit: etxRLimit,
etxPLimit: etxPLimit,
signer: types.MakeSigner(w.chainConfig, proposedWo.Number(w.hc.NodeCtx())),
state: state,
coinbase: coinbase,
ancestors: mapset.NewSet(),
family: mapset.NewSet(),
wo: proposedWo,
uncles: make(map[common.Hash]*types.WorkObjectHeader),
etxRLimit: etxRLimit,
etxPLimit: etxPLimit,
deletedUtxos: make(map[common.Hash]struct{}),
}
// Keep track of transactions which return errors so they can be removed
env.tcount = 0
Expand Down Expand Up @@ -953,8 +955,9 @@ func (w *worker) commitTransactions(env *environment, parent *types.WorkObject,
break
}
if err := w.processQiTx(tx, env, parent); err != nil {
if strings.Contains(err.Error(), "emits too many") {
if strings.Contains(err.Error(), "emits too many") || strings.Contains(err.Error(), "double spends") {
// This is not an invalid tx, our block is just full of ETXs
// Alternatively, a tx double spends a cached deleted UTXO, likely replaced-by-fee
txs.PopNoSort()
continue
}
Expand Down Expand Up @@ -1707,6 +1710,10 @@ func (w *worker) processQiTx(tx *types.Transaction, env *environment, parent *ty
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 {
Expand Down

0 comments on commit af90db3

Please sign in to comment.