From 01d83f1cea8a0125b5480766fee0aba0a698aa73 Mon Sep 17 00:00:00 2001 From: Casey Rodarmor Date: Tue, 24 Oct 2023 12:05:26 -0700 Subject: [PATCH] Improve rune minimum at height (#2546) --- src/runes.rs | 50 +++++++++++++------------- src/runes/rune.rs | 77 +++++++++++++++++++++++++++++++++------- src/subcommand/server.rs | 35 +++++++++--------- 3 files changed, 106 insertions(+), 56 deletions(-) diff --git a/src/runes.rs b/src/runes.rs index 97d5c52341..f914671fb6 100644 --- a/src/runes.rs +++ b/src/runes.rs @@ -21,7 +21,7 @@ type Result = std::result::Result; mod tests { use {super::*, crate::index::testing::Context}; - const RUNE: u128 = (21_000_000 * COIN_VALUE) as u128; + const RUNE: u128 = 99246114928149462; #[test] fn index_starts_with_no_runes() { @@ -186,7 +186,7 @@ mod tests { } #[test] - fn sat_corresponding_to_rune_must_have_been_mined() { + fn runes_must_be_greater_than_or_equal_to_minimum_for_height() { { let context = Context::builder() .arg("--index-runes-pre-alpha-i-agree-to-get-rekt") @@ -204,7 +204,7 @@ mod tests { output: 0, }], etching: Some(Etching { - rune: Rune(u128::from(Sat::SUPPLY - 150 * COIN_VALUE - 1)), + rune: Rune(RUNE - 1), ..Default::default() }), ..Default::default() @@ -238,7 +238,7 @@ mod tests { output: 0, }], etching: Some(Etching { - rune: Rune(u128::from(Sat::SUPPLY - 150 * COIN_VALUE)), + rune: Rune(RUNE), ..Default::default() }), ..Default::default() @@ -261,7 +261,7 @@ mod tests { id, RuneEntry { etching: txid, - rune: Rune(u128::from(Sat::SUPPLY - 150 * COIN_VALUE)), + rune: Rune(RUNE), supply: u128::max_value(), ..Default::default() } @@ -1271,17 +1271,17 @@ mod tests { [ ( OutPoint { - txid: txid1, + txid: txid0, vout: 0 }, - vec![(id1, u128::max_value())] + vec![(id0, u128::max_value())] ), ( OutPoint { - txid: txid0, + txid: txid1, vout: 0 }, - vec![(id0, u128::max_value())] + vec![(id1, u128::max_value())] ), ] ); @@ -1446,17 +1446,17 @@ mod tests { [ ( OutPoint { - txid: txid1, + txid: txid0, vout: 0 }, - vec![(id1, u128::max_value())] + vec![(id0, u128::max_value())] ), ( OutPoint { - txid: txid0, + txid: txid1, vout: 0 }, - vec![(id0, u128::max_value())] + vec![(id1, u128::max_value())] ), ] ); @@ -1695,17 +1695,17 @@ mod tests { [ ( OutPoint { - txid: txid1, + txid: txid0, vout: 0 }, - vec![(id1, u128::max_value())] + vec![(id0, u128::max_value())] ), ( OutPoint { - txid: txid0, + txid: txid1, vout: 0 }, - vec![(id0, u128::max_value())] + vec![(id1, u128::max_value())] ), ] ); @@ -1954,17 +1954,17 @@ mod tests { [ ( OutPoint { - txid: txid1, + txid: txid0, vout: 0 }, - vec![(id1, u128::max_value())] + vec![(id0, u128::max_value())] ), ( OutPoint { - txid: txid0, + txid: txid1, vout: 0 }, - vec![(id0, u128::max_value())] + vec![(id1, u128::max_value())] ), ] ); @@ -2195,17 +2195,17 @@ mod tests { [ ( OutPoint { - txid: txid1, + txid: txid0, vout: 0 }, - vec![(id1, u128::max_value())] + vec![(id0, u128::max_value())] ), ( OutPoint { - txid: txid0, + txid: txid1, vout: 0 }, - vec![(id0, u128::max_value())] + vec![(id1, u128::max_value())] ), ] ); diff --git a/src/runes/rune.rs b/src/runes/rune.rs index e47046b7b6..99a0ec7801 100644 --- a/src/runes/rune.rs +++ b/src/runes/rune.rs @@ -5,9 +5,19 @@ pub struct Rune(pub u128); impl Rune { pub(crate) fn minimum_at_height(height: Height) -> Self { - Self(u128::from( - Sat::SUPPLY - height.starting_sat().0 - height.subsidy(), - )) + let length = 13u64 + .saturating_sub(height.0 / (DIFFCHANGE_INTERVAL * 2)) + .max(1); + + let mut rune = 0u128; + for i in 0..length { + if i > 0 { + rune += 1; + } + rune *= 26; + } + + Rune(rune) } } @@ -131,16 +141,57 @@ mod tests { } #[test] - fn minimum_for_height() { - assert_eq!(Rune::minimum_at_height(Sat::LAST.height()).to_string(), "A"); - assert_eq!( - Rune::minimum_at_height(Height(0)).to_string(), - Sat(50 * COIN_VALUE - 1).name().to_uppercase() - ); - assert_eq!( - Rune::minimum_at_height(Height(1)).to_string(), - Sat(100 * COIN_VALUE - 1).name().to_uppercase() - ); + #[allow(clippy::identity_op)] + #[allow(clippy::erasing_op)] + #[allow(clippy::zero_prefixed_literal)] + fn minimum_at_height() { + #[track_caller] + fn case(height: u64, minimum: &str) { + assert_eq!(Rune::minimum_at_height(Height(height)).to_string(), minimum); + } + + case(2016 * 2 * 00 + 0, "AAAAAAAAAAAAA"); + case(2016 * 2 * 00 + 1, "AAAAAAAAAAAAA"); + case(2016 * 2 * 01 - 1, "AAAAAAAAAAAAA"); + case(2016 * 2 * 01 + 0, "AAAAAAAAAAAA"); + case(2016 * 2 * 01 + 1, "AAAAAAAAAAAA"); + case(2016 * 2 * 02 - 1, "AAAAAAAAAAAA"); + case(2016 * 2 * 02 + 0, "AAAAAAAAAAA"); + case(2016 * 2 * 02 + 1, "AAAAAAAAAAA"); + case(2016 * 2 * 03 - 1, "AAAAAAAAAAA"); + case(2016 * 2 * 03 + 0, "AAAAAAAAAA"); + case(2016 * 2 * 03 + 1, "AAAAAAAAAA"); + case(2016 * 2 * 04 - 1, "AAAAAAAAAA"); + case(2016 * 2 * 04 + 0, "AAAAAAAAA"); + case(2016 * 2 * 04 + 1, "AAAAAAAAA"); + case(2016 * 2 * 05 - 1, "AAAAAAAAA"); + case(2016 * 2 * 05 + 0, "AAAAAAAA"); + case(2016 * 2 * 05 + 1, "AAAAAAAA"); + case(2016 * 2 * 06 - 1, "AAAAAAAA"); + case(2016 * 2 * 06 + 0, "AAAAAAA"); + case(2016 * 2 * 06 + 1, "AAAAAAA"); + case(2016 * 2 * 07 - 1, "AAAAAAA"); + case(2016 * 2 * 07 + 0, "AAAAAA"); + case(2016 * 2 * 07 + 1, "AAAAAA"); + case(2016 * 2 * 08 - 1, "AAAAAA"); + case(2016 * 2 * 08 + 0, "AAAAA"); + case(2016 * 2 * 08 + 1, "AAAAA"); + case(2016 * 2 * 09 - 1, "AAAAA"); + case(2016 * 2 * 09 + 0, "AAAA"); + case(2016 * 2 * 09 + 1, "AAAA"); + case(2016 * 2 * 10 - 1, "AAAA"); + case(2016 * 2 * 10 + 0, "AAA"); + case(2016 * 2 * 10 + 1, "AAA"); + case(2016 * 2 * 11 - 1, "AAA"); + case(2016 * 2 * 11 + 0, "AA"); + case(2016 * 2 * 11 + 1, "AA"); + case(2016 * 2 * 12 - 1, "AA"); + case(2016 * 2 * 12 + 0, "A"); + case(2016 * 2 * 12 + 1, "A"); + case(2016 * 2 * 13 - 1, "A"); + case(2016 * 2 * 13 + 0, "A"); + case(2016 * 2 * 13 + 1, "A"); + case(u64::max_value(), "A"); } #[test] diff --git a/src/subcommand/server.rs b/src/subcommand/server.rs index 5f79faac42..becb38941c 100644 --- a/src/subcommand/server.rs +++ b/src/subcommand/server.rs @@ -1245,6 +1245,8 @@ mod tests { std::net::TcpListener, }; + const RUNE: u128 = 99246114928149462; + struct TestServer { bitcoin_rpc_server: test_bitcoincore_rpc::Handle, index: Arc, @@ -1766,7 +1768,7 @@ mod tests { server.mine_blocks(1); - let rune = Rune(u128::from(21_000_000 * COIN_VALUE)); + let rune = Rune(RUNE); server.assert_response_regex(format!("/rune/{rune}"), StatusCode::NOT_FOUND, ".*"); @@ -1792,8 +1794,8 @@ mod tests { server.mine_blocks(1); - server.assert_redirect("/search/2/1", "/rune/NVTDIJZYIPU"); - server.assert_redirect("/search?query=2/1", "/rune/NVTDIJZYIPU"); + server.assert_redirect("/search/2/1", "/rune/AAAAAAAAAAAAA"); + server.assert_redirect("/search?query=2/1", "/rune/AAAAAAAAAAAAA"); server.assert_response_regex("/rune/100/200", StatusCode::NOT_FOUND, ".*"); @@ -3202,7 +3204,7 @@ mod tests { output: 0, }], etching: Some(Etching { - rune: Rune(u128::from(21_000_000 * COIN_VALUE)), + rune: Rune(RUNE), ..Default::default() }), ..Default::default() @@ -3225,7 +3227,7 @@ mod tests { id, RuneEntry { etching: txid, - rune: Rune(u128::from(21_000_000 * COIN_VALUE)), + rune: Rune(RUNE), supply: u128::max_value(), ..Default::default() } @@ -3243,7 +3245,7 @@ mod tests { ".*Runes.*

Runes

.*", ); } @@ -3254,7 +3256,7 @@ mod tests { server.mine_blocks(1); - let rune = Rune(u128::from(21_000_000 * COIN_VALUE)); + let rune = Rune(RUNE); server.assert_response_regex(format!("/rune/{rune}"), StatusCode::NOT_FOUND, ".*"); @@ -3309,8 +3311,8 @@ mod tests { format!("/rune/{rune}"), StatusCode::OK, format!( - r".*Rune NVTDIJZYIPU.* -

Rune NVTDIJZYIPU

+ r".*Rune AAAAAAAAAAAAA.* +

Rune AAAAAAAAAAAAA

id
@@ -3341,7 +3343,7 @@ mod tests {
.*
rune
-
NVTDIJZYIPU
+
AAAAAAAAAAAAA
.*", ); @@ -3405,7 +3407,7 @@ mod tests { server.mine_blocks(1); - let rune = Rune(u128::from(21_000_000 * COIN_VALUE)); + let rune = Rune(RUNE); server.assert_response_regex(format!("/rune/{rune}"), StatusCode::NOT_FOUND, ".*"); @@ -3471,7 +3473,7 @@ mod tests { balance - NVTDIJZYIPU + AAAAAAAAAAAAA 34028236692093846346337460743176821145.5 @@ -3489,12 +3491,9 @@ mod tests { transaction: txid.to_string(), sat_ranges: None, inscriptions: Vec::new(), - runes: vec![( - Rune(2100000000000000), - 340282366920938463463374607431768211455 - )] - .into_iter() - .collect(), + runes: vec![(Rune(RUNE), 340282366920938463463374607431768211455)] + .into_iter() + .collect(), } ); }