Repository navigation
Native: move hardforks management to native Policy - #4726
cschuchardt88 wants to merge 26 commits into
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master-n3 #4726 +/- ##
===========================================
Coverage 83.93% 83.94%
===========================================
Files 240 242 +2
Lines 17129 17233 +104
Branches 2453 2481 +28
===========================================
+ Hits 14378 14466 +88
- Misses 1964 1974 +10
- Partials 787 793 +6 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Heads up @roman-khimov @AnnaShaleva — this implements #4580 (committee Policy hardfork activation), including the override-safety pieces from the discussion: public-network lock (MainNet magic + |
Add Policy.enableHardfork/getHardfork (HF_Huyao) so post-Huyao hardforks activate from the next block after a committee-signed call. Wire IsHardforkEnabled, native init, and contract state to honor on-chain Policy heights; unknown hardfork ids fail the block so outdated nodes stop until upgraded.
Address neo#4580 comment on override safety: well-known MainNet magic and on-chain setPublicNetwork seal public chains so post-Huyao activation is Policy-only. Add HardforkDebugOverrides for neo-express/private nets, HF_Ifrit as the first Policy-activatable hardfork, config divergence detection, and tests for misconfiguration failure modes.
Cover private-net enable rejections, public-config issue reporting, HardforkDebugOverrides validation/load paths, and Policy-aware NativeContract init/active helpers after rebasing onto HF_Iara.
b8f5763 to
08f3acf
Compare
|
@cschuchardt88 the final design of this feature is discussed with @roman-khimov and presented in nspcc-dev/neo-go#4377. So we need C# version to follow this PR. I haven't yet compared your implementation with nspcc-dev/neo-go#4377, will review deeply later. |
|
@AnnaShaleva can you check #4580 (comment) and give me some insights my concerns. |
Address Anna's review on neo#4726 / nspcc-dev/neo-go#4377: - Rename enableHardfork/getHardfork to activateHardfork/getHardforkActivationHeight - Use raw hardfork names (Iara) and return Null when unset - Rename HardforkEnabled to HardforkActivationScheduled - UnknownHardforkException after AssertCommittee so outdated nodes halt - Drop public-network marker and HardforkDebugOverrides; post-Huyao is Policy-only - Require a snapshot in NativeContract.IsActive
|
Thanks @AnnaShaleva — this push aligns the C# side with your review and nspcc-dev/neo-go#4377. Addressed:
Not in this push (same TODO as neo-go #4377): moving Aspidochelone–Huyao activations into Policy and initializing them at Huyao. Happy to do that as a follow-up once the neo-go design for it lands. |
- Parse Policy hardfork names as the exact raw string only (Iara, not iara/HF_Iara). - IsHardforkEnabledDelegate now takes settings and snapshot; drop the settings-only GetContractState overload. - Restore the omitted-hardfork-is-disabled comment in IsInitializeBlock. - activateHardfork uses engine.IsHardforkEnabled only; notify with the raw name. - Store A-H config heights in Policy on Huyao init; Policy.Activations includes Iara. - Reject post-Huyao entries in ProtocolSettings.Hardforks. - Remove DetectHardforkConfigDivergence and redundant Policy tests.
|
Thanks @AnnaShaleva — this push addresses your 2026-08-25 review. Policy names and activateHardfork
NativeContract
Huyao init / Activations
ProtocolSettings
Tests
78 related unit tests passed ( |
After Huyao initialize copies Aspidochelone-Huyao heights into Policy, TryGetActivationHeight prefers those stored heights so IsActive is Policy-backed (neo-go#4377). Config is used only until Huyao is enabled.
|
Completed the remaining neo-go#4377 / Anna TODO on this PR: use Policy as the runtime source of truth for Aspidochelone–Huyao once Huyao is enabled. Huyao
So Tests: Not in this PR: the same A–H copy inside nspcc-dev/neo-go#4377, and committee multi-sig packaging for |
Cover getHardforkActivationHeight after activate, missing Policy height, activate without a persisting block, UnknownHardforkException wrapping, and Hardforks.TryParseExact/GetName.
04df42d to
b69df3a
Compare
|
Yes, @AnnaShaleva But my main concern is regard the previous conducted tests . If anyone has already tested...anyway. The PR looks good. I am finishing some basic testing.+ |
| if (engine.SnapshotCache.Contains(key)) | ||
| throw new InvalidOperationException($"Hardfork {hardfork} is already scheduled."); | ||
|
|
||
| uint activationHeight = checked(engine.PersistingBlock.Index + 1); |
There was a problem hiding this comment.
Maybe we should send the num of blocks after activation, to have margin between sign, relay, and fork
There was a problem hiding this comment.
Can be done, but why do we need it? We don't have a mechanism of scheduled hardfork deactivation anyway.
send the num of blocks
Do you want it to be a parameter of ActivateHardfork method?
There was a problem hiding this comment.
Preparation, you can publish that fork will be in specific height, like this is not possible to know when will be active
There was a problem hiding this comment.
To me it's pretty useless, I'd rather have it activated once transaction gets in, it's just easier to handle. We don't know when block X will happen anyway.
There was a problem hiding this comment.
Contracts can be prepared, with this new logic you are no only changing how hardfork will be activated, you are changing how and when the users will know it
There was a problem hiding this comment.
Maybe we should send the num of blocks after activation, to have margin between sign, relay, and fork
Or we set the number of blocks after agreement when required number of signatures is reached (but remember that this will be prune to interpretation of txs and should be ensured by onchain TXs only).
Or, at least, we need a fixed height upon agreement, if not reached agreement until that we try again. That is the best model to me. Fixed height and tentative until it.
There was a problem hiding this comment.
Preparation, you can publish that fork will be in specific height, like this is not possible to know when will be active
My idea is the same, @shargon
There was a problem hiding this comment.
To me it's pretty useless, I'd rather have it activated once transaction gets in, it's just easier to handle. We don't know when block X will happen anyway.
I do not think so, to much uncertainties, too much prone to manipulation. Fixed height and fixed rule with a Preparation.
There was a problem hiding this comment.
Contracts can be prepared, with this new logic you are no only changing how hardfork will be activated, you are changing how and when the users will know it
I am fully aligned with you, @shargon
There was a problem hiding this comment.
Implemented, @shargon let's check the updated version. We also added an ability to reschedule the already scheduled hardfork. It's useful in case if hardfork is already scheduled but some bug is discovered and a fix should be applied prior to hardfork activation.
| return false; | ||
| } | ||
|
|
||
| if (settings.IsHardforkEnabled(ProtocolSettings.LastConfigManagedHardfork, currentIndex) |
There was a problem hiding this comment.
Why check of is enabled? You want to know the activation height
There was a problem hiding this comment.
Because starting from LastConfigManagedHardfork we store height in the Policy's storage. So if LastConfigManagedHardfork is enabled then we should refer to the Policy instead of config.
Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
| return false; | ||
|
|
||
| foreach (Hardfork value in Enum.GetValues<Hardfork>()) | ||
| if (Enum.TryParse(typeof(Hardfork), "HF_" + name, false, out var fork) && Enum.GetNames<Hardfork>().Any(n => n.Equals("HF_" + name, StringComparison.Ordinal))) |
There was a problem hiding this comment.
We need to check that the resulting enum is defined. But you're right, we add HF_ prefix to name, so any non-valid name will fail parsing.
Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
|
Updated to the latest master. |
[Flags] lets Enum.TryParse accept comma-separated aliases that equal a named value. TryParseExact now requires the canonical HF_ name, so activateHardfork only accepts exact names such as Iara. The macOS Test job failed UT_TaskManager.InvalidBlock_AbortsThePeerThatSuppliedIt because peer.Send returned before the mailbox recorded the hash. Drive the tests that assert ReceivedBlockHashes immediately through TestActorRef.Receive. Ref. neo-project#4726
|
Pushed Hardfork name parsing. macOS TaskManager failure. |
activateHardfork and getHardforkActivationHeight now take ByteArray (0x12) instead of String (0x13) so the Huyao Policy manifest matches nspcc-dev/neo-go#4377. Names are still UTF-8 canonical HF names parsed by Hardforks.TryParseExact. Ref. neo-project#4726
This reverts commit 640f1f6.
|
640f1f6 is reverted, we need a fully-qualified |
Ref. neo-project#4726 (comment). Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
|
@neo-project/core let's review the updated API one more time. |
| } | ||
|
|
||
| [TestMethod] | ||
| public void Load_IgnoresHardforkDebugOverrides_AndDoesNotEnableIara() |
There was a problem hiding this comment.
This test is no longer need. It will always fail.
Ref. neo-project#4726 (comment). Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
Close #4580.