May 21, 8-9 PM (23)
May 21, 9-10 PM (3)
May 21, 10-11 PM (29)
May 21, 11-12 AM (10)
May 22, 12-1 AM (16)
May 22, 1-2 AM (6)
May 22, 2-3 AM (8)
May 22, 3-4 AM (4)
May 22, 4-5 AM (11)
May 22, 5-6 AM (10)
May 22, 6-7 AM (21)
May 22, 7-8 AM (13)
May 22, 8-9 AM (38)
May 22, 9-10 AM (12)
May 22, 10-11 AM (18)
May 22, 11-12 PM (25)
May 22, 12-1 PM (24)
May 22, 1-2 PM (34)
May 22, 2-3 PM (56)
May 22, 3-4 PM (13)
May 22, 4-5 PM (29)
May 22, 5-6 PM (13)
May 22, 6-7 PM (20)
May 22, 7-8 PM (20)
May 22, 8-9 PM (12)
May 22, 9-10 PM (12)
May 22, 10-11 PM (41)
May 22, 11-12 AM (12)
May 23, 12-1 AM (9)
May 23, 1-2 AM (0)
May 23, 2-3 AM (3)
May 23, 3-4 AM (1)
May 23, 4-5 AM (1)
May 23, 5-6 AM (4)
May 23, 6-7 AM (12)
May 23, 7-8 AM (1)
May 23, 8-9 AM (3)
May 23, 9-10 AM (1)
May 23, 10-11 AM (1)
May 23, 11-12 PM (5)
May 23, 12-1 PM (1)
May 23, 1-2 PM (6)
May 23, 2-3 PM (5)
May 23, 3-4 PM (5)
May 23, 4-5 PM (4)
May 23, 5-6 PM (0)
May 23, 6-7 PM (3)
May 23, 7-8 PM (23)
May 23, 8-9 PM (1)
May 23, 9-10 PM (9)
May 23, 10-11 PM (21)
May 23, 11-12 AM (27)
May 24, 12-1 AM (9)
May 24, 1-2 AM (0)
May 24, 2-3 AM (1)
May 24, 3-4 AM (1)
May 24, 4-5 AM (0)
May 24, 5-6 AM (3)
May 24, 6-7 AM (1)
May 24, 7-8 AM (2)
May 24, 8-9 AM (2)
May 24, 9-10 AM (4)
May 24, 10-11 AM (4)
May 24, 11-12 PM (1)
May 24, 12-1 PM (7)
May 24, 1-2 PM (46)
May 24, 2-3 PM (5)
May 24, 3-4 PM (3)
May 24, 4-5 PM (18)
May 24, 5-6 PM (2)
May 24, 6-7 PM (4)
May 24, 7-8 PM (13)
May 24, 8-9 PM (10)
May 24, 9-10 PM (15)
May 24, 10-11 PM (34)
May 24, 11-12 AM (42)
May 25, 12-1 AM (9)
May 25, 1-2 AM (5)
May 25, 2-3 AM (6)
May 25, 3-4 AM (1)
May 25, 4-5 AM (6)
May 25, 5-6 AM (14)
May 25, 6-7 AM (17)
May 25, 7-8 AM (17)
May 25, 8-9 AM (32)
May 25, 9-10 AM (43)
May 25, 10-11 AM (64)
May 25, 11-12 PM (33)
May 25, 12-1 PM (43)
May 25, 1-2 PM (40)
May 25, 2-3 PM (20)
May 25, 3-4 PM (27)
May 25, 4-5 PM (16)
May 25, 5-6 PM (6)
May 25, 6-7 PM (7)
May 25, 7-8 PM (11)
May 25, 8-9 PM (12)
May 25, 9-10 PM (16)
May 25, 10-11 PM (44)
May 25, 11-12 AM (26)
May 26, 12-1 AM (12)
May 26, 1-2 AM (11)
May 26, 2-3 AM (8)
May 26, 3-4 AM (11)
May 26, 4-5 AM (6)
May 26, 5-6 AM (9)
May 26, 6-7 AM (26)
May 26, 7-8 AM (43)
May 26, 8-9 AM (39)
May 26, 9-10 AM (42)
May 26, 10-11 AM (45)
May 26, 11-12 PM (59)
May 26, 12-1 PM (34)
May 26, 1-2 PM (50)
May 26, 2-3 PM (50)
May 26, 3-4 PM (18)
May 26, 4-5 PM (20)
May 26, 5-6 PM (13)
May 26, 6-7 PM (20)
May 26, 7-8 PM (12)
May 26, 8-9 PM (15)
May 26, 9-10 PM (15)
May 26, 10-11 PM (35)
May 26, 11-12 AM (30)
May 27, 12-1 AM (16)
May 27, 1-2 AM (8)
May 27, 2-3 AM (9)
May 27, 3-4 AM (5)
May 27, 4-5 AM (32)
May 27, 5-6 AM (9)
May 27, 6-7 AM (49)
May 27, 7-8 AM (63)
May 27, 8-9 AM (37)
May 27, 9-10 AM (74)
May 27, 10-11 AM (83)
May 27, 11-12 PM (30)
May 27, 12-1 PM (50)
May 27, 1-2 PM (38)
May 27, 2-3 PM (53)
May 27, 3-4 PM (37)
May 27, 4-5 PM (6)
May 27, 5-6 PM (17)
May 27, 6-7 PM (18)
May 27, 7-8 PM (25)
May 27, 8-9 PM (14)
May 27, 9-10 PM (13)
May 27, 10-11 PM (29)
May 27, 11-12 AM (27)
May 28, 12-1 AM (9)
May 28, 1-2 AM (3)
May 28, 2-3 AM (5)
May 28, 3-4 AM (2)
May 28, 4-5 AM (8)
May 28, 5-6 AM (34)
May 28, 6-7 AM (26)
May 28, 7-8 AM (83)
May 28, 8-9 AM (33)
May 28, 9-10 AM (54)
May 28, 10-11 AM (50)
May 28, 11-12 PM (19)
May 28, 12-1 PM (45)
May 28, 1-2 PM (50)
May 28, 2-3 PM (23)
May 28, 3-4 PM (43)
May 28, 4-5 PM (86)
May 28, 5-6 PM (12)
May 28, 6-7 PM (31)
May 28, 7-8 PM (30)
May 28, 8-9 PM (3)
3,421 commits this week May 21, 2026 - May 28, 2026
Merge branch 'main' into cet/memory-telemetry
Resolves a parallel-implementation conflict in the LeiosStore retention
path: PR #913 landed on main with an untagged `VecDeque<LeiosNotification>`
and a `notification_evictable` predicate that inspects each notification's
referenced slots, while this branch had a slot-tagged deque.  Adopt
main's predicate-based design — it handles `VotesOffer` more accurately
than the conservative max-slot tag — and re-layer this branch's
additions on top:

- `notifications_bytes_estimate` field in stats (Serialize-derived
  through net-core's serde dep) with `notification_heap_bytes` only
  counting the variable `VotesOffer` payload, never the enum size.
- `tick_slot` advances retention by wall-clock without touching the
  version counter or watch channel — eviction is silent.
- `push_notification` filter drops late-arriving offers whose slots
  are already below cutoff, before they can sit at the back of the
  deque past the front-only pop_front loop.
- `notifications_after` clamps the cursor to the next-write index on
  overshoot so a consumer that gets ahead reconverges on the next
  inject.

All five new behaviour tests + a 10k-slot stress test exercise the
eviction guarantee end-to-end.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
chore(deps): bump golangci/golangci-lint-action from 9.2.0 to 9.2.1 (#451)
Bumps [golangci/golangci-lint-action](https://github.com/golangci/golangci-lint-action) from 9.2.0 to 9.2.1.
- [Release notes](https://github.com/golangci/golangci-lint-action/releases)
- [Commits](https://github.com/golangci/golangci-lint-action/compare/1e7e51e771db61008b38414a730f564565cf7c20...82606bf257cbaff209d206a39f5134f0cfbfd2ee)

---
updated-dependencies:
- dependency-name: golangci/golangci-lint-action
  dependency-version: 9.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
chore(deps): bump github.com/blinklabs-io/gouroboros (#450)
Bumps [github.com/blinklabs-io/gouroboros](https://github.com/blinklabs-io/gouroboros) from 0.170.1 to 0.171.0.
- [Release notes](https://github.com/blinklabs-io/gouroboros/releases)
- [Changelog](https://github.com/blinklabs-io/gouroboros/blob/main/RELEASE_NOTES.md)
- [Commits](https://github.com/blinklabs-io/gouroboros/compare/v0.170.1...v0.171.0)

---
updated-dependencies:
- dependency-name: github.com/blinklabs-io/gouroboros
  dependency-version: 0.171.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
CIP-186 | canonical-form port inclusion rule in Response signing
§Response signing canonical-form step 2 says
"Append <scheme>://<host_lowercased><path>" but does not specify
whether an explicit port is part of the canonical authority. Different
URL libraries disagree on default-port omission (RFC 3986 §3.2.3 says
default ports are equivalent but not identical). Pin: include port iff
it appears literally in the URL authority; default ports (443/80) MUST
NOT be emitted. Keeps canonical subject byte-deterministic.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
CIP-186 | pin reference Conway canonical CBOR encoders
The aux-data consistency rule requires BLAKE2b-256(canonical-cbor(...))
without pinning what produces canonical-cbor. CBOR canonicalisation
has multiple incompatible interpretations (deterministic-only vs
strictly-deterministic, definite-vs-indefinite length, sort orders for
non-text keys). Pin to cardano-ledger (Haskell), pallas-codec (Rust),
or cardano-multiplatform-lib (JS/Rust). Conformance against any is
sufficient.

Also clarify the contrast with tx_body extraction: tx_body is
byte-literal (commit binds to the ledger-validated source bytes), aux
data re-canonicalises (verifying a chain-recorded hash, not extracting
chain-validated bytes).

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
CIP-186 | tx body extraction: literal-bytes rule (do not re-canonicalise)
Spec mandates re-serialise under RFC 8949 §4.2 canonical encoding, but
this contradicts the chain's tx_id rule: chain's tx_id is BLAKE2b-256
over the source body bytes the ledger validated. If the wallet
re-canonicaliser disagrees with the source encoder (definite-vs-
indefinite length, non-text-key map sort order), wallet's commit
diverges from chain's tx_id and every downstream hash-pin breaks.

Pin to literal-bytes extraction. dApp MUST supply Conway-era canonical
CBOR (per RFC 8949 §4.2) so the extraction is well-defined; wallets
MAY but need not check source canonicity.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
CIP-186 | specify partialSign=true witness merge semantics
Spec inherits CIP-30:343-347 partialSign verbatim but does not say how
the dApp merges a wallet-returned partial witness_set into an
in-flight transaction_witness_set that already carries co-signer vkey
witnesses. Two readings: (a) replace the map's vkey_witnesses array
(silently drops prior co-signers), (b) array-append (correct). Pin to
(b) for vkey_witnesses (map key 0) and extend to native scripts (key 1),
Plutus scripts (keys 3/6/7), datums (key 4), redeemers (key 5). Add
SHOULD-reject on wallet returning non-empty entries for keys the dApp
did not authorise (anti-injection).

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
CIP-186 | promote result-json.commit echo verification to MUST
§Methods signTx response shows `result-json.commit` as "echo of request
commit" but does not state that the dApp MUST verify the echo. As a SHOULD
the wallet's pre-render commit check is sufficient; promoting to MUST
makes it the dApp-side complement and closes tx-body substitution as a
class across the full request/response loop. Defence-in-depth.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
CIP-186 | clarify errorCode=-4 envelope destination on redirect host mismatch
Spec says wallet MUST reject any subsequent request whose redirect host
differs from the connect-time persisted host, but does not say WHERE
the -4 rejection envelope is delivered. Two readings: (a) the offending
request's redirect host (defeats security — legitimate dApp never
observes the attack), (b) the connect-time persisted host (correct —
legitimate dApp can tear down the session). Pin to (b). Defence-in-depth
test updated to assert delivery target.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
CIP-186 | split key into request-key / response-key + enumerate response keys
§Response signing requires every response URL to carry `response`,
`walletKey`, `nonce`, `payload`, and `signature` parameters (and
`errorCode`/`errorMessage` on rejection envelopes), but the URI-format
ABNF only enumerates request-side keys. Under §Unknown-key policy
strict-reject, dApps parsing conformant wallet responses would reject
every response URL as carrying unknown keys.

Split `key` into `request-key` (wallet-bound) and `response-key`
(dApp-bound) productions. Update §Unknown-key policy to symmetrise the
strict-reject rule across both directions.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
CIP-186 | add aead to request-key ABNF production
The aead URL parameter is referenced in the §Methods AEAD envelope
section (`aead=xsalsa20poly1305`, `aead=chacha20poly1305-ietf`) for
suite negotiation at connect time, but the URI-format ABNF `key`
production omits it. Under §Unknown-key policy strict-reject, a
conforming wallet would reject a connect URL carrying the spec-defined
`aead` parameter with errorCode=-9 — the spec contradicts itself.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
CIP-186 | fix Appendix C.1 nonce example (36->32 chars, decodes to 24 bytes)
Spec mandates 24-byte nonce. Appendix C.1 example value
`AgICAgICAgICAgICAgICAgICAgICAgICAgIC` (36 chars) decodes to 27 bytes
under strict base64url-no-pad, violating the spec's own length rule.
Correct value for 24 bytes of 0x02 is `AgICAgICAgICAgICAgICAgICAgICAgIC`
(32 chars). Fix applied to both the constant listing and the request-URL
example. Caught independently by Yuti's parser conformance and the
conformance suite's base64url_001_valid_no_padding vector.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>