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

Perform native contract initialization for the set of hardforks #3200

Closed
AnnaShaleva opened this issue Apr 22, 2024 · 0 comments · Fixed by #3202
Closed

Perform native contract initialization for the set of hardforks #3200

AnnaShaleva opened this issue Apr 22, 2024 · 0 comments · Fixed by #3202
Assignees
Labels
Discussion Initial issue state - proposed but not yet accepted
Milestone

Comments

@AnnaShaleva
Copy link
Member

AnnaShaleva commented Apr 22, 2024

Summary or problem description
I've finished the port of HF-based native contract update, and this is the last remaining issue connected with this functionality. Currently native contract initialization happens every time when native contract needs to be deployed or updated:

await contract.Initialize(engine, hf);

This code works perfectly for the current mainnet/testnet and for the current version of native contracts. However, there might be a case (in some private installations like I had for the tests) when several hardforks are being active starting from the same height. Technically it's a valid node configuration, so let's take as an example the case when all hardforks are enabled from the genesis block. In this case await contract.Initialize(engine, hf); will be called only once during Genesis block persist with nil hardfork value.

Let's take as an example the following Initialize override:

internal override ContractTask Initialize(ApplicationEngine engine, Hardfork? hardfork)
{
if (hardfork == ActiveIn)
{
UInt160 account = Contract.GetBFTAddress(engine.ProtocolSettings.StandbyValidators);
return Mint(engine, account, engine.ProtocolSettings.InitialGasDistribution, false);
}
return ContractTask.CompletedTask;
}

The problem is: if we ever decide to extend this Initialize method with some contract storage changes required on new HFDomovoy hardfork (that is different from the contract's ActiveIn), then the initialization code is not going to work properly in case when several hardforks are active starting from the same height.

Do you have any solution you want to propose?
Call await contract.Initialize(engine, hf); in cycle consequently for the range of hardforks, starting from the hf and ending with the last hardfork that is active starting from the current block. Then native contracts will be able to properly manage their storage inside the Initialize override based on the provided hardfork. This change won't affect the existing behaviour for mainnet/testnet.

Where in the software does this update applies to?

  • Native contracts

Additional information
See the nspcc-dev/neo-go#3402 (comment).

Please, note that currently it's not a bug/problem for mainnet/testnet, that's why I'm creating a discussion issue rather than bug. But it can easily become a bug in future on further native contracts code extension, so to me it's worth solving right now.

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

Successfully merging a pull request may close this issue.

3 participants