From 9619614f9a00a33f228bc51f6d62a5c5803a2cdc Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 23 Apr 2024 12:09:23 +0200 Subject: [PATCH 01/13] Close https://github.com/neo-project/neo/issues/3200 --- .../Native/ContractManagement.cs | 8 +++++-- .../SmartContract/Native/NativeContract.cs | 24 ++++++++++++------- .../SmartContract/Native/UT_NativeContract.cs | 3 ++- 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/Neo/SmartContract/Native/ContractManagement.cs b/src/Neo/SmartContract/Native/ContractManagement.cs index 28642a2db1..61c47f526c 100644 --- a/src/Neo/SmartContract/Native/ContractManagement.cs +++ b/src/Neo/SmartContract/Native/ContractManagement.cs @@ -70,7 +70,7 @@ internal override async ContractTask OnPersist(ApplicationEngine engine) { foreach (NativeContract contract in Contracts) { - if (contract.IsInitializeBlock(engine.ProtocolSettings, engine.PersistingBlock.Index, out Hardfork? hf)) + if (contract.IsInitializeBlock(engine.ProtocolSettings, engine.PersistingBlock.Index, out var hfs)) { ContractState contractState = contract.GetContractState(engine.ProtocolSettings, engine.PersistingBlock.Index); StorageItem state = engine.Snapshot.GetAndChange(CreateStorageKey(Prefix_Contract).Add(contract.Hash)); @@ -92,7 +92,11 @@ internal override async ContractTask OnPersist(ApplicationEngine engine) oldContract.Manifest = contractState.Manifest; } - await contract.Initialize(engine, hf); + // Initialize native contract for all hardforks + foreach (var hf in hfs) + { + await contract.Initialize(engine, hf); + } // Emit native contract notification engine.SendNotification(Hash, state is null ? "Deploy" : "Update", new VM.Types.Array(engine.ReferenceCounter) { contract.Hash.ToArray() }); } diff --git a/src/Neo/SmartContract/Native/NativeContract.cs b/src/Neo/SmartContract/Native/NativeContract.cs index 2003962b87..a4a3a562ff 100644 --- a/src/Neo/SmartContract/Native/NativeContract.cs +++ b/src/Neo/SmartContract/Native/NativeContract.cs @@ -266,19 +266,21 @@ protected virtual void OnManifestCompose(ContractManifest manifest) { } /// /// The where the HardForks are configured. /// Block index - /// Active hardfork + /// Active hardforks /// True if the native contract must be initialized - internal bool IsInitializeBlock(ProtocolSettings settings, uint index, out Hardfork? hardfork) + internal bool IsInitializeBlock(ProtocolSettings settings, uint index, out Hardfork[]? hardforks) { // If is not configured, the Genesis is the a initialized block if (index == 0 && ActiveIn is null) { - hardfork = null; + hardforks = null; return true; } - // If is in the hardfork height, return true - foreach (Hardfork hf in usedHardforks) + var hfs = new List(); + + // If is in the hardfork height, add them to return array + foreach (var hf in usedHardforks) { if (!settings.Hardforks.TryGetValue(hf, out var activeIn)) { @@ -288,13 +290,19 @@ internal bool IsInitializeBlock(ProtocolSettings settings, uint index, out Hardf if (activeIn == index) { - hardfork = hf; - return true; + hfs.Add(hf); } } + // Return all initialize hardforks + if (hfs.Count > 0) + { + hardforks = hfs.ToArray(); + return true; + } + // Initialized not required - hardfork = null; + hardforks = null; return false; } diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs index 181ff139ec..fc20780b73 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs @@ -81,7 +81,8 @@ public void TestIsInitializeBlock() Assert.IsNull(hf); Assert.IsTrue(NativeContract.CryptoLib.IsInitializeBlock(settings, 20, out hf)); - Assert.AreEqual(Hardfork.HF_Cockatrice, hf); + Assert.AreEqual(1, hf.Length); + Assert.AreEqual(Hardfork.HF_Cockatrice, hf[0]); } [TestMethod] From 0ddfcabd08bc5652c5a51ab831ab52369e0d3719 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 25 Apr 2024 12:41:05 +0200 Subject: [PATCH 02/13] Anna's review --- src/Neo/SmartContract/Native/ContractManagement.cs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Neo/SmartContract/Native/ContractManagement.cs b/src/Neo/SmartContract/Native/ContractManagement.cs index 61c47f526c..4a768d4ff3 100644 --- a/src/Neo/SmartContract/Native/ContractManagement.cs +++ b/src/Neo/SmartContract/Native/ContractManagement.cs @@ -93,10 +93,18 @@ internal override async ContractTask OnPersist(ApplicationEngine engine) } // Initialize native contract for all hardforks - foreach (var hf in hfs) + if (hfs?.Length > 0) { - await contract.Initialize(engine, hf); + foreach (var hf in hfs) + { + await contract.Initialize(engine, hf); + } } + else + { + await contract.Initialize(engine, null); + } + // Emit native contract notification engine.SendNotification(Hash, state is null ? "Deploy" : "Update", new VM.Types.Array(engine.ReferenceCounter) { contract.Hash.ToArray() }); } From 0c17659365e32cf142cfb6c9d21f14bfd7c773f0 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 25 Apr 2024 12:45:14 +0200 Subject: [PATCH 03/13] All Hfs when genesis --- src/Neo/SmartContract/Native/NativeContract.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Neo/SmartContract/Native/NativeContract.cs b/src/Neo/SmartContract/Native/NativeContract.cs index a4a3a562ff..dd8e77f389 100644 --- a/src/Neo/SmartContract/Native/NativeContract.cs +++ b/src/Neo/SmartContract/Native/NativeContract.cs @@ -268,12 +268,12 @@ protected virtual void OnManifestCompose(ContractManifest manifest) { } /// Block index /// Active hardforks /// True if the native contract must be initialized - internal bool IsInitializeBlock(ProtocolSettings settings, uint index, out Hardfork[]? hardforks) + internal bool IsInitializeBlock(ProtocolSettings settings, uint index, out Hardfork[] hardforks) { // If is not configured, the Genesis is the a initialized block if (index == 0 && ActiveIn is null) { - hardforks = null; + hardforks = usedHardforks.ToArray(); return true; } From e2cbfe59fe6a0268cff31f8cdc1993dd83e71604 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 25 Apr 2024 12:48:46 +0200 Subject: [PATCH 04/13] fix --- src/Neo/SmartContract/Native/NativeContract.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Neo/SmartContract/Native/NativeContract.cs b/src/Neo/SmartContract/Native/NativeContract.cs index dd8e77f389..2e3db31c58 100644 --- a/src/Neo/SmartContract/Native/NativeContract.cs +++ b/src/Neo/SmartContract/Native/NativeContract.cs @@ -270,13 +270,6 @@ protected virtual void OnManifestCompose(ContractManifest manifest) { } /// True if the native contract must be initialized internal bool IsInitializeBlock(ProtocolSettings settings, uint index, out Hardfork[] hardforks) { - // If is not configured, the Genesis is the a initialized block - if (index == 0 && ActiveIn is null) - { - hardforks = usedHardforks.ToArray(); - return true; - } - var hfs = new List(); // If is in the hardfork height, add them to return array @@ -301,6 +294,13 @@ internal bool IsInitializeBlock(ProtocolSettings settings, uint index, out Hardf return true; } + // If is not configured, the Genesis is the a initialized block + if (index == 0 && ActiveIn is null) + { + hardforks = hfs.ToArray(); + return true; + } + // Initialized not required hardforks = null; return false; From ec95fa521aa1607037146c730bd2185f0f6b164e Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 26 Apr 2024 00:27:40 -0700 Subject: [PATCH 05/13] Update src/Neo/SmartContract/Native/NativeContract.cs Co-authored-by: Anna Shaleva --- src/Neo/SmartContract/Native/NativeContract.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo/SmartContract/Native/NativeContract.cs b/src/Neo/SmartContract/Native/NativeContract.cs index 2e3db31c58..7249ecdb9a 100644 --- a/src/Neo/SmartContract/Native/NativeContract.cs +++ b/src/Neo/SmartContract/Native/NativeContract.cs @@ -294,7 +294,7 @@ internal bool IsInitializeBlock(ProtocolSettings settings, uint index, out Hardf return true; } - // If is not configured, the Genesis is the a initialized block + // If is not configured, the Genesis is an initialization block. if (index == 0 && ActiveIn is null) { hardforks = hfs.ToArray(); From c1f18a4b6ca1ef2ceb290dec40358a559097e87f Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Fri, 26 Apr 2024 09:34:14 +0200 Subject: [PATCH 06/13] possible fix --- src/Neo/SmartContract/Native/ContractManagement.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Neo/SmartContract/Native/ContractManagement.cs b/src/Neo/SmartContract/Native/ContractManagement.cs index 4a768d4ff3..2eb369ace9 100644 --- a/src/Neo/SmartContract/Native/ContractManagement.cs +++ b/src/Neo/SmartContract/Native/ContractManagement.cs @@ -99,6 +99,11 @@ internal override async ContractTask OnPersist(ApplicationEngine engine) { await contract.Initialize(engine, hf); } + + if (contract.ActiveIn == null) + { + await contract.Initialize(engine, null); + } } else { From 68c285cd97395ca73c4e41ee75998014df103fbd Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 30 Apr 2024 10:37:22 +0200 Subject: [PATCH 07/13] always Initialize with null --- src/Neo/SmartContract/Native/ContractManagement.cs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/Neo/SmartContract/Native/ContractManagement.cs b/src/Neo/SmartContract/Native/ContractManagement.cs index 2eb369ace9..a383411a49 100644 --- a/src/Neo/SmartContract/Native/ContractManagement.cs +++ b/src/Neo/SmartContract/Native/ContractManagement.cs @@ -92,22 +92,16 @@ internal override async ContractTask OnPersist(ApplicationEngine engine) oldContract.Manifest = contractState.Manifest; } - // Initialize native contract for all hardforks + // Initialize native contract + await contract.Initialize(engine, null); + + // Initialize native contract for specific hardforks if (hfs?.Length > 0) { foreach (var hf in hfs) { await contract.Initialize(engine, hf); } - - if (contract.ActiveIn == null) - { - await contract.Initialize(engine, null); - } - } - else - { - await contract.Initialize(engine, null); } // Emit native contract notification From e0d8c88c175ceed1eff7a233d4f4e19cdc9b90ec Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Tue, 30 Apr 2024 11:28:51 +0200 Subject: [PATCH 08/13] Revert "always Initialize with null" This reverts commit 68c285cd97395ca73c4e41ee75998014df103fbd. --- src/Neo/SmartContract/Native/ContractManagement.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Neo/SmartContract/Native/ContractManagement.cs b/src/Neo/SmartContract/Native/ContractManagement.cs index a383411a49..2eb369ace9 100644 --- a/src/Neo/SmartContract/Native/ContractManagement.cs +++ b/src/Neo/SmartContract/Native/ContractManagement.cs @@ -92,16 +92,22 @@ internal override async ContractTask OnPersist(ApplicationEngine engine) oldContract.Manifest = contractState.Manifest; } - // Initialize native contract - await contract.Initialize(engine, null); - - // Initialize native contract for specific hardforks + // Initialize native contract for all hardforks if (hfs?.Length > 0) { foreach (var hf in hfs) { await contract.Initialize(engine, hf); } + + if (contract.ActiveIn == null) + { + await contract.Initialize(engine, null); + } + } + else + { + await contract.Initialize(engine, null); } // Emit native contract notification From 9a8e52133275f8af8e929d80a189d7b7a2284942 Mon Sep 17 00:00:00 2001 From: Fernando Diaz Toledano Date: Thu, 2 May 2024 11:28:32 +0200 Subject: [PATCH 09/13] Call with null during deploy --- src/Neo/SmartContract/Native/ContractManagement.cs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/Neo/SmartContract/Native/ContractManagement.cs b/src/Neo/SmartContract/Native/ContractManagement.cs index 2eb369ace9..89c8a98597 100644 --- a/src/Neo/SmartContract/Native/ContractManagement.cs +++ b/src/Neo/SmartContract/Native/ContractManagement.cs @@ -80,6 +80,9 @@ internal override async ContractTask OnPersist(ApplicationEngine engine) // Create the contract state engine.Snapshot.Add(CreateStorageKey(Prefix_Contract).Add(contract.Hash), new StorageItem(contractState)); engine.Snapshot.Add(CreateStorageKey(Prefix_ContractHash).AddBigEndian(contract.Id), new StorageItem(contract.Hash.ToArray())); + + // Initialize the native smart contract + await contract.Initialize(engine, null); } else { @@ -99,15 +102,6 @@ internal override async ContractTask OnPersist(ApplicationEngine engine) { await contract.Initialize(engine, hf); } - - if (contract.ActiveIn == null) - { - await contract.Initialize(engine, null); - } - } - else - { - await contract.Initialize(engine, null); } // Emit native contract notification From 1b7334bb8c08c5c0706f366c52aba58332000b1a Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 5 May 2024 12:08:03 +0200 Subject: [PATCH 10/13] Update src/Neo/SmartContract/Native/ContractManagement.cs Co-authored-by: Anna Shaleva --- src/Neo/SmartContract/Native/ContractManagement.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Neo/SmartContract/Native/ContractManagement.cs b/src/Neo/SmartContract/Native/ContractManagement.cs index 0700cbffab..bc659516c2 100644 --- a/src/Neo/SmartContract/Native/ContractManagement.cs +++ b/src/Neo/SmartContract/Native/ContractManagement.cs @@ -81,8 +81,12 @@ internal override async ContractTask OnPersistAsync(ApplicationEngine engine) engine.Snapshot.Add(CreateStorageKey(Prefix_Contract).Add(contract.Hash), new StorageItem(contractState)); engine.Snapshot.Add(CreateStorageKey(Prefix_ContractHash).AddBigEndian(contract.Id), new StorageItem(contract.Hash.ToArray())); - // Initialize the native smart contract - await contract.Initialize(engine, null); + // Initialize the native smart contract if it's active starting from the genesis. + // If it's not the case, then hardfork-based initialization will be performed down below. + if (contract.ActiveIn is null) + { + await contract.InitializeAsync(engine, null); + } } else { From b78ae29112a540340d202daba164954178c94aa6 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 5 May 2024 12:08:12 +0200 Subject: [PATCH 11/13] Update src/Neo/SmartContract/Native/ContractManagement.cs Co-authored-by: Anna Shaleva --- src/Neo/SmartContract/Native/ContractManagement.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Neo/SmartContract/Native/ContractManagement.cs b/src/Neo/SmartContract/Native/ContractManagement.cs index bc659516c2..519c129864 100644 --- a/src/Neo/SmartContract/Native/ContractManagement.cs +++ b/src/Neo/SmartContract/Native/ContractManagement.cs @@ -99,7 +99,8 @@ internal override async ContractTask OnPersistAsync(ApplicationEngine engine) oldContract.Manifest = contractState.Manifest; } - // Initialize native contract for all hardforks + // Initialize native contract for all hardforks that are active starting from the persisting block. + // If the contract is active starting from some non-nil hardfork, then this hardfork is also included into hfs. if (hfs?.Length > 0) { foreach (var hf in hfs) From 59365a63b7431c8e6da87f69ba552be343ad0496 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 5 May 2024 12:08:30 +0200 Subject: [PATCH 12/13] Update src/Neo/SmartContract/Native/ContractManagement.cs Co-authored-by: Anna Shaleva --- src/Neo/SmartContract/Native/ContractManagement.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo/SmartContract/Native/ContractManagement.cs b/src/Neo/SmartContract/Native/ContractManagement.cs index 519c129864..e7a7e122f2 100644 --- a/src/Neo/SmartContract/Native/ContractManagement.cs +++ b/src/Neo/SmartContract/Native/ContractManagement.cs @@ -105,7 +105,7 @@ internal override async ContractTask OnPersistAsync(ApplicationEngine engine) { foreach (var hf in hfs) { - await contract.Initialize(engine, hf); + await contract.InitializeAsync(engine, hf); } } From 5361d55488865bff2cb272ec2963d9bd6cd4f138 Mon Sep 17 00:00:00 2001 From: Anna Shaleva Date: Mon, 6 May 2024 23:25:28 +0300 Subject: [PATCH 13/13] Native: adjust failing TestIsInitializeBlock According to new logic, an empty set of hard-forks will be returned in case of genesis initialization with all hardforks disabled. Ref. https://github.com/neo-project/neo/pull/3202#discussion_r1590270244. Signed-off-by: Anna Shaleva --- tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs index fc20780b73..5a634d52d9 100644 --- a/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs +++ b/tests/Neo.UnitTests/SmartContract/Native/UT_NativeContract.cs @@ -75,7 +75,8 @@ public void TestIsInitializeBlock() File.Delete(file); Assert.IsTrue(NativeContract.CryptoLib.IsInitializeBlock(settings, 0, out var hf)); - Assert.IsNull(hf); + Assert.IsNotNull(hf); + Assert.AreEqual(0, hf.Length); Assert.IsFalse(NativeContract.CryptoLib.IsInitializeBlock(settings, 1, out hf)); Assert.IsNull(hf);