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

Fix ut #3113

Merged
merged 12 commits into from
Feb 6, 2024
3 changes: 2 additions & 1 deletion benchmarks/Neo.Benchmarks/Benchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
// modifications are permitted.

using Neo.Network.P2P.Payloads;
using Neo.Persistence;
using Neo.SmartContract;
using Neo.VM;
using System.Diagnostics;
Expand All @@ -19,7 +20,7 @@ namespace Neo;
static class Benchmarks
{
private static readonly ProtocolSettings protocol = ProtocolSettings.Load("config.json");
private static readonly NeoSystem system = new(protocol);
private static readonly NeoSystem system = new(protocol, new MemoryStore());

public static void NeoIssue2725()
{
Expand Down
4 changes: 3 additions & 1 deletion src/Neo.CLI/CLI/MainService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using Neo.Ledger;
using Neo.Network.P2P;
using Neo.Network.P2P.Payloads;
using Neo.Persistence;
using Neo.Plugins;
using Neo.SmartContract;
using Neo.SmartContract.Manifest;
Expand Down Expand Up @@ -376,7 +377,8 @@ public async void Start(CommandLineOptions options)
ProtocolSettings protocol = ProtocolSettings.Load("config.json");
CustomProtocolSettings(options, protocol);
CustomApplicationSettings(options, Settings.Default);
NeoSystem = new NeoSystem(protocol, Settings.Default.Storage.Engine, string.Format(Settings.Default.Storage.Path, protocol.Network.ToString("X8")));
var store = StoreFactory.GetStore(Settings.Default.Storage.Engine, string.Format(Settings.Default.Storage.Path, protocol.Network.ToString("X8")));
NeoSystem = new NeoSystem(protocol, store);
NeoSystem.AddService(this);

LocalNode = NeoSystem.LocalNode.Ask<LocalNode>(new LocalNode.GetInstance()).Result;
Expand Down
11 changes: 4 additions & 7 deletions src/Neo/NeoSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ public class NeoSystem : IDisposable
internal RelayCache RelayCache { get; } = new(100);

private ImmutableList<object> services = ImmutableList<object>.Empty;
private readonly string storage_engine;
private readonly IStore store;
private ChannelsConfig start_message = null;
private int suspend = 0;
Expand All @@ -114,14 +113,12 @@ static NeoSystem()
/// Initializes a new instance of the <see cref="NeoSystem"/> class.
/// </summary>
/// <param name="settings">The protocol settings of the <see cref="NeoSystem"/>.</param>
/// <param name="storageEngine">The storage engine used to create the <see cref="IStore"/> 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="storageEngine"/> is the default in-memory storage engine, this parameter is ignored.</param>
public NeoSystem(ProtocolSettings settings, string storageEngine = null, string storagePath = null)
/// <param name="storage">The <see cref="IStore"/> to use.</param>
public NeoSystem(ProtocolSettings settings, IStore storage)
{
this.Settings = settings;
this.GenesisBlock = CreateGenesisBlock(settings);
this.storage_engine = storageEngine ?? nameof(MemoryStore);
this.store = LoadStore(storagePath);
this.store = storage;
this.MemPool = new MemoryPool(this);
this.Blockchain = ActorSystem.ActorOf(Ledger.Blockchain.Props(this));
this.LocalNode = ActorSystem.ActorOf(Network.P2P.LocalNode.Props(this));
Expand Down Expand Up @@ -218,7 +215,7 @@ public void EnsureStopped(IActorRef actor)
/// <returns>The loaded <see cref="IStore"/>.</returns>
public IStore LoadStore(string path)
shargon marked this conversation as resolved.
Show resolved Hide resolved
{
return StoreFactory.GetStore(storage_engine, path);
return StoreFactory.GetStore(store.GetType().Name, path);
}

/// <summary>
Expand Down
30 changes: 21 additions & 9 deletions src/Neo/Persistence/MemoryStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;

namespace Neo.Persistence
{
Expand All @@ -21,49 +22,60 @@ namespace Neo.Persistence
/// </summary>
public class MemoryStore : IStore
{
private readonly ConcurrentDictionary<byte[], byte[]> innerData = new(ByteArrayEqualityComparer.Default);
private readonly ConcurrentDictionary<byte[], byte[]> _innerData = new(ByteArrayEqualityComparer.Default);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Delete(byte[] key)
{
innerData.TryRemove(key, out _);
_innerData.TryRemove(key, out _);
}

public void Dispose()
{
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ISnapshot GetSnapshot()
{
return new MemorySnapshot(innerData);
return new MemorySnapshot(_innerData);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Put(byte[] key, byte[] value)
{
innerData[key[..]] = value[..];
_innerData[key[..]] = value[..];
}

public IEnumerable<(byte[] Key, byte[] Value)> Seek(byte[] keyOrPrefix, SeekDirection direction = SeekDirection.Forward)
{
if (direction == SeekDirection.Backward && keyOrPrefix?.Length == 0) yield break;

ByteArrayComparer comparer = direction == SeekDirection.Forward ? ByteArrayComparer.Default : ByteArrayComparer.Reverse;
IEnumerable<KeyValuePair<byte[], byte[]>> records = innerData;
var comparer = direction == SeekDirection.Forward ? ByteArrayComparer.Default : ByteArrayComparer.Reverse;
IEnumerable<KeyValuePair<byte[], byte[]>> records = _innerData;
if (keyOrPrefix?.Length > 0)
records = records.Where(p => comparer.Compare(p.Key, keyOrPrefix) >= 0);
records = records.OrderBy(p => p.Key, comparer);
foreach (var pair in records)
yield return (pair.Key[..], pair.Value[..]);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public byte[] TryGet(byte[] key)
{
innerData.TryGetValue(key, out byte[] value);
return value?[..];
if (!_innerData.TryGetValue(key, out byte[] value)) return null;
return value[..];
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(byte[] key)
{
return innerData.ContainsKey(key);
return _innerData.ContainsKey(key);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void Reset()
{
_innerData.Clear();
}
}
}
14 changes: 13 additions & 1 deletion src/Neo/Persistence/StoreFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,26 @@ private class MemoryStoreProvider : IStoreProvider

static StoreFactory()
{
RegisterProvider(new MemoryStoreProvider());
var memProvider = new MemoryStoreProvider();
RegisterProvider(memProvider);

// Default cases

providers.Add("", memProvider);
providers.Add(null, memProvider);
}

public static void RegisterProvider(IStoreProvider provider)
{
providers.Add(provider.Name, provider);
}

/// <summary>
/// Get store from name
/// </summary>
/// <param name="storageEngine">The storage engine used to create the <see cref="IStore"/> objects. If this parameter is <see langword="null"/>, a default in-memory storage engine will be used.</param>
/// <param name="path">The path of the storage. If <paramref name="storageEngine"/> is the default in-memory storage engine, this parameter is ignored.</param>
/// <returns>The storage engine.</returns>
public static IStore GetStore(string storageEngine, string path)
{
return providers[storageEngine].GetStore(path);
Expand Down
6 changes: 6 additions & 0 deletions tests/Neo.UnitTests/Ledger/UT_Blockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ public void Initialize()
system.MemPool.TryAdd(txSample, TestBlockchain.GetTestSnapshot());
}

[TestCleanup]
public void Clean()
{
TestBlockchain.ResetStore();
}

[TestMethod]
public void TestValidTransaction()
{
Expand Down
4 changes: 2 additions & 2 deletions tests/Neo.UnitTests/Ledger/UT_MemoryPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public void TestSetup()
TimeProvider.ResetToDefault();

// Create a MemoryPool with capacity of 100
_unit = new MemoryPool(new NeoSystem(TestProtocolSettings.Default with { MemoryPoolMaxTransactions = 100 }));
_unit = new MemoryPool(new NeoSystem(TestProtocolSettings.Default with { MemoryPoolMaxTransactions = 100 }, new MemoryStore()));

// Verify capacity equals the amount specified
_unit.Capacity.Should().Be(100);
Expand Down Expand Up @@ -648,7 +648,7 @@ public void TestGetVerifiedTransactions()
[TestMethod]
public void TestReVerifyTopUnverifiedTransactionsIfNeeded()
{
_unit = new MemoryPool(new NeoSystem(TestProtocolSettings.Default with { MemoryPoolMaxTransactions = 600 }));
_unit = new MemoryPool(new NeoSystem(TestProtocolSettings.Default with { MemoryPoolMaxTransactions = 600 }, new MemoryStore()));

AddTransaction(CreateTransaction(100000001));
AddTransaction(CreateTransaction(100000001));
Expand Down
6 changes: 6 additions & 0 deletions tests/Neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ public void TestSetup()
uut = new Transaction();
}

[TestCleanup]
public void Clean()
{
TestBlockchain.ResetStore();
}

[TestMethod]
public void Script_Get()
{
Expand Down
6 changes: 6 additions & 0 deletions tests/Neo.UnitTests/SmartContract/Native/UT_RoleManagement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ public void TestSetup()
_snapshot = TestBlockchain.GetTestSnapshot();
}

[TestCleanup]
public void Clean()
{
TestBlockchain.ResetStore();
}

[TestMethod]
public void TestSetAndGet()
{
Expand Down
11 changes: 10 additions & 1 deletion tests/Neo.UnitTests/TestBlockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

using Akka.Actor;
using Neo.Ledger;
using Neo.Persistence;
using System;

Expand All @@ -18,11 +20,18 @@ public static class TestBlockchain
{
public static readonly NeoSystem TheNeoSystem;
public static readonly UInt160[] DefaultExtensibleWitnessWhiteList;
private static readonly MemoryStore Store = new();

static TestBlockchain()
{
Console.WriteLine("initialize NeoSystem");
TheNeoSystem = new NeoSystem(TestProtocolSettings.Default, null, null);
TheNeoSystem = new NeoSystem(TestProtocolSettings.Default, Store);
}

internal static void ResetStore()
{
Store.Reset();
TheNeoSystem.Blockchain.Ask(new Blockchain.Initialize()).Wait();
}

internal static DataCache GetTestSnapshot()
Expand Down
9 changes: 0 additions & 9 deletions tests/Neo.UnitTests/Wallets/UT_Wallet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -221,13 +221,11 @@ public void TestGetAvailable()
var key = NativeContract.GAS.CreateStorageKey(20, account.ScriptHash);
var entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState()));
entry.GetInteroperable<AccountState>().Balance = 10000 * NativeContract.GAS.Factor;
snapshot.Commit();

wallet.GetAvailable(snapshot, NativeContract.GAS.Hash).Should().Be(new BigDecimal(new BigInteger(1000000000000M), 8));

entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState()));
entry.GetInteroperable<AccountState>().Balance = 0;
snapshot.Commit();
}

[TestMethod]
Expand All @@ -243,14 +241,12 @@ public void TestGetBalance()
var key = NativeContract.GAS.CreateStorageKey(20, account.ScriptHash);
var entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState()));
entry.GetInteroperable<AccountState>().Balance = 10000 * NativeContract.GAS.Factor;
snapshot.Commit();

wallet.GetBalance(snapshot, UInt160.Zero, new UInt160[] { account.ScriptHash }).Should().Be(new BigDecimal(BigInteger.Zero, 0));
wallet.GetBalance(snapshot, NativeContract.GAS.Hash, new UInt160[] { account.ScriptHash }).Should().Be(new BigDecimal(new BigInteger(1000000000000M), 8));

entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState()));
entry.GetInteroperable<AccountState>().Balance = 0;
snapshot.Commit();
}

[TestMethod]
Expand Down Expand Up @@ -345,8 +341,6 @@ public void TestMakeTransaction1()
var entry2 = snapshot.GetAndChange(key, () => new StorageItem(new NeoToken.NeoAccountState()));
entry2.GetInteroperable<NeoToken.NeoAccountState>().Balance = 10000 * NativeContract.NEO.Factor;

snapshot.Commit();

var tx = wallet.MakeTransaction(snapshot, new TransferOutput[]
{
new TransferOutput()
Expand Down Expand Up @@ -374,7 +368,6 @@ public void TestMakeTransaction1()
entry2 = snapshot.GetAndChange(key, () => new StorageItem(new AccountState()));
entry1.GetInteroperable<AccountState>().Balance = 0;
entry2.GetInteroperable<NeoToken.NeoAccountState>().Balance = 0;
snapshot.Commit();
}

[TestMethod]
Expand All @@ -393,7 +386,6 @@ public void TestMakeTransaction2()
var key = NativeContract.GAS.CreateStorageKey(20, account.ScriptHash);
var entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState()));
entry.GetInteroperable<AccountState>().Balance = 1000000 * NativeContract.GAS.Factor;
snapshot.Commit();

var tx = wallet.MakeTransaction(snapshot, Array.Empty<byte>(), account.ScriptHash, new[]{ new Signer()
{
Expand All @@ -408,7 +400,6 @@ public void TestMakeTransaction2()

entry = snapshot.GetAndChange(key, () => new StorageItem(new AccountState()));
entry.GetInteroperable<AccountState>().Balance = 0;
snapshot.Commit();
}

[TestMethod]
Expand Down