Skip to content
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

feat(cycles-minting): Cycles Minting canister refunds automatically. #3484

Merged
merged 29 commits into from
Jan 24, 2025

Conversation

daniel-wong-dfinity-org
Copy link
Contributor

@daniel-wong-dfinity-org daniel-wong-dfinity-org commented Jan 16, 2025

This happens when the memo (or icrc1_memo) in an ICP transfer is not one of the special values that CMC recognizes as signaling the purpose of the transfer.

This behavior gets triggered when one of the notify_* methods gets called.

The new behavior is not actually active yet. To turn it on, we simply need to set IS_AUTOMATIC_REFUND_ENABLED to true. I have run the tests with this set to true locally, and they pass.

Motivation

Avoids ICP getting stuck, which can result from people making mistakes when sending ICP to the CMC.

Implementation Overview

Added issue_automatic_refund_if_memo_not_offerred. As indicated by the name, this is the heart of the implementation of this new functionality. This is called from fetch_transaction. The call is guarded behind the aforementioned IS_AUTOMATIC_REFUND_ENABLED flag.

Added MEANINGFUL_MEMOS constant. This is used to detect when automatic refund should be performed.

Minor Changes

Added AutomaticallyRefunded to NotificationStatus. This ensures that we do NOT duplicate refunds.

Changed one parameter of fetch_transaction from AccountIdentifier to Subaccount, because you cannot go "backwards" from AccountIdentifier to Subaccount.

Factored out the memo + icrc1_memo unifying code which used to live in transaction_has_expected_memo. Now, that code lives in a new get_u64_memo function.

Future Work

Added a couple of other helpers. One is set_block_status_to_processing. This could be used to reduce code duplication in notify_* methods, but such refactoring is left to future PRs.

References

This will be enabled by another PR.

We promised to do this in this forum post.

Closes NNS1-3573.

The other feature that we promised in that thread (use icrc1_memo) was implemented in an earlier PR.

@github-actions github-actions bot added the feat label Jan 16, 2025
@daniel-wong-dfinity-org daniel-wong-dfinity-org force-pushed the cmc-automatic-refund-daniel-wong branch 7 times, most recently from f50d3b7 to 3be81cc Compare January 20, 2025 20:11
@daniel-wong-dfinity-org daniel-wong-dfinity-org marked this pull request as ready for review January 20, 2025 20:12
@daniel-wong-dfinity-org daniel-wong-dfinity-org requested a review from a team as a code owner January 20, 2025 20:12
Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this pull request affects the behavior of any canister owned by
the Governance team, remember to update the corresponding
unreleased_changes.md file(s).

To acknowldge this reminder (and unblock the PR), dismiss this
code review by going to the bottom of the pull request page, and
supply one of the following reasons:

  1. Done.

  2. No canister behavior changes.

@daniel-wong-dfinity-org daniel-wong-dfinity-org dismissed github-actions[bot]’s stale review January 20, 2025 20:14

New functionality is disabled via a flag. It will be enabled once security team reviews.

rs/nns/cmc/src/lib.rs Outdated Show resolved Hide resolved
rs/nns/cmc/src/main.rs Outdated Show resolved Hide resolved
rs/nns/cmc/src/main.rs Outdated Show resolved Hide resolved
rs/nns/cmc/src/main.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@max-dfinity max-dfinity left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, other than small changes about commentary in code comments

@daniel-wong-dfinity-org daniel-wong-dfinity-org force-pushed the cmc-automatic-refund-daniel-wong branch from 47e606b to f6a9aa6 Compare January 24, 2025 19:14
@daniel-wong-dfinity-org daniel-wong-dfinity-org added this pull request to the merge queue Jan 24, 2025
Merged via the queue into master with commit 03393bc Jan 24, 2025
27 checks passed
@daniel-wong-dfinity-org daniel-wong-dfinity-org deleted the cmc-automatic-refund-daniel-wong branch January 24, 2025 19:42
Copy link
Contributor

@andrew-lee-work andrew-lee-work left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Comments:

  • It looks like you have carefully ensured that a block can be processed successfully at most once. Since processing a block only refunds a block XOR mints cycles for the block, there is no way to double issue_automatic_refund or issue_automatic_refund AND mint cycles. (Where issue_automatic_refund refers to the new refund path in this PR, as opposed to refund paths that happen when there is an error during minting.)
  • I’d like to note that there is some brittleness to the current design that is causing extra complexity in bookkeeping. This brittleness is not caused by the current PR, but it creates complexity for the current PR to handle — namely the current PR must ensure minting and issue_automatic_refund do not overlap. The issue is that the CMC deals with recent blocks and not the total ICP in a subaccount. During minting of cycles, the CMC mints first and burns later. This means that a panic could allow ICP to be left in the subaccount after minting. (The block would be stuck in “Processing”.) There could also be unrefunded ICP that gets stuck in the subaccount. Whereas, if the CMC burned first and minted second, the CMC could let the ledger ensure no double spending, and the bookkeeping and refunding logic in the CMC could be simplified.
  • The temporary buffer containing block statuses creates further brittleness. A block that is being processed for refunding could error out, and then become too old for further processing. Blocks could be stuck in processing and be forgotten. The condition for being too old must also be adjusted manually because it does not directly limit the size of the buffer. If there are too many blocks in a short time the buffer could still grow too large.

}

// There is no (known) way to reach this case, since we already
// verified that memo is in MEANINGFUL_MEMOS.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you mean "since we already verified that memo is NOT in MEANINGFUL_MEMOS".

.inspect_err(|_err| {
// This allows the user to retry.
clear_block_processing_status(incoming_block_index);
})?;
Copy link
Contributor

@andrew-lee-work andrew-lee-work Jan 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just a comment on the behavior. NCR.

If there is a panic after calling the ledger to refund ICP, the block will be stuck in processing. This would need to be manually resolved. Manual resolution would entail checking that the memo indicates the block should be refunded, and looking for a refund on the ledger to see if a new refund should be sent.

github-merge-queue bot pushed a commit that referenced this pull request Jan 27, 2025
This is per [feedback] from Andrew Lee.

[feedback]:
#3484 (comment)

---------

Co-authored-by: Arshavir Ter-Gabrielyan <[email protected]>
github-merge-queue bot pushed a commit that referenced this pull request Jan 27, 2025
Implementation of this feature was done in an [earlier PR][impl], but
was left disabled. For details of this feature, see the description of
the aforementioned PR.

[impl]: #3484

Per the reminder bot, an entry has been added to unreleased_changes.md.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants