HIP-150: accept data transfer multiplier tickets in ingest - #1242
Merged
Conversation
Adds submit_data_transfer_multiplier_ticket. A ticket grants one hotspot a multiplier on the data credits derived from its rewardable bytes. Ingest verifies the signer and the timestamp, then persists the ticket verbatim. It does not parse the multiplier — the packet verifier decides whether one is acceptable and records that verdict in a verified report, so a rejection stays as auditable as a grant. Notes: - Ticket signers get their own allow-list and is_ticket_signer() check, rather than a NetworkKeyRole variant: that enum belongs to the decommissioned mobile-config. A carrier key must not be able to grant a multiplier. - The list may be empty and defaults to empty, since the release ships before any ticket can be issued. Empty rejects every ticket and warns at startup. - Tickets older than data_transfer_multiplier_ticket_max_age (default 10 minutes) or dated in the future are refused. Signatures never expire, so without this a captured ticket is replayable forever. - valid_data_transfer_session gained a multiplier field with the proto bump; set to None here, so behaviour is unchanged. Cargo.toml patches helium-proto to proto's mj/hip-150 (helium/proto#483). REVERT BEFORE MERGING mj/hip-150 TO main.
bbalser
approved these changes
Aug 26, 2026
A client does not share a clock with ingest, so a ticket signed at what the client believes is "now" can arrive stamped slightly ahead of us. Those were refused as post-dated, which is a confusing failure for an honest client with a drifting clock. Tickets up to MAX_CLOCK_DRIFT (1 minute) in the future are now treated as current. Beyond that they are still refused: post-dating must not buy an attacker a longer replay window than an honest client gets, and a ticket inside the allowance still ages out of the freshness window at the same rate, it just starts a minute earlier. The allowance is a shared constant in file-store-oracles rather than a setting in each service. The packet verifier checks freshness too, and measures a ticket's age against the timestamp ingest stamped on it — so if ingest tolerated drift the verifier did not, every ticket ingest accepted from a fast client would be refused downstream. One value, not two that can be configured apart.
michaeldjeffrey
added a commit
that referenced
this pull request
Aug 28, 2026
* HIP-150: accept data transfer multiplier tickets in ingest Adds submit_data_transfer_multiplier_ticket. A ticket grants one hotspot a multiplier on the data credits derived from its rewardable bytes. Ingest verifies the signer and the timestamp, then persists the ticket verbatim. It does not parse the multiplier — the packet verifier decides whether one is acceptable and records that verdict in a verified report, so a rejection stays as auditable as a grant. Notes: - Ticket signers get their own allow-list and is_ticket_signer() check, rather than a NetworkKeyRole variant: that enum belongs to the decommissioned mobile-config. A carrier key must not be able to grant a multiplier. - The list may be empty and defaults to empty, since the release ships before any ticket can be issued. Empty rejects every ticket and warns at startup. - Tickets older than data_transfer_multiplier_ticket_max_age (default 10 minutes) or dated in the future are refused. Signatures never expire, so without this a captured ticket is replayable forever. - valid_data_transfer_session gained a multiplier field with the proto bump; set to None here, so behaviour is unchanged. Cargo.toml patches helium-proto to proto's mj/hip-150 (helium/proto#483). REVERT BEFORE MERGING mj/hip-150 TO main. * HIP-150: tolerate client clock drift on multiplier tickets A client does not share a clock with ingest, so a ticket signed at what the client believes is "now" can arrive stamped slightly ahead of us. Those were refused as post-dated, which is a confusing failure for an honest client with a drifting clock. Tickets up to MAX_CLOCK_DRIFT (1 minute) in the future are now treated as current. Beyond that they are still refused: post-dating must not buy an attacker a longer replay window than an honest client gets, and a ticket inside the allowance still ages out of the freshness window at the same rate, it just starts a minute earlier. The allowance is a shared constant in file-store-oracles rather than a setting in each service. The packet verifier checks freshness too, and measures a ticket's age against the timestamp ingest stamped on it — so if ingest tolerated drift the verifier did not, every ticket ingest accepted from a fast client would be refused downstream. One value, not two that can be configured apart.
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.
Adds
submit_data_transfer_multiplier_ticket. A ticket grants one hotspot a multiplier on the data credits derived from its rewardable bytes.Ingest verifies the signer and the timestamp, then persists the ticket verbatim. It does not parse the multiplier — the packet verifier decides whether one is acceptable and records that verdict in a verified report, so a rejection stays as auditable as a grant.
Notes:
Cargo.toml patches helium-proto to proto's mj/hip-150 (helium/proto#483). REVERT BEFORE MERGING mj/hip-150 TO main.