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

Allow Native Contracts to be updated #2942

Merged
merged 64 commits into from
Feb 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
24b181f
Update manifest
shargon Nov 5, 2023
3c6a1f0
Fix comment
shargon Nov 5, 2023
a5772bc
Format & fix methods
shargon Nov 5, 2023
95335e0
Fix new
shargon Nov 5, 2023
7ae51e1
Initialize storage fixes
shargon Nov 5, 2023
22d72b5
Fix IsInitializeBlock
shargon Nov 5, 2023
c7602c6
Fix update
shargon Nov 5, 2023
b573a00
Fix GetContractState
shargon Nov 5, 2023
3adddd2
Optimize
shargon Nov 5, 2023
984d3d7
Fix first invoke without sync
shargon Nov 5, 2023
6341bad
Remove current methods
shargon Nov 6, 2023
4f59c43
Clean usings
shargon Nov 6, 2023
c85a1cc
Improve reading Initialize
shargon Nov 6, 2023
2490280
Clean OnManifestCompose
shargon Nov 6, 2023
47317ee
Use cache for all native contracts
shargon Nov 6, 2023
8fd8fc2
Fix ut
shargon Nov 6, 2023
7ba6274
Move cache to ApplicationEngine
shargon Nov 6, 2023
67a9364
Clean code
shargon Nov 6, 2023
8eb82db
Allow nullable attribute
shargon Nov 6, 2023
8667047
Update src/Neo/SmartContract/Native/ContractEventAttribute.cs
Jim8y Nov 6, 2023
5f41acf
Merge branch 'master' into update-native-contracts
Jim8y Nov 7, 2023
ed33b32
Add base call
shargon Nov 7, 2023
eea7324
Merge branch 'update-native-contracts' of https://github.com/neo-proj…
shargon Nov 7, 2023
594c2e6
Fix one https://github.com/neo-project/neo/pull/2941#discussion_r1382…
shargon Nov 7, 2023
64e5cfc
Fix IsInitializeBlock https://github.com/neo-project/neo/pull/2941#di…
shargon Nov 7, 2023
1b210ce
Add ContractEventAttribute constructors for ActiveIn
shargon Nov 7, 2023
5bb42d2
Merge branch 'master' into update-native-contracts
shargon Nov 8, 2023
690b5d4
Ensure ommited hfs
shargon Nov 8, 2023
8cef6ce
Rename
shargon Nov 8, 2023
f114982
Case insensitive hf config
shargon Nov 8, 2023
4e27f15
Merge branch 'master' into update-native-contracts
Jim8y Nov 8, 2023
1fee32f
Increase coverage
shargon Nov 9, 2023
957a507
Merge branch 'update-native-contracts' of https://github.com/neo-proj…
shargon Nov 9, 2023
06f1b23
More uts
shargon Nov 9, 2023
aee4be3
Rename
shargon Nov 9, 2023
c4b4a88
Update src/Neo/SmartContract/Native/ContractManagement.cs
shargon Nov 9, 2023
c5ebf3f
Merge branch 'master' into update-native-contracts
shargon Nov 9, 2023
28ac4e6
format code
shargon Nov 10, 2023
ff852a3
Fix ProtocolSettings
shargon Nov 10, 2023
f2586ed
Merge branch 'master' into update-native-contracts
shargon Nov 10, 2023
53e15b3
Merge branch 'master' into update-native-contracts
shargon Nov 11, 2023
8b4d596
Merge branch 'master' into update-native-contracts
shargon Dec 7, 2023
405a816
Update src/Neo/SmartContract/ApplicationEngine.cs
shargon Dec 11, 2023
4f9739d
Merge branch 'master' into update-native-contracts
shargon Jan 2, 2024
d621476
format
shargon Jan 2, 2024
4ade232
reorder using
shargon Jan 2, 2024
baa7807
Merge branch 'master' into update-native-contracts
Jim8y Jan 3, 2024
487f4ac
Fix UT
shargon Jan 3, 2024
963c557
Merge branch 'master' into update-native-contracts
shargon Jan 11, 2024
8c9e0c6
Adding keccak256 (#2925)
Jim8y Jan 11, 2024
7a8bb33
Merge branch 'master' into update-native-contracts
Jim8y Feb 4, 2024
d45fc30
Merge branch 'master' into update-native-contracts
shargon Feb 7, 2024
c7f0209
Merge branch 'master' into update-native-contracts
shargon Feb 7, 2024
6b0916d
Merge branch 'master' into update-native-contracts
shargon Feb 8, 2024
c13575c
Fix net standard
shargon Feb 8, 2024
5940271
Merge branch 'master' into update-native-contracts
Jim8y Feb 12, 2024
48d2349
Merge branch 'master' into update-native-contracts
shargon Feb 18, 2024
41914d8
Add ut
shargon Feb 19, 2024
e87e2b2
Fix update
shargon Feb 19, 2024
447583f
Merge branch 'master' into update-native-contracts
shargon Feb 20, 2024
d00f510
Merge branch 'master' into update-native-contracts
shargon Feb 21, 2024
8bcda87
Fix update
shargon Feb 21, 2024
40c5d97
Merge branch 'master' into update-native-contracts
shargon Feb 23, 2024
ef43618
Merge branch 'master' into update-native-contracts
shargon Feb 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/Neo/Hardfork.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace Neo
public enum Hardfork : byte
{
HF_Aspidochelone,
HF_Basilisk
HF_Basilisk,
HF_Cockatrice
}
}
3 changes: 2 additions & 1 deletion src/Neo/NeoSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@
/// <param name="settings">The protocol settings of the <see cref="NeoSystem"/>.</param>
/// <param name="storageProvider">The storage engine used to create the <see cref="IStoreProvider"/> objects. If this parameter is <see langword="null"/>, a default in-memory storage engine will be used.</param>
/// <param name="storagePath">The path of the storage. If <paramref name="storageProvider"/> is the default in-memory storage engine, this parameter is ignored.</param>
public NeoSystem(ProtocolSettings settings, string? storageProvider = null, string? storagePath = null) :

Check warning on line 119 in src/Neo/NeoSystem.cs

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 119 in src/Neo/NeoSystem.cs

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 119 in src/Neo/NeoSystem.cs

View workflow job for this annotation

GitHub Actions / Test (windows-latest)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 119 in src/Neo/NeoSystem.cs

View workflow job for this annotation

GitHub Actions / Test (windows-latest)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 119 in src/Neo/NeoSystem.cs

View workflow job for this annotation

GitHub Actions / Test (macos-latest)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 119 in src/Neo/NeoSystem.cs

View workflow job for this annotation

GitHub Actions / Test (macos-latest)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
this(settings, StoreFactory.GetStoreProvider(storageProvider ?? nameof(MemoryStore)), storagePath)
this(settings, StoreFactory.GetStoreProvider(storageProvider ?? nameof(MemoryStore))
?? throw new ArgumentException($"Can't find the storage provider {storageProvider}", nameof(storageProvider)), storagePath)
{
}

Expand All @@ -127,7 +128,7 @@
/// <param name="settings">The protocol settings of the <see cref="NeoSystem"/>.</param>
/// <param name="storageProvider">The <see cref="IStoreProvider"/> to use.</param>
/// <param name="storagePath">The path of the storage. If <paramref name="storageProvider"/> is the default in-memory storage engine, this parameter is ignored.</param>
public NeoSystem(ProtocolSettings settings, IStoreProvider storageProvider, string? storagePath = null)

Check warning on line 131 in src/Neo/NeoSystem.cs

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 131 in src/Neo/NeoSystem.cs

View workflow job for this annotation

GitHub Actions / Test (windows-latest)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 131 in src/Neo/NeoSystem.cs

View workflow job for this annotation

GitHub Actions / Test (macos-latest)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
{
this.Settings = settings;
this.GenesisBlock = CreateGenesisBlock(settings);
Expand Down
2 changes: 1 addition & 1 deletion src/Neo/Persistence/DataCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public void Add(StorageKey key, StorageItem value)
{
TrackState.Deleted => TrackState.Changed,
TrackState.NotFound => TrackState.Added,
_ => throw new ArgumentException()
_ => throw new ArgumentException($"The element currently has state {trackable.State}")
};
}
else
Expand Down
52 changes: 47 additions & 5 deletions src/Neo/ProtocolSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
/// </summary>
public record ProtocolSettings
{
private static readonly IList<Hardfork> AllHardforks = Enum.GetValues(typeof(Hardfork)).Cast<Hardfork>().ToArray();

/// <summary>
/// The magic number of the NEO network.
/// </summary>
Expand Down Expand Up @@ -115,10 +117,10 @@
MemoryPoolMaxTransactions = 50_000,
MaxTraceableBlocks = 2_102_400,
InitialGasDistribution = 52_000_000_00000000,
Hardforks = ImmutableDictionary<Hardfork, uint>.Empty
Hardforks = EnsureOmmitedHardforks(new Dictionary<Hardfork, uint>()).ToImmutableDictionary()
};

public static ProtocolSettings? Custom { get; set; }

Check warning on line 123 in src/Neo/ProtocolSettings.cs

View workflow job for this annotation

GitHub Actions / Test (ubuntu-latest)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 123 in src/Neo/ProtocolSettings.cs

View workflow job for this annotation

GitHub Actions / Test (windows-latest)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

Check warning on line 123 in src/Neo/ProtocolSettings.cs

View workflow job for this annotation

GitHub Actions / Test (macos-latest)

The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.

/// <summary>
/// Loads the <see cref="ProtocolSettings"/> at the specified path.
Expand Down Expand Up @@ -159,17 +161,39 @@
MaxTraceableBlocks = section.GetValue("MaxTraceableBlocks", Default.MaxTraceableBlocks),
InitialGasDistribution = section.GetValue("InitialGasDistribution", Default.InitialGasDistribution),
Hardforks = section.GetSection("Hardforks").Exists()
? section.GetSection("Hardforks").GetChildren().ToImmutableDictionary(p => Enum.Parse<Hardfork>(p.Key), p => uint.Parse(p.Value))
? EnsureOmmitedHardforks(section.GetSection("Hardforks").GetChildren().ToDictionary(p => Enum.Parse<Hardfork>(p.Key, true), p => uint.Parse(p.Value))).ToImmutableDictionary()
: Default.Hardforks
};
}

/// <summary>
/// Explicitly set the height of all old omitted hardforks to 0 for proper IsHardforkEnabled behaviour.
Copy link
Member

Choose a reason for hiding this comment

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

For compatibility reasons, explicitly set the height of HF_Aspidochelone and HF_Basilisk hardforks to 0 for proper IsHardforkEnabled behaviour.

Copy link
Member

Choose a reason for hiding this comment

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

Maybe directly explain that, because this will be just for these two, right?

/// </summary>
/// <param name="hardForks">HardForks</param>
/// <returns>Processed hardfork configuration</returns>
private static Dictionary<Hardfork, uint> EnsureOmmitedHardforks(Dictionary<Hardfork, uint> hardForks)
{
foreach (Hardfork hf in AllHardforks)
{
if (!hardForks.ContainsKey(hf))
{
hardForks[hf] = 0;
}
else
{
break;
}
}

return hardForks;
}
shargon marked this conversation as resolved.
Show resolved Hide resolved

private static void CheckingHardfork(ProtocolSettings settings)
{
var allHardforks = Enum.GetValues(typeof(Hardfork)).Cast<Hardfork>().ToList();
// Check for continuity in configured hardforks
var sortedHardforks = settings.Hardforks.Keys
.OrderBy(h => allHardforks.IndexOf(h))
.OrderBy(allHardforks.IndexOf)
.ToList();

for (int i = 0; i < sortedHardforks.Count - 1; i++)
Expand All @@ -179,17 +203,35 @@

// If they aren't consecutive, return false.
if (nextIndex - currentIndex > 1)
throw new Exception("Hardfork configuration is not continuous.");
throw new ArgumentException("Hardfork configuration is not continuous.");
}
// Check that block numbers are not higher in earlier hardforks than in later ones
for (int i = 0; i < sortedHardforks.Count - 1; i++)
{
if (settings.Hardforks[sortedHardforks[i]] > settings.Hardforks[sortedHardforks[i + 1]])
{
// This means the block number for the current hardfork is greater than the next one, which should not be allowed.
throw new Exception($"The Hardfork configuration for {sortedHardforks[i]} is greater than for {sortedHardforks[i + 1]}");
throw new ArgumentException($"The Hardfork configuration for {sortedHardforks[i]} is greater than for {sortedHardforks[i + 1]}");
}
}
}

/// <summary>
/// Check if the Hardfork is Enabled
/// </summary>
/// <param name="hardfork">Hardfork</param>
/// <param name="index">Block index</param>
/// <returns>True if enabled</returns>
public bool IsHardforkEnabled(Hardfork hardfork, uint index)
{
if (Hardforks.TryGetValue(hardfork, out uint height))
shargon marked this conversation as resolved.
Show resolved Hide resolved
{
// If the hardfork has a specific height in the configuration, check the block height.
return index >= height;
}

// If the hardfork isn't specified in the configuration, return false.
return false;
}
shargon marked this conversation as resolved.
Show resolved Hide resolved
}
}
45 changes: 23 additions & 22 deletions src/Neo/SmartContract/ApplicationEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ public partial class ApplicationEngine : ExecutionEngine
/// </summary>
public static event EventHandler<LogEventArgs> Log;

private static readonly IList<Hardfork> AllHardforks = Enum.GetValues(typeof(Hardfork)).Cast<Hardfork>().ToArray();
private static Dictionary<uint, InteropDescriptor> services;
private readonly long gas_amount;
private Dictionary<Type, object> states;
Expand Down Expand Up @@ -647,6 +646,25 @@ public T GetState<T>()
return (T)state;
}

public T GetState<T>(Func<T> factory)
{
if (states is null)
{
T state = factory();
SetState(state);
return state;
}
else
{
if (!states.TryGetValue(typeof(T), out object state))
{
state = factory();
SetState(state);
}
return (T)state;
}
}

public void SetState<T>(T state)
{
states ??= new Dictionary<Type, object>();
Expand All @@ -655,28 +673,11 @@ public void SetState<T>(T state)

public bool IsHardforkEnabled(Hardfork hardfork)
{
// Return true if there's no specific configuration or PersistingBlock is null
if (PersistingBlock is null || ProtocolSettings.Hardforks.Count == 0)
return true;

// If the hardfork isn't specified in the configuration, check if it's a new one.
if (!ProtocolSettings.Hardforks.ContainsKey(hardfork))
{
int currentHardforkIndex = AllHardforks.IndexOf(hardfork);
int lastConfiguredHardforkIndex = AllHardforks.IndexOf(ProtocolSettings.Hardforks.Keys.Last());
// Return true if PersistingBlock is null and Hardfork is enabled
if (PersistingBlock is null)
return ProtocolSettings.Hardforks.ContainsKey(hardfork);

// If it's a newer hardfork compared to the ones in the configuration, disable it.
if (currentHardforkIndex > lastConfiguredHardforkIndex)
return false;
}

if (ProtocolSettings.Hardforks.TryGetValue(hardfork, out uint height))
{
// If the hardfork has a specific height in the configuration, check the block height.
return PersistingBlock.Index >= height;
}
// If no specific conditions are met, return true.
return true;
return ProtocolSettings.IsHardforkEnabled(hardfork, PersistingBlock.Index);
}
}
}
165 changes: 165 additions & 0 deletions src/Neo/SmartContract/Native/ContractEventAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
// Copyright (C) 2015-2024 The Neo Project.
shargon marked this conversation as resolved.
Show resolved Hide resolved
//
// ContractEventAttribute.cs file belongs to the neo project and is free
// software distributed under the MIT software license, see the
// accompanying file LICENSE in the main directory of the
// repository or http://www.opensource.org/licenses/mit-license.php
// for more details.
//
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

using Neo.SmartContract.Manifest;
using System;
using System.Diagnostics;

namespace Neo.SmartContract.Native
{
[DebuggerDisplay("{Descriptor.Name}")]
[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = true)]
internal class ContractEventAttribute : Attribute
{
public int Order { get; init; }
public ContractEventDescriptor Descriptor { get; set; }
public Hardfork? ActiveIn { get; init; } = null;

public ContractEventAttribute(Hardfork activeIn, int order, string name,
string arg1Name, ContractParameterType arg1Value) : this(order, name, arg1Name, arg1Value)
{
ActiveIn = activeIn;
}

public ContractEventAttribute(int order, string name, string arg1Name, ContractParameterType arg1Value)
{
Order = order;
Descriptor = new ContractEventDescriptor()
{
Name = name,
Parameters = new ContractParameterDefinition[]
{
new ContractParameterDefinition()
{
Name = arg1Name,
Type = arg1Value
}
}
};
}

public ContractEventAttribute(Hardfork activeIn, int order, string name,
string arg1Name, ContractParameterType arg1Value,
string arg2Name, ContractParameterType arg2Value) : this(order, name, arg1Name, arg1Value, arg2Name, arg2Value)
{
ActiveIn = activeIn;
}

public ContractEventAttribute(int order, string name,
string arg1Name, ContractParameterType arg1Value,
string arg2Name, ContractParameterType arg2Value)
{
Order = order;
Descriptor = new ContractEventDescriptor()
{
Name = name,
Parameters = new ContractParameterDefinition[]
{
new ContractParameterDefinition()
{
Name = arg1Name,
Type = arg1Value
},
new ContractParameterDefinition()
{
Name = arg2Name,
Type = arg2Value
}
}
};
}

public ContractEventAttribute(Hardfork activeIn, int order, string name,
string arg1Name, ContractParameterType arg1Value,
string arg2Name, ContractParameterType arg2Value,
string arg3Name, ContractParameterType arg3Value) : this(order, name, arg1Name, arg1Value, arg2Name, arg2Value, arg3Name, arg3Value)
{
ActiveIn = activeIn;
}

public ContractEventAttribute(int order, string name,
string arg1Name, ContractParameterType arg1Value,
string arg2Name, ContractParameterType arg2Value,
string arg3Name, ContractParameterType arg3Value
)
{
Order = order;
Descriptor = new ContractEventDescriptor()
{
Name = name,
Parameters = new ContractParameterDefinition[]
{
new ContractParameterDefinition()
{
Name = arg1Name,
Type = arg1Value
},
new ContractParameterDefinition()
{
Name = arg2Name,
Type = arg2Value
},
new ContractParameterDefinition()
{
Name = arg3Name,
Type = arg3Value
}
}
};
}

public ContractEventAttribute(Hardfork activeIn, int order, string name,
string arg1Name, ContractParameterType arg1Value,
string arg2Name, ContractParameterType arg2Value,
string arg3Name, ContractParameterType arg3Value,
string arg4Name, ContractParameterType arg4Value) : this(order, name, arg1Name, arg1Value, arg2Name, arg2Value, arg3Name, arg3Value, arg4Name, arg4Value)
{
ActiveIn = activeIn;
}

public ContractEventAttribute(int order, string name,
string arg1Name, ContractParameterType arg1Value,
string arg2Name, ContractParameterType arg2Value,
string arg3Name, ContractParameterType arg3Value,
string arg4Name, ContractParameterType arg4Value
)
{
Order = order;
Descriptor = new ContractEventDescriptor()
{
Name = name,
Parameters = new ContractParameterDefinition[]
{
new ContractParameterDefinition()
{
Name = arg1Name,
Type = arg1Value
},
new ContractParameterDefinition()
{
Name = arg2Name,
Type = arg2Value
},
new ContractParameterDefinition()
{
Name = arg3Name,
Type = arg3Value
},
new ContractParameterDefinition()
{
Name = arg4Name,
Type = arg4Value
}
}
};
}
}
}
Loading
Loading