Skip to content

Commit

Permalink
Improve rune minimum at height (ordinals#2546)
Browse files Browse the repository at this point in the history
  • Loading branch information
casey authored Oct 24, 2023
1 parent 805b949 commit 01d83f1
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 56 deletions.
50 changes: 25 additions & 25 deletions src/runes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type Result<T, E = Error> = std::result::Result<T, E>;
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() {
Expand Down Expand Up @@ -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")
Expand All @@ -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()
Expand Down Expand Up @@ -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()
Expand All @@ -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()
}
Expand Down Expand Up @@ -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())]
),
]
);
Expand Down Expand Up @@ -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())]
),
]
);
Expand Down Expand Up @@ -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())]
),
]
);
Expand Down Expand Up @@ -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())]
),
]
);
Expand Down Expand Up @@ -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())]
),
]
);
Expand Down
77 changes: 64 additions & 13 deletions src/runes/rune.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down Expand Up @@ -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]
Expand Down
35 changes: 17 additions & 18 deletions src/subcommand/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1245,6 +1245,8 @@ mod tests {
std::net::TcpListener,
};

const RUNE: u128 = 99246114928149462;

struct TestServer {
bitcoin_rpc_server: test_bitcoincore_rpc::Handle,
index: Arc<Index>,
Expand Down Expand Up @@ -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, ".*");

Expand All @@ -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, ".*");

Expand Down Expand Up @@ -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()
Expand All @@ -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()
}
Expand All @@ -3243,7 +3245,7 @@ mod tests {
".*<title>Runes</title>.*
<h1>Runes</h1>
<ul>
<li><a href=/rune/NVTDIJZYIPU>NVTDIJZYIPU</a></li>
<li><a href=/rune/AAAAAAAAAAAAA>AAAAAAAAAAAAA</a></li>
</ul>.*",
);
}
Expand All @@ -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, ".*");

Expand Down Expand Up @@ -3309,8 +3311,8 @@ mod tests {
format!("/rune/{rune}"),
StatusCode::OK,
format!(
r".*<title>Rune NVTDIJZYIPU</title>.*
<h1>Rune NVTDIJZYIPU</h1>
r".*<title>Rune AAAAAAAAAAAAA</title>.*
<h1>Rune AAAAAAAAAAAAA</h1>
<iframe .* src=/preview/{txid}i0></iframe>
<dl>
<dt>id</dt>
Expand Down Expand Up @@ -3341,7 +3343,7 @@ mod tests {
<dl>
.*
<dt>rune</dt>
<dd><a href=/rune/NVTDIJZYIPU>NVTDIJZYIPU</a></dd>
<dd><a href=/rune/AAAAAAAAAAAAA>AAAAAAAAAAAAA</a></dd>
</dl>
.*",
);
Expand Down Expand Up @@ -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, ".*");

Expand Down Expand Up @@ -3471,7 +3473,7 @@ mod tests {
<th>balance</th>
</tr>
<tr>
<td><a href=/rune/NVTDIJZYIPU>NVTDIJZYIPU</a></td>
<td><a href=/rune/AAAAAAAAAAAAA>AAAAAAAAAAAAA</a></td>
<td>34028236692093846346337460743176821145.5</td>
</tr>
</table>
Expand All @@ -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(),
}
);
}
Expand Down

0 comments on commit 01d83f1

Please sign in to comment.