256KB TCP buffers (was 8KB) + burst 64 (was 1) in smolmix; an
IpMixStream::from_client constructor + best_ipr helper and reply-SURBs
10->4 in the ipr wrapper so a caller can back the tunnel with a
high-traffic-profile MixnetClient. No behavior change to the default
connect_new path used by the scoped exit.
The default rustls platform verifier needs the app JNI context, which a
standalone client process (Goblin's bundled SOCKS5 sidecar) lacks — it panics
on the first nym-api HTTPS call. Pin webpki_roots::TLS_SERVER_ROOTS on Android
per Nym's own troubleshooting docs.
* wip
* batch processing of forward packets
* tmp: additional metrics for remote node
* fixed incorrect prometheus metric registration
* unified runtime metrics
* unify mixnet client metrics
* packet forwarding cleanup
* add batching for emptying the delay queue
* cleanup client io loop
* feat(nym-node): reap idle mixnet connections (ingress + egress)
Close mixnet connections that sit with no traffic past a configurable idle period (mixnet.debug.connection_idle_timeout, default 5min, 0 disables) to bound lingering tokio tasks/sockets.
Ingress handle_stream is read-only, so a silently-gone peer (NAT drop, crash without FIN, half-open) never triggers FIN/RST and the task would block on .next() forever; a new idle select arm closes it (the post-loop replay flush still runs, so nothing is stranded). Egress run_io_loop gets the symmetric arm keyed on last_send; on close EvictOnDrop clears the cache entry and the next packet transparently reconnects.
Adds a cumulative nym_node_network_idle_closed_ingress_mixnet_connections counter; egress reaping is observed via the existing active-egress gauge plus an exit_reason=idle_timeout log.
* downgrade sysinfo
* refactor(nym-node): split PacketForwarder into router + delay-queue tasks
Split the single PacketForwarder task into two concurrently-scheduled tasks connected by a bounded handoff channel, so intake and delayed-release no longer block each other.
PacketRouter (router.rs) is the intake task: sole consumer of the ingress channel, it applies the routing filter and either forwards zero/already-elapsed-delay packets directly or hands delayed ones to the delay task. Its per-packet work is sub-µs, so new packets no longer wait behind delayed-release processing (collapses the ForwarderQueue tail).
DelayForwarder (delay.rs) owns the NonExhaustiveDelayQueue exclusively (it can't be shared by reference). Its run loop services BOTH branches on every wakeup - draining pending inserts first to bring the queue current, then flushing everything now due - so the biased select can't let releases and inserts starve each other, and a freshly-arrived-but-already-due packet releases in the same pass (marginally improving DelayQueueOverrun).
The mixnet client is shared as Arc<C>; handoff-channel overflow is dropped as an egress drop rather than blocking, keeping intake decoupled from release.
* feat(nym-node): bound egress flush with a write timeout
Cap how long a single egress batch flush may block on a congested peer socket (mixnet.debug.connection_write_timeout, default 500ms, 0 disables), so a slow peer can no longer back this connection's egress queue up into the multi-second range - the root of the EgressQueue and SocketWrite tails.
A single timeout is treated as transient congestion: the un-fed tail of the batch is abandoned but the connection is retained. This is sound because NoiseStream::poll_write encrypts and buffers each frame synchronously, so a cancelled flush leaves the noise transport nonce-consistent and a later flush resumes the byte stream in order - so a momentary spike costs no re-handshake. Only MAX_CONSECUTIVE_WRITE_TIMEOUTS (3) timeouts in a row, i.e. a persistently congested peer, tears the connection down (it reconnects on the next packet); a successful flush resets the counter.
Buffer-size tuning (maximum_connection_buffer_size) deliberately left for live data.
* revert PacketForwarder split in favour of a single task that clears both channels on wake
* First sweep packages + some minor tweaking
* Second sweep
* Regenerate lockfile + package.json mods
* Regenerate lockfile again
* Fix CI
* Fix CI again
* All building properly
* unblock
* Tweak examples
* Comments + readme + fix rotten unit test
* First pass docs
* Big pass
* Massive pass on new docs
* Update integrations.md w mobile
* Partial overhaul review
* new playground + big pass
* new fix lychee err
* IPR notice tweak
- Account loading now dedupes in-flight requests per network instead of sharing one global promise across all networks.
- Regression tests cover same-network reuse and cross-network isolation.
- Transaction success is now checked through a shared helper that validates hash, gas usage, and response payloads, not hash presence alone.
- Node settings error helper renamed to match its broader scope.
- Balance refresh now owns the loading flag so nested balance and vesting fetches do not race each other.
- Unbond modal removes the non-null assertion on compounded rewards.
- Unbond totals no longer default malformed amounts to zero; a warning appears when exact totals cannot be calculated.
- Hostname updates no longer treat an empty transaction hash as success.
- Sign-in navigation is gated on successful account load with regression tests.
- Account loading is deduplicated so sign-in no longer fires two concurrent network switches.
- Main window boot relies on the network effect only; rust state init no longer double-loads the account.
- NYM price cache clears on sign-out.
- Wallet no longer forces fullscreen on launch - auth and main windows keep the same size and position when switching.
- Sign-in and balance loading feel smoother, with less layout jump on the home screen.
- Saving a node hostname shows the transaction fee upfront, warns when funds are low, and surfaces clear errors on failure.
- Operator unbond confirmation shows pledge plus compounded operator rewards (delegator stake stays separate).
- Add `historical_node_identity` to `DelegationWithEverything` and populate via `lookup_historical_node_identity` in `delegate.rs` so search works after unbond.
- `searchDelegations` searches `historical_node_identity` and guards null/empty `node_identity` with optional chaining.
- Acceptance tests: historical identity search, bonded-unbonding vs synthetic branch semantics, empty-identity search safety.
- Fix linting
- In `delegate.rs`, add `delegation_node_identity` and `delegation_mixnode_is_unbonding` so missing node details emit `unbonded:{mix_id}` with `mixnode_is_unbonding: true` instead of an empty `node_identity`.
- Add `delegationListVisibility.ts` (`shouldHideDelegationFromList`, `filterVisibleDelegations`, `searchDelegations`) and wire `DelegationList.tsx` to the shared helpers.
- Update `useSortDelegations.tsx` to pin fully unbonded delegations to the top via `isFullyUnbondedDelegation`.
- In `UndelegateModal.tsx`, display `Node unbonded (mix N)` instead of raw `unbonded:{mix_id}` on the confirm screen.
- Add jest tests
- Add Rust unit test
InviteToFamily previously rejected any second invitation for a (family, node)
pair with PendingInvitationAlreadyExists, even once the existing invitation had
expired and was left inert in the pending map. Now a still-valid invitation still
blocks a duplicate, but an expired one is archived under the new terminal status
FamilyInvitationStatus::Expired and superseded by the fresh invitation.
Regenerated the contract JSON schema and updated the openspec capability.
cosmwasm-crypto 2.2.2 targets ed25519-zebra 4.0.3 (default-features = false) and
uses its `batch` module, but the lockfile had resolved to 4.2.0, which gates
`batch` behind the `alloc` feature. That left cosmwasm-crypto - and therefore the
whole contracts workspace - failing to compile. Pin back to 4.0.3 so it builds.
* Keep peer in wg table when updating psk
* Fix unit test
* update handle_update_peer_psk_request
---------
Co-authored-by: Jędrzej Stuczyński <jedrzej.stuczynski@gmail.com>
* First sweep packages + some minor tweaking
* Second sweep
* Regenerate lockfile + package.json mods
* Regenerate lockfile again
* Fix CI
* Fix CI again
* All building properly
* unblock
* Tweak examples
* Comments + readme + fix rotten unit test