Skip to content

fix(ergo-nipopow): keep max level signed in update_interlinks so negative levels return interlinks unchanged - #959

Open
Kshot3000 wants to merge 1 commit into
ergoplatform:developfrom
Kshot3000:fix/update-interlinks-negative-level
Open

Kshot3000 wants to merge 1 commit into
ergoplatform:developfrom
Kshot3000:fix/update-interlinks-negative-level

Conversation

@Kshot3000

Copy link
Copy Markdown
Contributor

Fixes #958: NipopowAlgos::update_interlinks cast the previous header's max level to usize before checking whether it is positive. max_level_of returns an i32 and is negative for a header whose PoW hit exceeds its target (an invalid-PoW header), so the cast turned the level into a huge positive count and the function tried to build an interlinks vector with that many copies of the header id, panicking with capacity overflow. The reference implementation (NipopowAlgos.updateInterlinks in the Ergo node) keeps the level a signed Int, checks prevLevel > 0 on it, and returns the previous interlinks unchanged for a non-positive level.

Changes (ergo-nipopow only)

  • update_interlinks now keeps prev_level as i32 for the positivity check and casts to usize only after the check, mirroring the reference exactly. Behaviour for every positive level is unchanged — including the branch where the level exceeds the interlinks length (dropRight saturates the same way in the reference).

Tests

Five new regression tests in a new integration-test file, ergo-nipopow/tests/update_interlinks_negative_level.rs (kept out of nipopow_algos.rs so this diff stays independent of the other open changes to that file). The headers are Autolykos v1, where pow_hit is the pow_distance field itself; with n_bits = 0x207fffff the required target is exactly 2, so each test pins the max_level_of it exercises before asserting on update_interlinks:

  • negative_level_returns_prev_interlinks_unchanged — level -18 (pow_distance = 1_000_000); on develop this panicked with capacity overflow (verified before the fix, under a 2 GB ulimit -v), now the previous interlinks are returned unchanged.
  • level_truncating_to_zero_returns_prev_interlinks_unchanged — level 0 after truncation; unchanged.
  • positive_level_one_replaces_last_interlink — level 1 keeps working: genesis + tail-minus-last + one copy of the previous header id.
  • positive_level_above_interlinks_len_fills_from_genesis — level 8 against 3 interlinks: genesis + 8 copies of the previous header id.
  • genesis_header_starts_interlinks_with_own_id — the genesis path is untouched.

Results: cargo test -p ergo-nipopow --all-features 6/6 (5 new + the existing proof roundtrip); downstream cargo test -p ergo-chain-generation --all-features lib suite 18/18 (the crate that builds chains through update_interlinks) and cargo test -p ergo-lib --all-features 121/121; cargo clippy -p ergo-nipopow --all-features --all-targets -- -D warnings clean; cargo fmt --check clean for the touched files.

File-overlap note: open #957 also touches nipopow_algos.rs, but in pack_interlinks (a different function, non-overlapping hunks), and its tests live in a unit-test module in that file while these live in tests/ — the two should rebase cleanly in either order.


Built by @Kshot9000 (https://x.com/kshot9000) · Tips (ERG): 9fcM5RWnAjmP4vx5bnW6yohB6H9bLq8sJbaPLHtwZLtQPB32Pvy

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ergo-nipopow: update_interlinks panics on a header with a negative max level (signed level cast to usize before the positivity check)

1 participant