Merge branch 'bcmr-fix' into 'master'

bugfix: BCMR authchain

See merge request riftenlabs/riftenlabs-indexer!7
This commit is contained in:
Dagur Valberg Johannsson 2024-05-28 10:27:18 +00:00
commit f398b77974

View file

@ -192,24 +192,27 @@ pub fn index_bcmr(
}) })
.collect(); .collect();
let mut position_index: HashMap<OutPointHash, usize> = HashMap::default(); let mut candidates: HashMap<OutPointHash, (&Transaction, usize)> = sorted
.par_iter()
// Look for authchain updates. We collect all candidates first.
let mut candidates: HashMap<OutPointHash, Transaction> = sorted
.into_iter()
.enumerate() .enumerate()
.filter_map(|(pos, tx)| { .flat_map(|(tx_pos, tx)| {
let prevout = tx.input.first().expect("tx with no inputs").previous_output; let tx_candidates: Vec<(OutPointHash, (&Transaction, usize))> = tx
.input
.iter()
.filter_map(|i| {
let prevout = &i.previous_output;
if prevout.vout != 0 { if prevout.vout != 0 {
// authchain needs to spend first output of a previous tx // authchain needs to spend first output of a previous tx
None None
} else { } else {
let utxohash = compute_outpoint_hash(&prevout.txid, prevout.vout); let utxohash = compute_outpoint_hash(&prevout.txid, prevout.vout);
position_index.insert(utxohash, pos); Some((utxohash, (tx, tx_pos)))
Some((utxohash, tx))
} }
}) })
.collect(); .collect();
tx_candidates
})
.collect();
let mut inserts = 0; let mut inserts = 0;
@ -247,11 +250,11 @@ pub fn index_bcmr(
let mut smallest_index = usize::MAX; let mut smallest_index = usize::MAX;
for prev_autheader in matches { for prev_autheader in matches {
let tx = candidates let (tx, tx_pos) = candidates
.remove(&prev_autheader.utxo) .remove(&prev_autheader.utxo)
.expect("match not in candidate list"); .expect("match not in candidate list");
let bcmr = parse_bcmr(&tx); let bcmr = parse_bcmr(tx);
let txid = tx.txid(); let txid = tx.txid();
let utxohash = compute_outpoint_hash(&txid, 0); let utxohash = compute_outpoint_hash(&txid, 0);
@ -274,25 +277,15 @@ pub fn index_bcmr(
bcmr.map(|bcmr| bcmr.op_return), bcmr.map(|bcmr| bcmr.op_return),
)?; )?;
smallest_index = cmp::min( smallest_index = cmp::min(smallest_index, tx_pos);
smallest_index,
*position_index
.get(&prev_autheader.utxo)
.expect("entry not in position index"),
);
inserts += 1; inserts += 1;
} }
// since it's ttor sorted; there can be no chained updates above the first candidate; // Because transactions are TTOR sorted; there will be no new candidates above the "smallest index" autheader.
// and we can remove all candidates above smallest_index candidates = candidates
position_index.retain(|hash, pos| { .into_par_iter()
if pos > &mut smallest_index { .filter(|(_, (_, tx_pos))| tx_pos > &smallest_index)
true .collect();
} else {
candidates.remove(hash);
false
}
});
} }
Ok(inserts) Ok(inserts)