Skip to content

Commit

Permalink
Inscriptions with unrecognized even fields are unbound and cursed (#2359
Browse files Browse the repository at this point in the history
)
  • Loading branch information
raphjaph authored Aug 29, 2023
1 parent 04701d2 commit d41edf7
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 11 deletions.
46 changes: 46 additions & 0 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2562,6 +2562,52 @@ mod tests {
}
}

#[test]
fn unrecognized_even_field_inscriptions_are_cursed_and_unbound() {
for context in Context::configurations() {
context.mine_blocks(1);

let witness = envelope(&[
b"ord",
&[1],
b"text/plain;charset=utf-8",
&[2],
b"bar",
&[4],
b"ord",
]);

let txid = context.rpc_server.broadcast_tx(TransactionTemplate {
inputs: &[(1, 0, 0)],
witness,
..Default::default()
});

let inscription_id = InscriptionId { txid, index: 0 };

context.mine_blocks(1);

context.index.assert_inscription_location(
inscription_id,
SatPoint {
outpoint: unbound_outpoint(),
offset: 0,
},
None,
);

assert_eq!(
context
.index
.get_inscription_entry(inscription_id)
.unwrap()
.unwrap()
.number,
-1
);
}
}

#[test]
// https://github.com/ordinals/ord/issues/2062
fn zero_value_transaction_inscription_not_cursed_but_unbound() {
Expand Down
8 changes: 6 additions & 2 deletions src/index/updater/inscription_updater.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,9 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> {
index: id_counter,
};

let curse = if inscription.tx_in_index != 0 {
let curse = if inscription.inscription.unrecognized_even_field {
Some(Curse::UnrecognizedEvenField)
} else if inscription.tx_in_index != 0 {
Some(Curse::NotInFirstInput)
} else if inscription.tx_in_offset != 0 {
Some(Curse::NotAtOffsetZero)
Expand Down Expand Up @@ -214,7 +216,9 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> {
curse.is_some()
};

let unbound = input_value == 0 || inscription.tx_in_offset != 0;
let unbound = input_value == 0
|| inscription.tx_in_offset != 0
|| curse == Some(Curse::UnrecognizedEvenField);

if curse.is_some() || unbound {
log::info!(
Expand Down
35 changes: 29 additions & 6 deletions src/inscription.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@ pub(crate) enum Curse {
NotInFirstInput,
NotAtOffsetZero,
Reinscription,
UnrecognizedEvenField,
}

#[derive(Debug, PartialEq, Clone)]
pub struct Inscription {
body: Option<Vec<u8>>,
content_type: Option<Vec<u8>>,
pub(crate) unrecognized_even_field: bool,
}

#[derive(Debug, PartialEq, Clone)]
Expand All @@ -38,7 +40,11 @@ pub(crate) struct TransactionInscription {
impl Inscription {
#[cfg(test)]
pub(crate) fn new(content_type: Option<Vec<u8>>, body: Option<Vec<u8>>) -> Self {
Self { content_type, body }
Self {
content_type,
body,
unrecognized_even_field: false,
}
}

pub(crate) fn from_transaction(tx: &Transaction) -> Vec<TransactionInscription> {
Expand Down Expand Up @@ -81,6 +87,7 @@ impl Inscription {
Ok(Self {
body: Some(body),
content_type: Some(content_type.into()),
unrecognized_even_field: false,
})
}

Expand Down Expand Up @@ -160,7 +167,6 @@ pub(crate) enum InscriptionError {
KeyPathSpend,
NoInscription,
Script(script::Error),
UnrecognizedEvenField,
}

type Result<T, E = InscriptionError> = std::result::Result<T, E>;
Expand Down Expand Up @@ -250,12 +256,20 @@ impl<'a> InscriptionParser<'a> {
for tag in fields.keys() {
if let Some(lsb) = tag.first() {
if lsb % 2 == 0 {
return Err(InscriptionError::UnrecognizedEvenField);
return Ok(Inscription {
body,
content_type,
unrecognized_even_field: true,
});
}
}
}

Ok(Inscription { body, content_type })
Ok(Inscription {
body,
content_type,
unrecognized_even_field: false,
})
}

fn advance(&mut self) -> Result<Instruction<'a>> {
Expand Down Expand Up @@ -413,6 +427,7 @@ mod tests {
Ok(vec![Inscription {
content_type: Some(b"text/plain;charset=utf-8".to_vec()),
body: None,
unrecognized_even_field: false,
}]),
);
}
Expand All @@ -424,6 +439,7 @@ mod tests {
Ok(vec![Inscription {
content_type: None,
body: Some(b"foo".to_vec()),
unrecognized_even_field: false,
}]),
);
}
Expand Down Expand Up @@ -754,6 +770,7 @@ mod tests {
&Inscription {
content_type: None,
body: None,
unrecognized_even_field: false,
}
.append_reveal_script(script::Builder::new()),
);
Expand All @@ -765,6 +782,7 @@ mod tests {
vec![Inscription {
content_type: None,
body: None,
unrecognized_even_field: false,
}]
);
}
Expand All @@ -776,15 +794,20 @@ mod tests {
Ok(vec![Inscription {
content_type: None,
body: None,
unrecognized_even_field: false,
}]),
);
}

#[test]
fn unknown_even_fields_are_invalid() {
fn unknown_even_fields() {
assert_eq!(
InscriptionParser::parse(&envelope(&[b"ord", &[2], &[0]])),
Err(InscriptionError::UnrecognizedEvenField),
Ok(vec![Inscription {
content_type: None,
body: None,
unrecognized_even_field: true,
}]),
);
}
}
7 changes: 4 additions & 3 deletions src/test.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
pub(crate) use {
super::*,
crate::inscription::TransactionInscription,
bitcoin::blockdata::script::PushBytesBuf,
bitcoin::blockdata::{opcodes, script},
bitcoin::{ScriptBuf, Witness},
bitcoin::{
blockdata::{opcodes, script, script::PushBytesBuf},
ScriptBuf, Witness,
},
pretty_assertions::assert_eq as pretty_assert_eq,
std::iter,
test_bitcoincore_rpc::TransactionTemplate,
Expand Down

0 comments on commit d41edf7

Please sign in to comment.