Skip to content

Commit

Permalink
Add inscription charms (#2681)
Browse files Browse the repository at this point in the history
  • Loading branch information
casey authored Nov 16, 2023
1 parent b0c8cdf commit 94585a2
Show file tree
Hide file tree
Showing 9 changed files with 457 additions and 144 deletions.
66 changes: 66 additions & 0 deletions src/charm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#[derive(Copy, Clone)]
pub(crate) enum Charm {
Cursed,
Epic,
Legendary,
Lost,
Nineball,
Rare,
Reinscription,
Unbound,
Uncommon,
}

impl Charm {
pub(crate) const ALL: [Charm; 9] = [
Charm::Uncommon,
Charm::Rare,
Charm::Epic,
Charm::Legendary,
Charm::Nineball,
Charm::Reinscription,
Charm::Cursed,
Charm::Unbound,
Charm::Lost,
];

fn flag(self) -> u16 {
1 << self as u16
}

pub(crate) fn set(self, charms: &mut u16) {
*charms |= self.flag();
}

pub(crate) fn is_set(self, charms: u16) -> bool {
charms & self.flag() != 0
}

pub(crate) fn icon(self) -> &'static str {
match self {
Charm::Cursed => "👹",
Charm::Epic => "🪻",
Charm::Legendary => "🌝",
Charm::Lost => "🤔",
Charm::Nineball => "9️⃣",
Charm::Rare => "🧿",
Charm::Reinscription => "♻️",
Charm::Unbound => "🔓",
Charm::Uncommon => "🌱",
}
}

pub(crate) fn title(self) -> &'static str {
match self {
Charm::Cursed => "cursed",
Charm::Epic => "epic",
Charm::Legendary => "legendary",
Charm::Lost => "lost",
Charm::Nineball => "nineball",
Charm::Rare => "rare",
Charm::Reinscription => "reinscription",
Charm::Unbound => "unbound",
Charm::Uncommon => "uncommon",
}
}
}
6 changes: 5 additions & 1 deletion src/index/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ impl Entry for RuneId {

#[derive(Debug)]
pub(crate) struct InscriptionEntry {
pub(crate) charms: u16,
pub(crate) fee: u64,
pub(crate) height: u64,
pub(crate) inscription_number: i64,
Expand All @@ -149,6 +150,7 @@ pub(crate) struct InscriptionEntry {
}

pub(crate) type InscriptionEntryValue = (
u16, // charms
u64, // fee
u64, // height
i64, // inscription number
Expand All @@ -162,9 +164,10 @@ impl Entry for InscriptionEntry {
type Value = InscriptionEntryValue;

fn load(
(fee, height, inscription_number, parent, sat, sequence_number, timestamp): InscriptionEntryValue,
(charms, fee, height, inscription_number, parent, sat, sequence_number, timestamp): InscriptionEntryValue,
) -> Self {
Self {
charms,
fee,
height,
inscription_number,
Expand All @@ -181,6 +184,7 @@ impl Entry for InscriptionEntry {

fn store(self) -> Self::Value {
(
self.charms,
self.fee,
self.height,
self.inscription_number,
Expand Down
148 changes: 76 additions & 72 deletions src/index/updater/inscription_updater.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
use {super::*, inscription::Curse};
use super::*;

#[derive(Debug, PartialEq, Copy, Clone)]
enum Curse {
DuplicateField,
IncompleteField,
NotAtOffsetZero,
NotInFirstInput,
Pointer,
Pushnum,
Reinscription,
UnrecognizedEvenField,
}

#[derive(Debug, Clone)]
pub(super) struct Flotsam {
Expand All @@ -15,6 +27,7 @@ enum Origin {
hidden: bool,
parent: Option<InscriptionId>,
pointer: Option<u64>,
reinscription: bool,
unbound: bool,
},
Old {
Expand Down Expand Up @@ -123,6 +136,8 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> {
index: id_counter,
};

let reinscription = inscribed_offsets.contains_key(&offset);

This comment has been minimized.

Copy link
@huuep

huuep Nov 25, 2023

I believe this doesn't handle the reinscriptions that are created when a sat is inscribed multiple times at once (in 1 txn). inscribed_offsets gets inscriptions from previous transactions only is my guess, and not the current txn which might have both the first inscription of that sat and subsequent reinscriptions.


let curse = if inscription.payload.unrecognized_even_field {
Some(Curse::UnrecognizedEvenField)
} else if inscription.payload.duplicate_field {
Expand All @@ -137,22 +152,12 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> {
Some(Curse::Pointer)
} else if inscription.pushnum {
Some(Curse::Pushnum)
} else if inscribed_offsets.contains_key(&offset) {
let seq_num = self.next_sequence_number;

let sat = Self::calculate_sat(input_sat_ranges, offset);

log::info!("processing reinscription {inscription_id} on sat {:?}: sequence number {seq_num}, inscribed offsets {:?}", sat, inscribed_offsets);

} else if reinscription {
Some(Curse::Reinscription)
} else {
None
};

if curse.is_some() {
log::info!("found cursed inscription {inscription_id}: {:?}", curse);
}

let cursed = if let Some(Curse::Reinscription) = curse {
let first_reinscription = inscribed_offsets
.get(&offset)
Expand All @@ -172,28 +177,18 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> {
})
.unwrap_or(false);

log::info!("{inscription_id}: is first reinscription: {first_reinscription}, initial inscription is cursed: {initial_inscription_is_cursed}");

!(initial_inscription_is_cursed && first_reinscription)
} else {
curse.is_some()
};

let unbound = current_input_value == 0 || curse == Some(Curse::UnrecognizedEvenField);

if curse.is_some() || unbound {
log::info!(
"indexing inscription {inscription_id} with curse {:?} as cursed {} and unbound {}",
curse,
cursed,
unbound
);
}

floating_inscriptions.push(Flotsam {
inscription_id,
offset,
origin: Origin::New {
reinscription,
cursed,
fee: 0,
hidden: inscription.payload.hidden(),
Expand Down Expand Up @@ -229,40 +224,16 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> {

// still have to normalize over inscription size
let total_output_value = tx.output.iter().map(|txout| txout.value).sum::<u64>();
let mut floating_inscriptions = floating_inscriptions
.into_iter()
.map(|flotsam| {
if let Flotsam {
inscription_id,
offset,
origin:
Origin::New {
cursed,
fee: _,
hidden,
parent,
pointer,
unbound,
},
} = flotsam
{
Flotsam {
inscription_id,
offset,
origin: Origin::New {
cursed,
fee: (total_input_value - total_output_value) / u64::from(id_counter),
hidden,
parent,
pointer,
unbound,
},
}
} else {
flotsam
}
})
.collect::<Vec<Flotsam>>();

for flotsam in &mut floating_inscriptions {
if let Flotsam {
origin: Origin::New { ref mut fee, .. },
..
} = flotsam
{
*fee = (total_input_value - total_output_value) / u64::from(id_counter);
}
}

let is_coinbase = tx
.input
Expand Down Expand Up @@ -361,20 +332,19 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> {
input_sat_ranges: Option<&VecDeque<(u64, u64)>>,
input_offset: u64,
) -> Option<Sat> {
let mut sat = None;
if let Some(input_sat_ranges) = input_sat_ranges {
let mut offset = 0;
for (start, end) in input_sat_ranges {
let size = end - start;
if offset + size > input_offset {
let n = start + input_offset - offset;
sat = Some(Sat(n));
break;
}
offset += size;
let input_sat_ranges = input_sat_ranges?;

let mut offset = 0;
for (start, end) in input_sat_ranges {
let size = end - start;
if offset + size > input_offset {
let n = start + input_offset - offset;
return Some(Sat(n));
}
offset += size;
}
sat

unreachable!()
}

fn update_inscription_location(
Expand All @@ -393,10 +363,11 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> {
Origin::New {
cursed,
fee,
hidden,
parent,
pointer: _,
reinscription,
unbound,
hidden,
..
} => {
let inscription_number = if cursed {
let number: i64 = self.cursed_inscription_count.try_into().unwrap();
Expand Down Expand Up @@ -428,19 +399,52 @@ impl<'a, 'db, 'tx> InscriptionUpdater<'a, 'db, 'tx> {
Self::calculate_sat(input_sat_ranges, flotsam.offset)
};

let mut charms = 0;

if cursed {
Charm::Cursed.set(&mut charms);
}

if reinscription {
Charm::Reinscription.set(&mut charms);
}

if let Some(sat) = sat {
if sat.nineball() {
Charm::Nineball.set(&mut charms);
}

match sat.rarity() {
Rarity::Common | Rarity::Mythic => {}
Rarity::Uncommon => Charm::Uncommon.set(&mut charms),
Rarity::Rare => Charm::Rare.set(&mut charms),
Rarity::Epic => Charm::Epic.set(&mut charms),
Rarity::Legendary => Charm::Legendary.set(&mut charms),
}
}

if new_satpoint.outpoint == OutPoint::null() {
Charm::Lost.set(&mut charms);
}

if unbound {
Charm::Unbound.set(&mut charms);
}

if let Some(Sat(n)) = sat {
self.sat_to_inscription_id.insert(&n, &inscription_id)?;
}

self.id_to_entry.insert(
&inscription_id,
&InscriptionEntry {
charms,
fee,
height: self.height,
inscription_number,
sequence_number,
parent,
sat,
sequence_number,
timestamp: self.timestamp,
}
.store(),
Expand Down
12 changes: 0 additions & 12 deletions src/inscription.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,6 @@ use {
std::str,
};

#[derive(Debug, PartialEq, Clone)]
pub(crate) enum Curse {
DuplicateField,
IncompleteField,
NotAtOffsetZero,
NotInFirstInput,
Pointer,
Pushnum,
Reinscription,
UnrecognizedEvenField,
}

#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Eq, Default)]
pub struct Inscription {
pub body: Option<Vec<u8>>,
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use {
self::{
arguments::Arguments,
blocktime::Blocktime,
charm::Charm,
config::Config,
decimal::Decimal,
degree::Degree,
Expand Down Expand Up @@ -108,6 +109,7 @@ macro_rules! tprintln {
mod arguments;
mod blocktime;
mod chain;
mod charm;
mod config;
mod decimal;
mod degree;
Expand Down
Loading

0 comments on commit 94585a2

Please sign in to comment.