Skip to content

fix: Header.stateRoot is an AvlTree; v2 powOnetimePk is the group generator#887

Open
mwaddip wants to merge 2 commits into
ergoplatform:developfrom
mwaddip:fix/header-accessor-surfaces
Open

fix: Header.stateRoot is an AvlTree; v2 powOnetimePk is the group generator#887
mwaddip wants to merge 2 commits into
ergoplatform:developfrom
mwaddip:fix/header-accessor-surfaces

Conversation

@mwaddip

@mwaddip mwaddip commented Jun 7, 2026

Copy link
Copy Markdown

Two Header accessor surfaces diverged from the reference impl (both caught by JVM-blessed byte vectors):

stateRoot is typed SAvlTree — and our method descriptor already declares it so — but the eval impl returned the raw 33 digest bytes as Coll[Byte]. It now returns the AvlTree wrapping the digest with all operations enabled, keyLength 32, no value length (CHeader.stateRoot via AvlTreeData.avlTreeFromDigest).

powOnetimePk on autolykos-v2 headers surfaced 33 zero bytes (None at parse → EcPoint::default() at eval). The reference impl fills the group generator at parse (ErgoHeader.scala: wForV2); we now do the same (v2 serializer ignores the field — header ids and roundtrip bytes unchanged), with the eval fallback also the generator.

mwaddip and others added 2 commits June 7, 2026 12:21
… Coll[Byte]

The method is typed SAvlTree (and our descriptor already declares it
so): the reference impl wraps the header digest in an AvlTree with all
operations enabled, keyLength 32 and no value length
(CHeader.stateRoot via AvlTreeData.avlTreeFromDigest). The eval impl
returned the raw 33 digest bytes as Coll[Byte] — same bytes, wrong
type surface (downstream AvlTree method calls vs collection ops).

Pinned by the JVM-blessed byte vector (santa-eval
Header.property_accessors, h.stateRoot#nominal).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The reference impl has no absent state for the one-time pk: v2 header
parsing fills it with the group generator (ErgoHeader.scala: wForV2 =
CryptoConstants.dlogGroup.generator), and Header.powOnetimePk surfaces
that in scripts. sigma-rust parsed it as None and the eval fn defaulted
to EcPoint::default() — the identity, 33 zero bytes.

Wire parsing now fills the generator for v2 (the v2 serializer ignores
the field, so header ids and roundtrip bytes are unchanged; the
arbitrary generator produces the same post-parse shape), and the eval
fallback for headers built without it (e.g. JSON with no `w`) is the
generator as well.

Pinned by the JVM-blessed byte vector (santa-eval
Header.property_accessors, h.powOnetimePk#nominal).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

1 participant