Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- fixed: Fix failed transaction processing for FIRO transactions with SparkSpend inputs.

## 3.8.7 (2025-11-05)

- fixed: Added retry delay to fix dropped transaction thrashing.
Expand Down
36 changes: 25 additions & 11 deletions src/common/utxobased/engine/UtxoEngineProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1354,30 +1354,44 @@ const processTransactionResponse = (
return {
amount: outputTotalValue,
n: 0,
outputIndex: 4294967295,
// UINT32_MAX value, as a coinbase has no previous outpoint
outputIndex: 0xffffffff,
scriptPubkey: '', // Maybe there's a bogus scriptPubkey we can use here?
sequence: vin.sequence,
txId: '0000000000000000000000000000000000000000000000000000000000000000'
}
}

if (vin.txid == null) {
throw new Error(`Unexpected null txid when processing transaction inputs`)
}

const scriptPubkey =
let scriptPubkey: string = 'unknown'
try {
// Note: Blockbook has empirically not sent a hex value as the
// scriptPubkey for vins. If we discover this to be changed for some
// cases, we may want to use the `hex` field as an optimization.
asMaybe(
raw => validScriptPubkeyFromAddress(raw),
'unknown'
)({
scriptPubkey = validScriptPubkeyFromAddress({
address: vin.addresses[0],
coin: common.pluginInfo.coinInfo.name
})
} catch (error) {
common.log.warn(
`failed to get scriptPubkey from address ${vin.addresses[0]}: `,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Undefined access from empty input addresses array

Potential undefined access when vin.addresses is an empty array. According to the BlockbookTransaction type definition, addresses can be an empty array (default value is []). For SparkSpend inputs in FIRO (the purpose of this PR), the addresses array may be empty. Accessing vin.addresses[0] on line 1371 will return undefined, which is then passed to validScriptPubkeyFromAddress. While the try-catch will handle the error, the error message on line 1376 will log undefined as the address, making debugging difficult. The code should check if vin.addresses[0] exists before attempting to use it.

Fix in Cursor Fix in Web

error
)
}

// Some inputs may not have a txid in addition to coinbase inputs, such as
// private transaction inputs from privacy chains (e.g. SparkSpend inputs in FIRO).
// Warning: Because the engine doesn't support private transactions, or any
// transaction outputs that wouldn't have a txid as their input in the spend transaction,
// we can safely assume an all-zero txid for these inputs.
// If we're to ever support private transaction spends, then this wouldn't
// be safe to assume as "our own input" because it wouldn't remove the UTXO
// from the DataLayer properly.
const txId =
vin.txid ??
'0000000000000000000000000000000000000000000000000000000000000000'

return {
txId: vin.txid,
txId,
outputIndex: vin.vout,
n: vin.n,
scriptPubkey,
Expand Down
Loading