Skip to content

Commit 3fc8895

Browse files
authored
Merge NativeUpdateHistory with HardForks (#2941)
* Merge NativeUpdateHistory with HardForks * Change throw message * Ensure Genesis is not configured * Improve comment * Remove Genesis from HF and follow the Anna suggestions * Revert HF value changes
1 parent efa8659 commit 3fc8895

File tree

5 files changed

+59
-50
lines changed

5 files changed

+59
-50
lines changed

src/Neo/ProtocolSettings.cs

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,13 @@
88
// Redistribution and use in source and binary forms with or without
99
// modifications are permitted.
1010

11-
using Microsoft.Extensions.Configuration;
12-
using Neo.Cryptography.ECC;
13-
using Neo.Network.P2P.Payloads;
14-
using Neo.SmartContract.Native;
1511
using System;
1612
using System.Collections.Generic;
1713
using System.Collections.Immutable;
1814
using System.Linq;
15+
using Microsoft.Extensions.Configuration;
16+
using Neo.Cryptography.ECC;
17+
using Neo.Network.P2P.Payloads;
1918

2019
namespace Neo
2120
{
@@ -85,10 +84,8 @@ public record ProtocolSettings
8584
public uint MaxTraceableBlocks { get; init; }
8685

8786
/// <summary>
88-
/// Contains the update history of all native contracts.
87+
/// Sets the block height from which a hardfork is activated.
8988
/// </summary>
90-
public IReadOnlyDictionary<string, uint[]> NativeUpdateHistory { get; init; }
91-
9289
public ImmutableDictionary<Hardfork, uint> Hardforks { get; init; }
9390

9491
/// <summary>
@@ -149,18 +146,6 @@ public record ProtocolSettings
149146
MemoryPoolMaxTransactions = 50_000,
150147
MaxTraceableBlocks = 2_102_400,
151148
InitialGasDistribution = 52_000_000_00000000,
152-
NativeUpdateHistory = new Dictionary<string, uint[]>
153-
{
154-
[nameof(ContractManagement)] = new[] { 0u },
155-
[nameof(StdLib)] = new[] { 0u },
156-
[nameof(CryptoLib)] = new[] { 0u },
157-
[nameof(LedgerContract)] = new[] { 0u },
158-
[nameof(NeoToken)] = new[] { 0u },
159-
[nameof(GasToken)] = new[] { 0u },
160-
[nameof(PolicyContract)] = new[] { 0u },
161-
[nameof(RoleManagement)] = new[] { 0u },
162-
[nameof(OracleContract)] = new[] { 0u }
163-
},
164149
Hardforks = ImmutableDictionary<Hardfork, uint>.Empty
165150
};
166151

@@ -202,9 +187,6 @@ public static ProtocolSettings Load(IConfigurationSection section)
202187
MemoryPoolMaxTransactions = section.GetValue("MemoryPoolMaxTransactions", Default.MemoryPoolMaxTransactions),
203188
MaxTraceableBlocks = section.GetValue("MaxTraceableBlocks", Default.MaxTraceableBlocks),
204189
InitialGasDistribution = section.GetValue("InitialGasDistribution", Default.InitialGasDistribution),
205-
NativeUpdateHistory = section.GetSection("NativeUpdateHistory").Exists()
206-
? section.GetSection("NativeUpdateHistory").GetChildren().ToDictionary(p => p.Key, p => p.GetChildren().Select(q => uint.Parse(q.Value)).ToArray())
207-
: Default.NativeUpdateHistory,
208190
Hardforks = section.GetSection("Hardforks").Exists()
209191
? section.GetSection("Hardforks").GetChildren().ToImmutableDictionary(p => Enum.Parse<Hardfork>(p.Key), p => uint.Parse(p.Value))
210192
: Default.Hardforks

src/Neo/SmartContract/ApplicationEngine.Contract.cs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,7 @@ protected internal void CallNativeContract(byte version)
9595
NativeContract contract = NativeContract.GetContract(CurrentScriptHash);
9696
if (contract is null)
9797
throw new InvalidOperationException("It is not allowed to use \"System.Contract.CallNative\" directly.");
98-
uint[] updates = ProtocolSettings.NativeUpdateHistory[contract.Name];
99-
if (updates.Length == 0)
100-
throw new InvalidOperationException($"The native contract {contract.Name} is not active.");
101-
if (updates[0] > NativeContract.Ledger.CurrentIndex(Snapshot))
98+
if (!contract.IsActive(ProtocolSettings, NativeContract.Ledger.CurrentIndex(Snapshot)))
10299
throw new InvalidOperationException($"The native contract {contract.Name} is not active.");
103100
contract.Invoke(this, version);
104101
}
@@ -157,9 +154,7 @@ protected internal async void NativeOnPersist()
157154
throw new InvalidOperationException();
158155
foreach (NativeContract contract in NativeContract.Contracts)
159156
{
160-
uint[] updates = ProtocolSettings.NativeUpdateHistory[contract.Name];
161-
if (updates.Length == 0) continue;
162-
if (updates[0] <= PersistingBlock.Index)
157+
if (contract.IsActive(ProtocolSettings, PersistingBlock.Index))
163158
await contract.OnPersist(this);
164159
}
165160
}
@@ -181,9 +176,7 @@ protected internal async void NativePostPersist()
181176
throw new InvalidOperationException();
182177
foreach (NativeContract contract in NativeContract.Contracts)
183178
{
184-
uint[] updates = ProtocolSettings.NativeUpdateHistory[contract.Name];
185-
if (updates.Length == 0) continue;
186-
if (updates[0] <= PersistingBlock.Index)
179+
if (contract.IsActive(ProtocolSettings, PersistingBlock.Index))
187180
await contract.PostPersist(this);
188181
}
189182
}

src/Neo/SmartContract/Native/ContractManagement.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -106,18 +106,18 @@ internal override async ContractTask OnPersist(ApplicationEngine engine)
106106
{
107107
foreach (NativeContract contract in Contracts)
108108
{
109-
uint[] updates = engine.ProtocolSettings.NativeUpdateHistory[contract.Name];
110-
if (updates.Length == 0 || updates[0] != engine.PersistingBlock.Index)
111-
continue;
112-
engine.Snapshot.Add(CreateStorageKey(Prefix_Contract).Add(contract.Hash), new StorageItem(new ContractState
109+
if (contract.IsInitializeBlock(engine.ProtocolSettings, engine.PersistingBlock.Index))
113110
{
114-
Id = contract.Id,
115-
Nef = contract.Nef,
116-
Hash = contract.Hash,
117-
Manifest = contract.Manifest
118-
}));
119-
engine.Snapshot.Add(CreateStorageKey(Prefix_ContractHash).AddBigEndian(contract.Id), new StorageItem(contract.Hash.ToArray()));
120-
await contract.Initialize(engine);
111+
engine.Snapshot.Add(CreateStorageKey(Prefix_Contract).Add(contract.Hash), new StorageItem(new ContractState
112+
{
113+
Id = contract.Id,
114+
Nef = contract.Nef,
115+
Hash = contract.Hash,
116+
Manifest = contract.Manifest
117+
}));
118+
engine.Snapshot.Add(CreateStorageKey(Prefix_ContractHash).AddBigEndian(contract.Id), new StorageItem(contract.Hash.ToArray()));
119+
await contract.Initialize(engine);
120+
}
121121
}
122122
}
123123

src/Neo/SmartContract/Native/NativeContract.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ public abstract class NativeContract
8787
/// </summary>
8888
public string Name => GetType().Name;
8989

90+
/// <summary>
91+
/// Since Hardfork has to start having access to the native contract.
92+
/// </summary>
93+
public virtual Hardfork? ActiveIn { get; } = null;
94+
9095
/// <summary>
9196
/// The nef of the native contract.
9297
/// </summary>
@@ -160,6 +165,42 @@ protected NativeContract()
160165
contractsDictionary.Add(Hash, this);
161166
}
162167

168+
/// <summary>
169+
/// It is the initialize block
170+
/// </summary>
171+
/// <param name="settings">The <see cref="ProtocolSettings"/> where the HardForks are configured.</param>
172+
/// <param name="index">Block index</param>
173+
/// <returns>True if the native contract must be initialized</returns>
174+
internal bool IsInitializeBlock(ProtocolSettings settings, uint index)
175+
{
176+
if (ActiveIn is null) return index == 0;
177+
178+
if (!settings.Hardforks.TryGetValue(ActiveIn.Value, out var activeIn))
179+
{
180+
return false;
181+
}
182+
183+
return activeIn == index;
184+
}
185+
186+
/// <summary>
187+
/// Is the native contract active
188+
/// </summary>
189+
/// <param name="settings">The <see cref="ProtocolSettings"/> where the HardForks are configured.</param>
190+
/// <param name="index">Block index</param>
191+
/// <returns>True if the native contract is active</returns>
192+
internal bool IsActive(ProtocolSettings settings, uint index)
193+
{
194+
if (ActiveIn is null) return true;
195+
196+
if (!settings.Hardforks.TryGetValue(ActiveIn.Value, out var activeIn))
197+
{
198+
return false;
199+
}
200+
201+
return activeIn <= index;
202+
}
203+
163204
/// <summary>
164205
/// Checks whether the committee has witnessed the current transaction.
165206
/// </summary>

tests/Neo.UnitTests/UT_ProtocolSettings.cs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using FluentAssertions;
22
using Microsoft.VisualStudio.TestTools.UnitTesting;
3-
using Neo.SmartContract.Native;
43
using Neo.Wallets;
54

65
namespace Neo.UnitTests
@@ -41,11 +40,5 @@ public void TestGetSeedList()
4140
{
4241
ProtocolSettings.Default.SeedList.Should().BeEquivalentTo(new string[] { "seed1.neo.org:10333", "seed2.neo.org:10333", "seed3.neo.org:10333", "seed4.neo.org:10333", "seed5.neo.org:10333", });
4342
}
44-
45-
[TestMethod]
46-
public void TestNativeUpdateHistory()
47-
{
48-
ProtocolSettings.Default.NativeUpdateHistory.Count.Should().Be(NativeContract.Contracts.Count);
49-
}
5043
}
5144
}

0 commit comments

Comments
 (0)