From 6cde865c886bbfc8b39542726de2a2705729319d Mon Sep 17 00:00:00 2001 From: raphjaph Date: Wed, 30 Aug 2023 19:52:39 +0200 Subject: [PATCH 1/3] Make any zero-valued input inscription unbound --- src/index.rs | 45 ++++++++++++++++++++++++ src/index/updater/inscription_updater.rs | 20 ++++++----- 2 files changed, 57 insertions(+), 8 deletions(-) diff --git a/src/index.rs b/src/index.rs index 51ddf713c0..37c634ef49 100644 --- a/src/index.rs +++ b/src/index.rs @@ -2653,6 +2653,51 @@ mod tests { } } + #[test] + fn transaction_with_inscription_inside_zero_value_2nd_input_should_be_unbound_and_cursed() { + for context in Context::configurations() { + context.mine_blocks(1); + + // create zero value input + context.rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[(1, 0, 0)], + fee: 50 * 100_000_000, + ..Default::default() + }); + + context.mine_blocks(1); + + let txid = context.rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[(2, 0, 0), (2, 1, 0)], + witness: inscription("text/plain", "hello").to_witness(), + ..Default::default() + }); + + let second_inscription_id = InscriptionId { txid, index: 1 }; + + context.mine_blocks(1); + + context.index.assert_inscription_location( + second_inscription_id, + SatPoint { + outpoint: unbound_outpoint(), + offset: 0, + }, + None, + ); + + assert_eq!( + context + .index + .get_inscription_entry(second_inscription_id) + .unwrap() + .unwrap() + .number, + -1 + ); + } + } + #[test] fn multiple_inscriptions_in_same_tx_all_but_first_input_are_cursed() { for context in Context::configurations() { diff --git a/src/index/updater/inscription_updater.rs b/src/index/updater/inscription_updater.rs index f4a03dc6be..1034e44303 100644 --- a/src/index/updater/inscription_updater.rs +++ b/src/index/updater/inscription_updater.rs @@ -105,13 +105,13 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { let mut new_inscriptions = Inscription::from_transaction(tx).into_iter().peekable(); let mut floating_inscriptions = Vec::new(); let mut inscribed_offsets = BTreeMap::new(); - let mut input_value = 0; + let mut total_input_value = 0; let mut id_counter = 0; for (input_index, tx_in) in tx.input.iter().enumerate() { // skip subsidy since no inscriptions possible if tx_in.previous_output.is_null() { - input_value += Height(self.height).subsidy(); + total_input_value += Height(self.height).subsidy(); continue; } @@ -121,7 +121,7 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { self.satpoint_to_id, tx_in.previous_output, )? { - let offset = input_value + old_satpoint.offset; + let offset = total_input_value + old_satpoint.offset; floating_inscriptions.push(Flotsam { offset, inscription_id, @@ -134,10 +134,10 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { .or_insert((inscription_id, 0)); } - let offset = input_value; + let offset = total_input_value; // multi-level cache for UTXO set to get to the input amount - input_value += if let Some(value) = self.value_cache.remove(&tx_in.previous_output) { + let current_input_value = if let Some(value) = self.value_cache.remove(&tx_in.previous_output) { value } else if let Some(value) = self .outpoint_to_value @@ -153,6 +153,10 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { })? }; + total_input_value += current_input_value; + dbg!(¤t_input_value); + dbg!(&total_input_value); + // go through all inscriptions in this input while let Some(inscription) = new_inscriptions.peek() { if inscription.tx_in_index != u32::try_from(input_index).unwrap() { @@ -216,7 +220,7 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { curse.is_some() }; - let unbound = input_value == 0 + let unbound = current_input_value == 0 || inscription.tx_in_offset != 0 || curse == Some(Curse::UnrecognizedEvenField); @@ -264,7 +268,7 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { inscription_id, offset, origin: Origin::New { - fee: (input_value - total_output_value) / u64::from(id_counter), + fee: (total_input_value - total_output_value) / u64::from(id_counter), cursed, unbound, }, @@ -338,7 +342,7 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { offset: self.reward + flotsam.offset - output_value, ..flotsam })); - self.reward += input_value - output_value; + self.reward += total_input_value - output_value; Ok(()) } } From 2f71ae244d7606e899b47243338b3197a7ce343b Mon Sep 17 00:00:00 2001 From: raphjaph Date: Wed, 30 Aug 2023 19:54:44 +0200 Subject: [PATCH 2/3] remove dbgs --- src/index/updater/inscription_updater.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/index/updater/inscription_updater.rs b/src/index/updater/inscription_updater.rs index 1034e44303..4b40f06d46 100644 --- a/src/index/updater/inscription_updater.rs +++ b/src/index/updater/inscription_updater.rs @@ -154,8 +154,6 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { }; total_input_value += current_input_value; - dbg!(¤t_input_value); - dbg!(&total_input_value); // go through all inscriptions in this input while let Some(inscription) = new_inscriptions.peek() { From 475d41699b1dee3fc4a924aa1b4e35ed3281438c Mon Sep 17 00:00:00 2001 From: raphjaph Date: Wed, 30 Aug 2023 19:58:37 +0200 Subject: [PATCH 3/3] quick fix --- src/index/updater/inscription_updater.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/index/updater/inscription_updater.rs b/src/index/updater/inscription_updater.rs index 4b40f06d46..cd809fe431 100644 --- a/src/index/updater/inscription_updater.rs +++ b/src/index/updater/inscription_updater.rs @@ -137,7 +137,8 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { let offset = total_input_value; // multi-level cache for UTXO set to get to the input amount - let current_input_value = if let Some(value) = self.value_cache.remove(&tx_in.previous_output) { + let current_input_value = if let Some(value) = self.value_cache.remove(&tx_in.previous_output) + { value } else if let Some(value) = self .outpoint_to_value