Skip to content

Commit

Permalink
Add charm to burned inscriptions (#3836)
Browse files Browse the repository at this point in the history
  • Loading branch information
onchainguy-btc authored Jul 1, 2024
1 parent 8a07f11 commit 9121870
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 8 deletions.
2 changes: 2 additions & 0 deletions crates/mockcore/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ pub struct TransactionTemplate<'a> {
pub inputs: &'a [(usize, usize, usize, Witness)],
pub op_return: Option<ScriptBuf>,
pub op_return_index: Option<usize>,
pub op_return_value: Option<u64>,
pub output_values: &'a [u64],
pub outputs: usize,
pub p2tr: bool,
Expand Down Expand Up @@ -180,6 +181,7 @@ impl<'a> Default for TransactionTemplate<'a> {
inputs: &[],
op_return: None,
op_return_index: None,
op_return_value: None,
output_values: &[],
outputs: 1,
p2tr: false,
Expand Down
2 changes: 1 addition & 1 deletion crates/mockcore/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ impl State {
tx.output.insert(
template.op_return_index.unwrap_or(tx.output.len()),
TxOut {
value: 0,
value: template.op_return_value.unwrap_or_default(),
script_pubkey,
},
);
Expand Down
11 changes: 8 additions & 3 deletions crates/ordinals/src/charm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ pub enum Charm {
Uncommon = 9,
Vindicated = 10,
Mythic = 11,
Burned = 12,
}

impl Charm {
pub const ALL: [Self; 12] = [
pub const ALL: [Self; 13] = [
Self::Coin,
Self::Uncommon,
Self::Rare,
Expand All @@ -30,6 +31,7 @@ impl Charm {
Self::Unbound,
Self::Lost,
Self::Vindicated,
Self::Burned,
];

fn flag(self) -> u16 {
Expand All @@ -50,18 +52,19 @@ impl Charm {

pub fn icon(self) -> &'static str {
match self {
Self::Burned => "🔥",
Self::Coin => "🪙",
Self::Cursed => "👹",
Self::Epic => "🪻",
Self::Legendary => "🌝",
Self::Lost => "🤔",
Self::Mythic => "🎃",
Self::Nineball => "9️⃣",
Self::Nineball => "\u{39}\u{fe0f}\u{20e3}",
Self::Rare => "🧿",
Self::Reinscription => "♻️",
Self::Unbound => "🔓",
Self::Uncommon => "🌱",
Self::Vindicated => "❤️‍🔥",
Self::Vindicated => "\u{2764}\u{fe0f}\u{200d}\u{1f525}",
}
}

Expand All @@ -79,6 +82,7 @@ impl Display for Charm {
f,
"{}",
match self {
Self::Burned => "burned",
Self::Coin => "coin",
Self::Cursed => "cursed",
Self::Epic => "epic",
Expand All @@ -101,6 +105,7 @@ impl FromStr for Charm {

fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"burned" => Self::Burned,
"coin" => Self::Coin,
"cursed" => Self::Cursed,
"epic" => Self::Epic,
Expand Down
35 changes: 31 additions & 4 deletions src/index/updater/inscription_updater.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,11 @@ impl<'a, 'tx> InscriptionUpdater<'a, 'tx> {
offset: flotsam.offset - output_value,
};

new_locations.push((new_satpoint, inscriptions.next().unwrap()));
new_locations.push((
new_satpoint,
inscriptions.next().unwrap(),
txout.script_pubkey.is_op_return(),
));
}

range_to_vout.insert((output_value, end), vout.try_into().unwrap());
Expand All @@ -322,7 +326,7 @@ impl<'a, 'tx> InscriptionUpdater<'a, 'tx> {
);
}

for (new_satpoint, mut flotsam) in new_locations.into_iter() {
for (new_satpoint, mut flotsam, op_return) in new_locations.into_iter() {
let new_satpoint = match flotsam.origin {
Origin::New {
pointer: Some(pointer),
Expand All @@ -344,7 +348,7 @@ impl<'a, 'tx> InscriptionUpdater<'a, 'tx> {
_ => new_satpoint,
};

self.update_inscription_location(input_sat_ranges, flotsam, new_satpoint)?;
self.update_inscription_location(input_sat_ranges, flotsam, new_satpoint, op_return)?;
}

if is_coinbase {
Expand All @@ -353,7 +357,7 @@ impl<'a, 'tx> InscriptionUpdater<'a, 'tx> {
outpoint: OutPoint::null(),
offset: self.lost_sats + flotsam.offset - output_value,
};
self.update_inscription_location(input_sat_ranges, flotsam, new_satpoint)?;
self.update_inscription_location(input_sat_ranges, flotsam, new_satpoint, false)?;
}
self.lost_sats += self.reward - output_value;
Ok(())
Expand Down Expand Up @@ -391,6 +395,7 @@ impl<'a, 'tx> InscriptionUpdater<'a, 'tx> {
input_sat_ranges: Option<&VecDeque<(u64, u64)>>,
flotsam: Flotsam,
new_satpoint: SatPoint,
op_return: bool,
) -> Result {
let inscription_id = flotsam.inscription_id;
let (unbound, sequence_number) = match flotsam.origin {
Expand All @@ -405,6 +410,24 @@ impl<'a, 'tx> InscriptionUpdater<'a, 'tx> {
.unwrap()
.value();

if op_return {
let entry = InscriptionEntry::load(
self
.sequence_number_to_entry
.get(&sequence_number)?
.unwrap()
.value(),
);

let mut charms = entry.charms;
Charm::Burned.set(&mut charms);

self.sequence_number_to_entry.insert(
sequence_number,
&InscriptionEntry { charms, ..entry }.store(),
)?;
}

if let Some(sender) = self.event_sender {
sender.blocking_send(Event::InscriptionTransferred {
block_height: self.height,
Expand Down Expand Up @@ -464,6 +487,10 @@ impl<'a, 'tx> InscriptionUpdater<'a, 'tx> {
charms |= sat.charms();
}

if op_return {
Charm::Burned.set(&mut charms);
}

if new_satpoint.outpoint == OutPoint::null() {
Charm::Lost.set(&mut charms);
}
Expand Down
150 changes: 150 additions & 0 deletions src/subcommand/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6978,4 +6978,154 @@ next
let server = TestServer::builder().build();
server.assert_response("/update", StatusCode::NOT_FOUND, "");
}

#[test]
fn burned_charm() {
let server = TestServer::builder().chain(Chain::Regtest).build();

server.mine_blocks(1);

let inscription = Inscription {
content_type: Some("text/html".into()),
body: Some("foo".into()),
..default()
};

let txid = server.core.broadcast_tx(TransactionTemplate {
inputs: &[(1, 0, 0, inscription.to_witness())],
outputs: 0,
op_return_index: Some(0),
op_return_value: Some(50 * COIN_VALUE),
op_return: Some(
script::Builder::new()
.push_opcode(opcodes::all::OP_RETURN)
.into_script(),
),
..default()
});

server.mine_blocks(1);

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

pretty_assert_eq!(
server.get_json::<api::InscriptionRecursive>(format!("/r/inscription/{id}")),
api::InscriptionRecursive {
charms: vec![Charm::Burned],
content_type: Some("text/html".into()),
content_length: Some(3),
delegate: None,
fee: 0,
height: 2,
id,
number: 0,
output: OutPoint { txid, vout: 0 },
sat: None,
satpoint: SatPoint {
outpoint: OutPoint { txid, vout: 0 },
offset: 0
},
timestamp: 2,
value: Some(50 * COIN_VALUE),
}
);
}

#[test]
fn burned_charm_on_transfer() {
let server = TestServer::builder().chain(Chain::Regtest).build();

server.mine_blocks(1);

let inscription = Inscription {
content_type: Some("text/html".into()),
body: Some("foo".into()),
..default()
};

let create_txid = server.core.broadcast_tx(TransactionTemplate {
inputs: &[(1, 0, 0, inscription.to_witness())],
outputs: 1,
..default()
});

server.mine_blocks(1);

let id = InscriptionId {
txid: create_txid,
index: 0,
};

pretty_assert_eq!(
server.get_json::<api::InscriptionRecursive>(format!("/r/inscription/{id}")),
api::InscriptionRecursive {
charms: vec![],
content_type: Some("text/html".into()),
content_length: Some(3),
delegate: None,
fee: 0,
height: 2,
id,
number: 0,
output: OutPoint {
txid: create_txid,
vout: 0
},
sat: None,
satpoint: SatPoint {
outpoint: OutPoint {
txid: create_txid,
vout: 0
},
offset: 0
},
timestamp: 2,
value: Some(50 * COIN_VALUE),
}
);

let transfer_txid = server.core.broadcast_tx(TransactionTemplate {
inputs: &[(2, 1, 0, Default::default())],
fee: 0,
outputs: 0,
op_return_index: Some(0),
op_return_value: Some(50 * COIN_VALUE),
op_return: Some(
script::Builder::new()
.push_opcode(opcodes::all::OP_RETURN)
.into_script(),
),
..default()
});

server.mine_blocks(1);

pretty_assert_eq!(
server.get_json::<api::InscriptionRecursive>(format!("/r/inscription/{id}")),
api::InscriptionRecursive {
charms: vec![Charm::Burned],
content_type: Some("text/html".into()),
content_length: Some(3),
delegate: None,
fee: 0,
height: 2,
id,
number: 0,
output: OutPoint {
txid: transfer_txid,
vout: 0
},
sat: None,
satpoint: SatPoint {
outpoint: OutPoint {
txid: transfer_txid,
vout: 0
},
offset: 0
},
timestamp: 2,
value: Some(50 * COIN_VALUE),
}
);
}
}

0 comments on commit 9121870

Please sign in to comment.