Open
Conversation
Change _compileClaimOnP2SHMultiSigMiddle default sighashFlag from
SIGHASH_ALL to SIGHASH_ANYONECANPAY|SIGHASH_ALL so the receiver can
add their own EVR input for fees when claiming channel payments.
Also fix kwarg bug: {sighashFlag: sighashFlag} used the int value as
dict key instead of the string 'sighashFlag'.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SIGHASH_SINGLE locks only the output at the signed input's index (sender's change), while ANYONECANPAY allows additional inputs. Together they let the receiver add both fee inputs and fee change outputs when claiming. Updated _compileClaimOnP2SHMultiSigMiddle default, _createPartialOriginator- Simple, _createPartialCompleterSimple, and related docstrings.
_createPartialOriginatorSimple now splits the first output into multiple pieces if len(txins) > len(txouts), guaranteeing every input index has a corresponding output (required by SIGHASH_SINGLE to avoid degenerate hash). Also update ravencoin wallet to use SIGHASH_SINGLE|ANYONECANPAY (matching evrmore) and import SIGHASH_SINGLE.
_createPartialOriginatorSimple and _createPartialCompleterSimple are for Mundo transactions which only need ANYONECANPAY (add inputs, not outputs). SIGHASH_SINGLE is only for P2SH channel signing (_compileClaimOnP2SH- MultiSigMiddle) which was already set correctly.
New kind 34604 (KIND_CHANNEL_COMMITMENT) — parameterized replaceable event keyed by p2sh_address, tagged with receiver pubkey for push delivery. models.py: - ChannelCommitment dataclass (mirrors Mantra's Commitment object) - InboundCommitment wrapper - KIND_CHANNEL_COMMITMENT = 34604 constant client.py: - publish_commitment() — buyer posts partial tx (replaces POST /channel/commitment) - get_commitment() — fetch latest for a channel (replaces GET /channel/commitment/:addr) - remove_commitment() — publish tombstone after claim (replaces DELETE /channel/commitment/:addr) - commitments() — async iterator, push delivery to seller (replaces polling GET) - _handle_commitment_event() — internal handler, filters to own pubkey, drops tombstones - KIND_CHANNEL_COMMITMENT added to subscription filter and event router - _commitment_queue and commitments_sent/received stats added
- ChannelOpen dataclass + InboundChannelOpen wrapper in models.py - KIND_CHANNEL_OPEN = 34605 (parameterized replaceable, d=p2sh_address) - SatoriNostr.publish_channel_open() — sender announces channel to receiver - SatoriNostr.channel_opens() — async iterator for incoming announcements - _handle_channel_open_event() routes kind 34605 to _channel_open_queue - 34605 added to subscription filter so receivers get push delivery
- Add stream_name field to ChannelCommitment (in JSON body + as Nostr tag for relay filtering) - publish_commitment: emit ["stream", stream_name] tag when present - record_subscription: preserve last_paid_seq and subscribed_at on re-registration Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add kind 34607 constant and CompetitionAnnouncement dataclass with full serialization, d_tag(), and close() methods. 8 tests, all green. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add three competition methods to SatoriNostr client: - announce_competition: publishes KIND_34607 with d-tag and s/p tags - close_competition: re-publishes with active=False - discover_competitions: fetches, deduplicates by d-tag (latest wins), filters active_only client-side, supports stream_name tag filter 8 tests, all green. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add PredictionSubmission and InboundPrediction dataclasses (kind 34608) - Add submit_prediction() encrypted DM to host, incoming_predictions() async iterator - Fix discover_competitions() dedup to use content timestamp (not Nostr created_at) so close() (which bumps timestamp+1) always wins even within the same second - Add 26 tests covering prediction models and client round-trip Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The host needs the predictor's EVRmore wallet pubkey to open a payment channel and pay them. Previously it wasn't transmitted at all, forcing the neuron to search subscriptions for the predictor's nostr pubkey as if they were a stream producer — which never works because predictors aren't producers. Now it rides along inside the encrypted DM itself (still private to the host) and the host reads it back off the competition_predictions row when scoring fires.
publish_commitment now requires receiver_nostr_pubkey (32-byte x-only Nostr pubkey) instead of using commitment.receiver_pubkey (33-byte EVR wallet pubkey) for the Nostr p-tag. The old value was rejected by relays as an invalid fixed-size tag. _handle_commitment_event no longer filters by comparing wallet pubkey to Nostr pubkey (which always failed). Commitments are queued unconditionally; the consumer filters by p2sh_address DB lookup, matching the channel_open pattern.
Was 0, causing roundSatsDownToDivisibility to zero out any amount under 100M sats. With div=0, payment channel partial txs omitted the receiver output entirely — Alice got 0 SATORI despite being owed the cumulative.
added 2 commits
April 13, 2026 23:36
Add AccessRequest/InboundAccessRequest models, KIND_ACCESS_REQUEST (34609), approval_required flag on DatastreamMetadata. Client gains request_access(), incoming_access_requests(), and _handle_access_request_event() for NIP-04 encrypted access request DMs between subscribers and producers.
incoming_predictions() and incoming_access_requests() used `return` on asyncio.TimeoutError instead of `continue`, causing the async iterator to exit after 1 second of inactivity. This meant prediction listeners died immediately after startup — hosts never received prediction DMs in real-time. All other async iterators (observations, payments, channels, settlements, tombstones) correctly use `continue`.
New subscribers to paid streams had last_paid_seq=None, so the provider never sent them an observation, and without receiving an observation the subscriber never triggered payment — deadlock. Fix: when free_sample is True (default), send one free encrypted observation to new subscribers. After delivery, set last_paid_seq to the current seq so they must pay for subsequent observations. The subscriber's automatic payment on receipt then bootstraps the normal paid cycle. Adds free_sample field to DatastreamMetadata (default True). Providers can set it to False to require upfront payment instead.
Pin the agreed price at commitment time so receiver uses the same price the sender committed to, preventing mismatch on mid-cycle price edits.
Provider removes subscriber from in-memory _subscribers dict when receiving an unsubscribe announcement, stopping encrypted observations.
Drop non-tombstone commitment events whose p tag doesn't match our pubkey. Eliminates 3s retry + DB lookup for stale third-party commitments on reconnect.
No longer needed — receiver uses its own live price, sender refreshes price via relay discovery during reconcile.
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.