diff --git a/src/runes.rs b/src/runes.rs index 1cae1b378e..050c46e3f7 100644 --- a/src/runes.rs +++ b/src/runes.rs @@ -171,7 +171,7 @@ mod tests { #[test] fn runes_must_be_greater_than_or_equal_to_minimum_for_height() { - const SECOND_BLOCK_LOCKED_RUNE: u128 = 99235208761673842; + let block_two_minimum: u128 = Rune::minimum_at_height(Chain::Regtest, Height(2)).0; { let context = Context::builder() @@ -191,7 +191,7 @@ mod tests { output: 0, }], etching: Some(Etching { - rune: Some(Rune(SECOND_BLOCK_LOCKED_RUNE - 1)), + rune: Some(Rune(block_two_minimum - 1)), ..Default::default() }), ..Default::default() @@ -221,7 +221,7 @@ mod tests { output: 0, }], etching: Some(Etching { - rune: Some(Rune(SECOND_BLOCK_LOCKED_RUNE)), + rune: Some(Rune(block_two_minimum)), ..Default::default() }), ..Default::default() @@ -243,7 +243,7 @@ mod tests { id, RuneEntry { etching: txid, - rune: Rune(SECOND_BLOCK_LOCKED_RUNE), + rune: Rune(block_two_minimum), supply: u128::max_value(), timestamp: 2, ..Default::default() diff --git a/src/runes/rune.rs b/src/runes/rune.rs index 8dd061bff0..8321c81680 100644 --- a/src/runes/rune.rs +++ b/src/runes/rune.rs @@ -36,21 +36,23 @@ impl Rune { ]; pub(crate) fn minimum_at_height(chain: Chain, height: Height) -> Self { + let offset = height.0.saturating_add(1); + const INTERVAL: u32 = SUBSIDY_HALVING_INTERVAL / 12; let start = chain.first_rune_height(); let end = start + SUBSIDY_HALVING_INTERVAL; - if height.0 < start { + if offset < start { return Rune(Self::STEPS[12]); } - if height.0 >= end { + if offset >= end { return Rune(0); } - let progress = height.0.saturating_sub(start); + let progress = offset.saturating_sub(start); let length = 12u32.saturating_sub(progress / INTERVAL); @@ -210,66 +212,69 @@ mod tests { case(0, "AAAAAAAAAAAAA"); case(START / 2, "AAAAAAAAAAAAA"); - case(START, "AAAAAAAAAAAAA"); - case(START + 1, "ZZYZXBRKWXVA"); - case(END - 1, "B"); + case(START, "ZZYZXBRKWXVA"); + case(START + 1, "ZZXZUDIVTVQA"); + case(END - 1, "A"); case(END, "A"); case(END + 1, "A"); case(u32::max_value(), "A"); case(START + INTERVAL * 00 - 1, "AAAAAAAAAAAAA"); - case(START + INTERVAL * 00 + 0, "AAAAAAAAAAAAA"); - case(START + INTERVAL * 00 + 1, "ZZYZXBRKWXVA"); + case(START + INTERVAL * 00 + 0, "ZZYZXBRKWXVA"); + case(START + INTERVAL * 00 + 1, "ZZXZUDIVTVQA"); - case(START + INTERVAL * 01 - 1, "AABACYIPDCFB"); - case(START + INTERVAL * 01 + 0, "AAAAAAAAAAAA"); - case(START + INTERVAL * 01 + 1, "ZZYZXBRKWXV"); + case(START + INTERVAL * 01 - 1, "AAAAAAAAAAAA"); + case(START + INTERVAL * 01 + 0, "ZZYZXBRKWXV"); + case(START + INTERVAL * 01 + 1, "ZZXZUDIVTVQ"); - case(START + INTERVAL * 02 - 1, "AABACYIPDCG"); - case(START + INTERVAL * 02 + 0, "AAAAAAAAAAA"); - case(START + INTERVAL * 02 + 1, "ZZYZXBRKWY"); + case(START + INTERVAL * 02 - 1, "AAAAAAAAAAA"); + case(START + INTERVAL * 02 + 0, "ZZYZXBRKWY"); + case(START + INTERVAL * 02 + 1, "ZZXZUDIVTW"); - case(START + INTERVAL * 03 - 1, "AABACYIPDD"); - case(START + INTERVAL * 03 + 0, "AAAAAAAAAA"); - case(START + INTERVAL * 03 + 1, "ZZYZXBRKX"); + case(START + INTERVAL * 03 - 1, "AAAAAAAAAA"); + case(START + INTERVAL * 03 + 0, "ZZYZXBRKX"); + case(START + INTERVAL * 03 + 1, "ZZXZUDIVU"); - case(START + INTERVAL * 04 - 1, "AABACYIPE"); - case(START + INTERVAL * 04 + 0, "AAAAAAAAA"); - case(START + INTERVAL * 04 + 1, "ZZYZXBRL"); + case(START + INTERVAL * 04 - 1, "AAAAAAAAA"); + case(START + INTERVAL * 04 + 0, "ZZYZXBRL"); + case(START + INTERVAL * 04 + 1, "ZZXZUDIW"); - case(START + INTERVAL * 05 - 1, "AABACYIQ"); - case(START + INTERVAL * 05 + 0, "AAAAAAAA"); - case(START + INTERVAL * 05 + 1, "ZZYZXBS"); + case(START + INTERVAL * 05 - 1, "AAAAAAAA"); + case(START + INTERVAL * 05 + 0, "ZZYZXBS"); + case(START + INTERVAL * 05 + 1, "ZZXZUDJ"); - case(START + INTERVAL * 06 - 1, "AABACYJ"); - case(START + INTERVAL * 06 + 0, "AAAAAAA"); - case(START + INTERVAL * 06 + 1, "ZZYZXC"); + case(START + INTERVAL * 06 - 1, "AAAAAAA"); + case(START + INTERVAL * 06 + 0, "ZZYZXC"); + case(START + INTERVAL * 06 + 1, "ZZXZUE"); - case(START + INTERVAL * 07 - 1, "AABACZ"); - case(START + INTERVAL * 07 + 0, "AAAAAA"); - case(START + INTERVAL * 07 + 1, "ZZYZY"); + case(START + INTERVAL * 07 - 1, "AAAAAA"); + case(START + INTERVAL * 07 + 0, "ZZYZY"); + case(START + INTERVAL * 07 + 1, "ZZXZV"); - case(START + INTERVAL * 08 - 1, "AABAD"); - case(START + INTERVAL * 08 + 0, "AAAAA"); - case(START + INTERVAL * 08 + 1, "ZZZA"); + case(START + INTERVAL * 08 - 1, "AAAAA"); + case(START + INTERVAL * 08 + 0, "ZZZA"); + case(START + INTERVAL * 08 + 1, "ZZYA"); - case(START + INTERVAL * 09 - 1, "AABB"); - case(START + INTERVAL * 09 + 0, "AAAA"); - case(START + INTERVAL * 09 + 1, "ZZZ"); + case(START + INTERVAL * 09 - 1, "AAAA"); + case(START + INTERVAL * 09 + 0, "ZZZ"); + case(START + INTERVAL * 09 + 1, "ZZY"); - case(START + INTERVAL * 10 - 1, "AAC"); + case(START + INTERVAL * 10 - 2, "AAC"); + case(START + INTERVAL * 10 - 1, "AAA"); case(START + INTERVAL * 10 + 0, "AAA"); case(START + INTERVAL * 10 + 1, "AAA"); case(START + INTERVAL * 10 + INTERVAL / 2, "NA"); - case(START + INTERVAL * 11 - 1, "AB"); + case(START + INTERVAL * 11 - 2, "AB"); + case(START + INTERVAL * 11 - 1, "AA"); case(START + INTERVAL * 11 + 0, "AA"); case(START + INTERVAL * 11 + 1, "AA"); case(START + INTERVAL * 11 + INTERVAL / 2, "N"); - case(START + INTERVAL * 12 - 1, "B"); + case(START + INTERVAL * 12 - 2, "B"); + case(START + INTERVAL * 12 - 1, "A"); case(START + INTERVAL * 12 + 0, "A"); case(START + INTERVAL * 12 + 1, "A"); } @@ -287,20 +292,25 @@ mod tests { case(Chain::Testnet, 0, "AAAAAAAAAAAAA"); case( Chain::Testnet, - SUBSIDY_HALVING_INTERVAL * 12, + SUBSIDY_HALVING_INTERVAL * 12 - 1, "AAAAAAAAAAAAA", ); case( Chain::Testnet, - SUBSIDY_HALVING_INTERVAL * 12 + 1, + SUBSIDY_HALVING_INTERVAL * 12, "ZZYZXBRKWXVA", ); + case( + Chain::Testnet, + SUBSIDY_HALVING_INTERVAL * 12 + 1, + "ZZXZUDIVTVQA", + ); - case(Chain::Signet, 0, "AAAAAAAAAAAAA"); - case(Chain::Signet, 1, "ZZYZXBRKWXVA"); + case(Chain::Signet, 0, "ZZYZXBRKWXVA"); + case(Chain::Signet, 1, "ZZXZUDIVTVQA"); - case(Chain::Regtest, 0, "AAAAAAAAAAAAA"); - case(Chain::Regtest, 1, "ZZYZXBRKWXVA"); + case(Chain::Regtest, 0, "ZZYZXBRKWXVA"); + case(Chain::Regtest, 1, "ZZXZUDIVTVQA"); } #[test] diff --git a/tests/etch.rs b/tests/etch.rs index dfd996bd2d..b0cf5f7823 100644 --- a/tests/etch.rs +++ b/tests/etch.rs @@ -74,10 +74,10 @@ fn rune_below_minimum_is_an_error() { CommandBuilder::new( format!( "--index-runes --regtest wallet etch --rune {} --divisibility 0 --fee-rate 1 --supply 1000 --symbol ยข", - Rune(99235208761673842 - 1), + Rune(99229755678436031 - 1), )) .rpc_server(&rpc_server) - .expected_stderr("error: rune is less than minimum for next block: ZZXZUDIVTVPZ < ZZXZUDIVTVQA\n") + .expected_stderr("error: rune is less than minimum for next block: ZZWZRFAGQTKY < ZZWZRFAGQTKZ\n") .expected_exit_code(1) .run_and_extract_stdout(); }