-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Improved scheme for Conflicts attribute storing and pricing #2913
Conversation
This commit is a part of neo-project#2907: it implements conflict records storage scheme discribed in neo-project#2907 (comment). The short scheme description: Do not store the list of conflicting signers in the Ledger's conflict record value. Instead, put each conflicting signer in the conflict record key so that the reculting key is: {Prefix_Transaction, <conflict hash>, <signer>}, and the value is {<block index>}. As an optimisation, for each conflict record store the dummy stub where the key is {Prefix_Transaction, <conflict hash>} and the value is {<block index>}. This optimisation allows to reduce DB read requests during newly-pooled transaction verification for those transactions that do not have any on-chained conflicts. Also, IsTraceableBlock check is added for on-chain conflicts verification. It is needed to avoid situations when untraceable on-chained conflict affects the newly-pooled transaction verification. Signed-off-by: Anna Shaleva <[email protected]>
Malicious_OnChain_Conflict was constructed incorrectly (see the comment in the end of the test) and was replaced by the proper TestMaliciousOnChainConflict test in UT_Blockchain.cs way back ago in neo-project@0c06c91. Signed-off-by: Anna Shaleva <[email protected]>
This commit implements Conflicts attribute policy described in neo-project#2907 (comment). Signed-off-by: Anna Shaleva <[email protected]>
d9e90c6
to
cba97f1
Compare
// Remove possible previously saved malicious conflict records for the transaction (if any). | ||
foreach (var (key, _) in engine.Snapshot.Find(CreateStorageKey(Prefix_Transaction).Add(tx.Transaction.Hash).ToArray())) | ||
engine.Snapshot.Delete(key); |
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.
The discussion started by @roman-khimov and ported from AnnaShaleva@deb1470#r127677374:
Not sure about this. It's garbage collection effectively. Can slow down tx processing.
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.
That's true and everything will work without this line. This garbage collection may be safely run in a separate routine (or as a separate task), we don't need to include it into OnPersist
, but I'm not sure what's the right place for it.
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.
I'd say that's a job for RemoveUntraceableBlocks
option (C# node doesn't have it, but it can be implemented). This storage space is paid for at the same time with the new setting, so keeping these entries is OK.
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.
I think that we should have a maximum allowed signers too
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.
Having maximum allowed signers will bring us to the same problem that was described in #2907 (comment). So any kind of such restriction leads to this possible attack when malicious conflicts prevent some real (and valid) conflict from entering the chain.
That's why we build this new solution in such way so that all conflicts data are properly paid. And it's even harder to spam the DB with Conflicts-related data than via contract storage.
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.
it's not necessary to care about those "dust" records and they don't really hurt.
correct attr fee introduced by @shargon is able to avoid the abuse and restrict the storage cost.
an uncontrollable O(n) procedure here can be avoided
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.
an uncontrollable O(n) procedure here can be avoided
I agree, let's then keep these garbage records. Implemented in a separate commit, see the 024a82a.
Upgrade neo-modules to use neo-project/neo#2913. Signed-off-by: Anna Shaleva <[email protected]>
Upgrade neo-modules to use neo-project/neo#2913. Signed-off-by: Anna Shaleva <[email protected]>
We genuinely appreciate @shargon 's enthusiasm for NEO and the dedicated efforts he has put forth. He swiftly opened the #2908 and consistently enhanced the solution based on everyone's input. Occasionally, focusing on surface-level issues without delving into their root causes and relying on habitual thinking for quick solutions can impede genuine problem-solving. I admire this PR for avoiding the use of limitations to resolve the issue. |
Implement the neo-project/neo#2907 (comment) and port a part of neo-project/neo#2913.
Implement the neo-project/neo#2907 (comment) and port a part of neo-project/neo#2913. Signed-off-by: Anna Shaleva <[email protected]>
Implement the neo-project/neo#2907 (comment) and port a part of neo-project/neo#2913. Signed-off-by: Anna Shaleva <[email protected]>
Implement the neo-project/neo#2907 (comment) and port a part of neo-project/neo#2913. Signed-off-by: Anna Shaleva <[email protected]>
Implement the neo-project/neo#2907 (comment) and port a part of neo-project/neo#2913. Signed-off-by: Anna Shaleva <[email protected]>
Implement the neo-project/neo#2907 (comment) and port a part of neo-project/neo#2913. Signed-off-by: Anna Shaleva <[email protected]>
I'll rebase this branch onto current master in a few hours. |
…conflicts Signed-off-by: Anna Shaleva <[email protected]>
ConflictsFee logic was replaced by the generic attribute fee mechanism implemented in neo-project#2916. Signed-off-by: Anna Shaleva <[email protected]>
Current master is fetched, corresponding adjustments are done wrt #2916, ready for review. |
It's OK to keep them and save O(n) operations during OnPersist. The storage taken by these malicious conflict records is properly paid anyway. See the discussion under neo-project#2913 (comment). Signed-off-by: Anna Shaleva <[email protected]>
87e6d92
to
024a82a
Compare
Implement the neo-project/neo#2907 (comment) and port a part of neo-project/neo#2913. Signed-off-by: Anna Shaleva <[email protected]>
@superboyiii, do we need to test it? I've wrote a unit-test (included in the PR) and sure it works correctly, but maybe you also want to check. @Liaojinghui, @vang1ong7ang, @dusmart, let's move on with this PR, we need to roll the 3.6.2 and this fix is needed to avoid the possible Conflicts attribute misuse. |
Sure, let me double check. |
Wait for @superboyiii tests |
var conflictRecord = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Transaction).Add(attr.Hash), | ||
() => new StorageItem(new TransactionState { ConflictingSigners = Array.Empty<UInt160>() })).GetInteroperable<TransactionState>(); | ||
conflictRecord.ConflictingSigners = conflictRecord.ConflictingSigners.Concat(conflictingSigners).Distinct().ToArray(); | ||
engine.Snapshot.Add(CreateStorageKey(Prefix_Transaction).Add(attr.Hash), new StorageItem(new TransactionState() { BlockIndex = engine.PersistingBlock.Index })); |
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.
I tried to hack a private net by the code from #2907, when multi transactions want to cancel the same tx(the same conflict attribute), it will throw InvalidOperationException
when they all change the same key's vale in the same block but it passed consensus. So finally it will be like:
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.
It's my poor knowledge of NeoC# codebase, the intention here was to replace the existing conflict record (if it's in the DB), but engine.Snapshot.Add
doesn't allow to do it. I'll fix it, thank you for testing!
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.
@superboyiii, could you, please, run the same test? I've modified the code so that now it's possible to rewrite existing malicious conflict record with the proper transaction.
…torage `engine.Snapshot.Add` doesn't allow to rewrite storage entity if it's already exist. Thus, we firstly need to remove it and afterwards to add the updated entity. Signed-off-by: Anna Shaleva <[email protected]>
Signed-off-by: Anna Shaleva <[email protected]>
88aab31
to
32d1341
Compare
Use Snapshot.GetAndChange instead of subsequent calls to Delete and Add. Ref. neo-project#2913 (comment). Signed-off-by: Anna Shaleva <[email protected]>
@superboyiii mind to test again? |
Never mind :) |
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.
Now it works well! Pass two-hours malicious pressure test.
@shargon Good to go |
* DBFTPlugin: adapt new Conflicts attribute storage scheme Upgrade neo-modules to use neo-project/neo#2913. Signed-off-by: Anna Shaleva <[email protected]> * Update neo * Fix version * Fix NativeHistory --------- Signed-off-by: Anna Shaleva <[email protected]> Co-authored-by: Jimmy <[email protected]> Co-authored-by: Shargon <[email protected]>
Close #2907. An alternative to #2908. This PR implements the #2907 (comment) and prevents all kind of attacks that were described earlier in #2907 and in #2818.
Two basic things are implemented in the current PR:
As it was said in #2907 (comment), this scheme doesn't have the problems that #2908 has and doesn't have the #2907 (comment) issue as far.
Any related questions and comments are welcomed; we may accidentally miss something in design or implementation. We believe that this scheme is definitely more preferable than #2908.
Notes:
setConflictsFee
to 0.02 GAS value (as suggested in conflict attribute stops the network #2907 (comment)) after new release is being rolled on T5 and mainnet.