Skip to content

Commit

Permalink
Fix output indexes to be represented as a u32
Browse files Browse the repository at this point in the history
Bitcoin's consensus rules allows for output indexes larger than u16,
which would result in an overflow prior to this fix.

This recently happened with a transaction on testnet:
https://blockstream.info/testnet/tx/ca3b75556430e1adf9e9790bce9c73a3d9afdb42305588e64c65b258c06c05c9

Based on @junderw's mempool/electrs#75. Thanks!

This change requires a full database reindex.
  • Loading branch information
shesek committed Feb 15, 2024
1 parent 255fb17 commit f946a6f
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 35 deletions.
22 changes: 11 additions & 11 deletions src/elements/asset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ pub struct IssuedAsset {
#[derive(Serialize, Deserialize, Debug)]
pub struct AssetRow {
pub issuance_txid: FullHash,
pub issuance_vin: u16,
pub issuance_vin: u32,
pub prev_txid: FullHash,
pub prev_vout: u16,
pub prev_vout: u32,
pub issuance: Bytes, // bincode does not like dealing with AssetIssuance, deserialization fails with "invalid type: sequence, expected a struct"
pub reissuance_token: FullHash,
}
Expand Down Expand Up @@ -108,7 +108,7 @@ impl IssuedAsset {
},
issuance_prevout: OutPoint {
txid: deserialize(&asset.prev_txid).unwrap(),
vout: asset.prev_vout as u32,
vout: asset.prev_vout,
},
contract_hash,
reissuance_token,
Expand Down Expand Up @@ -157,7 +157,7 @@ impl LiquidAsset {
#[derive(Serialize, Deserialize, Debug)]
pub struct IssuingInfo {
pub txid: FullHash,
pub vin: u16,
pub vin: u32,
pub is_reissuance: bool,
// None for blinded issuances
pub issued_amount: Option<u64>,
Expand All @@ -167,7 +167,7 @@ pub struct IssuingInfo {
#[derive(Serialize, Deserialize, Debug)]
pub struct BurningInfo {
pub txid: FullHash,
pub vout: u16,
pub vout: u32,
pub value: u64,
}

Expand Down Expand Up @@ -251,7 +251,7 @@ fn index_tx_assets(
pegout.asset.explicit().unwrap(),
TxHistoryInfo::Pegout(PegoutInfo {
txid,
vout: txo_index as u16,
vout: txo_index as u32,
value: pegout.value,
}),
));
Expand All @@ -262,7 +262,7 @@ fn index_tx_assets(
asset_id,
TxHistoryInfo::Burning(BurningInfo {
txid,
vout: txo_index as u16,
vout: txo_index as u32,
value: value,
}),
));
Expand All @@ -277,7 +277,7 @@ fn index_tx_assets(
pegin.asset,
TxHistoryInfo::Pegin(PeginInfo {
txid,
vin: txi_index as u16,
vin: txi_index as u32,
value: pegin.value,
}),
));
Expand All @@ -302,7 +302,7 @@ fn index_tx_assets(
asset_id,
TxHistoryInfo::Issuing(IssuingInfo {
txid,
vin: txi_index as u16,
vin: txi_index as u32,
is_reissuance,
issued_amount,
token_amount,
Expand All @@ -321,9 +321,9 @@ fn index_tx_assets(
asset_id,
AssetRow {
issuance_txid: txid,
issuance_vin: txi_index as u16,
issuance_vin: txi_index as u32,
prev_txid: full_hash(&txi.previous_output.txid[..]),
prev_vout: txi.previous_output.vout as u16,
prev_vout: txi.previous_output.vout as u32,
issuance: serialize(&txi.asset_issuance),
reissuance_token: full_hash(&reissuance_token.into_inner()[..]),
},
Expand Down
4 changes: 2 additions & 2 deletions src/elements/peg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ impl PegoutValue {
#[derive(Serialize, Deserialize, Debug)]
pub struct PeginInfo {
pub txid: FullHash,
pub vin: u16,
pub vin: u32,
pub value: u64,
}

// Inner type for the indexer TxHistoryInfo::Pegout variant
#[derive(Serialize, Deserialize, Debug)]
pub struct PegoutInfo {
pub txid: FullHash,
pub vout: u16,
pub vout: u32,
pub value: u64,
}
8 changes: 4 additions & 4 deletions src/new_index/mempool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ impl Mempool {

Some(Utxo {
txid: deserialize(&info.txid).expect("invalid txid"),
vout: info.vout as u32,
vout: info.vout,
value: info.value,
confirmed: None,

Expand Down Expand Up @@ -377,9 +377,9 @@ impl Mempool {
compute_script_hash(&prevout.script_pubkey),
TxHistoryInfo::Spending(SpendingInfo {
txid: txid_bytes,
vin: input_index as u16,
vin: input_index,
prev_txid: full_hash(&txi.previous_output.txid[..]),
prev_vout: txi.previous_output.vout as u16,
prev_vout: txi.previous_output.vout,
value: prevout.value.amount_value(),
}),
)
Expand All @@ -398,7 +398,7 @@ impl Mempool {
compute_script_hash(&txo.script_pubkey),
TxHistoryInfo::Funding(FundingInfo {
txid: txid_bytes,
vout: index as u16,
vout: index as u32,
value: txo.value.amount_value(),
}),
)
Expand Down
34 changes: 17 additions & 17 deletions src/new_index/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,7 @@ impl ChainQuery {
let txid: Txid = deserialize(&edge.key.spending_txid).unwrap();
self.tx_confirming_block(&txid).map(|b| SpendingInput {
txid,
vin: edge.key.spending_vin as u32,
vin: edge.key.spending_vin,
confirmed: Some(b),
})
})
Expand Down Expand Up @@ -1104,7 +1104,7 @@ fn index_transaction(
confirmed_height,
TxHistoryInfo::Funding(FundingInfo {
txid,
vout: txo_index as u16,
vout: txo_index as u32,
value: txo.value.amount_value(),
}),
);
Expand All @@ -1130,19 +1130,19 @@ fn index_transaction(
confirmed_height,
TxHistoryInfo::Spending(SpendingInfo {
txid,
vin: txi_index as u16,
vin: txi_index as u32,
prev_txid: full_hash(&txi.previous_output.txid[..]),
prev_vout: txi.previous_output.vout as u16,
prev_vout: txi.previous_output.vout,
value: prev_txo.value.amount_value(),
}),
);
rows.push(history.into_row());

let edge = TxEdgeRow::new(
full_hash(&txi.previous_output.txid[..]),
txi.previous_output.vout as u16,
txi.previous_output.vout,
txid,
txi_index as u16,
txi_index as u32,
);
rows.push(edge.into_row());
}
Expand Down Expand Up @@ -1262,7 +1262,7 @@ impl TxConfRow {
struct TxOutKey {
code: u8,
txid: FullHash,
vout: u16,
vout: u32,
}

struct TxOutRow {
Expand All @@ -1276,7 +1276,7 @@ impl TxOutRow {
key: TxOutKey {
code: b'O',
txid: *txid,
vout: vout as u16,
vout: vout as u32,
},
value: serialize(txout),
}
Expand All @@ -1285,7 +1285,7 @@ impl TxOutRow {
bincode::serialize(&TxOutKey {
code: b'O',
txid: full_hash(&outpoint.txid[..]),
vout: outpoint.vout as u16,
vout: outpoint.vout as u32,
})
.unwrap()
}
Expand Down Expand Up @@ -1375,16 +1375,16 @@ impl BlockRow {
#[derive(Serialize, Deserialize, Debug)]
pub struct FundingInfo {
pub txid: FullHash,
pub vout: u16,
pub vout: u32,
pub value: Value,
}

#[derive(Serialize, Deserialize, Debug)]
pub struct SpendingInfo {
pub txid: FullHash, // spending transaction
pub vin: u16,
pub vin: u32,
pub prev_txid: FullHash, // funding transaction
pub prev_vout: u16,
pub prev_vout: u32,
pub value: Value,
}

Expand Down Expand Up @@ -1506,9 +1506,9 @@ impl TxHistoryInfo {
struct TxEdgeKey {
code: u8,
funding_txid: FullHash,
funding_vout: u16,
funding_vout: u32,
spending_txid: FullHash,
spending_vin: u16,
spending_vin: u32,
}

struct TxEdgeRow {
Expand All @@ -1518,9 +1518,9 @@ struct TxEdgeRow {
impl TxEdgeRow {
fn new(
funding_txid: FullHash,
funding_vout: u16,
funding_vout: u32,
spending_txid: FullHash,
spending_vin: u16,
spending_vin: u32,
) -> Self {
let key = TxEdgeKey {
code: b'S',
Expand All @@ -1534,7 +1534,7 @@ impl TxEdgeRow {

fn filter(outpoint: &OutPoint) -> Bytes {
// TODO build key without using bincode? [ b"S", &outpoint.txid[..], outpoint.vout?? ].concat()
bincode::serialize(&(b'S', full_hash(&outpoint.txid[..]), outpoint.vout as u16)).unwrap()
bincode::serialize(&(b'S', full_hash(&outpoint.txid[..]), outpoint.vout)).unwrap()
}

fn into_row(self) -> DBRow {
Expand Down
2 changes: 1 addition & 1 deletion src/util/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl From<Option<BlockId>> for TransactionStatus {
#[derive(Serialize, Deserialize)]
pub struct TxInput {
pub txid: Txid,
pub vin: u16,
pub vin: u32,
}

pub fn is_coinbase(txin: &TxIn) -> bool {
Expand Down

0 comments on commit f946a6f

Please sign in to comment.