-
Notifications
You must be signed in to change notification settings - Fork 56
feat(platform-wallet): expose an invitation's prospective identity id #4332
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
93a759a
2efd08e
7aa22f4
5a1c7d5
2e680ae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -378,6 +378,39 @@ impl IdentityWallet { | |
| }) | ||
| } | ||
|
|
||
| /// The identity id this invitation WOULD create, without claiming it. | ||
| /// | ||
| /// Platform derives a created identity's id from the asset-lock outpoint, | ||
| /// so the id is knowable before the claim — and an identity already | ||
| /// existing under it is exactly the "this voucher has been spent" signal. | ||
| /// The claim itself is the only other way to learn that, which is why a | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Blocking: Identity existence does not detect every consumed invitation An identity under the derived outpoint ID is not an exact signal that the asset lock has been consumed. The supported invitation-reclaim path in source: ['codex'] |
||
| /// used invitation otherwise surfaces as a raw "asset lock … already | ||
| /// completely used" after the invitee has picked a username and entered | ||
| /// their PIN. | ||
| /// | ||
| /// Costs one funding-tx fetch: the outpoint is not in the link (the credit | ||
| /// output is selected by pk↔script match, not by index), so the tx has to | ||
| /// be refetched exactly as the claim does. Same wrong-network fail-fast as | ||
| /// [`Self::claim_invitation`], so a testnet link on mainnet reports the | ||
| /// network mismatch rather than a confusing fetch miss. | ||
| pub async fn invitation_prospective_identity_id( | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| &self, | ||
| invitation: &ParsedInvitation, | ||
| ) -> Result<Identifier, PlatformWalletError> { | ||
| if !wif_network_matches(invitation.voucher_key_network, self.sdk.network) { | ||
| return Err(PlatformWalletError::InvalidIdentityData(format!( | ||
| "invitation is for the {:?} network but this wallet is on {:?}", | ||
| invitation.voucher_key_network, self.sdk.network | ||
| ))); | ||
| } | ||
| let proof = self.reconstruct_asset_lock_proof(invitation).await?; | ||
| proof.create_identifier().map_err(|e| { | ||
| PlatformWalletError::InvalidIdentityData(format!( | ||
| "invitation asset lock proof yielded no identity id: {e}" | ||
| )) | ||
| }) | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| /// Claim a DashPay invitation: register a NEW identity for the invitee, | ||
| /// funded by the imported voucher. | ||
| /// | ||
|
|
@@ -814,6 +847,51 @@ mod tests { | |
| assert!(matches!(proof, AssetLockProof::Chain(_))); | ||
| } | ||
|
|
||
| /// The prospective identity id is derived from the *selected* credit | ||
| /// output's outpoint. Selection itself is pinned next to | ||
| /// `voucher_output_index`; what matters here is that the id follows it — a | ||
| /// voucher sitting behind a decoy must not yield the index-0 id, or the | ||
| /// "has this invitation been used?" check answers about a stranger's | ||
| /// identity and reports a perfectly good voucher as spent. | ||
| #[test] | ||
| fn prospective_id_follows_the_selected_credit_output() { | ||
| let key = voucher_secret(); | ||
| let decoy = SecretKey::from_slice(&[0x22u8; 32]).unwrap(); | ||
| let payload = AssetLockPayload { | ||
| version: 1, | ||
| credit_outputs: vec![ | ||
| TxOut { | ||
| value: 100_000, | ||
| script_pubkey: voucher_credit_script(&decoy), | ||
| }, | ||
| TxOut { | ||
| value: 100_000, | ||
| script_pubkey: voucher_credit_script(&key), | ||
| }, | ||
| ], | ||
| }; | ||
| let tx = Transaction { | ||
| version: 3, | ||
| lock_time: 0, | ||
| input: vec![], | ||
| output: vec![], | ||
| special_transaction_payload: Some(TransactionPayload::AssetLockPayloadType(payload)), | ||
| }; | ||
| let txid = tx.txid(); | ||
| let inv = parsed(key, txid.to_string(), None); | ||
|
|
||
| let proof = assemble_asset_lock_proof(tx, true, 100, &inv).unwrap(); | ||
| let id = proof.create_identifier().unwrap(); | ||
|
|
||
| let from_index_0 = | ||
| ChainAssetLockProof::new(100, OutPoint::new(txid, 0).into()).create_identifier(); | ||
| let from_index_1 = | ||
| ChainAssetLockProof::new(100, OutPoint::new(txid, 1).into()).create_identifier(); | ||
|
|
||
| assert_ne!(id, from_index_0, "id must not come from credit output 0"); | ||
| assert_eq!(id, from_index_1); | ||
| } | ||
|
|
||
| /// An islock that locks a DIFFERENT tx than the funding tx is rejected (the | ||
| /// txid-binding guard), so a link can't pair a valid islock with a foreign tx. | ||
| #[test] | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔴 Blocking: Definitive input errors are incorrectly documented as undetermined
Not every error from this function leaves the invitation's usability undetermined.
parse_invitation_uridefinitively rejects malformed links, whileinvitation_prospective_identity_iddeterministically rejects a wallet-network mismatch;claim_invitationapplies the same network guard, so the link cannot be claimed through the current wallet. Both currently reach Swift through the generic catch-all becauseInvalidIdentityDatamaps toErrorUnknown, while the documentation tells callers to ignore every error and proceed. That sends users toward a claim that is already known to fail. Expose malformed-input and wrong-network failures through stable, distinguishable FFI/Swift result codes and reserve the “proceed because status is inconclusive” behavior for funding-transaction lookup and transport failures.source: ['codex']