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

SmartContract: restrict the number of allowed notifications #3548

Open
wants to merge 26 commits into
base: master
Choose a base branch
from

Conversation

AnnaShaleva
Copy link
Member

Description

The problem is described in nspcc-dev/neo-go#3490. In short words, an arbitrary number of smart contract notifications is allowed (up to VM's GasLimit and MaxBlockSystemFee, but it's huge), which results in a possibility to DoS the node. 10K of large notifications emitted in a single transaction result in block acceptance delays for both Go and C# nodes. 50K of large notifications may result in the node failure. I did these tests on privnet, you may find the results in nspcc-dev/neo-go#3490 (comment). Please, don't try to DoS mainnet/testnet using this vulnerability.

Port the solution from nspcc-dev/neo-go#3640, but an alternative solution is described in nspcc-dev/neo-go#3640 (comment) and in nspcc-dev/neo-go#3490 (comment). MaxNotificationsCount constraint is chosen based on the Mainnet statistics of the number of notifications per every transaction, ref. nspcc-dev/neo-go#3490 (comment).

This PR is a subject of discussion, hence please, share your thoughts on the described problem and proposed solution. Once we agree on the solution, I'll add unit-tests to this PR.

Type of change

  • Breaking change (fix or feature that would cause existing functionality to not work as expected)

How Has This Been Tested?

  • Unit-tests should be added once we agree on solution.

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

Jim8y and others added 8 commits August 8, 2024 00:24
* Add entries to Designation event

* Change to HF_Echidna

* Add UT

* Add count
* add base64url

* active in

* update placehold hf height

* fix hf issue and move methods to proper place.

* fix test

* use identifymodel instead.
* Add entries to Designation event

* Change to HF_Echidna

* Add UT

* Add count
* add base64url

* active in

* update placehold hf height

* fix hf issue and move methods to proper place.

* fix test

* use identifymodel instead.
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
Fix the problem described in
nspcc-dev/neo-go#3490. Port the solution from
nspcc-dev/neo-go#3640.

MaxNotificationsCount constraint is chosen based on the Mainnet
statistics of the number of notifications per every transaction, ref.
nspcc-dev/neo-go#3490 (comment).

Signed-off-by: Anna Shaleva <[email protected]>
Signed-off-by: Anna Shaleva <[email protected]>
@cschuchardt88
Copy link
Member

This needs to be in VM limit class.

@@ -78,7 +78,7 @@ private void DesignateAsRole(ApplicationEngine engine, Role role, ECPoint[] node
list.AddRange(nodes);
list.Sort();
engine.SnapshotCache.Add(key, new StorageItem(list));

Copy link
Member

Choose a reason for hiding this comment

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

revert

Copy link
Member Author

@AnnaShaleva AnnaShaleva Oct 23, 2024

Choose a reason for hiding this comment

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

Formatting job is failing without this change.

@AnnaShaleva
Copy link
Member Author

This needs to be in VM limit class.

Strictly speaking, it's not a VM limit. Notifications are not a part of VM, they are a part of execution engine.

// Restrict the number of notifications for Application executions. Do not check
// persisting triggers to avoid native persist failure. Do not check verification
// trigger since verification context is loaded with ReadOnly flag.
if (IsHardforkEnabled(Hardfork.HF_Echidna) && Trigger == TriggerType.Application && notifications.Count == MaxNotificationCount)
Copy link
Member

Choose a reason for hiding this comment

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

Looks good to me, we just need to ensure .Count is correct calculated at this step.

Copy link
Member

@cschuchardt88 cschuchardt88 Oct 23, 2024

Choose a reason for hiding this comment

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

Is trigger really needed? Limits shouldn't have a trigger.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, it's needed, because we can't allow OnPersist and PostPersist failures (imagine that in future MaxNotificationCount may be reduced to some lower value). And for Verification trigger this check is useless by design, no notifications are possible with this trigger.

Copy link
Member Author

Choose a reason for hiding this comment

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

@cschuchardt88
Copy link
Member

cschuchardt88 commented Oct 23, 2024

This needs to be in VM limit class.

Strictly speaking, it's not a VM limit. Notifications are not a part of VM, they are a part of execution engine.

All the same thing. Class is called ExecutionEngineLimits in Neo.VM namespace. How to use engine.Limit.MaxNotification

@Jim8y
Copy link
Contributor

Jim8y commented Oct 24, 2024

instead of limiting number of notifactions, i prefer to make the price related to the notifaction size. From @AnnaShaleva 's excellent benchmark, i think size * number is the real reason. Cause i think its a normal practice contract may need to send a lof of notifactions, but definately abnormal to send large notifactions.

@AnnaShaleva
Copy link
Member Author

AnnaShaleva commented Oct 24, 2024

i think size * number is the real reason

Exactly, as described in nspcc-dev/neo-go#3490 (comment).

i prefer to make the price related to the notifaction size.

Yes, it's an alternative solution proposed in nspcc-dev/neo-go#3490 (comment). But we need to discuss it because even with extremely expensive notifications there's a chance that CNs will be killed by a single transaction. Yes, the user will have to pay for it, but CNs may not be able to process this transaction. Also, large number of notifications is harmful for both C# and Go RPC servers.

So to me, the restriction of the overall notifications number is required, but at the same time it can be combined with dynamic price solution.

@shargon
Copy link
Member

shargon commented Dec 20, 2024

Any feedback or merge?

nan01ab
nan01ab previously approved these changes Dec 24, 2024
@Jim8y
Copy link
Contributor

Jim8y commented Dec 31, 2024

Any feedback or merge?

As is discussed in our previous meeting, this should wait for #3644

Base automatically changed from HF_Echidna to master January 23, 2025 09:52
@NGDAdmin NGDAdmin dismissed stale reviews from nan01ab and shargon January 23, 2025 09:52

The base branch was changed.

@@ -40,7 +40,8 @@
"HF_Aspidochelone": 3000000,
"HF_Basilisk": 4500000,
"HF_Cockatrice": 5800000,
"HF_Domovoi": 5800000
"HF_Domovoi": 5800000,
"HF_Echidna": 5800001
Copy link
Member

Choose a reason for hiding this comment

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

@AnnaShaleva Should be removed from config

Copy link
Member

Choose a reason for hiding this comment

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

It comes from the branch change

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

Will update.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed.

@shargon
Copy link
Member

shargon commented Mar 3, 2025

This should be included in 3.8

@shargon shargon added the Bug Used to tag confirmed bugs label Mar 3, 2025
@AnnaShaleva
Copy link
Member Author

Previously we’ve agreed that this solution is less preferable than #3600. @roman-khimov do you think we need to merge it?

@shargon
Copy link
Member

shargon commented Mar 3, 2025

Previously we’ve agreed that this solution is less preferable than #3600. @roman-khimov do you think we need to merge it?

Why not complementary?

@roman-khimov
Copy link
Contributor

The theory is that if we're to have #3552 done with MaxBlockSystemFee of like 20 and then have ExecutionFeeFactor of 30 again then 20 GAS is ~2034 notifications and we're fine as is. The problem is that we neither have a low MaxBlockSystemFee value nor we have a high ExecutionFeeFactor (and can't have it till #3600, which will happen no one knows when). Given the severity of the issue at the same time, I'm OK with some hard limit for 3.8/Echidna. At least it's simple and effective.

@AnnaShaleva AnnaShaleva force-pushed the restrict-notifications-count branch 2 times, most recently from 8dd5b25 to 7345ac4 Compare March 3, 2025 13:32
@AnnaShaleva AnnaShaleva force-pushed the restrict-notifications-count branch from 7345ac4 to c309f63 Compare March 3, 2025 13:32
@AnnaShaleva
Copy link
Member Author

Good, updated. Then let's consider merging this PR in 3.8.

I'm also voting for the merge since I agree that this solution is better than nothing. Later, when we have lower MaxBlockSystemFee and flexible opcode prices, we may revert notifications number constraint (in some next hardfork).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Used to tag confirmed bugs Discussion Initial issue state - proposed but not yet accepted Hardfork
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants