diff --git a/docs/src/inscriptions.md b/docs/src/inscriptions.md index 3104cee8b9..3aa05ee833 100644 --- a/docs/src/inscriptions.md +++ b/docs/src/inscriptions.md @@ -124,6 +124,22 @@ go through the inputs consecutively and look for all inscription `envelopes`. | 3 | 0 | | | 4 | 1 | i6 | +Inscription Numbers +------------------- + +Inscriptions are assigned inscription numbers starting at zero, first by the +order reveal transactions appear in blocks, and the order that reveal envelopes +appear in those transactions. + +Due to a historical bug in `ord` which cannot be fixed without changing a great +many inscription numbers, inscriptions which are revealed and then immediately +spent to fees are numbered as if they appear last in the block in which they +are revealed. + +Inscriptions which are cursed are numbered starting at negative one, counting +down. Cursed inscriptions on and after the jubilee at block 824544 are +vindicated, and are assigned positive inscription numbers. + Sandboxing ---------- diff --git a/src/index.rs b/src/index.rs index 2991ddaf20..fa14f2637e 100644 --- a/src/index.rs +++ b/src/index.rs @@ -722,6 +722,15 @@ impl Index { .unwrap_or_default() } + #[cfg(test)] + pub(crate) fn inscription_number(&self, inscription_id: InscriptionId) -> i32 { + self + .get_inscription_entry(inscription_id) + .unwrap() + .unwrap() + .inscription_number + } + pub(crate) fn block_count(&self) -> Result { self.begin_read()?.block_count() } @@ -3290,15 +3299,7 @@ mod tests { None, ); - assert_eq!( - context - .index - .get_inscription_entry(inscription_id) - .unwrap() - .unwrap() - .inscription_number, - -1 - ); + assert_eq!(context.index.inscription_number(inscription_id), -1); } } @@ -3335,15 +3336,7 @@ mod tests { None, ); - assert_eq!( - context - .index - .get_inscription_entry(inscription_id) - .unwrap() - .unwrap() - .inscription_number, - 0 - ); + assert_eq!(context.index.inscription_number(inscription_id), 0); } } @@ -3371,15 +3364,7 @@ mod tests { assert_eq!(context.rpc_server.height(), 109); - assert_eq!( - context - .index - .get_inscription_entry(inscription_id) - .unwrap() - .unwrap() - .inscription_number, - -1 - ); + assert_eq!(context.index.inscription_number(inscription_id), -1); let txid = context.rpc_server.broadcast_tx(TransactionTemplate { inputs: &[(2, 0, 0, witness)], @@ -3392,15 +3377,7 @@ mod tests { assert_eq!(context.rpc_server.height(), 110); - assert_eq!( - context - .index - .get_inscription_entry(inscription_id) - .unwrap() - .unwrap() - .inscription_number, - 0 - ); + assert_eq!(context.index.inscription_number(inscription_id), 0); } } @@ -3426,15 +3403,7 @@ mod tests { context.mine_blocks(1); - assert_eq!( - context - .index - .get_inscription_entry(inscription_id) - .unwrap() - .unwrap() - .inscription_number, - -1 - ); + assert_eq!(context.index.inscription_number(inscription_id), -1); } } @@ -3454,15 +3423,7 @@ mod tests { context.mine_blocks(1); - assert_eq!( - context - .index - .get_inscription_entry(inscription_id) - .unwrap() - .unwrap() - .inscription_number, - -1 - ); + assert_eq!(context.index.inscription_number(inscription_id), -1); } } @@ -3491,15 +3452,7 @@ mod tests { context.mine_blocks(1); - assert_eq!( - context - .index - .get_inscription_entry(inscription_id) - .unwrap() - .unwrap() - .inscription_number, - -1 - ); + assert_eq!(context.index.inscription_number(inscription_id), -1); } } @@ -3529,15 +3482,7 @@ mod tests { context.mine_blocks(1); - assert_eq!( - context - .index - .get_inscription_entry(inscription_id) - .unwrap() - .unwrap() - .inscription_number, - -1 - ); + assert_eq!(context.index.inscription_number(inscription_id), -1); } } @@ -3573,15 +3518,7 @@ mod tests { None, ); - assert_eq!( - context - .index - .get_inscription_entry(inscription_id) - .unwrap() - .unwrap() - .inscription_number, - 0 - ); + assert_eq!(context.index.inscription_number(inscription_id), 0); } } @@ -3619,15 +3556,7 @@ mod tests { None, ); - assert_eq!( - context - .index - .get_inscription_entry(second_inscription_id) - .unwrap() - .unwrap() - .inscription_number, - -1 - ); + assert_eq!(context.index.inscription_number(second_inscription_id), -1); } } @@ -3682,35 +3611,9 @@ mod tests { Some(150 * COIN_VALUE), ); - assert_eq!( - context - .index - .get_inscription_entry(first) - .unwrap() - .unwrap() - .inscription_number, - 0 - ); - - assert_eq!( - context - .index - .get_inscription_entry(second) - .unwrap() - .unwrap() - .inscription_number, - -1 - ); - - assert_eq!( - context - .index - .get_inscription_entry(third) - .unwrap() - .unwrap() - .inscription_number, - -2 - ); + assert_eq!(context.index.inscription_number(first), 0); + assert_eq!(context.index.inscription_number(second), -1); + assert_eq!(context.index.inscription_number(third), -2); } } @@ -3786,35 +3689,9 @@ mod tests { Some(50 * COIN_VALUE), ); - assert_eq!( - context - .index - .get_inscription_entry(first) - .unwrap() - .unwrap() - .inscription_number, - 0 - ); - - assert_eq!( - context - .index - .get_inscription_entry(second) - .unwrap() - .unwrap() - .inscription_number, - -1 - ); - - assert_eq!( - context - .index - .get_inscription_entry(third) - .unwrap() - .unwrap() - .inscription_number, - -2 - ); + assert_eq!(context.index.inscription_number(first), 0); + assert_eq!(context.index.inscription_number(second), -1); + assert_eq!(context.index.inscription_number(third), -2); } } @@ -3906,15 +3783,7 @@ mod tests { Some(150 * COIN_VALUE), ); - assert_eq!( - context - .index - .get_inscription_entry(first) - .unwrap() - .unwrap() - .inscription_number, - 0 - ); + assert_eq!(context.index.inscription_number(first), 0); assert_eq!( context @@ -3925,25 +3794,9 @@ mod tests { fourth ); - assert_eq!( - context - .index - .get_inscription_entry(fourth) - .unwrap() - .unwrap() - .inscription_number, - -3 - ); + assert_eq!(context.index.inscription_number(fourth), -3); - assert_eq!( - context - .index - .get_inscription_entry(ninth) - .unwrap() - .unwrap() - .inscription_number, - -8 - ); + assert_eq!(context.index.inscription_number(ninth), -8); } } @@ -4047,15 +3900,7 @@ mod tests { Some(100 * COIN_VALUE), ); - assert_eq!( - context - .index - .get_inscription_entry(cursed) - .unwrap() - .unwrap() - .inscription_number, - -1 - ); + assert_eq!(context.index.inscription_number(cursed), -1); let witness = envelope(&[ b"ord", @@ -4083,15 +3928,7 @@ mod tests { Some(100 * COIN_VALUE), ); - assert_eq!( - context - .index - .get_inscription_entry(reinscription_on_cursed) - .unwrap() - .unwrap() - .inscription_number, - 1 - ); + assert_eq!(context.index.inscription_number(reinscription_on_cursed), 1); } } @@ -4128,15 +3965,7 @@ mod tests { Some(100 * COIN_VALUE), ); - assert_eq!( - context - .index - .get_inscription_entry(cursed) - .unwrap() - .unwrap() - .inscription_number, - -1 - ); + assert_eq!(context.index.inscription_number(cursed), -1); let witness = envelope(&[ b"ord", @@ -4164,15 +3993,7 @@ mod tests { Some(100 * COIN_VALUE), ); - assert_eq!( - context - .index - .get_inscription_entry(reinscription_on_cursed) - .unwrap() - .unwrap() - .inscription_number, - 1 - ); + assert_eq!(context.index.inscription_number(reinscription_on_cursed), 1); let witness = envelope(&[ b"ord", @@ -4203,10 +4024,7 @@ mod tests { assert_eq!( context .index - .get_inscription_entry(second_reinscription_on_cursed) - .unwrap() - .unwrap() - .inscription_number, + .inscription_number(second_reinscription_on_cursed), -2 ); @@ -4934,15 +4752,7 @@ mod tests { Some(50 * COIN_VALUE), ); - assert_eq!( - context - .index - .get_inscription_entry(inscription_id) - .unwrap() - .unwrap() - .inscription_number, - -1 - ); + assert_eq!(context.index.inscription_number(inscription_id), -1); } } @@ -4998,15 +4808,7 @@ mod tests { Some(50 * COIN_VALUE), ); - assert_eq!( - context - .index - .get_inscription_entry(child_inscription_id) - .unwrap() - .unwrap() - .inscription_number, - -1 - ); + assert_eq!(context.index.inscription_number(child_inscription_id), -1); assert_eq!( context @@ -5351,23 +5153,10 @@ mod tests { Some(50 * COIN_VALUE), ); - assert_eq!( - context - .index - .get_inscription_entry(inscription_id) - .unwrap() - .unwrap() - .inscription_number, - 0 - ); + assert_eq!(context.index.inscription_number(inscription_id), 0); assert_eq!( - context - .index - .get_inscription_entry(cursed_reinscription_id) - .unwrap() - .unwrap() - .inscription_number, + context.index.inscription_number(cursed_reinscription_id), -1 ); } @@ -5840,4 +5629,31 @@ mod tests { }) .unwrap()); } + + #[test] + fn fee_spent_inscriptions_are_numbered_last_in_block() { + for context in Context::configurations() { + context.mine_blocks(2); + + let txid = context.rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[(1, 0, 0, inscription("text/plain", "hello").to_witness())], + fee: 50 * COIN_VALUE, + ..Default::default() + }); + + let a = InscriptionId { txid, index: 0 }; + + let txid = context.rpc_server.broadcast_tx(TransactionTemplate { + inputs: &[(2, 0, 0, inscription("text/plain", "hello").to_witness())], + ..Default::default() + }); + + let b = InscriptionId { txid, index: 0 }; + + context.mine_blocks(1); + + assert_eq!(context.index.inscription_number(a), 1); + assert_eq!(context.index.inscription_number(b), 0); + } + } } diff --git a/src/index/updater/inscription_updater.rs b/src/index/updater/inscription_updater.rs index 19f99033cc..8c65881014 100644 --- a/src/index/updater/inscription_updater.rs +++ b/src/index/updater/inscription_updater.rs @@ -188,10 +188,6 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { None }; - let unbound = current_input_value == 0 - || curse == Some(Curse::UnrecognizedEvenField) - || inscription.payload.unrecognized_even_field; - let offset = inscription .payload .pointer() @@ -208,7 +204,9 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { parent: inscription.payload.parent(), pointer: inscription.payload.pointer(), reinscription: inscribed_offsets.get(&offset).is_some(), - unbound, + unbound: current_input_value == 0 + || curse == Some(Curse::UnrecognizedEvenField) + || inscription.payload.unrecognized_even_field, vindicated: curse.is_some() && jubilant, }, }); @@ -411,13 +409,10 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> { let inscription_number = if cursed { let number: i32 = self.cursed_inscription_count.try_into().unwrap(); self.cursed_inscription_count += 1; - - // because cursed numbers start at -1 -(number + 1) } else { let number: i32 = self.blessed_inscription_count.try_into().unwrap(); self.blessed_inscription_count += 1; - number };