Skip to content

Glossary Groove: Additional tweaks to the glossary - #4

Merged
mhluongo merged 4 commits into
masterfrom
glossary-groove
Nov 20, 2017
Merged

Glossary Groove: Additional tweaks to the glossary#4
mhluongo merged 4 commits into
masterfrom
glossary-groove

Conversation

@Shadowfiend

@Shadowfiend Shadowfiend commented Nov 15, 2017

Copy link
Copy Markdown
Contributor

For accumulating any updates based on remarks/comments about the glossary.

  • Add some verbiage and relationships for the threshold relay.

Comment thread docs/glossary.adoc Outdated
@@ -1,15 +1,21 @@
= Glossary

Stake:: An amount of KEEP that is put in escrow in order to participate in the

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say "bonded" to use the correct term rather than confusing this with escrow.

Comment thread docs/glossary.adoc

Minimum Stake Amount:: The minimum stake that will make a staking client a
staker.
Minimum Stake Amount:: The minimum stake amount that will make a staking client

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something about being required by the contract, maybe?

@Shadowfiend

Copy link
Copy Markdown
Contributor Author

Addressed those two notes and added a couple of more concepts/verbs/relationships around the relay.

@mhluongo mhluongo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@mhluongo
mhluongo merged commit 162fcd4 into master Nov 20, 2017
@Shadowfiend
Shadowfiend deleted the glossary-groove branch November 21, 2017 14:34
lionakhnazarov added a commit that referenced this pull request Jun 4, 2026
…ety) (#4016)

## Context

Follow-up to #4000 addressing valid findings from the multi-agent
review. Stacks **on top of** `stack/testnet4-02-solidity-logic`; merge
after #4000.

## Findings addressed

| # | Fix | Commit |
|---|-----|--------|
| 3 | Allowlist redeploy-safe networks for `EcdsaDkgValidator` (was:
mainnet-only denylist) | \`fix(ecdsa/deploy): allowlist redeploy-safe
networks\` |
| 5 | README documenting vendored `random-beacon-export` regeneration
policy (`05_*.js` diverges intentionally) | \`docs(ecdsa/deploy):
document vendored random-beacon-export format policy\` |
| 7 | Restore \`HardhatUserConfig\` type annotation (TS 4.5 compatible,
no \`satisfies\`) | \`fix(ecdsa/hardhat): restore HardhatUserConfig type
annotation\` |
| 8 | \`verifyOnTenderlyOrContinue\` helper applied to all 4 deploy
scripts (was: only 03 swallowed errors) | \`fix(ecdsa/deploy): apply
tenderly verify-or-continue helper everywhere\` |
| 9 | Comment explaining sepolia named-account role collapse |
\`docs(ecdsa/hardhat): note sepolia named-account role collapse\` |
| 10 | Comment marking the second \`WalletRegistry.governance()\` read
as a deliberate TOCTOU recheck | \`docs(ecdsa/tasks): explain TOCTOU
recheck of WR.governance()\` |
| extra | Move \`README.md\` out of \`deploy/\` (hardhat-deploy walks
the dir and \`require()\`s every file) | \`fix(ecdsa/deploy): move
README out of deploy/ dir\` |

## Findings rejected after review

- **PR body wording on `WalletRegistry.sol`** (NatSpec-only) — best
handled by editing PR #4000's body directly, not as a code commit here.
- **Skip-suite disclosure** — same: belongs in PR #4000's body.
- \`#4\` (gate \`00_resolve_*\` on env var) — would break
\`deployments.fixture()\` in tests (\`yarn test\` runs the hardhat
network which needs the skip).
- \`#6\` (drop \`approveApplication\` try/catch) — deliberate runtime
backstop for forked/aliased networks where artifact ABI ≠ on-chain.

## Test Plan

Verified locally with \`FORKING_URL\` unset:
- \`cd solidity/ecdsa && yarn test\` → **644 passing, 44 pending, 0
failing**
- \`cd solidity/random-beacon && yarn test\` → **535 passing, 397
pending, 0 failing**

The 44 + 397 pending are the pre-existing \`describe.skip(...)\` suites
(legacy Keep TokenStaking ABI unavailable in current Threshold build).
mswilkison added a commit that referenced this pull request Jun 12, 2026
…ence (#4040)

Post-merge follow-up **#4** from the June 2026 review stack
(#4028#4035): replace `json.Marshal` as the canonical signed-bytes
encoding for evidence snapshots/bundles — explicitly scheduled to land
**before Phase 7 wiring ossifies the format**. (Items 2 and 3 landed as
#4036/#4037 on the mirror branch; this is the Go-side sibling on the
scaffold branch.)

## Why now

The RFC-21 Layer B evidence signatures were computed over canonical
JSON. That byte stability is a Go-implementation accident —
field-order-stable `encoding/json` output — not a portable contract. The
moment Phase 7 wires evidence verification into the Rust signer (or any
second implementation appears), every verifier would need to replicate
Go's exact JSON emission. No persisted or cross-component evidence
exists yet, so the format can still change for free.

## Design: sign what you transmit, verify what you received

New `pkg/frost/roast/gen/pb/evidence.proto`:

- A snapshot travels as `SignedLocalEvidenceSnapshot{body,
operator_signature}` where `body` is the serialized
`LocalEvidenceSnapshotBody` — the operator signs those exact bytes.
- A transition message travels as `SignedTransitionMessage{body,
coordinator_signature}` whose `TransitionMessageBody` embeds every
member's signed snapshot envelope **verbatim** (`repeated bytes
signed_snapshots`) — the coordinator attests to the exact signed
snapshots it assembled, in order.
- Producers marshal a body **exactly once**, at signing time, and cache
it; parsed messages retain received body/envelope bytes verbatim;
verification always runs over exact received bytes. **Nothing in the
evidence chain is ever re-encoded**, so signature validity never depends
on any serializer's canonical form — across protobuf library versions or
across languages. This deliberately sidesteps protobuf's own caveat that
deterministic serialization is not canonical across implementations.
- `Marshal` of a received message returns the received envelope verbatim
— evidence bytes survive re-broadcast, including wire-legal but
non-canonical encodings (pinned by a handcrafted reversed-field-order
test).
- `CanonicalSnapshotBytes`/`CanonicalBundleBytes` → `SignableBytes()`
accessors; the coordinator's first-write-wins conflict check now
compares exact signed bytes.

## Tests

- Existing suite migrated off JSON fixtures: test-only encode helpers
bypass production signing so every structural-rejection path (zero
sender, bad hash length, unsorted/duplicate entries, oversize caps,
bundle ordering/hash-binding) is still exercised at the wire level.
- New `wire_test.go` pins the format's core properties:
byte-preservation through unmarshal→re-marshal, verbatim
snapshot-envelope embedding inside bundle bodies, producer-signed bytes
== receiver-verified bytes, non-canonical-encoding survival,
tampered-body verification failure.
- `go build ./...`, `go vet`, `gofmt` clean; frost + tbtc package tests
green. Generated with protoc 33.4 / protoc-gen-go v1.36.3 (matches the
go.mod protobuf runtime v1.36.3).

## Docs

RFC-21 "Evidence message format" decision rewritten: signed-body
protobuf envelopes, with the retirement rationale for canonical JSON
recorded.

## Notes for reviewers

- The in-memory model types (`LocalEvidenceSnapshot`,
`TransitionMessage`) are unchanged apart from two unexported byte
caches; all call sites kept their shapes.
- Immutability contract: evidence fields must not be mutated after
`SignableBytes()` is first computed (documented on the cache fields);
the aggregation flow already treats snapshots as immutable post-receipt.
- Phase 7 cross-language note: the Rust signer will verify
operator/coordinator signatures over `body` bytes and parse them with
any protobuf implementation — no canonicalization requirements transfer.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
mswilkison added a commit that referenced this pull request Jul 7, 2026
…#4)

Two honest nodes with divergent selection state selecting for the same
committed attempt would broadcast DIFFERENT NextAttempt included sets -- a
ROAST-consumed set vs a legacy shuffle -- the fracture class that splits the
signing group. The test first proves the divergence is real (a registered,
ROAST-active node selects the full 5-member transition set while a would-be
legacy node trims to the honest threshold), then proves the fail-closed guard
collapses that divergence: the SAME node-B Select call that returned a concrete
legacy set with the registry empty FAILS CLOSED once ROAST is active (a wiring
partial-registration), and node A fails closed on its missing expected
transition. Neither emits a NextAttempt set, so they cannot converge on
divergent ones -- the network fails closed instead of splitting.

Closes the gap where the fail-closed branches were only exercised in isolation
with fakes; nothing proved the two configs would actually diverge and that the
guard, not chance, suppresses the divergent legacy selection. The false->true
RoastRetryActive flip on node B's identical call is the proof, and each
fail-closed decision is repeated to show it is a deterministic per-seat function
of registry state. Pure-Go: no FROST rounds, bus, or block timing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
mswilkison added a commit that referenced this pull request Jul 7, 2026
…out, invalid-share, equivocation, overflow, cross-node fracture) (#4134)

## What

Adds **real-under-failure** ROAST retry/blame tests. Prior coverage was
disjoint: the real-cgo interactive e2es are happy-path only, and the
retry/parking/blame machinery (`next_attempt.go`, the round-2 collector,
the overflow primitive, the cross-node selector guard) is unit-tested
with fakes — nothing wired the real component + an induced fault + its
retry/blame outcome together. Each test asserts the induced fault was
**actually reached** (not merely that the outcome happened), so a
synthetic bundle can't make it pass vacuously.

## The tests

Over the real `pkg/net` transport against the real cgo FROST engine
(`pkg/frost/signing`, `frost_native frost_tbtc_signer cgo`):

- **`..._dropout_retry_...`** (#1) — a *selected* signer withholds its
round-2 share → the elected coordinator (the aggregator) starves on a
real collect-shares timeout → `NextAttempt` **transiently parks** the
silent seat → the reshuffled subset aggregates a real BIP-340 signature
and reaches `Succeeded`. Asserts the coordinator starves *specifically*
at share collection AND the target actually reached round 2 and produced
the share it withheld.
- **`..._invalid_share_exclusion_...`** (#2) — a selected signer submits
a structurally valid but cryptographically **wrong** round-2 share → the
real aggregate fails with a typed share-verification error naming the
culprit → an f+1 reject quorum **permanently excludes** it → the
surviving subset finalizes for real.
- **`..._share_conflict_equivocation_...`** (#3b) — a selected signer
runs round 2, produces a genuine FROST share, then broadcasts **two
body-different signed share submissions** (its real share + a re-signed
copy with a mutated `signature_share`), both binding the authoritative
package so both are *accepted* shares. An honest `Round2Collector` flags
the second as `EquivocationKindShareConflict` (`ErrShareConflict`) and
the process-wide observer receives the culprit-naming evidence. Asserts
the two envelopes are distinct, same-package-bound accepted shares (a
genuine double-sign, not a divergent share).
- **`..._coordinator_equivocation_...`** (#3a) — the elected coordinator
distributes **two VALID coordinator-signed packages** (distinct taproot
roots) for the same attempt → `verifiedCoordinatorEquivocations`
bypasses the f+1 gate and forces **instant permanent exclusion**, even
when the two proofs are split across two observers. Uses a **real
secp256k1 operator-key Signer/Verifier** (not the NoOp pair), with a
non-vacuous negative control: one authentic package + one whose
signature is corrupted (rejected by the real verifier) is only one
distinct authentic body and does **not** exclude — proving the verifier
is genuinely cryptographic.
- **`..._overflow_park_...`** (#3c) — a member floods a receive loop
faster than it drains, genuinely overflowing the bounded inbound channel
via the real `enqueueOrRecordOverflow` primitive → the real recorded
overflow evidence, carried by an f+1 quorum, drives a **transient park**
(not exclusion). Asserts the channel actually rejected enqueues and the
recorder recorded overflow, that the park is transient (a following
attempt reinstates the flooder), and that the f+1 quorum is genuinely
enforced (a single accuser does not park). The flooder is itself a
bundle sender, so silence-parking can't account for the park.

In `pkg/tbtc` (`frost_native frost_roast_retry`, pure-Go):

- **`..._cross_node_fracture_...`** (#4) — two nodes with divergent
selection state would broadcast **different NextAttempt sets** (a
ROAST-consumed set vs a legacy shuffle) — the fracture class that splits
the group. The test proves the divergence is real (registered
ROAST-active node selects the full transition set; a would-be-legacy
node trims to the honest threshold), then proves the **fail-closed
guard** collapses it: the SAME node-B `Select` call that returned a
concrete legacy set with the registry empty fails closed once ROAST is
active, and node A fails closed on its missing expected transition.
Neither emits a set, so they can't converge on divergent ones. Each
fail-closed decision is repeated to show it is deterministic per-seat.

## CI coverage

- #1/#2/#3a/#3b/#3c run under **frost-cgo-integration** (`frost_native
frost_tbtc_signer frost_roast_retry`, linked libfrost_tbtc).
- #4 runs under the **client** `frost_native frost_roast_retry` tag set
over `./pkg/tbtc/...`.

All six are green locally, stable across repeated runs, with no
regression to the existing real-cgo suite.
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.

2 participants