-
Notifications
You must be signed in to change notification settings - Fork 27
Fix multisig partial spends #661
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 all commits
04d343e
b2fefde
45dba91
fad04cc
67d1115
7ca9a7e
c0ea517
5f1195c
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 |
|---|---|---|
|
|
@@ -85,8 +85,12 @@ module ShieldedTreasury { | |
| * @description Sends shielded tokens from the treasury. | ||
| * | ||
| * Looks up the stored coin by color, verifies sufficient value, | ||
| * and executes the shielded send. If the send produces change, | ||
| * it is sent back to the contract via `sendImmediateShielded`. | ||
| * and executes the shielded send. `sendShielded` already routes any | ||
| * change back to this contract as a self-owned output. Unlike the | ||
| * stateless variant, this treasury RETAINS the change: it is recorded in | ||
| * the UTXO map for the next spend. The returned `result.change` therefore | ||
| * belongs to the treasury and must not be re-spent by the caller (doing | ||
| * so would double-spend the recorded coin). | ||
| * | ||
| * @notice Access control is NOT enforced here. | ||
| * The consuming contract must gate this behind its own | ||
|
|
@@ -119,14 +123,13 @@ module ShieldedTreasury { | |
|
|
||
| const result = sendShielded(coin, disclose(recipient), disclose(amount)); | ||
|
|
||
| // `sendShielded` spends the stored coin (revealing its nullifier) and, | ||
| // when there is change, emits it as a fresh output owned by this | ||
| // contract. That change coin is already spendable. Do NOT re-spend it | ||
| // with `sendImmediateShielded`, which would reveal its nullifier in this | ||
| // same transaction and leave the recorded coin permanently double-spent. | ||
| if (disclose(result.change.is_some)) { | ||
| const changeCoin = result.change.value; | ||
| sendImmediateShielded( | ||
| changeCoin, | ||
| Utils_selfAsRecipient(), | ||
| changeCoin.value | ||
| ); | ||
| _coins.insertCoin(disclose(color), changeCoin, Utils_selfAsRecipient()); | ||
| _coins.insertCoin(disclose(color), result.change.value, Utils_selfAsRecipient()); | ||
|
Member
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. ❔ question (non-blocking): This stores sent by claude (dev3-midnight-basic-review)
Contributor
Author
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. Confirmed on the local node...if preferred, I can create a new repo or something with the scripts to run so it's verifiable and not "just trust me, bro"
Member
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. No need we just need to push the live harness for running tests on local node. |
||
| } else { | ||
| _coins.remove(disclose(color)); | ||
| } | ||
|
|
||
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.
🔵 followup (non-blocking): This guidance ("spend it onward to a different recipient … via
sendImmediateShielded") carries no recipient-type caveat, but for this module routing change to aContractAddressrepublishes a contract address in cleartext — the exact leak the module forbids forparent. Add: onward change routing here must stay to aZswapCoinPublicKey, same reason as the parent. (The generic treasuries don't carry the parent-privacy guarantee, so their identical wording is fine.)sent by claude (dev3-midnight-basic-review)