clean API - #262
Merged
Merged
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Check the slot range before grinding the encoding randomness (no expensive work on out-of-range slots). - Reuse the encoding found during grinding instead of recomputing it, which removes the unreachable InvalidRandomness error variant and the now-unused WotsSecretKey::sign_with_randomness. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
xmss_key_gen(rng, activation_slot, num_active_slots) -> (pk, sk), sampling the seed from the caller's RNG and validating the activation interval against the 2^32 lifetime. The 'sequential' flag is gone from the public API: key generation asks the pool whether it already runs inside a pool task - where a nested dispatch would panic - via the new parallel::is_in_pool_task(), and falls back to a sequential build in that case (e.g. generating many keys in a parallel batch). Bottom-subtree builds during signing remain always sequential: signing must never wait on the thread pool while holding the signing-cache mutex, or a pool task blocked on the same key would deadlock the pool, and hence the signer. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The public API now takes message: &[u8; 32] (like leanSig), in leanSig's parameter order: sign(rng, sk, slot, msg) / verify(pk, slot, msg, sig). The message is embedded injectively into 9 field elements (little-endian base-p decomposition, identical convention to leanSig's encode_message) and hashed with a domain-separated poseidon16_compress into the [F; 8] 'message' the WOTS encoding - and hence the snark, which is unchanged - consumes. hash_message() is public so the aggregation pipeline can compute the snark-side message at the boundary. encode_message is checked against independently computed base-p reference vectors. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
xmss_sign(&sk, slot, message) no longer takes an RNG: the encoding randomness for attempt i is Poseidon-derived from (secret seed, slot, attempt, hashed message). Re-signing the same (slot, message) pair now returns the identical signature, so an accidental double-sign of the same message is harmless (signing a different message at the same slot remains fatal, as in any synchronized scheme). Grinding is bounded by MAX_SIGNING_ATTEMPTS (expected ~a few hundred attempts for target_sum = 184); exceeding it returns EncodingAttemptsExceeded instead of looping forever. The unbounded find_randomness_for_wots_encoding is gone. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The first signature after crossing into a new bottom subtree pays an O(sqrt(R)) rebuild inside xmss_sign. XmssSecretKey::prepare(slot) lets callers do that work off the signing critical path; signing itself is unchanged (same lazy cache, now factored into cached_bottom_subtree). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Serializes (seed, slot range, top tree): storing the top tree makes reload cheap (no re-hashing of the key's whole range), while the derived fields are recomputed and the tree shape is revalidated against the range on deserialization. The bottom-subtree cache restarts empty. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Manual ethereum_ssz implementations; field elements are canonical u32 little-endian, rejected on decode when non-canonical. - XmssPublicKey: fixed 32 bytes (root | public_param) - XmssSignature: fixed 1208 bytes (chain_tips | randomness | merkle_proof) Only these two appear in consensus objects. The secret key deliberately gets no SSZ: it never crosses the consensus layer, serde covers local persistence, and a future keystore standard (a la EIP-2335 for BLS, which encrypts the raw scalar, not an SSZ object) should own the canonical secret-key format - for this scheme the minimal secret material is just the 32-byte seed and the activation range. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Missed in the per-commit migration because cargo check without --all-targets skips the root integration tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pool tasks and a plain thread signing with one shared key: exercises the cache-mutex contention paths (sequential subtree builds under the lock, so no signer ever waits on the pool while holding it) and checks that derandomization yields identical signatures from either context. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Only WotsSignature (a field of XmssSignature) is API; the one-time secret keys (whose pre-image array was even a public field), chain walking, public-key recovery, and the encoding are building blocks of xmss_sign / xmss_verify that no external caller should touch. The grinding measurement moves in-crate as a unit test with them. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
XmssSecretKey's derived Debug printed the seed (and the seed-derived
tree); one {:?} in a log line would leak the key. The manual impl shows
only the slot range and split level. WotsSecretKey (crate-internal)
loses Debug entirely.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
signers_cache generates 10k keys, writes caches under target/, and prints progress - benchmark machinery, not signature API. It is now compiled only for in-crate tests or under the new 'test-utils' feature, which rec_aggregation and the root crate enable explicitly (postcard becomes an optional dependency tied to it). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
They already appeared in public signatures (pub merkle_root: Digest, ...), so rustdoc rendered types downstream users could not name. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
xmss_key_gen_from_seed(seed, activation_slot, num_active_slots): the same (seed, range) always regenerates the same key pair, so a backed-up seed is enough to recover a key. xmss_key_gen becomes a thin wrapper that samples the seed from the RNG. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Without them a lean-multisig user could not match on the errors returned by the re-exported xmss_key_gen / xmss_sign / xmss_verify without adding a direct xmss dependency. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A leading format-version byte in the serde encoding, checked on decode, so a future layout change fails with an explicit error (and can be migrated) instead of a confusing shape mismatch. pk/sig SSZ formats are consensus-spec'd and stay untagged. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
aggregate_single_message_signatures, SingleMessageInfo.message, and split_multi_message_aggregate_by_message now take the raw 32-byte message; the Poseidon message hash the snark consumes is computed internally (once per aggregation / input-data build). Callers no longer deal in field-element messages anywhere. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The public API deals exclusively in 32-byte messages: MESSAGE_LEN_FE, MESSAGE_EMBEDDING_LEN_FE, and encode_message become crate-private, and hash_message is doc(hidden) (it stays technically pub only because rec_aggregation needs it for the snark public input). The zkDSL placeholder uses DIGEST_LEN, which the hashed message is. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The workspace build always enables xmss's 'test-utils' feature via rec_aggregation, so the configuration downstream users get (no feature, optional postcard off) was never built in CI. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.