Skip to content

Commit

Permalink
Always store script pubkey in output table (#4254)
Browse files Browse the repository at this point in the history
  • Loading branch information
raphjaph authored Mar 6, 2025
1 parent 7bd9d38 commit bf841a3
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 41 deletions.
46 changes: 45 additions & 1 deletion src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ mod utxo_entry;
#[cfg(test)]
pub(crate) mod testing;

const SCHEMA_VERSION: u64 = 30;
const SCHEMA_VERSION: u64 = 31;

define_multimap_table! { SAT_TO_SEQUENCE_NUMBER, u64, u32 }
define_multimap_table! { SEQUENCE_NUMBER_TO_CHILDREN, u32, u32 }
Expand Down Expand Up @@ -2455,12 +2455,56 @@ impl Index {
txout,
)))
}

#[cfg(test)]
pub(crate) fn list_all_spks(&self) -> Result<Vec<ScriptBuf>> {
let rtx = self.database.begin_read()?;
let mut spks = Vec::new();

for entry in rtx.open_table(OUTPOINT_TO_UTXO_ENTRY)?.iter()? {
let (_outpoint, utxo_entry) = entry?;

spks.push(ScriptBuf::from_bytes(
utxo_entry.value().parse(self).script_pubkey().to_vec(),
));
}

Ok(spks)
}
}

#[cfg(test)]
mod tests {
use {super::*, crate::index::testing::Context};

#[test]
fn list_all_spks() {
let context = Context::builder().build();

context.mine_blocks(2);

let tx_1 = TransactionTemplate {
inputs: &[(1, 0, 0, Default::default())],
fee: 0,
recipient: Some(address(0)),
..default()
};

let tx_2 = TransactionTemplate {
inputs: &[(2, 0, 0, Default::default())],
fee: 0,
recipient: Some(address(1)),
..default()
};

context.core.broadcast_tx(tx_1);
context.core.broadcast_tx(tx_2);

context.mine_blocks(1);

assert_eq!(context.index.list_all_spks().unwrap().len(), 4);
}

#[test]
fn height_limit() {
{
Expand Down
14 changes: 4 additions & 10 deletions src/index/updater.rs
Original file line number Diff line number Diff line change
Expand Up @@ -574,9 +574,7 @@ impl Updater<'_> {

let mut entry = UtxoEntryBuf::new();
entry.push_value(txout.value.to_sat(), self.index);
if self.index.index_addresses {
entry.push_script_pubkey(txout.script_pubkey.as_bytes(), self.index);
}
entry.push_script_pubkey(txout.script_pubkey.as_bytes());

entry
};
Expand Down Expand Up @@ -632,9 +630,7 @@ impl Updater<'_> {
}
}

if self.index.index_addresses {
self.index_transaction_output_script_pubkeys(tx, &mut output_utxo_entries);
}
self.index_transaction_output_script_pubkeys(tx, &mut output_utxo_entries);

if index_inscriptions {
inscription_updater.index_inscriptions(
Expand Down Expand Up @@ -685,9 +681,7 @@ impl Updater<'_> {

let mut new_utxo_entry = UtxoEntryBuf::new();
new_utxo_entry.push_sat_ranges(&lost_sat_ranges, self.index);
if self.index.index_addresses {
new_utxo_entry.push_script_pubkey(&[], self.index);
}
new_utxo_entry.push_script_pubkey(&[]);

*utxo_entry = UtxoEntryBuf::merged(utxo_entry, &new_utxo_entry, self.index);
}
Expand Down Expand Up @@ -725,7 +719,7 @@ impl Updater<'_> {
output_utxo_entries: &mut [UtxoEntryBuf],
) {
for (vout, txout) in tx.output.iter().enumerate() {
output_utxo_entries[vout].push_script_pubkey(txout.script_pubkey.as_bytes(), self.index);
output_utxo_entries[vout].push_script_pubkey(txout.script_pubkey.as_bytes());
}
}

Expand Down
47 changes: 17 additions & 30 deletions src/index/utxo_entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ enum Sats<'a> {
/// by that many 11-byte sat range entries, otherwise the total output value
/// stored as a varint.
///
/// If `--index-addresses`, the script pubkey stored as a varint followed by
/// that many bytes of data.
/// The script pubkey stored as a varint followed by that many bytes of data.
///
/// If `--index-inscriptions`, the list of inscriptions stored as
/// `(sequence_number, offset)`, with the sequence number stored as a u32 and
Expand All @@ -43,7 +42,6 @@ pub struct UtxoEntry {
impl UtxoEntry {
pub fn parse(&self, index: &Index) -> ParsedUtxoEntry {
let sats;
let mut script_pubkey = None;
let mut inscriptions = None;

let mut offset = 0;
Expand All @@ -61,14 +59,12 @@ impl UtxoEntry {
offset += varint_len;
};

if index.index_addresses {
let (script_pubkey_len, varint_len) = varint::decode(&self.bytes[offset..]).unwrap();
offset += varint_len;
let (script_pubkey_len, varint_len) = varint::decode(&self.bytes[offset..]).unwrap();
offset += varint_len;

let script_pubkey_len: usize = script_pubkey_len.try_into().unwrap();
script_pubkey = Some(&self.bytes[offset..offset + script_pubkey_len]);
offset += script_pubkey_len;
}
let script_pubkey_len = usize::try_from(script_pubkey_len).unwrap();
let script_pubkey = Some(&self.bytes[offset..offset + script_pubkey_len]);
offset += script_pubkey_len;

if index.index_inscriptions {
inscriptions = Some(&self.bytes[offset..self.bytes.len()]);
Expand Down Expand Up @@ -214,7 +210,7 @@ impl UtxoEntryBuf {
varint::encode_to_vec(value.into(), &mut self.vec);

#[cfg(debug_assertions)]
self.advance_state(State::NeedSats, State::NeedScriptPubkey, index);
self.advance_state(State::NeedSats, State::NeedScriptPubkey);
}

pub fn push_sat_ranges(&mut self, sat_ranges: &[u8], index: &Index) {
Expand All @@ -225,24 +221,23 @@ impl UtxoEntryBuf {
self.vec.extend(sat_ranges);

#[cfg(debug_assertions)]
self.advance_state(State::NeedSats, State::NeedScriptPubkey, index);
self.advance_state(State::NeedSats, State::NeedScriptPubkey);
}

pub fn push_script_pubkey(&mut self, script_pubkey: &[u8], index: &Index) {
assert!(index.index_addresses);
pub fn push_script_pubkey(&mut self, script_pubkey: &[u8]) {
varint::encode_to_vec(script_pubkey.len().try_into().unwrap(), &mut self.vec);
self.vec.extend(script_pubkey);

#[cfg(debug_assertions)]
self.advance_state(State::NeedScriptPubkey, State::Valid, index);
self.advance_state(State::NeedScriptPubkey, State::Valid);
}

pub fn push_inscriptions(&mut self, inscriptions: &[u8], index: &Index) {
assert!(index.index_inscriptions);
self.vec.extend(inscriptions);

#[cfg(debug_assertions)]
self.advance_state(State::Valid, State::Valid, index);
self.advance_state(State::Valid, State::Valid);
}

pub fn push_inscription(&mut self, sequence_number: u32, satpoint_offset: u64, index: &Index) {
Expand All @@ -251,17 +246,13 @@ impl UtxoEntryBuf {
varint::encode_to_vec(satpoint_offset.into(), &mut self.vec);

#[cfg(debug_assertions)]
self.advance_state(State::Valid, State::Valid, index);
self.advance_state(State::Valid, State::Valid);
}

#[cfg(debug_assertions)]
fn advance_state(&mut self, expected_state: State, new_state: State, index: &Index) {
fn advance_state(&mut self, expected_state: State, new_state: State) {
assert!(self.state == expected_state);
self.state = new_state;

if self.state == State::NeedScriptPubkey && !index.index_addresses {
self.state = State::Valid;
}
}

pub fn merged(a: &UtxoEntry, b: &UtxoEntry, index: &Index) -> Self {
Expand All @@ -278,11 +269,9 @@ impl UtxoEntryBuf {
merged.push_value(0, index);
}

if index.index_addresses {
assert!(a_parsed.script_pubkey().is_empty());
assert!(b_parsed.script_pubkey().is_empty());
merged.push_script_pubkey(&[], index);
}
assert!(a_parsed.script_pubkey().is_empty());
assert!(b_parsed.script_pubkey().is_empty());
merged.push_script_pubkey(&[]);

if index.index_inscriptions {
merged.push_inscriptions(a_parsed.inscriptions(), index);
Expand All @@ -301,9 +290,7 @@ impl UtxoEntryBuf {
utxo_entry.push_value(0, index);
}

if index.index_addresses {
utxo_entry.push_script_pubkey(&[], index);
}
utxo_entry.push_script_pubkey(&[]);

utxo_entry
}
Expand Down

0 comments on commit bf841a3

Please sign in to comment.