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: fix native NEP-17 manifest construction #3195

Merged
merged 4 commits into from
Apr 16, 2024

Conversation

AnnaShaleva
Copy link
Member

@AnnaShaleva AnnaShaleva commented Apr 12, 2024

Description

Take into account event attributes declared onto the base class while constructing manifest for native contracts. Close #3194.

Type of change

  • Bug fix (non-breaking change which fixes an issue)

How Has This Been Tested?

  • getcontractstate RPC call for native NeoToken and GasToken sent to the updated node. The result is expected and correct, see the result:
Updated NeoToken contract state
anna@kiwi:~/Documents/GitProjects/nspcc-dev/neo-go$ curl -d '{ "jsonrpc": "2.0", "id": 1, "method": "getcontractstate", "params": [-5] }' localhost:10332 | json_pp
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  3433    0  3358  100    75  1287k  29446 --:--:-- --:--:-- --:--:-- 1676k
{
   "id" : 1,
   "jsonrpc" : "2.0",
   "result" : {
      "hash" : "0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5",
      "id" : -5,
      "manifest" : {
         "abi" : {
            "events" : [
               {
                  "name" : "Transfer",
                  "parameters" : [
                     {
                        "name" : "from",
                        "type" : "Hash160"
                     },
                     {
                        "name" : "to",
                        "type" : "Hash160"
                     },
                     {
                        "name" : "amount",
                        "type" : "Integer"
                     }
                  ]
               },
               {
                  "name" : "CandidateStateChanged",
                  "parameters" : [
                     {
                        "name" : "pubkey",
                        "type" : "PublicKey"
                     },
                     {
                        "name" : "registered",
                        "type" : "Boolean"
                     },
                     {
                        "name" : "votes",
                        "type" : "Integer"
                     }
                  ]
               },
               {
                  "name" : "Vote",
                  "parameters" : [
                     {
                        "name" : "account",
                        "type" : "Hash160"
                     },
                     {
                        "name" : "from",
                        "type" : "PublicKey"
                     },
                     {
                        "name" : "to",
                        "type" : "PublicKey"
                     },
                     {
                        "name" : "amount",
                        "type" : "Integer"
                     }
                  ]
               },
               {
                  "name" : "CommitteeChanged",
                  "parameters" : [
                     {
                        "name" : "old",
                        "type" : "Array"
                     },
                     {
                        "name" : "new",
                        "type" : "Array"
                     }
                  ]
               }
            ],
            "methods" : [
               {
                  "name" : "balanceOf",
                  "offset" : 0,
                  "parameters" : [
                     {
                        "name" : "account",
                        "type" : "Hash160"
                     }
                  ],
                  "returntype" : "Integer",
                  "safe" : true
               },
               {
                  "name" : "decimals",
                  "offset" : 7,
                  "parameters" : [],
                  "returntype" : "Integer",
                  "safe" : true
               },
               {
                  "name" : "getAccountState",
                  "offset" : 14,
                  "parameters" : [
                     {
                        "name" : "account",
                        "type" : "Hash160"
                     }
                  ],
                  "returntype" : "Array",
                  "safe" : true
               },
               {
                  "name" : "getAllCandidates",
                  "offset" : 21,
                  "parameters" : [],
                  "returntype" : "InteropInterface",
                  "safe" : true
               },
               {
                  "name" : "getCandidateVote",
                  "offset" : 28,
                  "parameters" : [
                     {
                        "name" : "pubKey",
                        "type" : "PublicKey"
                     }
                  ],
                  "returntype" : "Integer",
                  "safe" : true
               },
               {
                  "name" : "getCandidates",
                  "offset" : 35,
                  "parameters" : [],
                  "returntype" : "Array",
                  "safe" : true
               },
               {
                  "name" : "getCommittee",
                  "offset" : 42,
                  "parameters" : [],
                  "returntype" : "Array",
                  "safe" : true
               },
               {
                  "name" : "getGasPerBlock",
                  "offset" : 49,
                  "parameters" : [],
                  "returntype" : "Integer",
                  "safe" : true
               },
               {
                  "name" : "getNextBlockValidators",
                  "offset" : 56,
                  "parameters" : [],
                  "returntype" : "Array",
                  "safe" : true
               },
               {
                  "name" : "getRegisterPrice",
                  "offset" : 63,
                  "parameters" : [],
                  "returntype" : "Integer",
                  "safe" : true
               },
               {
                  "name" : "registerCandidate",
                  "offset" : 70,
                  "parameters" : [
                     {
                        "name" : "pubkey",
                        "type" : "PublicKey"
                     }
                  ],
                  "returntype" : "Boolean",
                  "safe" : false
               },
               {
                  "name" : "setGasPerBlock",
                  "offset" : 77,
                  "parameters" : [
                     {
                        "name" : "gasPerBlock",
                        "type" : "Integer"
                     }
                  ],
                  "returntype" : "Void",
                  "safe" : false
               },
               {
                  "name" : "setRegisterPrice",
                  "offset" : 84,
                  "parameters" : [
                     {
                        "name" : "registerPrice",
                        "type" : "Integer"
                     }
                  ],
                  "returntype" : "Void",
                  "safe" : false
               },
               {
                  "name" : "symbol",
                  "offset" : 91,
                  "parameters" : [],
                  "returntype" : "String",
                  "safe" : true
               },
               {
                  "name" : "totalSupply",
                  "offset" : 98,
                  "parameters" : [],
                  "returntype" : "Integer",
                  "safe" : true
               },
               {
                  "name" : "transfer",
                  "offset" : 105,
                  "parameters" : [
                     {
                        "name" : "from",
                        "type" : "Hash160"
                     },
                     {
                        "name" : "to",
                        "type" : "Hash160"
                     },
                     {
                        "name" : "amount",
                        "type" : "Integer"
                     },
                     {
                        "name" : "data",
                        "type" : "Any"
                     }
                  ],
                  "returntype" : "Boolean",
                  "safe" : false
               },
               {
                  "name" : "unclaimedGas",
                  "offset" : 112,
                  "parameters" : [
                     {
                        "name" : "account",
                        "type" : "Hash160"
                     },
                     {
                        "name" : "end",
                        "type" : "Integer"
                     }
                  ],
                  "returntype" : "Integer",
                  "safe" : true
               },
               {
                  "name" : "unregisterCandidate",
                  "offset" : 119,
                  "parameters" : [
                     {
                        "name" : "pubkey",
                        "type" : "PublicKey"
                     }
                  ],
                  "returntype" : "Boolean",
                  "safe" : false
               },
               {
                  "name" : "vote",
                  "offset" : 126,
                  "parameters" : [
                     {
                        "name" : "account",
                        "type" : "Hash160"
                     },
                     {
                        "name" : "voteTo",
                        "type" : "PublicKey"
                     }
                  ],
                  "returntype" : "Boolean",
                  "safe" : false
               }
            ]
         },
         "extra" : null,
         "features" : {},
         "groups" : [],
         "name" : "NeoToken",
         "permissions" : [
            {
               "contract" : "*",
               "methods" : "*"
            }
         ],
         "supportedstandards" : [
            "NEP-17"
         ],
         "trusts" : []
      },
      "nef" : {
         "checksum" : 65467259,
         "compiler" : "neo-core-v3.0",
         "magic" : 860243278,
         "script" : "EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQA==",
         "source" : "",
         "tokens" : []
      },
      "updatecounter" : 0
   }
}
Updated GasToken contract state
anna@kiwi:~/Documents/GitProjects/nspcc-dev/neo-go$ curl -d '{ "jsonrpc": "2.0", "id": 1, "method": "getcontractstate", "params": [-6] }' localhost:10332 | json_pp
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1250    0  1175  100    75   408k  26709 --:--:-- --:--:-- --:--:--  610k
{
   "id" : 1,
   "jsonrpc" : "2.0",
   "result" : {
      "hash" : "0xd2a4cff31913016155e38e474a2c06d08be276cf",
      "id" : -6,
      "manifest" : {
         "abi" : {
            "events" : [
               {
                  "name" : "Transfer",
                  "parameters" : [
                     {
                        "name" : "from",
                        "type" : "Hash160"
                     },
                     {
                        "name" : "to",
                        "type" : "Hash160"
                     },
                     {
                        "name" : "amount",
                        "type" : "Integer"
                     }
                  ]
               }
            ],
            "methods" : [
               {
                  "name" : "balanceOf",
                  "offset" : 0,
                  "parameters" : [
                     {
                        "name" : "account",
                        "type" : "Hash160"
                     }
                  ],
                  "returntype" : "Integer",
                  "safe" : true
               },
               {
                  "name" : "decimals",
                  "offset" : 7,
                  "parameters" : [],
                  "returntype" : "Integer",
                  "safe" : true
               },
               {
                  "name" : "symbol",
                  "offset" : 14,
                  "parameters" : [],
                  "returntype" : "String",
                  "safe" : true
               },
               {
                  "name" : "totalSupply",
                  "offset" : 21,
                  "parameters" : [],
                  "returntype" : "Integer",
                  "safe" : true
               },
               {
                  "name" : "transfer",
                  "offset" : 28,
                  "parameters" : [
                     {
                        "name" : "from",
                        "type" : "Hash160"
                     },
                     {
                        "name" : "to",
                        "type" : "Hash160"
                     },
                     {
                        "name" : "amount",
                        "type" : "Integer"
                     },
                     {
                        "name" : "data",
                        "type" : "Any"
                     }
                  ],
                  "returntype" : "Boolean",
                  "safe" : false
               }
            ]
         },
         "extra" : null,
         "features" : {},
         "groups" : [],
         "name" : "GasToken",
         "permissions" : [
            {
               "contract" : "*",
               "methods" : "*"
            }
         ],
         "supportedstandards" : [
            "NEP-17"
         ],
         "trusts" : []
      },
      "nef" : {
         "checksum" : 2663858513,
         "compiler" : "neo-core-v3.0",
         "magic" : 860243278,
         "script" : "EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=",
         "source" : "",
         "tokens" : []
      },
      "updatecounter" : 0
   }
}

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

Take into account event attributes declared onto the base class for
native contracts. Close #3194.

Signed-off-by: Anna Shaleva <[email protected]>
@AnnaShaleva AnnaShaleva added critical Issues (bugs) that need to be fixed ASAP waiting for review labels Apr 12, 2024
roman-khimov
roman-khimov previously approved these changes Apr 12, 2024
Copy link
Contributor

@roman-khimov roman-khimov left a comment

Choose a reason for hiding this comment

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

I don't want to think about the case with overrides of some kind for the same event name. Hopefully, we'll never do this for natives.

@dusmart
Copy link

dusmart commented Apr 13, 2024

Thanks for locating this bug.
BTW, this fix is also a hard fork.

@AnnaShaleva
Copy link
Member Author

AnnaShaleva commented Apr 13, 2024

BTW, this fix is also a hard fork.

It’s not. This bug was introduced in post-3.6, in #2942, so this code was not in production yet, and the fix itself just fixes natives manifest and Management’s storage.

But you’re right from the point that this fix requires node resync from genesis to work.

@Jim8y
Copy link
Contributor

Jim8y commented Apr 13, 2024

Any possible UT for this fix?

Jim8y
Jim8y previously approved these changes Apr 13, 2024
Copy link
Member

@superboyiii superboyiii left a comment

Choose a reason for hiding this comment

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

Checked all native manifest. Yes, this really fixed.

@AnnaShaleva
Copy link
Member Author

Any possible UT for this fix?

Sure, will add in a couple of hours.

shargon
shargon previously approved these changes Apr 15, 2024
Copy link
Member

@vncoelho vncoelho left a comment

Choose a reason for hiding this comment

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

Isn't it possible to set up a UT to ensure that this fix is correct?

@vncoelho
Copy link
Member

Any possible UT for this fix?

I just saw @Jim8y request now. I was checking the code.

The code looks good and makes sense. It would be good to ensure a failed UT now and the fix for it.

@vncoelho
Copy link
Member

This reminds me that it would be also good to generate automatically manifest for NEO and GAS instead of manually. That would had make this error appear earlier perhaps.

@Jim8y
Copy link
Contributor

Jim8y commented Apr 15, 2024

This reminds me that it would be also good to generate automatically manifest for NEO and GAS instead of manually. That would had make this error appear earlier perhaps.

Totally agree.

@AnnaShaleva AnnaShaleva dismissed stale reviews from shargon, Jim8y, and roman-khimov via 2bd4fe5 April 15, 2024 13:50
@AnnaShaleva
Copy link
Member Author

Sure, will add in a couple of hours.

Two tests are added: one for particularly this bug (check Transfer events for NEP17 native contracts), and another one to check the whole set of native contract states at genesis block with all hardforks disabled. The expected manifests are checked precisely, so they are correct. Also checked against NeoGo's ones.

In future TestGenesisNativeState will help us to detect similar bugs.

Jim8y
Jim8y previously approved these changes Apr 15, 2024
@AnnaShaleva
Copy link
Member Author

at genesis block with all hardforks disabled

With all hardforks enabled, actually. Let me fix this.

Ensure that contract states generated with all hardforks enabled match
the expected values.

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

With all hardforks enabled, actually. Let me fix this.

Fixed.

vncoelho
vncoelho previously approved these changes Apr 15, 2024
Jim8y
Jim8y previously approved these changes Apr 15, 2024
@Jim8y
Copy link
Contributor

Jim8y commented Apr 15, 2024

With all hardforks enabled, actually. Let me fix this.

Fixed.

wait a sec, what is the new logic? hardforks enabled or disabled?

@AnnaShaleva
Copy link
Member Author

AnnaShaleva commented Apr 15, 2024

wait a sec, what is the new logic? hardforks enabled or disabled?

The code itself preserves the old logic except that NEP17 notifications are included into the NEP17 state, so #3194 is fixed for both enabled/disabled hardforks.

The unit tests check the presence of these notifications and check natives state with all hardforks enabled since it's the default behaviour of TestBlockchain (it uses the default ProtocolSettings). I think it's perfectly OK for our tests, since we need to test fresh functionality as far. But for this particular bug it doesn't make any difference since Transfer notifications should always be present in the native state (with or without hardforks).

@shargon shargon dismissed stale reviews from Jim8y and vncoelho via 3b16a00 April 15, 2024 15:37
shargon
shargon previously approved these changes Apr 15, 2024
roman-khimov
roman-khimov previously approved these changes Apr 15, 2024
@Jim8y Jim8y dismissed stale reviews from roman-khimov and shargon via 568823b April 16, 2024 00:40
@Jim8y
Copy link
Contributor

Jim8y commented Apr 16, 2024

@shargon can be merged.

@shargon shargon merged commit b2b1150 into master Apr 16, 2024
6 checks passed
@shargon shargon deleted the fix-native-nep17 branch April 16, 2024 08:03
@roman-khimov roman-khimov added this to the v3.7.0 milestone May 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
critical Issues (bugs) that need to be fixed ASAP waiting for review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

HF-based native contract update doesn't work as expected
7 participants