iuna

iuna - experimental devnet protocol
git clone https://iuna.jhx.app/git/iuna.git
Log | Files | Refs | README | LICENSE

commit 987a8312b91aaa5209a08c6f5dca5cf387cd8ada
parent ebb42a45515784cff6b5ce4683b57aabd00bff26
Author: Joris Hartog <jorishartog@hotmail.com>
Date:   Mon, 10 Aug 2026 00:00:54 +0200

Release v0.2.39

Diffstat:
MCargo.lock | 2+-
MCargo.toml | 2+-
Msrc/adapters/http.rs | 22++++------------------
Msrc/domain.rs | 35+++++++++++++++++++++++++++--------
4 files changed, 33 insertions(+), 28 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -537,7 +537,7 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "iuna" -version = "0.2.38" +version = "0.2.39" dependencies = [ "anyhow", "axum", diff --git a/Cargo.toml b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "iuna" -version = "0.2.38" +version = "0.2.39" edition = "2024" license = "Apache-2.0" diff --git a/src/adapters/http.rs b/src/adapters/http.rs @@ -3370,6 +3370,8 @@ const INDEX_HTML: &str = r#"<!doctype html> .mining-event-title { color: #eef6f8; font-weight: 850; overflow-wrap: anywhere; } .mining-event-detail { margin-top: 3px; color: #9fa8ad; font-size: 12px; line-height: 1.35; overflow-wrap: anywhere; } .mining-event-time { color: #7f888e; font-size: 11px; font-weight: 800; white-space: nowrap; } + .mining-event-empty { height: 42px; border: 1px solid #30383d; border-radius: 8px; background: #111316; } + .mining-event-empty .skeleton-line { width: 100%; height: 100%; border-radius: 8px; opacity: .55; } .panel-separator { border-top: 1px solid #2f363c; margin: 14px 0 12px; } .stratum-config { display: grid; gap: 10px; } .stratum-note { max-width: 760px; color: #9eb3bc; font-size: 12px; line-height: 1.45; } @@ -3795,24 +3797,7 @@ const INDEX_HTML: &str = r#"<!doctype html> <div class="mining-event-log" aria-label="Mining event log"> <div class="mining-event-log-head"><span>Event log</span><span x-text="`${miningEventLog().length} lines`"></span></div> <template x-if="miningEventLog().length === 0"> - <div class="mining-event skeleton-card" aria-hidden="true"> - <span class="mining-event-dot"></span> - <div> - <div class="skeleton-line medium"></div> - <div class="skeleton-line long"></div> - </div> - <div class="skeleton-line short"></div> - </div> - </template> - <template x-if="miningEventLog().length === 0"> - <div class="mining-event skeleton-card" aria-hidden="true"> - <span class="mining-event-dot"></span> - <div> - <div class="skeleton-line short"></div> - <div class="skeleton-line medium"></div> - </div> - <div class="skeleton-line short"></div> - </div> + <div class="mining-event-empty skeleton-card" aria-hidden="true"><div class="skeleton-line"></div></div> </template> <template x-for="event in miningEventLog()" :key="event.key"> <div class="mining-event" :class="event.kind"> @@ -6272,6 +6257,7 @@ mod tests { assert!(app_js.contains("slice(0, this.miningEventLimit)")); assert!(super::INDEX_HTML.contains("aria-label=\"Mining event log\"")); assert!(super::INDEX_HTML.contains("miningEventLog().length === 0")); + assert!(super::INDEX_HTML.contains("mining-event-empty")); assert!(app_js.contains("Resource budget:")); assert!(app_js.contains("isPowMineSuccessStatus")); assert!(app_js.contains("You mined a PoW action")); diff --git a/src/domain.rs b/src/domain.rs @@ -28,6 +28,7 @@ pub const MAX_VDF_ROUNDS: u64 = i64::MAX as u64; pub const MINE_DIFFICULTY_BITS: u32 = 12; pub const MINE_ACTIONS_PER_ANCHOR_LIMIT: usize = 2; pub const MINE_ACTIONS_PER_ANCHOR_LIMIT_ACTIVATION_HEIGHT: u64 = 200; +pub const FALLBACK_VDF_RETARGET_ACTIVATION_HEIGHT: u64 = 380; pub const MAX_BLINDED_TRANSACTION_EXPIRY_HEIGHTS: u64 = 20; pub const REVEAL_COMMITTEE_SIZE: usize = 3; pub const MAX_REVEAL_BUNDLE_BYTES: usize = 10_000; @@ -5862,7 +5863,10 @@ fn clamped_vdf_retarget_observed_block_ms(observed_block_ms: u64) -> u64 { } fn vdf_retarget_observed_block_ms(parent: &Block, child: &Block) -> Option<u64> { - if child.finalizer_mode != FinalizerMode::Ticket || child.finalizer_rank != 0 { + if child.finalizer_mode != FinalizerMode::Ticket { + return None; + } + if child.finalizer_rank != 0 && child.height < FALLBACK_VDF_RETARGET_ACTIVATION_HEIGHT { return None; } @@ -6650,14 +6654,16 @@ mod tests { } #[test] - fn vdf_retarget_observed_block_time_ignores_ticket_fallback_ranks() { + fn vdf_retarget_observed_block_time_includes_ticket_fallback_ranks_after_activation() { let parent = vdf_retarget_sample_block(0, FinalizerMode::Ticket, 0); let primary_child = vdf_retarget_sample_block(VDF_TARGET_BLOCK_MS, FinalizerMode::Ticket, 0); - let rank_one_child = - vdf_retarget_sample_block(VDF_TARGET_BLOCK_MS, FinalizerMode::Ticket, 1); - let rank_two_child = - vdf_retarget_sample_block(VDF_TARGET_BLOCK_MS * 2, FinalizerMode::Ticket, 2); + let mut rank_one_child = + vdf_retarget_sample_block(VDF_TARGET_BLOCK_MS * 2, FinalizerMode::Ticket, 1); + rank_one_child.height = FALLBACK_VDF_RETARGET_ACTIVATION_HEIGHT; + let mut rank_two_child = + vdf_retarget_sample_block(VDF_TARGET_BLOCK_MS * 4, FinalizerMode::Ticket, 2); + rank_two_child.height = FALLBACK_VDF_RETARGET_ACTIVATION_HEIGHT + 1; assert_eq!( vdf_retarget_observed_block_ms(&parent, &primary_child), @@ -6665,10 +6671,23 @@ mod tests { ); assert_eq!( vdf_retarget_observed_block_ms(&parent, &rank_one_child), - None + Some(VDF_TARGET_BLOCK_MS * 2) ); assert_eq!( vdf_retarget_observed_block_ms(&parent, &rank_two_child), + Some(VDF_TARGET_BLOCK_MS * 4) + ); + } + + #[test] + fn vdf_retarget_observed_block_time_ignores_ticket_fallback_ranks_before_activation() { + let parent = vdf_retarget_sample_block(0, FinalizerMode::Ticket, 0); + let mut fallback_child = + vdf_retarget_sample_block(VDF_TARGET_BLOCK_MS * 2, FinalizerMode::Ticket, 1); + fallback_child.height = FALLBACK_VDF_RETARGET_ACTIVATION_HEIGHT - 1; + + assert_eq!( + vdf_retarget_observed_block_ms(&parent, &fallback_child), None ); } @@ -6743,7 +6762,7 @@ mod tests { } #[test] - fn fallback_block_is_excluded_from_vdf_retarget_observations() { + fn fallback_block_before_activation_is_excluded_from_vdf_retarget_observations() { let alice = Wallet::from_seed("fallback-retarget-alice"); let bob = Wallet::from_seed("fallback-retarget-bob"); let wallets = [&alice, &bob];