fix(receipts): fix #58 by binding receipts to payload commitments#315
Merged
kryputh merged 1 commit intoJun 17, 2026
Merged
Conversation
4 tasks
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.
Closes #58
PR Description
This PR fixes issue #58 by binding delivery receipts to encrypted payload commitments in the Soroban receipts contract.
Before this change, a receipt was keyed by
message_idand stored sender, recipient, delivery time, and optional read time. That proved a message ID had a receipt, but it did not prove which encrypted payload the receipt referred to.The delivery flow now records the message ID, payload hash, protocol version, sender, recipient, delivery timestamp, and optional read timestamp in the receipt state. The sender authorizes the delivery record with those commitment fields as part of the contract call. Once a receipt exists for a message ID, the contract rejects any attempt to reuse that ID with a different payload hash, protocol version, sender, or recipient. Reusing the same commitment also fails, so receipt state cannot be overwritten.
The read flow remains recipient-controlled.
read(message_id)loads the existing receipt, requires authorization from the stored recipient, and only addsread_at; it does not change the payload commitment. A third party can callget(message_id)to verify receipt consistency against the known payload hash without seeing message content.Changes Made
contracts/soroban/receipts/src/lib.rsby addingmessage_id,payload_hash, andprotocol_versiontoReceipt.contracts/soroban/receipts/src/lib.rsby changingdeliveredto accept and persist the payload commitment fields.contracts/soroban/receipts/src/lib.rsby rejecting duplicate IDs with changed commitments usingCommitmentMismatch.contracts/soroban/receipts/src/lib.rsby preserving recipient-only control overread_at.contracts/soroban/receipts/src/lib.rsby adding typed receipt events for delivery and read transitions.contracts/soroban/receipts/src/lib.rsby adding tests for commitment persistence, duplicate handling, sender delivery auth, and recipient read auth.contracts/soroban/receipts/README.mdto document the new receipt interface and immutability behavior.