From 118bce591849672151b7f8b1d855fb29e26a07bc Mon Sep 17 00:00:00 2001 From: zizibizi <54120867+harutyunaraci@users.noreply.github.com> Date: Tue, 2 Apr 2024 11:33:50 +0400 Subject: [PATCH] Revert "Allow supply-capped mints (#3365)" This reverts commit 293a8eae4c8b80ca1d05647290cc4538785c87be. --- src/index.rs | 2 +- src/index/entry.rs | 212 ++------------ src/index/testing.rs | 2 +- src/index/updater.rs | 19 +- src/index/updater/rune_updater.rs | 91 +++--- src/runes.rs | 448 +++++++++--------------------- src/runes/etching.rs | 5 +- src/runes/mint.rs | 1 - src/runes/runestone.rs | 186 ++++--------- src/runes/tag.rs | 2 - src/subcommand/runes.rs | 7 +- src/subcommand/server.rs | 14 +- src/subcommand/wallet/inscribe.rs | 23 -- src/subcommand/wallet/mint.rs | 2 +- src/templates/rune.rs | 67 ++++- src/wallet/batch/etching.rs | 1 - src/wallet/batch/mint.rs | 1 - src/wallet/batch/plan.rs | 8 +- templates/rune.html | 12 +- tests/json_api.rs | 4 + tests/lib.rs | 19 +- tests/wallet/balance.rs | 1 - tests/wallet/inscribe.rs | 153 ---------- tests/wallet/mint.rs | 7 - tests/wallet/selection.rs | 2 - tests/wallet/send.rs | 1 - 26 files changed, 339 insertions(+), 951 deletions(-) diff --git a/src/index.rs b/src/index.rs index b87ff832f8..c3219f70c6 100644 --- a/src/index.rs +++ b/src/index.rs @@ -47,7 +47,7 @@ mod updater; #[cfg(test)] pub(crate) mod testing; -const SCHEMA_VERSION: u64 = 23; +const SCHEMA_VERSION: u64 = 22; macro_rules! define_table { ($name:ident, $key:ty, $value:ty) => { diff --git a/src/index/entry.rs b/src/index/entry.rs index e32d107f5b..47796eac54 100644 --- a/src/index/entry.rs +++ b/src/index/entry.rs @@ -34,10 +34,11 @@ pub struct RuneEntry { pub divisibility: u8, pub etching: Txid, pub mint: Option, - pub mints: u128, + pub mints: u64, pub number: u64, pub premine: u128, pub spaced_rune: SpacedRune, + pub supply: u128, pub symbol: Option, pub timestamp: u32, } @@ -45,40 +46,22 @@ pub struct RuneEntry { impl RuneEntry { pub fn mintable(&self, block_height: Height, block_time: u32) -> Result { let Some(mint) = self.mint else { - return Err(MintError::Unmintable); + return Err(MintError::Unmintable(self.spaced_rune.rune)); }; if let Some(end) = mint.end { if block_height.0 >= end { - return Err(MintError::End(end)); + return Err(MintError::End((self.spaced_rune.rune, end))); } } if let Some(deadline) = mint.deadline { if block_time >= deadline { - return Err(MintError::Deadline(deadline)); + return Err(MintError::Deadline((self.spaced_rune.rune, deadline))); } } - let cap = mint.cap.unwrap_or_default(); - - if self.mints >= cap { - return Err(MintError::Cap(cap)); - } - - Ok(mint.limit.unwrap_or_default()) - } - - pub fn supply(&self) -> u128 { - self.premine + self.mints * self.mint.and_then(|mint| mint.limit).unwrap_or_default() - } - - pub fn pile(&self, amount: u128) -> Pile { - Pile { - amount, - divisibility: self.divisibility, - symbol: self.symbol, - } + Ok(mint.limit.unwrap_or(runes::MAX_LIMIT)) } } @@ -87,24 +70,23 @@ pub(super) type RuneEntryValue = ( u8, // divisibility (u128, u128), // etching Option, // mint parameters - u128, // mints + u64, // mints u64, // number u128, // premine (u128, u32), // spaced rune + u128, // supply Option, // symbol u32, // timestamp ); #[derive(Debug, PartialEq, Copy, Clone, Serialize, Deserialize, Default)] pub struct MintEntry { - pub cap: Option, // mint cap pub deadline: Option, // unix timestamp pub end: Option, // block height pub limit: Option, // claim amount } type MintEntryValue = ( - Option, // cap Option, // deadline Option, // end Option, // limit @@ -121,6 +103,7 @@ impl Default for RuneEntry { number: 0, premine: 0, spaced_rune: SpacedRune::default(), + supply: 0, symbol: None, timestamp: 0, } @@ -140,6 +123,7 @@ impl Entry for RuneEntry { number, premine, (rune, spacers), + supply, symbol, timestamp, ): RuneEntryValue, @@ -157,8 +141,7 @@ impl Entry for RuneEntry { high[14], high[15], ]) }, - mint: mint.map(|(cap, deadline, end, limit)| MintEntry { - cap, + mint: mint.map(|(deadline, end, limit)| MintEntry { deadline, end, limit, @@ -170,6 +153,7 @@ impl Entry for RuneEntry { rune: Rune(rune), spacers, }, + supply, symbol, timestamp, } @@ -194,16 +178,16 @@ impl Entry for RuneEntry { }, self.mint.map( |MintEntry { - cap, deadline, end, limit, - }| (cap, deadline, end, limit), + }| (deadline, end, limit), ), self.mints, self.number, self.premine, (self.spaced_rune.rune.0, self.spaced_rune.spacers), + self.supply, self.symbol, self.timestamp, ) @@ -508,7 +492,6 @@ mod tests { 0x1E, 0x1F, ]), mint: Some(MintEntry { - cap: Some(1), deadline: Some(2), end: Some(4), limit: Some(5), @@ -520,6 +503,7 @@ mod tests { rune: Rune(7), spacers: 8, }, + supply: 9, symbol: Some('a'), timestamp: 10, }; @@ -531,11 +515,12 @@ mod tests { 0x0F0E0D0C0B0A09080706050403020100, 0x1F1E1D1C1B1A19181716151413121110, ), - Some((Some(1), Some(2), Some(4), Some(5))), + Some((Some(2), Some(4), Some(5))), 11, 6, 12, (7, 8), + 9, Some('a'), 10, ); @@ -565,167 +550,4 @@ mod tests { assert_eq!(actual, expected); } - - #[test] - fn mintable() { - assert_eq!( - RuneEntry::default().mintable(Height(0), 0), - Err(MintError::Unmintable) - ); - - assert_eq!( - RuneEntry { - mint: Some(MintEntry { - end: Some(1), - limit: Some(1000), - cap: Some(1), - ..default() - }), - ..default() - } - .mintable(Height(0), 0), - Ok(1000), - ); - - assert_eq!( - RuneEntry { - mint: Some(MintEntry { - end: Some(1), - limit: Some(1000), - cap: Some(1), - ..default() - }), - ..default() - } - .mintable(Height(1), 0), - Err(MintError::End(1)), - ); - - assert_eq!( - RuneEntry { - mint: Some(MintEntry { - deadline: Some(1), - limit: Some(1000), - cap: Some(1), - ..default() - }), - ..default() - } - .mintable(Height(0), 0), - Ok(1000), - ); - - assert_eq!( - RuneEntry { - mint: Some(MintEntry { - deadline: Some(1), - limit: Some(1000), - cap: Some(1), - ..default() - }), - ..default() - } - .mintable(Height(0), 1), - Err(MintError::Deadline(1)), - ); - - assert_eq!( - RuneEntry { - mint: Some(MintEntry { - cap: Some(1), - limit: Some(1000), - ..default() - }), - mints: 0, - ..default() - } - .mintable(Height(0), 0), - Ok(1000), - ); - - assert_eq!( - RuneEntry { - mint: Some(MintEntry { - cap: Some(1), - limit: Some(1000), - ..default() - }), - mints: 1, - ..default() - } - .mintable(Height(0), 0), - Err(MintError::Cap(1)), - ); - - assert_eq!( - RuneEntry { - mint: Some(MintEntry { - cap: None, - limit: Some(1000), - ..default() - }), - mints: 0, - ..default() - } - .mintable(Height(0), 0), - Err(MintError::Cap(0)), - ); - } - - #[test] - fn supply() { - assert_eq!( - RuneEntry { - mint: Some(MintEntry { - limit: Some(1000), - ..default() - }), - mints: 0, - ..default() - } - .supply(), - 0 - ); - - assert_eq!( - RuneEntry { - mint: Some(MintEntry { - limit: Some(1000), - ..default() - }), - mints: 1, - ..default() - } - .supply(), - 1000 - ); - - assert_eq!( - RuneEntry { - mint: Some(MintEntry { - limit: Some(1000), - ..default() - }), - mints: 0, - premine: 1, - ..default() - } - .supply(), - 1 - ); - - assert_eq!( - RuneEntry { - mint: Some(MintEntry { - limit: Some(1000), - ..default() - }), - mints: 1, - premine: 1, - ..default() - } - .supply(), - 1001 - ); - } } diff --git a/src/index/testing.rs b/src/index/testing.rs index dd0c5ed8ab..0032a3e68f 100644 --- a/src/index/testing.rs +++ b/src/index/testing.rs @@ -147,7 +147,7 @@ impl Context { for (id, entry) in runes { pretty_assert_eq!( outstanding.get(id).copied().unwrap_or_default(), - entry.supply() - entry.burned + entry.supply - entry.burned ); } } diff --git a/src/index/updater.rs b/src/index/updater.rs index 5e21331cc3..b5229d171b 100644 --- a/src/index/updater.rs +++ b/src/index/updater.rs @@ -591,8 +591,6 @@ impl<'index> Updater<'index> { .unwrap_or(0); let mut rune_updater = RuneUpdater { - block_time: block.header.time, - burned: HashMap::new(), client: &self.index.client, height: self.height, id_to_entry: &mut rune_id_to_rune_entry, @@ -603,14 +601,29 @@ impl<'index> Updater<'index> { runes, sequence_number_to_rune_id: &mut sequence_number_to_rune_id, statistic_to_count: &mut statistic_to_count, + block_time: block.header.time, transaction_id_to_rune: &mut transaction_id_to_rune, + updates: HashMap::new(), }; for (i, (tx, txid)) in block.txdata.iter().enumerate() { rune_updater.index_runes(u32::try_from(i).unwrap(), tx, *txid)?; } - rune_updater.update()?; + for (rune_id, update) in rune_updater.updates { + let mut entry = RuneEntry::load( + rune_id_to_rune_entry + .get(&rune_id.store())? + .unwrap() + .value(), + ); + + entry.burned += update.burned; + entry.mints += update.mints; + entry.supply += update.supply; + + rune_id_to_rune_entry.insert(&rune_id.store(), entry.store())?; + } } height_to_block_header.insert(&self.height, &block.header.store())?; diff --git a/src/index/updater/rune_updater.rs b/src/index/updater/rune_updater.rs index 5f2b6e8a57..210039a134 100644 --- a/src/index/updater/rune_updater.rs +++ b/src/index/updater/rune_updater.rs @@ -9,17 +9,22 @@ struct Claim { } struct Etched { + balance: u128, divisibility: u8, id: RuneId, mint: Option, - premine: u128, spaced_rune: SpacedRune, symbol: Option, } +#[derive(Default)] +pub(crate) struct RuneUpdate { + pub(crate) burned: u128, + pub(crate) mints: u64, + pub(crate) supply: u128, +} + pub(super) struct RuneUpdater<'a, 'tx, 'client> { - pub(super) block_time: u32, - pub(super) burned: HashMap, pub(super) client: &'client Client, pub(super) height: u32, pub(super) id_to_entry: &'a mut Table<'tx, RuneIdValue, RuneEntryValue>, @@ -30,7 +35,9 @@ pub(super) struct RuneUpdater<'a, 'tx, 'client> { pub(super) runes: u64, pub(super) sequence_number_to_rune_id: &'a mut Table<'tx, u32, RuneIdValue>, pub(super) statistic_to_count: &'a mut Table<'tx, u64, u64>, + pub(super) block_time: u32, pub(super) transaction_id_to_rune: &'a mut Table<'tx, &'static TxidValue, u128>, + pub(super) updates: HashMap, } impl<'a, 'tx, 'client> RuneUpdater<'a, 'tx, 'client> { @@ -57,14 +64,15 @@ impl<'a, 'tx, 'client> RuneUpdater<'a, 'tx, 'client> { .transpose()? { *unallocated.entry(claim.id).or_default() += claim.limit; - } - let etched = self.etched(tx_index, tx, &runestone)?; + let update = self.updates.entry(claim.id).or_default(); - if let Some(Etched { id, premine, .. }) = etched { - *unallocated.entry(id).or_default() += premine; + update.mints += 1; + update.supply += claim.limit; } + let mut etched = self.etched(tx_index, tx, &runestone)?; + if !cenotaph { for Edict { id, amount, output } in runestone.edicts { // edicts with output values greater than the number of outputs @@ -72,18 +80,21 @@ impl<'a, 'tx, 'client> RuneUpdater<'a, 'tx, 'client> { let output = usize::try_from(output).unwrap(); assert!(output <= tx.output.len()); - let id = if id == RuneId::default() { - let Some(Etched { id, .. }) = etched else { - continue; - }; - - id + let (balance, id) = if id == RuneId::default() { + // If this edict allocates new issuance runes, skip it + // if no issuance was present, or if the issuance was invalid. + // Additionally, replace ID 0 with the newly assigned ID, and + // get the unallocated balance of the issuance. + match etched.as_mut() { + Some(Etched { balance, id, .. }) => (balance, *id), + None => continue, + } } else { - id - }; - - let Some(balance) = unallocated.get_mut(&id) else { - continue; + // Get the unallocated balance of the given ID + match unallocated.get_mut(&id) { + Some(balance) => (balance, id), + None => continue, + } }; let mut allocate = |balance: &mut u128, amount: u128, output: usize| { @@ -213,17 +224,7 @@ impl<'a, 'tx, 'client> RuneUpdater<'a, 'tx, 'client> { // increment entries with burned runes for (id, amount) in burned { - *self.burned.entry(id).or_default() += amount; - } - - Ok(()) - } - - pub(super) fn update(self) -> Result { - for (rune_id, burned) in self.burned { - let mut entry = RuneEntry::load(self.id_to_entry.get(&rune_id.store())?.unwrap().value()); - entry.burned += burned; - self.id_to_entry.insert(&rune_id.store(), entry.store())?; + self.updates.entry(id).or_default().burned += amount; } Ok(()) @@ -231,10 +232,10 @@ impl<'a, 'tx, 'client> RuneUpdater<'a, 'tx, 'client> { fn create_rune_entry(&mut self, txid: Txid, burn: bool, etched: Etched) -> Result { let Etched { + balance, divisibility, id, mint, - premine, spaced_rune, symbol, } = etched; @@ -247,6 +248,8 @@ impl<'a, 'tx, 'client> RuneUpdater<'a, 'tx, 'client> { let number = self.runes; self.runes += 1; + let premine = u128::MAX - balance; + self .statistic_to_count .insert(&Statistic::Runes.into(), self.runes)?; @@ -262,6 +265,7 @@ impl<'a, 'tx, 'client> RuneUpdater<'a, 'tx, 'client> { number, premine, spaced_rune, + supply: premine, symbol, timestamp: self.block_time, } @@ -316,43 +320,36 @@ impl<'a, 'tx, 'client> RuneUpdater<'a, 'tx, 'client> { }; Ok(Some(Etched { - divisibility: etching.divisibility.unwrap_or_default(), + balance: u128::MAX, + divisibility: etching.divisibility, id: RuneId { block: self.height, tx: tx_index, }, - mint: etching.mint.map(|mint| MintEntry { - cap: mint.cap, - deadline: mint.deadline, - end: mint.term.map(|term| term + self.height), - limit: mint.limit, - }), - premine: etching.premine.unwrap_or_default(), spaced_rune: SpacedRune { rune, - spacers: etching.spacers.unwrap_or_default(), + spacers: etching.spacers, }, symbol: etching.symbol, + mint: etching.mint.map(|mint| MintEntry { + deadline: mint.deadline, + end: mint.term.map(|term| term + self.height), + limit: mint.limit.map(|limit| limit.min(runes::MAX_LIMIT)), + }), })) } - fn claim(&mut self, id: RuneId) -> Result> { + fn claim(&self, id: RuneId) -> Result> { let Some(entry) = self.id_to_entry.get(&id.store())? else { return Ok(None); }; - let mut rune_entry = RuneEntry::load(entry.value()); + let rune_entry = RuneEntry::load(entry.value()); let Ok(limit) = rune_entry.mintable(Height(self.height), self.block_time) else { return Ok(None); }; - drop(entry); - - rune_entry.mints += 1; - - self.id_to_entry.insert(&id.store(), rune_entry.store())?; - Ok(Some(Claim { id, limit })) } diff --git a/src/runes.rs b/src/runes.rs index 6d03e69b5a..1ed1d22886 100644 --- a/src/runes.rs +++ b/src/runes.rs @@ -9,6 +9,7 @@ pub use { }; pub const MAX_DIVISIBILITY: u8 = 38; +pub const MAX_LIMIT: u128 = u64::MAX as u128; const MAGIC_NUMBER: opcodes::All = opcodes::all::OP_PUSHNUM_13; const RESERVED: u128 = 6402364363415443603228541259936211926; @@ -27,21 +28,21 @@ pub mod varint; type Result = std::result::Result; -#[derive(Debug, PartialEq)] +#[derive(Debug)] pub enum MintError { - Cap(u128), - Deadline(u32), - End(u32), - Unmintable, + Deadline((Rune, u32)), + End((Rune, u32)), + Unmintable(Rune), } impl Display for MintError { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { - MintError::Cap(cap) => write!(f, "limited to {cap} mints"), - MintError::Deadline(deadline) => write!(f, "mint ended at {deadline}"), - MintError::End(end) => write!(f, "mint ended on block {end}"), - MintError::Unmintable => write!(f, "not mintable"), + MintError::Deadline((rune, deadline)) => { + write!(f, "rune {rune} mint ended at {deadline}") + } + MintError::End((rune, end)) => write!(f, "rune {rune} mint ended on block {end}"), + MintError::Unmintable(rune) => write!(f, "rune {rune} not mintable"), } } } @@ -142,7 +143,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -160,6 +160,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -187,7 +188,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(minimum - 1)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -213,7 +213,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(minimum)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -231,6 +230,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -276,7 +276,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RESERVED - 1)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -294,6 +293,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -321,7 +321,6 @@ mod tests { }], etching: Some(Etching { rune: None, - premine: Some(u128::MAX), ..default() }), ..default() @@ -345,6 +344,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: 2, ..default() }, @@ -370,7 +370,6 @@ mod tests { output: 0, }], etching: Some(Etching { - premine: Some(u128::MAX), rune: None, ..default() }), @@ -396,6 +395,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: 2, ..default() }, @@ -409,6 +409,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: 4, number: 1, ..default() @@ -446,9 +447,8 @@ mod tests { output: 0, }], etching: Some(Etching { - divisibility: Some(1), + divisibility: 1, rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -469,6 +469,7 @@ mod tests { etching: txid, divisibility: 1, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -497,7 +498,6 @@ mod tests { ], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -515,6 +515,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -543,7 +544,6 @@ mod tests { ], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -561,6 +561,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, symbol: None, timestamp: id.block, ..default() @@ -585,7 +586,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(100), ..default() }), ..default() @@ -603,6 +603,7 @@ mod tests { spacers: 0, }, premine: 100, + supply: 100, timestamp: id.block, ..default() }, @@ -631,7 +632,6 @@ mod tests { ], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(200), ..default() }), ..default() @@ -650,6 +650,7 @@ mod tests { spacers: 0, }, premine: 200, + supply: 200, timestamp: id.block, ..default() }, @@ -695,6 +696,7 @@ mod tests { spacers: 0, }, premine: 0, + supply: 0, timestamp: id.block, ..default() }, @@ -716,7 +718,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -734,6 +735,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -775,6 +777,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -829,7 +832,7 @@ mod tests { } #[test] - fn etched_rune_open_mint_parameters_are_unset_for_cenotaph() { + fn etched_rune_open_etching_parameters_are_unset_for_cenotaph() { let context = Context::builder().arg("--index-runes").build(); let (txid0, id) = context.etch( @@ -840,17 +843,15 @@ mod tests { output: 0, }], etching: Some(Etching { - premine: Some(u128::MAX), rune: Some(Rune(RUNE)), mint: Some(Mint { - cap: Some(1), deadline: Some(1), limit: Some(1), term: Some(1), }), - divisibility: Some(1), + divisibility: 1, symbol: Some('$'), - spacers: Some(1), + spacers: 1, }), cenotaph: true, ..default() @@ -862,17 +863,18 @@ mod tests { [( id, RuneEntry { - burned: u128::MAX, + burned: 0, divisibility: 1, etching: txid0, mint: None, mints: 0, number: 0, - premine: u128::MAX, + premine: 0, spaced_rune: SpacedRune { rune: Rune(RUNE), spacers: 1, }, + supply: 0, symbol: Some('$'), timestamp: id.block, }, @@ -939,7 +941,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -957,6 +958,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -995,6 +997,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -1016,7 +1019,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -1034,6 +1036,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -1065,6 +1068,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -1092,7 +1096,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -1110,6 +1113,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -1142,6 +1146,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, burned: u128::MAX, ..default() @@ -1164,7 +1169,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -1182,6 +1186,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -1220,6 +1225,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -1247,7 +1253,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -1265,6 +1270,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -1303,6 +1309,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, burned: u128::MAX, timestamp: id.block, ..default() @@ -1326,7 +1333,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -1344,6 +1350,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -1375,6 +1382,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -1402,7 +1410,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -1420,6 +1427,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -1455,6 +1463,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -1476,7 +1485,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -1494,6 +1502,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id0.block, ..default() }, @@ -1516,7 +1525,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE + 1)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -1535,6 +1543,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id0.block, ..default() }, @@ -1548,6 +1557,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id1.block, number: 1, ..default() @@ -1593,6 +1603,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id0.block, ..default() }, @@ -1606,6 +1617,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id1.block, number: 1, ..default() @@ -1635,7 +1647,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -1653,6 +1664,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id0.block, ..default() }, @@ -1675,7 +1687,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE + 1)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -1694,6 +1705,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id0.block, ..default() }, @@ -1707,6 +1719,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id1.block, number: 1, ..default() @@ -1752,6 +1765,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id0.block, ..default() }, @@ -1765,6 +1779,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id1.block, number: 1, ..default() @@ -1817,6 +1832,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id0.block, ..default() }, @@ -1830,6 +1846,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id1.block, number: 1, ..default() @@ -1868,7 +1885,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -1886,6 +1902,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id0.block, ..default() }, @@ -1908,7 +1925,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE + 1)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -1927,6 +1943,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id0.block, ..default() }, @@ -1940,6 +1957,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id1.block, number: 1, ..default() @@ -2003,6 +2021,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id0.block, ..default() }, @@ -2016,6 +2035,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id1.block, number: 1, ..default() @@ -2046,7 +2066,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -2064,6 +2083,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -2100,6 +2120,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -2109,7 +2130,7 @@ mod tests { } #[test] - fn multiple_runes_may_be_etched_in_one_block() { + fn rune_rarity_is_assigned_correctly() { let context = Context::builder().arg("--index-runes").build(); let (txid0, id0) = context.etch( @@ -2121,7 +2142,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -2138,7 +2158,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE + 1)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -2157,6 +2176,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id0.block, ..default() }, @@ -2170,6 +2190,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id1.block, number: 1, ..default() @@ -2210,7 +2231,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -2228,6 +2248,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -2276,6 +2297,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -2303,7 +2325,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -2321,6 +2342,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id0.block, ..default() }, @@ -2343,7 +2365,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE + 1)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -2362,6 +2383,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id0.block, ..default() }, @@ -2375,6 +2397,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id1.block, number: 1, ..default() @@ -2435,6 +2458,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id0.block, ..default() }, @@ -2448,6 +2472,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id1.block, number: 1, ..default() @@ -2486,7 +2511,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX / 2), ..default() }), ..default() @@ -2504,6 +2528,7 @@ mod tests { spacers: 0, }, premine: u128::MAX / 2, + supply: u128::MAX / 2, timestamp: id.block, ..default() }, @@ -2545,6 +2570,7 @@ mod tests { spacers: 0, }, premine: u128::MAX / 2, + supply: u128::MAX / 2, timestamp: id.block, ..default() }, @@ -2572,7 +2598,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -2591,6 +2616,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -2612,7 +2638,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -2630,6 +2655,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -2658,7 +2684,6 @@ mod tests { ], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -2676,6 +2701,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -2697,7 +2723,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -2715,6 +2740,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -2748,7 +2774,6 @@ mod tests { ], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -2766,6 +2791,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -2811,7 +2837,6 @@ mod tests { ], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -2829,6 +2854,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -2855,7 +2881,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(4000), ..default() }), ..default() @@ -2873,6 +2898,7 @@ mod tests { spacers: 0, }, premine: 4000, + supply: 4000, timestamp: id.block, ..default() }, @@ -2906,7 +2932,6 @@ mod tests { ], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -2924,6 +2949,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -2956,7 +2982,6 @@ mod tests { ], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -2974,6 +2999,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -3003,7 +3029,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -3021,6 +3046,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -3063,6 +3089,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -3099,7 +3126,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -3117,6 +3143,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -3166,6 +3193,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -3202,7 +3230,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -3220,6 +3247,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -3269,6 +3297,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -3305,7 +3334,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -3323,6 +3351,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -3365,6 +3394,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -3401,7 +3431,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -3419,6 +3448,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -3468,6 +3498,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -3504,7 +3535,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -3522,6 +3552,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -3571,6 +3602,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -3622,7 +3654,6 @@ mod tests { etching: Some(Etching { rune: Some(Rune(RUNE)), symbol: Some('$'), - premine: Some(u128::MAX), ..default() }), ..default() @@ -3640,6 +3671,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, symbol: Some('$'), timestamp: id.block, ..default() @@ -3662,7 +3694,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -3680,6 +3711,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -3701,7 +3733,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -3719,6 +3750,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -3761,6 +3793,7 @@ mod tests { spacers: 0, }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() }, @@ -3775,6 +3808,13 @@ mod tests { ); } + #[test] + fn max_limit() { + MAX_LIMIT + .checked_mul(u128::from(u16::MAX) * u128::from(RUNE_COMMIT_INTERVAL) * 365 * 1_000_000_000) + .unwrap(); + } + #[test] fn rune_can_be_minted_without_edict() { let context = Context::builder().arg("--index-runes").build(); @@ -3785,7 +3825,6 @@ mod tests { rune: Some(Rune(RUNE)), mint: Some(Mint { limit: Some(1000), - cap: Some(100), ..default() }), ..default() @@ -3808,7 +3847,6 @@ mod tests { mints: 0, mint: Some(MintEntry { limit: Some(1000), - cap: Some(100), ..default() }), ..default() @@ -3838,7 +3876,6 @@ mod tests { etching: txid0, mint: Some(MintEntry { limit: Some(1000), - cap: Some(100), ..default() }), mints: 1, @@ -3847,6 +3884,7 @@ mod tests { spacers: 0, }, premine: 0, + supply: 1000, timestamp: id.block, ..default() }, @@ -3870,7 +3908,6 @@ mod tests { etching: Some(Etching { rune: Some(Rune(RUNE)), mint: Some(Mint { - cap: Some(100), limit: Some(1000), ..default() }), @@ -3892,10 +3929,10 @@ mod tests { }, timestamp: id.block, premine: 0, + supply: 0, mints: 0, mint: Some(MintEntry { limit: Some(1000), - cap: Some(100), ..default() }), ..default() @@ -3930,7 +3967,6 @@ mod tests { etching: txid0, mint: Some(MintEntry { limit: Some(1000), - cap: Some(100), ..default() }), mints: 1, @@ -3939,6 +3975,7 @@ mod tests { spacers: 0, }, premine: 0, + supply: 1000, timestamp: id.block, ..default() }, @@ -3979,7 +4016,6 @@ mod tests { etching: txid0, mint: Some(MintEntry { limit: Some(1000), - cap: Some(100), ..default() }), mints: 2, @@ -3988,6 +4024,7 @@ mod tests { spacers: 0, }, premine: 0, + supply: 2000, timestamp: id.block, ..default() }, @@ -4039,7 +4076,6 @@ mod tests { etching: txid0, mint: Some(MintEntry { limit: Some(1000), - cap: Some(100), ..default() }), mints: 3, @@ -4048,6 +4084,7 @@ mod tests { spacers: 0, }, premine: 0, + supply: 3000, timestamp: id.block, ..default() }, @@ -4072,7 +4109,7 @@ mod tests { } #[test] - fn open_mints_can_be_limited_to_term() { + fn open_etchings_can_be_limited_to_term() { let context = Context::builder().arg("--index-runes").build(); let (txid0, id) = context.etch( @@ -4081,7 +4118,6 @@ mod tests { rune: Some(Rune(RUNE)), mint: Some(Mint { limit: Some(1000), - cap: Some(100), term: Some(2), ..default() }), @@ -4104,7 +4140,6 @@ mod tests { mint: Some(MintEntry { limit: Some(1000), end: Some(id.block + 2), - cap: Some(100), ..default() }), timestamp: id.block, @@ -4145,10 +4180,10 @@ mod tests { mint: Some(MintEntry { limit: Some(1000), end: Some(id.block + 2), - cap: Some(100), ..default() }), premine: 0, + supply: 1000, timestamp: id.block, mints: 1, ..default() @@ -4192,11 +4227,11 @@ mod tests { spacers: 0, }, premine: 0, + supply: 1000, timestamp: id.block, mint: Some(MintEntry { limit: Some(1000), end: Some(id.block + 2), - cap: Some(100), ..default() }), mints: 1, @@ -4214,7 +4249,7 @@ mod tests { } #[test] - fn open_mints_with_term_zero_can_be_premined() { + fn open_etchings_with_term_zero_can_be_premined() { let context = Context::builder().arg("--index-runes").build(); let (txid, id) = context.etch( @@ -4226,7 +4261,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(1111), mint: Some(Mint { limit: Some(1000), term: Some(0), @@ -4255,6 +4289,7 @@ mod tests { }), timestamp: id.block, premine: 1111, + supply: 1111, ..default() }, )], @@ -4292,6 +4327,7 @@ mod tests { ..default() }), premine: 1111, + supply: 1111, ..default() }, )], @@ -4300,7 +4336,7 @@ mod tests { } #[test] - fn open_mints_with_end_before_deadline() { + fn open_etchings_with_end_before_deadline() { let context = Context::builder().arg("--index-runes").build(); context.mine_blocks(1); @@ -4310,7 +4346,6 @@ mod tests { etching: Some(Etching { rune: Some(Rune(RUNE)), mint: Some(Mint { - cap: Some(2), limit: Some(1000), deadline: Some(12), term: Some(2), @@ -4333,7 +4368,6 @@ mod tests { }, timestamp: 9, mint: Some(MintEntry { - cap: Some(2), deadline: Some(12), end: Some(11), limit: Some(1000), @@ -4367,11 +4401,11 @@ mod tests { spacers: 0, }, premine: 0, + supply: 1000, timestamp: 9, mints: 1, etching: txid0, mint: Some(MintEntry { - cap: Some(2), deadline: Some(12), end: Some(11), limit: Some(1000), @@ -4412,9 +4446,9 @@ mod tests { spacers: 0, }, premine: 0, + supply: 1000, timestamp: 9, mint: Some(MintEntry { - cap: Some(2), limit: Some(1000), deadline: Some(12), end: Some(11), @@ -4434,7 +4468,7 @@ mod tests { } #[test] - fn open_mints_with_deadline_before_end() { + fn open_etchings_with_deadline_before_end() { let context = Context::builder().arg("--index-runes").build(); context.mine_blocks(1); @@ -4444,7 +4478,6 @@ mod tests { etching: Some(Etching { rune: Some(Rune(RUNE)), mint: Some(Mint { - cap: Some(2), limit: Some(1000), deadline: Some(11), term: Some(3), @@ -4467,7 +4500,6 @@ mod tests { }, timestamp: id.block, mint: Some(MintEntry { - cap: Some(2), deadline: Some(11), end: Some(12), limit: Some(1000), @@ -4501,11 +4533,11 @@ mod tests { spacers: 0, }, premine: 0, + supply: 1000, timestamp: id.block, mints: 1, etching: txid0, mint: Some(MintEntry { - cap: Some(2), deadline: Some(11), end: Some(12), limit: Some(1000), @@ -4546,9 +4578,9 @@ mod tests { spacers: 0, }, premine: 0, + supply: 1000, timestamp: id.block, mint: Some(MintEntry { - cap: Some(2), limit: Some(1000), deadline: Some(11), end: Some(12), @@ -4568,7 +4600,7 @@ mod tests { } #[test] - fn open_mints_can_be_limited_to_deadline() { + fn open_etchings_can_be_limited_to_deadline() { let context = Context::builder().arg("--index-runes").build(); let (txid0, id) = context.etch( @@ -4577,7 +4609,6 @@ mod tests { rune: Some(Rune(RUNE)), mint: Some(Mint { limit: Some(1000), - cap: Some(100), deadline: Some(RUNE_COMMIT_INTERVAL + 4), ..default() }), @@ -4601,7 +4632,6 @@ mod tests { mint: Some(MintEntry { deadline: Some(id.block + 2), limit: Some(1000), - cap: Some(100), ..default() }), ..default() @@ -4637,13 +4667,13 @@ mod tests { rune: Rune(RUNE), spacers: 0, }, + supply: 1000, timestamp: id.block, mints: 1, etching: txid0, mint: Some(MintEntry { deadline: Some(id.block + 2), limit: Some(1000), - cap: Some(100), ..default() }), ..default() @@ -4686,103 +4716,14 @@ mod tests { rune: Rune(RUNE), spacers: 0, }, + supply: 1000, timestamp: id.block, mint: Some(MintEntry { limit: Some(1000), deadline: Some(id.block + 2), - cap: Some(100), - ..default() - }), - mints: 1, - ..default() - }, - )], - [( - OutPoint { - txid: txid1, - vout: 0, - }, - vec![(id, 1000)], - )], - ); - } - - #[test] - fn open_mints_can_be_limited_to_cap() { - let context = Context::builder().arg("--index-runes").build(); - - let (txid0, id) = context.etch( - Runestone { - etching: Some(Etching { - rune: Some(Rune(RUNE)), - mint: Some(Mint { - limit: Some(1000), - cap: Some(2), - ..default() - }), - ..default() - }), - ..default() - }, - 1, - ); - - context.assert_runes( - [( - id, - RuneEntry { - etching: txid0, - spaced_rune: SpacedRune { - rune: Rune(RUNE), - spacers: 0, - }, - timestamp: id.block, - mint: Some(MintEntry { - limit: Some(1000), - cap: Some(2), ..default() }), - ..default() - }, - )], - [], - ); - - let txid1 = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(2, 0, 0, Witness::new())], - op_return: Some( - Runestone { - edicts: vec![Edict { - id, - amount: 1000, - output: 0, - }], - claim: Some(id), - ..default() - } - .encipher(), - ), - ..default() - }); - - context.mine_blocks(1); - - context.assert_runes( - [( - id, - RuneEntry { - spaced_rune: SpacedRune { - rune: Rune(RUNE), - spacers: 0, - }, - timestamp: id.block, mints: 1, - etching: txid0, - mint: Some(MintEntry { - cap: Some(2), - limit: Some(1000), - ..default() - }), ..default() }, )], @@ -4794,122 +4735,10 @@ mod tests { vec![(id, 1000)], )], ); - - let txid2 = context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(3, 0, 0, Witness::new())], - op_return: Some( - Runestone { - edicts: vec![Edict { - id, - amount: 1000, - output: 0, - }], - claim: Some(id), - ..default() - } - .encipher(), - ), - ..default() - }); - - context.mine_blocks(1); - - context.assert_runes( - [( - id, - RuneEntry { - etching: txid0, - spaced_rune: SpacedRune { - rune: Rune(RUNE), - spacers: 0, - }, - timestamp: id.block, - mint: Some(MintEntry { - limit: Some(1000), - cap: Some(2), - ..default() - }), - mints: 2, - ..default() - }, - )], - [ - ( - OutPoint { - txid: txid1, - vout: 0, - }, - vec![(id, 1000)], - ), - ( - OutPoint { - txid: txid2, - vout: 0, - }, - vec![(id, 1000)], - ), - ], - ); - - context.rpc_server.broadcast_tx(TransactionTemplate { - inputs: &[(4, 0, 0, Witness::new())], - op_return: Some( - Runestone { - edicts: vec![Edict { - id, - amount: 1000, - output: 0, - }], - claim: Some(id), - ..default() - } - .encipher(), - ), - ..default() - }); - - context.mine_blocks(1); - - context.assert_runes( - [( - id, - RuneEntry { - etching: txid0, - spaced_rune: SpacedRune { - rune: Rune(RUNE), - spacers: 0, - }, - timestamp: id.block, - mint: Some(MintEntry { - limit: Some(1000), - cap: Some(2), - ..default() - }), - mints: 2, - ..default() - }, - )], - [ - ( - OutPoint { - txid: txid1, - vout: 0, - }, - vec![(id, 1000)], - ), - ( - OutPoint { - txid: txid2, - vout: 0, - }, - vec![(id, 1000)], - ), - ], - ); } #[test] - fn open_mint_claims_can_use_split() { + fn open_etching_claims_can_use_split() { let context = Context::builder().arg("--index-runes").build(); let (txid0, id) = context.etch( @@ -4918,7 +4747,6 @@ mod tests { rune: Some(Rune(RUNE)), mint: Some(Mint { limit: Some(1000), - cap: Some(100), ..default() }), ..default() @@ -4939,7 +4767,6 @@ mod tests { }, mint: Some(MintEntry { limit: Some(1000), - cap: Some(100), ..default() }), timestamp: id.block, @@ -4978,10 +4805,10 @@ mod tests { rune: Rune(RUNE), spacers: 0, }, + supply: 1000, timestamp: id.block, mint: Some(MintEntry { limit: Some(1000), - cap: Some(100), ..default() }), mints: 1, @@ -5015,7 +4842,6 @@ mod tests { Runestone { etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(2000), mint: Some(Mint { limit: Some(1000), ..default() @@ -5047,6 +4873,7 @@ mod tests { }), timestamp: id.block, premine: 2000, + supply: 2000, ..default() }, )], @@ -5103,10 +4930,8 @@ mod tests { Runestone { etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(2000), mint: Some(Mint { limit: Some(1000), - cap: Some(1), ..default() }), ..default() @@ -5132,11 +4957,11 @@ mod tests { }, mint: Some(MintEntry { limit: Some(1000), - cap: Some(1), ..default() }), timestamp: rune_id.block, premine: 2000, + supply: 2000, mints: 0, ..default() }, @@ -5161,7 +4986,6 @@ mod tests { rune: Some(Rune(RUNE)), mint: Some(Mint { limit: Some(1000), - cap: Some(100), ..default() }), ..default() @@ -5201,10 +5025,10 @@ mod tests { }, mint: Some(MintEntry { limit: Some(1000), - cap: Some(100), ..default() }), timestamp: id.block, + supply: 1000, mints: 1, ..default() }, @@ -5220,7 +5044,7 @@ mod tests { } #[test] - fn multiple_edicts_in_one_transaction_may_claim_open_mint() { + fn multiple_edicts_in_one_transaction_may_claim_open_etching() { let context = Context::builder().arg("--index-runes").build(); let (txid0, id) = context.etch( @@ -5229,7 +5053,6 @@ mod tests { rune: Some(Rune(RUNE)), mint: Some(Mint { limit: Some(1000), - cap: Some(100), ..default() }), ..default() @@ -5250,7 +5073,6 @@ mod tests { }, mint: Some(MintEntry { limit: Some(1000), - cap: Some(100), ..default() }), timestamp: id.block, @@ -5302,10 +5124,10 @@ mod tests { }, mint: Some(MintEntry { limit: Some(1000), - cap: Some(100), ..default() }), timestamp: id.block, + supply: 1000, mints: 1, ..default() }, diff --git a/src/runes/etching.rs b/src/runes/etching.rs index 9329388b4e..0d5b9f49ec 100644 --- a/src/runes/etching.rs +++ b/src/runes/etching.rs @@ -2,10 +2,9 @@ use super::*; #[derive(Default, Serialize, Deserialize, Debug, PartialEq, Copy, Clone, Eq)] pub struct Etching { - pub divisibility: Option, + pub divisibility: u8, pub mint: Option, - pub premine: Option, pub rune: Option, - pub spacers: Option, + pub spacers: u32, pub symbol: Option, } diff --git a/src/runes/mint.rs b/src/runes/mint.rs index 122714e4db..aaacfce349 100644 --- a/src/runes/mint.rs +++ b/src/runes/mint.rs @@ -2,7 +2,6 @@ use super::*; #[derive(Default, Serialize, Deserialize, Debug, PartialEq, Copy, Clone, Eq)] pub struct Mint { - pub cap: Option, // mint cap pub deadline: Option, // unix timestamp pub limit: Option, // claim amount pub term: Option, // relative block height diff --git a/src/runes/runestone.rs b/src/runes/runestone.rs index 9741ff583e..896a87cc92 100644 --- a/src/runes/runestone.rs +++ b/src/runes/runestone.rs @@ -112,23 +112,23 @@ impl Runestone { (default_output.into_usize() < transaction.output.len()).then_some(default_output) }); - let divisibility = Tag::Divisibility.take(&mut fields, |[divisibility]| { - let divisibility = u8::try_from(divisibility).ok()?; - (divisibility <= MAX_DIVISIBILITY).then_some(divisibility) - }); + let divisibility = Tag::Divisibility + .take(&mut fields, |[divisibility]| { + let divisibility = u8::try_from(divisibility).ok()?; + (divisibility <= MAX_DIVISIBILITY).then_some(divisibility) + }) + .unwrap_or_default(); - let limit = Tag::Limit.take(&mut fields, |[limit]| Some(limit)); + let limit = Tag::Limit.take(&mut fields, |[limit]| (limit <= MAX_LIMIT).then_some(limit)); let rune = Tag::Rune.take(&mut fields, |[rune]| Some(Rune(rune))); - let cap = Tag::Cap.take(&mut fields, |[cap]| Some(cap)); - - let premine = Tag::Premine.take(&mut fields, |[premine]| Some(premine)); - - let spacers = Tag::Spacers.take(&mut fields, |[spacers]| { - let spacers = u32::try_from(spacers).ok()?; - (spacers <= MAX_SPACERS).then_some(spacers) - }); + let spacers = Tag::Spacers + .take(&mut fields, |[spacers]| { + let spacers = u32::try_from(spacers).ok()?; + (spacers <= MAX_SPACERS).then_some(spacers) + }) + .unwrap_or_default(); let symbol = Tag::Symbol.take(&mut fields, |[symbol]| { char::from_u32(u32::try_from(symbol).ok()?) @@ -144,34 +144,24 @@ impl Runestone { let mint = Flag::Mint.take(&mut flags); - let overflow = (|| { - let premine = premine.unwrap_or_default(); - let cap = cap.unwrap_or_default(); - let limit = limit.unwrap_or_default(); - premine.checked_add(cap.checked_mul(limit)?) - })() - .is_none(); - let etching = if etch { Some(Etching { divisibility, + rune, + spacers, + symbol, mint: mint.then_some(Mint { - cap, deadline, limit, term, }), - premine, - rune, - spacers, - symbol, }) } else { None }; Ok(Some(Self { - cenotaph: cenotaph || overflow || flags != 0 || fields.keys().any(|tag| tag % 2 == 0), + cenotaph: cenotaph || flags != 0 || fields.keys().any(|tag| tag % 2 == 0), claim, default_output, edicts, @@ -196,22 +186,18 @@ impl Runestone { Tag::Rune.encode([rune.0], &mut payload); } - if let Some(divisibility) = etching.divisibility { - Tag::Divisibility.encode([divisibility.into()], &mut payload); + if etching.divisibility != 0 { + Tag::Divisibility.encode([etching.divisibility.into()], &mut payload); } - if let Some(spacers) = etching.spacers { - Tag::Spacers.encode([spacers.into()], &mut payload); + if etching.spacers != 0 { + Tag::Spacers.encode([etching.spacers.into()], &mut payload); } if let Some(symbol) = etching.symbol { Tag::Symbol.encode([symbol.into()], &mut payload); } - if let Some(premine) = etching.premine { - Tag::Premine.encode([premine], &mut payload); - } - if let Some(mint) = etching.mint { if let Some(deadline) = mint.deadline { Tag::Deadline.encode([deadline.into()], &mut payload); @@ -224,10 +210,6 @@ impl Runestone { if let Some(term) = mint.term { Tag::Term.encode([term.into()], &mut payload); } - - if let Some(cap) = mint.cap { - Tag::Cap.encode([cap], &mut payload); - } } } @@ -824,7 +806,7 @@ mod tests { }], etching: Some(Etching { rune: None, - divisibility: Some(4), + divisibility: 4, ..default() }), ..default() @@ -969,7 +951,7 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(4)), - divisibility: Some(5), + divisibility: 5, ..default() }), ..default() @@ -1068,7 +1050,7 @@ mod tests { #[test] fn decipher_etching_with_all_etching_tags() { - pretty_assert_eq!( + assert_eq!( decipher(&[ Tag::Flags.into(), Flag::Etch.mask() | Flag::Mint.mask(), @@ -1086,16 +1068,6 @@ mod tests { 2, Tag::Limit.into(), 3, - Tag::Premine.into(), - 8, - Tag::Cap.into(), - 9, - Tag::DefaultOutput.into(), - 0, - Tag::Claim.into(), - 1, - Tag::Claim.into(), - 1, Tag::Body.into(), 1, 1, @@ -1111,19 +1083,15 @@ mod tests { etching: Some(Etching { rune: Some(Rune(4)), mint: Some(Mint { - cap: Some(9), deadline: Some(7), term: Some(2), limit: Some(3), }), - premine: Some(8), - divisibility: Some(1), + divisibility: 1, symbol: Some('a'), - spacers: Some(5), + spacers: 5, }), - cenotaph: false, - default_output: Some(0), - claim: Some(RuneId::new(1, 1).unwrap()), + ..default() }, ); } @@ -1185,7 +1153,7 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(4)), - divisibility: Some(1), + divisibility: 1, symbol: Some('a'), ..default() }), @@ -1214,10 +1182,7 @@ mod tests { amount: 2, output: 0, }], - etching: Some(Etching { - divisibility: Some(0), - ..default() - }), + etching: Some(Etching::default()), ..default() }, ); @@ -1328,7 +1293,7 @@ mod tests { output: 0, }], etching: Some(Etching { - divisibility: Some(5), + divisibility: 5, ..default() }), ..default() @@ -1443,7 +1408,7 @@ mod tests { case( Vec::new(), Some(Etching { - divisibility: Some(MAX_DIVISIBILITY), + divisibility: MAX_DIVISIBILITY, rune: Some(Rune(0)), ..default() }), @@ -1453,17 +1418,15 @@ mod tests { case( Vec::new(), Some(Etching { - divisibility: Some(MAX_DIVISIBILITY), + divisibility: MAX_DIVISIBILITY, mint: Some(Mint { - cap: None, deadline: Some(10000), limit: Some(1), term: Some(1), }), - premine: None, rune: Some(Rune(0)), symbol: Some('$'), - spacers: Some(1), + spacers: 1, }), 20, ); @@ -1484,7 +1447,7 @@ mod tests { output: 0, }], Some(Etching { - divisibility: Some(MAX_DIVISIBILITY), + divisibility: MAX_DIVISIBILITY, rune: Some(Rune(u128::MAX)), ..default() }), @@ -1498,7 +1461,7 @@ mod tests { output: 0, }], Some(Etching { - divisibility: Some(MAX_DIVISIBILITY), + divisibility: MAX_DIVISIBILITY, rune: Some(Rune(u128::MAX)), ..default() }), @@ -1709,17 +1672,15 @@ mod tests { case( Runestone { etching: Some(Etching { - premine: Some(1), - divisibility: Some(1), + divisibility: 1, mint: Some(Mint { - cap: Some(1), deadline: Some(2), limit: Some(3), term: Some(5), }), symbol: Some('@'), rune: Some(Rune(4)), - spacers: Some(6), + spacers: 6, }), edicts: vec![ Edict { @@ -1748,16 +1709,12 @@ mod tests { 6, Tag::Symbol.into(), '@'.into(), - Tag::Premine.into(), - 1, Tag::Deadline.into(), 2, Tag::Limit.into(), 3, Tag::Term.into(), 5, - Tag::Cap.into(), - 1, Tag::Claim.into(), 1, Tag::Claim.into(), @@ -1781,12 +1738,11 @@ mod tests { case( Runestone { etching: Some(Etching { - premine: None, - divisibility: None, + divisibility: 0, mint: None, symbol: None, rune: Some(Rune(3)), - spacers: None, + spacers: 0, }), cenotaph: false, ..default() @@ -1797,12 +1753,11 @@ mod tests { case( Runestone { etching: Some(Etching { - premine: None, - divisibility: None, + divisibility: 0, mint: None, symbol: None, rune: None, - spacers: None, + spacers: 0, }), cenotaph: false, ..default() @@ -1898,6 +1853,12 @@ mod tests { assert!(!decipher(&[Tag::Divisibility.into(), u128::MAX]).cenotaph); } + #[test] + fn invalid_limit_produces_cenotaph() { + assert!(decipher(&[Tag::Limit.into(), u128::MAX]).cenotaph); + assert!(decipher(&[Tag::Limit.into(), u128::from(u64::MAX) + 1]).cenotaph); + } + #[test] fn min_and_max_runes_are_not_cenotaphs() { assert!(!decipher(&[Tag::Rune.into(), 0]).cenotaph); @@ -1918,57 +1879,4 @@ mod tests { fn invalid_term_produces_cenotaph() { assert!(decipher(&[Tag::Term.into(), u128::MAX]).cenotaph); } - - #[test] - fn invalid_supply_produces_cenotaph() { - assert!( - !decipher(&[ - Tag::Flags.into(), - Flag::Etch.mask() | Flag::Mint.mask(), - Tag::Cap.into(), - 1, - Tag::Limit.into(), - u128::MAX - ]) - .cenotaph - ); - - assert!( - decipher(&[ - Tag::Flags.into(), - Flag::Etch.mask() | Flag::Mint.mask(), - Tag::Cap.into(), - 2, - Tag::Limit.into(), - u128::MAX - ]) - .cenotaph - ); - - assert!( - decipher(&[ - Tag::Flags.into(), - Flag::Etch.mask() | Flag::Mint.mask(), - Tag::Cap.into(), - 2, - Tag::Limit.into(), - u128::MAX / 2 + 1 - ]) - .cenotaph - ); - - assert!( - decipher(&[ - Tag::Flags.into(), - Flag::Etch.mask() | Flag::Mint.mask(), - Tag::Premine.into(), - 1, - Tag::Cap.into(), - 1, - Tag::Limit.into(), - u128::MAX - ]) - .cenotaph - ); - } } diff --git a/src/runes/tag.rs b/src/runes/tag.rs index 7dbfcca8f6..cd22fea51e 100644 --- a/src/runes/tag.rs +++ b/src/runes/tag.rs @@ -10,8 +10,6 @@ pub(super) enum Tag { Deadline = 10, DefaultOutput = 12, Claim = 14, - Cap = 16, - Premine = 18, #[allow(unused)] Cenotaph = 126, diff --git a/src/subcommand/runes.rs b/src/subcommand/runes.rs index 2617755015..a162f471d7 100644 --- a/src/subcommand/runes.rs +++ b/src/subcommand/runes.rs @@ -13,7 +13,7 @@ pub struct RuneInfo { pub etching: Txid, pub id: RuneId, pub mint: Option, - pub mints: u128, + pub mints: u64, pub number: u64, pub premine: u128, pub rune: SpacedRune, @@ -40,7 +40,7 @@ pub(crate) fn run(settings: Settings) -> SubcommandResult { .map( |( id, - entry @ RuneEntry { + RuneEntry { burned, divisibility, etching, @@ -49,6 +49,7 @@ pub(crate) fn run(settings: Settings) -> SubcommandResult { number, premine, spaced_rune, + supply, symbol, timestamp, }, @@ -66,7 +67,7 @@ pub(crate) fn run(settings: Settings) -> SubcommandResult { number, premine, rune: spaced_rune, - supply: entry.supply(), + supply, symbol, timestamp: crate::timestamp(timestamp), tx: id.tx, diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index 27fb5e0b99..071654151c 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -2687,7 +2687,6 @@ mod tests { etching: Some(Etching { rune: Some(Rune(RUNE)), symbol: Some('%'), - premine: Some(u128::MAX), ..default() }), ..default() @@ -2707,6 +2706,7 @@ mod tests { spacers: 0 }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, symbol: Some('%'), ..default() @@ -2753,7 +2753,6 @@ mod tests { etching: Some(Etching { rune: Some(rune), symbol: Some('%'), - premine: Some(u128::MAX), ..default() }), ..default() @@ -2778,6 +2777,7 @@ mod tests { etching: txid, spaced_rune: SpacedRune { rune, spacers: 0 }, premine: u128::MAX, + supply: u128::MAX, symbol: Some('%'), timestamp: id.block, ..default() @@ -2865,8 +2865,7 @@ mod tests { etching: Some(Etching { rune: Some(rune), symbol: Some('%'), - spacers: Some(1), - premine: Some(u128::MAX), + spacers: 1, ..default() }), ..default() @@ -2891,6 +2890,7 @@ mod tests { etching: txid, spaced_rune: SpacedRune { rune, spacers: 1 }, premine: u128::MAX, + supply: u128::MAX, symbol: Some('%'), timestamp: id.block, ..default() @@ -2964,7 +2964,6 @@ mod tests { }], etching: Some(Etching { rune: Some(Rune(RUNE)), - premine: Some(u128::MAX), ..default() }), ..default() @@ -2984,6 +2983,7 @@ mod tests { spacers: 0 }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() } @@ -3026,9 +3026,8 @@ mod tests { output: 0, }], etching: Some(Etching { - divisibility: Some(1), + divisibility: 1, rune: Some(rune), - premine: Some(u128::MAX), ..default() }), ..default() @@ -3046,6 +3045,7 @@ mod tests { etching: txid, spaced_rune: SpacedRune { rune, spacers: 0 }, premine: u128::MAX, + supply: u128::MAX, timestamp: id.block, ..default() } diff --git a/src/subcommand/wallet/inscribe.rs b/src/subcommand/wallet/inscribe.rs index 91e2b3063f..a7d69053fc 100644 --- a/src/subcommand/wallet/inscribe.rs +++ b/src/subcommand/wallet/inscribe.rs @@ -188,29 +188,6 @@ impl Inscribe { "rune `{rune}` has already been etched", ); - let premine = etching.premine.to_amount(etching.divisibility)?; - - let supply = etching.supply.to_amount(etching.divisibility)?; - - let mintable = etching - .mint - .map(|mint| -> Result { - mint - .cap - .checked_mul(mint.limit.to_amount(etching.divisibility)?) - .ok_or_else(|| anyhow!("`mint.count` * `mint.limit` over maximum")) - }) - .transpose()? - .unwrap_or_default(); - - ensure!( - supply - == premine - .checked_add(mintable) - .ok_or_else(|| anyhow!("`premine` + `mint.count` * `mint.limit` over maximum"))?, - "`supply` not equal to `premine` + `mint.count` * `mint.limit`" - ); - let bitcoin_client = wallet.bitcoin_client(); let count = bitcoin_client.get_block_count()?; diff --git a/src/subcommand/wallet/mint.rs b/src/subcommand/wallet/mint.rs index 7982457bf4..efefb0f2ad 100644 --- a/src/subcommand/wallet/mint.rs +++ b/src/subcommand/wallet/mint.rs @@ -39,7 +39,7 @@ impl Mint { let limit = rune_entry .mintable(Height(block_height), block_time) - .map_err(|err| anyhow!("rune {rune} {err}"))?; + .map_err(|e| anyhow!(e))?; let destination = wallet.get_change_address()?; diff --git a/src/templates/rune.rs b/src/templates/rune.rs index e43c5c2b8b..08b0fd05b7 100644 --- a/src/templates/rune.rs +++ b/src/templates/rune.rs @@ -28,7 +28,6 @@ mod tests { etching: Txid::all_zeros(), mints: 100, mint: Some(MintEntry { - cap: Some(101), end: Some(11), limit: Some(1000000001), deadline: Some(7), @@ -39,6 +38,7 @@ mod tests { rune: Rune(u128::MAX), spacers: 1 }, + supply: 123456789123456789, symbol: Some('%'), timestamp: 0, }, @@ -73,16 +73,12 @@ mod tests {
1.000000001 %
mints
100
-
cap
-
101
-
remaining
-
1
mintable
true
supply
-
100.123456889\u{A0}%
+
123456789.123456789\u{A0}%
premine
0.123456789\u{A0}%
burned
@@ -116,6 +112,7 @@ mod tests { rune: Rune(u128::MAX), spacers: 1 }, + supply: 123456789123456789, symbol: Some('%'), timestamp: 0, }, @@ -124,10 +121,32 @@ mod tests { parent: None, }, "

B•CGDENLQRQWDSLRUGSNLBTMFIJAV

-
.* +
+
number
+
25
+
timestamp
+
+
id
+
10:9
+
etching block
+
10
+
etching transaction
+
9
mint
no
-.*
+
supply
+
123456789.123456789\u{A0}%
+
premine
+
0\u{A0}%
+
burned
+
123456789.123456789\u{A0}%
+
divisibility
+
9
+
symbol
+
%
+
etching
+
0{64}
+
" ); } @@ -139,7 +158,6 @@ mod tests { entry: RuneEntry { burned: 123456789123456789, mint: Some(MintEntry { - cap: None, deadline: None, end: None, limit: None, @@ -153,6 +171,7 @@ mod tests { rune: Rune(u128::MAX), spacers: 1 }, + supply: 123456789123456789, symbol: Some('%'), timestamp: 0, }, @@ -161,7 +180,17 @@ mod tests { parent: None, }, "

B•CGDENLQRQWDSLRUGSNLBTMFIJAV

-
.* +
+
number
+
25
+
timestamp
+
+
id
+
10:9
+
etching block
+
10
+
etching transaction
+
9
mint
@@ -173,15 +202,23 @@ mod tests {
none
mints
0
-
cap
-
0
-
remaining
-
0
mintable
false
-.*
+
supply
+
123456789.123456789\u{A0}%
+
premine
+
0\u{A0}%
+
burned
+
123456789.123456789\u{A0}%
+
divisibility
+
9
+
symbol
+
%
+
etching
+
0{64}
+
" ); } diff --git a/src/wallet/batch/etching.rs b/src/wallet/batch/etching.rs index 9af5f4bcc2..f7d2683a9d 100644 --- a/src/wallet/batch/etching.rs +++ b/src/wallet/batch/etching.rs @@ -7,6 +7,5 @@ pub struct Etching { pub mint: Option, pub premine: Decimal, pub rune: SpacedRune, - pub supply: Decimal, pub symbol: char, } diff --git a/src/wallet/batch/mint.rs b/src/wallet/batch/mint.rs index cced5469b7..a55c95ad9c 100644 --- a/src/wallet/batch/mint.rs +++ b/src/wallet/batch/mint.rs @@ -5,6 +5,5 @@ use super::*; pub struct Mint { pub deadline: Option, pub limit: Decimal, - pub cap: u128, pub term: Option, } diff --git a/src/wallet/batch/plan.rs b/src/wallet/batch/plan.rs index e3b6937ca1..88bf8f57fc 100644 --- a/src/wallet/batch/plan.rs +++ b/src/wallet/batch/plan.rs @@ -462,21 +462,19 @@ impl Plan { default_output: None, edicts, etching: Some(runes::Etching { - divisibility: (etching.divisibility > 0).then_some(etching.divisibility), + divisibility: etching.divisibility, mint: etching .mint .map(|mint| -> Result { Ok(runes::Mint { - cap: (mint.cap > 0).then_some(mint.cap), deadline: mint.deadline, - limit: Some(mint.limit.to_amount(etching.divisibility)?), term: mint.term, + limit: Some(mint.limit.to_amount(etching.divisibility)?), }) }) .transpose()?, - premine: (premine > 0).then_some(premine), rune: Some(etching.rune.rune), - spacers: (etching.rune.spacers > 0).then_some(etching.rune.spacers), + spacers: etching.rune.spacers, symbol: Some(etching.symbol), }), }; diff --git a/templates/rune.html b/templates/rune.html index c83430e8bd..5d61bc221a 100644 --- a/templates/rune.html +++ b/templates/rune.html @@ -33,16 +33,12 @@

{{ self.entry.spaced_rune }}

%% }
limit
%% if let Some(limit) = mint.limit { -
{{ self.entry.pile(limit) }}
+
{{ Pile{ amount: limit, divisibility: self.entry.divisibility, symbol: self.entry.symbol } }}
%% } else {
none
%% }
mints
{{ self.entry.mints }}
-
cap
-
{{ mint.cap.unwrap_or_default() }}
-
remaining
-
{{ mint.cap.unwrap_or_default() - self.entry.mints }}
mintable
{{ self.mintable }}
@@ -51,11 +47,11 @@

{{ self.entry.spaced_rune }}

no
%% }
supply
-
{{ self.entry.pile(self.entry.supply()) }}
+
{{ Pile{ amount: self.entry.supply, divisibility: self.entry.divisibility, symbol: self.entry.symbol } }}
premine
-
{{ self.entry.pile(self.entry.premine) }}
+
{{ Pile{ amount: self.entry.premine, divisibility: self.entry.divisibility, symbol: self.entry.symbol } }}
burned
-
{{ self.entry.pile(self.entry.burned) }}
+
{{ Pile{ amount: self.entry.burned, divisibility: self.entry.divisibility, symbol: self.entry.symbol } }}
divisibility
{{ self.entry.divisibility }}
%% if let Some(symbol) = self.entry.symbol { diff --git a/tests/json_api.rs b/tests/json_api.rs index 3e5cd292be..67719f45e7 100644 --- a/tests/json_api.rs +++ b/tests/json_api.rs @@ -557,6 +557,7 @@ fn get_runes() { rune: Rune(RUNE), spacers: 0 }, + supply: 1000, symbol: Some('¢'), timestamp: 11, }, @@ -593,6 +594,7 @@ fn get_runes() { rune: Rune(RUNE), spacers: 0 }, + supply: 1000, symbol: Some('¢'), timestamp: 11, } @@ -611,6 +613,7 @@ fn get_runes() { rune: Rune(RUNE + 1), spacers: 0 }, + supply: 1000, symbol: Some('¢'), timestamp: 19, } @@ -629,6 +632,7 @@ fn get_runes() { rune: Rune(RUNE + 2), spacers: 0 }, + supply: 1000, symbol: Some('¢'), timestamp: 27, } diff --git a/tests/lib.rs b/tests/lib.rs index ab5c6d4903..67b040260e 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -188,7 +188,6 @@ fn etch( ord_rpc_server, batch::File { etching: Some(batch::Etching { - supply: "1000".parse().unwrap(), divisibility: 0, mint: None, premine: "1000".parse().unwrap(), @@ -251,24 +250,12 @@ fn batch( let batch::Etching { divisibility, - mint, premine, rune, - supply, symbol, + mint, } = batchfile.etching.unwrap(); - { - let supply = supply.to_amount(divisibility).unwrap(); - let premine = premine.to_amount(divisibility).unwrap(); - - let mintable = mint - .map(|mint| mint.cap * mint.limit.to_amount(divisibility).unwrap()) - .unwrap_or_default(); - - assert_eq!(supply, premine + mintable); - } - let mut mint_definition = Vec::::new(); if let Some(mint) = mint { @@ -311,10 +298,6 @@ fn batch( mint_definition.push("
mints
".into()); mint_definition.push("
0
".into()); - mint_definition.push("
cap
".into()); - mint_definition.push(format!("
{}
", mint.cap)); - mint_definition.push("
remaining
".into()); - mint_definition.push(format!("
{}
", mint.cap)); mint_definition.push("
mintable
".into()); mint_definition.push(format!("
{mintable}
")); diff --git a/tests/wallet/balance.rs b/tests/wallet/balance.rs index d47f6f178e..f3073c785e 100644 --- a/tests/wallet/balance.rs +++ b/tests/wallet/balance.rs @@ -108,7 +108,6 @@ fn runic_utxos_are_deducted_from_cardinal() { divisibility: 0, mint: None, premine: "1000".parse().unwrap(), - supply: "1000".parse().unwrap(), rune: SpacedRune { rune, spacers: 1 }, symbol: '¢', }), diff --git a/tests/wallet/inscribe.rs b/tests/wallet/inscribe.rs index 4bee89b88c..9c1549f353 100644 --- a/tests/wallet/inscribe.rs +++ b/tests/wallet/inscribe.rs @@ -2640,7 +2640,6 @@ fn batch_inscribe_can_etch_rune() { rune: Rune(RUNE), spacers: 0, }, - supply: "1000".parse().unwrap(), premine: "1000".parse().unwrap(), symbol: '¢', mint: None, @@ -2709,7 +2708,6 @@ fn etch_existing_rune_error() { rune: Rune(RUNE), spacers: 1, }, - supply: "1000".parse().unwrap(), premine: "1000".parse().unwrap(), symbol: '¢', mint: None, @@ -2754,7 +2752,6 @@ fn etch_reserved_rune_error() { spacers: 0, }, premine: "1000".parse().unwrap(), - supply: "1000".parse().unwrap(), symbol: '¢', mint: None, }), @@ -2797,7 +2794,6 @@ fn etch_sub_minimum_rune_error() { rune: Rune(0), spacers: 0, }, - supply: "1000".parse().unwrap(), premine: "1000".parse().unwrap(), symbol: '¢', mint: None, @@ -2840,7 +2836,6 @@ fn etch_requires_rune_index() { rune: Rune(RUNE), spacers: 0, }, - supply: "1000".parse().unwrap(), premine: "1000".parse().unwrap(), symbol: '¢', mint: None, @@ -2884,7 +2879,6 @@ fn etch_divisibility_over_maximum_error() { rune: Rune(RUNE), spacers: 0, }, - supply: "1000".parse().unwrap(), premine: "1000".parse().unwrap(), symbol: '¢', mint: None, @@ -2903,150 +2897,3 @@ fn etch_divisibility_over_maximum_error() { .expected_exit_code(1) .run_and_extract_stdout(); } - -#[test] -fn etch_mintable_overflow_error() { - let bitcoin_rpc_server = test_bitcoincore_rpc::builder() - .network(Network::Regtest) - .build(); - - let ord_rpc_server = - TestServer::spawn_with_server_args(&bitcoin_rpc_server, &["--regtest", "--index-runes"], &[]); - - create_wallet(&bitcoin_rpc_server, &ord_rpc_server); - - bitcoin_rpc_server.mine_blocks(1); - - CommandBuilder::new("--regtest --index-runes wallet inscribe --fee-rate 0 --batch batch.yaml") - .write("inscription.txt", "foo") - .write( - "batch.yaml", - serde_yaml::to_string(&batch::File { - etching: Some(batch::Etching { - divisibility: 0, - rune: SpacedRune { - rune: Rune(RUNE), - spacers: 0, - }, - supply: default(), - premine: default(), - symbol: '¢', - mint: Some(batch::Mint { - cap: 2, - term: Some(2), - limit: "340282366920938463463374607431768211455".parse().unwrap(), - deadline: None, - }), - }), - inscriptions: vec![batch::Entry { - file: "inscription.txt".into(), - ..default() - }], - ..default() - }) - .unwrap(), - ) - .bitcoin_rpc_server(&bitcoin_rpc_server) - .ord_rpc_server(&ord_rpc_server) - .expected_stderr("error: `mint.count` * `mint.limit` over maximum\n") - .expected_exit_code(1) - .run_and_extract_stdout(); -} - -#[test] -fn etch_mintable_plus_premine_overflow_error() { - let bitcoin_rpc_server = test_bitcoincore_rpc::builder() - .network(Network::Regtest) - .build(); - - let ord_rpc_server = - TestServer::spawn_with_server_args(&bitcoin_rpc_server, &["--regtest", "--index-runes"], &[]); - - create_wallet(&bitcoin_rpc_server, &ord_rpc_server); - - bitcoin_rpc_server.mine_blocks(1); - - CommandBuilder::new("--regtest --index-runes wallet inscribe --fee-rate 0 --batch batch.yaml") - .write("inscription.txt", "foo") - .write( - "batch.yaml", - serde_yaml::to_string(&batch::File { - etching: Some(batch::Etching { - divisibility: 0, - rune: SpacedRune { - rune: Rune(RUNE), - spacers: 0, - }, - supply: default(), - premine: "1".parse().unwrap(), - symbol: '¢', - mint: Some(batch::Mint { - cap: 1, - term: Some(2), - limit: "340282366920938463463374607431768211455".parse().unwrap(), - deadline: None, - }), - }), - inscriptions: vec![batch::Entry { - file: "inscription.txt".into(), - ..default() - }], - ..default() - }) - .unwrap(), - ) - .bitcoin_rpc_server(&bitcoin_rpc_server) - .ord_rpc_server(&ord_rpc_server) - .expected_stderr("error: `premine` + `mint.count` * `mint.limit` over maximum\n") - .expected_exit_code(1) - .run_and_extract_stdout(); -} - -#[test] -fn incorrect_supply_error() { - let bitcoin_rpc_server = test_bitcoincore_rpc::builder() - .network(Network::Regtest) - .build(); - - let ord_rpc_server = - TestServer::spawn_with_server_args(&bitcoin_rpc_server, &["--regtest", "--index-runes"], &[]); - - create_wallet(&bitcoin_rpc_server, &ord_rpc_server); - - bitcoin_rpc_server.mine_blocks(1); - - CommandBuilder::new("--regtest --index-runes wallet inscribe --fee-rate 0 --batch batch.yaml") - .write("inscription.txt", "foo") - .write( - "batch.yaml", - serde_yaml::to_string(&batch::File { - etching: Some(batch::Etching { - divisibility: 0, - rune: SpacedRune { - rune: Rune(RUNE), - spacers: 0, - }, - supply: "1".parse().unwrap(), - premine: "1".parse().unwrap(), - symbol: '¢', - mint: Some(batch::Mint { - cap: 1, - term: Some(2), - limit: "1".parse().unwrap(), - deadline: None, - }), - }), - inscriptions: vec![batch::Entry { - file: "inscription.txt".into(), - ..default() - }], - ..default() - }) - .unwrap(), - ) - .bitcoin_rpc_server(&bitcoin_rpc_server) - .ord_rpc_server(&ord_rpc_server) - .expected_stderr("error: `supply` not equal to `premine` + `mint.count` * `mint.limit`\n") - .expected_exit_code(1) - .run_and_extract_stdout(); -} diff --git a/tests/wallet/mint.rs b/tests/wallet/mint.rs index 7160950ec9..b6024638ef 100644 --- a/tests/wallet/mint.rs +++ b/tests/wallet/mint.rs @@ -28,9 +28,7 @@ fn minting_rune_and_fails_if_after_end() { }, premine: "0".parse().unwrap(), symbol: '¢', - supply: "111.1".parse().unwrap(), mint: Some(batch::Mint { - cap: 1, term: Some(2), limit: "111.1".parse().unwrap(), deadline: None, @@ -122,7 +120,6 @@ fn minting_rune_fails_if_not_mintable() { rune: Rune(RUNE), spacers: 0, }, - supply: "1000".parse().unwrap(), premine: "1000".parse().unwrap(), symbol: '¢', mint: None, @@ -168,10 +165,8 @@ fn minting_rune_fails_if_after_deadline() { divisibility: 1, rune: SpacedRune { rune, spacers: 0 }, premine: "0".parse().unwrap(), - supply: "222.2".parse().unwrap(), symbol: '¢', mint: Some(batch::Mint { - cap: 2, term: Some(2), limit: "111.1".parse().unwrap(), deadline: Some(deadline), @@ -251,10 +246,8 @@ fn minting_rune_and_then_sending_works() { spacers: 0, }, premine: "111".parse().unwrap(), - supply: "132".parse().unwrap(), symbol: '¢', mint: Some(batch::Mint { - cap: 1, term: Some(10), limit: "21".parse().unwrap(), deadline: None, diff --git a/tests/wallet/selection.rs b/tests/wallet/selection.rs index 26800030e9..25a4bf17d0 100644 --- a/tests/wallet/selection.rs +++ b/tests/wallet/selection.rs @@ -128,11 +128,9 @@ fn mint_does_not_select_inscription() { spacers: 0, }, premine: "1000".parse().unwrap(), - supply: "2000".parse().unwrap(), symbol: '¢', mint: Some(batch::Mint { deadline: None, - cap: 1, limit: "1000".parse().unwrap(), term: None, }), diff --git a/tests/wallet/send.rs b/tests/wallet/send.rs index c02dfa4263..e67e835059 100644 --- a/tests/wallet/send.rs +++ b/tests/wallet/send.rs @@ -886,7 +886,6 @@ fn sending_rune_with_divisibility_works() { divisibility: 1, rune: SpacedRune { rune, spacers: 0 }, premine: "1000".parse().unwrap(), - supply: "1000".parse().unwrap(), symbol: '¢', mint: None, }),