From 77363cc6dba3277df932f4ee0f91eac06741d7b6 Mon Sep 17 00:00:00 2001
From: Shargon
Date: Tue, 4 Jun 2019 23:00:11 +0200
Subject: [PATCH 001/305] Show hash on sendrawtransaction (#796)
* Show hash on sendrawtransaction
* Update RpcServer.cs
* txid
* relayed
* Revert to hash
* txid -> hash
* Update RpcServer.cs
* Fix test
---
neo.UnitTests/UT_Block.cs | 9 ++-------
neo.UnitTests/UT_Transaction.cs | 2 +-
neo/Network/P2P/Payloads/Transaction.cs | 2 +-
neo/Network/RPC/RpcServer.cs | 12 ++++++++----
4 files changed, 12 insertions(+), 13 deletions(-)
diff --git a/neo.UnitTests/UT_Block.cs b/neo.UnitTests/UT_Block.cs
index c0c1163d5e..f7acf254be 100644
--- a/neo.UnitTests/UT_Block.cs
+++ b/neo.UnitTests/UT_Block.cs
@@ -240,12 +240,7 @@ public void RebuildMerkleRoot_Updates()
public void ToJson()
{
UInt256 val256 = UInt256.Zero;
- UInt256 merkRoot;
- UInt160 val160;
- uint timestampVal, indexVal;
- Witness scriptVal;
- Transaction[] transactionsVal;
- TestUtils.SetupBlockWithValues(uut, val256, out merkRoot, out val160, out timestampVal, out indexVal, out scriptVal, out transactionsVal, 1);
+ TestUtils.SetupBlockWithValues(uut, val256, out var merkRoot, out var val160, out var timestampVal, out var indexVal, out var scriptVal, out var transactionsVal, 1);
JObject jObj = uut.ToJson();
jObj.Should().NotBeNull();
@@ -264,7 +259,7 @@ public void ToJson()
jObj["tx"].Should().NotBeNull();
JArray txObj = (JArray)jObj["tx"];
- txObj[0]["txid"].AsString().Should().Be("0x7647acf1ef8a841b87f2369398a0e9f0ccde0ed9e835d980657103da6da59580");
+ txObj[0]["hash"].AsString().Should().Be("0x7647acf1ef8a841b87f2369398a0e9f0ccde0ed9e835d980657103da6da59580");
txObj[0]["size"].AsNumber().Should().Be(50);
txObj[0]["version"].AsNumber().Should().Be(0);
((JArray)txObj[0]["attributes"]).Count.Should().Be(0);
diff --git a/neo.UnitTests/UT_Transaction.cs b/neo.UnitTests/UT_Transaction.cs
index 2600867986..b192a2479d 100644
--- a/neo.UnitTests/UT_Transaction.cs
+++ b/neo.UnitTests/UT_Transaction.cs
@@ -82,7 +82,7 @@ public void ToJson()
JObject jObj = uut.ToJson();
jObj.Should().NotBeNull();
- jObj["txid"].AsString().Should().Be("0x38274692538dfecaae36f8fd518d92bae25607d491c40a8f927cc06bd97ab2c8");
+ jObj["hash"].AsString().Should().Be("0x38274692538dfecaae36f8fd518d92bae25607d491c40a8f927cc06bd97ab2c8");
jObj["size"].AsNumber().Should().Be(81);
jObj["version"].AsNumber().Should().Be(0);
((JArray)jObj["attributes"]).Count.Should().Be(0);
diff --git a/neo/Network/P2P/Payloads/Transaction.cs b/neo/Network/P2P/Payloads/Transaction.cs
index 52a6fc867a..b21f02ccbb 100644
--- a/neo/Network/P2P/Payloads/Transaction.cs
+++ b/neo/Network/P2P/Payloads/Transaction.cs
@@ -176,7 +176,7 @@ void IVerifiable.SerializeUnsigned(BinaryWriter writer)
public JObject ToJson()
{
JObject json = new JObject();
- json["txid"] = Hash.ToString();
+ json["hash"] = Hash.ToString();
json["size"] = Size;
json["version"] = Version;
json["nonce"] = Nonce;
diff --git a/neo/Network/RPC/RpcServer.cs b/neo/Network/RPC/RpcServer.cs
index 6b5e7f549d..6bfdd15618 100644
--- a/neo/Network/RPC/RpcServer.cs
+++ b/neo/Network/RPC/RpcServer.cs
@@ -90,12 +90,16 @@ private JObject GetInvokeResult(byte[] script)
return json;
}
- private static JObject GetRelayResult(RelayResultReason reason)
+ private static JObject GetRelayResult(RelayResultReason reason, UInt256 hash)
{
switch (reason)
{
case RelayResultReason.Succeed:
- return true;
+ {
+ var ret = new JObject();
+ ret["hash"] = hash.ToString();
+ return ret;
+ }
case RelayResultReason.AlreadyExists:
throw new RpcException(-501, "Block or transaction already exists and cannot be sent repeatedly.");
case RelayResultReason.OutOfMemory:
@@ -606,13 +610,13 @@ private JObject ListPlugins()
private JObject SendRawTransaction(Transaction tx)
{
RelayResultReason reason = system.Blockchain.Ask(tx).Result;
- return GetRelayResult(reason);
+ return GetRelayResult(reason, tx.Hash);
}
private JObject SubmitBlock(Block block)
{
RelayResultReason reason = system.Blockchain.Ask(block).Result;
- return GetRelayResult(reason);
+ return GetRelayResult(reason, block.Hash);
}
private JObject ValidateAddress(string address)
From 94070491ee57bf11e18f27baeb473cbbe7e1c1d3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vitor=20Naz=C3=A1rio=20Coelho?=
Date: Mon, 10 Jun 2019 06:15:31 -0300
Subject: [PATCH 002/305] Drop invalid messages and set low priority (3.x)
(#805)
---
neo/Network/P2P/ProtocolHandler.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/neo/Network/P2P/ProtocolHandler.cs b/neo/Network/P2P/ProtocolHandler.cs
index 099b2d6dca..487efda6dd 100644
--- a/neo/Network/P2P/ProtocolHandler.cs
+++ b/neo/Network/P2P/ProtocolHandler.cs
@@ -309,7 +309,7 @@ public ProtocolHandlerMailbox(Settings settings, Config config)
protected override bool IsHighPriority(object message)
{
- if (!(message is Message msg)) return true;
+ if (!(message is Message msg)) return false;
switch (msg.Command)
{
case MessageCommand.Consensus:
@@ -327,7 +327,7 @@ protected override bool IsHighPriority(object message)
protected override bool ShallDrop(object message, IEnumerable queue)
{
- if (!(message is Message msg)) return false;
+ if (!(message is Message msg)) return true;
switch (msg.Command)
{
case MessageCommand.GetAddr:
From 7dc1b56b4228d31e5b494239e79a90633023b4fa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vitor=20Naz=C3=A1rio=20Coelho?=
Date: Tue, 11 Jun 2019 17:04:02 -0300
Subject: [PATCH 003/305] Test travis with most recent dotnet (#815)
---
.travis.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index 760992a634..516dd5855c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,7 +8,7 @@ dist: bionic
osx_image: xcode9.1
mono: none
-dotnet: 2.1.502
+dotnet: 2.2.300
before_install:
- cd neo.UnitTests
From 29bdd9d8a24abb6ce0164c74371609160e1e60ed Mon Sep 17 00:00:00 2001
From: Alvaro Diaz
Date: Tue, 11 Jun 2019 22:19:41 +0200
Subject: [PATCH 004/305] Create SECURITY.md (#811)
---
SECURITY.md | 13 +++++++++++++
1 file changed, 13 insertions(+)
create mode 100644 SECURITY.md
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 0000000000..24894d5e9a
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,13 @@
+# Security Policy
+
+The purpose of NEO vulnerability bounty program is to be proactive about blockchain security by providing a channel for security researchers to report potential security vulnerabilities identified related to our underlying infrastructure.
+
+First, it is recommended to read the following page https://neo.org/dev/bounty, if you find a security vulnerability in NEO, please report it as indicated on that page.
+
+Please withhold public disclosure until the security team has addressed the vulnerability and it has been solved.
+
+We appreciate your efforts to responsibly disclose your findings, and we will make every effort to acknowledge your contributions.
+
+The security team will acknowledge your email within 5 business days. You will receive a more detailed response within 10 business days.
+
+When in doubt, please do send us a report.
From fa8b85fd321e70ec5862cd91045676d075c7ea40 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vitor=20Naz=C3=A1rio=20Coelho?=
Date: Tue, 11 Jun 2019 17:54:26 -0300
Subject: [PATCH 005/305] Declaring timeout variables for connection (#807)
* Declaring timeout variables for connection
* Improving comments
---
neo/Network/P2P/Connection.cs | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/neo/Network/P2P/Connection.cs b/neo/Network/P2P/Connection.cs
index a6ae95f8f5..b7a007ad62 100644
--- a/neo/Network/P2P/Connection.cs
+++ b/neo/Network/P2P/Connection.cs
@@ -19,12 +19,20 @@ public abstract class Connection : UntypedActor
private readonly IActorRef tcp;
private readonly WebSocket ws;
private bool disconnected = false;
+ ///
+ /// connection initial timeout (in seconds) before any package has been accepted
+ ///
+ private double connectionTimeoutLimitStart = 10;
+ ///
+ /// connection timeout (in seconds) after every `OnReceived(ByteString data)` event
+ ///
+ private double connectionTimeoutLimit = 60;
protected Connection(object connection, IPEndPoint remote, IPEndPoint local)
{
this.Remote = remote;
this.Local = local;
- this.timer = Context.System.Scheduler.ScheduleTellOnceCancelable(TimeSpan.FromSeconds(10), Self, Timer.Instance, ActorRefs.NoSender);
+ this.timer = Context.System.Scheduler.ScheduleTellOnceCancelable(TimeSpan.FromSeconds(connectionTimeoutLimitStart), Self, Timer.Instance, ActorRefs.NoSender);
switch (connection)
{
case IActorRef tcp:
@@ -100,7 +108,7 @@ protected override void OnReceive(object message)
private void OnReceived(ByteString data)
{
timer.CancelIfNotNull();
- timer = Context.System.Scheduler.ScheduleTellOnceCancelable(TimeSpan.FromMinutes(1), Self, Timer.Instance, ActorRefs.NoSender);
+ timer = Context.System.Scheduler.ScheduleTellOnceCancelable(TimeSpan.FromSeconds(connectionTimeoutLimit), Self, Timer.Instance, ActorRefs.NoSender);
try
{
OnData(data);
From b6b4c89c790a4bed3c63f7c494577d1a53ad6adc Mon Sep 17 00:00:00 2001
From: Shine Li
Date: Thu, 13 Jun 2019 01:00:26 +0800
Subject: [PATCH 006/305] change load method (#816)
---
neo/Plugins/Plugin.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/neo/Plugins/Plugin.cs b/neo/Plugins/Plugin.cs
index 59699e7562..862ff6ae9a 100644
--- a/neo/Plugins/Plugin.cs
+++ b/neo/Plugins/Plugin.cs
@@ -97,7 +97,8 @@ internal static void LoadPlugins(NeoSystem system)
if (!Directory.Exists(pluginsPath)) return;
foreach (string filename in Directory.EnumerateFiles(pluginsPath, "*.dll", SearchOption.TopDirectoryOnly))
{
- Assembly assembly = Assembly.LoadFile(filename);
+ var file = File.ReadAllBytes(filename);
+ Assembly assembly = Assembly.Load(file);
foreach (Type type in assembly.ExportedTypes)
{
if (!type.IsSubclassOf(typeof(Plugin))) continue;
From e9633788c0f13279f3e99fd4bcbbbdc84c93520a Mon Sep 17 00:00:00 2001
From: Igor Machado Coelho
Date: Wed, 12 Jun 2019 14:58:04 -0300
Subject: [PATCH 007/305] Tests for ProtocolHandler Mailboxes (Neo 3.x) (#809)
* tests for mailboxes on 3x
* Fixing UT to MessageCommand
* Fixing string
* Explicit Byte
* MessageCommand with random byte
* space
* testing all cases
* Update UT_ConsensusServiceMailbox.cs
* Update UT_RemoteNodeMailbox.cs
* Update UT_TaskManagerMailbox.cs
---
neo.UnitTests/UT_ConsensusServiceMailbox.cs | 37 ++++
neo.UnitTests/UT_ProtocolHandlerMailbox.cs | 194 ++++++++++++++++++++
neo.UnitTests/UT_RemoteNodeMailbox.cs | 36 ++++
neo.UnitTests/UT_TaskManagerMailbox.cs | 36 ++++
neo/Consensus/ConsensusService.cs | 2 +-
neo/IO/Actors/PriorityMailbox.cs | 4 +-
neo/Ledger/Blockchain.cs | 2 +-
neo/Network/P2P/ProtocolHandler.cs | 4 +-
neo/Network/P2P/RemoteNode.cs | 2 +-
neo/Network/P2P/TaskManager.cs | 2 +-
10 files changed, 311 insertions(+), 8 deletions(-)
create mode 100644 neo.UnitTests/UT_ConsensusServiceMailbox.cs
create mode 100644 neo.UnitTests/UT_ProtocolHandlerMailbox.cs
create mode 100644 neo.UnitTests/UT_RemoteNodeMailbox.cs
create mode 100644 neo.UnitTests/UT_TaskManagerMailbox.cs
diff --git a/neo.UnitTests/UT_ConsensusServiceMailbox.cs b/neo.UnitTests/UT_ConsensusServiceMailbox.cs
new file mode 100644
index 0000000000..de0d02cf2e
--- /dev/null
+++ b/neo.UnitTests/UT_ConsensusServiceMailbox.cs
@@ -0,0 +1,37 @@
+using Akka.TestKit;
+using Akka.TestKit.Xunit2;
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using Moq;
+using Neo.Ledger;
+using Neo.Network.P2P.Payloads;
+using Neo.Network.P2P;
+using Akka.Configuration;
+using Neo.Consensus;
+
+namespace Neo.UnitTests
+{
+ [TestClass]
+ public class UT_ConsensusServiceMailbox : TestKit
+ {
+ private static readonly Random TestRandom = new Random(1337); // use fixed seed for guaranteed determinism
+
+ ConsensusServiceMailbox uut;
+
+ [TestCleanup]
+ public void Cleanup()
+ {
+ Shutdown();
+ }
+
+ [TestInitialize]
+ public void TestSetup()
+ {
+ Akka.Actor.ActorSystem system = Sys;
+ var config = TestKit.DefaultConfig;
+ var akkaSettings = new Akka.Actor.Settings(system, config);
+ uut = new ConsensusServiceMailbox(akkaSettings, config);
+ }
+ }
+}
diff --git a/neo.UnitTests/UT_ProtocolHandlerMailbox.cs b/neo.UnitTests/UT_ProtocolHandlerMailbox.cs
new file mode 100644
index 0000000000..4645e3cfdc
--- /dev/null
+++ b/neo.UnitTests/UT_ProtocolHandlerMailbox.cs
@@ -0,0 +1,194 @@
+using Akka.TestKit;
+using Akka.TestKit.Xunit2;
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using Moq;
+using Neo.Ledger;
+using Neo.Network.P2P.Payloads;
+using Neo.Network.P2P;
+using Akka.Configuration;
+using Neo.IO;
+using System.Linq;
+using System.Collections.Generic;
+
+namespace Neo.UnitTests
+{
+ [TestClass]
+ public class UT_ProtocolHandlerMailbox : TestKit
+ {
+ private static readonly Random TestRandom = new Random(1337); // use fixed seed for guaranteed determinism
+
+ ProtocolHandlerMailbox uut;
+
+ [TestCleanup]
+ public void Cleanup()
+ {
+ Shutdown();
+ }
+
+ [TestInitialize]
+ public void TestSetup()
+ {
+ Akka.Actor.ActorSystem system = Sys;
+ var config = TestKit.DefaultConfig;
+ var akkaSettings = new Akka.Actor.Settings(system, config);
+ uut = new ProtocolHandlerMailbox(akkaSettings, config);
+ }
+
+ [TestMethod]
+ public void ProtocolHandlerMailbox_Test_IsHighPriority()
+ {
+ ISerializable s = null;
+
+ //handshaking
+ uut.IsHighPriority(Message.Create(MessageCommand.Version, s)).Should().Be(true);
+ uut.IsHighPriority(Message.Create(MessageCommand.Verack, s)).Should().Be(true);
+
+ //connectivity
+ uut.IsHighPriority(Message.Create(MessageCommand.GetAddr, s)).Should().Be(false);
+ uut.IsHighPriority(Message.Create(MessageCommand.Addr, s)).Should().Be(false);
+ uut.IsHighPriority(Message.Create(MessageCommand.Ping, s)).Should().Be(false);
+ uut.IsHighPriority(Message.Create(MessageCommand.Pong, s)).Should().Be(false);
+
+ //synchronization
+ uut.IsHighPriority(Message.Create(MessageCommand.GetHeaders, s)).Should().Be(false);
+ uut.IsHighPriority(Message.Create(MessageCommand.Headers, s)).Should().Be(false);
+ uut.IsHighPriority(Message.Create(MessageCommand.GetBlocks, s)).Should().Be(false);
+ uut.IsHighPriority(Message.Create(MessageCommand.Mempool, s)).Should().Be(false);
+ uut.IsHighPriority(Message.Create(MessageCommand.Inv, s)).Should().Be(false);
+ uut.IsHighPriority(Message.Create(MessageCommand.GetData, s)).Should().Be(false);
+ uut.IsHighPriority(Message.Create(MessageCommand.NotFound, s)).Should().Be(false);
+ uut.IsHighPriority(Message.Create(MessageCommand.Transaction, s)).Should().Be(false);
+ uut.IsHighPriority(Message.Create(MessageCommand.Block, s)).Should().Be(false);
+ uut.IsHighPriority(Message.Create(MessageCommand.Consensus, s)).Should().Be(true);
+ uut.IsHighPriority(Message.Create(MessageCommand.Reject, s)).Should().Be(false);
+
+ //SPV protocol
+ uut.IsHighPriority(Message.Create(MessageCommand.FilterLoad, s)).Should().Be(true);
+ uut.IsHighPriority(Message.Create(MessageCommand.FilterAdd, s)).Should().Be(true);
+ uut.IsHighPriority(Message.Create(MessageCommand.FilterClear, s)).Should().Be(true);
+ uut.IsHighPriority(Message.Create(MessageCommand.MerkleBlock, s)).Should().Be(false);
+
+ //others
+ uut.IsHighPriority(Message.Create(MessageCommand.Alert, s)).Should().Be(true);
+
+ // any random object (non Message) should not have priority
+ object obj = null;
+ uut.IsHighPriority(obj).Should().Be(false);
+ }
+
+
+ [TestMethod]
+ public void ProtocolHandlerMailbox_Test_ShallDrop()
+ {
+ // using this for messages
+ ISerializable s = null;
+ Message msg = null; // multiple uses
+ // empty queue
+ IEnumerable
-
-
+
+
-
+
-
+
+
+
+
-
NEO 3.0 (under development): A distributed network for the Smart Economy
From 6c5e2cf0543a4bbace18e8a506558486660ef0ea Mon Sep 17 00:00:00 2001
From: Igor Machado Coelho
Date: Sat, 29 Jun 2019 17:54:50 -0300
Subject: [PATCH 026/305] dotnet format (#879)
---
neo.UnitTests/UT_ConsensusServiceMailbox.cs | 6 +--
neo.UnitTests/UT_ProtocolHandlerMailbox.cs | 46 ++++++++++-----------
neo.UnitTests/UT_RemoteNodeMailbox.cs | 2 +-
neo.UnitTests/UT_StorageItem.cs | 4 +-
neo.UnitTests/UT_TaskManagerMailbox.cs | 8 ++--
neo/Consensus/ConsensusService.cs | 4 +-
neo/Consensus/RecoveryRequest.cs | 2 +-
neo/UIntBase.cs | 2 +-
8 files changed, 37 insertions(+), 37 deletions(-)
diff --git a/neo.UnitTests/UT_ConsensusServiceMailbox.cs b/neo.UnitTests/UT_ConsensusServiceMailbox.cs
index 4000b99f61..fded2ab54e 100644
--- a/neo.UnitTests/UT_ConsensusServiceMailbox.cs
+++ b/neo.UnitTests/UT_ConsensusServiceMailbox.cs
@@ -13,7 +13,7 @@
namespace Neo.UnitTests
{
[TestClass]
- public class UT_ConsensusServiceMailbox : TestKit
+ public class UT_ConsensusServiceMailbox : TestKit
{
private static readonly Random TestRandom = new Random(1337); // use fixed seed for guaranteed determinism
@@ -42,10 +42,10 @@ public void ConsensusServiceMailbox_Test_IsHighPriority()
uut.IsHighPriority(new ConsensusService.SetViewNumber()).Should().Be(true);
uut.IsHighPriority(new ConsensusService.Timer()).Should().Be(true);
uut.IsHighPriority(new Blockchain.PersistCompleted()).Should().Be(true);
-
+
// any random object should not have priority
object obj = null;
- uut.IsHighPriority(obj).Should().Be(false);
+ uut.IsHighPriority(obj).Should().Be(false);
}
}
}
diff --git a/neo.UnitTests/UT_ProtocolHandlerMailbox.cs b/neo.UnitTests/UT_ProtocolHandlerMailbox.cs
index 4645e3cfdc..edd5a4191f 100644
--- a/neo.UnitTests/UT_ProtocolHandlerMailbox.cs
+++ b/neo.UnitTests/UT_ProtocolHandlerMailbox.cs
@@ -15,7 +15,7 @@
namespace Neo.UnitTests
{
[TestClass]
- public class UT_ProtocolHandlerMailbox : TestKit
+ public class UT_ProtocolHandlerMailbox : TestKit
{
private static readonly Random TestRandom = new Random(1337); // use fixed seed for guaranteed determinism
@@ -96,99 +96,99 @@ public void ProtocolHandlerMailbox_Test_ShallDrop()
// Version (no drop)
msg = Message.Create(MessageCommand.Version, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(false);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(false);
// Verack (no drop)
msg = Message.Create(MessageCommand.Verack, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(false);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(false);
//connectivity
// GetAddr (drop)
msg = Message.Create(MessageCommand.GetAddr, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(true);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(true);
// Addr (no drop)
msg = Message.Create(MessageCommand.Addr, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(false);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(false);
// Ping (no drop)
msg = Message.Create(MessageCommand.Ping, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(false);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(false);
// Pong (no drop)
msg = Message.Create(MessageCommand.Pong, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(false);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(false);
//synchronization
// GetHeaders (drop)
msg = Message.Create(MessageCommand.GetHeaders, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(true);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(true);
// Headers (no drop)
msg = Message.Create(MessageCommand.Headers, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(false);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(false);
// GetBlocks (drop)
msg = Message.Create(MessageCommand.GetBlocks, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(true);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(true);
// Mempool (drop)
msg = Message.Create(MessageCommand.Mempool, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(true);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(true);
// Inv (no drop)
msg = Message.Create(MessageCommand.Inv, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(false);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(false);
// GetData (drop)
msg = Message.Create(MessageCommand.GetData, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(true);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(true);
// NotFound (no drop)
msg = Message.Create(MessageCommand.NotFound, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(false);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(false);
// Transaction (no drop)
msg = Message.Create(MessageCommand.Transaction, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(false);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(false);
// Block (no drop)
msg = Message.Create(MessageCommand.Block, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(false);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(false);
// Consensus (no drop)
msg = Message.Create(MessageCommand.Consensus, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(false);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(false);
// Reject (no drop)
msg = Message.Create(MessageCommand.Reject, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(false);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(false);
//SPV protocol
// FilterLoad (no drop)
msg = Message.Create(MessageCommand.FilterLoad, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(false);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(false);
// FilterAdd (no drop)
msg = Message.Create(MessageCommand.FilterAdd, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(false);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(false);
// FilterClear (no drop)
msg = Message.Create(MessageCommand.FilterClear, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(false);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(false);
// MerkleBlock (no drop)
msg = Message.Create(MessageCommand.MerkleBlock, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(false);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(false);
//others
// Alert (no drop)
msg = Message.Create(MessageCommand.Alert, s);
uut.ShallDrop(msg, emptyQueue).Should().Be(false);
- uut.ShallDrop(msg, new object[]{ msg }).Should().Be(false);
+ uut.ShallDrop(msg, new object[] { msg }).Should().Be(false);
}
}
}
diff --git a/neo.UnitTests/UT_RemoteNodeMailbox.cs b/neo.UnitTests/UT_RemoteNodeMailbox.cs
index 9b35bf44e0..3e9e8a7c3b 100644
--- a/neo.UnitTests/UT_RemoteNodeMailbox.cs
+++ b/neo.UnitTests/UT_RemoteNodeMailbox.cs
@@ -15,7 +15,7 @@
namespace Neo.UnitTests
{
[TestClass]
- public class UT_RemoteNodeMailbox : TestKit
+ public class UT_RemoteNodeMailbox : TestKit
{
private static readonly Random TestRandom = new Random(1337); // use fixed seed for guaranteed determinism
diff --git a/neo.UnitTests/UT_StorageItem.cs b/neo.UnitTests/UT_StorageItem.cs
index 602a46ed11..c7372eb455 100644
--- a/neo.UnitTests/UT_StorageItem.cs
+++ b/neo.UnitTests/UT_StorageItem.cs
@@ -27,7 +27,7 @@ public void Value_Get()
[TestMethod]
public void Value_Set()
{
- byte[] val = new byte[] { 0x42, 0x32};
+ byte[] val = new byte[] { 0x42, 0x32 };
uut.Value = val;
uut.Value.Length.Should().Be(2);
uut.Value[0].Should().Be(val[0]);
@@ -56,7 +56,7 @@ public void Clone()
StorageItem newSi = ((ICloneable)uut).Clone();
newSi.Value.Length.Should().Be(10);
newSi.Value[0].Should().Be(0x42);
- for (int i=1; i<10; i++)
+ for (int i = 1; i < 10; i++)
{
newSi.Value[i].Should().Be(0x20);
}
diff --git a/neo.UnitTests/UT_TaskManagerMailbox.cs b/neo.UnitTests/UT_TaskManagerMailbox.cs
index 17244d80d9..2ba4ff2d85 100644
--- a/neo.UnitTests/UT_TaskManagerMailbox.cs
+++ b/neo.UnitTests/UT_TaskManagerMailbox.cs
@@ -12,7 +12,7 @@
namespace Neo.UnitTests
{
[TestClass]
- public class UT_TaskManagerMailbox : TestKit
+ public class UT_TaskManagerMailbox : TestKit
{
private static readonly Random TestRandom = new Random(1337); // use fixed seed for guaranteed determinism
@@ -42,12 +42,12 @@ public void TaskManager_Test_IsHighPriority()
// low priority
// -> NewTasks: generic InvPayload
- uut.IsHighPriority(new TaskManager.NewTasks{ Payload = new InvPayload() }).Should().Be(false);
+ uut.IsHighPriority(new TaskManager.NewTasks { Payload = new InvPayload() }).Should().Be(false);
// high priority
// -> NewTasks: payload Block or Consensus
- uut.IsHighPriority(new TaskManager.NewTasks{ Payload = new InvPayload{ Type = InventoryType.Block } }).Should().Be(true);
- uut.IsHighPriority(new TaskManager.NewTasks{ Payload = new InvPayload{ Type = InventoryType.Consensus } }).Should().Be(true);
+ uut.IsHighPriority(new TaskManager.NewTasks { Payload = new InvPayload { Type = InventoryType.Block } }).Should().Be(true);
+ uut.IsHighPriority(new TaskManager.NewTasks { Payload = new InvPayload { Type = InventoryType.Consensus } }).Should().Be(true);
// any random object should not have priority
object obj = null;
diff --git a/neo/Consensus/ConsensusService.cs b/neo/Consensus/ConsensusService.cs
index 2f538f2b6e..459a9e055b 100644
--- a/neo/Consensus/ConsensusService.cs
+++ b/neo/Consensus/ConsensusService.cs
@@ -232,7 +232,7 @@ private void OnCommitReceived(ConsensusPayload payload, Commit commit)
// this function increases existing timer (never decreases) with a value proportional to `maxDelayInBlockTimes`*`Blockchain.SecondsPerBlock`
private void ExtendTimerByFactor(int maxDelayInBlockTimes)
{
- TimeSpan nextDelay = expected_delay - (TimeProvider.Current.UtcNow - clock_started) + TimeSpan.FromMilliseconds(maxDelayInBlockTimes*Blockchain.SecondsPerBlock * 1000.0 / context.M);
+ TimeSpan nextDelay = expected_delay - (TimeProvider.Current.UtcNow - clock_started) + TimeSpan.FromMilliseconds(maxDelayInBlockTimes * Blockchain.SecondsPerBlock * 1000.0 / context.M);
if (!context.WatchOnly && !context.ViewChanging && !context.CommitSent && (nextDelay > TimeSpan.Zero))
ChangeTimer(nextDelay);
}
@@ -263,7 +263,7 @@ private void OnConsensusPayload(ConsensusPayload payload)
{
return;
}
- context.LastSeenMessage[payload.ValidatorIndex] = (int) payload.BlockIndex;
+ context.LastSeenMessage[payload.ValidatorIndex] = (int)payload.BlockIndex;
foreach (IP2PPlugin plugin in Plugin.P2PPlugins)
if (!plugin.OnConsensusMessage(payload))
return;
diff --git a/neo/Consensus/RecoveryRequest.cs b/neo/Consensus/RecoveryRequest.cs
index 3152264894..971b49a324 100644
--- a/neo/Consensus/RecoveryRequest.cs
+++ b/neo/Consensus/RecoveryRequest.cs
@@ -13,7 +13,7 @@ public class RecoveryRequest : ConsensusMessage
public override int Size => base.Size
+ sizeof(uint); //Timestamp
-
+
public RecoveryRequest() : base(ConsensusMessageType.RecoveryRequest) { }
public override void Deserialize(BinaryReader reader)
diff --git a/neo/UIntBase.cs b/neo/UIntBase.cs
index 4ab43c83f9..3808001022 100644
--- a/neo/UIntBase.cs
+++ b/neo/UIntBase.cs
@@ -5,7 +5,7 @@
namespace Neo
{
-
+
///
/// Base class for little-endian unsigned integers. Two classes inherit from this: UInt160 and UInt256.
/// Only basic comparison/serialization are proposed for these classes. For arithmetic purposes, use BigInteger class.
From 366233aaa993a06dd500e7feff3a56a844eaaf9c Mon Sep 17 00:00:00 2001
From: Ricardo Prado <38396062+lock9@users.noreply.github.com>
Date: Wed, 3 Jul 2019 05:09:02 -0300
Subject: [PATCH 027/305] UT for Version/Verack messages (#853)
* UT for Version/Verack messages
* Indentation
* Indentation
* Update ProtocolHandler.cs
* Fixing ClassInit;
Removing shutdown;
Initializing testblockchain during class setup (only once)
* Running formatter
* Eriks suggestion
* fix typo
* removed ProtocolFactory
* remove TestProtocolFactory
* simplify
* CreateActor
* Revert "CreateActor"
This reverts commit 3ad56f7293b1bf63778dac3e7a55307c776b6ff0.
* removed parameter from RemoteNode
* fix
* removed unused parameters
* format
---
neo.UnitTests/UT_Culture.cs | 31 ++++++++---
neo.UnitTests/UT_ProtocolHandler.cs | 50 +++++++++++++++++
neo.UnitTests/UT_RemoteNode.cs | 85 +++++++++++++++++++++++++++++
3 files changed, 159 insertions(+), 7 deletions(-)
create mode 100644 neo.UnitTests/UT_ProtocolHandler.cs
create mode 100644 neo.UnitTests/UT_RemoteNode.cs
diff --git a/neo.UnitTests/UT_Culture.cs b/neo.UnitTests/UT_Culture.cs
index 28dc09aef4..2ddfee5381 100644
--- a/neo.UnitTests/UT_Culture.cs
+++ b/neo.UnitTests/UT_Culture.cs
@@ -1,5 +1,6 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
+using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
@@ -36,7 +37,8 @@ where t.GetCustomAttribute() != null
var cultures = new string[] { "en-US", "zh-CN", "de-DE", "ko-KR", "ja-JP" };
var originalUICulture = CultureInfo.CurrentCulture;
- var emtpyObjArray = new object[] { };
+ var emptyObjArray = new object[] { };
+ var testContext = new object[] { new UnitTestContext() };
// run all the tests, varying the culture each time.
try
@@ -47,26 +49,26 @@ where t.GetCustomAttribute() != null
foreach (var c in testClasses)
{
- var instance = c.Constructor.Invoke(emtpyObjArray);
+ var instance = c.Constructor.Invoke(emptyObjArray);
if (c.ClassInit != null)
{
- c.ClassInit.Invoke(instance, emtpyObjArray);
+ c.ClassInit.Invoke(instance, testContext);
}
foreach (var m in c.TestMethods)
{
if (c.TestInit != null)
{
- c.TestInit.Invoke(instance, emtpyObjArray);
+ c.TestInit.Invoke(instance, emptyObjArray);
}
- m.Invoke(instance, emtpyObjArray);
+ m.Invoke(instance, emptyObjArray);
if (c.TestCleanup != null)
{
- c.TestCleanup.Invoke(instance, emtpyObjArray);
+ c.TestCleanup.Invoke(instance, emptyObjArray);
}
}
if (c.ClassCleanup != null)
{
- c.ClassCleanup.Invoke(instance, emtpyObjArray);
+ c.ClassCleanup.Invoke(instance, emptyObjArray);
}
}
}
@@ -79,6 +81,21 @@ where t.GetCustomAttribute() != null
}
}
+ public class UnitTestContext : TestContext
+ {
+ public override IDictionary Properties => throw new NotImplementedException();
+
+ public override void WriteLine(string message)
+ {
+ Console.WriteLine(message);
+ }
+
+ public override void WriteLine(string format, params object[] args)
+ {
+ Console.WriteLine(format, args);
+ }
+ }
+
public class NotReRunnableAttribute : Attribute
{
diff --git a/neo.UnitTests/UT_ProtocolHandler.cs b/neo.UnitTests/UT_ProtocolHandler.cs
new file mode 100644
index 0000000000..63bfe90e44
--- /dev/null
+++ b/neo.UnitTests/UT_ProtocolHandler.cs
@@ -0,0 +1,50 @@
+using Akka.TestKit.Xunit2;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Network.P2P;
+using Neo.Network.P2P.Capabilities;
+using Neo.Network.P2P.Payloads;
+
+namespace Neo.UnitTests
+{
+ [TestClass]
+ public class UT_ProtocolHandler : TestKit
+ {
+ private NeoSystem testBlockchain;
+
+ [TestCleanup]
+ public void Cleanup()
+ {
+ Shutdown();
+ }
+
+ [TestInitialize]
+ public void TestSetup()
+ {
+ testBlockchain = TestBlockchain.InitializeMockNeoSystem();
+ }
+
+ [TestMethod]
+ public void ProtocolHandler_Test_SendVersion_TellParent()
+ {
+ var senderProbe = CreateTestProbe();
+ var parent = CreateTestProbe();
+ var protocolActor = ActorOfAsTestActorRef(() => new ProtocolHandler(testBlockchain), parent);
+
+ var payload = new VersionPayload()
+ {
+ UserAgent = "".PadLeft(1024, '0'),
+ Nonce = 1,
+ Magic = 2,
+ Timestamp = 5,
+ Version = 6,
+ Capabilities = new NodeCapability[]
+ {
+ new ServerCapability(NodeCapabilityType.TcpServer, 25)
+ }
+ };
+
+ senderProbe.Send(protocolActor, Message.Create(MessageCommand.Version, payload));
+ parent.ExpectMsg();
+ }
+ }
+}
diff --git a/neo.UnitTests/UT_RemoteNode.cs b/neo.UnitTests/UT_RemoteNode.cs
new file mode 100644
index 0000000000..6b19461748
--- /dev/null
+++ b/neo.UnitTests/UT_RemoteNode.cs
@@ -0,0 +1,85 @@
+using Akka.IO;
+using Akka.TestKit.Xunit2;
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Network.P2P;
+using Neo.Network.P2P.Capabilities;
+using Neo.Network.P2P.Payloads;
+
+namespace Neo.UnitTests
+{
+ [TestClass]
+ public class UT_RemoteNode : TestKit
+ {
+ private static NeoSystem testBlockchain;
+
+ public UT_RemoteNode()
+ : base($"remote-node-mailbox {{ mailbox-type: \"{typeof(RemoteNodeMailbox).AssemblyQualifiedName}\" }}" +
+ $"protocol-handler-mailbox {{ mailbox-type: \"{typeof(ProtocolHandlerMailbox).AssemblyQualifiedName}\" }}")
+ {
+ }
+
+ [ClassInitialize]
+ public static void TestSetup(TestContext ctx)
+ {
+ testBlockchain = TestBlockchain.InitializeMockNeoSystem();
+ }
+
+ [TestMethod]
+ public void RemoteNode_Test_Abort_DifferentMagic()
+ {
+ var connectionTestProbe = CreateTestProbe();
+ var remoteNodeActor = ActorOfAsTestActorRef(() => new RemoteNode(testBlockchain, connectionTestProbe, null, null));
+
+ connectionTestProbe.ExpectMsg();
+
+ var payload = new VersionPayload()
+ {
+ UserAgent = "".PadLeft(1024, '0'),
+ Nonce = 1,
+ Magic = 2,
+ Timestamp = 5,
+ Version = 6,
+ Capabilities = new NodeCapability[]
+ {
+ new ServerCapability(NodeCapabilityType.TcpServer, 25)
+ }
+ };
+
+ var testProbe = CreateTestProbe();
+ testProbe.Send(remoteNodeActor, payload);
+
+ connectionTestProbe.ExpectMsg();
+ }
+
+ [TestMethod]
+ public void RemoteNode_Test_Accept_IfSameMagic()
+ {
+ var connectionTestProbe = CreateTestProbe();
+ var remoteNodeActor = ActorOfAsTestActorRef(() => new RemoteNode(testBlockchain, connectionTestProbe, null, null));
+
+ connectionTestProbe.ExpectMsg();
+
+ var payload = new VersionPayload()
+ {
+ UserAgent = "Unit Test".PadLeft(1024, '0'),
+ Nonce = 1,
+ Magic = ProtocolSettings.Default.Magic,
+ Timestamp = 5,
+ Version = 6,
+ Capabilities = new NodeCapability[]
+ {
+ new ServerCapability(NodeCapabilityType.TcpServer, 25)
+ }
+ };
+
+ var testProbe = CreateTestProbe();
+ testProbe.Send(remoteNodeActor, payload);
+
+ var verackMessage = connectionTestProbe.ExpectMsg();
+
+ //Verack
+ verackMessage.Data.Count.Should().Be(3);
+ }
+ }
+}
From aa61ae5dc1bf33cb483b75160ef52da737d32e37 Mon Sep 17 00:00:00 2001
From: Shargon
Date: Wed, 3 Jul 2019 12:36:08 +0200
Subject: [PATCH 028/305] Fix AssetDescriptor (#882)
* Fix
* Better with fixed gas
* Remove testnet
* Fix
Better with fixed gas
Remove testnet
* UT Asset Description
* Reduce limit
---
neo.UnitTests/UT_AssetDescription.cs | 38 ++++++++++++++++++++++++++++
neo/Wallets/AssetDescriptor.cs | 2 +-
2 files changed, 39 insertions(+), 1 deletion(-)
create mode 100644 neo.UnitTests/UT_AssetDescription.cs
diff --git a/neo.UnitTests/UT_AssetDescription.cs b/neo.UnitTests/UT_AssetDescription.cs
new file mode 100644
index 0000000000..175814b91f
--- /dev/null
+++ b/neo.UnitTests/UT_AssetDescription.cs
@@ -0,0 +1,38 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Persistence;
+using Neo.SmartContract.Native;
+
+namespace Neo.UnitTests
+{
+ [TestClass]
+ public class UT_AssetDescription
+ {
+ private Store Store;
+
+ [TestInitialize]
+ public void TestSetup()
+ {
+ TestBlockchain.InitializeMockNeoSystem();
+ Store = TestBlockchain.GetStore();
+ }
+
+ [TestMethod]
+ public void Check_GAS()
+ {
+ var descriptor = new Wallets.AssetDescriptor(NativeContract.GAS.Hash);
+ descriptor.AssetId.Should().Be(NativeContract.GAS.Hash);
+ descriptor.AssetName.Should().Be("GAS");
+ descriptor.Decimals.Should().Be(8);
+ }
+
+ [TestMethod]
+ public void Check_NEO()
+ {
+ var descriptor = new Wallets.AssetDescriptor(NativeContract.NEO.Hash);
+ descriptor.AssetId.Should().Be(NativeContract.NEO.Hash);
+ descriptor.AssetName.Should().Be("NEO");
+ descriptor.Decimals.Should().Be(0);
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo/Wallets/AssetDescriptor.cs b/neo/Wallets/AssetDescriptor.cs
index 25e40dc04e..49144834bb 100644
--- a/neo/Wallets/AssetDescriptor.cs
+++ b/neo/Wallets/AssetDescriptor.cs
@@ -19,7 +19,7 @@ public AssetDescriptor(UInt160 asset_id)
sb.EmitAppCall(asset_id, "name");
script = sb.ToArray();
}
- ApplicationEngine engine = ApplicationEngine.Run(script);
+ ApplicationEngine engine = ApplicationEngine.Run(script, extraGAS: 3_000_000);
if (engine.State.HasFlag(VMState.FAULT)) throw new ArgumentException();
this.AssetId = asset_id;
this.AssetName = engine.ResultStack.Pop().GetString();
From e4a6c3f1d8b356caa18e7f232015296edc20b944 Mon Sep 17 00:00:00 2001
From: Erik Zhang
Date: Sat, 6 Jul 2019 02:50:52 +0800
Subject: [PATCH 029/305] Limit SYSCALLs in Verification (#856)
* Limit SYSCALLs in Verification
* Allow deployed contract as verification script
* Simplify re-verification
* Clear mempool when policy is changed
* put _policyChanged in local scope
* Reverify transactions when policy changes
---
neo.UnitTests/UT_MemoryPool.cs | 1 +
neo/Ledger/MemoryPool.cs | 23 +++-
neo/Network/P2P/Payloads/Transaction.cs | 30 +++--
neo/SmartContract/InteropDescriptor.cs | 40 ++++++
neo/SmartContract/InteropService.NEO.cs | 58 ++++-----
neo/SmartContract/InteropService.cs | 122 ++++++++----------
.../Native/ContractMethodAttribute.cs | 1 -
.../Native/ContractMethodMetadata.cs | 1 -
neo/SmartContract/Native/NativeContract.cs | 7 +-
neo/SmartContract/Native/PolicyContract.cs | 8 +-
neo/SmartContract/Native/Tokens/NeoToken.cs | 4 +-
neo/SmartContract/Native/Tokens/Nep5Token.cs | 2 +-
12 files changed, 171 insertions(+), 126 deletions(-)
create mode 100644 neo/SmartContract/InteropDescriptor.cs
diff --git a/neo.UnitTests/UT_MemoryPool.cs b/neo.UnitTests/UT_MemoryPool.cs
index 1beabc1d65..ee79d96842 100644
--- a/neo.UnitTests/UT_MemoryPool.cs
+++ b/neo.UnitTests/UT_MemoryPool.cs
@@ -48,6 +48,7 @@ private Transaction CreateTransactionWithFee(long fee)
var randomBytes = new byte[16];
random.NextBytes(randomBytes);
Mock mock = new Mock();
+ mock.Setup(p => p.Reverify(It.IsAny(), It.IsAny>())).Returns(true);
mock.Setup(p => p.Verify(It.IsAny(), It.IsAny>())).Returns(true);
mock.Object.Script = randomBytes;
mock.Object.Sender = UInt160.Zero;
diff --git a/neo/Ledger/MemoryPool.cs b/neo/Ledger/MemoryPool.cs
index f4fee9bdf2..94f7ec9e0f 100644
--- a/neo/Ledger/MemoryPool.cs
+++ b/neo/Ledger/MemoryPool.cs
@@ -1,3 +1,4 @@
+using Akka.Actor;
using Akka.Util.Internal;
using Neo.Network.P2P;
using Neo.Network.P2P.Payloads;
@@ -61,6 +62,7 @@ public class MemoryPool : IReadOnlyCollection
internal int UnverifiedSortedTxCount => _unverifiedSortedTransactions.Count;
private int _maxTxPerBlock;
+ private long _feePerByte;
///
/// Total maximum capacity of transactions the pool can hold.
@@ -99,9 +101,13 @@ public MemoryPool(NeoSystem system, int capacity)
Capacity = capacity;
}
- internal void LoadPolicy(Snapshot snapshot)
+ internal bool LoadPolicy(Snapshot snapshot)
{
_maxTxPerBlock = (int)NativeContract.Policy.GetMaxTransactionsPerBlock(snapshot);
+ long newFeePerByte = NativeContract.Policy.GetFeePerByte(snapshot);
+ bool policyChanged = newFeePerByte > _feePerByte;
+ _feePerByte = newFeePerByte;
+ return policyChanged;
}
///
@@ -337,6 +343,8 @@ internal void InvalidateVerifiedTransactions()
// Note: this must only be called from a single thread (the Blockchain actor)
internal void UpdatePoolForBlockPersisted(Block block, Snapshot snapshot)
{
+ bool policyChanged = LoadPolicy(snapshot);
+
_txRwLock.EnterWriteLock();
try
{
@@ -349,6 +357,14 @@ internal void UpdatePoolForBlockPersisted(Block block, Snapshot snapshot)
// Add all the previously verified transactions back to the unverified transactions
InvalidateVerifiedTransactions();
+
+ if (policyChanged)
+ {
+ foreach (PoolItem item in _unverifiedSortedTransactions.Reverse())
+ _system.Blockchain.Tell(item.Tx, ActorRefs.NoSender);
+ _unverifiedTransactions.Clear();
+ _unverifiedSortedTransactions.Clear();
+ }
}
finally
{
@@ -357,10 +373,9 @@ internal void UpdatePoolForBlockPersisted(Block block, Snapshot snapshot)
// If we know about headers of future blocks, no point in verifying transactions from the unverified tx pool
// until we get caught up.
- if (block.Index > 0 && block.Index < Blockchain.Singleton.HeaderHeight)
+ if (block.Index > 0 && block.Index < Blockchain.Singleton.HeaderHeight || policyChanged)
return;
- LoadPolicy(snapshot);
ReverifyTransactions(_sortedTransactions, _unverifiedSortedTransactions,
_maxTxPerBlock, MaxSecondsToReverifyTx, snapshot);
}
@@ -388,7 +403,7 @@ private int ReverifyTransactions(SortedSet verifiedSortedTxPool,
// Since unverifiedSortedTxPool is ordered in an ascending manner, we take from the end.
foreach (PoolItem item in unverifiedSortedTxPool.Reverse().Take(count))
{
- if (item.Tx.Verify(snapshot, _unsortedTransactions.Select(p => p.Value.Tx)))
+ if (item.Tx.Reverify(snapshot, _unsortedTransactions.Select(p => p.Value.Tx)))
reverifiedItems.Add(item);
else // Transaction no longer valid -- it will be removed from unverifiedTxPool.
invalidItems.Add(item);
diff --git a/neo/Network/P2P/Payloads/Transaction.cs b/neo/Network/P2P/Payloads/Transaction.cs
index 152ac12b59..923fe6447f 100644
--- a/neo/Network/P2P/Payloads/Transaction.cs
+++ b/neo/Network/P2P/Payloads/Transaction.cs
@@ -122,6 +122,26 @@ public UInt160[] GetScriptHashesForVerifying(Snapshot snapshot)
return hashes.OrderBy(p => p).ToArray();
}
+ public virtual bool Reverify(Snapshot snapshot, IEnumerable mempool)
+ {
+ if (ValidUntilBlock <= snapshot.Height || ValidUntilBlock > snapshot.Height + MaxValidUntilBlockIncrement)
+ return false;
+ if (NativeContract.Policy.GetBlockedAccounts(snapshot).Intersect(GetScriptHashesForVerifying(snapshot)).Count() > 0)
+ return false;
+ BigInteger balance = NativeContract.GAS.BalanceOf(snapshot, Sender);
+ BigInteger fee = SystemFee + NetworkFee;
+ if (balance < fee) return false;
+ fee += mempool.Where(p => p != this && p.Sender.Equals(Sender)).Select(p => (BigInteger)(p.SystemFee + p.NetworkFee)).Sum();
+ if (balance < fee) return false;
+ UInt160[] hashes = GetScriptHashesForVerifying(snapshot);
+ for (int i = 0; i < hashes.Length; i++)
+ {
+ if (Witnesses[i].VerificationScript.Length > 0) continue;
+ if (snapshot.Contracts.TryGet(hashes[i]) is null) return false;
+ }
+ return true;
+ }
+
void ISerializable.Serialize(BinaryWriter writer)
{
((IVerifiable)this).SerializeUnsigned(writer);
@@ -164,19 +184,11 @@ bool IInventory.Verify(Snapshot snapshot)
public virtual bool Verify(Snapshot snapshot, IEnumerable mempool)
{
- if (ValidUntilBlock <= snapshot.Height || ValidUntilBlock > snapshot.Height + MaxValidUntilBlockIncrement)
- return false;
+ if (!Reverify(snapshot, mempool)) return false;
int size = Size;
if (size > MaxTransactionSize) return false;
long net_fee = NetworkFee - size * NativeContract.Policy.GetFeePerByte(snapshot);
if (net_fee < 0) return false;
- if (NativeContract.Policy.GetBlockedAccounts(snapshot).Intersect(GetScriptHashesForVerifying(snapshot)).Count() > 0)
- return false;
- BigInteger balance = NativeContract.GAS.BalanceOf(snapshot, Sender);
- BigInteger fee = SystemFee + NetworkFee;
- if (balance < fee) return false;
- fee += mempool.Where(p => p != this && p.Sender.Equals(Sender)).Select(p => (BigInteger)(p.SystemFee + p.NetworkFee)).Sum();
- if (balance < fee) return false;
return this.VerifyWitnesses(snapshot, net_fee);
}
}
diff --git a/neo/SmartContract/InteropDescriptor.cs b/neo/SmartContract/InteropDescriptor.cs
new file mode 100644
index 0000000000..c283e474de
--- /dev/null
+++ b/neo/SmartContract/InteropDescriptor.cs
@@ -0,0 +1,40 @@
+using Neo.VM;
+using System;
+
+namespace Neo.SmartContract
+{
+ internal class InteropDescriptor
+ {
+ public string Method { get; }
+ public uint Hash { get; }
+ public Func Handler { get; }
+ public long Price { get; }
+ public Func, long> PriceCalculator { get; }
+ public TriggerType AllowedTriggers { get; }
+
+ public InteropDescriptor(string method, Func handler, long price, TriggerType allowedTriggers)
+ : this(method, handler, allowedTriggers)
+ {
+ this.Price = price;
+ }
+
+ public InteropDescriptor(string method, Func handler, Func, long> priceCalculator, TriggerType allowedTriggers)
+ : this(method, handler, allowedTriggers)
+ {
+ this.PriceCalculator = priceCalculator;
+ }
+
+ private InteropDescriptor(string method, Func handler, TriggerType allowedTriggers)
+ {
+ this.Method = method;
+ this.Hash = method.ToInteropMethodHash();
+ this.Handler = handler;
+ this.AllowedTriggers = allowedTriggers;
+ }
+
+ public long GetPrice(RandomAccessStack stack)
+ {
+ return PriceCalculator is null ? Price : PriceCalculator(stack);
+ }
+ }
+}
diff --git a/neo/SmartContract/InteropService.NEO.cs b/neo/SmartContract/InteropService.NEO.cs
index a496497962..5787cebdb4 100644
--- a/neo/SmartContract/InteropService.NEO.cs
+++ b/neo/SmartContract/InteropService.NEO.cs
@@ -18,37 +18,37 @@ namespace Neo.SmartContract
{
static partial class InteropService
{
- public static readonly uint Neo_Native_Deploy = Register("Neo.Native.Deploy", Native_Deploy, 0);
- public static readonly uint Neo_Crypto_CheckSig = Register("Neo.Crypto.CheckSig", Crypto_CheckSig, 0_01000000);
- public static readonly uint Neo_Crypto_CheckMultiSig = Register("Neo.Crypto.CheckMultiSig", Crypto_CheckMultiSig, GetCheckMultiSigPrice);
- public static readonly uint Neo_Header_GetVersion = Register("Neo.Header.GetVersion", Header_GetVersion, 0_00000400);
- public static readonly uint Neo_Header_GetMerkleRoot = Register("Neo.Header.GetMerkleRoot", Header_GetMerkleRoot, 0_00000400);
- public static readonly uint Neo_Header_GetNextConsensus = Register("Neo.Header.GetNextConsensus", Header_GetNextConsensus, 0_00000400);
- public static readonly uint Neo_Transaction_GetScript = Register("Neo.Transaction.GetScript", Transaction_GetScript, 0_00000400);
- public static readonly uint Neo_Transaction_GetWitnesses = Register("Neo.Transaction.GetWitnesses", Transaction_GetWitnesses, 0_00010000);
- public static readonly uint Neo_Witness_GetVerificationScript = Register("Neo.Witness.GetVerificationScript", Witness_GetVerificationScript, 0_00000400);
- public static readonly uint Neo_Account_IsStandard = Register("Neo.Account.IsStandard", Account_IsStandard, 0_00030000);
- public static readonly uint Neo_Contract_Create = Register("Neo.Contract.Create", Contract_Create, GetDeploymentPrice);
- public static readonly uint Neo_Contract_Update = Register("Neo.Contract.Update", Contract_Update, GetDeploymentPrice);
- public static readonly uint Neo_Contract_GetScript = Register("Neo.Contract.GetScript", Contract_GetScript, 0_00000400);
- public static readonly uint Neo_Contract_IsPayable = Register("Neo.Contract.IsPayable", Contract_IsPayable, 0_00000400);
- public static readonly uint Neo_Storage_Find = Register("Neo.Storage.Find", Storage_Find, 0_01000000);
- public static readonly uint Neo_Enumerator_Create = Register("Neo.Enumerator.Create", Enumerator_Create, 0_00000400);
- public static readonly uint Neo_Enumerator_Next = Register("Neo.Enumerator.Next", Enumerator_Next, 0_01000000);
- public static readonly uint Neo_Enumerator_Value = Register("Neo.Enumerator.Value", Enumerator_Value, 0_00000400);
- public static readonly uint Neo_Enumerator_Concat = Register("Neo.Enumerator.Concat", Enumerator_Concat, 0_00000400);
- public static readonly uint Neo_Iterator_Create = Register("Neo.Iterator.Create", Iterator_Create, 0_00000400);
- public static readonly uint Neo_Iterator_Key = Register("Neo.Iterator.Key", Iterator_Key, 0_00000400);
- public static readonly uint Neo_Iterator_Keys = Register("Neo.Iterator.Keys", Iterator_Keys, 0_00000400);
- public static readonly uint Neo_Iterator_Values = Register("Neo.Iterator.Values", Iterator_Values, 0_00000400);
- public static readonly uint Neo_Iterator_Concat = Register("Neo.Iterator.Concat", Iterator_Concat, 0_00000400);
- public static readonly uint Neo_Json_Serialize = Register("Neo.Json.Serialize", Json_Serialize, 0_00100000);
- public static readonly uint Neo_Json_Deserialize = Register("Neo.Json.Deserialize", Json_Deserialize, 0_00500000);
+ public static readonly uint Neo_Native_Deploy = Register("Neo.Native.Deploy", Native_Deploy, 0, TriggerType.Application);
+ public static readonly uint Neo_Crypto_CheckSig = Register("Neo.Crypto.CheckSig", Crypto_CheckSig, 0_01000000, TriggerType.All);
+ public static readonly uint Neo_Crypto_CheckMultiSig = Register("Neo.Crypto.CheckMultiSig", Crypto_CheckMultiSig, GetCheckMultiSigPrice, TriggerType.All);
+ public static readonly uint Neo_Header_GetVersion = Register("Neo.Header.GetVersion", Header_GetVersion, 0_00000400, TriggerType.Application);
+ public static readonly uint Neo_Header_GetMerkleRoot = Register("Neo.Header.GetMerkleRoot", Header_GetMerkleRoot, 0_00000400, TriggerType.Application);
+ public static readonly uint Neo_Header_GetNextConsensus = Register("Neo.Header.GetNextConsensus", Header_GetNextConsensus, 0_00000400, TriggerType.Application);
+ public static readonly uint Neo_Transaction_GetScript = Register("Neo.Transaction.GetScript", Transaction_GetScript, 0_00000400, TriggerType.All);
+ public static readonly uint Neo_Transaction_GetWitnesses = Register("Neo.Transaction.GetWitnesses", Transaction_GetWitnesses, 0_00010000, TriggerType.All);
+ public static readonly uint Neo_Witness_GetVerificationScript = Register("Neo.Witness.GetVerificationScript", Witness_GetVerificationScript, 0_00000400, TriggerType.All);
+ public static readonly uint Neo_Account_IsStandard = Register("Neo.Account.IsStandard", Account_IsStandard, 0_00030000, TriggerType.All);
+ public static readonly uint Neo_Contract_Create = Register("Neo.Contract.Create", Contract_Create, GetDeploymentPrice, TriggerType.Application);
+ public static readonly uint Neo_Contract_Update = Register("Neo.Contract.Update", Contract_Update, GetDeploymentPrice, TriggerType.Application);
+ public static readonly uint Neo_Contract_GetScript = Register("Neo.Contract.GetScript", Contract_GetScript, 0_00000400, TriggerType.Application);
+ public static readonly uint Neo_Contract_IsPayable = Register("Neo.Contract.IsPayable", Contract_IsPayable, 0_00000400, TriggerType.Application);
+ public static readonly uint Neo_Storage_Find = Register("Neo.Storage.Find", Storage_Find, 0_01000000, TriggerType.Application);
+ public static readonly uint Neo_Enumerator_Create = Register("Neo.Enumerator.Create", Enumerator_Create, 0_00000400, TriggerType.All);
+ public static readonly uint Neo_Enumerator_Next = Register("Neo.Enumerator.Next", Enumerator_Next, 0_01000000, TriggerType.All);
+ public static readonly uint Neo_Enumerator_Value = Register("Neo.Enumerator.Value", Enumerator_Value, 0_00000400, TriggerType.All);
+ public static readonly uint Neo_Enumerator_Concat = Register("Neo.Enumerator.Concat", Enumerator_Concat, 0_00000400, TriggerType.All);
+ public static readonly uint Neo_Iterator_Create = Register("Neo.Iterator.Create", Iterator_Create, 0_00000400, TriggerType.All);
+ public static readonly uint Neo_Iterator_Key = Register("Neo.Iterator.Key", Iterator_Key, 0_00000400, TriggerType.All);
+ public static readonly uint Neo_Iterator_Keys = Register("Neo.Iterator.Keys", Iterator_Keys, 0_00000400, TriggerType.All);
+ public static readonly uint Neo_Iterator_Values = Register("Neo.Iterator.Values", Iterator_Values, 0_00000400, TriggerType.All);
+ public static readonly uint Neo_Iterator_Concat = Register("Neo.Iterator.Concat", Iterator_Concat, 0_00000400, TriggerType.All);
+ public static readonly uint Neo_Json_Serialize = Register("Neo.Json.Serialize", Json_Serialize, 0_00100000, TriggerType.All);
+ public static readonly uint Neo_Json_Deserialize = Register("Neo.Json.Deserialize", Json_Deserialize, 0_00500000, TriggerType.All);
static InteropService()
{
foreach (NativeContract contract in NativeContract.Contracts)
- Register(contract.ServiceName, contract.Invoke, contract.GetPrice);
+ Register(contract.ServiceName, contract.Invoke, contract.GetPrice, TriggerType.System | TriggerType.Application);
}
private static long GetCheckMultiSigPrice(RandomAccessStack stack)
@@ -70,7 +70,6 @@ private static long GetDeploymentPrice(RandomAccessStack stack)
private static bool Native_Deploy(ApplicationEngine engine)
{
- if (engine.Trigger != TriggerType.Application) return false;
if (engine.Snapshot.PersistingBlock.Index != 0) return false;
foreach (NativeContract contract in NativeContract.Contracts)
{
@@ -244,7 +243,6 @@ private static bool Account_IsStandard(ApplicationEngine engine)
private static bool Contract_Create(ApplicationEngine engine)
{
- if (engine.Trigger != TriggerType.Application) return false;
byte[] script = engine.CurrentContext.EvaluationStack.Pop().GetByteArray();
if (script.Length > 1024 * 1024) return false;
@@ -269,8 +267,6 @@ private static bool Contract_Create(ApplicationEngine engine)
private static bool Contract_Update(ApplicationEngine engine)
{
- if (engine.Trigger != TriggerType.Application) return false;
-
byte[] script = engine.CurrentContext.EvaluationStack.Pop().GetByteArray();
if (script.Length > 1024 * 1024) return false;
var manifest = engine.CurrentContext.EvaluationStack.Pop().GetString();
diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs
index 77a17369fa..669a937885 100644
--- a/neo/SmartContract/InteropService.cs
+++ b/neo/SmartContract/InteropService.cs
@@ -23,47 +23,45 @@ public static partial class InteropService
public const int MaxStorageKeySize = 64;
public const int MaxStorageValueSize = ushort.MaxValue;
- private static readonly Dictionary> methods = new Dictionary>();
- private static readonly Dictionary prices = new Dictionary();
- private static readonly Dictionary, long>> priceCalculators = new Dictionary, long>>();
-
- public static readonly uint System_ExecutionEngine_GetScriptContainer = Register("System.ExecutionEngine.GetScriptContainer", ExecutionEngine_GetScriptContainer, 0_00000250);
- public static readonly uint System_ExecutionEngine_GetExecutingScriptHash = Register("System.ExecutionEngine.GetExecutingScriptHash", ExecutionEngine_GetExecutingScriptHash, 0_00000400);
- public static readonly uint System_ExecutionEngine_GetCallingScriptHash = Register("System.ExecutionEngine.GetCallingScriptHash", ExecutionEngine_GetCallingScriptHash, 0_00000400);
- public static readonly uint System_ExecutionEngine_GetEntryScriptHash = Register("System.ExecutionEngine.GetEntryScriptHash", ExecutionEngine_GetEntryScriptHash, 0_00000400);
- public static readonly uint System_Runtime_Platform = Register("System.Runtime.Platform", Runtime_Platform, 0_00000250);
- public static readonly uint System_Runtime_GetTrigger = Register("System.Runtime.GetTrigger", Runtime_GetTrigger, 0_00000250);
- public static readonly uint System_Runtime_CheckWitness = Register("System.Runtime.CheckWitness", Runtime_CheckWitness, 0_00030000);
- public static readonly uint System_Runtime_Notify = Register("System.Runtime.Notify", Runtime_Notify, 0_00000250);
- public static readonly uint System_Runtime_Log = Register("System.Runtime.Log", Runtime_Log, 0_00300000);
- public static readonly uint System_Runtime_GetTime = Register("System.Runtime.GetTime", Runtime_GetTime, 0_00000250);
- public static readonly uint System_Runtime_Serialize = Register("System.Runtime.Serialize", Runtime_Serialize, 0_00100000);
- public static readonly uint System_Runtime_Deserialize = Register("System.Runtime.Deserialize", Runtime_Deserialize, 0_00500000);
- public static readonly uint System_Runtime_GetInvocationCounter = Register("System.Runtime.GetInvocationCounter", Runtime_GetInvocationCounter, 0_00000400);
- public static readonly uint System_Crypto_Verify = Register("System.Crypto.Verify", Crypto_Verify, 0_01000000);
- public static readonly uint System_Blockchain_GetHeight = Register("System.Blockchain.GetHeight", Blockchain_GetHeight, 0_00000400);
- public static readonly uint System_Blockchain_GetHeader = Register("System.Blockchain.GetHeader", Blockchain_GetHeader, 0_00007000);
- public static readonly uint System_Blockchain_GetBlock = Register("System.Blockchain.GetBlock", Blockchain_GetBlock, 0_02500000);
- public static readonly uint System_Blockchain_GetTransaction = Register("System.Blockchain.GetTransaction", Blockchain_GetTransaction, 0_01000000);
- public static readonly uint System_Blockchain_GetTransactionHeight = Register("System.Blockchain.GetTransactionHeight", Blockchain_GetTransactionHeight, 0_01000000);
- public static readonly uint System_Blockchain_GetContract = Register("System.Blockchain.GetContract", Blockchain_GetContract, 0_01000000);
- public static readonly uint System_Header_GetIndex = Register("System.Header.GetIndex", Header_GetIndex, 0_00000400);
- public static readonly uint System_Header_GetHash = Register("System.Header.GetHash", Header_GetHash, 0_00000400);
- public static readonly uint System_Header_GetPrevHash = Register("System.Header.GetPrevHash", Header_GetPrevHash, 0_00000400);
- public static readonly uint System_Header_GetTimestamp = Register("System.Header.GetTimestamp", Header_GetTimestamp, 0_00000400);
- public static readonly uint System_Block_GetTransactionCount = Register("System.Block.GetTransactionCount", Block_GetTransactionCount, 0_00000400);
- public static readonly uint System_Block_GetTransactions = Register("System.Block.GetTransactions", Block_GetTransactions, 0_00010000);
- public static readonly uint System_Block_GetTransaction = Register("System.Block.GetTransaction", Block_GetTransaction, 0_00000400);
- public static readonly uint System_Transaction_GetHash = Register("System.Transaction.GetHash", Transaction_GetHash, 0_00000400);
- public static readonly uint System_Contract_Call = Register("System.Contract.Call", Contract_Call, 0_01000000);
- public static readonly uint System_Contract_Destroy = Register("System.Contract.Destroy", Contract_Destroy, 0_01000000);
- public static readonly uint System_Storage_GetContext = Register("System.Storage.GetContext", Storage_GetContext, 0_00000400);
- public static readonly uint System_Storage_GetReadOnlyContext = Register("System.Storage.GetReadOnlyContext", Storage_GetReadOnlyContext, 0_00000400);
- public static readonly uint System_Storage_Get = Register("System.Storage.Get", Storage_Get, 0_01000000);
- public static readonly uint System_Storage_Put = Register("System.Storage.Put", Storage_Put, GetStoragePrice);
- public static readonly uint System_Storage_PutEx = Register("System.Storage.PutEx", Storage_PutEx, GetStoragePrice);
- public static readonly uint System_Storage_Delete = Register("System.Storage.Delete", Storage_Delete, 0_01000000);
- public static readonly uint System_StorageContext_AsReadOnly = Register("System.StorageContext.AsReadOnly", StorageContext_AsReadOnly, 0_00000400);
+ private static readonly Dictionary methods = new Dictionary();
+
+ public static readonly uint System_ExecutionEngine_GetScriptContainer = Register("System.ExecutionEngine.GetScriptContainer", ExecutionEngine_GetScriptContainer, 0_00000250, TriggerType.All);
+ public static readonly uint System_ExecutionEngine_GetExecutingScriptHash = Register("System.ExecutionEngine.GetExecutingScriptHash", ExecutionEngine_GetExecutingScriptHash, 0_00000400, TriggerType.All);
+ public static readonly uint System_ExecutionEngine_GetCallingScriptHash = Register("System.ExecutionEngine.GetCallingScriptHash", ExecutionEngine_GetCallingScriptHash, 0_00000400, TriggerType.All);
+ public static readonly uint System_ExecutionEngine_GetEntryScriptHash = Register("System.ExecutionEngine.GetEntryScriptHash", ExecutionEngine_GetEntryScriptHash, 0_00000400, TriggerType.All);
+ public static readonly uint System_Runtime_Platform = Register("System.Runtime.Platform", Runtime_Platform, 0_00000250, TriggerType.All);
+ public static readonly uint System_Runtime_GetTrigger = Register("System.Runtime.GetTrigger", Runtime_GetTrigger, 0_00000250, TriggerType.All);
+ public static readonly uint System_Runtime_CheckWitness = Register("System.Runtime.CheckWitness", Runtime_CheckWitness, 0_00030000, TriggerType.All);
+ public static readonly uint System_Runtime_Notify = Register("System.Runtime.Notify", Runtime_Notify, 0_00000250, TriggerType.All);
+ public static readonly uint System_Runtime_Log = Register("System.Runtime.Log", Runtime_Log, 0_00300000, TriggerType.All);
+ public static readonly uint System_Runtime_GetTime = Register("System.Runtime.GetTime", Runtime_GetTime, 0_00000250, TriggerType.Application);
+ public static readonly uint System_Runtime_Serialize = Register("System.Runtime.Serialize", Runtime_Serialize, 0_00100000, TriggerType.All);
+ public static readonly uint System_Runtime_Deserialize = Register("System.Runtime.Deserialize", Runtime_Deserialize, 0_00500000, TriggerType.All);
+ public static readonly uint System_Runtime_GetInvocationCounter = Register("System.Runtime.GetInvocationCounter", Runtime_GetInvocationCounter, 0_00000400, TriggerType.All);
+ public static readonly uint System_Crypto_Verify = Register("System.Crypto.Verify", Crypto_Verify, 0_01000000, TriggerType.All);
+ public static readonly uint System_Blockchain_GetHeight = Register("System.Blockchain.GetHeight", Blockchain_GetHeight, 0_00000400, TriggerType.Application);
+ public static readonly uint System_Blockchain_GetHeader = Register("System.Blockchain.GetHeader", Blockchain_GetHeader, 0_00007000, TriggerType.Application);
+ public static readonly uint System_Blockchain_GetBlock = Register("System.Blockchain.GetBlock", Blockchain_GetBlock, 0_02500000, TriggerType.Application);
+ public static readonly uint System_Blockchain_GetTransaction = Register("System.Blockchain.GetTransaction", Blockchain_GetTransaction, 0_01000000, TriggerType.Application);
+ public static readonly uint System_Blockchain_GetTransactionHeight = Register("System.Blockchain.GetTransactionHeight", Blockchain_GetTransactionHeight, 0_01000000, TriggerType.Application);
+ public static readonly uint System_Blockchain_GetContract = Register("System.Blockchain.GetContract", Blockchain_GetContract, 0_01000000, TriggerType.Application);
+ public static readonly uint System_Header_GetIndex = Register("System.Header.GetIndex", Header_GetIndex, 0_00000400, TriggerType.Application);
+ public static readonly uint System_Header_GetHash = Register("System.Header.GetHash", Header_GetHash, 0_00000400, TriggerType.Application);
+ public static readonly uint System_Header_GetPrevHash = Register("System.Header.GetPrevHash", Header_GetPrevHash, 0_00000400, TriggerType.Application);
+ public static readonly uint System_Header_GetTimestamp = Register("System.Header.GetTimestamp", Header_GetTimestamp, 0_00000400, TriggerType.Application);
+ public static readonly uint System_Block_GetTransactionCount = Register("System.Block.GetTransactionCount", Block_GetTransactionCount, 0_00000400, TriggerType.Application);
+ public static readonly uint System_Block_GetTransactions = Register("System.Block.GetTransactions", Block_GetTransactions, 0_00010000, TriggerType.Application);
+ public static readonly uint System_Block_GetTransaction = Register("System.Block.GetTransaction", Block_GetTransaction, 0_00000400, TriggerType.Application);
+ public static readonly uint System_Transaction_GetHash = Register("System.Transaction.GetHash", Transaction_GetHash, 0_00000400, TriggerType.All);
+ public static readonly uint System_Contract_Call = Register("System.Contract.Call", Contract_Call, 0_01000000, TriggerType.Application);
+ public static readonly uint System_Contract_Destroy = Register("System.Contract.Destroy", Contract_Destroy, 0_01000000, TriggerType.Application);
+ public static readonly uint System_Storage_GetContext = Register("System.Storage.GetContext", Storage_GetContext, 0_00000400, TriggerType.Application);
+ public static readonly uint System_Storage_GetReadOnlyContext = Register("System.Storage.GetReadOnlyContext", Storage_GetReadOnlyContext, 0_00000400, TriggerType.Application);
+ public static readonly uint System_Storage_Get = Register("System.Storage.Get", Storage_Get, 0_01000000, TriggerType.Application);
+ public static readonly uint System_Storage_Put = Register("System.Storage.Put", Storage_Put, GetStoragePrice, TriggerType.Application);
+ public static readonly uint System_Storage_PutEx = Register("System.Storage.PutEx", Storage_PutEx, GetStoragePrice, TriggerType.Application);
+ public static readonly uint System_Storage_Delete = Register("System.Storage.Delete", Storage_Delete, 0_01000000, TriggerType.Application);
+ public static readonly uint System_StorageContext_AsReadOnly = Register("System.StorageContext.AsReadOnly", StorageContext_AsReadOnly, 0_00000400, TriggerType.Application);
private static bool CheckStorageContext(ApplicationEngine engine, StorageContext context)
{
@@ -75,10 +73,7 @@ private static bool CheckStorageContext(ApplicationEngine engine, StorageContext
public static long GetPrice(uint hash, RandomAccessStack stack)
{
- if (prices.TryGetValue(hash, out long price))
- return price;
- else
- return priceCalculators[hash](stack);
+ return methods[hash].GetPrice(stack);
}
private static long GetStoragePrice(RandomAccessStack stack)
@@ -88,25 +83,25 @@ private static long GetStoragePrice(RandomAccessStack stack)
internal static bool Invoke(ApplicationEngine engine, uint method)
{
- if (!methods.TryGetValue(method, out Func func))
+ if (!methods.TryGetValue(method, out InteropDescriptor descriptor))
+ return false;
+ if (!descriptor.AllowedTriggers.HasFlag(engine.Trigger))
return false;
- return func(engine);
+ return descriptor.Handler(engine);
}
- private static uint Register(string method, Func handler, long price)
+ private static uint Register(string method, Func handler, long price, TriggerType allowedTriggers)
{
- uint hash = method.ToInteropMethodHash();
- methods.Add(hash, handler);
- prices.Add(hash, price);
- return hash;
+ InteropDescriptor descriptor = new InteropDescriptor(method, handler, price, allowedTriggers);
+ methods.Add(descriptor.Hash, descriptor);
+ return descriptor.Hash;
}
- private static uint Register(string method, Func handler, Func, long> priceCalculator)
+ private static uint Register(string method, Func handler, Func, long> priceCalculator, TriggerType allowedTriggers)
{
- uint hash = method.ToInteropMethodHash();
- methods.Add(hash, handler);
- priceCalculators.Add(hash, priceCalculator);
- return hash;
+ InteropDescriptor descriptor = new InteropDescriptor(method, handler, priceCalculator, allowedTriggers);
+ methods.Add(descriptor.Hash, descriptor);
+ return descriptor.Hash;
}
private static bool ExecutionEngine_GetScriptContainer(ApplicationEngine engine)
@@ -185,15 +180,7 @@ private static bool Runtime_Log(ApplicationEngine engine)
private static bool Runtime_GetTime(ApplicationEngine engine)
{
- if (engine.Snapshot.PersistingBlock == null)
- {
- Header header = engine.Snapshot.GetHeader(engine.Snapshot.CurrentBlockHash);
- engine.CurrentContext.EvaluationStack.Push(header.Timestamp + Blockchain.SecondsPerBlock);
- }
- else
- {
- engine.CurrentContext.EvaluationStack.Push(engine.Snapshot.PersistingBlock.Timestamp);
- }
+ engine.CurrentContext.EvaluationStack.Push(engine.Snapshot.PersistingBlock.Timestamp);
return true;
}
@@ -529,7 +516,6 @@ private static bool Contract_Call(ApplicationEngine engine)
private static bool Contract_Destroy(ApplicationEngine engine)
{
- if (engine.Trigger != TriggerType.Application) return false;
UInt160 hash = engine.CurrentScriptHash;
ContractState contract = engine.Snapshot.Contracts.TryGet(hash);
if (contract == null) return true;
@@ -542,7 +528,6 @@ private static bool Contract_Destroy(ApplicationEngine engine)
private static bool PutEx(ApplicationEngine engine, StorageContext context, byte[] key, byte[] value, StorageFlags flags)
{
- if (engine.Trigger != TriggerType.Application) return false;
if (key.Length > MaxStorageKeySize) return false;
if (value.Length > MaxStorageValueSize) return false;
if (context.IsReadOnly) return false;
@@ -593,7 +578,6 @@ private static bool Storage_PutEx(ApplicationEngine engine)
private static bool Storage_Delete(ApplicationEngine engine)
{
- if (engine.Trigger != TriggerType.Application) return false;
if (engine.CurrentContext.EvaluationStack.Pop() is InteropInterface _interface)
{
StorageContext context = _interface.GetInterface();
diff --git a/neo/SmartContract/Native/ContractMethodAttribute.cs b/neo/SmartContract/Native/ContractMethodAttribute.cs
index 145979a6cb..393737d92e 100644
--- a/neo/SmartContract/Native/ContractMethodAttribute.cs
+++ b/neo/SmartContract/Native/ContractMethodAttribute.cs
@@ -7,7 +7,6 @@ internal class ContractMethodAttribute : Attribute
{
public string Name { get; set; }
public long Price { get; }
- public TriggerType AllowedTriggers { get; set; } = TriggerType.All;
public ContractParameterType ReturnType { get; }
public ContractParameterType[] ParameterTypes { get; set; } = new ContractParameterType[0];
public string[] ParameterNames { get; set; } = new string[0];
diff --git a/neo/SmartContract/Native/ContractMethodMetadata.cs b/neo/SmartContract/Native/ContractMethodMetadata.cs
index 1c67b553e2..f63344eec9 100644
--- a/neo/SmartContract/Native/ContractMethodMetadata.cs
+++ b/neo/SmartContract/Native/ContractMethodMetadata.cs
@@ -8,6 +8,5 @@ internal class ContractMethodMetadata
{
public Func Delegate;
public long Price;
- public TriggerType AllowedTriggers;
}
}
diff --git a/neo/SmartContract/Native/NativeContract.cs b/neo/SmartContract/Native/NativeContract.cs
index 41a700ee9c..08971dcf6b 100644
--- a/neo/SmartContract/Native/NativeContract.cs
+++ b/neo/SmartContract/Native/NativeContract.cs
@@ -57,8 +57,7 @@ protected NativeContract()
methods.Add(name, new ContractMethodMetadata
{
Delegate = (Func)method.CreateDelegate(typeof(Func), this),
- Price = attribute.Price,
- AllowedTriggers = attribute.AllowedTriggers
+ Price = attribute.Price
});
}
this.Manifest.Abi.Methods = descriptors.ToArray();
@@ -92,7 +91,6 @@ internal bool Invoke(ApplicationEngine engine)
VMArray args = (VMArray)engine.CurrentContext.EvaluationStack.Pop();
if (!methods.TryGetValue(operation, out ContractMethodMetadata method))
return false;
- if (!method.AllowedTriggers.HasFlag(engine.Trigger)) return false;
StackItem result = method.Delegate(engine, args);
engine.CurrentContext.EvaluationStack.Push(result);
return true;
@@ -110,9 +108,10 @@ internal virtual bool Initialize(ApplicationEngine engine)
return true;
}
- [ContractMethod(0, ContractParameterType.Boolean, AllowedTriggers = TriggerType.System)]
+ [ContractMethod(0, ContractParameterType.Boolean)]
protected StackItem OnPersist(ApplicationEngine engine, VMArray args)
{
+ if (engine.Trigger != TriggerType.System) return false;
return OnPersist(engine);
}
diff --git a/neo/SmartContract/Native/PolicyContract.cs b/neo/SmartContract/Native/PolicyContract.cs
index 03781a5cb7..2109e8b65d 100644
--- a/neo/SmartContract/Native/PolicyContract.cs
+++ b/neo/SmartContract/Native/PolicyContract.cs
@@ -84,7 +84,7 @@ public UInt160[] GetBlockedAccounts(Snapshot snapshot)
return snapshot.Storages[CreateStorageKey(Prefix_BlockedAccounts)].Value.AsSerializableArray();
}
- [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "value" }, AllowedTriggers = TriggerType.Application)]
+ [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "value" })]
private StackItem SetMaxTransactionsPerBlock(ApplicationEngine engine, VMArray args)
{
if (!CheckValidators(engine)) return false;
@@ -94,7 +94,7 @@ private StackItem SetMaxTransactionsPerBlock(ApplicationEngine engine, VMArray a
return true;
}
- [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "value" }, AllowedTriggers = TriggerType.Application)]
+ [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Integer }, ParameterNames = new[] { "value" })]
private StackItem SetFeePerByte(ApplicationEngine engine, VMArray args)
{
if (!CheckValidators(engine)) return false;
@@ -104,7 +104,7 @@ private StackItem SetFeePerByte(ApplicationEngine engine, VMArray args)
return true;
}
- [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Hash160 }, ParameterNames = new[] { "account" }, AllowedTriggers = TriggerType.Application)]
+ [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Hash160 }, ParameterNames = new[] { "account" })]
private StackItem BlockAccount(ApplicationEngine engine, VMArray args)
{
if (!CheckValidators(engine)) return false;
@@ -118,7 +118,7 @@ private StackItem BlockAccount(ApplicationEngine engine, VMArray args)
return true;
}
- [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Hash160 }, ParameterNames = new[] { "account" }, AllowedTriggers = TriggerType.Application)]
+ [ContractMethod(0_03000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Hash160 }, ParameterNames = new[] { "account" })]
private StackItem UnblockAccount(ApplicationEngine engine, VMArray args)
{
if (!CheckValidators(engine)) return false;
diff --git a/neo/SmartContract/Native/Tokens/NeoToken.cs b/neo/SmartContract/Native/Tokens/NeoToken.cs
index 5320171059..6de1ac1970 100644
--- a/neo/SmartContract/Native/Tokens/NeoToken.cs
+++ b/neo/SmartContract/Native/Tokens/NeoToken.cs
@@ -132,7 +132,7 @@ public BigInteger UnclaimedGas(Snapshot snapshot, UInt160 account, uint end)
return CalculateBonus(snapshot, state.Balance, state.BalanceHeight, end);
}
- [ContractMethod(0_05000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.PublicKey }, ParameterNames = new[] { "pubkey" }, AllowedTriggers = TriggerType.Application)]
+ [ContractMethod(0_05000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.PublicKey }, ParameterNames = new[] { "pubkey" })]
private StackItem RegisterValidator(ApplicationEngine engine, VMArray args)
{
ECPoint pubkey = args[0].GetByteArray().AsSerializable();
@@ -150,7 +150,7 @@ private bool RegisterValidator(Snapshot snapshot, ECPoint pubkey)
return true;
}
- [ContractMethod(5_00000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Hash160, ContractParameterType.Array }, ParameterNames = new[] { "account", "pubkeys" }, AllowedTriggers = TriggerType.Application)]
+ [ContractMethod(5_00000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Hash160, ContractParameterType.Array }, ParameterNames = new[] { "account", "pubkeys" })]
private StackItem Vote(ApplicationEngine engine, VMArray args)
{
UInt160 account = new UInt160(args[0].GetByteArray());
diff --git a/neo/SmartContract/Native/Tokens/Nep5Token.cs b/neo/SmartContract/Native/Tokens/Nep5Token.cs
index 8234bbcac4..6a2e1c78b3 100644
--- a/neo/SmartContract/Native/Tokens/Nep5Token.cs
+++ b/neo/SmartContract/Native/Tokens/Nep5Token.cs
@@ -158,7 +158,7 @@ public virtual BigInteger BalanceOf(Snapshot snapshot, UInt160 account)
return state.Balance;
}
- [ContractMethod(0_08000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Hash160, ContractParameterType.Hash160, ContractParameterType.Integer }, ParameterNames = new[] { "from", "to", "amount" }, AllowedTriggers = TriggerType.Application)]
+ [ContractMethod(0_08000000, ContractParameterType.Boolean, ParameterTypes = new[] { ContractParameterType.Hash160, ContractParameterType.Hash160, ContractParameterType.Integer }, ParameterNames = new[] { "from", "to", "amount" })]
protected StackItem Transfer(ApplicationEngine engine, VMArray args)
{
UInt160 from = new UInt160(args[0].GetByteArray());
From 9a6d96b86f384efcff9b1240431cef2e8313fd4b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vitor=20Naz=C3=A1rio=20Coelho?=
Date: Fri, 5 Jul 2019 18:17:18 -0300
Subject: [PATCH 030/305] Adding total number of lines on README (#884)
---
README.md | 3 +++
1 file changed, 3 insertions(+)
diff --git a/README.md b/README.md
index 6273e7350c..7f6402eb06 100644
--- a/README.md
+++ b/README.md
@@ -17,6 +17,9 @@
+
+
+
NEO 3.0 (under development): A distributed network for the Smart Economy
From 6073040ed7f6f982af784ae0f55f3a4f6e03280b Mon Sep 17 00:00:00 2001
From: Shargon
Date: Mon, 8 Jul 2019 09:14:44 +0200
Subject: [PATCH 031/305] DeriveKey Scrypt unit test (#886)
* Strengthen PBKDF2
* Update SCrypt.cs
* Scrypt DeriveKey ut
* Deterministic behaviour
---
neo.UnitTests/UT_Scrypt.cs | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
create mode 100644 neo.UnitTests/UT_Scrypt.cs
diff --git a/neo.UnitTests/UT_Scrypt.cs b/neo.UnitTests/UT_Scrypt.cs
new file mode 100644
index 0000000000..2d5100aa53
--- /dev/null
+++ b/neo.UnitTests/UT_Scrypt.cs
@@ -0,0 +1,19 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Cryptography;
+using System;
+
+namespace Neo.UnitTests
+{
+ [TestClass]
+ public class UT_Scrypt
+ {
+ [TestMethod]
+ public void DeriveKeyTest()
+ {
+ int N = 16384, r = 8, p = 8;
+
+ var derivedkey = SCrypt.DeriveKey(new byte[] { 0x01, 0x02, 0x03 }, new byte[] { 0x04, 0x05, 0x06 }, N, r, p, 64).ToHexString();
+ Assert.AreEqual("2bb9c7bb9c392f0dd37821b76e42b01944902520f48d00946a51e72c960fba0a3c62a87d835c9df10a8ad66a04cdf02fbb10b9d7396c20959f28d6cb3ddfdffb", derivedkey);
+ }
+ }
+}
From f482362f416629da7312247bdc9f9e4bfea692ee Mon Sep 17 00:00:00 2001
From: Shargon
Date: Mon, 8 Jul 2019 11:31:47 +0200
Subject: [PATCH 032/305] Remove Debug.Assert (#893)
* if Debug
* if DEBUG
---
neo/Cryptography/ECC/ECFieldElement.cs | 4 ----
neo/Cryptography/ECC/ECPoint.cs | 2 --
2 files changed, 6 deletions(-)
diff --git a/neo/Cryptography/ECC/ECFieldElement.cs b/neo/Cryptography/ECC/ECFieldElement.cs
index 4ce303dcc8..e33cab4206 100644
--- a/neo/Cryptography/ECC/ECFieldElement.cs
+++ b/neo/Cryptography/ECC/ECFieldElement.cs
@@ -1,5 +1,4 @@
using System;
-using System.Diagnostics;
using System.Linq;
using System.Numerics;
@@ -47,8 +46,6 @@ private static BigInteger[] FastLucasSequence(BigInteger p, BigInteger P, BigInt
int n = k.GetBitLength();
int s = k.GetLowestSetBit();
- Debug.Assert(k.TestBit(s));
-
BigInteger Uh = 1;
BigInteger Vl = 2;
BigInteger Vh = P;
@@ -131,7 +128,6 @@ public ECFieldElement Sqrt()
V += curve.Q;
}
V >>= 1;
- Debug.Assert((V * V).Mod(curve.Q) == Value);
return new ECFieldElement(V, curve);
}
}
diff --git a/neo/Cryptography/ECC/ECPoint.cs b/neo/Cryptography/ECC/ECPoint.cs
index 6c0746adab..18b1cdab1a 100644
--- a/neo/Cryptography/ECC/ECPoint.cs
+++ b/neo/Cryptography/ECC/ECPoint.cs
@@ -1,6 +1,5 @@
using Neo.IO;
using System;
-using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Numerics;
@@ -386,7 +385,6 @@ private static sbyte[] WindowNaf(sbyte width, BigInteger k)
{
if (x.Y.Equals(y.Y))
return x.Twice();
- Debug.Assert(x.Y.Equals(-y.Y));
return x.Curve.Infinity;
}
ECFieldElement gamma = (y.Y - x.Y) / (y.X - x.X);
From bf67fc1b3090048f62494c3483339d5e510b25a0 Mon Sep 17 00:00:00 2001
From: Shargon
Date: Tue, 9 Jul 2019 10:10:42 +0200
Subject: [PATCH 033/305] Ensure the hash length (3x) (#896)
* Ensure the hash length
* Update UIntBase.cs
* Fix ecpoint
---
neo/Cryptography/ECC/ECPoint.cs | 18 ++++++++++++++----
neo/UIntBase.cs | 12 +++++++-----
2 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/neo/Cryptography/ECC/ECPoint.cs b/neo/Cryptography/ECC/ECPoint.cs
index 18b1cdab1a..dbd556eb50 100644
--- a/neo/Cryptography/ECC/ECPoint.cs
+++ b/neo/Cryptography/ECC/ECPoint.cs
@@ -112,11 +112,21 @@ public static ECPoint DeserializeFrom(BinaryReader reader, ECCurve curve)
{
case 0x02:
case 0x03:
- reader.Read(buffer, 1, expectedLength);
- return DecodePoint(buffer.Take(1 + expectedLength).ToArray(), curve);
+ {
+ if (reader.Read(buffer, 1, expectedLength) != expectedLength)
+ {
+ throw new FormatException();
+ }
+ return DecodePoint(buffer.Take(1 + expectedLength).ToArray(), curve);
+ }
case 0x04:
- reader.Read(buffer, 1, expectedLength * 2);
- return DecodePoint(buffer, curve);
+ {
+ if (reader.Read(buffer, 1, expectedLength * 2) != expectedLength * 2)
+ {
+ throw new FormatException();
+ }
+ return DecodePoint(buffer, curve);
+ }
default:
throw new FormatException("Invalid point encoding " + buffer[0]);
}
diff --git a/neo/UIntBase.cs b/neo/UIntBase.cs
index 3808001022..22431c4cae 100644
--- a/neo/UIntBase.cs
+++ b/neo/UIntBase.cs
@@ -5,7 +5,6 @@
namespace Neo
{
-
///
/// Base class for little-endian unsigned integers. Two classes inherit from this: UInt160 and UInt256.
/// Only basic comparison/serialization are proposed for these classes. For arithmetic purposes, use BigInteger class.
@@ -15,7 +14,7 @@ public abstract class UIntBase : IEquatable, ISerializable
///
/// Storing unsigned int in a little-endian byte array.
///
- private byte[] data_bytes;
+ private readonly byte[] data_bytes;
///
/// Number of bytes of the unsigned int.
@@ -44,7 +43,10 @@ protected UIntBase(int bytes, byte[] value)
///
void ISerializable.Deserialize(BinaryReader reader)
{
- reader.Read(data_bytes, 0, data_bytes.Length);
+ if (reader.Read(data_bytes, 0, data_bytes.Length) != data_bytes.Length)
+ {
+ throw new FormatException();
+ }
}
///
@@ -53,7 +55,7 @@ void ISerializable.Deserialize(BinaryReader reader)
///
public bool Equals(UIntBase other)
{
- if (ReferenceEquals(other, null))
+ if (other is null)
return false;
if (ReferenceEquals(this, other))
return true;
@@ -68,7 +70,7 @@ public bool Equals(UIntBase other)
///
public override bool Equals(object obj)
{
- if (ReferenceEquals(obj, null))
+ if (obj is null)
return false;
if (!(obj is UIntBase))
return false;
From 45838754d556d0a235f9beb22617ef709e97fb4c Mon Sep 17 00:00:00 2001
From: Shargon
Date: Wed, 10 Jul 2019 20:49:03 +0200
Subject: [PATCH 034/305] Fix fifoset (3x) (#905)
* Fix fifo set
* More tests for FIFO size
* Fixing indexes
* Testing asset of different sets
* Testing again
* Update UT_FifoSet.cs
* Update UT_FifoSet.cs
* Tests for fifo max size
* Fixing indentation
---
neo.UnitTests/UT_FifoSet.cs | 54 +++++++++++++++++++++++++++++++++++++
neo/IO/Caching/FIFOSet.cs | 2 +-
2 files changed, 55 insertions(+), 1 deletion(-)
create mode 100644 neo.UnitTests/UT_FifoSet.cs
diff --git a/neo.UnitTests/UT_FifoSet.cs b/neo.UnitTests/UT_FifoSet.cs
new file mode 100644
index 0000000000..ff5ccf9c27
--- /dev/null
+++ b/neo.UnitTests/UT_FifoSet.cs
@@ -0,0 +1,54 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.IO.Caching;
+using System.Linq;
+
+namespace Neo.UnitTests
+{
+ [TestClass]
+ public class UT_FifoSet
+ {
+ [TestMethod]
+ public void FifoSetTest()
+ {
+ var a = UInt256.Zero;
+ var b = new UInt256();
+ var c = new UInt256(new byte[32] {
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01
+ });
+
+ var set = new FIFOSet(3);
+
+ Assert.IsTrue(set.Add(a));
+ Assert.IsFalse(set.Add(a));
+ Assert.IsFalse(set.Add(b));
+ Assert.IsTrue(set.Add(c));
+
+ CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { a, c });
+
+ var d = new UInt256(new byte[32] {
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02
+ });
+
+ // Testing Fifo max size
+ Assert.IsTrue(set.Add(d));
+ CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { a, c, d });
+
+ var e = new UInt256(new byte[32] {
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x03
+ });
+
+ Assert.IsTrue(set.Add(e));
+ Assert.IsFalse(set.Add(e));
+ CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { c, d, e });
+ }
+ }
+}
diff --git a/neo/IO/Caching/FIFOSet.cs b/neo/IO/Caching/FIFOSet.cs
index 6dd52dbccf..7769cb5ad5 100644
--- a/neo/IO/Caching/FIFOSet.cs
+++ b/neo/IO/Caching/FIFOSet.cs
@@ -51,7 +51,7 @@ public void ExceptWith(IEnumerable hashes)
public IEnumerator GetEnumerator()
{
- var entries = dictionary.Values.Cast().ToArray();
+ var entries = dictionary.Keys.Cast().ToArray();
foreach (var entry in entries) yield return entry;
}
From 4928065f7bc39321d19ba7d918751192a270ffcb Mon Sep 17 00:00:00 2001
From: Shargon
Date: Thu, 11 Jul 2019 11:39:02 +0200
Subject: [PATCH 035/305] Speed up multisig ut (#908)
* Speedup multisign ut
* Start tasks
---
neo.UnitTests/UT_Transaction.cs | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/neo.UnitTests/UT_Transaction.cs b/neo.UnitTests/UT_Transaction.cs
index 18aafb31bb..fc4b89b4a9 100644
--- a/neo.UnitTests/UT_Transaction.cs
+++ b/neo.UnitTests/UT_Transaction.cs
@@ -12,6 +12,7 @@
using Neo.VM;
using Neo.Wallets;
using Neo.Wallets.NEP6;
+using System.Threading.Tasks;
namespace Neo.UnitTests
{
@@ -104,8 +105,14 @@ public void FeeIsMultiSigContract()
using (var unlockA = walletA.Unlock("123"))
using (var unlockB = walletB.Unlock("123"))
{
- var a = walletA.CreateAccount();
- var b = walletB.CreateAccount();
+ var ta = new Task(() => walletA.CreateAccount());
+ var tb = new Task(() => walletA.CreateAccount());
+ ta.Start();
+ tb.Start();
+ Task.WaitAll(ta, tb);
+
+ var a = ta.Result;
+ var b = tb.Result;
var multiSignContract = Contract.CreateMultiSigContract(2,
new ECPoint[]
@@ -114,8 +121,13 @@ public void FeeIsMultiSigContract()
b.GetKey().PublicKey
});
- var acc = walletA.CreateAccount(multiSignContract, a.GetKey());
- acc = walletB.CreateAccount(multiSignContract, b.GetKey());
+ ta = new Task(() => walletA.CreateAccount(multiSignContract, a.GetKey()));
+ tb = new Task(() => walletB.CreateAccount(multiSignContract, b.GetKey()));
+ ta.Start();
+ tb.Start();
+ Task.WaitAll(ta, tb);
+
+ var acc = tb.Result;
// Fake balance
From 1dde609fb1837f45a193bc2ef452bda904badc86 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vitor=20Naz=C3=A1rio=20Coelho?=
Date: Thu, 11 Jul 2019 10:04:51 -0300
Subject: [PATCH 036/305] Speed up mempool reverify on policy change (#892)
* Speed up mempool reverify on policy change
* Caching newFeePerByte before loop
* Reverting fee per byte check when PolicyChange
* optimize
---
neo/Ledger/MemoryPool.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/neo/Ledger/MemoryPool.cs b/neo/Ledger/MemoryPool.cs
index 94f7ec9e0f..96e17dc34f 100644
--- a/neo/Ledger/MemoryPool.cs
+++ b/neo/Ledger/MemoryPool.cs
@@ -361,7 +361,8 @@ internal void UpdatePoolForBlockPersisted(Block block, Snapshot snapshot)
if (policyChanged)
{
foreach (PoolItem item in _unverifiedSortedTransactions.Reverse())
- _system.Blockchain.Tell(item.Tx, ActorRefs.NoSender);
+ if(item.Tx.FeePerByte >= _feePerByte)
+ _system.Blockchain.Tell(item.Tx, ActorRefs.NoSender);
_unverifiedTransactions.Clear();
_unverifiedSortedTransactions.Clear();
}
From f1c2879dd1a00c4918a1dc80ece595befc4aba14 Mon Sep 17 00:00:00 2001
From: Shargon
Date: Thu, 11 Jul 2019 17:08:56 +0200
Subject: [PATCH 037/305] Update UT_Transaction.cs (#913)
---
neo.UnitTests/UT_Transaction.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/neo.UnitTests/UT_Transaction.cs b/neo.UnitTests/UT_Transaction.cs
index fc4b89b4a9..5b06a816a5 100644
--- a/neo.UnitTests/UT_Transaction.cs
+++ b/neo.UnitTests/UT_Transaction.cs
@@ -106,7 +106,7 @@ public void FeeIsMultiSigContract()
using (var unlockB = walletB.Unlock("123"))
{
var ta = new Task(() => walletA.CreateAccount());
- var tb = new Task(() => walletA.CreateAccount());
+ var tb = new Task(() => walletB.CreateAccount());
ta.Start();
tb.Start();
Task.WaitAll(ta, tb);
From 338d0508e19be5036d317a9af3097eb82387a8b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vitor=20Naz=C3=A1rio=20Coelho?=
Date: Sat, 13 Jul 2019 11:25:09 -0300
Subject: [PATCH 038/305] Codecov badge (#917)
* Codecov badge
* Update README.md
---
README.md | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
index 7f6402eb06..77e2a2e566 100644
--- a/README.md
+++ b/README.md
@@ -5,21 +5,21 @@
-
-
-
-
-
-
+
+
+
-
+
+
+
+
NEO 3.0 (under development): A distributed network for the Smart Economy
From 884bd405b6daa191b755ce120bd6a968e6fd204b Mon Sep 17 00:00:00 2001
From: Shargon
Date: Mon, 15 Jul 2019 23:00:55 +0200
Subject: [PATCH 039/305] Super speed multisg unit test (#915)
* Speed up
* Remove async
---
neo.UnitTests/UT_Transaction.cs | 24 ++++++------------------
1 file changed, 6 insertions(+), 18 deletions(-)
diff --git a/neo.UnitTests/UT_Transaction.cs b/neo.UnitTests/UT_Transaction.cs
index 5b06a816a5..dc41d3a0d8 100644
--- a/neo.UnitTests/UT_Transaction.cs
+++ b/neo.UnitTests/UT_Transaction.cs
@@ -12,7 +12,6 @@
using Neo.VM;
using Neo.Wallets;
using Neo.Wallets.NEP6;
-using System.Threading.Tasks;
namespace Neo.UnitTests
{
@@ -87,10 +86,10 @@ private NEP6Wallet GenerateTestWallet()
JObject wallet = new JObject();
wallet["name"] = "noname";
wallet["version"] = new System.Version().ToString();
- wallet["scrypt"] = ScryptParameters.Default.ToJson();
+ wallet["scrypt"] = new ScryptParameters(0, 0, 0).ToJson();
wallet["accounts"] = new JArray();
wallet["extra"] = null;
- wallet.ToString().Should().Be("{\"name\":\"noname\",\"version\":\"0.0\",\"scrypt\":{\"n\":16384,\"r\":8,\"p\":8},\"accounts\":[],\"extra\":null}");
+ wallet.ToString().Should().Be("{\"name\":\"noname\",\"version\":\"0.0\",\"scrypt\":{\"n\":0,\"r\":0,\"p\":0},\"accounts\":[],\"extra\":null}");
return new NEP6Wallet(wallet);
}
@@ -105,14 +104,8 @@ public void FeeIsMultiSigContract()
using (var unlockA = walletA.Unlock("123"))
using (var unlockB = walletB.Unlock("123"))
{
- var ta = new Task(() => walletA.CreateAccount());
- var tb = new Task(() => walletB.CreateAccount());
- ta.Start();
- tb.Start();
- Task.WaitAll(ta, tb);
-
- var a = ta.Result;
- var b = tb.Result;
+ var a = walletA.CreateAccount();
+ var b = walletB.CreateAccount();
var multiSignContract = Contract.CreateMultiSigContract(2,
new ECPoint[]
@@ -121,13 +114,8 @@ public void FeeIsMultiSigContract()
b.GetKey().PublicKey
});
- ta = new Task(() => walletA.CreateAccount(multiSignContract, a.GetKey()));
- tb = new Task(() => walletB.CreateAccount(multiSignContract, b.GetKey()));
- ta.Start();
- tb.Start();
- Task.WaitAll(ta, tb);
-
- var acc = tb.Result;
+ walletA.CreateAccount(multiSignContract, a.GetKey());
+ var acc = walletB.CreateAccount(multiSignContract, b.GetKey());
// Fake balance
From 81e5faf11eb1d1d243d7a68ecc2428231269cf35 Mon Sep 17 00:00:00 2001
From: Shargon
Date: Tue, 16 Jul 2019 13:55:22 +0200
Subject: [PATCH 040/305] Get notifications (#898)
* Get notifications
* Allow all notifications
* Check array size
* Update neo/SmartContract/InteropService.cs
Co-Authored-By: Erik Zhang
* Unit test
* optimize
* Return hash and state
---
neo.UnitTests/UT_InteropService.cs | 193 ++++++++++++++++++++++++++++
neo/SmartContract/InteropService.cs | 16 +++
neo/UInt160.cs | 11 +-
neo/UInt256.cs | 11 +-
4 files changed, 221 insertions(+), 10 deletions(-)
create mode 100644 neo.UnitTests/UT_InteropService.cs
diff --git a/neo.UnitTests/UT_InteropService.cs b/neo.UnitTests/UT_InteropService.cs
new file mode 100644
index 0000000000..b5e3626109
--- /dev/null
+++ b/neo.UnitTests/UT_InteropService.cs
@@ -0,0 +1,193 @@
+using System;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.SmartContract;
+using Neo.SmartContract.Manifest;
+using Neo.VM;
+
+namespace Neo.UnitTests
+{
+ [TestClass]
+ public class UT_InteropService
+ {
+ [TestInitialize]
+ public void TestSetup()
+ {
+ TestBlockchain.InitializeMockNeoSystem();
+ }
+
+ [TestMethod]
+ public void Runtime_GetNotifications_Test()
+ {
+ UInt160 scriptHash2;
+ var snapshot = TestBlockchain.GetStore().GetSnapshot();
+
+ using (var script = new ScriptBuilder())
+ {
+ // Drop arguments
+
+ script.Emit(VM.OpCode.TOALTSTACK);
+ script.Emit(VM.OpCode.DROP);
+ script.Emit(VM.OpCode.FROMALTSTACK);
+
+ // Notify method
+
+ script.EmitSysCall(InteropService.System_Runtime_Notify);
+
+ // Add return
+
+ script.EmitPush(true);
+
+ // Mock contract
+
+ scriptHash2 = script.ToArray().ToScriptHash();
+
+ snapshot.Contracts.Delete(scriptHash2);
+ snapshot.Contracts.Add(scriptHash2, new Ledger.ContractState()
+ {
+ Script = script.ToArray(),
+ Manifest = ContractManifest.CreateDefault(scriptHash2),
+ });
+ }
+
+ // Wrong length
+
+ using (var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true))
+ using (var script = new ScriptBuilder())
+ {
+ // Retrive
+
+ script.EmitPush(1);
+ script.EmitSysCall(InteropService.System_Runtime_GetNotifications);
+
+ // Execute
+
+ engine.LoadScript(script.ToArray());
+
+ Assert.AreEqual(VMState.FAULT, engine.Execute());
+ }
+
+ // All test
+
+ using (var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true))
+ using (var script = new ScriptBuilder())
+ {
+ // Notification 1 -> 13
+
+ script.EmitPush(13);
+ script.EmitSysCall(InteropService.System_Runtime_Notify);
+
+ // Call script
+
+ script.EmitAppCall(scriptHash2, "test");
+
+ // Drop return
+
+ script.Emit(OpCode.DROP);
+
+ // Receive all notifications
+
+ script.EmitPush(UInt160.Zero.ToArray());
+ script.EmitSysCall(InteropService.System_Runtime_GetNotifications);
+
+ // Execute
+
+ engine.LoadScript(script.ToArray());
+ var currentScriptHash = engine.EntryScriptHash;
+
+ Assert.AreEqual(VMState.HALT, engine.Execute());
+ Assert.AreEqual(1, engine.ResultStack.Count);
+ Assert.AreEqual(2, engine.Notifications.Count);
+
+ Assert.IsInstanceOfType(engine.ResultStack.Peek(), typeof(VM.Types.Array));
+
+ var array = (VM.Types.Array)engine.ResultStack.Pop();
+
+ // Check syscall result
+
+ AssertNotification(array[1], scriptHash2, "test");
+ AssertNotification(array[0], currentScriptHash, 13);
+
+ // Check notifications
+
+ Assert.AreEqual(scriptHash2, engine.Notifications[1].ScriptHash);
+ Assert.AreEqual("test", engine.Notifications[1].State.GetString());
+
+ Assert.AreEqual(currentScriptHash, engine.Notifications[0].ScriptHash);
+ Assert.AreEqual(13, engine.Notifications[0].State.GetBigInteger());
+ }
+
+ // Script notifications
+
+ using (var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true))
+ using (var script = new ScriptBuilder())
+ {
+ // Notification 1 -> 13
+
+ script.EmitPush(13);
+ script.EmitSysCall(InteropService.System_Runtime_Notify);
+
+ // Call script
+
+ script.EmitAppCall(scriptHash2, "test");
+
+ // Drop return
+
+ script.Emit(OpCode.DROP);
+
+ // Receive all notifications
+
+ script.EmitPush(scriptHash2.ToArray());
+ script.EmitSysCall(InteropService.System_Runtime_GetNotifications);
+
+ // Execute
+
+ engine.LoadScript(script.ToArray());
+ var currentScriptHash = engine.EntryScriptHash;
+
+ Assert.AreEqual(VMState.HALT, engine.Execute());
+ Assert.AreEqual(1, engine.ResultStack.Count);
+ Assert.AreEqual(2, engine.Notifications.Count);
+
+ Assert.IsInstanceOfType(engine.ResultStack.Peek(), typeof(VM.Types.Array));
+
+ var array = (VM.Types.Array)engine.ResultStack.Pop();
+
+ // Check syscall result
+
+ AssertNotification(array[0], scriptHash2, "test");
+
+ // Check notifications
+
+ Assert.AreEqual(scriptHash2, engine.Notifications[1].ScriptHash);
+ Assert.AreEqual("test", engine.Notifications[1].State.GetString());
+
+ Assert.AreEqual(currentScriptHash, engine.Notifications[0].ScriptHash);
+ Assert.AreEqual(13, engine.Notifications[0].State.GetBigInteger());
+ }
+
+ // Clean storage
+
+ snapshot.Contracts.Delete(scriptHash2);
+ }
+
+ private void AssertNotification(StackItem stackItem, UInt160 scriptHash, string notification)
+ {
+ Assert.IsInstanceOfType(stackItem, typeof(VM.Types.Array));
+
+ var array = (VM.Types.Array)stackItem;
+ Assert.AreEqual(2, array.Count);
+ CollectionAssert.AreEqual(scriptHash.ToArray(), array[0].GetByteArray());
+ Assert.AreEqual(notification, array[1].GetString());
+ }
+
+ private void AssertNotification(StackItem stackItem, UInt160 scriptHash, int notification)
+ {
+ Assert.IsInstanceOfType(stackItem, typeof(VM.Types.Array));
+
+ var array = (VM.Types.Array)stackItem;
+ Assert.AreEqual(2, array.Count);
+ CollectionAssert.AreEqual(scriptHash.ToArray(), array[0].GetByteArray());
+ Assert.AreEqual(notification, array[1].GetBigInteger());
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs
index 669a937885..fbb3a8655d 100644
--- a/neo/SmartContract/InteropService.cs
+++ b/neo/SmartContract/InteropService.cs
@@ -38,6 +38,7 @@ public static partial class InteropService
public static readonly uint System_Runtime_Serialize = Register("System.Runtime.Serialize", Runtime_Serialize, 0_00100000, TriggerType.All);
public static readonly uint System_Runtime_Deserialize = Register("System.Runtime.Deserialize", Runtime_Deserialize, 0_00500000, TriggerType.All);
public static readonly uint System_Runtime_GetInvocationCounter = Register("System.Runtime.GetInvocationCounter", Runtime_GetInvocationCounter, 0_00000400, TriggerType.All);
+ public static readonly uint System_Runtime_GetNotifications = Register("System.Runtime.GetNotifications", Runtime_GetNotifications, 0_00010000, TriggerType.All);
public static readonly uint System_Crypto_Verify = Register("System.Crypto.Verify", Crypto_Verify, 0_01000000, TriggerType.All);
public static readonly uint System_Blockchain_GetHeight = Register("System.Blockchain.GetHeight", Blockchain_GetHeight, 0_00000400, TriggerType.Application);
public static readonly uint System_Blockchain_GetHeader = Register("System.Blockchain.GetHeader", Blockchain_GetHeader, 0_00007000, TriggerType.Application);
@@ -201,6 +202,21 @@ private static bool Runtime_Serialize(ApplicationEngine engine)
return true;
}
+ private static bool Runtime_GetNotifications(ApplicationEngine engine)
+ {
+ var data = engine.CurrentContext.EvaluationStack.Pop().GetByteArray();
+ if (data.Length != UInt160.Length) return false;
+ if (!engine.CheckArraySize(engine.Notifications.Count)) return false;
+
+ var hash = new UInt160(data);
+ IEnumerable notifications = engine.Notifications;
+ if (!hash.Equals(UInt160.Zero))
+ notifications = notifications.Where(p => p.ScriptHash == hash);
+
+ engine.CurrentContext.EvaluationStack.Push(notifications.Select(u => new VM.Types.Array(new StackItem[] { u.ScriptHash.ToArray(), u.State })).ToArray());
+ return true;
+ }
+
private static bool Runtime_GetInvocationCounter(ApplicationEngine engine)
{
if (!engine.InvocationCounter.TryGetValue(engine.CurrentScriptHash, out var counter))
diff --git a/neo/UInt160.cs b/neo/UInt160.cs
index fd11b7fb9b..0c6bea4b5a 100644
--- a/neo/UInt160.cs
+++ b/neo/UInt160.cs
@@ -9,6 +9,7 @@ namespace Neo
///
public class UInt160 : UIntBase, IComparable, IEquatable
{
+ public const int Length = 20;
public static readonly UInt160 Zero = new UInt160();
///
@@ -23,7 +24,7 @@ public UInt160()
/// The byte[] constructor invokes base class UIntBase constructor for 20 bytes
///
public UInt160(byte[] value)
- : base(20, value)
+ : base(Length, value)
{
}
@@ -79,7 +80,7 @@ public unsafe bool Equals(UInt160 other)
throw new ArgumentNullException();
if (value.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
value = value.Substring(2);
- if (value.Length != 40)
+ if (value.Length != Length * 2)
throw new FormatException();
return new UInt160(value.HexToBytes().Reverse().ToArray());
}
@@ -97,13 +98,13 @@ public static bool TryParse(string s, out UInt160 result)
}
if (s.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
s = s.Substring(2);
- if (s.Length != 40)
+ if (s.Length != Length * 2)
{
result = null;
return false;
}
- byte[] data = new byte[20];
- for (int i = 0; i < 20; i++)
+ byte[] data = new byte[Length];
+ for (int i = 0; i < Length; i++)
if (!byte.TryParse(s.Substring(i * 2, 2), NumberStyles.AllowHexSpecifier, null, out data[i]))
{
result = null;
diff --git a/neo/UInt256.cs b/neo/UInt256.cs
index de3c9ecd47..ec79ae21ea 100644
--- a/neo/UInt256.cs
+++ b/neo/UInt256.cs
@@ -9,6 +9,7 @@ namespace Neo
///
public class UInt256 : UIntBase, IComparable, IEquatable
{
+ public const int Length = 32;
public static readonly UInt256 Zero = new UInt256();
@@ -24,7 +25,7 @@ public UInt256()
/// The byte[] constructor invokes base class UIntBase constructor for 32 bytes
///
public UInt256(byte[] value)
- : base(32, value)
+ : base(Length, value)
{
}
@@ -80,7 +81,7 @@ public unsafe bool Equals(UInt256 other)
throw new ArgumentNullException();
if (s.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
s = s.Substring(2);
- if (s.Length != 64)
+ if (s.Length != Length * 2)
throw new FormatException();
return new UInt256(s.HexToBytes().Reverse().ToArray());
}
@@ -98,13 +99,13 @@ public static bool TryParse(string s, out UInt256 result)
}
if (s.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase))
s = s.Substring(2);
- if (s.Length != 64)
+ if (s.Length != Length * 2)
{
result = null;
return false;
}
- byte[] data = new byte[32];
- for (int i = 0; i < 32; i++)
+ byte[] data = new byte[Length];
+ for (int i = 0; i < Length; i++)
if (!byte.TryParse(s.Substring(i * 2, 2), NumberStyles.AllowHexSpecifier, null, out data[i]))
{
result = null;
From 74146ebb08ceaf2169330a1123d29b72425920f9 Mon Sep 17 00:00:00 2001
From: Erik Zhang
Date: Wed, 17 Jul 2019 17:37:54 +0800
Subject: [PATCH 041/305] Gas initialize (#911)
---
neo.UnitTests/UT_GasToken.cs | 24 ++++++++++-----------
neo.UnitTests/UT_NeoToken.cs | 4 ++--
neo/Ledger/Blockchain.cs | 2 +-
neo/SmartContract/Native/Tokens/GasToken.cs | 9 ++++++++
4 files changed, 24 insertions(+), 15 deletions(-)
diff --git a/neo.UnitTests/UT_GasToken.cs b/neo.UnitTests/UT_GasToken.cs
index cdf73eecbb..72a0c4d7ae 100644
--- a/neo.UnitTests/UT_GasToken.cs
+++ b/neo.UnitTests/UT_GasToken.cs
@@ -52,12 +52,12 @@ public void Check_BalanceOfTransferAndBurn()
NativeContract.NEO.Initialize(new ApplicationEngine(TriggerType.Application, null, snapshot, 0));
var supply = NativeContract.GAS.TotalSupply(snapshot);
- supply.Should().Be(0);
+ supply.Should().Be(3000000000000000);
// Check unclaim
var unclaim = UT_NeoToken.Check_UnclaimedGas(snapshot, from);
- unclaim.Value.Should().Be(new BigInteger(800000000000));
+ unclaim.Value.Should().Be(new BigInteger(600000000000));
unclaim.State.Should().BeTrue();
// Transfer
@@ -66,7 +66,7 @@ public void Check_BalanceOfTransferAndBurn()
NativeContract.NEO.BalanceOf(snapshot, from).Should().Be(100_000_000);
NativeContract.NEO.BalanceOf(snapshot, to).Should().Be(0);
- NativeContract.GAS.BalanceOf(snapshot, from).Should().Be(800000000000);
+ NativeContract.GAS.BalanceOf(snapshot, from).Should().Be(3000600000000000);
NativeContract.GAS.BalanceOf(snapshot, to).Should().Be(0);
// Check unclaim
@@ -76,7 +76,7 @@ public void Check_BalanceOfTransferAndBurn()
unclaim.State.Should().BeTrue();
supply = NativeContract.GAS.TotalSupply(snapshot);
- supply.Should().Be(800000000000);
+ supply.Should().Be(3000600000000000);
snapshot.Storages.GetChangeSet().Count().Should().Be(keyCount + 3); // Gas
@@ -84,16 +84,16 @@ public void Check_BalanceOfTransferAndBurn()
keyCount = snapshot.Storages.GetChangeSet().Count();
- NativeContract.GAS.Transfer(snapshot, from, to, 800000000000, false).Should().BeFalse(); // Not signed
- NativeContract.GAS.Transfer(snapshot, from, to, 800000000001, true).Should().BeFalse(); // More than balance
- NativeContract.GAS.Transfer(snapshot, from, to, 800000000000, true).Should().BeTrue(); // All balance
+ NativeContract.GAS.Transfer(snapshot, from, to, 3000600000000000, false).Should().BeFalse(); // Not signed
+ NativeContract.GAS.Transfer(snapshot, from, to, 3000600000000001, true).Should().BeFalse(); // More than balance
+ NativeContract.GAS.Transfer(snapshot, from, to, 3000600000000000, true).Should().BeTrue(); // All balance
// Balance of
- NativeContract.GAS.BalanceOf(snapshot, to).Should().Be(800000000000);
+ NativeContract.GAS.BalanceOf(snapshot, to).Should().Be(3000600000000000);
NativeContract.GAS.BalanceOf(snapshot, from).Should().Be(0);
- snapshot.Storages.GetChangeSet().Count().Should().Be(keyCount); // All
+ snapshot.Storages.GetChangeSet().Count().Should().Be(keyCount + 1); // All
// Burn
@@ -106,19 +106,19 @@ public void Check_BalanceOfTransferAndBurn()
// Burn more than expected
Assert.ThrowsException(() =>
- NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(800000000001)));
+ NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(3000600000000001)));
// Real burn
NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(1));
- NativeContract.GAS.BalanceOf(snapshot, to).Should().Be(799999999999);
+ NativeContract.GAS.BalanceOf(snapshot, to).Should().Be(3000599999999999);
keyCount.Should().Be(snapshot.Storages.GetChangeSet().Count());
// Burn all
- NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(799999999999));
+ NativeContract.GAS.Burn(engine, new UInt160(to), new BigInteger(3000599999999999));
(keyCount - 1).Should().Be(snapshot.Storages.GetChangeSet().Count());
diff --git a/neo.UnitTests/UT_NeoToken.cs b/neo.UnitTests/UT_NeoToken.cs
index 8ef2314c23..3997573c0f 100644
--- a/neo.UnitTests/UT_NeoToken.cs
+++ b/neo.UnitTests/UT_NeoToken.cs
@@ -91,7 +91,7 @@ public void Check_UnclaimedGas()
Blockchain.StandbyValidators).ToScriptHash().ToArray();
var unclaim = Check_UnclaimedGas(snapshot, from);
- unclaim.Value.Should().Be(new BigInteger(800000000000));
+ unclaim.Value.Should().Be(new BigInteger(600000000000));
unclaim.State.Should().BeTrue();
unclaim = Check_UnclaimedGas(snapshot, new byte[19]);
@@ -146,7 +146,7 @@ public void Check_Transfer()
// Check unclaim
var unclaim = Check_UnclaimedGas(snapshot, from);
- unclaim.Value.Should().Be(new BigInteger(800000000000));
+ unclaim.Value.Should().Be(new BigInteger(600000000000));
unclaim.State.Should().BeTrue();
// Transfer
diff --git a/neo/Ledger/Blockchain.cs b/neo/Ledger/Blockchain.cs
index 181421cc3f..5d9ad00ee9 100644
--- a/neo/Ledger/Blockchain.cs
+++ b/neo/Ledger/Blockchain.cs
@@ -30,7 +30,7 @@ public class FillCompleted { }
public static readonly uint SecondsPerBlock = ProtocolSettings.Default.SecondsPerBlock;
public const uint DecrementInterval = 2000000;
public const int MaxValidators = 1024;
- public static readonly uint[] GenerationAmount = { 8, 7, 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
+ public static readonly uint[] GenerationAmount = { 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
public static readonly TimeSpan TimePerBlock = TimeSpan.FromSeconds(SecondsPerBlock);
public static readonly ECPoint[] StandbyValidators = ProtocolSettings.Default.StandbyValidators.OfType().Select(p => ECPoint.DecodePoint(p.HexToBytes(), ECCurve.Secp256r1)).ToArray();
diff --git a/neo/SmartContract/Native/Tokens/GasToken.cs b/neo/SmartContract/Native/Tokens/GasToken.cs
index ca74a41855..fd39979670 100644
--- a/neo/SmartContract/Native/Tokens/GasToken.cs
+++ b/neo/SmartContract/Native/Tokens/GasToken.cs
@@ -25,6 +25,15 @@ internal GasToken()
{
}
+ internal override bool Initialize(ApplicationEngine engine)
+ {
+ if (!base.Initialize(engine)) return false;
+ if (TotalSupply(engine.Snapshot) != BigInteger.Zero) return false;
+ UInt160 account = Contract.CreateMultiSigRedeemScript(Blockchain.StandbyValidators.Length / 2 + 1, Blockchain.StandbyValidators).ToScriptHash();
+ Mint(engine, account, 30_000_000 * Factor);
+ return true;
+ }
+
protected override bool OnPersist(ApplicationEngine engine)
{
if (!base.OnPersist(engine)) return false;
From 2faf037d35e576878827e37341d0327fb717d32b Mon Sep 17 00:00:00 2001
From: Shargon
Date: Wed, 17 Jul 2019 20:21:58 +0200
Subject: [PATCH 042/305] Add ChangeView.Reason (#926)
* Change view reason
* Move order for compatibility
* Moved to other file
* Change order
* Change agreement
---
neo/Consensus/ChangeView.cs | 13 +++++++++++--
neo/Consensus/ChangeViewReason.cs | 11 +++++++++++
neo/Consensus/ConsensusContext.cs | 3 ++-
neo/Consensus/ConsensusService.cs | 19 +++++++++++++------
4 files changed, 37 insertions(+), 9 deletions(-)
create mode 100644 neo/Consensus/ChangeViewReason.cs
diff --git a/neo/Consensus/ChangeView.cs b/neo/Consensus/ChangeView.cs
index 5cc00cc77a..7d5b3e96eb 100644
--- a/neo/Consensus/ChangeView.cs
+++ b/neo/Consensus/ChangeView.cs
@@ -8,6 +8,7 @@ public class ChangeView : ConsensusMessage
/// NewViewNumber is always set to the current ViewNumber asking changeview + 1
///
public byte NewViewNumber => (byte)(ViewNumber + 1);
+
///
/// Timestamp of when the ChangeView message was created. This allows receiving nodes to ensure
/// they only respond once to a specific ChangeView request (it thus prevents replay of the ChangeView
@@ -15,8 +16,14 @@ public class ChangeView : ConsensusMessage
///
public uint Timestamp;
- public override int Size => base.Size
- + sizeof(uint); //Timestamp
+ ///
+ /// Reason
+ ///
+ public ChangeViewReason Reason;
+
+ public override int Size => base.Size +
+ sizeof(uint) + // Timestamp
+ sizeof(ChangeViewReason); // Reason
public ChangeView() : base(ConsensusMessageType.ChangeView) { }
@@ -24,12 +31,14 @@ public override void Deserialize(BinaryReader reader)
{
base.Deserialize(reader);
Timestamp = reader.ReadUInt32();
+ Reason = (ChangeViewReason)reader.ReadByte();
}
public override void Serialize(BinaryWriter writer)
{
base.Serialize(writer);
writer.Write(Timestamp);
+ writer.Write((byte)Reason);
}
}
}
diff --git a/neo/Consensus/ChangeViewReason.cs b/neo/Consensus/ChangeViewReason.cs
new file mode 100644
index 0000000000..64a2a6053e
--- /dev/null
+++ b/neo/Consensus/ChangeViewReason.cs
@@ -0,0 +1,11 @@
+namespace Neo.Consensus
+{
+ public enum ChangeViewReason : byte
+ {
+ Timeout = 0x0,
+ ChangeAgreement = 0x1,
+ TxNotFound = 0x2,
+ TxRejectedByPolicy = 0x3,
+ TxInvalid = 0x4,
+ }
+}
\ No newline at end of file
diff --git a/neo/Consensus/ConsensusContext.cs b/neo/Consensus/ConsensusContext.cs
index 5fa53ce567..0d6855a623 100644
--- a/neo/Consensus/ConsensusContext.cs
+++ b/neo/Consensus/ConsensusContext.cs
@@ -159,10 +159,11 @@ public bool Load()
}
}
- public ConsensusPayload MakeChangeView()
+ public ConsensusPayload MakeChangeView(ChangeViewReason reason)
{
return ChangeViewPayloads[MyIndex] = MakeSignedPayload(new ChangeView
{
+ Reason = reason,
Timestamp = TimeProvider.Current.UtcNow.ToTimestamp()
});
}
diff --git a/neo/Consensus/ConsensusService.cs b/neo/Consensus/ConsensusService.cs
index 459a9e055b..b8e594d642 100644
--- a/neo/Consensus/ConsensusService.cs
+++ b/neo/Consensus/ConsensusService.cs
@@ -63,13 +63,13 @@ private bool AddTransaction(Transaction tx, bool verify)
if (verify && !tx.Verify(context.Snapshot, context.Transactions.Values))
{
Log($"Invalid transaction: {tx.Hash}{Environment.NewLine}{tx.ToArray().ToHexString()}", LogLevel.Warning);
- RequestChangeView();
+ RequestChangeView(ChangeViewReason.TxInvalid);
return false;
}
if (!Plugin.CheckPolicy(tx))
{
Log($"reject tx: {tx.Hash}{Environment.NewLine}{tx.ToArray().ToHexString()}", LogLevel.Warning);
- RequestChangeView();
+ RequestChangeView(ChangeViewReason.TxRejectedByPolicy);
return false;
}
context.Transactions[tx.Hash] = tx;
@@ -124,7 +124,7 @@ private void CheckExpectedView(byte viewNumber)
// Communicate the network about my agreement to move to `viewNumber`
// if my last change view payload, `message`, has NewViewNumber lower than current view to change
if (message is null || message.NewViewNumber < viewNumber)
- localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakeChangeView() });
+ localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakeChangeView(ChangeViewReason.ChangeAgreement) });
}
InitializeConsensus(viewNumber);
}
@@ -547,7 +547,14 @@ private void OnTimer(Timer timer)
}
else
{
- RequestChangeView();
+ var reason = ChangeViewReason.Timeout;
+
+ if (context.Block != null && context.TransactionHashes.Count() > context.Transactions.Count)
+ {
+ reason = ChangeViewReason.TxNotFound;
+ }
+
+ RequestChangeView(reason);
}
}
}
@@ -575,7 +582,7 @@ public static Props Props(IActorRef localNode, IActorRef taskManager, Store stor
return Akka.Actor.Props.Create(() => new ConsensusService(localNode, taskManager, store, wallet)).WithMailbox("consensus-service-mailbox");
}
- private void RequestChangeView()
+ private void RequestChangeView(ChangeViewReason reason)
{
if (context.WatchOnly) return;
// Request for next view is always one view more than the current context.ViewNumber
@@ -591,7 +598,7 @@ private void RequestChangeView()
return;
}
Log($"request change view: height={context.Block.Index} view={context.ViewNumber} nv={expectedView} nc={context.CountCommitted} nf={context.CountFailed}");
- localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakeChangeView() });
+ localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakeChangeView(reason) });
CheckExpectedView(expectedView);
}
From 01a88a2fe98a9e5212957af37f79dee7050db373 Mon Sep 17 00:00:00 2001
From: Shargon
Date: Thu, 18 Jul 2019 09:15:05 +0200
Subject: [PATCH 043/305] Optimization (#929)
---
neo.UnitTests/UT_StorageKey.cs | 17 +++++++++++++++--
neo/Ledger/StorageKey.cs | 5 ++---
2 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/neo.UnitTests/UT_StorageKey.cs b/neo.UnitTests/UT_StorageKey.cs
index 965e46ae4e..ab718f0f89 100644
--- a/neo.UnitTests/UT_StorageKey.cs
+++ b/neo.UnitTests/UT_StorageKey.cs
@@ -1,5 +1,6 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.IO;
using Neo.Ledger;
namespace Neo.UnitTests
@@ -21,6 +22,19 @@ public void ScriptHash_Get()
uut.ScriptHash.Should().BeNull();
}
+ [TestMethod]
+ public void Size()
+ {
+ var ut = new StorageKey() { Key = new byte[17], ScriptHash = UInt160.Zero };
+ ut.ToArray().Length.Should().Be(((ISerializable)ut).Size);
+
+ ut = new StorageKey() { Key = new byte[0], ScriptHash = UInt160.Zero };
+ ut.ToArray().Length.Should().Be(((ISerializable)ut).Size);
+
+ ut = new StorageKey() { Key = new byte[16], ScriptHash = UInt160.Zero };
+ ut.ToArray().Length.Should().Be(((ISerializable)ut).Size);
+ }
+
[TestMethod]
public void ScriptHash_Set()
{
@@ -113,6 +127,5 @@ public void GetHashCode_Get()
uut.Key = TestUtils.GetByteArray(10, 0x42);
uut.GetHashCode().Should().Be(806209853);
}
-
}
-}
+}
\ No newline at end of file
diff --git a/neo/Ledger/StorageKey.cs b/neo/Ledger/StorageKey.cs
index 891fb081ec..f975b7a422 100644
--- a/neo/Ledger/StorageKey.cs
+++ b/neo/Ledger/StorageKey.cs
@@ -30,9 +30,8 @@ public bool Equals(StorageKey other)
public override bool Equals(object obj)
{
- if (obj is null) return false;
- if (!(obj is StorageKey)) return false;
- return Equals((StorageKey)obj);
+ if (!(obj is StorageKey other)) return false;
+ return Equals(other);
}
public override int GetHashCode()
From fd52018bdcab645c7bd03018daac2a22289e66fb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vitor=20Naz=C3=A1rio=20Coelho?=
Date: Thu, 18 Jul 2019 05:55:16 -0300
Subject: [PATCH 044/305] Fixing wrong size on ConsensusPayload (#931)
---
neo/Network/P2P/Payloads/ConsensusPayload.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/neo/Network/P2P/Payloads/ConsensusPayload.cs b/neo/Network/P2P/Payloads/ConsensusPayload.cs
index 7a20e7c46b..a4c6e86ee6 100644
--- a/neo/Network/P2P/Payloads/ConsensusPayload.cs
+++ b/neo/Network/P2P/Payloads/ConsensusPayload.cs
@@ -58,7 +58,6 @@ public UInt256 Hash
PrevHash.Size + //PrevHash
sizeof(uint) + //BlockIndex
sizeof(ushort) + //ValidatorIndex
- sizeof(uint) + //Timestamp
Data.GetVarSize() + //Data
1 + Witness.Size; //Witness
From deb3e6d9a512d82a0b8b2fc938f8dc52fd25b6ba Mon Sep 17 00:00:00 2001
From: Shargon
Date: Fri, 19 Jul 2019 18:28:26 +0200
Subject: [PATCH 045/305] Temporary fix for #922 (#936)
---
neo.UnitTests/UT_Culture.cs | 6 +++---
neo.UnitTests/UT_RemoteNode.cs | 5 +++--
neo.UnitTests/UT_RemoteNodeMailbox.cs | 12 +++---------
3 files changed, 9 insertions(+), 14 deletions(-)
diff --git a/neo.UnitTests/UT_Culture.cs b/neo.UnitTests/UT_Culture.cs
index 2ddfee5381..807e67990c 100644
--- a/neo.UnitTests/UT_Culture.cs
+++ b/neo.UnitTests/UT_Culture.cs
@@ -1,9 +1,9 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System;
+using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Neo.UnitTests
{
@@ -18,7 +18,7 @@ public void All_Tests_Cultures()
{
// get all tests in the unit test project assembly
var testClasses = (from t in typeof(NotReRunnableAttribute).GetTypeInfo().Assembly.DefinedTypes
- where t.GetCustomAttribute() != null
+ where t.GetCustomAttribute() != null && t.GetCustomAttribute() == null
select new
{
Constructor = t.GetConstructor(new Type[] { }),
diff --git a/neo.UnitTests/UT_RemoteNode.cs b/neo.UnitTests/UT_RemoteNode.cs
index 6b19461748..60d587ed13 100644
--- a/neo.UnitTests/UT_RemoteNode.cs
+++ b/neo.UnitTests/UT_RemoteNode.cs
@@ -1,4 +1,4 @@
-using Akka.IO;
+using Akka.IO;
using Akka.TestKit.Xunit2;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -8,7 +8,8 @@
namespace Neo.UnitTests
{
- [TestClass]
+ [TestClass]
+ [NotReRunnable]
public class UT_RemoteNode : TestKit
{
private static NeoSystem testBlockchain;
diff --git a/neo.UnitTests/UT_RemoteNodeMailbox.cs b/neo.UnitTests/UT_RemoteNodeMailbox.cs
index 3e9e8a7c3b..ff3e6e17d9 100644
--- a/neo.UnitTests/UT_RemoteNodeMailbox.cs
+++ b/neo.UnitTests/UT_RemoteNodeMailbox.cs
@@ -1,20 +1,14 @@
-using Akka.TestKit;
+using System;
+using Akka.IO;
using Akka.TestKit.Xunit2;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System;
-using Moq;
-using Neo.Ledger;
-using Neo.Network.P2P.Payloads;
using Neo.Network.P2P;
-using Akka.Configuration;
-using System.Net;
-using Akka.Actor;
-using Akka.IO;
namespace Neo.UnitTests
{
[TestClass]
+ [NotReRunnable]
public class UT_RemoteNodeMailbox : TestKit
{
private static readonly Random TestRandom = new Random(1337); // use fixed seed for guaranteed determinism
From a3d53d044b299f2ed5f80a5d141cf26a32ebc05c Mon Sep 17 00:00:00 2001
From: Shargon
Date: Fri, 19 Jul 2019 18:40:21 +0200
Subject: [PATCH 046/305] Scrypt from 3s to 16ms (#937)
---
neo.UnitTests/UT_Scrypt.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/neo.UnitTests/UT_Scrypt.cs b/neo.UnitTests/UT_Scrypt.cs
index 2d5100aa53..8e2bf1e30a 100644
--- a/neo.UnitTests/UT_Scrypt.cs
+++ b/neo.UnitTests/UT_Scrypt.cs
@@ -10,10 +10,10 @@ public class UT_Scrypt
[TestMethod]
public void DeriveKeyTest()
{
- int N = 16384, r = 8, p = 8;
+ int N = 32, r = 2, p = 2;
var derivedkey = SCrypt.DeriveKey(new byte[] { 0x01, 0x02, 0x03 }, new byte[] { 0x04, 0x05, 0x06 }, N, r, p, 64).ToHexString();
- Assert.AreEqual("2bb9c7bb9c392f0dd37821b76e42b01944902520f48d00946a51e72c960fba0a3c62a87d835c9df10a8ad66a04cdf02fbb10b9d7396c20959f28d6cb3ddfdffb", derivedkey);
+ Assert.AreEqual("b6274d3a81892c24335ab46a08ec16d040ac00c5943b212099a44b76a9b8102631ab988fa07fb35357cee7b0e3910098c0774c0e97399997676d890b2bf2bb25", derivedkey);
}
}
}
From b19ca6d948a5d221f5990b46efb6ab4d755be4d8 Mon Sep 17 00:00:00 2001
From: Shargon
Date: Mon, 22 Jul 2019 03:59:52 +0200
Subject: [PATCH 047/305] Remove minner tx hole (#934)
* Remove minner tx hole
* Fix equals
---
neo.UnitTests/UT_Block.cs | 27 ++++++++-------------------
neo/Network/P2P/Payloads/Block.cs | 13 +++++++------
2 files changed, 15 insertions(+), 25 deletions(-)
diff --git a/neo.UnitTests/UT_Block.cs b/neo.UnitTests/UT_Block.cs
index 886f5099f0..f6b9218070 100644
--- a/neo.UnitTests/UT_Block.cs
+++ b/neo.UnitTests/UT_Block.cs
@@ -1,5 +1,6 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.IO;
using Neo.IO.Json;
using Neo.Network.P2P.Payloads;
using System.IO;
@@ -86,21 +87,13 @@ public void Serialize()
byte[] data;
using (MemoryStream stream = new MemoryStream())
+ using (BinaryWriter writer = new BinaryWriter(stream, Encoding.ASCII, true))
{
- using (BinaryWriter writer = new BinaryWriter(stream, Encoding.ASCII, true))
- {
- uut.Serialize(writer);
- data = stream.ToArray();
- }
+ uut.Serialize(writer);
+ data = stream.ToArray();
}
- byte[] requiredData = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 41, 176, 215, 72, 169, 204, 248, 197, 175, 60, 222, 16, 219, 62, 54, 236, 154, 95, 114, 6, 67, 162, 188, 180, 173, 215, 107, 61, 175, 65, 216, 128, 171, 4, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0 };
-
- data.Length.Should().Be(requiredData.Length);
- for (int i = 0; i < data.Length; i++)
- {
- data[i].Should().Be(requiredData[i]);
- }
+ Assert.AreEqual(data.ToHexString(), "0000000000000000000000000000000000000000000000000000000000000000000000000f29b0d748a9ccf8c5af3cde10db3e36ec9a5f720643a2bcb4add76b3daf41d880ab04fd0000000000000000000000000000000000000000000000000100015101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100010000");
}
[TestMethod]
@@ -111,14 +104,10 @@ public void Deserialize()
uut.MerkleRoot = merkRoot; // need to set for deserialise to be valid
- byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 41, 176, 215, 72, 169, 204, 248, 197, 175, 60, 222, 16, 219, 62, 54, 236, 154, 95, 114, 6, 67, 162, 188, 180, 173, 215, 107, 61, 175, 65, 216, 128, 171, 4, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };
- int index = 0;
- using (MemoryStream ms = new MemoryStream(data, index, data.Length - index, false))
+ using (MemoryStream ms = new MemoryStream("0000000000000000000000000000000000000000000000000000000000000000000000000f29b0d748a9ccf8c5af3cde10db3e36ec9a5f720643a2bcb4add76b3daf41d880ab04fd0000000000000000000000000000000000000000000000000100015101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100010000".HexToBytes(), false))
+ using (BinaryReader reader = new BinaryReader(ms))
{
- using (BinaryReader reader = new BinaryReader(ms))
- {
- uut.Deserialize(reader);
- }
+ uut.Deserialize(reader);
}
assertStandardBlockTestVals(val256, merkRoot, val160, timestampVal, indexVal, scriptVal, transactionsVal);
diff --git a/neo/Network/P2P/Payloads/Block.cs b/neo/Network/P2P/Payloads/Block.cs
index 58faf54cb1..b63035e0ed 100644
--- a/neo/Network/P2P/Payloads/Block.cs
+++ b/neo/Network/P2P/Payloads/Block.cs
@@ -12,7 +12,7 @@ namespace Neo.Network.P2P.Payloads
public class Block : BlockBase, IInventory, IEquatable
{
public const int MaxContentsPerBlock = ushort.MaxValue;
- public const int MaxTransactionsPerBlock = MaxContentsPerBlock - 1;
+ public const int MaxTransactionsPerBlock = MaxContentsPerBlock;
public ConsensusData ConsensusData;
public Transaction[] Transactions;
@@ -41,13 +41,13 @@ public Header Header
InventoryType IInventory.InventoryType => InventoryType.Block;
public override int Size => base.Size
- + IO.Helper.GetVarSize(Transactions.Length + 1) //Count
+ + IO.Helper.GetVarSize(Transactions.Length) //Count
+ ConsensusData.Size //ConsensusData
+ Transactions.Sum(p => p.Size); //Transactions
public static UInt256 CalculateMerkleRoot(UInt256 consensusDataHash, params UInt256[] transactionHashes)
{
- List hashes = new List(transactionHashes.Length + 1) { consensusDataHash };
+ List hashes = new List(transactionHashes.Length) { consensusDataHash };
hashes.AddRange(transactionHashes);
return MerkleTree.ComputeRoot(hashes);
}
@@ -58,7 +58,7 @@ public override void Deserialize(BinaryReader reader)
int count = (int)reader.ReadVarInt(MaxContentsPerBlock);
if (count == 0) throw new FormatException();
ConsensusData = reader.ReadSerializable();
- Transactions = new Transaction[count - 1];
+ Transactions = new Transaction[count];
for (int i = 0; i < Transactions.Length; i++)
Transactions[i] = reader.ReadSerializable();
if (Transactions.Distinct().Count() != Transactions.Length)
@@ -76,7 +76,8 @@ public bool Equals(Block other)
public override bool Equals(object obj)
{
- return Equals(obj as Block);
+ if (!(obj is Block b)) return false;
+ return Equals(b);
}
public override int GetHashCode()
@@ -92,7 +93,7 @@ public void RebuildMerkleRoot()
public override void Serialize(BinaryWriter writer)
{
base.Serialize(writer);
- writer.WriteVarInt(Transactions.Length + 1);
+ writer.WriteVarInt(Transactions.Length);
writer.Write(ConsensusData);
foreach (Transaction tx in Transactions)
writer.Write(tx);
From 0730e080508d17afaed2e163fea677f640b0e873 Mon Sep 17 00:00:00 2001
From: Shargon
Date: Mon, 22 Jul 2019 12:03:41 +0200
Subject: [PATCH 048/305] Revert "Remove minner tx hole (#934)" (#944)
This reverts commit 5b321fbcf97f9fff43980d9e0108c1cbf374968c.
---
neo.UnitTests/UT_Block.cs | 27 +++++++++++++++++++--------
neo/Network/P2P/Payloads/Block.cs | 13 ++++++-------
2 files changed, 25 insertions(+), 15 deletions(-)
diff --git a/neo.UnitTests/UT_Block.cs b/neo.UnitTests/UT_Block.cs
index f6b9218070..886f5099f0 100644
--- a/neo.UnitTests/UT_Block.cs
+++ b/neo.UnitTests/UT_Block.cs
@@ -1,6 +1,5 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.IO;
using Neo.IO.Json;
using Neo.Network.P2P.Payloads;
using System.IO;
@@ -87,13 +86,21 @@ public void Serialize()
byte[] data;
using (MemoryStream stream = new MemoryStream())
- using (BinaryWriter writer = new BinaryWriter(stream, Encoding.ASCII, true))
{
- uut.Serialize(writer);
- data = stream.ToArray();
+ using (BinaryWriter writer = new BinaryWriter(stream, Encoding.ASCII, true))
+ {
+ uut.Serialize(writer);
+ data = stream.ToArray();
+ }
}
- Assert.AreEqual(data.ToHexString(), "0000000000000000000000000000000000000000000000000000000000000000000000000f29b0d748a9ccf8c5af3cde10db3e36ec9a5f720643a2bcb4add76b3daf41d880ab04fd0000000000000000000000000000000000000000000000000100015101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100010000");
+ byte[] requiredData = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 41, 176, 215, 72, 169, 204, 248, 197, 175, 60, 222, 16, 219, 62, 54, 236, 154, 95, 114, 6, 67, 162, 188, 180, 173, 215, 107, 61, 175, 65, 216, 128, 171, 4, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0 };
+
+ data.Length.Should().Be(requiredData.Length);
+ for (int i = 0; i < data.Length; i++)
+ {
+ data[i].Should().Be(requiredData[i]);
+ }
}
[TestMethod]
@@ -104,10 +111,14 @@ public void Deserialize()
uut.MerkleRoot = merkRoot; // need to set for deserialise to be valid
- using (MemoryStream ms = new MemoryStream("0000000000000000000000000000000000000000000000000000000000000000000000000f29b0d748a9ccf8c5af3cde10db3e36ec9a5f720643a2bcb4add76b3daf41d880ab04fd0000000000000000000000000000000000000000000000000100015101000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100010000".HexToBytes(), false))
- using (BinaryReader reader = new BinaryReader(ms))
+ byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 41, 176, 215, 72, 169, 204, 248, 197, 175, 60, 222, 16, 219, 62, 54, 236, 154, 95, 114, 6, 67, 162, 188, 180, 173, 215, 107, 61, 175, 65, 216, 128, 171, 4, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };
+ int index = 0;
+ using (MemoryStream ms = new MemoryStream(data, index, data.Length - index, false))
{
- uut.Deserialize(reader);
+ using (BinaryReader reader = new BinaryReader(ms))
+ {
+ uut.Deserialize(reader);
+ }
}
assertStandardBlockTestVals(val256, merkRoot, val160, timestampVal, indexVal, scriptVal, transactionsVal);
diff --git a/neo/Network/P2P/Payloads/Block.cs b/neo/Network/P2P/Payloads/Block.cs
index b63035e0ed..58faf54cb1 100644
--- a/neo/Network/P2P/Payloads/Block.cs
+++ b/neo/Network/P2P/Payloads/Block.cs
@@ -12,7 +12,7 @@ namespace Neo.Network.P2P.Payloads
public class Block : BlockBase, IInventory, IEquatable
{
public const int MaxContentsPerBlock = ushort.MaxValue;
- public const int MaxTransactionsPerBlock = MaxContentsPerBlock;
+ public const int MaxTransactionsPerBlock = MaxContentsPerBlock - 1;
public ConsensusData ConsensusData;
public Transaction[] Transactions;
@@ -41,13 +41,13 @@ public Header Header
InventoryType IInventory.InventoryType => InventoryType.Block;
public override int Size => base.Size
- + IO.Helper.GetVarSize(Transactions.Length) //Count
+ + IO.Helper.GetVarSize(Transactions.Length + 1) //Count
+ ConsensusData.Size //ConsensusData
+ Transactions.Sum(p => p.Size); //Transactions
public static UInt256 CalculateMerkleRoot(UInt256 consensusDataHash, params UInt256[] transactionHashes)
{
- List hashes = new List(transactionHashes.Length) { consensusDataHash };
+ List hashes = new List(transactionHashes.Length + 1) { consensusDataHash };
hashes.AddRange(transactionHashes);
return MerkleTree.ComputeRoot(hashes);
}
@@ -58,7 +58,7 @@ public override void Deserialize(BinaryReader reader)
int count = (int)reader.ReadVarInt(MaxContentsPerBlock);
if (count == 0) throw new FormatException();
ConsensusData = reader.ReadSerializable();
- Transactions = new Transaction[count];
+ Transactions = new Transaction[count - 1];
for (int i = 0; i < Transactions.Length; i++)
Transactions[i] = reader.ReadSerializable();
if (Transactions.Distinct().Count() != Transactions.Length)
@@ -76,8 +76,7 @@ public bool Equals(Block other)
public override bool Equals(object obj)
{
- if (!(obj is Block b)) return false;
- return Equals(b);
+ return Equals(obj as Block);
}
public override int GetHashCode()
@@ -93,7 +92,7 @@ public void RebuildMerkleRoot()
public override void Serialize(BinaryWriter writer)
{
base.Serialize(writer);
- writer.WriteVarInt(Transactions.Length);
+ writer.WriteVarInt(Transactions.Length + 1);
writer.Write(ConsensusData);
foreach (Transaction tx in Transactions)
writer.Write(tx);
From 7a0e82f0650a50bcf9543c42e7d16e179de79ad4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vitor=20Naz=C3=A1rio=20Coelho?=
Date: Mon, 22 Jul 2019 14:21:38 -0300
Subject: [PATCH 049/305] Seconds to milliseconds (#918)
* Seconds to milliseconds
* Sending unsaved files
* fixing formula of consensus bonification
* Refactoring milliseconds
* Refactoring milliseconds from capeslock
* Refactoring milliseconds from capeslock II
* Adjusting UT
* Adjusting UT II
* Super fast protocol to 2s
* Fixing timestamps to long and tests
* Minor adjusts
* Change view deserialization fix
* Timestamp to ulong
* Update neo/Helper.cs
Co-Authored-By: Shargon
* Update JNumber.cs
* Optimize and remove TODO
* Update ApplicationEngine.cs
* Fixing ExtendTimerByFactor
This was already from milliseconds, thus, just removing the multiplier
---
neo.UnitTests/TestUtils.cs | 9 +++---
neo.UnitTests/UT_Block.cs | 31 ++++++++++---------
neo.UnitTests/UT_Consensus.cs | 18 +++++------
neo.UnitTests/UT_Header.cs | 16 +++++-----
neo.UnitTests/protocol.json | 2 +-
neo/Consensus/ChangeView.cs | 6 ++--
neo/Consensus/ConsensusContext.cs | 8 ++---
neo/Consensus/ConsensusService.cs | 18 +++++------
neo/Consensus/PrepareRequest.cs | 6 ++--
...ecoveryMessage.ChangeViewPayloadCompact.cs | 6 ++--
neo/Consensus/RecoveryRequest.cs | 6 ++--
neo/Helper.cs | 14 +++------
neo/IO/Json/JNumber.cs | 7 -----
neo/Ledger/Blockchain.cs | 11 ++++---
neo/Ledger/MemoryPool.cs | 16 +++++-----
neo/Network/P2P/Payloads/BlockBase.cs | 16 +++++++---
neo/ProtocolSettings.cs | 4 +--
neo/SmartContract/ApplicationEngine.cs | 18 +++++++----
18 files changed, 111 insertions(+), 101 deletions(-)
diff --git a/neo.UnitTests/TestUtils.cs b/neo.UnitTests/TestUtils.cs
index 9bf06acbf7..fd06f0ba1b 100644
--- a/neo.UnitTests/TestUtils.cs
+++ b/neo.UnitTests/TestUtils.cs
@@ -36,12 +36,12 @@ public static Transaction GetTransaction()
};
}
- public static void SetupHeaderWithValues(Header header, UInt256 val256, out UInt256 merkRootVal, out UInt160 val160, out uint timestampVal, out uint indexVal, out Witness scriptVal)
+ public static void SetupHeaderWithValues(Header header, UInt256 val256, out UInt256 merkRootVal, out UInt160 val160, out ulong timestampVal, out uint indexVal, out Witness scriptVal)
{
setupBlockBaseWithValues(header, val256, out merkRootVal, out val160, out timestampVal, out indexVal, out scriptVal);
}
- public static void SetupBlockWithValues(Block block, UInt256 val256, out UInt256 merkRootVal, out UInt160 val160, out uint timestampVal, out uint indexVal, out Witness scriptVal, out Transaction[] transactionsVal, int numberOfTransactions)
+ public static void SetupBlockWithValues(Block block, UInt256 val256, out UInt256 merkRootVal, out UInt160 val160, out ulong timestampVal, out uint indexVal, out Witness scriptVal, out Transaction[] transactionsVal, int numberOfTransactions)
{
setupBlockBaseWithValues(block, val256, out merkRootVal, out val160, out timestampVal, out indexVal, out scriptVal);
@@ -58,13 +58,12 @@ public static void SetupBlockWithValues(Block block, UInt256 val256, out UInt256
block.Transactions = transactionsVal;
}
- private static void setupBlockBaseWithValues(BlockBase bb, UInt256 val256, out UInt256 merkRootVal, out UInt160 val160, out uint timestampVal, out uint indexVal, out Witness scriptVal)
+ private static void setupBlockBaseWithValues(BlockBase bb, UInt256 val256, out UInt256 merkRootVal, out UInt160 val160, out ulong timestampVal, out uint indexVal, out Witness scriptVal)
{
bb.PrevHash = val256;
merkRootVal = UInt256.Parse("0xd841af3d6bd7adb4bca24306725f9aec363edb10de3cafc5f8cca948d7b0290f");
-
bb.MerkleRoot = merkRootVal;
- timestampVal = new DateTime(1968, 06, 01, 0, 0, 0, DateTimeKind.Utc).ToTimestamp();
+ timestampVal = new DateTime(1980, 06, 01, 0, 0, 1, 001, DateTimeKind.Utc).ToTimestampMS(); // GMT: Sunday, June 1, 1980 12:00:01.001 AM
bb.Timestamp = timestampVal;
indexVal = 0;
bb.Index = indexVal;
diff --git a/neo.UnitTests/UT_Block.cs b/neo.UnitTests/UT_Block.cs
index 886f5099f0..c91776f0c0 100644
--- a/neo.UnitTests/UT_Block.cs
+++ b/neo.UnitTests/UT_Block.cs
@@ -43,9 +43,9 @@ public void Size_Get()
{
UInt256 val256 = UInt256.Zero;
TestUtils.SetupBlockWithValues(uut, val256, out var _, out var _, out var _, out var _, out var _, out var _, 0);
- // blockbase 4 + 32 + 32 + 4 + 4 + 20 + 4
+ // blockbase 4 + 64 + 32 + 4 + 4 + 20 + 4
// block 9 + 1
- uut.Size.Should().Be(110);
+ uut.Size.Should().Be(114);
}
[TestMethod]
@@ -59,7 +59,7 @@ public void Size_Get_1_Transaction()
TestUtils.GetTransaction()
};
- uut.Size.Should().Be(161);
+ uut.Size.Should().Be(165);
}
[TestMethod]
@@ -75,7 +75,7 @@ public void Size_Get_3_Transaction()
TestUtils.GetTransaction()
};
- uut.Size.Should().Be(263);
+ uut.Size.Should().Be(267);
}
[TestMethod]
@@ -94,8 +94,7 @@ public void Serialize()
}
}
- byte[] requiredData = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 41, 176, 215, 72, 169, 204, 248, 197, 175, 60, 222, 16, 219, 62, 54, 236, 154, 95, 114, 6, 67, 162, 188, 180, 173, 215, 107, 61, 175, 65, 216, 128, 171, 4, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0 };
-
+ byte[] requiredData = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 41, 176, 215, 72, 169, 204, 248, 197, 175, 60, 222, 16, 219, 62, 54, 236, 154, 95, 114, 6, 67, 162, 188, 180, 173, 215, 107, 61, 175, 65, 216, 233, 19, 255, 133, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0 };
data.Length.Should().Be(requiredData.Length);
for (int i = 0; i < data.Length; i++)
{
@@ -111,7 +110,8 @@ public void Deserialize()
uut.MerkleRoot = merkRoot; // need to set for deserialise to be valid
- byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 41, 176, 215, 72, 169, 204, 248, 197, 175, 60, 222, 16, 219, 62, 54, 236, 154, 95, 114, 6, 67, 162, 188, 180, 173, 215, 107, 61, 175, 65, 216, 128, 171, 4, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 };
+ byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 41, 176, 215, 72, 169, 204, 248, 197, 175, 60, 222, 16, 219, 62, 54, 236, 154, 95, 114, 6, 67, 162, 188, 180, 173, 215, 107, 61, 175, 65, 216, 233, 19, 255, 133, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0 };
+
int index = 0;
using (MemoryStream ms = new MemoryStream(data, index, data.Length - index, false))
{
@@ -124,7 +124,7 @@ public void Deserialize()
assertStandardBlockTestVals(val256, merkRoot, val160, timestampVal, indexVal, scriptVal, transactionsVal);
}
- private void assertStandardBlockTestVals(UInt256 val256, UInt256 merkRoot, UInt160 val160, uint timestampVal, uint indexVal, Witness scriptVal, Transaction[] transactionsVal, bool testTransactions = true)
+ private void assertStandardBlockTestVals(UInt256 val256, UInt256 merkRoot, UInt160 val160, ulong timestampVal, uint indexVal, Witness scriptVal, Transaction[] transactionsVal, bool testTransactions = true)
{
uut.PrevHash.Should().Be(val256);
uut.MerkleRoot.Should().Be(merkRoot);
@@ -155,7 +155,8 @@ public void Equals_DiffObj()
UInt256 prevHash = new UInt256(TestUtils.GetByteArray(32, 0x42));
UInt256 merkRoot;
UInt160 val160;
- uint timestampVal, indexVal;
+ ulong timestampVal;
+ uint indexVal;
Witness scriptVal;
Transaction[] transactionsVal;
TestUtils.SetupBlockWithValues(newBlock, val256, out merkRoot, out val160, out timestampVal, out indexVal, out scriptVal, out transactionsVal, 1);
@@ -178,7 +179,8 @@ public void Equals_SameHash()
UInt256 prevHash = new UInt256(TestUtils.GetByteArray(32, 0x42));
UInt256 merkRoot;
UInt160 val160;
- uint timestampVal, indexVal;
+ ulong timestampVal;
+ uint indexVal;
Witness scriptVal;
Transaction[] transactionsVal;
TestUtils.SetupBlockWithValues(newBlock, prevHash, out merkRoot, out val160, out timestampVal, out indexVal, out scriptVal, out transactionsVal, 1);
@@ -193,7 +195,8 @@ public void RebuildMerkleRoot_Updates()
UInt256 val256 = UInt256.Zero;
UInt256 merkRoot;
UInt160 val160;
- uint timestampVal, indexVal;
+ ulong timestampVal;
+ uint indexVal;
Witness scriptVal;
Transaction[] transactionsVal;
TestUtils.SetupBlockWithValues(uut, val256, out merkRoot, out val160, out timestampVal, out indexVal, out scriptVal, out transactionsVal, 1);
@@ -214,12 +217,12 @@ public void ToJson()
JObject jObj = uut.ToJson();
jObj.Should().NotBeNull();
- jObj["hash"].AsString().Should().Be("0x1d8642796276c8ce3c5c03b8984a1b593d99b49a63d830bb06f800b8c953be77");
- jObj["size"].AsNumber().Should().Be(161);
+ jObj["hash"].AsString().Should().Be("0x4e1d8392e7c44830e7e45c18e5e0e3ef3c36af883868846d3691a436a62494b2");
+ jObj["size"].AsNumber().Should().Be(165);
jObj["version"].AsNumber().Should().Be(0);
jObj["previousblockhash"].AsString().Should().Be("0x0000000000000000000000000000000000000000000000000000000000000000");
jObj["merkleroot"].AsString().Should().Be("0xd841af3d6bd7adb4bca24306725f9aec363edb10de3cafc5f8cca948d7b0290f");
- jObj["time"].AsNumber().Should().Be(4244941696);
+ jObj["time"].AsNumber().Should().Be(328665601001);
jObj["index"].AsNumber().Should().Be(0);
jObj["nextconsensus"].AsString().Should().Be("AFmseVrdL9f9oyCzZefL9tG6UbvhPbdYzM");
diff --git a/neo.UnitTests/UT_Consensus.cs b/neo.UnitTests/UT_Consensus.cs
index d410bb5142..c5bf1828f8 100644
--- a/neo.UnitTests/UT_Consensus.cs
+++ b/neo.UnitTests/UT_Consensus.cs
@@ -47,10 +47,10 @@ public void ConsensusService_Primary_Sends_PrepareRequest_After_OnStart()
int timeIndex = 0;
var timeValues = new[] {
//new DateTime(1968, 06, 01, 0, 0, 15, DateTimeKind.Utc), // For tests here
- new DateTime(1968, 06, 01, 0, 0, 1, DateTimeKind.Utc), // For receiving block
- new DateTime(1968, 06, 01, 0, 0, (int) Blockchain.SecondsPerBlock, DateTimeKind.Utc), // For Initialize
- new DateTime(1968, 06, 01, 0, 0, 15, DateTimeKind.Utc), // unused
- new DateTime(1968, 06, 01, 0, 0, 15, DateTimeKind.Utc) // unused
+ new DateTime(1980, 06, 01, 0, 0, 1, 001, DateTimeKind.Utc), // For receiving block
+ new DateTime(1980, 06, 01, 0, 0, (int) Blockchain.MillisecondsPerBlock / 1000, 100, DateTimeKind.Utc), // For Initialize
+ new DateTime(1980, 06, 01, 0, 0, 15, 001, DateTimeKind.Utc), // unused
+ new DateTime(1980, 06, 01, 0, 0, 15, 001, DateTimeKind.Utc) // unused
};
//TimeProvider.Current.UtcNow.ToTimestamp().Should().Be(4244941711); //1968-06-01 00:00:15
@@ -74,12 +74,12 @@ public void ConsensusService_Primary_Sends_PrepareRequest_After_OnStart()
// Creating proposed block
Header header = new Header();
- TestUtils.SetupHeaderWithValues(header, UInt256.Zero, out UInt256 merkRootVal, out UInt160 val160, out uint timestampVal, out uint indexVal, out Witness scriptVal);
- header.Size.Should().Be(101);
+ TestUtils.SetupHeaderWithValues(header, UInt256.Zero, out UInt256 merkRootVal, out UInt160 val160, out ulong timestampVal, out uint indexVal, out Witness scriptVal);
+ header.Size.Should().Be(105);
- Console.WriteLine($"header {header} hash {header.Hash} timstamp {timestampVal}");
+ Console.WriteLine($"header {header} hash {header.Hash} timestamp {timestampVal}");
- timestampVal.Should().Be(4244941696); //1968-06-01 00:00:00
+ timestampVal.Should().Be(328665601001); // GMT: Sunday, June 1, 1980 12:00:01.001 AM
// check basic ConsensusContext
//mockConsensusContext.Object.block_received_time.ToTimestamp().Should().Be(4244941697); //1968-06-01 00:00:01
@@ -197,7 +197,7 @@ public void TestSerializeAndDeserializeConsensusContext()
consensusContext.CommitPayloads[6] = MakeSignedPayload(consensusContext, new Commit { Signature = sha256.ComputeHash(testTx2.Hash.ToArray()) }, 3, new[] { (byte)'6', (byte)'7' });
}
- consensusContext.Block.Timestamp = TimeProvider.Current.UtcNow.ToTimestamp();
+ consensusContext.Block.Timestamp = TimeProvider.Current.UtcNow.ToTimestampMS();
consensusContext.ChangeViewPayloads = new ConsensusPayload[consensusContext.Validators.Length];
consensusContext.ChangeViewPayloads[0] = MakeSignedPayload(consensusContext, new ChangeView { ViewNumber = 1, Timestamp = 6 }, 0, new[] { (byte)'A' });
diff --git a/neo.UnitTests/UT_Header.cs b/neo.UnitTests/UT_Header.cs
index 82744a7f8b..f07be59051 100644
--- a/neo.UnitTests/UT_Header.cs
+++ b/neo.UnitTests/UT_Header.cs
@@ -22,22 +22,23 @@ public void Size_Get()
{
UInt256 val256 = UInt256.Zero;
TestUtils.SetupHeaderWithValues(uut, val256, out _, out _, out _, out _, out _);
- // blockbase 4 + 32 + 32 + 4 + 4 + 20 + 4
+ // blockbase 4 + 64 + 32 + 4 + 4 + 20 + 4
// header 1
- uut.Size.Should().Be(101);
+ uut.Size.Should().Be(105);
}
[TestMethod]
public void Deserialize()
{
UInt256 val256 = UInt256.Zero;
- TestUtils.SetupHeaderWithValues(new Header(), val256, out UInt256 merkRoot, out UInt160 val160, out uint timestampVal, out uint indexVal, out Witness scriptVal);
+ TestUtils.SetupHeaderWithValues(new Header(), val256, out UInt256 merkRoot, out UInt160 val160, out ulong timestampVal, out uint indexVal, out Witness scriptVal);
uut.MerkleRoot = merkRoot; // need to set for deserialise to be valid
- byte[] data = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 41, 176, 215, 72, 169, 204, 248, 197, 175, 60, 222, 16, 219, 62, 54, 236, 154, 95, 114, 6, 67, 162, 188, 180, 173, 215, 107, 61, 175, 65, 216, 128, 171, 4, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 0 };
+ byte[] requiredData = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 41, 176, 215, 72, 169, 204, 248, 197, 175, 60, 222, 16, 219, 62, 54, 236, 154, 95, 114, 6, 67, 162, 188, 180, 173, 215, 107, 61, 175, 65, 216, 233, 19, 255, 133, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 0 };
+
int index = 0;
- using (MemoryStream ms = new MemoryStream(data, index, data.Length - index, false))
+ using (MemoryStream ms = new MemoryStream(requiredData, index, requiredData.Length - index, false))
{
using (BinaryReader reader = new BinaryReader(ms))
{
@@ -48,7 +49,7 @@ public void Deserialize()
assertStandardHeaderTestVals(val256, merkRoot, val160, timestampVal, indexVal, scriptVal);
}
- private void assertStandardHeaderTestVals(UInt256 val256, UInt256 merkRoot, UInt160 val160, uint timestampVal, uint indexVal, Witness scriptVal)
+ private void assertStandardHeaderTestVals(UInt256 val256, UInt256 merkRoot, UInt160 val160, ulong timestampVal, uint indexVal, Witness scriptVal)
{
uut.PrevHash.Should().Be(val256);
uut.MerkleRoot.Should().Be(merkRoot);
@@ -106,9 +107,10 @@ public void Serialize()
}
}
- byte[] requiredData = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 41, 176, 215, 72, 169, 204, 248, 197, 175, 60, 222, 16, 219, 62, 54, 236, 154, 95, 114, 6, 67, 162, 188, 180, 173, 215, 107, 61, 175, 65, 216, 128, 171, 4, 253, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 0 };
+ byte[] requiredData = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15, 41, 176, 215, 72, 169, 204, 248, 197, 175, 60, 222, 16, 219, 62, 54, 236, 154, 95, 114, 6, 67, 162, 188, 180, 173, 215, 107, 61, 175, 65, 216, 233, 19, 255, 133, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 81, 0 };
data.Length.Should().Be(requiredData.Length);
+
for (int i = 0; i < data.Length; i++)
{
data[i].Should().Be(requiredData[i]);
diff --git a/neo.UnitTests/protocol.json b/neo.UnitTests/protocol.json
index 476a25d4aa..06aec5ccce 100644
--- a/neo.UnitTests/protocol.json
+++ b/neo.UnitTests/protocol.json
@@ -1,5 +1,5 @@
{
"ProtocolConfiguration": {
- "SecondsPerBlock": 2
+ "MillisecondsPerBlock": 2000
}
}
diff --git a/neo/Consensus/ChangeView.cs b/neo/Consensus/ChangeView.cs
index 7d5b3e96eb..4c18b3fb3f 100644
--- a/neo/Consensus/ChangeView.cs
+++ b/neo/Consensus/ChangeView.cs
@@ -14,7 +14,7 @@ public class ChangeView : ConsensusMessage
/// they only respond once to a specific ChangeView request (it thus prevents replay of the ChangeView
/// message from repeatedly broadcasting RecoveryMessages).
///
- public uint Timestamp;
+ public ulong Timestamp;
///
/// Reason
@@ -22,7 +22,7 @@ public class ChangeView : ConsensusMessage
public ChangeViewReason Reason;
public override int Size => base.Size +
- sizeof(uint) + // Timestamp
+ sizeof(ulong) + // Timestamp
sizeof(ChangeViewReason); // Reason
public ChangeView() : base(ConsensusMessageType.ChangeView) { }
@@ -30,7 +30,7 @@ public ChangeView() : base(ConsensusMessageType.ChangeView) { }
public override void Deserialize(BinaryReader reader)
{
base.Deserialize(reader);
- Timestamp = reader.ReadUInt32();
+ Timestamp = reader.ReadUInt64();
Reason = (ChangeViewReason)reader.ReadByte();
}
diff --git a/neo/Consensus/ConsensusContext.cs b/neo/Consensus/ConsensusContext.cs
index 0d6855a623..270536fc89 100644
--- a/neo/Consensus/ConsensusContext.cs
+++ b/neo/Consensus/ConsensusContext.cs
@@ -95,7 +95,7 @@ public void Deserialize(BinaryReader reader)
Reset(0);
if (reader.ReadUInt32() != Block.Version) throw new FormatException();
if (reader.ReadUInt32() != Block.Index) throw new InvalidOperationException();
- Block.Timestamp = reader.ReadUInt32();
+ Block.Timestamp = reader.ReadUInt64();
Block.NextConsensus = reader.ReadSerializable();
if (Block.NextConsensus.Equals(UInt160.Zero))
Block.NextConsensus = null;
@@ -164,7 +164,7 @@ public ConsensusPayload MakeChangeView(ChangeViewReason reason)
return ChangeViewPayloads[MyIndex] = MakeSignedPayload(new ChangeView
{
Reason = reason,
- Timestamp = TimeProvider.Current.UtcNow.ToTimestamp()
+ Timestamp = TimeProvider.Current.UtcNow.ToTimestampMS()
});
}
@@ -216,7 +216,7 @@ public ConsensusPayload MakePrepareRequest()
List transactions = memoryPoolTransactions.ToList();
TransactionHashes = transactions.Select(p => p.Hash).ToArray();
Transactions = transactions.ToDictionary(p => p.Hash);
- Block.Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestamp(), PrevHeader.Timestamp + 1);
+ Block.Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestampMS(), PrevHeader.Timestamp + 1);
Block.ConsensusData.Nonce = BitConverter.ToUInt64(buffer, 0);
return PreparationPayloads[MyIndex] = MakeSignedPayload(new PrepareRequest
{
@@ -230,7 +230,7 @@ public ConsensusPayload MakeRecoveryRequest()
{
return MakeSignedPayload(new RecoveryRequest
{
- Timestamp = TimeProvider.Current.UtcNow.ToTimestamp()
+ Timestamp = TimeProvider.Current.UtcNow.ToTimestampMS()
});
}
diff --git a/neo/Consensus/ConsensusService.cs b/neo/Consensus/ConsensusService.cs
index b8e594d642..2e850807e4 100644
--- a/neo/Consensus/ConsensusService.cs
+++ b/neo/Consensus/ConsensusService.cs
@@ -139,7 +139,7 @@ private void CheckPreparations()
context.Save();
localNode.Tell(new LocalNode.SendDirectly { Inventory = payload });
// Set timer, so we will resend the commit in case of a networking issue
- ChangeTimer(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock));
+ ChangeTimer(TimeSpan.FromMilliseconds(Blockchain.MillisecondsPerBlock));
CheckCommits();
}
}
@@ -155,7 +155,7 @@ private void InitializeConsensus(byte viewNumber)
{
if (isRecovering)
{
- ChangeTimer(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << (viewNumber + 1)));
+ ChangeTimer(TimeSpan.FromMilliseconds(Blockchain.MillisecondsPerBlock << (viewNumber + 1)));
}
else
{
@@ -168,7 +168,7 @@ private void InitializeConsensus(byte viewNumber)
}
else
{
- ChangeTimer(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << (viewNumber + 1)));
+ ChangeTimer(TimeSpan.FromMilliseconds(Blockchain.MillisecondsPerBlock << (viewNumber + 1)));
}
}
@@ -229,10 +229,10 @@ private void OnCommitReceived(ConsensusPayload payload, Commit commit)
existingCommitPayload = payload;
}
- // this function increases existing timer (never decreases) with a value proportional to `maxDelayInBlockTimes`*`Blockchain.SecondsPerBlock`
+ // this function increases existing timer (never decreases) with a value proportional to `maxDelayInBlockTimes`*`Blockchain.MillisecondsPerBlock`
private void ExtendTimerByFactor(int maxDelayInBlockTimes)
{
- TimeSpan nextDelay = expected_delay - (TimeProvider.Current.UtcNow - clock_started) + TimeSpan.FromMilliseconds(maxDelayInBlockTimes * Blockchain.SecondsPerBlock * 1000.0 / context.M);
+ TimeSpan nextDelay = expected_delay - (TimeProvider.Current.UtcNow - clock_started) + TimeSpan.FromMilliseconds(maxDelayInBlockTimes * Blockchain.MillisecondsPerBlock / context.M);
if (!context.WatchOnly && !context.ViewChanging && !context.CommitSent && (nextDelay > TimeSpan.Zero))
ChangeTimer(nextDelay);
}
@@ -390,7 +390,7 @@ private void OnPrepareRequestReceived(ConsensusPayload payload, PrepareRequest m
if (context.RequestSentOrReceived || context.NotAcceptingPayloadsDueToViewChanging) return;
if (payload.ValidatorIndex != context.Block.ConsensusData.PrimaryIndex || message.ViewNumber != context.ViewNumber) return;
Log($"{nameof(OnPrepareRequestReceived)}: height={payload.BlockIndex} view={message.ViewNumber} index={payload.ValidatorIndex} tx={message.TransactionHashes.Length}");
- if (message.Timestamp <= context.PrevHeader.Timestamp || message.Timestamp > TimeProvider.Current.UtcNow.AddMinutes(10).ToTimestamp())
+ if (message.Timestamp <= context.PrevHeader.Timestamp || message.Timestamp > TimeProvider.Current.UtcNow.AddMinutes(10).ToTimestampMS())
{
Log($"Timestamp incorrect: {message.Timestamp}", LogLevel.Warning);
return;
@@ -543,7 +543,7 @@ private void OnTimer(Timer timer)
// Re-send commit periodically by sending recover message in case of a network issue.
Log($"send recovery to resend commit");
localNode.Tell(new LocalNode.SendDirectly { Inventory = context.MakeRecoveryMessage() });
- ChangeTimer(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << 1));
+ ChangeTimer(TimeSpan.FromMilliseconds(Blockchain.MillisecondsPerBlock << 1));
}
else
{
@@ -590,7 +590,7 @@ private void RequestChangeView(ChangeViewReason reason)
// The latter may happen by nodes in higher views with, at least, `M` proofs
byte expectedView = context.ViewNumber;
expectedView++;
- ChangeTimer(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << (expectedView + 1)));
+ ChangeTimer(TimeSpan.FromMilliseconds(Blockchain.MillisecondsPerBlock << (expectedView + 1)));
if ((context.CountCommitted + context.CountFailed) > context.F)
{
Log($"Skip requesting change view to nv={expectedView} because nc={context.CountCommitted} nf={context.CountFailed}");
@@ -622,7 +622,7 @@ private void SendPrepareRequest()
foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, context.TransactionHashes))
localNode.Tell(Message.Create(MessageCommand.Inv, payload));
}
- ChangeTimer(TimeSpan.FromSeconds((Blockchain.SecondsPerBlock << (context.ViewNumber + 1)) - (context.ViewNumber == 0 ? Blockchain.SecondsPerBlock : 0)));
+ ChangeTimer(TimeSpan.FromMilliseconds((Blockchain.MillisecondsPerBlock << (context.ViewNumber + 1)) - (context.ViewNumber == 0 ? Blockchain.MillisecondsPerBlock : 0)));
}
}
diff --git a/neo/Consensus/PrepareRequest.cs b/neo/Consensus/PrepareRequest.cs
index 299b0f6a72..85823fe957 100644
--- a/neo/Consensus/PrepareRequest.cs
+++ b/neo/Consensus/PrepareRequest.cs
@@ -8,12 +8,12 @@ namespace Neo.Consensus
{
public class PrepareRequest : ConsensusMessage
{
- public uint Timestamp;
+ public ulong Timestamp;
public ulong Nonce;
public UInt256[] TransactionHashes;
public override int Size => base.Size
- + sizeof(uint) //Timestamp
+ + sizeof(ulong) //Timestamp
+ sizeof(ulong) //Nonce
+ TransactionHashes.GetVarSize(); //TransactionHashes
@@ -25,7 +25,7 @@ public PrepareRequest()
public override void Deserialize(BinaryReader reader)
{
base.Deserialize(reader);
- Timestamp = reader.ReadUInt32();
+ Timestamp = reader.ReadUInt64();
Nonce = reader.ReadUInt64();
TransactionHashes = reader.ReadSerializableArray(Block.MaxTransactionsPerBlock);
if (TransactionHashes.Distinct().Count() != TransactionHashes.Length)
diff --git a/neo/Consensus/RecoveryMessage.ChangeViewPayloadCompact.cs b/neo/Consensus/RecoveryMessage.ChangeViewPayloadCompact.cs
index 373e7e75a3..6d4d6a7ae2 100644
--- a/neo/Consensus/RecoveryMessage.ChangeViewPayloadCompact.cs
+++ b/neo/Consensus/RecoveryMessage.ChangeViewPayloadCompact.cs
@@ -10,20 +10,20 @@ public class ChangeViewPayloadCompact : ISerializable
{
public ushort ValidatorIndex;
public byte OriginalViewNumber;
- public uint Timestamp;
+ public ulong Timestamp;
public byte[] InvocationScript;
int ISerializable.Size =>
sizeof(ushort) + //ValidatorIndex
sizeof(byte) + //OriginalViewNumber
- sizeof(uint) + //Timestamp
+ sizeof(ulong) + //Timestamp
InvocationScript.GetVarSize(); //InvocationScript
void ISerializable.Deserialize(BinaryReader reader)
{
ValidatorIndex = reader.ReadUInt16();
OriginalViewNumber = reader.ReadByte();
- Timestamp = reader.ReadUInt32();
+ Timestamp = reader.ReadUInt64();
InvocationScript = reader.ReadVarBytes(1024);
}
diff --git a/neo/Consensus/RecoveryRequest.cs b/neo/Consensus/RecoveryRequest.cs
index 971b49a324..c02ceb176c 100644
--- a/neo/Consensus/RecoveryRequest.cs
+++ b/neo/Consensus/RecoveryRequest.cs
@@ -9,17 +9,17 @@ public class RecoveryRequest : ConsensusMessage
/// they only respond once to a specific RecoveryRequest request.
/// In this sense, it prevents replay of the RecoveryRequest message from the repeatedly broadcast of Recovery's messages.
///
- public uint Timestamp;
+ public ulong Timestamp;
public override int Size => base.Size
- + sizeof(uint); //Timestamp
+ + sizeof(ulong); //Timestamp
public RecoveryRequest() : base(ConsensusMessageType.RecoveryRequest) { }
public override void Deserialize(BinaryReader reader)
{
base.Deserialize(reader);
- Timestamp = reader.ReadUInt32();
+ Timestamp = reader.ReadUInt64();
}
public override void Serialize(BinaryWriter writer)
diff --git a/neo/Helper.cs b/neo/Helper.cs
index 8c562740bd..d8409b64bd 100644
--- a/neo/Helper.cs
+++ b/neo/Helper.cs
@@ -140,15 +140,6 @@ internal static bool TestBit(this BigInteger i, int index)
return (i & (BigInteger.One << index)) > BigInteger.Zero;
}
- public static DateTime ToDateTime(this uint timestamp)
- {
- return unixEpoch.AddSeconds(timestamp).ToLocalTime();
- }
-
- public static DateTime ToDateTime(this ulong timestamp)
- {
- return unixEpoch.AddSeconds(timestamp).ToLocalTime();
- }
public static string ToHexString(this IEnumerable value)
{
@@ -181,6 +172,11 @@ public static uint ToTimestamp(this DateTime time)
return (uint)(time.ToUniversalTime() - unixEpoch).TotalSeconds;
}
+ public static ulong ToTimestampMS(this DateTime time)
+ {
+ return (ulong)(time.ToUniversalTime() - unixEpoch).TotalMilliseconds;
+ }
+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
unsafe internal static ushort ToUInt16(this byte[] value, int startIndex)
{
diff --git a/neo/IO/Json/JNumber.cs b/neo/IO/Json/JNumber.cs
index f9fa5e05e5..2a23dc3157 100644
--- a/neo/IO/Json/JNumber.cs
+++ b/neo/IO/Json/JNumber.cs
@@ -101,13 +101,6 @@ public override string ToString()
return AsString();
}
- public DateTime ToTimestamp()
- {
- if (Value < 0 || Value > ulong.MaxValue)
- throw new InvalidCastException();
- return ((ulong)Value).ToDateTime();
- }
-
public override T TryGetEnum(T defaultValue = default, bool ignoreCase = false)
{
Type enumType = typeof(T);
diff --git a/neo/Ledger/Blockchain.cs b/neo/Ledger/Blockchain.cs
index 5d9ad00ee9..854583423d 100644
--- a/neo/Ledger/Blockchain.cs
+++ b/neo/Ledger/Blockchain.cs
@@ -27,17 +27,17 @@ public class ImportCompleted { }
public class FillMemoryPool { public IEnumerable Transactions; }
public class FillCompleted { }
- public static readonly uint SecondsPerBlock = ProtocolSettings.Default.SecondsPerBlock;
+ public static readonly uint MillisecondsPerBlock = ProtocolSettings.Default.MillisecondsPerBlock;
public const uint DecrementInterval = 2000000;
public const int MaxValidators = 1024;
public static readonly uint[] GenerationAmount = { 6, 5, 4, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
- public static readonly TimeSpan TimePerBlock = TimeSpan.FromSeconds(SecondsPerBlock);
+ public static readonly TimeSpan TimePerBlock = TimeSpan.FromMilliseconds(MillisecondsPerBlock);
public static readonly ECPoint[] StandbyValidators = ProtocolSettings.Default.StandbyValidators.OfType().Select(p => ECPoint.DecodePoint(p.HexToBytes(), ECCurve.Secp256r1)).ToArray();
public static readonly Block GenesisBlock = new Block
{
PrevHash = UInt256.Zero,
- Timestamp = (new DateTime(2016, 7, 15, 15, 8, 21, DateTimeKind.Utc)).ToTimestamp(),
+ Timestamp = (new DateTime(2016, 7, 15, 15, 8, 21, DateTimeKind.Utc)).ToTimestampMS(),
Index = 0,
NextConsensus = GetConsensusAddress(StandbyValidators),
Witness = new Witness
@@ -283,7 +283,10 @@ private RelayResultReason OnNewBlock(Block block)
block_cache_unverified.Remove(blockToPersist.Index);
Persist(blockToPersist);
- if (blocksPersisted++ < blocksToPersistList.Count - (2 + Math.Max(0, (15 - SecondsPerBlock)))) continue;
+ // 15000 is the default among of seconds per block, while MilliSecondsPerBlock is the current
+ uint extraBlocks = (15000 - MillisecondsPerBlock) / 1000;
+
+ if (blocksPersisted++ < blocksToPersistList.Count - (2 + Math.Max(0, extraBlocks))) continue;
// Empirically calibrated for relaying the most recent 2 blocks persisted with 15s network
// Increase in the rate of 1 block per second in configurations with faster blocks
diff --git a/neo/Ledger/MemoryPool.cs b/neo/Ledger/MemoryPool.cs
index 96e17dc34f..912ea69c73 100644
--- a/neo/Ledger/MemoryPool.cs
+++ b/neo/Ledger/MemoryPool.cs
@@ -21,10 +21,10 @@ public class MemoryPool : IReadOnlyCollection
private const int BlocksTillRebroadcastHighPriorityPoolTx = 10;
private int RebroadcastMultiplierThreshold => Capacity / 10;
- private static readonly double MaxSecondsToReverifyTx = (double)Blockchain.SecondsPerBlock / 3;
+ private static readonly double MaxMillisecondsToReverifyTx = (double)Blockchain.MillisecondsPerBlock / 3;
// These two are not expected to be hit, they are just safegaurds.
- private static readonly double MaxSecondsToReverifyTxPerIdle = (double)Blockchain.SecondsPerBlock / 15;
+ private static readonly double MaxMillisecondsToReverifyTxPerIdle = (double)Blockchain.MillisecondsPerBlock / 15;
private readonly NeoSystem _system;
@@ -378,7 +378,7 @@ internal void UpdatePoolForBlockPersisted(Block block, Snapshot snapshot)
return;
ReverifyTransactions(_sortedTransactions, _unverifiedSortedTransactions,
- _maxTxPerBlock, MaxSecondsToReverifyTx, snapshot);
+ _maxTxPerBlock, MaxMillisecondsToReverifyTx, snapshot);
}
internal void InvalidateAllTransactions()
@@ -395,9 +395,9 @@ internal void InvalidateAllTransactions()
}
private int ReverifyTransactions(SortedSet verifiedSortedTxPool,
- SortedSet unverifiedSortedTxPool, int count, double secondsTimeout, Snapshot snapshot)
+ SortedSet unverifiedSortedTxPool, int count, double millisecondsTimeout, Snapshot snapshot)
{
- DateTime reverifyCutOffTimeStamp = DateTime.UtcNow.AddSeconds(secondsTimeout);
+ DateTime reverifyCutOffTimeStamp = DateTime.UtcNow.AddMilliseconds(millisecondsTimeout);
List reverifiedItems = new List(count);
List invalidItems = new List();
@@ -421,8 +421,8 @@ private int ReverifyTransactions(SortedSet verifiedSortedTxPool,
if (Count > RebroadcastMultiplierThreshold)
blocksTillRebroadcast = blocksTillRebroadcast * Count / RebroadcastMultiplierThreshold;
- var rebroadcastCutOffTime = DateTime.UtcNow.AddSeconds(
- -Blockchain.SecondsPerBlock * blocksTillRebroadcast);
+ var rebroadcastCutOffTime = DateTime.UtcNow.AddMilliseconds(
+ -Blockchain.MillisecondsPerBlock * blocksTillRebroadcast);
foreach (PoolItem item in reverifiedItems)
{
if (_unsortedTransactions.TryAdd(item.Tx.Hash, item))
@@ -477,7 +477,7 @@ internal bool ReVerifyTopUnverifiedTransactionsIfNeeded(int maxToVerify, Snapsho
{
int verifyCount = _sortedTransactions.Count > _maxTxPerBlock ? 1 : maxToVerify;
ReverifyTransactions(_sortedTransactions, _unverifiedSortedTransactions,
- verifyCount, MaxSecondsToReverifyTxPerIdle, snapshot);
+ verifyCount, MaxMillisecondsToReverifyTxPerIdle, snapshot);
}
return _unverifiedTransactions.Count > 0;
diff --git a/neo/Network/P2P/Payloads/BlockBase.cs b/neo/Network/P2P/Payloads/BlockBase.cs
index 9f56ca0d97..22ef72d021 100644
--- a/neo/Network/P2P/Payloads/BlockBase.cs
+++ b/neo/Network/P2P/Payloads/BlockBase.cs
@@ -14,7 +14,7 @@ public abstract class BlockBase : IVerifiable
public uint Version;
public UInt256 PrevHash;
public UInt256 MerkleRoot;
- public uint Timestamp;
+ public ulong Timestamp;
public uint Index;
public UInt160 NextConsensus;
public Witness Witness;
@@ -32,8 +32,16 @@ public UInt256 Hash
}
}
- public virtual int Size => sizeof(uint) + PrevHash.Size + MerkleRoot.Size + sizeof(uint) + sizeof(uint) + NextConsensus.Size + 1 + Witness.Size;
-
+ public virtual int Size =>
+ sizeof(uint) + //Version
+ PrevHash.Size + //PrevHash
+ MerkleRoot.Size + //MerkleRoot
+ sizeof(ulong) + //Timestamp
+ sizeof(uint) + //Index
+ NextConsensus.Size + //NextConsensus
+ 1 + //
+ Witness.Size; //Witness
+
Witness[] IVerifiable.Witnesses
{
get
@@ -59,7 +67,7 @@ void IVerifiable.DeserializeUnsigned(BinaryReader reader)
Version = reader.ReadUInt32();
PrevHash = reader.ReadSerializable();
MerkleRoot = reader.ReadSerializable();
- Timestamp = reader.ReadUInt32();
+ Timestamp = reader.ReadUInt64();
Index = reader.ReadUInt32();
NextConsensus = reader.ReadSerializable();
}
diff --git a/neo/ProtocolSettings.cs b/neo/ProtocolSettings.cs
index ba4c192e8b..b690cd7602 100644
--- a/neo/ProtocolSettings.cs
+++ b/neo/ProtocolSettings.cs
@@ -10,7 +10,7 @@ public class ProtocolSettings
public byte AddressVersion { get; }
public string[] StandbyValidators { get; }
public string[] SeedList { get; }
- public uint SecondsPerBlock { get; }
+ public uint MillisecondsPerBlock { get; }
static ProtocolSettings _default;
@@ -69,7 +69,7 @@ private ProtocolSettings(IConfigurationSection section)
"seed4.neo.org:10333",
"seed5.neo.org:10333"
};
- this.SecondsPerBlock = section.GetValue("SecondsPerBlock", 15u);
+ this.MillisecondsPerBlock = section.GetValue("SecondsPerBlock", 15000u);
}
}
}
diff --git a/neo/SmartContract/ApplicationEngine.cs b/neo/SmartContract/ApplicationEngine.cs
index ced43d379e..03a098530a 100644
--- a/neo/SmartContract/ApplicationEngine.cs
+++ b/neo/SmartContract/ApplicationEngine.cs
@@ -83,18 +83,18 @@ protected override bool PreExecuteInstruction()
return true;
return AddGas(OpCodePrices[CurrentContext.CurrentInstruction.OpCode]);
}
-
- public static ApplicationEngine Run(byte[] script, Snapshot snapshot,
- IVerifiable container = null, Block persistingBlock = null, bool testMode = false, long extraGAS = default)
+
+ private static Block CreateDummyBlock(Snapshot snapshot)
{
- snapshot.PersistingBlock = persistingBlock ?? snapshot.PersistingBlock ?? new Block
+ var currentBlock = snapshot.Blocks[snapshot.CurrentBlockHash];
+ return new Block
{
Version = 0,
PrevHash = snapshot.CurrentBlockHash,
MerkleRoot = new UInt256(),
- Timestamp = snapshot.Blocks[snapshot.CurrentBlockHash].Timestamp + Blockchain.SecondsPerBlock,
+ Timestamp = currentBlock.Timestamp + Blockchain.MillisecondsPerBlock,
Index = snapshot.Height + 1,
- NextConsensus = snapshot.Blocks[snapshot.CurrentBlockHash].NextConsensus,
+ NextConsensus = currentBlock.NextConsensus,
Witness = new Witness
{
InvocationScript = new byte[0],
@@ -103,6 +103,12 @@ public static ApplicationEngine Run(byte[] script, Snapshot snapshot,
ConsensusData = new ConsensusData(),
Transactions = new Transaction[0]
};
+ }
+
+ public static ApplicationEngine Run(byte[] script, Snapshot snapshot,
+ IVerifiable container = null, Block persistingBlock = null, bool testMode = false, long extraGAS = default)
+ {
+ snapshot.PersistingBlock = persistingBlock ?? snapshot.PersistingBlock ?? CreateDummyBlock(snapshot);
ApplicationEngine engine = new ApplicationEngine(TriggerType.Application, container, snapshot, extraGAS, testMode);
engine.LoadScript(script);
engine.Execute();
From d3dee6b39c47639f9a6db05e1941cbf633c3aaeb Mon Sep 17 00:00:00 2001
From: Nikolai Perevozchikov
Date: Tue, 23 Jul 2019 15:39:05 +0900
Subject: [PATCH 050/305] allow CheckWitness to work when using invokescript
(#335)
* allow CheckWitness to work when using invokescript
* Fix
* Update RpcServer.cs
* Allow more than one signature
* Reorder properties
---
neo/Network/RPC/RpcServer.cs | 49 +++++++++++++++++++++++++++++++++---
1 file changed, 46 insertions(+), 3 deletions(-)
diff --git a/neo/Network/RPC/RpcServer.cs b/neo/Network/RPC/RpcServer.cs
index 6bfdd15618..c47e6644e7 100644
--- a/neo/Network/RPC/RpcServer.cs
+++ b/neo/Network/RPC/RpcServer.cs
@@ -31,6 +31,43 @@ namespace Neo.Network.RPC
{
public sealed class RpcServer : IDisposable
{
+ private class CheckWitnessHashes : IVerifiable
+ {
+ private readonly UInt160[] _scriptHashesForVerifying;
+ public Witness[] Witnesses { get; set; }
+ public int Size { get; }
+
+ public CheckWitnessHashes(UInt160[] scriptHashesForVerifying)
+ {
+ _scriptHashesForVerifying = scriptHashesForVerifying;
+ }
+
+ public void Serialize(BinaryWriter writer)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Deserialize(BinaryReader reader)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void DeserializeUnsigned(BinaryReader reader)
+ {
+ throw new NotImplementedException();
+ }
+
+ public UInt160[] GetScriptHashesForVerifying(Snapshot snapshot)
+ {
+ return _scriptHashesForVerifying;
+ }
+
+ public void SerializeUnsigned(BinaryWriter writer)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
public Wallet Wallet { get; set; }
public long MaxGasInvoke { get; }
@@ -72,9 +109,9 @@ public void Dispose()
}
}
- private JObject GetInvokeResult(byte[] script)
+ private JObject GetInvokeResult(byte[] script, IVerifiable checkWitnessHashes = null)
{
- ApplicationEngine engine = ApplicationEngine.Run(script, extraGAS: MaxGasInvoke);
+ ApplicationEngine engine = ApplicationEngine.Run(script, checkWitnessHashes, extraGAS: MaxGasInvoke);
JObject json = new JObject();
json["script"] = script.ToHexString();
json["state"] = engine.State;
@@ -202,7 +239,13 @@ private JObject Process(string method, JArray _params)
case "invokescript":
{
byte[] script = _params[0].AsString().HexToBytes();
- return InvokeScript(script);
+ CheckWitnessHashes checkWitnessHashes = null;
+ if (_params.Count > 1)
+ {
+ UInt160[] scriptHashesForVerifying = _params.Skip(1).Select(u => UInt160.Parse(u.AsString())).ToArray();
+ checkWitnessHashes = new CheckWitnessHashes(scriptHashesForVerifying);
+ }
+ return GetInvokeResult(script, checkWitnessHashes);
}
case "listplugins":
{
From e0f6455081217018c04f6eaf3ffec19caf05023b Mon Sep 17 00:00:00 2001
From: Shargon
Date: Tue, 23 Jul 2019 20:50:38 +0200
Subject: [PATCH 051/305] Allow to configure the memory pool capacity (#948)
Making memory pool capacity configurable
---
neo/Ledger/Blockchain.cs | 3 +--
neo/ProtocolSettings.cs | 3 +++
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/neo/Ledger/Blockchain.cs b/neo/Ledger/Blockchain.cs
index 854583423d..ee8e114701 100644
--- a/neo/Ledger/Blockchain.cs
+++ b/neo/Ledger/Blockchain.cs
@@ -53,7 +53,6 @@ public class FillCompleted { }
Transactions = new[] { DeployNativeContracts() }
};
- private const int MemoryPoolMaxTransactions = 50_000;
private const int MaxTxToReverifyPerIdle = 10;
private static readonly object lockObj = new object();
private readonly NeoSystem system;
@@ -89,7 +88,7 @@ static Blockchain()
public Blockchain(NeoSystem system, Store store)
{
this.system = system;
- this.MemPool = new MemoryPool(system, MemoryPoolMaxTransactions);
+ this.MemPool = new MemoryPool(system, ProtocolSettings.Default.MemoryPoolMaxTransactions);
this.Store = store;
lock (lockObj)
{
diff --git a/neo/ProtocolSettings.cs b/neo/ProtocolSettings.cs
index b690cd7602..478d5b71b3 100644
--- a/neo/ProtocolSettings.cs
+++ b/neo/ProtocolSettings.cs
@@ -1,4 +1,5 @@
using Microsoft.Extensions.Configuration;
+using System;
using System.Linq;
using System.Threading;
@@ -11,6 +12,7 @@ public class ProtocolSettings
public string[] StandbyValidators { get; }
public string[] SeedList { get; }
public uint MillisecondsPerBlock { get; }
+ public int MemoryPoolMaxTransactions { get; }
static ProtocolSettings _default;
@@ -70,6 +72,7 @@ private ProtocolSettings(IConfigurationSection section)
"seed5.neo.org:10333"
};
this.MillisecondsPerBlock = section.GetValue("SecondsPerBlock", 15000u);
+ this.MemoryPoolMaxTransactions = Math.Max(1, section.GetValue("MemoryPoolMaxTransactions", 50_000));
}
}
}
From 3151e48c7ea7d87df9944fce2aa82008869359bc Mon Sep 17 00:00:00 2001
From: Erik Zhang
Date: Thu, 25 Jul 2019 20:16:33 +0800
Subject: [PATCH 052/305] Update dependency: Neo.VM v3.0.0-CI00030 (#956)
---
neo/SmartContract/ApplicationEngine.OpCodePrices.cs | 2 --
neo/neo.csproj | 2 +-
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/neo/SmartContract/ApplicationEngine.OpCodePrices.cs b/neo/SmartContract/ApplicationEngine.OpCodePrices.cs
index 05105e2261..9da0f6c75d 100644
--- a/neo/SmartContract/ApplicationEngine.OpCodePrices.cs
+++ b/neo/SmartContract/ApplicationEngine.OpCodePrices.cs
@@ -162,8 +162,6 @@ partial class ApplicationEngine
[OpCode.MIN] = 200,
[OpCode.MAX] = 200,
[OpCode.WITHIN] = 200,
- [OpCode.SHA1] = 300000,
- [OpCode.SHA256] = 1000000,
[OpCode.ARRAYSIZE] = 150,
[OpCode.PACK] = 7000,
[OpCode.UNPACK] = 7000,
diff --git a/neo/neo.csproj b/neo/neo.csproj
index e811c280dd..df29d088f2 100644
--- a/neo/neo.csproj
+++ b/neo/neo.csproj
@@ -29,7 +29,7 @@
-
+
From 30edffa6c82b9f8fd85fb01f773bbc220f2dde4f Mon Sep 17 00:00:00 2001
From: Charis Zhao
Date: Fri, 26 Jul 2019 18:46:28 +0800
Subject: [PATCH 053/305] Unit tests for IO, Cryptography, Wallets and VM
modules (#943)
* testDemo
* add dll lib
* add dbsnapshot dispose
* test get blocks in levelDBStore
* add levelDBStore test funcs
* fix levelDBStore funcs
* add DbCache addInternal
* differ db path
* space
* fix delete internal test
* add test getInternal tryGetInternal move libleveldb.dll
* add dbCache method test
* add store test
* add cache unit tests
* add cache unit tests
* up readonly max_capacity
* fix leveldbexception
* fix comment on UT_Cache
* format
* fix multithread test problem
* up cache
* update travis config
* update travis.yml
* test DbMetaDataCache
* fix db directory
* format and update travis for maxos
* fix mac env travis
* 2019/7/12 10:34
* 2019/7/12 11:01
* remove commented line
* test BigDecimal
* fix format and csproj
* rm coverage.opencover.xml
* update method name
* add UT_P_Helper
* modify UT_P_Helper
* modify UT_P_helper
* Clean ut
* test Base58 & BloomFilter
* Update UT_Cache.cs
* Correct Typo
* test JsonArray
* update namespace
* update namespace
* update format
* update format
* organise folder structure
* add UT_JString
* test JBoolean JNumber & JObject
* 2019/7/16 10:30
add some test case for UInt32Wrapper and SerializableWrapper
* fix timestamp
* test ECDsa and Crypto
* test OrderedDictionary & complete IO.Json tests
* 2019/7/16 17:33
add some test case of SQLiteWallet
* test FIFOSet
* add CloneCache and DataCache unit tests
* fix namespace
* add UT_Cryptography_Helper
* format UT_CloneCache and UT_DataCache
* add UT_DataCache.GetAndChange unit test
* update namespace
* remove comment code
* delete Persistence part
* 2019/7/19 11:07
add some test case for Helper in VM
* Fix Base58 Test
* 2019/7/19 11:33
change some format
* update IOHelper exception assert
* 2019/7/19 14:22
change format
* format IOHelper
* review IO.Wrapper
* review Wallets.SQLite UT
* Test ECFieldElement ECPoint
* refactor package
* format ECDsa
* update namespace
* Code fix
* review cache
* modify UT_JString
* fomat
* using Actin replace with try-catch
* add UT_CloneMetaCache and UT_MetaDataCache
* update namespace
* format UT_DataCache.cs
* Code Fix
* format
* update csproj
* Code fix for UT_ECFieldElement and UT_ECPoint
* Code fix
* format
* update travis
* delete deleteFiles
* fix path and comment
* update travis
* delete test ToTimeStamp
* format UT_*Cache
* update format
* fomat
* use hex extensions in Cryptography_Helper
* remove reflection
* optimization of UT_DataCache
* update namespace
* modify TestSha256
---
neo.UnitTests/{ => Consensus}/UT_Consensus.cs | 16 +-
.../UT_ConsensusServiceMailbox.cs | 2 +-
neo.UnitTests/Cryptography/ECC/UT_ECDsa.cs | 55 ++
.../Cryptography/ECC/UT_ECFieldElement.cs | 69 +++
neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs | 310 ++++++++++
neo.UnitTests/Cryptography/UT_Base58.cs | 31 +
neo.UnitTests/Cryptography/UT_BloomFilter.cs | 69 +++
neo.UnitTests/Cryptography/UT_Crypto.cs | 64 ++
.../Cryptography/UT_Cryptography_Helper.cs | 225 +++++++
neo.UnitTests/{ => Cryptography}/UT_Scrypt.cs | 4 +-
.../Extensions/NativeContractExtensions.cs | 4 +-
.../Nep5NativeContractExtensions.cs | 8 +-
neo.UnitTests/IO/Caching/UT_Cache.cs | 214 +++++++
neo.UnitTests/IO/Caching/UT_CloneCache.cs | 126 ++++
neo.UnitTests/IO/Caching/UT_CloneMetaCache.cs | 48 ++
neo.UnitTests/IO/Caching/UT_DataCache.cs | 347 +++++++++++
neo.UnitTests/IO/Caching/UT_FifoSet.cs | 120 ++++
neo.UnitTests/IO/Caching/UT_MetaDataCache.cs | 76 +++
.../IO/Caching/UT_OrderedDictionary.cs | 87 +++
neo.UnitTests/IO/Json/UT_JArray.cs | 249 ++++++++
neo.UnitTests/IO/Json/UT_JBoolean.cs | 77 +++
neo.UnitTests/IO/Json/UT_JNumber.cs | 67 +++
neo.UnitTests/IO/Json/UT_JObject.cs | 119 ++++
neo.UnitTests/IO/Json/UT_JString.cs | 73 +++
neo.UnitTests/IO/UT_IOHelper.cs | 549 ++++++++++++++++++
.../IO/Wrappers/UT_SerializableWrapper.cs | 50 ++
neo.UnitTests/IO/Wrappers/UT_UInt32Wrapper.cs | 97 ++++
neo.UnitTests/{ => Ledger}/UT_MemoryPool.cs | 2 +-
neo.UnitTests/{ => Ledger}/UT_PoolItem.cs | 2 +-
neo.UnitTests/{ => Ledger}/UT_StorageItem.cs | 2 +-
neo.UnitTests/{ => Ledger}/UT_StorageKey.cs | 2 +-
.../{ => Network/P2P/Payloads}/UT_Block.cs | 2 +-
.../{ => Network/P2P/Payloads}/UT_Header.cs | 2 +-
.../P2P/Payloads}/UT_Transaction.cs | 2 +-
.../{ => Network/P2P/Payloads}/UT_Witness.cs | 2 +-
.../P2P/UT_Message.cs} | 4 +-
.../{ => Network/P2P}/UT_ProtocolHandler.cs | 2 +-
.../P2P}/UT_ProtocolHandlerMailbox.cs | 15 +-
.../{ => Network/P2P}/UT_RemoteNode.cs | 2 +-
.../{ => Network/P2P}/UT_RemoteNodeMailbox.cs | 6 +-
.../P2P}/UT_TaskManagerMailbox.cs | 12 +-
.../Iterators}/UT_ConcatenatedIterator.cs | 2 +-
.../Manifest}/UT_ContractManifest.cs | 2 +-
.../Native/Tokens}/UT_GasToken.cs | 2 +-
.../Native/Tokens}/UT_NeoToken.cs | 2 +-
.../Native/UT_PolicyContract.cs} | 10 +-
.../{ => SmartContract}/UT_InteropPrices.cs | 2 +-
.../{ => SmartContract}/UT_InteropService.cs | 5 +-
.../{ => SmartContract}/UT_JsonSerializer.cs | 2 +-
.../{ => SmartContract}/UT_OpCodePrices.cs | 2 +-
.../{ => SmartContract}/UT_Syscalls.cs | 2 +-
neo.UnitTests/UT_BigDecimal.cs | 191 ++++++
neo.UnitTests/UT_FifoSet.cs | 54 --
neo.UnitTests/UT_ProtocolSettings.cs | 2 +-
neo.UnitTests/VM/UT_Helper.cs | 82 +++
.../{ => Wallets/NEP6}/UT_NEP6Wallet.cs | 2 +-
.../{ => Wallets/NEP6}/UT_ScryptParameters.cs | 2 +-
neo.UnitTests/Wallets/SQLite/UT_Account.cs | 37 ++
neo.UnitTests/Wallets/SQLite/UT_Address.cs | 27 +
neo.UnitTests/Wallets/SQLite/UT_Contract.cs | 65 +++
neo.UnitTests/Wallets/SQLite/UT_Key.cs | 37 ++
.../UT_AssetDescriptor.cs} | 8 +-
neo.UnitTests/neo.UnitTests.csproj | 1 -
neo/Ledger/MemoryPool.cs | 2 +-
64 files changed, 3625 insertions(+), 129 deletions(-)
rename neo.UnitTests/{ => Consensus}/UT_Consensus.cs (97%)
rename neo.UnitTests/{ => Consensus}/UT_ConsensusServiceMailbox.cs (97%)
create mode 100644 neo.UnitTests/Cryptography/ECC/UT_ECDsa.cs
create mode 100644 neo.UnitTests/Cryptography/ECC/UT_ECFieldElement.cs
create mode 100644 neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs
create mode 100644 neo.UnitTests/Cryptography/UT_Base58.cs
create mode 100644 neo.UnitTests/Cryptography/UT_BloomFilter.cs
create mode 100644 neo.UnitTests/Cryptography/UT_Crypto.cs
create mode 100644 neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs
rename neo.UnitTests/{ => Cryptography}/UT_Scrypt.cs (93%)
create mode 100644 neo.UnitTests/IO/Caching/UT_Cache.cs
create mode 100644 neo.UnitTests/IO/Caching/UT_CloneCache.cs
create mode 100644 neo.UnitTests/IO/Caching/UT_CloneMetaCache.cs
create mode 100644 neo.UnitTests/IO/Caching/UT_DataCache.cs
create mode 100644 neo.UnitTests/IO/Caching/UT_FifoSet.cs
create mode 100644 neo.UnitTests/IO/Caching/UT_MetaDataCache.cs
create mode 100644 neo.UnitTests/IO/Caching/UT_OrderedDictionary.cs
create mode 100644 neo.UnitTests/IO/Json/UT_JArray.cs
create mode 100644 neo.UnitTests/IO/Json/UT_JBoolean.cs
create mode 100644 neo.UnitTests/IO/Json/UT_JNumber.cs
create mode 100644 neo.UnitTests/IO/Json/UT_JObject.cs
create mode 100644 neo.UnitTests/IO/Json/UT_JString.cs
create mode 100644 neo.UnitTests/IO/UT_IOHelper.cs
create mode 100644 neo.UnitTests/IO/Wrappers/UT_SerializableWrapper.cs
create mode 100644 neo.UnitTests/IO/Wrappers/UT_UInt32Wrapper.cs
rename neo.UnitTests/{ => Ledger}/UT_MemoryPool.cs (99%)
rename neo.UnitTests/{ => Ledger}/UT_PoolItem.cs (99%)
rename neo.UnitTests/{ => Ledger}/UT_StorageItem.cs (98%)
rename neo.UnitTests/{ => Ledger}/UT_StorageKey.cs (99%)
rename neo.UnitTests/{ => Network/P2P/Payloads}/UT_Block.cs (99%)
rename neo.UnitTests/{ => Network/P2P/Payloads}/UT_Header.cs (99%)
rename neo.UnitTests/{ => Network/P2P/Payloads}/UT_Transaction.cs (99%)
rename neo.UnitTests/{ => Network/P2P/Payloads}/UT_Witness.cs (98%)
rename neo.UnitTests/{UT_P2PMessage.cs => Network/P2P/UT_Message.cs} (98%)
rename neo.UnitTests/{ => Network/P2P}/UT_ProtocolHandler.cs (97%)
rename neo.UnitTests/{ => Network/P2P}/UT_ProtocolHandlerMailbox.cs (98%)
rename neo.UnitTests/{ => Network/P2P}/UT_RemoteNode.cs (98%)
rename neo.UnitTests/{ => Network/P2P}/UT_RemoteNodeMailbox.cs (94%)
rename neo.UnitTests/{ => Network/P2P}/UT_TaskManagerMailbox.cs (93%)
rename neo.UnitTests/{ => SmartContract/Iterators}/UT_ConcatenatedIterator.cs (97%)
rename neo.UnitTests/{ => SmartContract/Manifest}/UT_ContractManifest.cs (99%)
rename neo.UnitTests/{ => SmartContract/Native/Tokens}/UT_GasToken.cs (99%)
rename neo.UnitTests/{ => SmartContract/Native/Tokens}/UT_NeoToken.cs (99%)
rename neo.UnitTests/{UT_Policy.cs => SmartContract/Native/UT_PolicyContract.cs} (94%)
rename neo.UnitTests/{ => SmartContract}/UT_InteropPrices.cs (99%)
rename neo.UnitTests/{ => SmartContract}/UT_InteropService.cs (98%)
rename neo.UnitTests/{ => SmartContract}/UT_JsonSerializer.cs (99%)
rename neo.UnitTests/{ => SmartContract}/UT_OpCodePrices.cs (91%)
rename neo.UnitTests/{ => SmartContract}/UT_Syscalls.cs (98%)
create mode 100644 neo.UnitTests/UT_BigDecimal.cs
delete mode 100644 neo.UnitTests/UT_FifoSet.cs
create mode 100644 neo.UnitTests/VM/UT_Helper.cs
rename neo.UnitTests/{ => Wallets/NEP6}/UT_NEP6Wallet.cs (97%)
rename neo.UnitTests/{ => Wallets/NEP6}/UT_ScryptParameters.cs (97%)
create mode 100644 neo.UnitTests/Wallets/SQLite/UT_Account.cs
create mode 100644 neo.UnitTests/Wallets/SQLite/UT_Address.cs
create mode 100644 neo.UnitTests/Wallets/SQLite/UT_Contract.cs
create mode 100644 neo.UnitTests/Wallets/SQLite/UT_Key.cs
rename neo.UnitTests/{UT_AssetDescription.cs => Wallets/UT_AssetDescriptor.cs} (78%)
diff --git a/neo.UnitTests/UT_Consensus.cs b/neo.UnitTests/Consensus/UT_Consensus.cs
similarity index 97%
rename from neo.UnitTests/UT_Consensus.cs
rename to neo.UnitTests/Consensus/UT_Consensus.cs
index c5bf1828f8..34e8322615 100644
--- a/neo.UnitTests/UT_Consensus.cs
+++ b/neo.UnitTests/Consensus/UT_Consensus.cs
@@ -18,7 +18,7 @@
using System.Security.Cryptography;
using ECPoint = Neo.Cryptography.ECC.ECPoint;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.Consensus
{
[TestClass]
@@ -151,13 +151,13 @@ public void TestSerializeAndDeserializeConsensusContext()
ViewNumber = 2,
Validators = new ECPoint[7]
{
- ECPoint.Parse("02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70", Cryptography.ECC.ECCurve.Secp256r1),
- ECPoint.Parse("024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d", Cryptography.ECC.ECCurve.Secp256r1),
- ECPoint.Parse("02aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e", Cryptography.ECC.ECCurve.Secp256r1),
- ECPoint.Parse("02ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba554", Cryptography.ECC.ECCurve.Secp256r1),
- ECPoint.Parse("02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093", Cryptography.ECC.ECCurve.Secp256r1),
- ECPoint.Parse("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", Cryptography.ECC.ECCurve.Secp256r1),
- ECPoint.Parse("03b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a", Cryptography.ECC.ECCurve.Secp256r1)
+ ECPoint.Parse("02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70", Neo.Cryptography.ECC.ECCurve.Secp256r1),
+ ECPoint.Parse("024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d", Neo.Cryptography.ECC.ECCurve.Secp256r1),
+ ECPoint.Parse("02aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e", Neo.Cryptography.ECC.ECCurve.Secp256r1),
+ ECPoint.Parse("02ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba554", Neo.Cryptography.ECC.ECCurve.Secp256r1),
+ ECPoint.Parse("02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093", Neo.Cryptography.ECC.ECCurve.Secp256r1),
+ ECPoint.Parse("03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", Neo.Cryptography.ECC.ECCurve.Secp256r1),
+ ECPoint.Parse("03b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a", Neo.Cryptography.ECC.ECCurve.Secp256r1)
},
MyIndex = -1
};
diff --git a/neo.UnitTests/UT_ConsensusServiceMailbox.cs b/neo.UnitTests/Consensus/UT_ConsensusServiceMailbox.cs
similarity index 97%
rename from neo.UnitTests/UT_ConsensusServiceMailbox.cs
rename to neo.UnitTests/Consensus/UT_ConsensusServiceMailbox.cs
index fded2ab54e..fec1ee6bc9 100644
--- a/neo.UnitTests/UT_ConsensusServiceMailbox.cs
+++ b/neo.UnitTests/Consensus/UT_ConsensusServiceMailbox.cs
@@ -10,7 +10,7 @@
using Akka.Configuration;
using Neo.Consensus;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.Consensus
{
[TestClass]
public class UT_ConsensusServiceMailbox : TestKit
diff --git a/neo.UnitTests/Cryptography/ECC/UT_ECDsa.cs b/neo.UnitTests/Cryptography/ECC/UT_ECDsa.cs
new file mode 100644
index 0000000000..dcd394fa4f
--- /dev/null
+++ b/neo.UnitTests/Cryptography/ECC/UT_ECDsa.cs
@@ -0,0 +1,55 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Wallets;
+using System;
+using System.Numerics;
+using ECDsa = Neo.Cryptography.ECC.ECDsa;
+
+namespace Neo.UnitTests.Cryptography
+{
+ [TestClass]
+ public class UT_ECDsa
+ {
+ private KeyPair key = null;
+
+ [TestInitialize]
+ public void TestSetup()
+ {
+ key = UT_Crypto.generateCertainKey(32);
+ }
+
+ [TestMethod]
+ public void TestECDsaConstructor()
+ {
+ Action action = () => new ECDsa(key.PublicKey);
+ action.ShouldNotThrow();
+ action = () => new ECDsa(key.PrivateKey, key.PublicKey.Curve);
+ action.ShouldNotThrow();
+ }
+
+ [TestMethod]
+ public void TestGenerateSignature()
+ {
+ ECDsa sa = new ECDsa(key.PrivateKey, key.PublicKey.Curve);
+ byte[] message = System.Text.Encoding.Default.GetBytes("HelloWorld");
+ for (int i = 0; i < 30; i++)
+ {
+ BigInteger[] result = sa.GenerateSignature(message);
+ result.Length.Should().Be(2);
+ }
+ sa = new ECDsa(key.PublicKey);
+ Action action = () => sa.GenerateSignature(message);
+ action.ShouldThrow();
+ }
+
+ [TestMethod]
+ public void TestVerifySignature()
+ {
+ ECDsa sa = new ECDsa(key.PrivateKey, key.PublicKey.Curve);
+ byte[] message = System.Text.Encoding.Default.GetBytes("HelloWorld");
+ BigInteger[] result = sa.GenerateSignature(message);
+ sa.VerifySignature(message, result[0], result[1]).Should().BeTrue();
+ sa.VerifySignature(message, new BigInteger(-100), result[1]).Should().BeFalse();
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/Cryptography/ECC/UT_ECFieldElement.cs b/neo.UnitTests/Cryptography/ECC/UT_ECFieldElement.cs
new file mode 100644
index 0000000000..035e4dc469
--- /dev/null
+++ b/neo.UnitTests/Cryptography/ECC/UT_ECFieldElement.cs
@@ -0,0 +1,69 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Cryptography.ECC;
+using System;
+using System.Globalization;
+using System.Numerics;
+using System.Reflection;
+
+namespace Neo.UnitTests.Cryptography.ECC
+{
+ [TestClass]
+ public class UT_ECFieldElement
+ {
+ [TestMethod]
+ public void TestECFieldElementConstructor()
+ {
+ BigInteger input = new BigInteger(100);
+ Action action = () => new ECFieldElement(input, ECCurve.Secp256k1);
+ action.ShouldNotThrow();
+
+ input = ECCurve.Secp256k1.Q;
+ action = () => new ECFieldElement(input, ECCurve.Secp256k1);
+ action.ShouldThrow();
+ }
+
+ [TestMethod]
+ public void TestEquals()
+ {
+ BigInteger input = new BigInteger(100);
+ object element = new ECFieldElement(input, ECCurve.Secp256k1);
+ element.Equals(element).Should().BeTrue();
+ element.Equals(1).Should().BeFalse();
+
+ input = new BigInteger(200);
+ element.Equals(new ECFieldElement(input, ECCurve.Secp256k1)).Should().BeFalse();
+ }
+
+ [TestMethod]
+ public void TestSqrt()
+ {
+ ECFieldElement element = new ECFieldElement(new BigInteger(100), ECCurve.Secp256k1);
+ element.Sqrt().Should().Be(new ECFieldElement(BigInteger.Parse("115792089237316195423570985008687907853269984665640564039457584007908834671653"), ECCurve.Secp256k1));
+
+ ConstructorInfo constructor = typeof(ECCurve).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(BigInteger), typeof(BigInteger), typeof(BigInteger), typeof(BigInteger), typeof(byte[]) }, null);
+ ECCurve testCruve = constructor.Invoke(new object[] {
+ BigInteger.Parse("00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFF0", NumberStyles.AllowHexSpecifier),
+ BigInteger.Parse("00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFF00", NumberStyles.AllowHexSpecifier),
+ BigInteger.Parse("005AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", NumberStyles.AllowHexSpecifier),
+ BigInteger.Parse("00FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", NumberStyles.AllowHexSpecifier),
+ ("04" + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296" + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5").HexToBytes() }) as ECCurve;
+ element = new ECFieldElement(new BigInteger(200), testCruve);
+ element.Sqrt().Should().Be(null);
+ }
+
+ [TestMethod]
+ public void TestToByteArray()
+ {
+ byte[] result = new byte[32];
+ result[31] = 100;
+ new ECFieldElement(new BigInteger(100), ECCurve.Secp256k1).ToByteArray().Should().BeEquivalentTo(result);
+
+ byte[] result2 = { 2, 53, 250, 221, 129, 194, 130, 43, 179, 240, 120, 119, 151, 61, 80, 242, 139, 242, 42, 49, 190, 142, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ new ECFieldElement(BigInteger.Pow(new BigInteger(10), 75), ECCurve.Secp256k1).ToByteArray().Should().BeEquivalentTo(result2);
+
+ byte[] result3 = { 221, 21, 254, 134, 175, 250, 217, 18, 73, 239, 14, 183, 19, 243, 158, 190, 170, 152, 123, 110, 111, 210, 160, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ new ECFieldElement(BigInteger.Pow(new BigInteger(10), 77), ECCurve.Secp256k1).ToByteArray().Should().BeEquivalentTo(result3);
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs b/neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs
new file mode 100644
index 0000000000..9de751e851
--- /dev/null
+++ b/neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs
@@ -0,0 +1,310 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Cryptography.ECC;
+using Neo.IO;
+using System;
+using System.IO;
+using System.Linq;
+using System.Numerics;
+using ECCurve = Neo.Cryptography.ECC.ECCurve;
+using ECPoint = Neo.Cryptography.ECC.ECPoint;
+
+namespace Neo.UnitTests.Cryptography.ECC
+{
+ [TestClass]
+ public class UT_ECPoint
+ {
+ public static byte[] generatePrivateKey(int privateKeyLength)
+ {
+ byte[] privateKey = new byte[privateKeyLength];
+ for (int i = 0; i < privateKeyLength; i++)
+ {
+ privateKey[i] = (byte)((byte)i % byte.MaxValue);
+ }
+ return privateKey;
+ }
+
+ [TestMethod]
+ public void TestCompareTo()
+ {
+ ECFieldElement X1 = new ECFieldElement(new BigInteger(100), ECCurve.Secp256k1);
+ ECFieldElement Y1 = new ECFieldElement(new BigInteger(200), ECCurve.Secp256k1);
+ ECFieldElement X2 = new ECFieldElement(new BigInteger(300), ECCurve.Secp256k1);
+ ECFieldElement Y2 = new ECFieldElement(new BigInteger(400), ECCurve.Secp256k1);
+ ECPoint point1 = new ECPoint(X1, Y1, ECCurve.Secp256k1);
+ ECPoint point2 = new ECPoint(X2, Y1, ECCurve.Secp256k1);
+ ECPoint point3 = new ECPoint(X1, Y2, ECCurve.Secp256k1);
+
+ point1.CompareTo(point1).Should().Be(0);
+ point1.CompareTo(point2).Should().Be(-1);
+ point2.CompareTo(point1).Should().Be(1);
+ point1.CompareTo(point3).Should().Be(-1);
+ point3.CompareTo(point1).Should().Be(1);
+ }
+
+ [TestMethod]
+ public void TestECPointConstructor()
+ {
+ ECPoint point = new ECPoint();
+ point.X.Should().BeNull();
+ point.Y.Should().BeNull();
+ point.Curve.Should().Be(ECCurve.Secp256r1);
+
+ ECFieldElement X = new ECFieldElement(new BigInteger(100), ECCurve.Secp256k1);
+ ECFieldElement Y = new ECFieldElement(new BigInteger(200), ECCurve.Secp256k1);
+ point = new ECPoint(X, Y, ECCurve.Secp256k1);
+ point.X.Should().Be(X);
+ point.Y.Should().Be(Y);
+ point.Curve.Should().Be(ECCurve.Secp256k1);
+ }
+
+ [TestMethod]
+ public void TestDecodePoint()
+ {
+ byte[] input1 = { 0 };
+ Action action = () => ECPoint.DecodePoint(input1, ECCurve.Secp256k1);
+ action.ShouldThrow();
+
+ byte[] input2 = { 4, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149, 206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242, 129, 91, 22, 248, 23, 152, 72,
+ 58, 218, 119, 38, 163, 196, 101, 93, 164, 251, 252, 14, 17, 8, 168, 253, 23, 180, 72, 166, 133, 84, 25, 156, 71, 208, 143, 251, 16, 212, 184 };
+ ECPoint.DecodePoint(input2, ECCurve.Secp256k1).Should().Be(ECCurve.Secp256k1.G);
+ action = () => ECPoint.DecodePoint(input2.Take(32).ToArray(), ECCurve.Secp256k1);
+ action.ShouldThrow();
+
+ byte[] input3 = { 2, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149, 206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242, 129, 91, 22, 248, 23, 152 };
+ byte[] input4 = { 3, 107, 23, 209, 242, 225, 44, 66, 71, 248, 188, 230, 229, 99, 164, 64, 242, 119, 3, 125, 129, 45, 235, 51, 160, 244, 161, 57, 69, 216, 152, 194, 150 };
+ ECPoint.DecodePoint(input3, ECCurve.Secp256k1).Should().Be(ECCurve.Secp256k1.G);
+ ECPoint.DecodePoint(input4, ECCurve.Secp256r1).Should().Be(ECCurve.Secp256r1.G);
+
+ action = () => ECPoint.DecodePoint(input3.Take(input3.Length - 1).ToArray(), ECCurve.Secp256k1);
+ action.ShouldThrow();
+ }
+
+ [TestMethod]
+ public void TestDeserializeFrom()
+ {
+ byte[] input1 = { 0 };
+ Action action = () => ECPoint.DeserializeFrom(new BinaryReader(new MemoryStream(input1)), ECCurve.Secp256k1);
+ action.ShouldThrow();
+
+ byte[] input2 = { 4, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149, 206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242, 129, 91, 22, 248, 23, 152, 72,
+ 58, 218, 119, 38, 163, 196, 101, 93, 164, 251, 252, 14, 17, 8, 168, 253, 23, 180, 72, 166, 133, 84, 25, 156, 71, 208, 143, 251, 16, 212, 184 };
+ ECPoint.DeserializeFrom(new BinaryReader(new MemoryStream(input2)), ECCurve.Secp256k1).Should().Be(ECCurve.Secp256k1.G);
+ action = () => ECPoint.DeserializeFrom(new BinaryReader(new MemoryStream(input2.Take(32).ToArray())), ECCurve.Secp256k1).Should().Be(ECCurve.Secp256k1.G);
+ action.ShouldThrow();
+
+ byte[] input3 = { 2, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149, 206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242, 129, 91, 22, 248, 23, 152 };
+ ECPoint.DeserializeFrom(new BinaryReader(new MemoryStream(input3)), ECCurve.Secp256k1).Should().Be(ECCurve.Secp256k1.G);
+ byte[] input4 = { 3, 107, 23, 209, 242, 225, 44, 66, 71, 248, 188, 230, 229, 99, 164, 64, 242, 119, 3, 125, 129, 45, 235, 51, 160, 244, 161, 57, 69, 216, 152, 194, 150 };
+ ECPoint.DeserializeFrom(new BinaryReader(new MemoryStream(input4)), ECCurve.Secp256r1).Should().Be(ECCurve.Secp256r1.G);
+
+ action = () => ECPoint.DeserializeFrom(new BinaryReader(new MemoryStream(input3.Take(input3.Length - 1).ToArray())), ECCurve.Secp256k1).Should().Be(ECCurve.Secp256k1.G);
+ action.ShouldThrow();
+ }
+
+ [TestMethod]
+ public void TestEncodePoint()
+ {
+ ECPoint point = new ECPoint(null, null, ECCurve.Secp256k1);
+ byte[] result1 = { 0 };
+ point.EncodePoint(true).Should().BeEquivalentTo(result1);
+
+ point = ECCurve.Secp256k1.G;
+ byte[] result2 = { 4, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149, 206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242, 129, 91, 22, 248, 23, 152, 72,
+ 58, 218, 119, 38, 163, 196, 101, 93, 164, 251, 252, 14, 17, 8, 168, 253, 23, 180, 72, 166, 133, 84, 25, 156, 71, 208, 143, 251, 16, 212, 184 };
+ point.EncodePoint(false).Should().BeEquivalentTo(result2);
+
+ byte[] result3 = { 2, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149, 206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242, 129, 91, 22, 248, 23, 152 };
+ point.EncodePoint(true).Should().BeEquivalentTo(result3);
+
+ point = ECCurve.Secp256r1.G;
+ byte[] result4 = { 3, 107, 23, 209, 242, 225, 44, 66, 71, 248, 188, 230, 229, 99, 164, 64, 242, 119, 3, 125, 129, 45, 235, 51, 160, 244, 161, 57, 69, 216, 152, 194, 150 };
+ point.EncodePoint(true).Should().BeEquivalentTo(result4);
+ }
+
+ [TestMethod]
+ public void TestEquals()
+ {
+ ECPoint point = ECCurve.Secp256k1.G;
+ point.Equals(point).Should().BeTrue();
+ point.Equals(null).Should().BeFalse();
+
+ point = new ECPoint(null, null, ECCurve.Secp256k1);
+ point.Equals(new ECPoint(null, null, ECCurve.Secp256r1)).Should().BeTrue();
+ point.Equals(ECCurve.Secp256r1.G).Should().BeFalse();
+ ECCurve.Secp256r1.G.Equals(point).Should().BeFalse();
+
+ ECFieldElement X1 = new ECFieldElement(new BigInteger(100), ECCurve.Secp256k1);
+ ECFieldElement Y1 = new ECFieldElement(new BigInteger(200), ECCurve.Secp256k1);
+ ECFieldElement X2 = new ECFieldElement(new BigInteger(300), ECCurve.Secp256k1);
+ ECFieldElement Y2 = new ECFieldElement(new BigInteger(400), ECCurve.Secp256k1);
+ ECPoint point1 = new ECPoint(X1, Y1, ECCurve.Secp256k1);
+ ECPoint point2 = new ECPoint(X2, Y1, ECCurve.Secp256k1);
+ ECPoint point3 = new ECPoint(X1, Y2, ECCurve.Secp256k1);
+ point1.Equals(point2).Should().BeFalse();
+ point1.Equals(point3).Should().BeFalse();
+ }
+
+ [TestMethod]
+ public void TestFromBytes()
+ {
+ byte[] input1 = { 0 };
+ Action action = () => ECPoint.FromBytes(input1, ECCurve.Secp256k1);
+ action.ShouldThrow();
+
+ byte[] input2 = { 4, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149, 206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242, 129, 91, 22, 248, 23, 152, 72,
+ 58, 218, 119, 38, 163, 196, 101, 93, 164, 251, 252, 14, 17, 8, 168, 253, 23, 180, 72, 166, 133, 84, 25, 156, 71, 208, 143, 251, 16, 212, 184 };
+ ECPoint.FromBytes(input2, ECCurve.Secp256k1).Should().Be(ECCurve.Secp256k1.G);
+
+ byte[] input3 = { 2, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149, 206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242, 129, 91, 22, 248, 23, 152 };
+ ECPoint.FromBytes(input3, ECCurve.Secp256k1).Should().Be(ECCurve.Secp256k1.G);
+ ECPoint.FromBytes(input2.Skip(1).ToArray(), ECCurve.Secp256k1).Should().Be(ECCurve.Secp256k1.G);
+
+ byte[] input4 = generatePrivateKey(72);
+ ECPoint.FromBytes(input4, ECCurve.Secp256k1).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("3634473727541135791764834762056624681715094789735830699031648" +
+ "273128038409767"), ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("18165245710263168158644330920009617039772504630129940696140050972160274286151"),
+ ECCurve.Secp256k1), ECCurve.Secp256k1));
+
+ byte[] input5 = generatePrivateKey(96);
+ ECPoint.FromBytes(input5, ECCurve.Secp256k1).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("1780731860627700044960722568376592200742329637303199754547598" +
+ "369979440671"), ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("14532552714582660066924456880521368950258152170031413196862950297402215317055"),
+ ECCurve.Secp256k1), ECCurve.Secp256k1));
+
+ byte[] input6 = generatePrivateKey(104);
+ ECPoint.FromBytes(input6, ECCurve.Secp256k1).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("3634473727541135791764834762056624681715094789735830699031648" +
+ "273128038409767"), ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("18165245710263168158644330920009617039772504630129940696140050972160274286151"),
+ ECCurve.Secp256k1), ECCurve.Secp256k1));
+ }
+
+ [TestMethod]
+ public void TestMultiply()
+ {
+ ECPoint p = ECCurve.Secp256k1.G;
+ BigInteger k = BigInteger.Parse("100");
+ ECPoint.Multiply(p, k).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("107303582290733097924842193972465022053148211775194373671539518313500194639752"),
+ ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("103795966108782717446806684023742168462365449272639790795591544606836007446638"), ECCurve.Secp256k1),
+ ECCurve.Secp256k1));
+
+ k = BigInteger.Parse("10000");
+ ECPoint.Multiply(p, k).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("55279067612272658004429375184716238028207484982037227804583126224321918234542"),
+ ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("93139664895507357192565643142424306097487832058389223752321585898830257071353"), ECCurve.Secp256k1),
+ ECCurve.Secp256k1));
+
+ k = BigInteger.Parse("10000000000000");
+ ECPoint.Multiply(p, k).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("115045167963494515061513744671884131783397561769819471159495798754884242293003"),
+ ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("93759167105263077270762304290738437383691912799231615884447658154878797241853"), ECCurve.Secp256k1),
+ ECCurve.Secp256k1));
+
+ k = BigInteger.Parse("1000000000000000000000000000000000000000");
+ ECPoint.Multiply(p, k).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("114831276968810911840931876895388845736099852671055832194631099067239418074350"),
+ ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("16721517996619732311261078486295444964227498319433363271180755596201863690708"), ECCurve.Secp256k1),
+ ECCurve.Secp256k1));
+
+ k = new BigInteger(generatePrivateKey(100));
+ ECPoint.Multiply(p, k).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("19222995016448259376216431079553428738726180595337971417371897285865264889977"),
+ ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("6637081904924493791520919212064582313497884724460823966446023080706723904419"), ECCurve.Secp256k1),
+ ECCurve.Secp256k1));
+
+ k = new BigInteger(generatePrivateKey(120));
+ ECPoint.Multiply(p, k).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("79652345192111851576650978679091010173409410384772942769927955775006682639778"),
+ ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("6460429961979335115790346961011058418773289452368186110818621539624566803831"), ECCurve.Secp256k1),
+ ECCurve.Secp256k1));
+
+ k = new BigInteger(generatePrivateKey(300));
+ ECPoint.Multiply(p, k).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("105331914562708556186724786757483927866790351460145374033180496740107603569412"),
+ ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("60523670886755698512704385951571322569877668383890769288780681319304421873758"), ECCurve.Secp256k1),
+ ECCurve.Secp256k1));
+ }
+
+ [TestMethod]
+ public void TestDeserialize()
+ {
+ ECPoint point = new ECPoint(null, null, ECCurve.Secp256k1);
+ ISerializable serializable = point;
+ byte[] input = { 4, 121, 190, 102, 126, 249, 220, 187, 172, 85, 160, 98, 149, 206, 135, 11, 7, 2, 155, 252, 219, 45, 206, 40, 217, 89, 242, 129, 91, 22, 248, 23, 152,
+ 72, 58, 218, 119, 38, 163, 196, 101, 93, 164, 251, 252, 14, 17, 8, 168, 253, 23, 180, 72, 166, 133, 84, 25, 156, 71, 208, 143, 251, 16, 212, 184 };
+ serializable.Deserialize(new BinaryReader(new MemoryStream(input)));
+ point.X.Should().Be(ECCurve.Secp256k1.G.X);
+ point.Y.Should().Be(ECCurve.Secp256k1.G.Y);
+ }
+
+ [TestMethod]
+ public void TestSerialize()
+ {
+ MemoryStream stream = new MemoryStream();
+ ECPoint point = new ECPoint(null, null, ECCurve.Secp256k1);
+ ISerializable serializable = point;
+ serializable.Serialize(new BinaryWriter(stream));
+ stream.ToArray().Should().BeEquivalentTo(new byte[] { 0 });
+ }
+
+ [TestMethod]
+ public void TestOpAddition()
+ {
+ (ECCurve.Secp256k1.Infinity + ECCurve.Secp256k1.G).Should().Be(ECCurve.Secp256k1.G);
+ (ECCurve.Secp256k1.G + ECCurve.Secp256k1.Infinity).Should().Be(ECCurve.Secp256k1.G);
+ (ECCurve.Secp256k1.G + ECCurve.Secp256k1.G).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("8956589192654700423125292042593569236064414582962220983368432" +
+ "9913297188986597"), ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("12158399299693830322967808612713398636155367887041628176798871954788371653930"),
+ ECCurve.Secp256k1), ECCurve.Secp256k1));
+ (ECCurve.Secp256k1.G + new ECPoint(ECCurve.Secp256k1.G.X, new ECFieldElement(BigInteger.One, ECCurve.Secp256k1), ECCurve.Secp256k1)).Should().Be(ECCurve.Secp256k1.Infinity);
+ (ECCurve.Secp256k1.G + ECCurve.Secp256k1.G + ECCurve.Secp256k1.G).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("112711660439710606056748659173929673102" +
+ "114977341539408544630613555209775888121"), ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("2558302798057088369165690587740197640644886825481629506991988" +
+ "8960541586679410"), ECCurve.Secp256k1), ECCurve.Secp256k1));
+ }
+
+ [TestMethod]
+ public void TestOpMultiply()
+ {
+ ECPoint p = null;
+ byte[] n = new byte[] { 1 };
+ Action action = () => p = p * n;
+ action.ShouldThrow();
+
+ p = ECCurve.Secp256k1.G;
+ n = null;
+ action.ShouldThrow();
+
+ n = new byte[] { 1 };
+ action.ShouldThrow();
+
+ p = ECCurve.Secp256k1.Infinity;
+ n = new byte[32];
+ (p * n).Should().Be(p);
+
+ p = ECCurve.Secp256k1.G;
+ (p * n).Should().Be(ECCurve.Secp256k1.Infinity);
+
+ n[0] = 1;
+ (p * n).Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("63395642421589016740518975608504846303065672135176650115036476193363423546538"), ECCurve.Secp256k1),
+ new ECFieldElement(BigInteger.Parse("29236048674093813394523910922582374630829081423043497254162533033164154049666"), ECCurve.Secp256k1), ECCurve.Secp256k1));
+ }
+
+ [TestMethod]
+ public void TestOpUnaryNegation()
+ {
+ (-ECCurve.Secp256k1.G).Should().Be(new ECPoint(ECCurve.Secp256k1.G.X, -ECCurve.Secp256k1.G.Y, ECCurve.Secp256k1));
+ }
+
+ [TestMethod]
+ public void TestTryParse()
+ {
+ ECPoint.TryParse("00", ECCurve.Secp256k1, out ECPoint result).Should().BeFalse();
+ result.Should().BeNull();
+
+ ECPoint.TryParse("0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", ECCurve.Secp256k1,
+ out result).Should().BeTrue();
+ result.Should().Be(ECCurve.Secp256k1.G);
+ }
+
+ [TestMethod]
+ public void TestTwice()
+ {
+ ECCurve.Secp256k1.Infinity.Twice().Should().Be(ECCurve.Secp256k1.Infinity);
+ new ECPoint(new ECFieldElement(BigInteger.Zero, ECCurve.Secp256k1), new ECFieldElement(BigInteger.Zero, ECCurve.Secp256k1),
+ ECCurve.Secp256k1).Twice().Should().Be(ECCurve.Secp256k1.Infinity);
+ ECCurve.Secp256k1.G.Twice().Should().Be(new ECPoint(new ECFieldElement(BigInteger.Parse("89565891926547004231252920425935692360644145829622209833684329913297188986597"),
+ ECCurve.Secp256k1), new ECFieldElement(BigInteger.Parse("12158399299693830322967808612713398636155367887041628176798871954788371653930"), ECCurve.Secp256k1),
+ ECCurve.Secp256k1));
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/Cryptography/UT_Base58.cs b/neo.UnitTests/Cryptography/UT_Base58.cs
new file mode 100644
index 0000000000..2d18975445
--- /dev/null
+++ b/neo.UnitTests/Cryptography/UT_Base58.cs
@@ -0,0 +1,31 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Cryptography;
+using System;
+
+namespace Neo.UnitTests.Cryptography
+{
+ [TestClass]
+ public class UT_Base58
+ {
+ byte[] decoded1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ string encoded1 = "1kA3B2yGe2z4";
+ byte[] decoded2 = { 0, 0, 0, 0, 0};
+ string encoded2 = "1111";
+
+ [TestMethod]
+ public void TestEncode()
+ {
+ Base58.Encode(decoded1).Should().Be(encoded1);
+ }
+
+ [TestMethod]
+ public void TestDecode()
+ {
+ Base58.Decode(encoded1).Should().BeEquivalentTo(decoded1);
+ Base58.Decode(encoded2).Should().BeEquivalentTo(decoded2);
+ Action action = () => Base58.Decode(encoded1 + "l").Should().BeEquivalentTo(decoded1);
+ action.ShouldThrow();
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/Cryptography/UT_BloomFilter.cs b/neo.UnitTests/Cryptography/UT_BloomFilter.cs
new file mode 100644
index 0000000000..d611e0965d
--- /dev/null
+++ b/neo.UnitTests/Cryptography/UT_BloomFilter.cs
@@ -0,0 +1,69 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Cryptography;
+using System;
+
+namespace Neo.UnitTests.Cryptography
+{
+ [TestClass]
+ public class UT_BloomFilter
+ {
+ [TestMethod]
+ public void TestAddCheck()
+ {
+ int m = 7, n = 10;
+ uint nTweak = 123456;
+ byte[] elements = { 0, 1, 2, 3, 4 };
+ BloomFilter filter = new BloomFilter(m, n, nTweak);
+ filter.Add(elements);
+ filter.Check(elements).Should().BeTrue();
+ byte[] anotherElements = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ filter.Check(anotherElements).Should().BeFalse();
+ }
+
+ [TestMethod]
+ public void TestBloomFIlterConstructorGetKMTweak()
+ {
+ int m = -7, n = 10;
+ uint nTweak = 123456;
+ Action action = () => new BloomFilter(m, n, nTweak);
+ action.ShouldThrow();
+
+ m = 7;
+ n = -10;
+ action = () => new BloomFilter(m, n, nTweak);
+ action.ShouldThrow();
+
+ n = 10;
+ BloomFilter filter = new BloomFilter(m, n, nTweak);
+ filter.M.Should().Be(m);
+ filter.K.Should().Be(n);
+ filter.Tweak.Should().Be(nTweak);
+
+ byte[] shorterElements = { 0, 1, 2, 3, 4 };
+ filter = new BloomFilter(m, n, nTweak, shorterElements);
+ filter.M.Should().Be(m);
+ filter.K.Should().Be(n);
+ filter.Tweak.Should().Be(nTweak);
+
+ byte[] longerElements = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ filter = new BloomFilter(m, n, nTweak, longerElements);
+ filter.M.Should().Be(m);
+ filter.K.Should().Be(n);
+ filter.Tweak.Should().Be(nTweak);
+ }
+
+ [TestMethod]
+ public void TestGetBits()
+ {
+ int m = 7, n = 10;
+ uint nTweak = 123456;
+ byte[] elements = { 0, 1, 2, 3, 4 };
+ BloomFilter filter = new BloomFilter(m, n, nTweak);
+ byte[] result = new byte[m];
+ filter.GetBits(result);
+ foreach (byte value in result)
+ value.Should().Be(0);
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/Cryptography/UT_Crypto.cs b/neo.UnitTests/Cryptography/UT_Crypto.cs
new file mode 100644
index 0000000000..ec0d95add6
--- /dev/null
+++ b/neo.UnitTests/Cryptography/UT_Crypto.cs
@@ -0,0 +1,64 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Cryptography;
+using Neo.Wallets;
+using System;
+using System.Linq;
+using System.Security.Cryptography;
+
+namespace Neo.UnitTests.Cryptography
+{
+ [TestClass]
+ public class UT_Crypto
+ {
+ private KeyPair key = null;
+
+ public static KeyPair generateKey(int privateKeyLength)
+ {
+ byte[] privateKey = new byte[privateKeyLength];
+ using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
+ {
+ rng.GetBytes(privateKey);
+ }
+ return new KeyPair(privateKey);
+ }
+
+ public static KeyPair generateCertainKey(int privateKeyLength)
+ {
+ byte[] privateKey = new byte[privateKeyLength];
+ for (int i = 0; i < privateKeyLength; i++)
+ {
+ privateKey[i] = (byte)((byte)i % byte.MaxValue);
+ }
+ return new KeyPair(privateKey);
+ }
+
+ [TestInitialize]
+ public void TestSetup()
+ {
+ key = generateKey(32);
+ }
+
+ [TestMethod]
+ public void TestVerifySignature()
+ {
+ byte[] message = System.Text.Encoding.Default.GetBytes("HelloWorld");
+ byte[] signature = Crypto.Default.Sign(message, key.PrivateKey, key.PublicKey.EncodePoint(false).Skip(1).ToArray());
+ Crypto.Default.VerifySignature(message, signature, key.PublicKey.EncodePoint(false)).Should().BeTrue();
+ Crypto.Default.VerifySignature(message, signature, key.PublicKey.EncodePoint(false).Skip(1).ToArray()).Should().BeTrue();
+ Crypto.Default.VerifySignature(message, signature, key.PublicKey.EncodePoint(false).Skip(1).ToArray()).Should().BeTrue();
+
+ byte[] wrongKey = new byte[33];
+ wrongKey[0] = 0x02;
+ Crypto.Default.VerifySignature(message, signature, wrongKey).Should().BeFalse();
+
+ wrongKey[0] = 0x03;
+ for (int i = 1; i < 33; i++) wrongKey[i] = byte.MaxValue;
+ Crypto.Default.VerifySignature(message, signature, wrongKey).Should().BeFalse();
+
+ wrongKey = new byte[36];
+ Action action = () => Crypto.Default.VerifySignature(message, signature, wrongKey).Should().BeFalse();
+ action.ShouldThrow();
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs b/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs
new file mode 100644
index 0000000000..af909e3d71
--- /dev/null
+++ b/neo.UnitTests/Cryptography/UT_Cryptography_Helper.cs
@@ -0,0 +1,225 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Cryptography;
+using Neo.Network.P2P.Payloads;
+using System;
+using System.Security;
+using System.Text;
+
+namespace Neo.UnitTests.Cryptography
+{
+ [TestClass]
+ public class UT_Cryptography_Helper
+ {
+ [TestMethod]
+ public void TestAES256Encrypt()
+ {
+ byte[] block = Encoding.ASCII.GetBytes("00000000000000000000000000000000");
+ byte[] key = Encoding.ASCII.GetBytes("1234567812345678");
+ byte[] result = block.AES256Encrypt(key);
+ string encryptString = result.ToHexString();
+ encryptString.Should().Be("f69e0923d8247eef417d6a78944a4b39f69e0923d8247eef417d6a78944a4b39");
+ }
+
+ [TestMethod]
+ public void TestAES256Decrypt()
+ {
+ byte[] block = new byte[32];
+ byte[] key = Encoding.ASCII.GetBytes("1234567812345678");
+ string decryptString = "f69e0923d8247eef417d6a78944a4b39f69e0923d8247eef417d6a78944a4b399ae8fd02b340288a0e7bbff0f0ba54d6";
+ for (int i = 0; i < 32; i++)
+ block[i] = Convert.ToByte(decryptString.Substring(i * 2, 2), 16);
+ string str = System.Text.Encoding.Default.GetString(block.AES256Decrypt(key));
+ str.Should().Be("00000000000000000000000000000000");
+ }
+
+ [TestMethod]
+ public void TestAesEncrypt()
+ {
+ byte[] data = Encoding.ASCII.GetBytes("00000000000000000000000000000000");
+ byte[] key = Encoding.ASCII.GetBytes("12345678123456781234567812345678");
+ byte[] iv = Encoding.ASCII.GetBytes("1234567812345678");
+ byte[] result = data.AesEncrypt(key, iv);
+
+ string encryptString = result.ToHexString();
+ encryptString.Should().Be("07c748cf7d326782f82e60ebe60e2fac289e84e9ce91c1bc41565d14ecb53640");
+
+ byte[] nullData = null;
+ Action action = () => nullData.AesEncrypt(key, iv);
+ action.ShouldThrow();
+
+ byte[] nullKey = null;
+ action = () => data.AesEncrypt(nullKey, iv);
+ action.ShouldThrow();
+
+ byte[] nullIv = null;
+ action = () => data.AesEncrypt(key, nullIv);
+ action.ShouldThrow();
+
+ byte[] wrongData = Encoding.ASCII.GetBytes("000000000000000000000000000000001"); ;
+ action = () => wrongData.AesEncrypt(key, iv);
+ action.ShouldThrow();
+
+ byte[] wrongKey = Encoding.ASCII.GetBytes("123456781234567812345678123456780"); ;
+ action = () => data.AesEncrypt(wrongKey, iv);
+ action.ShouldThrow();
+
+ byte[] wrongIv = Encoding.ASCII.GetBytes("12345678123456780"); ;
+ action = () => data.AesEncrypt(key, wrongIv);
+ action.ShouldThrow();
+ }
+
+ [TestMethod]
+ public void TestAesDecrypt()
+ {
+ byte[] data = new byte[32];
+ byte[] key = Encoding.ASCII.GetBytes("12345678123456781234567812345678");
+ byte[] iv = Encoding.ASCII.GetBytes("1234567812345678");
+ string decryptString = "07c748cf7d326782f82e60ebe60e2fac289e84e9ce91c1bc41565d14ecb5364073f28c9aa7bd6b069e44d8a97beb2b58";
+ for (int i = 0; i < 32; i++)
+ data[i] = Convert.ToByte(decryptString.Substring(i * 2, 2), 16);
+ string str = System.Text.Encoding.Default.GetString(data.AesDecrypt(key, iv));
+ str.Should().Be("00000000000000000000000000000000");
+
+ byte[] nullData = null;
+ Action action = () => nullData.AesDecrypt(key, iv);
+ action.ShouldThrow();
+
+ byte[] nullKey = null;
+ action = () => data.AesDecrypt(nullKey, iv);
+ action.ShouldThrow();
+
+ byte[] nullIv = null;
+ action = () => data.AesDecrypt(key, nullIv);
+ action.ShouldThrow();
+
+ byte[] wrongData = Encoding.ASCII.GetBytes("00000000000000001"); ;
+ action = () => wrongData.AesDecrypt(key, iv);
+ action.ShouldThrow();
+
+ byte[] wrongKey = Encoding.ASCII.GetBytes("123456781234567812345678123456780"); ;
+ action = () => data.AesDecrypt(wrongKey, iv);
+ action.ShouldThrow();
+
+ byte[] wrongIv = Encoding.ASCII.GetBytes("12345678123456780"); ;
+ action = () => data.AesDecrypt(key, wrongIv);
+ action.ShouldThrow();
+ }
+
+ [TestMethod]
+ public void TestBase58CheckDecode()
+ {
+ string input = "3vQB7B6MrGQZaxCuFg4oh";
+ byte[] result = input.Base58CheckDecode();
+ byte[] helloWorld = { 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100 };
+ result.Should().Equal(helloWorld);
+
+ input = "3v";
+ Action action = () => input.Base58CheckDecode();
+ action.ShouldThrow();
+
+ input = "3vQB7B6MrGQZaxCuFg4og";
+ action = () => input.Base58CheckDecode();
+ action.ShouldThrow();
+ }
+
+ [TestMethod]
+ public void TestSha256()
+ {
+ byte[] value = Encoding.ASCII.GetBytes("hello world");
+ byte[] result = value.Sha256(0, value.Length);
+ string resultStr = result.ToHexString();
+ resultStr.Should().Be("b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9");
+ }
+
+ [TestMethod]
+ public void TestTest()
+ {
+ int m = 7, n = 10;
+ uint nTweak = 123456;
+ BloomFilter filter = new BloomFilter(m, n, nTweak);
+
+ Transaction tx = new Transaction
+ {
+ Script = TestUtils.GetByteArray(32, 0x42),
+ Sender = UInt160.Zero,
+ SystemFee = 4200000000,
+ Attributes = new TransactionAttribute[0],
+ Witnesses = new[]
+ {
+ new Witness
+ {
+ InvocationScript = new byte[0],
+ VerificationScript = new byte[0]
+ }
+ }
+ };
+ filter.Test(tx).Should().BeFalse();
+
+ filter.Add(tx.Witnesses[0].ScriptHash.ToArray());
+ filter.Test(tx).Should().BeTrue();
+
+ filter.Add(tx.Hash.ToArray());
+ filter.Test(tx).Should().BeTrue();
+ }
+
+ [TestMethod]
+ public void TestStringToAesKey()
+ {
+ string password = "hello world";
+ string string1 = "bc62d4b80d9e36da29c16c5d4d9f11731f36052c72401a76c23c0fb5a9b74423";
+ byte[] byteArray = new byte[string1.Length / 2];
+ byteArray = string1.HexToBytes();
+ password.ToAesKey().Should().Equal(byteArray);
+ }
+
+ [TestMethod]
+ public void TestSecureStringToAesKey()
+ {
+ var password = new SecureString();
+ password.AppendChar('h');
+ password.AppendChar('e');
+ password.AppendChar('l');
+ password.AppendChar('l');
+ password.AppendChar('o');
+ password.AppendChar(' ');
+ password.AppendChar('w');
+ password.AppendChar('o');
+ password.AppendChar('r');
+ password.AppendChar('l');
+ password.AppendChar('d');
+ string string1 = "bc62d4b80d9e36da29c16c5d4d9f11731f36052c72401a76c23c0fb5a9b74423";
+ byte[] byteArray = new byte[string1.Length / 2];
+ byteArray = string1.HexToBytes();
+ password.ToAesKey().Should().Equal(byteArray);
+ }
+
+ [TestMethod]
+ public void TestToArray()
+ {
+ var password = new SecureString();
+ password.AppendChar('h');
+ password.AppendChar('e');
+ password.AppendChar('l');
+ password.AppendChar('l');
+ password.AppendChar('o');
+ password.AppendChar(' ');
+ password.AppendChar('w');
+ password.AppendChar('o');
+ password.AppendChar('r');
+ password.AppendChar('l');
+ password.AppendChar('d');
+ byte[] byteArray = { 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F, 0x72, 0x6C, 0x64 };
+ password.ToArray().Should().Equal(byteArray);
+
+ SecureString nullString = null;
+ Action action = () => nullString.ToArray();
+ action.ShouldThrow();
+
+ var zeroString = new SecureString();
+ var result = zeroString.ToArray();
+ byteArray = new byte[0];
+ result.Should().Equal(byteArray);
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/UT_Scrypt.cs b/neo.UnitTests/Cryptography/UT_Scrypt.cs
similarity index 93%
rename from neo.UnitTests/UT_Scrypt.cs
rename to neo.UnitTests/Cryptography/UT_Scrypt.cs
index 8e2bf1e30a..8ec603da48 100644
--- a/neo.UnitTests/UT_Scrypt.cs
+++ b/neo.UnitTests/Cryptography/UT_Scrypt.cs
@@ -2,7 +2,7 @@
using Neo.Cryptography;
using System;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.Cryptography
{
[TestClass]
public class UT_Scrypt
@@ -16,4 +16,4 @@ public void DeriveKeyTest()
Assert.AreEqual("b6274d3a81892c24335ab46a08ec16d040ac00c5943b212099a44b76a9b8102631ab988fa07fb35357cee7b0e3910098c0774c0e97399997676d890b2bf2bb25", derivedkey);
}
}
-}
+}
\ No newline at end of file
diff --git a/neo.UnitTests/Extensions/NativeContractExtensions.cs b/neo.UnitTests/Extensions/NativeContractExtensions.cs
index 7d33841ef8..6a641c2387 100644
--- a/neo.UnitTests/Extensions/NativeContractExtensions.cs
+++ b/neo.UnitTests/Extensions/NativeContractExtensions.cs
@@ -8,12 +8,12 @@ namespace Neo.UnitTests.Extensions
{
public static class NativeContractExtensions
{
- public static StackItem Call(this NativeContract contract, Persistence.Snapshot snapshot, string method, params ContractParameter[] args)
+ public static StackItem Call(this NativeContract contract, Neo.Persistence.Snapshot snapshot, string method, params ContractParameter[] args)
{
return Call(contract, snapshot, null, method, args);
}
- public static StackItem Call(this NativeContract contract, Persistence.Snapshot snapshot, IVerifiable container, string method, params ContractParameter[] args)
+ public static StackItem Call(this NativeContract contract, Neo.Persistence.Snapshot snapshot, IVerifiable container, string method, params ContractParameter[] args)
{
var engine = new ApplicationEngine(TriggerType.Application, container, snapshot, 0, true);
diff --git a/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs b/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs
index a87fd7c3e1..42c5c87543 100644
--- a/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs
+++ b/neo.UnitTests/Extensions/Nep5NativeContractExtensions.cs
@@ -34,14 +34,14 @@ public void Deserialize(BinaryReader reader) { }
public void DeserializeUnsigned(BinaryReader reader) { }
- public UInt160[] GetScriptHashesForVerifying(Persistence.Snapshot snapshot) => _hashForVerify;
+ public UInt160[] GetScriptHashesForVerifying(Neo.Persistence.Snapshot snapshot) => _hashForVerify;
public void Serialize(BinaryWriter writer) { }
public void SerializeUnsigned(BinaryWriter writer) { }
}
- public static bool Transfer(this NativeContract contract, Persistence.Snapshot snapshot, byte[] from, byte[] to, BigInteger amount, bool signFrom)
+ public static bool Transfer(this NativeContract contract, Neo.Persistence.Snapshot snapshot, byte[] from, byte[] to, BigInteger amount, bool signFrom)
{
var engine = new ApplicationEngine(TriggerType.Application,
new ManualWitness(signFrom ? new UInt160(from) : null), snapshot, 0, true);
@@ -90,7 +90,7 @@ public static string[] SupportedStandards(this NativeContract contract)
.ToArray();
}
- public static BigInteger TotalSupply(this NativeContract contract, Persistence.Snapshot snapshot)
+ public static BigInteger TotalSupply(this NativeContract contract, Neo.Persistence.Snapshot snapshot)
{
var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true);
@@ -110,7 +110,7 @@ public static BigInteger TotalSupply(this NativeContract contract, Persistence.S
return (result as VM.Types.Integer).GetBigInteger();
}
- public static BigInteger BalanceOf(this NativeContract contract, Persistence.Snapshot snapshot, byte[] account)
+ public static BigInteger BalanceOf(this NativeContract contract, Neo.Persistence.Snapshot snapshot, byte[] account)
{
var engine = new ApplicationEngine(TriggerType.Application, null, snapshot, 0, true);
diff --git a/neo.UnitTests/IO/Caching/UT_Cache.cs b/neo.UnitTests/IO/Caching/UT_Cache.cs
new file mode 100644
index 0000000000..01484ae65e
--- /dev/null
+++ b/neo.UnitTests/IO/Caching/UT_Cache.cs
@@ -0,0 +1,214 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.IO.Caching;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Neo.UnitTests.IO.Caching
+{
+ class MyCache : Cache
+ {
+ public MyCache(int max_capacity) : base(max_capacity) { }
+
+ protected override int GetKeyForItem(string item)
+ {
+ return item.GetHashCode();
+ }
+
+ protected override void OnAccess(CacheItem item) { }
+
+ public IEnumerator MyGetEnumerator()
+ {
+ IEnumerable enumerable = this;
+ return enumerable.GetEnumerator();
+ }
+ }
+
+ [TestClass]
+ public class UT_Cache
+ {
+ MyCache cache;
+ readonly int max_capacity = 4;
+
+ [TestInitialize]
+ public void init()
+ {
+ cache = new MyCache(max_capacity);
+ }
+
+ [TestMethod]
+ public void TestCount()
+ {
+ cache.Count.Should().Be(0);
+
+ cache.Add("hello");
+ cache.Add("world");
+ cache.Count.Should().Be(2);
+
+ cache.Remove("hello");
+ cache.Count.Should().Be(1);
+ }
+
+ [TestMethod]
+ public void TestIsReadOnly()
+ {
+ cache.IsReadOnly.Should().BeFalse();
+ }
+
+ [TestMethod]
+ public void TestAddAndAddInternal()
+ {
+ cache.Add("hello");
+ cache.Contains("hello").Should().BeTrue();
+ cache.Contains("world").Should().BeFalse();
+ cache.Add("hello");
+ cache.Count.Should().Be(1);
+ }
+
+ [TestMethod]
+ public void TestAddRange()
+ {
+ string[] range = { "hello", "world" };
+ cache.AddRange(range);
+ cache.Count.Should().Be(2);
+ cache.Contains("hello").Should().BeTrue();
+ cache.Contains("world").Should().BeTrue();
+ cache.Contains("non exist string").Should().BeFalse();
+ }
+
+ [TestMethod]
+ public void TestClear()
+ {
+ cache.Add("hello");
+ cache.Add("world");
+ cache.Count.Should().Be(2);
+ cache.Clear();
+ cache.Count.Should().Be(0);
+ }
+
+ [TestMethod]
+ public void TestContainsKey()
+ {
+ cache.Add("hello");
+ cache.Contains("hello").Should().BeTrue();
+ cache.Contains("world").Should().BeFalse();
+ }
+
+ [TestMethod]
+ public void TestContainsValue()
+ {
+ cache.Add("hello");
+ cache.Contains("hello".GetHashCode()).Should().BeTrue();
+ cache.Contains("world".GetHashCode()).Should().BeFalse();
+ }
+
+ [TestMethod]
+ public void TestCopyTo()
+ {
+ cache.Add("hello");
+ cache.Add("world");
+ string[] temp = new string[2];
+
+ Action action = () => cache.CopyTo(null, 1);
+ action.ShouldThrow();
+
+ action = () => cache.CopyTo(temp, -1);
+ action.ShouldThrow();
+
+ action = () => cache.CopyTo(temp, 1);
+ action.ShouldThrow();
+
+ cache.CopyTo(temp, 0);
+ temp[0].Should().Be("hello");
+ temp[1].Should().Be("world");
+ }
+
+ [TestMethod]
+ public void TestRemoveKey()
+ {
+ cache.Add("hello");
+ cache.Remove("hello".GetHashCode()).Should().BeTrue();
+ cache.Remove("world".GetHashCode()).Should().BeFalse();
+ cache.Contains("hello").Should().BeFalse();
+ }
+
+ [TestMethod]
+ public void TestRemoveValue()
+ {
+ cache.Add("hello");
+ cache.Remove("hello").Should().BeTrue();
+ cache.Remove("world").Should().BeFalse();
+ cache.Contains("hello").Should().BeFalse();
+ }
+
+ [TestMethod]
+ public void TestTryGet()
+ {
+ cache.Add("hello");
+ cache.TryGet("hello".GetHashCode(), out string output).Should().BeTrue();
+ output.Should().Be("hello");
+ cache.TryGet("world".GetHashCode(), out string output2).Should().BeFalse();
+ output2.Should().NotBe("world");
+ output2.Should().BeNull();
+ }
+
+ [TestMethod]
+ public void TestArrayIndexAccess()
+ {
+ cache.Add("hello");
+ cache.Add("world");
+ cache["hello".GetHashCode()].Should().Be("hello");
+ cache["world".GetHashCode()].Should().Be("world");
+
+ Action action = () =>
+ {
+ string temp = cache["non exist string".GetHashCode()];
+ };
+ action.ShouldThrow();
+ }
+
+ [TestMethod]
+ public void TestGetEnumerator()
+ {
+ cache.Add("hello");
+ cache.Add("world");
+ int i = 0;
+ foreach (string item in cache)
+ {
+ if (i == 0) item.Should().Be("hello");
+ if (i == 1) item.Should().Be("world");
+ i++;
+ }
+ i.Should().Be(2);
+ cache.MyGetEnumerator().Should().NotBeNull();
+ }
+
+ [TestMethod]
+ public void TestOverMaxCapacity()
+ {
+ int i = 1;
+ for (; i <= max_capacity; i++)
+ {
+ cache.Add(i.ToString());
+ }
+ cache.Add(i.ToString()); // The first one will be deleted
+ cache.Count.Should().Be(max_capacity);
+ cache.Contains((max_capacity + 1).ToString()).Should().BeTrue();
+ }
+
+ [TestMethod]
+ public void TestDispose()
+ {
+ cache.Add("hello");
+ cache.Add("world");
+ cache.Dispose();
+
+ Action action = () =>
+ {
+ int count = cache.Count;
+ };
+ action.ShouldThrow();
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/IO/Caching/UT_CloneCache.cs b/neo.UnitTests/IO/Caching/UT_CloneCache.cs
new file mode 100644
index 0000000000..1c9c2db74d
--- /dev/null
+++ b/neo.UnitTests/IO/Caching/UT_CloneCache.cs
@@ -0,0 +1,126 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.IO;
+using Neo.IO.Caching;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Neo.UnitTests.IO.Caching
+{
+ [TestClass]
+ public class UT_CloneCache
+ {
+ CloneCache cloneCache;
+ MyDataCache myDataCache;
+
+ [TestInitialize]
+ public void Init()
+ {
+ myDataCache = new MyDataCache();
+ cloneCache = new CloneCache(myDataCache);
+ }
+
+ [TestMethod]
+ public void TestCloneCache()
+ {
+ cloneCache.Should().NotBeNull();
+ }
+
+ [TestMethod]
+ public void TestAddInternal()
+ {
+ cloneCache.Add(new MyKey("key1"), new MyValue("value1"));
+ cloneCache[new MyKey("key1")].Should().Be(new MyValue("value1"));
+
+ cloneCache.Commit();
+ myDataCache[new MyKey("key1")].Should().Be(new MyValue("value1"));
+ }
+
+ [TestMethod]
+ public void TestDeleteInternal()
+ {
+ myDataCache.Add(new MyKey("key1"), new MyValue("value1"));
+ cloneCache.Delete(new MyKey("key1")); // trackable.State = TrackState.Deleted
+ cloneCache.Commit();
+
+ cloneCache.TryGet(new MyKey("key1")).Should().BeNull();
+ myDataCache.TryGet(new MyKey("key1")).Should().BeNull();
+ }
+
+ [TestMethod]
+ public void TestFindInternal()
+ {
+ cloneCache.Add(new MyKey("key1"), new MyValue("value1"));
+ myDataCache.Add(new MyKey("key2"), new MyValue("value2"));
+ myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3"));
+
+ var items = cloneCache.Find(new MyKey("key1").ToArray());
+ items.ElementAt(0).Key.Should().Be(new MyKey("key1"));
+ items.ElementAt(0).Value.Should().Be(new MyValue("value1"));
+ items.Count().Should().Be(1);
+
+ items = cloneCache.Find(new MyKey("key2").ToArray());
+ items.ElementAt(0).Key.Should().Be(new MyKey("key2"));
+ items.ElementAt(0).Value.Should().Be(new MyValue("value2"));
+ items.Count().Should().Be(1);
+
+ items = cloneCache.Find(new MyKey("key3").ToArray());
+ items.ElementAt(0).Key.Should().Be(new MyKey("key3"));
+ items.ElementAt(0).Value.Should().Be(new MyValue("value3"));
+ items.Count().Should().Be(1);
+
+ items = cloneCache.Find(new MyKey("key4").ToArray());
+ items.Count().Should().Be(0);
+ }
+
+ [TestMethod]
+ public void TestGetInternal()
+ {
+ cloneCache.Add(new MyKey("key1"), new MyValue("value1"));
+ myDataCache.Add(new MyKey("key2"), new MyValue("value2"));
+ myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3"));
+
+ cloneCache[new MyKey("key1")].Should().Be(new MyValue("value1"));
+ cloneCache[new MyKey("key2")].Should().Be(new MyValue("value2"));
+ cloneCache[new MyKey("key3")].Should().Be(new MyValue("value3"));
+
+ Action action = () => {
+ var item = cloneCache[new MyKey("key4")];
+ };
+ action.ShouldThrow();
+ }
+
+ [TestMethod]
+ public void TestTryGetInternal()
+ {
+ cloneCache.Add(new MyKey("key1"), new MyValue("value1"));
+ myDataCache.Add(new MyKey("key2"), new MyValue("value2"));
+ myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3"));
+
+ cloneCache.TryGet(new MyKey("key1")).Should().Be(new MyValue("value1"));
+ cloneCache.TryGet(new MyKey("key2")).Should().Be(new MyValue("value2"));
+ cloneCache.TryGet(new MyKey("key3")).Should().Be(new MyValue("value3"));
+ cloneCache.TryGet(new MyKey("key4")).Should().BeNull();
+ }
+
+ [TestMethod]
+ public void TestUpdateInternal()
+ {
+ cloneCache.Add(new MyKey("key1"), new MyValue("value1"));
+ myDataCache.Add(new MyKey("key2"), new MyValue("value2"));
+ myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3"));
+
+ cloneCache.GetAndChange(new MyKey("key1")).Value = "value_new_1";
+ cloneCache.GetAndChange(new MyKey("key2")).Value = "value_new_2";
+ cloneCache.GetAndChange(new MyKey("key3")).Value = "value_new_3";
+
+ cloneCache.Commit();
+
+ cloneCache[new MyKey("key1")].Should().Be(new MyValue("value_new_1"));
+ cloneCache[new MyKey("key2")].Should().Be(new MyValue("value_new_2"));
+ cloneCache[new MyKey("key3")].Should().Be(new MyValue("value_new_3"));
+ myDataCache[new MyKey("key2")].Should().Be(new MyValue("value_new_2"));
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/IO/Caching/UT_CloneMetaCache.cs b/neo.UnitTests/IO/Caching/UT_CloneMetaCache.cs
new file mode 100644
index 0000000000..812cbc26ba
--- /dev/null
+++ b/neo.UnitTests/IO/Caching/UT_CloneMetaCache.cs
@@ -0,0 +1,48 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.IO.Caching;
+
+namespace Neo.UnitTests.IO.Caching
+{
+ [TestClass]
+ public class UT_CloneMetaCache
+ {
+ MyMetaCache myMetaCache;
+ CloneMetaCache cloneMetaCache;
+
+ [TestInitialize]
+ public void Init()
+ {
+ myMetaCache = new MyMetaCache(() => new MyValue());
+ cloneMetaCache = new CloneMetaCache(myMetaCache);
+ }
+
+ [TestMethod]
+ public void TestConstructor()
+ {
+ cloneMetaCache.Should().NotBeNull();
+ }
+
+ [TestMethod]
+ public void TestTryGetInternal()
+ {
+ MyValue value = myMetaCache.GetAndChange();
+ value.Value = "value1";
+
+ cloneMetaCache.Get().Should().Be(value);
+ }
+
+ [TestMethod]
+ public void TestUpdateInternal()
+ {
+ MyValue value = myMetaCache.GetAndChange();
+ value.Value = "value1";
+
+ MyValue value2 = cloneMetaCache.GetAndChange();
+ value2.Value = "value2";
+
+ cloneMetaCache.Commit();
+ value.Value.Should().Be("value2");
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/IO/Caching/UT_DataCache.cs b/neo.UnitTests/IO/Caching/UT_DataCache.cs
new file mode 100644
index 0000000000..d93316022d
--- /dev/null
+++ b/neo.UnitTests/IO/Caching/UT_DataCache.cs
@@ -0,0 +1,347 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.IO;
+using Neo.IO.Caching;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace Neo.UnitTests.IO.Caching
+{
+ class MyKey : ISerializable, IEquatable
+ {
+ public string Key;
+
+ public int Size => Key.Length;
+
+ public MyKey() { }
+
+ public MyKey(string val)
+ {
+ Key = val;
+ }
+
+ public void Deserialize(BinaryReader reader)
+ {
+ Key = reader.ReadString();
+ }
+
+ public void Serialize(BinaryWriter writer)
+ {
+ writer.Write(Key);
+ }
+
+ public bool Equals(MyKey other)
+ {
+ return Key.Equals(other.Key);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is MyKey key)) return false;
+ return Equals(key);
+ }
+
+ public override int GetHashCode()
+ {
+ return Key.GetHashCode();
+ }
+ }
+
+ public class MyValue : ISerializable, ICloneable
+ {
+ public string Value;
+
+ public int Size => Value.Length;
+
+ public MyValue() { }
+
+ public MyValue(string val)
+ {
+ Value = val;
+ }
+
+ public void Deserialize(BinaryReader reader)
+ {
+ Value = reader.ReadString();
+ }
+
+ public void Serialize(BinaryWriter writer)
+ {
+ writer.Write(Value);
+ }
+
+ MyValue ICloneable.Clone()
+ {
+ return new MyValue(Value);
+ }
+
+ void ICloneable.FromReplica(MyValue replica)
+ {
+ Value = replica.Value;
+ }
+
+ public bool Equals(MyValue other)
+ {
+ return (Value == null && other.Value == null) || Value.Equals(other.Value);
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is MyValue key)) return false;
+ return Equals(key);
+ }
+
+ public override int GetHashCode()
+ {
+ return Value.GetHashCode();
+ }
+ }
+
+ class MyDataCache : DataCache
+ where TKey : IEquatable, ISerializable, new()
+ where TValue : class, ICloneable, ISerializable, new()
+ {
+ public Dictionary InnerDict = new Dictionary();
+
+ public override void DeleteInternal(TKey key)
+ {
+ InnerDict.Remove(key);
+ }
+
+ protected override void AddInternal(TKey key, TValue value)
+ {
+ InnerDict.Add(key, value);
+ }
+
+ protected override IEnumerable> FindInternal(byte[] key_prefix)
+ {
+ return InnerDict.Where(kvp => kvp.Key.ToArray().Take(key_prefix.Length).SequenceEqual(key_prefix));
+ }
+
+ protected override TValue GetInternal(TKey key)
+ {
+ if (InnerDict.TryGetValue(key, out TValue value))
+ {
+ return value.Clone();
+ }
+ throw new KeyNotFoundException();
+ }
+
+ protected override TValue TryGetInternal(TKey key)
+ {
+ if (InnerDict.TryGetValue(key, out TValue value))
+ {
+ return value.Clone();
+ }
+ return null;
+ }
+
+ protected override void UpdateInternal(TKey key, TValue value)
+ {
+ InnerDict[key] = value;
+ }
+ }
+
+ [TestClass]
+ public class UT_DataCache
+ {
+ MyDataCache myDataCache;
+
+ [TestInitialize]
+ public void Initialize()
+ {
+ myDataCache = new MyDataCache();
+ }
+
+ [TestMethod]
+ public void TestAccessByKey()
+ {
+ myDataCache.Add(new MyKey("key1"), new MyValue("value1"));
+ myDataCache.Add(new MyKey("key2"), new MyValue("value2"));
+
+ myDataCache[new MyKey("key1")].Should().Be(new MyValue("value1"));
+
+ // case 2 read from inner
+ myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3"));
+ myDataCache[new MyKey("key3")].Should().Be(new MyValue("value3"));
+ }
+
+ [TestMethod]
+ public void TestAccessByNotFoundKey()
+ {
+ Action action = () =>
+ {
+ var item = myDataCache[new MyKey("key1")];
+ };
+ action.ShouldThrow();
+ }
+
+ [TestMethod]
+ public void TestAccessByDeletedKey()
+ {
+ myDataCache.InnerDict.Add(new MyKey("key1"), new MyValue("value1"));
+ myDataCache.Delete(new MyKey("key1"));
+
+ Action action = () =>
+ {
+ var item = myDataCache[new MyKey("key1")];
+ };
+ action.ShouldThrow();
+ }
+
+ [TestMethod]
+ public void TestAdd()
+ {
+ myDataCache.Add(new MyKey("key1"), new MyValue("value1"));
+ myDataCache[new MyKey("key1")].Should().Be(new MyValue("value1"));
+
+ Action action = () => myDataCache.Add(new MyKey("key1"), new MyValue("value1"));
+ action.ShouldThrow();
+
+ myDataCache.InnerDict.Add(new MyKey("key2"), new MyValue("value2"));
+ myDataCache.Delete(new MyKey("key2")); // trackable.State = TrackState.Deleted
+ myDataCache.Add(new MyKey("key2"), new MyValue("value2")); // trackable.State = TrackState.Changed
+
+ action = () => myDataCache.Add(new MyKey("key2"), new MyValue("value2"));
+ action.ShouldThrow();
+ }
+
+ [TestMethod]
+ public void TestCommit()
+ {
+ myDataCache.Add(new MyKey("key1"), new MyValue("value1")); // trackable.State = TrackState.Added
+
+ myDataCache.InnerDict.Add(new MyKey("key2"), new MyValue("value2"));
+ myDataCache.Delete(new MyKey("key2")); // trackable.State = TrackState.Deleted
+
+ myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3"));
+ myDataCache.Delete(new MyKey("key3")); // trackable.State = TrackState.Deleted
+ myDataCache.Add(new MyKey("key3"), new MyValue("value4")); // trackable.State = TrackState.Changed
+
+ myDataCache.Commit();
+
+ myDataCache.InnerDict[new MyKey("key1")].Should().Be(new MyValue("value1"));
+ myDataCache.InnerDict.ContainsKey(new MyKey("key2")).Should().BeFalse();
+ myDataCache.InnerDict[new MyKey("key3")].Should().Be(new MyValue("value4"));
+ }
+
+ [TestMethod]
+ public void TestCreateSnapshot()
+ {
+ myDataCache.CreateSnapshot().Should().NotBeNull();
+ }
+
+ [TestMethod]
+ public void TestDelete()
+ {
+ myDataCache.Add(new MyKey("key1"), new MyValue("value1"));
+ myDataCache.Delete(new MyKey("key1"));
+ myDataCache.InnerDict.ContainsKey(new MyKey("key1")).Should().BeFalse();
+
+ myDataCache.InnerDict.Add(new MyKey("key2"), new MyValue("value2"));
+ myDataCache.Delete(new MyKey("key2"));
+ myDataCache.Commit();
+ myDataCache.InnerDict.ContainsKey(new MyKey("key2")).Should().BeFalse();
+ }
+
+ [TestMethod]
+ public void TestDeleteWhere()
+ {
+ myDataCache.Add(new MyKey("key1"), new MyValue("value1"));
+ myDataCache.Add(new MyKey("key2"), new MyValue("value2"));
+
+ myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3"));
+ myDataCache.InnerDict.Add(new MyKey("key4"), new MyValue("value4"));
+
+ myDataCache.DeleteWhere((k, v) => k.Key.StartsWith("key"));
+ myDataCache.Commit();
+ myDataCache.TryGet(new MyKey("key1")).Should().BeNull();
+ myDataCache.TryGet(new MyKey("key2")).Should().BeNull();
+ myDataCache.InnerDict.ContainsKey(new MyKey("key1")).Should().BeFalse();
+ myDataCache.InnerDict.ContainsKey(new MyKey("key2")).Should().BeFalse();
+ }
+
+ [TestMethod]
+ public void TestFind()
+ {
+ myDataCache.Add(new MyKey("key1"), new MyValue("value1"));
+ myDataCache.Add(new MyKey("key2"), new MyValue("value2"));
+
+ myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3"));
+ myDataCache.InnerDict.Add(new MyKey("key4"), new MyValue("value4"));
+
+ var items = myDataCache.Find(new MyKey("key1").ToArray());
+ items.ElementAt(0).Key.Should().Be(new MyKey("key1"));
+ items.ElementAt(0).Value.Should().Be(new MyValue("value1"));
+ items.Count().Should().Be(1);
+
+ items = myDataCache.Find(new MyKey("key5").ToArray());
+ items.Count().Should().Be(0);
+ }
+
+ [TestMethod]
+ public void TestGetChangeSet()
+ {
+ myDataCache.Add(new MyKey("key1"), new MyValue("value1")); // trackable.State = TrackState.Added
+ myDataCache.Add(new MyKey("key2"), new MyValue("value2")); // trackable.State = TrackState.Added
+
+ myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3"));
+ myDataCache.InnerDict.Add(new MyKey("key4"), new MyValue("value4"));
+ myDataCache.Delete(new MyKey("key3")); // trackable.State = TrackState.Deleted
+ myDataCache.Delete(new MyKey("key4")); // trackable.State = TrackState.Deleted
+
+ var items = myDataCache.GetChangeSet();
+ int i = 0;
+ foreach (var item in items)
+ {
+ i++;
+ item.Key.Should().Be(new MyKey("key" + i));
+ item.Item.Should().Be(new MyValue("value" + i));
+ }
+ i.Should().Be(4);
+ }
+
+ [TestMethod]
+ public void TestGetAndChange()
+ {
+ myDataCache.Add(new MyKey("key1"), new MyValue("value1")); // trackable.State = TrackState.Added
+ myDataCache.InnerDict.Add(new MyKey("key2"), new MyValue("value2"));
+ myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3"));
+ myDataCache.Delete(new MyKey("key3")); // trackable.State = TrackState.Deleted
+
+ myDataCache.GetAndChange(new MyKey("key1"), () => new MyValue("value_bk_1")).Should().Be(new MyValue("value1"));
+ myDataCache.GetAndChange(new MyKey("key2"), () => new MyValue("value_bk_2")).Should().Be(new MyValue("value2"));
+ myDataCache.GetAndChange(new MyKey("key3"), () => new MyValue("value_bk_3")).Should().Be(new MyValue("value_bk_3"));
+ myDataCache.GetAndChange(new MyKey("key4"), () => new MyValue("value_bk_4")).Should().Be(new MyValue("value_bk_4"));
+ }
+
+ [TestMethod]
+ public void TestGetOrAdd()
+ {
+ myDataCache.Add(new MyKey("key1"), new MyValue("value1")); // trackable.State = TrackState.Added
+ myDataCache.InnerDict.Add(new MyKey("key2"), new MyValue("value2"));
+ myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3"));
+ myDataCache.Delete(new MyKey("key3")); // trackable.State = TrackState.Deleted
+
+ myDataCache.GetOrAdd(new MyKey("key1"), () => new MyValue("value_bk_1")).Should().Be(new MyValue("value1"));
+ myDataCache.GetOrAdd(new MyKey("key2"), () => new MyValue("value_bk_2")).Should().Be(new MyValue("value2"));
+ myDataCache.GetOrAdd(new MyKey("key3"), () => new MyValue("value_bk_3")).Should().Be(new MyValue("value_bk_3"));
+ myDataCache.GetOrAdd(new MyKey("key4"), () => new MyValue("value_bk_4")).Should().Be(new MyValue("value_bk_4"));
+ }
+
+ [TestMethod]
+ public void TestTryGet()
+ {
+ myDataCache.Add(new MyKey("key1"), new MyValue("value1")); // trackable.State = TrackState.Added
+ myDataCache.InnerDict.Add(new MyKey("key2"), new MyValue("value2"));
+ myDataCache.InnerDict.Add(new MyKey("key3"), new MyValue("value3"));
+ myDataCache.Delete(new MyKey("key3")); // trackable.State = TrackState.Deleted
+
+ myDataCache.TryGet(new MyKey("key1")).Should().Be(new MyValue("value1"));
+ myDataCache.TryGet(new MyKey("key2")).Should().Be(new MyValue("value2"));
+ myDataCache.TryGet(new MyKey("key3")).Should().BeNull();
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/IO/Caching/UT_FifoSet.cs b/neo.UnitTests/IO/Caching/UT_FifoSet.cs
new file mode 100644
index 0000000000..8242572e86
--- /dev/null
+++ b/neo.UnitTests/IO/Caching/UT_FifoSet.cs
@@ -0,0 +1,120 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.IO.Caching;
+using System;
+using System.Linq;
+
+namespace Neo.UnitTests.IO.Caching
+{
+ [TestClass]
+ public class UT_FIFOSet
+ {
+ [TestMethod]
+ public void FIFOSetTest()
+ {
+ var a = UInt256.Zero;
+ var b = new UInt256();
+ var c = new UInt256(new byte[32] {
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01
+ });
+
+ var set = new FIFOSet(3);
+
+ Assert.IsTrue(set.Add(a));
+ Assert.IsFalse(set.Add(a));
+ Assert.IsFalse(set.Add(b));
+ Assert.IsTrue(set.Add(c));
+
+ CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { a, c });
+
+ var d = new UInt256(new byte[32] {
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02
+ });
+
+ // Testing Fifo max size
+ Assert.IsTrue(set.Add(d));
+ CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { a, c, d });
+
+ var e = new UInt256(new byte[32] {
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x03
+ });
+
+ Assert.IsTrue(set.Add(e));
+ Assert.IsFalse(set.Add(e));
+ CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { c, d, e });
+ }
+
+ [TestMethod]
+ public void TestConstructor()
+ {
+ Action action1 = () => new FIFOSet(-1);
+ action1.ShouldThrow();
+
+ Action action2 = () => new FIFOSet(1,-1);
+ action2.ShouldThrow();
+
+ Action action3 = () => new FIFOSet(1,2);
+ action3.ShouldThrow();
+ }
+
+ [TestMethod]
+ public void TestAdd()
+ {
+ var a = new UInt256(new byte[32] {
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01
+ });
+ var b = new UInt256(new byte[32] {
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02
+ });
+ var set = new FIFOSet(1, 1);
+ set.Add(a);
+ set.Add(b);
+ CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { b });
+ }
+
+ [TestMethod]
+ public void TestExceptWith()
+ {
+ var a = new UInt256(new byte[32] {
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01
+ });
+ var b = new UInt256(new byte[32] {
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02
+ });
+ var c = new UInt256(new byte[32] {
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x03
+ });
+
+ var set = new FIFOSet(10);
+ set.Add(a);
+ set.Add(b);
+ set.Add(c);
+ set.ExceptWith(new UInt256[] { b, c });
+ CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { a });
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/IO/Caching/UT_MetaDataCache.cs b/neo.UnitTests/IO/Caching/UT_MetaDataCache.cs
new file mode 100644
index 0000000000..368e866f54
--- /dev/null
+++ b/neo.UnitTests/IO/Caching/UT_MetaDataCache.cs
@@ -0,0 +1,76 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.IO;
+using Neo.IO.Caching;
+using System;
+
+namespace Neo.UnitTests.IO.Caching
+{
+ public class MyMetaCache : MetaDataCache
+ where T : class, ICloneable, ISerializable, new()
+ {
+ public T Value;
+
+ public MyMetaCache(Func factory) : base(factory) { }
+
+ protected override void AddInternal(T item)
+ {
+ Value = item;
+ }
+
+ protected override T TryGetInternal()
+ {
+ return Value;
+ }
+
+ protected override void UpdateInternal(T item)
+ {
+ Value = item;
+ }
+ }
+
+ [TestClass]
+ public class UT_MetaDataCache
+ {
+ MyMetaCache myMetaCache;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ myMetaCache = new MyMetaCache(() => new MyValue());
+ }
+
+ [TestMethod]
+ public void TestContructor()
+ {
+ myMetaCache.Should().NotBeNull();
+ }
+
+ [TestMethod]
+ public void TestCommitAndAddInternal()
+ {
+ MyValue value = myMetaCache.Get();
+ value.Should().NotBeNull();
+ value.Value.Should().BeNull();
+
+ myMetaCache.Commit();
+ myMetaCache.Value.Should().Be(value);
+ }
+
+ public void TestCommitAndUpdateInternal()
+ {
+ MyValue value = myMetaCache.GetAndChange();
+ value.Value = "value1";
+
+ myMetaCache.Commit();
+ myMetaCache.Value.Should().Be(value);
+ myMetaCache.Value.Value.Should().Be("value1");
+ }
+
+ [TestMethod]
+ public void TestCreateSnapshot()
+ {
+ myMetaCache.CreateSnapshot().Should().NotBeNull();
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/IO/Caching/UT_OrderedDictionary.cs b/neo.UnitTests/IO/Caching/UT_OrderedDictionary.cs
new file mode 100644
index 0000000000..94d7b70ce1
--- /dev/null
+++ b/neo.UnitTests/IO/Caching/UT_OrderedDictionary.cs
@@ -0,0 +1,87 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.IO.Caching;
+
+namespace Neo.UnitTests.IO.Caching
+{
+ [TestClass]
+ public class UT_OrderedDictionary
+ {
+ private OrderedDictionary od;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ od = new OrderedDictionary();
+ od.Add("a", 1);
+ od.Add("b", 2);
+ od.Add("c", 3);
+ }
+
+ [TestMethod]
+ public void TestClear()
+ {
+ od.Clear();
+ od.Count.Should().Be(0);
+ od.TryGetValue("a", out uint i).Should().BeFalse();
+ }
+
+ [TestMethod]
+ public void TestCount()
+ {
+ od.Count.Should().Be(3);
+ od.Add("d", 4);
+ od.Count.Should().Be(4);
+ }
+
+ [TestMethod]
+ public void TestIsReadOnly()
+ {
+ od.IsReadOnly.Should().BeFalse();
+ }
+
+ [TestMethod]
+ public void TestSetAndGetItem()
+ {
+ var val = od["a"];
+ val.Should().Be(1);
+ od["d"] = 10;
+ od["d"].Should().Be(10);
+ od["d"] = 15;
+ od["d"].Should().Be(15);
+ }
+
+ [TestMethod]
+ public void TestGetKeys()
+ {
+ var keys = od.Keys;
+ keys.Contains("a").Should().BeTrue();
+ keys.Count.Should().Be(3);
+ }
+
+ [TestMethod]
+ public void TestGetValues()
+ {
+ var values = od.Values;
+ values.Contains(1).Should().BeTrue();
+ values.Count.Should().Be(3);
+ }
+
+ [TestMethod]
+ public void TestRemove()
+ {
+ od.Remove("a");
+ od.Count.Should().Be(2);
+ od.ContainsKey("a").Should().BeFalse();
+ }
+
+ [TestMethod]
+ public void TestTryGetValue()
+ {
+ od.TryGetValue("a", out uint i).Should().BeTrue();
+ i.Should().Be(1);
+ od.TryGetValue("d", out uint j).Should().BeFalse();
+ j.Should().Be(0);
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/IO/Json/UT_JArray.cs b/neo.UnitTests/IO/Json/UT_JArray.cs
new file mode 100644
index 0000000000..7e6e81c8d3
--- /dev/null
+++ b/neo.UnitTests/IO/Json/UT_JArray.cs
@@ -0,0 +1,249 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.IO.Json;
+using FluentAssertions;
+using System;
+using System.Linq;
+using System.Collections;
+
+namespace Neo.UnitTests.IO.Json
+{
+ enum Foo
+ {
+ male,
+ female
+ }
+
+ [TestClass]
+ public class UT_JArray
+ {
+ private JObject alice;
+ private JObject bob;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ alice = new JObject();
+ alice["name"] = "alice";
+ alice["age"] = 30;
+ alice["score"] = 100.001;
+ alice["gender"] = Foo.female;
+ alice["isMarried"] = true;
+ var pet1 = new JObject();
+ pet1["name"] = "Tom";
+ pet1["type"] = "cat";
+ alice["pet"] = pet1;
+
+ bob = new JObject();
+ bob["name"] = "bob";
+ bob["age"] = 100000;
+ bob["score"] = 0.001;
+ bob["gender"] = Foo.male;
+ bob["isMarried"] = false;
+ var pet2 = new JObject();
+ pet2["name"] = "Paul";
+ pet2["type"] = "dog";
+ bob["pet"] = pet2;
+ }
+
+ [TestMethod]
+ public void TestAdd()
+ {
+ var jArray = new JArray();
+ jArray.Add(alice);
+ jArray.Add(bob);
+ var jAlice = jArray[0];
+ var jBob = jArray[1];
+ jAlice["name"].ToString().Should().Be(alice["name"].ToString());
+ jAlice["age"].ToString().Should().Be(alice["age"].ToString());
+ jAlice["score"].ToString().Should().Be(alice["score"].ToString());
+ jAlice["gender"].ToString().Should().Be(alice["gender"].ToString());
+ jAlice["isMarried"].ToString().Should().Be(alice["isMarried"].ToString());
+ jAlice["pet"].ToString().Should().Be(alice["pet"].ToString());
+ jBob["name"].ToString().Should().Be(bob["name"].ToString());
+ jBob["age"].ToString().Should().Be(bob["age"].ToString());
+ jBob["score"].ToString().Should().Be(bob["score"].ToString());
+ jBob["gender"].ToString().Should().Be(bob["gender"].ToString());
+ jBob["isMarried"].ToString().Should().Be(bob["isMarried"].ToString());
+ jBob["pet"].ToString().Should().Be(bob["pet"].ToString());
+ }
+
+ [TestMethod]
+ public void TestSetItem()
+ {
+ var jArray = new JArray
+ {
+ alice
+ };
+ jArray[0] = bob;
+ Assert.AreEqual(jArray[0], bob);
+
+ Action action = () => jArray[1] = alice;
+ action.ShouldThrow();
+ }
+
+ [TestMethod]
+ public void TestClear()
+ {
+ var jArray = new JArray
+ {
+ alice
+ };
+ var jAlice = jArray[0];
+ jAlice["name"].ToString().Should().Be(alice["name"].ToString());
+ jAlice["age"].ToString().Should().Be(alice["age"].ToString());
+ jAlice["score"].ToString().Should().Be(alice["score"].ToString());
+ jAlice["gender"].ToString().Should().Be(alice["gender"].ToString());
+ jAlice["isMarried"].ToString().Should().Be(alice["isMarried"].ToString());
+ jAlice["pet"].ToString().Should().Be(alice["pet"].ToString());
+
+ jArray.Clear();
+ Action action = () => jArray[0].ToString();
+ action.ShouldThrow();
+ }
+
+ [TestMethod]
+ public void TestContains()
+ {
+ var jArray = new JArray();
+ jArray.Add(alice);
+
+ jArray.Contains(alice).Should().BeTrue();
+ jArray.Contains(bob).Should().BeFalse();
+ }
+
+ [TestMethod]
+ public void TestCopyTo()
+ {
+ var jArray = new JArray
+ {
+ alice,
+ bob
+ };
+
+ JObject[] jObjects1 = new JObject[2];
+ jArray.CopyTo(jObjects1, 0);
+ var jAlice1 = jObjects1[0];
+ var jBob1 = jObjects1[1];
+ Assert.AreEqual(alice, jAlice1);
+ Assert.AreEqual(bob, jBob1);
+
+ JObject[] jObjects2 = new JObject[4];
+ jArray.CopyTo(jObjects2, 2);
+ var jAlice2 = jObjects2[2];
+ var jBob2 = jObjects2[3];
+ jObjects2[0].Should().BeNull();
+ jObjects2[1].Should().BeNull();
+ Assert.AreEqual(alice, jAlice2);
+ Assert.AreEqual(bob, jBob2);
+ }
+
+ [TestMethod]
+ public void TestInsert()
+ {
+ var jArray = new JArray
+ {
+ alice,
+ alice,
+ alice,
+ alice
+ };
+
+ jArray.Insert(1, bob);
+ jArray.Count().Should().Be(5);
+ jArray[0].Should().Be(alice);
+ jArray[1].Should().Be(bob);
+ jArray[2].Should().Be(alice);
+
+ jArray.Insert(5, bob);
+ jArray.Count().Should().Be(6);
+ jArray[5].Should().Be(bob);
+ }
+
+ [TestMethod]
+ public void TestIndexOf()
+ {
+ var jArray = new JArray();
+ jArray.IndexOf(alice).Should().Be(-1);
+
+ jArray.Add(alice);
+ jArray.Add(alice);
+ jArray.Add(alice);
+ jArray.Add(alice);
+ jArray.IndexOf(alice).Should().Be(0);
+
+ jArray.Insert(1, bob);
+ jArray.IndexOf(bob).Should().Be(1);
+ }
+
+ [TestMethod]
+ public void TestIsReadOnly()
+ {
+ var jArray = new JArray();
+ jArray.IsReadOnly.Should().BeFalse();
+ }
+
+ [TestMethod]
+ public void TestRemove()
+ {
+ var jArray = new JArray
+ {
+ alice
+ };
+ jArray.Count().Should().Be(1);
+ jArray.Remove(alice);
+ jArray.Count().Should().Be(0);
+
+ jArray.Add(alice);
+ jArray.Add(alice);
+ jArray.Count().Should().Be(2);
+ jArray.Remove(alice);
+ jArray.Count().Should().Be(1);
+ }
+
+ [TestMethod]
+ public void TestRemoveAt()
+ {
+ var jArray = new JArray
+ {
+ alice,
+ bob,
+ alice
+ };
+ jArray.RemoveAt(1);
+ jArray.Count().Should().Be(2);
+ jArray.Contains(bob).Should().BeFalse();
+ }
+
+ [TestMethod]
+ public void TestGetEnumerator()
+ {
+ var jArray = new JArray
+ {
+ alice,
+ bob,
+ alice,
+ bob
+ };
+ int i = 0;
+ foreach (var item in jArray)
+ {
+ if (i % 2 == 0) item.Should().Be(alice);
+ if (i % 2 != 0) item.Should().Be(bob);
+ i++;
+ }
+ Assert.IsNotNull(((IEnumerable)jArray).GetEnumerator());
+ }
+
+ [TestMethod]
+ public void TestAsString()
+ {
+ var jArray = new JArray
+ {
+ alice,
+ bob,
+ };
+ var s = jArray.AsString();
+ Assert.AreEqual(s, "{\"name\":\"alice\",\"age\":30,\"score\":100.001,\"gender\":\"female\",\"isMarried\":true,\"pet\":{\"name\":\"Tom\",\"type\":\"cat\"}},{\"name\":\"bob\",\"age\":100000,\"score\":0.001,\"gender\":\"male\",\"isMarried\":false,\"pet\":{\"name\":\"Paul\",\"type\":\"dog\"}}");
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/IO/Json/UT_JBoolean.cs b/neo.UnitTests/IO/Json/UT_JBoolean.cs
new file mode 100644
index 0000000000..cb44570e45
--- /dev/null
+++ b/neo.UnitTests/IO/Json/UT_JBoolean.cs
@@ -0,0 +1,77 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.IO.Json;
+using System;
+using System.IO;
+
+namespace Neo.UnitTests.IO.Json
+{
+ [TestClass]
+ public class UT_JBoolean
+ {
+ private JBoolean jFalse;
+ private JBoolean jTrue;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ jFalse = new JBoolean();
+ jTrue = new JBoolean(true);
+ }
+
+ [TestMethod]
+ public void TestAsNumber()
+ {
+ jFalse.AsNumber().Should().Be(0);
+ jTrue.AsNumber().Should().Be(1);
+ }
+
+ [TestMethod]
+ public void TestParse()
+ {
+ TextReader tr1 = new StringReader("true");
+ JBoolean ret1 = JBoolean.Parse(tr1);
+ ret1.AsBoolean().Should().BeTrue();
+
+ TextReader tr2 = new StringReader("false");
+ JBoolean ret2 = JBoolean.Parse(tr2);
+ ret2.AsBoolean().Should().BeFalse();
+
+ TextReader tr3 = new StringReader("aaa");
+ Action action = () => JBoolean.Parse(tr3);
+ action.ShouldThrow();
+ }
+
+ [TestMethod]
+ public void TestParseFalse()
+ {
+ TextReader tr1 = new StringReader("false");
+ JBoolean ret1 = JBoolean.ParseFalse(tr1);
+ ret1.AsBoolean().Should().BeFalse();
+
+ TextReader tr2 = new StringReader("aaa");
+ Action action = () => JBoolean.ParseFalse(tr2);
+ action.ShouldThrow();
+
+ TextReader tr3 = new StringReader("\t\rfalse");
+ JBoolean ret3 = JBoolean.ParseFalse(tr3);
+ ret3.AsBoolean().Should().BeFalse();
+ }
+
+ [TestMethod]
+ public void TestParseTrue()
+ {
+ TextReader tr1 = new StringReader("true");
+ JBoolean ret1 = JBoolean.ParseTrue(tr1);
+ ret1.AsBoolean().Should().BeTrue();
+
+ TextReader tr2 = new StringReader("aaa");
+ Action action = () => JBoolean.ParseTrue(tr2);
+ action.ShouldThrow();
+
+ TextReader tr3 = new StringReader(" true");
+ JBoolean ret3 = JBoolean.ParseTrue(tr3);
+ ret3.AsBoolean().Should().BeTrue();
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/IO/Json/UT_JNumber.cs b/neo.UnitTests/IO/Json/UT_JNumber.cs
new file mode 100644
index 0000000000..7232e8b969
--- /dev/null
+++ b/neo.UnitTests/IO/Json/UT_JNumber.cs
@@ -0,0 +1,67 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.IO.Json;
+using System;
+using System.IO;
+
+namespace Neo.UnitTests.IO.Json
+{
+ enum Woo
+ {
+ Tom,
+ Jerry,
+ James
+ }
+
+ [TestClass]
+ public class UT_JNumber
+ {
+ private JNumber maxInt;
+ private JNumber minInt;
+ private JNumber zero;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ maxInt = new JNumber(JNumber.MAX_SAFE_INTEGER);
+ minInt = new JNumber(JNumber.MIN_SAFE_INTEGER);
+ zero = new JNumber();
+ }
+
+ [TestMethod]
+ public void TestAsBoolean()
+ {
+ maxInt.AsBoolean().Should().BeTrue();
+ zero.AsBoolean().Should().BeFalse();
+ }
+
+ [TestMethod]
+ public void TestAsString()
+ {
+ Action action1 = () => new JNumber(double.PositiveInfinity).AsString();
+ action1.ShouldThrow();
+
+ Action action2 = () => new JNumber(double.NegativeInfinity).AsString();
+ action2.ShouldThrow();
+ }
+
+ [TestMethod]
+ public void TestTryGetEnum()
+ {
+ zero.TryGetEnum().Should().Be(Woo.Tom);
+ new JNumber(1).TryGetEnum().Should().Be(Woo.Jerry);
+ new JNumber(2).TryGetEnum().Should().Be(Woo.James);
+ new JNumber(3).TryGetEnum().Should().Be(Woo.Tom);
+ }
+
+ [TestMethod]
+ public void TestParse()
+ {
+ Action action1 = () => JNumber.Parse(new StringReader("100.a"));
+ action1.ShouldThrow();
+
+ Action action2 = () => JNumber.Parse(new StringReader("100.+"));
+ action2.ShouldThrow();
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/IO/Json/UT_JObject.cs b/neo.UnitTests/IO/Json/UT_JObject.cs
new file mode 100644
index 0000000000..38781ed96a
--- /dev/null
+++ b/neo.UnitTests/IO/Json/UT_JObject.cs
@@ -0,0 +1,119 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.IO.Json;
+using System;
+using System.IO;
+using System.Reflection;
+
+namespace Neo.UnitTests.IO.Json
+{
+ [TestClass]
+ public class UT_JObject
+ {
+ private JObject alice;
+ private JObject bob;
+
+ [TestInitialize]
+ public void SetUp()
+ {
+ alice = new JObject();
+ alice["name"] = "alice";
+ alice["age"] = 30;
+ alice["score"] = 100.001;
+ alice["gender"] = Foo.female;
+ alice["isMarried"] = true;
+ var pet1 = new JObject();
+ pet1["name"] = "Tom";
+ pet1["type"] = "cat";
+ alice["pet"] = pet1;
+
+ bob = new JObject();
+ bob["name"] = "bob";
+ bob["age"] = 100000;
+ bob["score"] = 0.001;
+ bob["gender"] = Foo.male;
+ bob["isMarried"] = false;
+ var pet2 = new JObject();
+ pet2["name"] = "Paul";
+ pet2["type"] = "dog";
+ bob["pet"] = pet2;
+ }
+
+ [TestMethod]
+ public void TestAsBoolean()
+ {
+ alice.AsBoolean().Should().BeTrue();
+ }
+
+ [TestMethod]
+ public void TestAsNumber()
+ {
+ alice.AsNumber().Should().Be(double.NaN);
+ }
+
+ [TestMethod]
+ public void TestParse()
+ {
+ Action action = () => JObject.Parse(new StringReader(""), -1);
+ action.ShouldThrow();
+ }
+
+ [TestMethod]
+ public void TestParseNull()
+ {
+ Action action = () => JObject.Parse(new StringReader("naaa"));
+ action.ShouldThrow();
+
+ JObject.Parse(new StringReader("null")).Should().BeNull();
+ }
+
+ [TestMethod]
+ public void TestParseObject()
+ {
+ Action action1 = () => JObject.Parse(new StringReader("{\"k1\":\"v1\",\"k1\":\"v2\"}"), 100);
+ action1.ShouldThrow();
+
+ Action action2 = () => JObject.Parse(new StringReader("{\"k1\",\"k1\"}"), 100);
+ action2.ShouldThrow();
+
+ Action action3 = () => JObject.Parse(new StringReader("{\"k1\":\"v1\""), 100);
+ action3.ShouldThrow();
+
+ Action action4 = () => JObject.Parse(new StringReader("aaa"), 100);
+ action4.ShouldThrow();
+
+ JObject.Parse(new StringReader("{\"k1\":\"v1\"}"), 100).ToString().Should().Be("{\"k1\":\"v1\"}");
+ }
+
+ [TestMethod]
+ public void TestTryGetEnum()
+ {
+ alice.TryGetEnum().Should().Be(Woo.Tom);
+ }
+
+ [TestMethod]
+ public void TestOpImplicitEnum()
+ {
+ var obj = new JObject();
+ obj = Woo.Tom;
+ obj.AsString().Should().Be("Tom");
+ }
+
+ [TestMethod]
+ public void TestOpImplicitString()
+ {
+ var obj = new JObject();
+ obj = null;
+ obj.Should().BeNull();
+
+ obj = "{\"aaa\":\"111\"}";
+ obj.AsString().Should().Be("{\"aaa\":\"111\"}");
+ }
+
+ [TestMethod]
+ public void TestGetNull()
+ {
+ JObject.Null.Should().BeNull();
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/IO/Json/UT_JString.cs b/neo.UnitTests/IO/Json/UT_JString.cs
new file mode 100644
index 0000000000..07f231674f
--- /dev/null
+++ b/neo.UnitTests/IO/Json/UT_JString.cs
@@ -0,0 +1,73 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.IO.Json;
+using Neo.SmartContract;
+using System;
+using System.IO;
+
+namespace Neo.UnitTests.IO
+{
+ [TestClass]
+ public class UT_JString
+ {
+ [TestMethod]
+ public void TestConstructor()
+ {
+ String s = "hello world";
+ JString jstring = new JString(s);
+ Assert.AreEqual(s, jstring.Value);
+ Assert.ThrowsException(() => new JString(null));
+ }
+
+ [TestMethod]
+ public void TestAsBoolean()
+ {
+ String s1 = "hello world";
+ String s2 = "";
+ JString jstring1 = new JString(s1);
+ JString jstring2 = new JString(s2);
+ Assert.AreEqual(true, jstring1.AsBoolean());
+ Assert.AreEqual(false, jstring2.AsBoolean());
+ }
+
+ [TestMethod]
+ public void TestParse()
+ {
+ TextReader tr = new StringReader("\"hello world\"");
+ String s = JString.Parse(tr).Value;
+ Assert.AreEqual("hello world", s);
+
+ tr = new StringReader("hello world");
+ Assert.ThrowsException(() => JString.Parse(tr));
+
+ tr = new StringReader("\"\\s\"");
+ Assert.ThrowsException(() => JString.Parse(tr));
+
+ tr = new StringReader("\"\\\"\\\\\\/\\b\\f\\n\\r\\t\"");
+ s = JString.Parse(tr).Value;
+ Assert.AreEqual("\"\\/\b\f\n\r\t", s);
+
+ tr = new StringReader("\"\\u0030\"");
+ s = JString.Parse(tr).Value;
+ Assert.AreEqual("0", s);
+
+ tr = new StringReader("\"a");
+ Assert.ThrowsException(() => JString.Parse(tr));
+
+ byte[] byteArray = new byte[] { 0x22, 0x01, 0x22 };
+ tr = new StringReader(System.Text.Encoding.ASCII.GetString(byteArray));
+ Assert.ThrowsException(() => JString.Parse(tr));
+ }
+
+ [TestMethod]
+ public void TestTryGetEnum()
+ {
+ JString s = new JString("Signature");
+ ContractParameterType cp = s.TryGetEnum(ContractParameterType.Void, false);
+ Assert.AreEqual(ContractParameterType.Signature, cp);
+
+ s = new JString("");
+ cp = s.TryGetEnum(ContractParameterType.Void, false);
+ Assert.AreEqual(ContractParameterType.Void, cp);
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/IO/UT_IOHelper.cs b/neo.UnitTests/IO/UT_IOHelper.cs
new file mode 100644
index 0000000000..e113ce8cd4
--- /dev/null
+++ b/neo.UnitTests/IO/UT_IOHelper.cs
@@ -0,0 +1,549 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.IO;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Neo.UnitTests.IO
+{
+ [TestClass]
+ public class UT_IOHelper
+ {
+ [TestMethod]
+ public void TestAsSerializableGeneric()
+ {
+ byte[] caseArray = new byte[] { 0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00 };
+ UInt160 result = Neo.IO.Helper.AsSerializable(caseArray);
+ Assert.AreEqual(UInt160.Zero, result);
+ }
+
+ [TestMethod]
+ public void TestAsSerializable()
+ {
+ for (int i = 0; i < 2; i++)
+ {
+ if (i == 0)
+ {
+ byte[] caseArray = new byte[] { 0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00 };
+ ISerializable result = Neo.IO.Helper.AsSerializable(caseArray, typeof(UInt160));
+ Assert.AreEqual(UInt160.Zero, result);
+ }
+ else
+ {
+ Action action = () => Neo.IO.Helper.AsSerializable(new byte[0], typeof(Double));
+ action.ShouldThrow();
+ }
+ }
+ }
+
+ [TestMethod]
+ public void TestAsSerializableArray()
+ {
+ byte[] byteArray = Neo.IO.Helper.ToByteArray(new UInt160[] { UInt160.Zero });
+ UInt160[] result = Neo.IO.Helper.AsSerializableArray(byteArray);
+ Assert.AreEqual(1, result.Length);
+ Assert.AreEqual(UInt160.Zero, result[0]);
+ }
+
+ [TestMethod]
+ public void TestGetVarSizeInt()
+ {
+ for (int i = 0; i < 3; i++)
+ {
+ if (i == 0)
+ {
+ int result = Neo.IO.Helper.GetVarSize(1);
+ Assert.AreEqual(1, result);
+ }
+ else if (i == 1)
+ {
+ int result = Neo.IO.Helper.GetVarSize(0xFFFF);
+ Assert.AreEqual(3, result);
+ }
+ else
+ {
+ int result = Neo.IO.Helper.GetVarSize(0xFFFFFF);
+ Assert.AreEqual(5, result);
+ }
+ }
+ }
+ enum TestEnum0 : sbyte
+ {
+ case1 = 1, case2 = 2
+ }
+
+ enum TestEnum1 : byte
+ {
+ case1 = 1, case2 = 2
+ }
+
+ enum TestEnum2 : short
+ {
+ case1 = 1, case2 = 2
+ }
+
+ enum TestEnum3 : ushort
+ {
+ case1 = 1, case2 = 2
+ }
+
+ enum TestEnum4 : int
+ {
+ case1 = 1, case2 = 2
+ }
+
+ enum TestEnum5 : uint
+ {
+ case1 = 1, case2 = 2
+ }
+
+ enum TestEnum6 : long
+ {
+ case1 = 1, case2 = 2
+ }
+
+ [TestMethod]
+ public void TestGetVarSizeGeneric()
+ {
+ for (int i = 0; i < 9; i++)
+ {
+ if (i == 0)
+ {
+ int result = Neo.IO.Helper.GetVarSize(new UInt160[] { UInt160.Zero });
+ Assert.AreEqual(21, result);
+ }
+ else if (i == 1)//sbyte
+ {
+ List initList = new List
+ {
+ TestEnum0.case1
+ };
+ IReadOnlyCollection testList = initList.AsReadOnly();
+ int result = Neo.IO.Helper.GetVarSize(testList);
+ Assert.AreEqual(2, result);
+ }
+ else if (i == 2)//byte
+ {
+ List initList = new List
+ {
+ TestEnum1.case1
+ };
+ IReadOnlyCollection testList = initList.AsReadOnly();
+ int result = Neo.IO.Helper.GetVarSize(testList);
+ Assert.AreEqual(2, result);
+ }
+ else if (i == 3)//short
+ {
+ List initList = new List
+ {
+ TestEnum2.case1
+ };
+ IReadOnlyCollection testList = initList.AsReadOnly();
+ int result = Neo.IO.Helper.GetVarSize(testList);
+ Assert.AreEqual(3, result);
+ }
+ else if (i == 4)//ushort
+ {
+ List initList = new List
+ {
+ TestEnum3.case1
+ };
+ IReadOnlyCollection testList = initList.AsReadOnly();
+ int result = Neo.IO.Helper.GetVarSize(testList);
+ Assert.AreEqual(3, result);
+ }
+ else if (i == 5)//int
+ {
+ List initList = new List
+ {
+ TestEnum4.case1
+ };
+ IReadOnlyCollection testList = initList.AsReadOnly();
+ int result = Neo.IO.Helper.GetVarSize(testList);
+ Assert.AreEqual(5, result);
+ }
+ else if (i == 6)//uint
+ {
+ List initList = new List
+ {
+ TestEnum5.case1
+ };
+ IReadOnlyCollection testList = initList.AsReadOnly();
+ int result = Neo.IO.Helper.GetVarSize(testList);
+ Assert.AreEqual(5, result);
+ }
+ else if (i == 7)//long
+ {
+ List initList = new List
+ {
+ TestEnum6.case1
+ };
+ IReadOnlyCollection testList = initList.AsReadOnly();
+ int result = Neo.IO.Helper.GetVarSize(testList);
+ Assert.AreEqual(9, result);
+ }
+ else if (i == 8)
+ {
+ List initList = new List
+ {
+ 1
+ };
+ IReadOnlyCollection testList = initList.AsReadOnly();
+ int result = Neo.IO.Helper.GetVarSize(testList);
+ Assert.AreEqual(5, result);
+ }
+ }
+ }
+
+ [TestMethod]
+ public void TestGetVarSizeString()
+ {
+ int result = Neo.IO.Helper.GetVarSize("AA");
+ Assert.AreEqual(3, result);
+ }
+
+ [TestMethod]
+ public void TestReadBytesWithGrouping()
+ {
+ for (int i = 0; i < 2; i++)
+ {
+ if (i == 0)
+ {
+ byte[] caseArray = new byte[] { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA};
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Neo.IO.Helper.WriteBytesWithGrouping(writer, caseArray);
+ stream.Seek(0, SeekOrigin.Begin);
+ BinaryReader reader = new BinaryReader(stream);
+ byte[] result = Neo.IO.Helper.ReadBytesWithGrouping(reader);
+ Assert.AreEqual(Encoding.Default.GetString(caseArray), Encoding.Default.GetString(result));
+ }
+ else
+ {
+ byte[] caseArray = new byte[] { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x00,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x00,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x11};
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ writer.Write(caseArray);
+ stream.Seek(0, SeekOrigin.Begin);
+ BinaryReader reader = new BinaryReader(stream);
+ Action action = () => Neo.IO.Helper.ReadBytesWithGrouping(reader);
+ action.ShouldThrow();
+ }
+ }
+ }
+
+ [TestMethod]
+ public void TestReadFixedString()
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Neo.IO.Helper.WriteFixedString(writer, "AA", Encoding.UTF8.GetBytes("AA").Length + 1);
+ stream.Seek(0, SeekOrigin.Begin);
+ BinaryReader reader = new BinaryReader(stream);
+ string result = Neo.IO.Helper.ReadFixedString(reader, Encoding.UTF8.GetBytes("AA").Length + 1);
+ Assert.AreEqual("AA", result);
+ }
+
+ [TestMethod]
+ public void TestReadSerializable()
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Neo.IO.Helper.Write(writer, UInt160.Zero);
+ stream.Seek(0, SeekOrigin.Begin);
+ BinaryReader reader = new BinaryReader(stream);
+ UInt160 result = Neo.IO.Helper.ReadSerializable(reader);
+ Assert.AreEqual(UInt160.Zero, result);
+ }
+
+ [TestMethod]
+ public void TestReadSerializableArray()
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Neo.IO.Helper.Write(writer, new UInt160[] { UInt160.Zero });
+ stream.Seek(0, SeekOrigin.Begin);
+ BinaryReader reader = new BinaryReader(stream);
+ UInt160[] resultArray = Neo.IO.Helper.ReadSerializableArray(reader);
+ Assert.AreEqual(1, resultArray.Length);
+ Assert.AreEqual(UInt160.Zero, resultArray[0]);
+ }
+
+ [TestMethod]
+ public void TestReadVarBytes()
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Neo.IO.Helper.WriteVarBytes(writer, new byte[] { 0xAA, 0xAA });
+ stream.Seek(0, SeekOrigin.Begin);
+ BinaryReader reader = new BinaryReader(stream);
+ byte[] byteArray = Neo.IO.Helper.ReadVarBytes(reader, 10);
+ Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0xAA, 0xAA }), Encoding.Default.GetString(byteArray));
+ }
+
+ [TestMethod]
+ public void TestReadVarInt()
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ if (i == 0)
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Neo.IO.Helper.WriteVarInt(writer, 0xFFFF);
+ stream.Seek(0, SeekOrigin.Begin);
+ BinaryReader reader = new BinaryReader(stream);
+ ulong result = Neo.IO.Helper.ReadVarInt(reader, 0xFFFF);
+ Assert.AreEqual((ulong)0xFFFF, result);
+ }
+ else if (i == 1)
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Neo.IO.Helper.WriteVarInt(writer, 0xFFFFFFFF);
+ stream.Seek(0, SeekOrigin.Begin);
+ BinaryReader reader = new BinaryReader(stream);
+ ulong result = Neo.IO.Helper.ReadVarInt(reader, 0xFFFFFFFF);
+ Assert.AreEqual(0xFFFFFFFF, result);
+ }
+ else
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Neo.IO.Helper.WriteVarInt(writer, 0xFFFFFFFFFF);
+ stream.Seek(0, SeekOrigin.Begin);
+ BinaryReader reader = new BinaryReader(stream);
+ Action action = () => Neo.IO.Helper.ReadVarInt(reader, 0xFFFFFFFF);
+ action.ShouldThrow();
+ }
+ }
+ }
+
+ [TestMethod]
+ public void TestReadVarString()
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Neo.IO.Helper.WriteVarString(writer, "AAAAAAA");
+ stream.Seek(0, SeekOrigin.Begin);
+ BinaryReader reader = new BinaryReader(stream);
+ string result = Neo.IO.Helper.ReadVarString(reader, 10);
+ stream.Seek(0, SeekOrigin.Begin);
+ Assert.AreEqual("AAAAAAA", result);
+ }
+
+ [TestMethod]
+ public void TestToArray()
+ {
+ byte[] byteArray = Neo.IO.Helper.ToArray(UInt160.Zero);
+ Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00}), Encoding.Default.GetString(byteArray));
+ }
+
+ [TestMethod]
+ public void TestToByteArrayGeneric()
+ {
+ byte[] byteArray = Neo.IO.Helper.ToByteArray(new UInt160[] { UInt160.Zero });
+ Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00}), Encoding.Default.GetString(byteArray));
+ }
+
+ [TestMethod]
+ public void TestWrite()
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Neo.IO.Helper.Write(writer, UInt160.Zero);
+ stream.Seek(0, SeekOrigin.Begin);
+ byte[] byteArray = new byte[stream.Length];
+ stream.Read(byteArray, 0, (int)stream.Length);
+ Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00}), Encoding.Default.GetString(byteArray));
+ }
+
+ [TestMethod]
+ public void TestWriteGeneric()
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Neo.IO.Helper.Write(writer, new UInt160[] { UInt160.Zero });
+ stream.Seek(0, SeekOrigin.Begin);
+ byte[] byteArray = new byte[stream.Length];
+ stream.Read(byteArray, 0, (int)stream.Length);
+ Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00}), Encoding.Default.GetString(byteArray));
+ }
+
+
+ [TestMethod]
+ public void TestWriteBytesWithGrouping()
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Neo.IO.Helper.WriteBytesWithGrouping(writer, new byte[] { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA});
+ stream.Seek(0, SeekOrigin.Begin);
+ byte[] byteArray = new byte[stream.Length];
+ stream.Read(byteArray, 0, (int)stream.Length);
+ Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x00,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x00,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x0C}), Encoding.Default.GetString(byteArray));
+ }
+
+ [TestMethod]
+ public void TestWriteFixedString()
+ {
+ for (int i = 0; i < 5; i++)
+ {
+ if (i == 0)
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Action action = () => Neo.IO.Helper.WriteFixedString(writer, null, 0);
+ action.ShouldThrow();
+ }
+ else if (i == 1)
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Action action = () => Neo.IO.Helper.WriteFixedString(writer, "AA", Encoding.UTF8.GetBytes("AA").Length - 1);
+ action.ShouldThrow();
+ }
+ else if (i == 2)
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Action action = () => Neo.IO.Helper.WriteFixedString(writer, "拉拉", Encoding.UTF8.GetBytes("拉拉").Length - 1);
+ action.ShouldThrow();
+ }
+ else if (i == 3)
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Neo.IO.Helper.WriteFixedString(writer, "AA", Encoding.UTF8.GetBytes("AA").Length + 1);
+ stream.Seek(0, SeekOrigin.Begin);
+ byte[] byteArray = new byte[stream.Length];
+ stream.Read(byteArray, 0, (int)stream.Length);
+ byte[] newArray = new byte[Encoding.UTF8.GetBytes("AA").Length + 1];
+ Encoding.UTF8.GetBytes("AA").CopyTo(newArray, 0);
+ Assert.AreEqual(Encoding.Default.GetString(newArray), Encoding.Default.GetString(byteArray));
+ }
+ }
+ }
+
+ [TestMethod]
+ public void TestWriteVarBytes()
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Neo.IO.Helper.WriteVarBytes(writer, new byte[] { 0xAA });
+ stream.Seek(0, SeekOrigin.Begin);
+ byte[] byteArray = new byte[stream.Length];
+ stream.Read(byteArray, 0, (int)stream.Length);
+ Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01, 0xAA }), Encoding.Default.GetString(byteArray));
+ }
+
+ [TestMethod]
+ public void TestWriteVarInt()
+ {
+ for (int i = 0; i < 5; i++)
+ {
+ if (i == 0)
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Action action = () => Neo.IO.Helper.WriteVarInt(writer, -1);
+ action.ShouldThrow();
+ }
+ else if (i == 1)
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Neo.IO.Helper.WriteVarInt(writer, 0xFC);
+ stream.Seek(0, SeekOrigin.Begin);
+ byte[] byteArray = new byte[stream.Length];
+ stream.Read(byteArray, 0, (int)stream.Length);
+ Assert.AreEqual(0xFC, byteArray[0]);
+ }
+ else if (i == 2)
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Neo.IO.Helper.WriteVarInt(writer, 0xFFFF);
+ stream.Seek(0, SeekOrigin.Begin);
+ byte[] byteArray = new byte[stream.Length];
+ stream.Read(byteArray, 0, (int)stream.Length);
+ Assert.AreEqual(0xFD, byteArray[0]);
+ Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0xFF, 0xFF }), Encoding.Default.GetString(byteArray.Skip(1).Take(byteArray.Length - 1).ToArray()));
+ }
+ else if (i == 3)
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Neo.IO.Helper.WriteVarInt(writer, 0xFFFFFFFF);
+ stream.Seek(0, SeekOrigin.Begin);
+ byte[] byteArray = new byte[stream.Length];
+ stream.Read(byteArray, 0, (int)stream.Length);
+ Assert.AreEqual(0xFE, byteArray[0]);
+ Assert.AreEqual(0xFFFFFFFF, BitConverter.ToUInt32(byteArray, 1));
+ }
+ else
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Neo.IO.Helper.WriteVarInt(writer, 0xAEFFFFFFFF);
+ stream.Seek(0, SeekOrigin.Begin);
+ byte[] byteArray = new byte[stream.Length];
+ stream.Read(byteArray, 0, (int)stream.Length);
+ Assert.AreEqual(0xFF, byteArray[0]);
+ Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00 }), Encoding.Default.GetString(byteArray.Skip(1).Take(byteArray.Length - 1).ToArray()));
+ }
+ }
+ }
+
+ [TestMethod]
+ public void TestWriteVarString()
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ Neo.IO.Helper.WriteVarString(writer, "a");
+ stream.Seek(0, SeekOrigin.Begin);
+ byte[] byteArray = new byte[stream.Length];
+ stream.Read(byteArray, 0, (int)stream.Length);
+ Assert.AreEqual(0x01, byteArray[0]);
+ Assert.AreEqual(0x61, byteArray[1]);
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/IO/Wrappers/UT_SerializableWrapper.cs b/neo.UnitTests/IO/Wrappers/UT_SerializableWrapper.cs
new file mode 100644
index 0000000000..3f4f0c6d06
--- /dev/null
+++ b/neo.UnitTests/IO/Wrappers/UT_SerializableWrapper.cs
@@ -0,0 +1,50 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.IO.Wrappers;
+using System.IO;
+
+namespace Neo.UnitTests
+{
+ [TestClass]
+ public class UT_SerializableWrapper
+ {
+ [TestMethod]
+ public void TestGetSize()
+ {
+ SerializableWrapper temp = new UInt32Wrapper();
+ Assert.AreEqual(4, temp.Size);
+ }
+
+ [TestMethod]
+ public void TestEqualsOtherObject()
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ BinaryReader reader = new BinaryReader(stream);
+ writer.Write((uint)1);
+ stream.Seek(0, SeekOrigin.Begin);
+ SerializableWrapper temp = new UInt32Wrapper();
+ temp.Deserialize(reader);
+ Assert.AreEqual(true, temp.Equals(1));
+ }
+
+ [TestMethod]
+ public void TestEqualsOtherSerializableWrapper()
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ BinaryReader reader = new BinaryReader(stream);
+ writer.Write((uint)1);
+ stream.Seek(0, SeekOrigin.Begin);
+ SerializableWrapper temp = new UInt32Wrapper();
+ temp.Deserialize(reader);
+ MemoryStream stream2 = new MemoryStream();
+ BinaryWriter writer2 = new BinaryWriter(stream2);
+ BinaryReader reader2 = new BinaryReader(stream2);
+ writer2.Write((uint)1);
+ stream2.Seek(0, SeekOrigin.Begin);
+ SerializableWrapper temp2 = new UInt32Wrapper();
+ temp2.Deserialize(reader2);
+ Assert.AreEqual(true, temp.Equals(temp2));
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/IO/Wrappers/UT_UInt32Wrapper.cs b/neo.UnitTests/IO/Wrappers/UT_UInt32Wrapper.cs
new file mode 100644
index 0000000000..7762c56b7c
--- /dev/null
+++ b/neo.UnitTests/IO/Wrappers/UT_UInt32Wrapper.cs
@@ -0,0 +1,97 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.IO.Wrappers;
+using System.IO;
+using System.Text;
+
+namespace Neo.UnitTests
+{
+ [TestClass]
+ public class UT_UInt32Wrapper
+ {
+ [TestMethod]
+ public void TestGetSize()
+ {
+ UInt32Wrapper temp = new UInt32Wrapper();
+ Assert.AreEqual(4, temp.Size);
+ }
+
+ [TestMethod]
+ public void TestDeserialize()
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ BinaryReader reader = new BinaryReader(stream);
+ writer.Write(new byte[] { 0x00, 0x00, 0x00, 0x01 });
+ stream.Seek(0, SeekOrigin.Begin);
+ UInt32Wrapper temp = new UInt32Wrapper();
+ temp.Deserialize(reader);
+ MemoryStream stream2 = new MemoryStream();
+ BinaryWriter writer2 = new BinaryWriter(stream2);
+ temp.Serialize(writer2);
+ stream2.Seek(0, SeekOrigin.Begin);
+ byte[] byteArray = new byte[stream2.Length];
+ stream2.Read(byteArray, 0, (int)stream2.Length);
+ Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x00, 0x00, 0x00, 0x01 }), Encoding.Default.GetString(byteArray));
+ }
+
+ [TestMethod]
+ public void TestSerialize()
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ BinaryReader reader = new BinaryReader(stream);
+ writer.Write(new byte[] { 0x00, 0x00, 0x00, 0x01 });
+ stream.Seek(0, SeekOrigin.Begin);
+ UInt32Wrapper temp = new UInt32Wrapper();
+ temp.Deserialize(reader);
+ MemoryStream stream2 = new MemoryStream();
+ BinaryWriter writer2 = new BinaryWriter(stream2);
+ temp.Serialize(writer2);
+ stream2.Seek(0, SeekOrigin.Begin);
+ byte[] byteArray = new byte[stream2.Length];
+ stream2.Read(byteArray, 0, (int)stream2.Length);
+ Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x00, 0x00, 0x00, 0x01 }), Encoding.Default.GetString(byteArray));
+ }
+
+ [TestMethod]
+ public void TestEqualsUInt32Wrapper()
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ BinaryReader reader = new BinaryReader(stream);
+ writer.Write((uint)1);
+ stream.Seek(0, SeekOrigin.Begin);
+ UInt32Wrapper temp = new UInt32Wrapper();
+ temp.Deserialize(reader);
+ MemoryStream stream2 = new MemoryStream();
+ BinaryWriter writer2 = new BinaryWriter(stream2);
+ BinaryReader reader2 = new BinaryReader(stream2);
+ writer2.Write((uint)1);
+ stream2.Seek(0, SeekOrigin.Begin);
+ UInt32Wrapper temp2 = new UInt32Wrapper();
+ temp2.Deserialize(reader2);
+ Assert.AreEqual(true, temp.Equals(temp2));
+ }
+
+ [TestMethod]
+ public void TestOperatorUint()
+ {
+ MemoryStream stream = new MemoryStream();
+ BinaryWriter writer = new BinaryWriter(stream);
+ BinaryReader reader = new BinaryReader(stream);
+ writer.Write((uint)1);
+ stream.Seek(0, SeekOrigin.Begin);
+ UInt32Wrapper temp = new UInt32Wrapper();
+ temp.Deserialize(reader);
+ uint result = temp;
+ Assert.AreEqual((uint)1, result);
+ }
+
+ [TestMethod]
+ public void TestOperatorUInt32Wrapper()
+ {
+ UInt32Wrapper temp = 1;
+ Assert.AreEqual(true, temp.Equals(1));
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/UT_MemoryPool.cs b/neo.UnitTests/Ledger/UT_MemoryPool.cs
similarity index 99%
rename from neo.UnitTests/UT_MemoryPool.cs
rename to neo.UnitTests/Ledger/UT_MemoryPool.cs
index ee79d96842..1b5af16240 100644
--- a/neo.UnitTests/UT_MemoryPool.cs
+++ b/neo.UnitTests/Ledger/UT_MemoryPool.cs
@@ -8,7 +8,7 @@
using System.Collections.Generic;
using System.Linq;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.Ledger
{
[TestClass]
public class UT_MemoryPool
diff --git a/neo.UnitTests/UT_PoolItem.cs b/neo.UnitTests/Ledger/UT_PoolItem.cs
similarity index 99%
rename from neo.UnitTests/UT_PoolItem.cs
rename to neo.UnitTests/Ledger/UT_PoolItem.cs
index cedf7f3fa9..d8f4e4f696 100644
--- a/neo.UnitTests/UT_PoolItem.cs
+++ b/neo.UnitTests/Ledger/UT_PoolItem.cs
@@ -5,7 +5,7 @@
using Neo.Network.P2P.Payloads;
using System;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.Ledger
{
[TestClass]
public class UT_PoolItem
diff --git a/neo.UnitTests/UT_StorageItem.cs b/neo.UnitTests/Ledger/UT_StorageItem.cs
similarity index 98%
rename from neo.UnitTests/UT_StorageItem.cs
rename to neo.UnitTests/Ledger/UT_StorageItem.cs
index c7372eb455..9afab26372 100644
--- a/neo.UnitTests/UT_StorageItem.cs
+++ b/neo.UnitTests/Ledger/UT_StorageItem.cs
@@ -5,7 +5,7 @@
using System.IO;
using System.Text;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.Ledger
{
[TestClass]
public class UT_StorageItem
diff --git a/neo.UnitTests/UT_StorageKey.cs b/neo.UnitTests/Ledger/UT_StorageKey.cs
similarity index 99%
rename from neo.UnitTests/UT_StorageKey.cs
rename to neo.UnitTests/Ledger/UT_StorageKey.cs
index ab718f0f89..7e2ec9bdb2 100644
--- a/neo.UnitTests/UT_StorageKey.cs
+++ b/neo.UnitTests/Ledger/UT_StorageKey.cs
@@ -3,7 +3,7 @@
using Neo.IO;
using Neo.Ledger;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.Ledger
{
[TestClass]
public class UT_StorageKey
diff --git a/neo.UnitTests/UT_Block.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Block.cs
similarity index 99%
rename from neo.UnitTests/UT_Block.cs
rename to neo.UnitTests/Network/P2P/Payloads/UT_Block.cs
index c91776f0c0..6736d8f936 100644
--- a/neo.UnitTests/UT_Block.cs
+++ b/neo.UnitTests/Network/P2P/Payloads/UT_Block.cs
@@ -5,7 +5,7 @@
using System.IO;
using System.Text;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.Network.P2P.Payloads
{
[TestClass]
public class UT_Block
diff --git a/neo.UnitTests/UT_Header.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Header.cs
similarity index 99%
rename from neo.UnitTests/UT_Header.cs
rename to neo.UnitTests/Network/P2P/Payloads/UT_Header.cs
index f07be59051..f9dfd30d1e 100644
--- a/neo.UnitTests/UT_Header.cs
+++ b/neo.UnitTests/Network/P2P/Payloads/UT_Header.cs
@@ -4,7 +4,7 @@
using System.IO;
using System.Text;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.Network.P2P.Payloads
{
[TestClass]
public class UT_Header
diff --git a/neo.UnitTests/UT_Transaction.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs
similarity index 99%
rename from neo.UnitTests/UT_Transaction.cs
rename to neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs
index dc41d3a0d8..2dfa8b4c35 100644
--- a/neo.UnitTests/UT_Transaction.cs
+++ b/neo.UnitTests/Network/P2P/Payloads/UT_Transaction.cs
@@ -13,7 +13,7 @@
using Neo.Wallets;
using Neo.Wallets.NEP6;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.Network.P2P.Payloads
{
[TestClass]
public class UT_Transaction
diff --git a/neo.UnitTests/UT_Witness.cs b/neo.UnitTests/Network/P2P/Payloads/UT_Witness.cs
similarity index 98%
rename from neo.UnitTests/UT_Witness.cs
rename to neo.UnitTests/Network/P2P/Payloads/UT_Witness.cs
index 4ca00b6643..ec3525931e 100644
--- a/neo.UnitTests/UT_Witness.cs
+++ b/neo.UnitTests/Network/P2P/Payloads/UT_Witness.cs
@@ -3,7 +3,7 @@
using Neo.IO.Json;
using Neo.Network.P2P.Payloads;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.Network.P2P.Payloads
{
[TestClass]
public class UT_Witness
diff --git a/neo.UnitTests/UT_P2PMessage.cs b/neo.UnitTests/Network/P2P/UT_Message.cs
similarity index 98%
rename from neo.UnitTests/UT_P2PMessage.cs
rename to neo.UnitTests/Network/P2P/UT_Message.cs
index 99af976992..4bb37a8166 100644
--- a/neo.UnitTests/UT_P2PMessage.cs
+++ b/neo.UnitTests/Network/P2P/UT_Message.cs
@@ -6,10 +6,10 @@
using Neo.Network.P2P.Capabilities;
using Neo.Network.P2P.Payloads;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.Network.P2P
{
[TestClass]
- public class UT_P2PMessage
+ public class UT_Message
{
[TestMethod]
public void Serialize_Deserialize()
diff --git a/neo.UnitTests/UT_ProtocolHandler.cs b/neo.UnitTests/Network/P2P/UT_ProtocolHandler.cs
similarity index 97%
rename from neo.UnitTests/UT_ProtocolHandler.cs
rename to neo.UnitTests/Network/P2P/UT_ProtocolHandler.cs
index 63bfe90e44..4ea998ef40 100644
--- a/neo.UnitTests/UT_ProtocolHandler.cs
+++ b/neo.UnitTests/Network/P2P/UT_ProtocolHandler.cs
@@ -4,7 +4,7 @@
using Neo.Network.P2P.Capabilities;
using Neo.Network.P2P.Payloads;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.Network.P2P
{
[TestClass]
public class UT_ProtocolHandler : TestKit
diff --git a/neo.UnitTests/UT_ProtocolHandlerMailbox.cs b/neo.UnitTests/Network/P2P/UT_ProtocolHandlerMailbox.cs
similarity index 98%
rename from neo.UnitTests/UT_ProtocolHandlerMailbox.cs
rename to neo.UnitTests/Network/P2P/UT_ProtocolHandlerMailbox.cs
index edd5a4191f..91caf65297 100644
--- a/neo.UnitTests/UT_ProtocolHandlerMailbox.cs
+++ b/neo.UnitTests/Network/P2P/UT_ProtocolHandlerMailbox.cs
@@ -1,18 +1,13 @@
-using Akka.TestKit;
-using Akka.TestKit.Xunit2;
+using Akka.TestKit.Xunit2;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System;
-using Moq;
-using Neo.Ledger;
-using Neo.Network.P2P.Payloads;
-using Neo.Network.P2P;
-using Akka.Configuration;
using Neo.IO;
-using System.Linq;
+using Neo.Network.P2P;
+using System;
using System.Collections.Generic;
+using System.Linq;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.Network.P2P
{
[TestClass]
public class UT_ProtocolHandlerMailbox : TestKit
diff --git a/neo.UnitTests/UT_RemoteNode.cs b/neo.UnitTests/Network/P2P/UT_RemoteNode.cs
similarity index 98%
rename from neo.UnitTests/UT_RemoteNode.cs
rename to neo.UnitTests/Network/P2P/UT_RemoteNode.cs
index 60d587ed13..03da2a3db8 100644
--- a/neo.UnitTests/UT_RemoteNode.cs
+++ b/neo.UnitTests/Network/P2P/UT_RemoteNode.cs
@@ -6,7 +6,7 @@
using Neo.Network.P2P.Capabilities;
using Neo.Network.P2P.Payloads;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.Network.P2P
{
[TestClass]
[NotReRunnable]
diff --git a/neo.UnitTests/UT_RemoteNodeMailbox.cs b/neo.UnitTests/Network/P2P/UT_RemoteNodeMailbox.cs
similarity index 94%
rename from neo.UnitTests/UT_RemoteNodeMailbox.cs
rename to neo.UnitTests/Network/P2P/UT_RemoteNodeMailbox.cs
index ff3e6e17d9..860012a31e 100644
--- a/neo.UnitTests/UT_RemoteNodeMailbox.cs
+++ b/neo.UnitTests/Network/P2P/UT_RemoteNodeMailbox.cs
@@ -1,11 +1,11 @@
-using System;
-using Akka.IO;
+using Akka.IO;
using Akka.TestKit.Xunit2;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Neo.Network.P2P;
+using System;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.Network.P2P
{
[TestClass]
[NotReRunnable]
diff --git a/neo.UnitTests/UT_TaskManagerMailbox.cs b/neo.UnitTests/Network/P2P/UT_TaskManagerMailbox.cs
similarity index 93%
rename from neo.UnitTests/UT_TaskManagerMailbox.cs
rename to neo.UnitTests/Network/P2P/UT_TaskManagerMailbox.cs
index 2ba4ff2d85..6d014cd9c7 100644
--- a/neo.UnitTests/UT_TaskManagerMailbox.cs
+++ b/neo.UnitTests/Network/P2P/UT_TaskManagerMailbox.cs
@@ -1,15 +1,11 @@
-using Akka.TestKit;
-using Akka.TestKit.Xunit2;
+using Akka.TestKit.Xunit2;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System;
-using Moq;
-using Neo.Ledger;
-using Neo.Network.P2P.Payloads;
using Neo.Network.P2P;
-using Akka.Configuration;
+using Neo.Network.P2P.Payloads;
+using System;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.Network.P2P
{
[TestClass]
public class UT_TaskManagerMailbox : TestKit
diff --git a/neo.UnitTests/UT_ConcatenatedIterator.cs b/neo.UnitTests/SmartContract/Iterators/UT_ConcatenatedIterator.cs
similarity index 97%
rename from neo.UnitTests/UT_ConcatenatedIterator.cs
rename to neo.UnitTests/SmartContract/Iterators/UT_ConcatenatedIterator.cs
index 7051f5f4f8..51db50ea31 100644
--- a/neo.UnitTests/UT_ConcatenatedIterator.cs
+++ b/neo.UnitTests/SmartContract/Iterators/UT_ConcatenatedIterator.cs
@@ -4,7 +4,7 @@
using Neo.VM.Types;
using System.Numerics;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.SmartContract.Iterators
{
[TestClass]
diff --git a/neo.UnitTests/UT_ContractManifest.cs b/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs
similarity index 99%
rename from neo.UnitTests/UT_ContractManifest.cs
rename to neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs
index 451791e9bd..bbb613c2be 100644
--- a/neo.UnitTests/UT_ContractManifest.cs
+++ b/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs
@@ -2,7 +2,7 @@
using Neo.Cryptography.ECC;
using Neo.SmartContract.Manifest;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.SmartContract.Manifest
{
[TestClass]
public class UT_ContractManifest
diff --git a/neo.UnitTests/UT_GasToken.cs b/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs
similarity index 99%
rename from neo.UnitTests/UT_GasToken.cs
rename to neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs
index 72a0c4d7ae..0ad69a7198 100644
--- a/neo.UnitTests/UT_GasToken.cs
+++ b/neo.UnitTests/SmartContract/Native/Tokens/UT_GasToken.cs
@@ -11,7 +11,7 @@
using System.Linq;
using System.Numerics;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.SmartContract.Native.Tokens
{
[TestClass]
public class UT_GasToken
diff --git a/neo.UnitTests/UT_NeoToken.cs b/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs
similarity index 99%
rename from neo.UnitTests/UT_NeoToken.cs
rename to neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs
index 3997573c0f..9a22bab3c4 100644
--- a/neo.UnitTests/UT_NeoToken.cs
+++ b/neo.UnitTests/SmartContract/Native/Tokens/UT_NeoToken.cs
@@ -15,7 +15,7 @@
using System.Linq;
using System.Numerics;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.SmartContract.Native.Tokens
{
[TestClass]
public class UT_NeoToken
diff --git a/neo.UnitTests/UT_Policy.cs b/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs
similarity index 94%
rename from neo.UnitTests/UT_Policy.cs
rename to neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs
index 09a09b20ba..0f353e37da 100644
--- a/neo.UnitTests/UT_Policy.cs
+++ b/neo.UnitTests/SmartContract/Native/UT_PolicyContract.cs
@@ -7,10 +7,10 @@
using Neo.UnitTests.Extensions;
using System.Linq;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.SmartContract.Native
{
[TestClass]
- public class UT_Policy
+ public class UT_PolicyContract
{
Store Store;
@@ -55,7 +55,7 @@ public void Check_SetMaxTransactionsPerBlock()
// Fake blockchain
snapshot.PersistingBlock = new Block() { Index = 1000, PrevHash = UInt256.Zero };
- snapshot.Blocks.Add(UInt256.Zero, new Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero });
+ snapshot.Blocks.Add(UInt256.Zero, new Neo.Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero });
NativeContract.Policy.Initialize(new ApplicationEngine(TriggerType.Application, null, snapshot, 0)).Should().BeTrue();
@@ -90,7 +90,7 @@ public void Check_SetFeePerByte()
// Fake blockchain
snapshot.PersistingBlock = new Block() { Index = 1000, PrevHash = UInt256.Zero };
- snapshot.Blocks.Add(UInt256.Zero, new Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero });
+ snapshot.Blocks.Add(UInt256.Zero, new Neo.Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero });
NativeContract.Policy.Initialize(new ApplicationEngine(TriggerType.Application, null, snapshot, 0)).Should().BeTrue();
@@ -125,7 +125,7 @@ public void Check_Block_UnblockAccount()
// Fake blockchain
snapshot.PersistingBlock = new Block() { Index = 1000, PrevHash = UInt256.Zero };
- snapshot.Blocks.Add(UInt256.Zero, new Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero });
+ snapshot.Blocks.Add(UInt256.Zero, new Neo.Ledger.TrimmedBlock() { NextConsensus = UInt160.Zero });
NativeContract.Policy.Initialize(new ApplicationEngine(TriggerType.Application, null, snapshot, 0)).Should().BeTrue();
diff --git a/neo.UnitTests/UT_InteropPrices.cs b/neo.UnitTests/SmartContract/UT_InteropPrices.cs
similarity index 99%
rename from neo.UnitTests/UT_InteropPrices.cs
rename to neo.UnitTests/SmartContract/UT_InteropPrices.cs
index 27c0a4cdc0..d6b9b8254b 100644
--- a/neo.UnitTests/UT_InteropPrices.cs
+++ b/neo.UnitTests/SmartContract/UT_InteropPrices.cs
@@ -3,7 +3,7 @@
using Neo.SmartContract;
using Neo.VM;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.SmartContract
{
[TestClass]
public class UT_InteropPrices
diff --git a/neo.UnitTests/UT_InteropService.cs b/neo.UnitTests/SmartContract/UT_InteropService.cs
similarity index 98%
rename from neo.UnitTests/UT_InteropService.cs
rename to neo.UnitTests/SmartContract/UT_InteropService.cs
index b5e3626109..023ba4c8e5 100644
--- a/neo.UnitTests/UT_InteropService.cs
+++ b/neo.UnitTests/SmartContract/UT_InteropService.cs
@@ -1,10 +1,9 @@
-using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Neo.SmartContract;
using Neo.SmartContract.Manifest;
using Neo.VM;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.SmartContract
{
[TestClass]
public class UT_InteropService
@@ -42,7 +41,7 @@ public void Runtime_GetNotifications_Test()
scriptHash2 = script.ToArray().ToScriptHash();
snapshot.Contracts.Delete(scriptHash2);
- snapshot.Contracts.Add(scriptHash2, new Ledger.ContractState()
+ snapshot.Contracts.Add(scriptHash2, new Neo.Ledger.ContractState()
{
Script = script.ToArray(),
Manifest = ContractManifest.CreateDefault(scriptHash2),
diff --git a/neo.UnitTests/UT_JsonSerializer.cs b/neo.UnitTests/SmartContract/UT_JsonSerializer.cs
similarity index 99%
rename from neo.UnitTests/UT_JsonSerializer.cs
rename to neo.UnitTests/SmartContract/UT_JsonSerializer.cs
index ed20b15392..adfbea8760 100644
--- a/neo.UnitTests/UT_JsonSerializer.cs
+++ b/neo.UnitTests/SmartContract/UT_JsonSerializer.cs
@@ -7,7 +7,7 @@
using System.Linq;
using System.Numerics;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.SmartContract
{
[TestClass]
public class UT_JsonSerializer
diff --git a/neo.UnitTests/UT_OpCodePrices.cs b/neo.UnitTests/SmartContract/UT_OpCodePrices.cs
similarity index 91%
rename from neo.UnitTests/UT_OpCodePrices.cs
rename to neo.UnitTests/SmartContract/UT_OpCodePrices.cs
index b53d745d6a..3174d8494b 100644
--- a/neo.UnitTests/UT_OpCodePrices.cs
+++ b/neo.UnitTests/SmartContract/UT_OpCodePrices.cs
@@ -3,7 +3,7 @@
using Neo.VM;
using System;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.SmartContract
{
[TestClass]
public class UT_OpCodePrices
diff --git a/neo.UnitTests/UT_Syscalls.cs b/neo.UnitTests/SmartContract/UT_Syscalls.cs
similarity index 98%
rename from neo.UnitTests/UT_Syscalls.cs
rename to neo.UnitTests/SmartContract/UT_Syscalls.cs
index c6642c4e88..c80899b8f8 100644
--- a/neo.UnitTests/UT_Syscalls.cs
+++ b/neo.UnitTests/SmartContract/UT_Syscalls.cs
@@ -4,7 +4,7 @@
using Neo.VM;
using System.Linq;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.SmartContract
{
[TestClass]
public class UT_Syscalls
diff --git a/neo.UnitTests/UT_BigDecimal.cs b/neo.UnitTests/UT_BigDecimal.cs
new file mode 100644
index 0000000000..3975d5503e
--- /dev/null
+++ b/neo.UnitTests/UT_BigDecimal.cs
@@ -0,0 +1,191 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System;
+using System.Numerics;
+
+namespace Neo.UnitTests
+{
+ [TestClass]
+ public class UT_BigDecimal
+ {
+ [TestMethod]
+ public void TestChangeDecimals()
+ {
+ BigDecimal originalValue = new BigDecimal(new BigInteger(12300), 5);
+ BigDecimal result1 = originalValue.ChangeDecimals(7);
+ result1.Value.Should().Be(new BigInteger(1230000));
+ result1.Decimals.Should().Be(7);
+ BigDecimal result2 = originalValue.ChangeDecimals(3);
+ result2.Value.Should().Be(new BigInteger(123));
+ result2.Decimals.Should().Be(3);
+ BigDecimal result3 = originalValue.ChangeDecimals(5);
+ result3.Value.Should().Be(originalValue.Value);
+ Action action = () => originalValue.ChangeDecimals(2);
+ action.ShouldThrow();
+ }
+
+ [TestMethod]
+ public void TestBigDecimalConstructor()
+ {
+ BigDecimal value = new BigDecimal(new BigInteger(45600), 7);
+ value.Value.Should().Be(new BigInteger(45600));
+ value.Decimals.Should().Be(7);
+ value = new BigDecimal(new BigInteger(0), 5);
+ value.Value.Should().Be(new BigInteger(0));
+ value.Decimals.Should().Be(5);
+ value = new BigDecimal(new BigInteger(-10), 0);
+ value.Value.Should().Be(new BigInteger(-10));
+ value.Decimals.Should().Be(0);
+ }
+
+ [TestMethod]
+ public void TestGetDecimals()
+ {
+ BigDecimal value = new BigDecimal(new BigInteger(45600), 7);
+ value.Sign.Should().Be(1);
+ value = new BigDecimal(new BigInteger(0), 5);
+ value.Sign.Should().Be(0);
+ value = new BigDecimal(new BigInteger(-10), 0);
+ value.Sign.Should().Be(-1);
+ }
+
+ [TestMethod]
+ public void TestGetSign()
+ {
+ BigDecimal value = new BigDecimal(new BigInteger(45600), 7);
+ value.Sign.Should().Be(1);
+ value = new BigDecimal(new BigInteger(0), 5);
+ value.Sign.Should().Be(0);
+ value = new BigDecimal(new BigInteger(-10), 0);
+ value.Sign.Should().Be(-1);
+ }
+
+ [TestMethod]
+ public void TestParse()
+ {
+ string s = "12345";
+ byte decimals = 0;
+ BigDecimal.Parse(s, decimals).Should().Be(new BigDecimal(new BigInteger(12345), 0));
+
+ s = "abcdEfg";
+ Action action = () => BigDecimal.Parse(s, decimals);
+ action.ShouldThrow();
+ }
+
+ [TestMethod]
+ public void TestToString()
+ {
+ BigDecimal value = new BigDecimal(new BigInteger(100000), 5);
+ value.ToString().Should().Be("1");
+ value = new BigDecimal(new BigInteger(123456), 5);
+ value.ToString().Should().Be("1.23456");
+ }
+
+ [TestMethod]
+ public void TestTryParse()
+ {
+ string s = "";
+ byte decimals = 0;
+ BigDecimal result;
+
+ s = "12345";
+ decimals = 0;
+ BigDecimal.TryParse(s, decimals, out result).Should().BeTrue();
+ result.Should().Be(new BigDecimal(new BigInteger(12345), 0));
+
+ s = "12345E-5";
+ decimals = 5;
+ BigDecimal.TryParse(s, decimals, out result).Should().BeTrue();
+ result.Should().Be(new BigDecimal(new BigInteger(12345), 5));
+
+ s = "abcdEfg";
+ BigDecimal.TryParse(s, decimals, out result).Should().BeFalse();
+ result.Should().Be(default(BigDecimal));
+
+ s = "123.45";
+ decimals = 2;
+ BigDecimal.TryParse(s, decimals, out result).Should().BeTrue();
+ result.Should().Be(new BigDecimal(new BigInteger(12345), 2));
+
+ s = "123.45E-5";
+ decimals = 7;
+ BigDecimal.TryParse(s, decimals, out result).Should().BeTrue();
+ result.Should().Be(new BigDecimal(new BigInteger(12345), 7));
+
+ s = "12345E-5";
+ decimals = 3;
+ BigDecimal.TryParse(s, decimals, out result).Should().BeFalse();
+ result.Should().Be(default(BigDecimal));
+
+ s = "1.2345";
+ decimals = 3;
+ BigDecimal.TryParse(s, decimals, out result).Should().BeFalse();
+ result.Should().Be(default(BigDecimal));
+
+ s = "1.2345E-5";
+ decimals = 3;
+ BigDecimal.TryParse(s, decimals, out result).Should().BeFalse();
+ result.Should().Be(default(BigDecimal));
+
+ s = "12345";
+ decimals = 3;
+ BigDecimal.TryParse(s, decimals, out result).Should().BeTrue();
+ result.Should().Be(new BigDecimal(new BigInteger(12345000), 3));
+
+ s = "12345E-2";
+ decimals = 3;
+ BigDecimal.TryParse(s, decimals, out result).Should().BeTrue();
+ result.Should().Be(new BigDecimal(new BigInteger(123450), 3));
+
+ s = "123.45";
+ decimals = 3;
+ BigDecimal.TryParse(s, decimals, out result).Should().BeTrue();
+ result.Should().Be(new BigDecimal(new BigInteger(123450), 3));
+
+ s = "123.45E3";
+ decimals = 3;
+ BigDecimal.TryParse(s, decimals, out result).Should().BeTrue();
+ result.Should().Be(new BigDecimal(new BigInteger(123450000), 3));
+
+ s = "a456bcdfg";
+ decimals = 0;
+ BigDecimal.TryParse(s, decimals, out result).Should().BeFalse();
+ result.Should().Be(default(BigDecimal));
+
+ s = "a456bce-5";
+ decimals = 5;
+ BigDecimal.TryParse(s, decimals, out result).Should().BeFalse();
+ result.Should().Be(default(BigDecimal));
+
+ s = "a4.56bcd";
+ decimals = 5;
+ BigDecimal.TryParse(s, decimals, out result).Should().BeFalse();
+ result.Should().Be(default(BigDecimal));
+
+ s = "a4.56bce3";
+ decimals = 2;
+ BigDecimal.TryParse(s, decimals, out result).Should().BeFalse();
+ result.Should().Be(default(BigDecimal));
+
+ s = "a456bcd";
+ decimals = 2;
+ BigDecimal.TryParse(s, decimals, out result).Should().BeFalse();
+ result.Should().Be(default(BigDecimal));
+
+ s = "a456bcdE3";
+ decimals = 2;
+ BigDecimal.TryParse(s, decimals, out result).Should().BeFalse();
+ result.Should().Be(default(BigDecimal));
+
+ s = "a456b.cd";
+ decimals = 5;
+ BigDecimal.TryParse(s, decimals, out result).Should().BeFalse();
+ result.Should().Be(default(BigDecimal));
+
+ s = "a456b.cdE3";
+ decimals = 5;
+ BigDecimal.TryParse(s, decimals, out result).Should().BeFalse();
+ result.Should().Be(default(BigDecimal));
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/UT_FifoSet.cs b/neo.UnitTests/UT_FifoSet.cs
deleted file mode 100644
index ff5ccf9c27..0000000000
--- a/neo.UnitTests/UT_FifoSet.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using Neo.IO.Caching;
-using System.Linq;
-
-namespace Neo.UnitTests
-{
- [TestClass]
- public class UT_FifoSet
- {
- [TestMethod]
- public void FifoSetTest()
- {
- var a = UInt256.Zero;
- var b = new UInt256();
- var c = new UInt256(new byte[32] {
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01
- });
-
- var set = new FIFOSet(3);
-
- Assert.IsTrue(set.Add(a));
- Assert.IsFalse(set.Add(a));
- Assert.IsFalse(set.Add(b));
- Assert.IsTrue(set.Add(c));
-
- CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { a, c });
-
- var d = new UInt256(new byte[32] {
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x02
- });
-
- // Testing Fifo max size
- Assert.IsTrue(set.Add(d));
- CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { a, c, d });
-
- var e = new UInt256(new byte[32] {
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x03
- });
-
- Assert.IsTrue(set.Add(e));
- Assert.IsFalse(set.Add(e));
- CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { c, d, e });
- }
- }
-}
diff --git a/neo.UnitTests/UT_ProtocolSettings.cs b/neo.UnitTests/UT_ProtocolSettings.cs
index 92cabae19b..053c5d7e37 100644
--- a/neo.UnitTests/UT_ProtocolSettings.cs
+++ b/neo.UnitTests/UT_ProtocolSettings.cs
@@ -93,4 +93,4 @@ public void Cant_initialize_ProtocolSettings_twice()
ProtocolSettings.Default.Magic.Should().Be(expectedMagic);
}
}
-}
+}
\ No newline at end of file
diff --git a/neo.UnitTests/VM/UT_Helper.cs b/neo.UnitTests/VM/UT_Helper.cs
new file mode 100644
index 0000000000..7fc0088632
--- /dev/null
+++ b/neo.UnitTests/VM/UT_Helper.cs
@@ -0,0 +1,82 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.SmartContract;
+using Neo.VM;
+using System;
+using System.Text;
+
+namespace Neo.UnitTests.IO
+{
+ [TestClass]
+ public class UT_Helper
+ {
+ [TestMethod]
+ public void TestEmit()
+ {
+ ScriptBuilder sb = new ScriptBuilder();
+ sb.Emit(new OpCode[] { OpCode.PUSH0 });
+ Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x00 }), Encoding.Default.GetString(sb.ToArray()));
+ }
+
+ [TestMethod]
+ public void TestEmitAppCall1()
+ {
+ //format:(byte)0x00+(byte)OpCode.NEWARRAY+(string)operation+(Uint160)scriptHash+(uint)InteropService.System_Contract_Call
+ ScriptBuilder sb = new ScriptBuilder();
+ sb.EmitAppCall(UInt160.Zero, "AAAAA");
+ byte[] tempArray = new byte[34];
+ tempArray[0] = 0x00;//0
+ tempArray[1] = 0xC5;//OpCode.NEWARRAY
+ tempArray[2] = 5;//operation.Length
+ Array.Copy(Encoding.UTF8.GetBytes("AAAAA"),0, tempArray,3, 5);//operation.data
+ tempArray[8] = 0x14;//scriptHash.Length
+ Array.Copy(UInt160.Zero.ToArray(), 0, tempArray, 9, 20);//operation.data
+ uint api = InteropService.System_Contract_Call;
+ tempArray[29] = 0x68;//OpCode.SYSCALL
+ Array.Copy(BitConverter.GetBytes(api), 0, tempArray, 30, 4);//api.data
+ byte[] resultArray = sb.ToArray();
+ Assert.AreEqual(Encoding.Default.GetString(tempArray), Encoding.Default.GetString(resultArray));
+ }
+
+ [TestMethod]
+ public void TestEmitAppCall2()
+ {
+ //format:(ContractParameter[])ContractParameter+(byte)OpCode.PACK+(string)operation+(Uint160)scriptHash+(uint)InteropService.System_Contract_Call
+ ScriptBuilder sb = new ScriptBuilder();
+ sb.EmitAppCall(UInt160.Zero, "AAAAA",new ContractParameter[] {new ContractParameter(ContractParameterType.Integer)});
+ byte[] tempArray = new byte[35];
+ tempArray[0] = 0x00;//0
+ tempArray[1] = 0x51;//ContractParameter.Length
+ tempArray[2] = 0xC1;//OpCode.PACK
+ tempArray[3] = 0x05;//operation.Length
+ Array.Copy(Encoding.UTF8.GetBytes("AAAAA"), 0, tempArray, 4, 5);//operation.data
+ tempArray[9] = 0x14;//scriptHash.Length
+ Array.Copy(UInt160.Zero.ToArray(), 0, tempArray, 10, 20);//operation.data
+ uint api = InteropService.System_Contract_Call;
+ tempArray[30] = 0x68;//OpCode.SYSCALL
+ Array.Copy(BitConverter.GetBytes(api), 0, tempArray, 31, 4);//api.data
+ byte[] resultArray = sb.ToArray();
+ Assert.AreEqual(Encoding.Default.GetString(tempArray), Encoding.Default.GetString(resultArray));
+ }
+
+ [TestMethod]
+ public void TestEmitAppCall3()
+ {
+ //format:(object[])args+(byte)OpCode.PACK+(string)operation+(Uint160)scriptHash+(uint)InteropService.System_Contract_Call
+ ScriptBuilder sb = new ScriptBuilder();
+ sb.EmitAppCall(UInt160.Zero, "AAAAA", true);
+ byte[] tempArray = new byte[35];
+ tempArray[0] = 0x51;//arg
+ tempArray[1] = 0x51;//args.Length
+ tempArray[2] = 0xC1;//OpCode.PACK
+ tempArray[3] = 0x05;//operation.Length
+ Array.Copy(Encoding.UTF8.GetBytes("AAAAA"), 0, tempArray, 4, 5);//operation.data
+ tempArray[9] = 0x14;//scriptHash.Length
+ Array.Copy(UInt160.Zero.ToArray(), 0, tempArray, 10, 20);//operation.data
+ uint api = InteropService.System_Contract_Call;
+ tempArray[30] = 0x68;//OpCode.SYSCALL
+ Array.Copy(BitConverter.GetBytes(api), 0, tempArray, 31, 4);//api.data
+ byte[] resultArray = sb.ToArray();
+ Assert.AreEqual(Encoding.Default.GetString(tempArray), Encoding.Default.GetString(resultArray));
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/UT_NEP6Wallet.cs b/neo.UnitTests/Wallets/NEP6/UT_NEP6Wallet.cs
similarity index 97%
rename from neo.UnitTests/UT_NEP6Wallet.cs
rename to neo.UnitTests/Wallets/NEP6/UT_NEP6Wallet.cs
index 187e487030..9bac3de4ac 100644
--- a/neo.UnitTests/UT_NEP6Wallet.cs
+++ b/neo.UnitTests/Wallets/NEP6/UT_NEP6Wallet.cs
@@ -4,7 +4,7 @@
using Neo.Wallets.NEP6;
using System;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.Wallets.NEP6
{
[TestClass]
public class UT_NEP6Wallet
diff --git a/neo.UnitTests/UT_ScryptParameters.cs b/neo.UnitTests/Wallets/NEP6/UT_ScryptParameters.cs
similarity index 97%
rename from neo.UnitTests/UT_ScryptParameters.cs
rename to neo.UnitTests/Wallets/NEP6/UT_ScryptParameters.cs
index e0021f0eb0..3d4550a48d 100644
--- a/neo.UnitTests/UT_ScryptParameters.cs
+++ b/neo.UnitTests/Wallets/NEP6/UT_ScryptParameters.cs
@@ -3,7 +3,7 @@
using Neo.IO.Json;
using Neo.Wallets.NEP6;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.Wallets.NEP6
{
[TestClass]
public class UT_ScryptParameters
diff --git a/neo.UnitTests/Wallets/SQLite/UT_Account.cs b/neo.UnitTests/Wallets/SQLite/UT_Account.cs
new file mode 100644
index 0000000000..c60e90fd10
--- /dev/null
+++ b/neo.UnitTests/Wallets/SQLite/UT_Account.cs
@@ -0,0 +1,37 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Wallets.SQLite;
+using System.Text;
+
+namespace Neo.UnitTests.Wallets.SQLite
+{
+ [TestClass]
+ public class UT_Account
+ {
+ [TestMethod]
+ public void TestGenerator()
+ {
+ Account account = new Account();
+ Assert.IsNotNull(account);
+ }
+
+ [TestMethod]
+ public void TestSetAndGetPrivateKeyEncrypted()
+ {
+ Account account = new Account
+ {
+ PrivateKeyEncrypted = new byte[] { 0x01 }
+ };
+ Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01 }), Encoding.Default.GetString(account.PrivateKeyEncrypted));
+ }
+
+ [TestMethod]
+ public void TestSetAndGetPublicKeyHash()
+ {
+ Account account = new Account
+ {
+ PublicKeyHash = new byte[] { 0x01 }
+ };
+ Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01 }), Encoding.Default.GetString(account.PublicKeyHash));
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/Wallets/SQLite/UT_Address.cs b/neo.UnitTests/Wallets/SQLite/UT_Address.cs
new file mode 100644
index 0000000000..4d3e2d6717
--- /dev/null
+++ b/neo.UnitTests/Wallets/SQLite/UT_Address.cs
@@ -0,0 +1,27 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Wallets.SQLite;
+using System.Text;
+
+namespace Neo.UnitTests.Wallets.SQLite
+{
+ [TestClass]
+ public class UT_Address
+ {
+ [TestMethod]
+ public void TestGenerator()
+ {
+ Address address = new Address();
+ Assert.IsNotNull(address);
+ }
+
+ [TestMethod]
+ public void TestSetAndGetScriptHash()
+ {
+ Address address = new Address
+ {
+ ScriptHash = new byte[] { 0x01 }
+ };
+ Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01 }), Encoding.Default.GetString(address.ScriptHash));
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/Wallets/SQLite/UT_Contract.cs b/neo.UnitTests/Wallets/SQLite/UT_Contract.cs
new file mode 100644
index 0000000000..52c197a778
--- /dev/null
+++ b/neo.UnitTests/Wallets/SQLite/UT_Contract.cs
@@ -0,0 +1,65 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Wallets.SQLite;
+using System.Text;
+
+namespace Neo.UnitTests.Wallets.SQLite
+{
+ [TestClass]
+ public class UT_Contract
+ {
+ [TestMethod]
+ public void TestGenerator()
+ {
+ Contract contract = new Contract();
+ Assert.IsNotNull(contract);
+ }
+
+ [TestMethod]
+ public void TestSetAndGetRawData()
+ {
+ Contract contract = new Contract
+ {
+ RawData = new byte[] { 0x01 }
+ };
+ Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01 }), Encoding.Default.GetString(contract.RawData));
+ }
+
+ [TestMethod]
+ public void TestSetAndGetScriptHash()
+ {
+ Contract contract = new Contract
+ {
+ ScriptHash = new byte[] { 0x01 }
+ };
+ Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01 }), Encoding.Default.GetString(contract.ScriptHash));
+ }
+
+ [TestMethod]
+ public void TestSetAndGetPublicKeyHash()
+ {
+ Contract contract = new Contract
+ {
+ PublicKeyHash = new byte[] { 0x01 }
+ };
+ Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01 }), Encoding.Default.GetString(contract.PublicKeyHash));
+ }
+
+ [TestMethod]
+ public void TestSetAndGetAccount()
+ {
+ Contract contract = new Contract();
+ Account account = new Account();
+ contract.Account = account;
+ Assert.AreEqual(account, contract.Account);
+ }
+
+ [TestMethod]
+ public void TestSetAndGetAddress()
+ {
+ Contract contract = new Contract();
+ Address address = new Address();
+ contract.Address = address;
+ Assert.AreEqual(address, contract.Address);
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/Wallets/SQLite/UT_Key.cs b/neo.UnitTests/Wallets/SQLite/UT_Key.cs
new file mode 100644
index 0000000000..e09896b72c
--- /dev/null
+++ b/neo.UnitTests/Wallets/SQLite/UT_Key.cs
@@ -0,0 +1,37 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Wallets.SQLite;
+using System.Text;
+
+namespace Neo.UnitTests.Wallets.SQLite
+{
+ [TestClass]
+ public class UT_Key
+ {
+ [TestMethod]
+ public void TestGenerator()
+ {
+ Key key = new Key();
+ Assert.IsNotNull(key);
+ }
+
+ [TestMethod]
+ public void TestSetAndGetName()
+ {
+ Key key = new Key
+ {
+ Name = "AAA"
+ };
+ Assert.AreEqual("AAA", key.Name);
+ }
+
+ [TestMethod]
+ public void TestSetAndGetValue()
+ {
+ Key key = new Key
+ {
+ Value = new byte[] { 0x01 }
+ };
+ Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0x01 }), Encoding.Default.GetString(key.Value));
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/UT_AssetDescription.cs b/neo.UnitTests/Wallets/UT_AssetDescriptor.cs
similarity index 78%
rename from neo.UnitTests/UT_AssetDescription.cs
rename to neo.UnitTests/Wallets/UT_AssetDescriptor.cs
index 175814b91f..6630a8450b 100644
--- a/neo.UnitTests/UT_AssetDescription.cs
+++ b/neo.UnitTests/Wallets/UT_AssetDescriptor.cs
@@ -3,10 +3,10 @@
using Neo.Persistence;
using Neo.SmartContract.Native;
-namespace Neo.UnitTests
+namespace Neo.UnitTests.Wallets
{
[TestClass]
- public class UT_AssetDescription
+ public class UT_AssetDescriptor
{
private Store Store;
@@ -20,7 +20,7 @@ public void TestSetup()
[TestMethod]
public void Check_GAS()
{
- var descriptor = new Wallets.AssetDescriptor(NativeContract.GAS.Hash);
+ var descriptor = new Neo.Wallets.AssetDescriptor(NativeContract.GAS.Hash);
descriptor.AssetId.Should().Be(NativeContract.GAS.Hash);
descriptor.AssetName.Should().Be("GAS");
descriptor.Decimals.Should().Be(8);
@@ -29,7 +29,7 @@ public void Check_GAS()
[TestMethod]
public void Check_NEO()
{
- var descriptor = new Wallets.AssetDescriptor(NativeContract.NEO.Hash);
+ var descriptor = new Neo.Wallets.AssetDescriptor(NativeContract.NEO.Hash);
descriptor.AssetId.Should().Be(NativeContract.NEO.Hash);
descriptor.AssetName.Should().Be("NEO");
descriptor.Decimals.Should().Be(0);
diff --git a/neo.UnitTests/neo.UnitTests.csproj b/neo.UnitTests/neo.UnitTests.csproj
index 9f57166c69..5d967c0845 100644
--- a/neo.UnitTests/neo.UnitTests.csproj
+++ b/neo.UnitTests/neo.UnitTests.csproj
@@ -31,5 +31,4 @@
-
diff --git a/neo/Ledger/MemoryPool.cs b/neo/Ledger/MemoryPool.cs
index 912ea69c73..739085f5b6 100644
--- a/neo/Ledger/MemoryPool.cs
+++ b/neo/Ledger/MemoryPool.cs
@@ -361,7 +361,7 @@ internal void UpdatePoolForBlockPersisted(Block block, Snapshot snapshot)
if (policyChanged)
{
foreach (PoolItem item in _unverifiedSortedTransactions.Reverse())
- if(item.Tx.FeePerByte >= _feePerByte)
+ if (item.Tx.FeePerByte >= _feePerByte)
_system.Blockchain.Tell(item.Tx, ActorRefs.NoSender);
_unverifiedTransactions.Clear();
_unverifiedSortedTransactions.Clear();
From c47f2e329697caf10ab69841a8c030017b034676 Mon Sep 17 00:00:00 2001
From: Shargon
Date: Mon, 29 Jul 2019 07:24:58 +0200
Subject: [PATCH 054/305] Script header (#903)
* Script header
* Script header draft
* Clean files
* Typo
* Rename class and magic header
* Clean hash
* UT
* Erik's suggestions
* Change name
* Typo
* Check magic
* 64 to 32
* Nef file only for neo-cli
* Real Checksum
* Clean
* Clean again
* Remove code
* Update neo/SmartContract/NefFile.cs
Co-Authored-By: Igor Machado Coelho
* Enum to const
* Remove unnecessary change
* Apply Erik's suggestions
---
neo.UnitTests/UT_NefFile.cs | 75 ++++++++++++++++++++
neo/SmartContract/NefFile.cs | 129 +++++++++++++++++++++++++++++++++++
2 files changed, 204 insertions(+)
create mode 100644 neo.UnitTests/UT_NefFile.cs
create mode 100644 neo/SmartContract/NefFile.cs
diff --git a/neo.UnitTests/UT_NefFile.cs b/neo.UnitTests/UT_NefFile.cs
new file mode 100644
index 0000000000..ba14496a27
--- /dev/null
+++ b/neo.UnitTests/UT_NefFile.cs
@@ -0,0 +1,75 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Cryptography;
+using Neo.IO;
+using Neo.SmartContract;
+using System;
+
+namespace Neo.UnitTests
+{
+ [TestClass]
+ public class UT_NefFile
+ {
+ [TestMethod]
+ public void ParseTest()
+ {
+ var file = new NefFile()
+ {
+ Compiler = "".PadLeft(32, ' '),
+ Version = new Version(1, 2, 3, 4),
+ Script = new byte[] { 0x01, 0x02, 0x03 }
+ };
+
+ file.ScriptHash = file.Script.ToScriptHash();
+ file.CheckSum = NefFile.ComputeChecksum(file);
+
+ var data = file.ToArray();
+ file = data.AsSerializable();
+
+ Assert.AreEqual("".PadLeft(32, ' '), file.Compiler);
+ Assert.AreEqual(new Version(1, 2, 3, 4), file.Version);
+ Assert.AreEqual(file.Script.ToScriptHash(), file.ScriptHash);
+ CollectionAssert.AreEqual(new byte[] { 0x01, 0x02, 0x03 }, file.Script);
+ }
+
+ [TestMethod]
+ public void LimitTest()
+ {
+ var file = new NefFile()
+ {
+ Compiler = "".PadLeft(byte.MaxValue, ' '),
+ Version = new Version(1, 2, 3, 4),
+ Script = new byte[1024 * 1024],
+ ScriptHash = new byte[1024 * 1024].ToScriptHash(),
+ CheckSum = 0
+ };
+
+ // Wrong compiler
+
+ Assert.ThrowsException(() => file.ToArray());
+
+ // Wrong script
+
+ file.Compiler = "";
+ file.Script = new byte[(1024 * 1024) + 1];
+ file.ScriptHash = file.Script.ToScriptHash();
+ var data = file.ToArray();
+
+ Assert.ThrowsException(() => data.AsSerializable());
+
+ // Wrong script hash
+
+ file.Script = new byte[1024 * 1024];
+ data = file.ToArray();
+
+ Assert.ThrowsException(() => data.AsSerializable());
+
+ // Wrong checksum
+
+ file.Script = new byte[1024];
+ data = file.ToArray();
+ file.CheckSum = NefFile.ComputeChecksum(file) + 1;
+
+ Assert.ThrowsException(() => data.AsSerializable());
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo/SmartContract/NefFile.cs b/neo/SmartContract/NefFile.cs
new file mode 100644
index 0000000000..52507eda08
--- /dev/null
+++ b/neo/SmartContract/NefFile.cs
@@ -0,0 +1,129 @@
+using Neo.Cryptography;
+using Neo.IO;
+using System;
+using System.IO;
+
+namespace Neo.SmartContract
+{
+ ///
+ /// +------------+-----------+------------------------------------------------------------+
+ /// | Field | Length | Comment |
+ /// +------------+-----------+------------------------------------------------------------+
+ /// | Magic | 4 bytes | Magic header |
+ /// | Compiler | 32 bytes | Compiler used |
+ /// | Version | 16 bytes | Compiler version (Mayor, Minor, Build, Version) |
+ /// | ScriptHash | 20 bytes | ScriptHash for the script |
+ /// +------------+-----------+------------------------------------------------------------+
+ /// | Checksum | 4 bytes | Sha256 of the header (CRC) |
+ /// +------------+-----------+------------------------------------------------------------+
+ /// | Script | Var bytes | Var bytes for the payload |
+ /// +------------+-----------+------------------------------------------------------------+
+ ///
+ public class NefFile : ISerializable
+ {
+ ///
+ /// NEO Executable Format 3 (NEF3)
+ ///
+ private const uint Magic = 0x3346454E;
+
+ ///
+ /// Compiler
+ ///
+ public string Compiler { get; set; }
+
+ ///
+ /// Version
+ ///
+ public Version Version { get; set; }
+
+ ///
+ /// Script Hash
+ ///
+ public UInt160 ScriptHash { get; set; }
+
+ ///
+ /// Checksum
+ ///
+ public uint CheckSum { get; set; }
+
+ ///
+ /// Script
+ ///
+ public byte[] Script { get; set; }
+
+ private const int HeaderSize =
+ sizeof(uint) + // Magic
+ 32 + // Compiler
+ (sizeof(int) * 4) + // Version
+ UInt160.Length + // ScriptHash
+ sizeof(uint); // Checksum
+
+ public int Size =>
+ HeaderSize + // Header
+ Script.GetVarSize(); // Script
+
+ public void Serialize(BinaryWriter writer)
+ {
+ writer.Write(Magic);
+ writer.WriteFixedString(Compiler, 32);
+
+ // Version
+ writer.Write(Version.Major);
+ writer.Write(Version.Minor);
+ writer.Write(Version.Build);
+ writer.Write(Version.Revision);
+
+ writer.Write(ScriptHash);
+ writer.Write(CheckSum);
+ writer.WriteVarBytes(Script ?? new byte[0]);
+ }
+
+ public void Deserialize(BinaryReader reader)
+ {
+ if (reader.ReadUInt32() != Magic)
+ {
+ throw new FormatException("Wrong magic");
+ }
+
+ Compiler = reader.ReadFixedString(32);
+ Version = new Version(reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32());
+ ScriptHash = reader.ReadSerializable();
+ CheckSum = reader.ReadUInt32();
+
+ if (CheckSum != ComputeChecksum(this))
+ {
+ throw new FormatException("CRC verification fail");
+ }
+
+ Script = reader.ReadVarBytes(1024 * 1024);
+
+ if (Script.ToScriptHash() != ScriptHash)
+ {
+ throw new FormatException("ScriptHash is different");
+ }
+ }
+
+ ///
+ /// Compute checksum for a file
+ ///
+ /// File
+ /// Return checksum
+ public static uint ComputeChecksum(NefFile file)
+ {
+ using (var ms = new MemoryStream())
+ using (var wr = new BinaryWriter(ms))
+ {
+ file.Serialize(wr);
+ wr.Flush();
+
+ // Read header without CRC
+
+ var buffer = new byte[HeaderSize - sizeof(uint)];
+ ms.Seek(0, SeekOrigin.Begin);
+ ms.Read(buffer, 0, buffer.Length);
+
+ return BitConverter.ToUInt32(buffer.Sha256(), 0);
+ }
+ }
+ }
+}
From 1554050943986e80fe32cff767bf3b7a13be438a Mon Sep 17 00:00:00 2001
From: Charis Zhao
Date: Mon, 29 Jul 2019 23:41:14 +0800
Subject: [PATCH 055/305] Unit Tests of Crypto Module (#962)
* testDemo
* add dll lib
* add dbsnapshot dispose
* test get blocks in levelDBStore
* add levelDBStore test funcs
* fix levelDBStore funcs
* add DbCache addInternal
* differ db path
* space
* fix delete internal test
* add test getInternal tryGetInternal move libleveldb.dll
* add dbCache method test
* add store test
* add cache unit tests
* add cache unit tests
* up readonly max_capacity
* fix leveldbexception
* fix comment on UT_Cache
* format
* fix multithread test problem
* up cache
* update travis config
* update travis.yml
* test DbMetaDataCache
* fix db directory
* format and update travis for maxos
* fix mac env travis
* 2019/7/12 10:34
* 2019/7/12 11:01
* remove commented line
* test BigDecimal
* fix format and csproj
* rm coverage.opencover.xml
* update method name
* add UT_P_Helper
* modify UT_P_Helper
* modify UT_P_helper
* Clean ut
* test Base58 & BloomFilter
* Update UT_Cache.cs
* Correct Typo
* test JsonArray
* update namespace
* update namespace
* update format
* update format
* organise folder structure
* add UT_JString
* test JBoolean JNumber & JObject
* 2019/7/16 10:30
add some test case for UInt32Wrapper and SerializableWrapper
* fix timestamp
* test ECDsa and Crypto
* test OrderedDictionary & complete IO.Json tests
* 2019/7/16 17:33
add some test case of SQLiteWallet
* test FIFOSet
* add CloneCache and DataCache unit tests
* fix namespace
* add UT_Cryptography_Helper
* format UT_CloneCache and UT_DataCache
* add UT_DataCache.GetAndChange unit test
* update namespace
* remove comment code
* delete Persistence part
* 2019/7/19 11:07
add some test case for Helper in VM
* Fix Base58 Test
* 2019/7/19 11:33
change some format
* update IOHelper exception assert
* 2019/7/19 14:22
change format
* format IOHelper
* review IO.Wrapper
* review Wallets.SQLite UT
* Test ECFieldElement ECPoint
* refactor package
* format ECDsa
* update namespace
* Code fix
* review cache
* modify UT_JString
* fomat
* using Actin replace with try-catch
* add UT_CloneMetaCache and UT_MetaDataCache
* update namespace
* format UT_DataCache.cs
* Code Fix
* format
* update csproj
* Code fix for UT_ECFieldElement and UT_ECPoint
* Code fix
* format
* update travis
* delete deleteFiles
* fix path and comment
* update travis
* delete test ToTimeStamp
* format UT_*Cache
* update format
* fomat
* use hex extensions in Cryptography_Helper
* remove reflection
* optimization of UT_DataCache
* update namespace
* modify TestSha256
* update UT in crypto module
* Rename UT_Scrypt.cs to UT_SCrypt.cs
* format
* update UT_Murmur3
---
neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs | 42 ++++++++++
neo.UnitTests/Cryptography/UT_MerkleTree.cs | 80 +++++++++++++++++++
.../Cryptography/UT_MerkleTreeNode.cs | 51 ++++++++++++
neo.UnitTests/Cryptography/UT_Murmur3.cs | 24 ++++++
.../{UT_Scrypt.cs => UT_SCrypt.cs} | 3 +-
5 files changed, 198 insertions(+), 2 deletions(-)
create mode 100644 neo.UnitTests/Cryptography/UT_MerkleTree.cs
create mode 100644 neo.UnitTests/Cryptography/UT_MerkleTreeNode.cs
create mode 100644 neo.UnitTests/Cryptography/UT_Murmur3.cs
rename neo.UnitTests/Cryptography/{UT_Scrypt.cs => UT_SCrypt.cs} (93%)
diff --git a/neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs b/neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs
index 9de751e851..cc6fa87d5a 100644
--- a/neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs
+++ b/neo.UnitTests/Cryptography/ECC/UT_ECPoint.cs
@@ -56,6 +56,10 @@ public void TestECPointConstructor()
point.X.Should().Be(X);
point.Y.Should().Be(Y);
point.Curve.Should().Be(ECCurve.Secp256k1);
+ Action action = () => new ECPoint(X, null, ECCurve.Secp256k1);
+ action.ShouldThrow();
+ action = () => new ECPoint(null, Y, ECCurve.Secp256k1);
+ action.ShouldThrow();
}
[TestMethod]
@@ -145,6 +149,30 @@ public void TestEquals()
point1.Equals(point3).Should().BeFalse();
}
+ [TestMethod]
+ public void TestEqualsObject()
+ {
+ object point = ECCurve.Secp256k1.G;
+ point.Equals(point).Should().BeTrue();
+ point.Equals(null).Should().BeFalse();
+ point.Equals(1u).Should().BeFalse();
+
+ point = new ECPoint(null, null, ECCurve.Secp256k1);
+ point.Equals(new ECPoint(null, null, ECCurve.Secp256r1)).Should().BeTrue();
+ point.Equals(ECCurve.Secp256r1.G).Should().BeFalse();
+ ECCurve.Secp256r1.G.Equals(point).Should().BeFalse();
+
+ ECFieldElement X1 = new ECFieldElement(new BigInteger(100), ECCurve.Secp256k1);
+ ECFieldElement Y1 = new ECFieldElement(new BigInteger(200), ECCurve.Secp256k1);
+ ECFieldElement X2 = new ECFieldElement(new BigInteger(300), ECCurve.Secp256k1);
+ ECFieldElement Y2 = new ECFieldElement(new BigInteger(400), ECCurve.Secp256k1);
+ object point1 = new ECPoint(X1, Y1, ECCurve.Secp256k1);
+ object point2 = new ECPoint(X2, Y1, ECCurve.Secp256k1);
+ object point3 = new ECPoint(X1, Y2, ECCurve.Secp256k1);
+ point1.Equals(point2).Should().BeFalse();
+ point1.Equals(point3).Should().BeFalse();
+ }
+
[TestMethod]
public void TestFromBytes()
{
@@ -176,6 +204,13 @@ public void TestFromBytes()
ECCurve.Secp256k1), ECCurve.Secp256k1));
}
+ [TestMethod]
+ public void TestGetSize()
+ {
+ ECCurve.Secp256k1.G.Size.Should().Be(33);
+ ECCurve.Secp256k1.Infinity.Size.Should().Be(1);
+ }
+
[TestMethod]
public void TestMultiply()
{
@@ -279,6 +314,13 @@ public void TestOpMultiply()
new ECFieldElement(BigInteger.Parse("29236048674093813394523910922582374630829081423043497254162533033164154049666"), ECCurve.Secp256k1), ECCurve.Secp256k1));
}
+ [TestMethod]
+ public void TestOpSubtraction()
+ {
+ (ECCurve.Secp256k1.G - ECCurve.Secp256k1.Infinity).Should().Be(ECCurve.Secp256k1.G);
+ (ECCurve.Secp256k1.G - ECCurve.Secp256k1.G).Should().Be(ECCurve.Secp256k1.Infinity);
+ }
+
[TestMethod]
public void TestOpUnaryNegation()
{
diff --git a/neo.UnitTests/Cryptography/UT_MerkleTree.cs b/neo.UnitTests/Cryptography/UT_MerkleTree.cs
new file mode 100644
index 0000000000..3edf6b4a8b
--- /dev/null
+++ b/neo.UnitTests/Cryptography/UT_MerkleTree.cs
@@ -0,0 +1,80 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Cryptography;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Neo.UnitTests.Cryptography
+{
+ [TestClass]
+ public class UT_MerkleTree
+ {
+ public UInt256 GetByteArrayHash(byte[] byteArray)
+ {
+ if(byteArray == null || byteArray.Length == 0) throw new ArgumentNullException();
+ var hash = new UInt256(Crypto.Default.Hash256(byteArray));
+ return hash;
+ }
+
+ [TestMethod]
+ public void TestBuildAndDepthFirstSearch()
+ {
+ IReadOnlyList hashNull = new UInt256[] { };
+ Action action = () => new MerkleTree(hashNull);
+ action.ShouldThrow();
+
+ byte[] array1 = { 0x01 };
+ var hash1 = GetByteArrayHash(array1);
+
+ byte[] array2 = { 0x02 };
+ var hash2 = GetByteArrayHash(array2);
+
+ byte[] array3 = { 0x03 };
+ var hash3 = GetByteArrayHash(array3);
+
+ IReadOnlyList hashes = new UInt256[] { hash1, hash2, hash3 };
+ MerkleTree tree = new MerkleTree(hashes);
+ var hashArray = tree.ToHashArray();
+ hashArray[0].Should().Be(hash1);
+ hashArray[1].Should().Be(hash2);
+ hashArray[2].Should().Be(hash3);
+ hashArray[3].Should().Be(hash3);
+
+ var rootHash = MerkleTree.ComputeRoot(hashes);
+ var hash4 = Crypto.Default.Hash256(hash1.ToArray().Concat(hash2.ToArray()).ToArray());
+ var hash5 = Crypto.Default.Hash256(hash3.ToArray().Concat(hash3.ToArray()).ToArray());
+ var result = new UInt256(Crypto.Default.Hash256(hash4.ToArray().Concat(hash5.ToArray()).ToArray()));
+ rootHash.Should().Be(result);
+ }
+
+ [TestMethod]
+ public void TestTrim()
+ {
+ byte[] array1 = { 0x01 };
+ var hash1 = GetByteArrayHash(array1);
+
+ byte[] array2 = { 0x02 };
+ var hash2 = GetByteArrayHash(array2);
+
+ byte[] array3 = { 0x03 };
+ var hash3 = GetByteArrayHash(array3);
+
+ IReadOnlyList hashes = new UInt256[] { hash1, hash2, hash3 };
+ MerkleTree tree = new MerkleTree(hashes);
+
+ bool[] boolArray = { false, false, false };
+ BitArray bitArray = new BitArray(boolArray);
+ tree.Trim(bitArray);
+ var hashArray = tree.ToHashArray();
+
+ hashArray.Length.Should().Be(1);
+ var rootHash = MerkleTree.ComputeRoot(hashes);
+ var hash4 = Crypto.Default.Hash256(hash1.ToArray().Concat(hash2.ToArray()).ToArray());
+ var hash5 = Crypto.Default.Hash256(hash3.ToArray().Concat(hash3.ToArray()).ToArray());
+ var result = new UInt256(Crypto.Default.Hash256(hash4.ToArray().Concat(hash5.ToArray()).ToArray()));
+ hashArray[0].Should().Be(result);
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/Cryptography/UT_MerkleTreeNode.cs b/neo.UnitTests/Cryptography/UT_MerkleTreeNode.cs
new file mode 100644
index 0000000000..48fd05745d
--- /dev/null
+++ b/neo.UnitTests/Cryptography/UT_MerkleTreeNode.cs
@@ -0,0 +1,51 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Cryptography;
+using System.Text;
+
+namespace Neo.UnitTests.Cryptography
+{
+ [TestClass]
+ public class UT_MerkleTreeNode
+ {
+ private MerkleTreeNode node = new MerkleTreeNode();
+
+ [TestInitialize]
+ public void TestSetup()
+ {
+ node.Hash = null;
+ node.Parent = null;
+ node.LeftChild = null;
+ node.RightChild = null;
+ }
+
+ [TestMethod]
+ public void TestConstructor()
+ {
+ byte[] byteArray = Encoding.ASCII.GetBytes("hello world");
+ var hash = new UInt256(Crypto.Default.Hash256(byteArray));
+ node.Hash = hash;
+
+ node.Hash.Should().Be(hash);
+ node.Parent.Should().BeNull();
+ node.LeftChild.Should().BeNull();
+ node.RightChild.Should().BeNull();
+ }
+
+ [TestMethod]
+ public void TestGetIsLeaf()
+ {
+ node.IsLeaf.Should().BeTrue();
+
+ MerkleTreeNode child = new MerkleTreeNode();
+ node.LeftChild = child;
+ node.IsLeaf.Should().BeFalse();
+ }
+
+ [TestMethod]
+ public void TestGetIsRoot()
+ {
+ node.IsRoot.Should().BeTrue();
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/Cryptography/UT_Murmur3.cs b/neo.UnitTests/Cryptography/UT_Murmur3.cs
new file mode 100644
index 0000000000..c59a53645a
--- /dev/null
+++ b/neo.UnitTests/Cryptography/UT_Murmur3.cs
@@ -0,0 +1,24 @@
+using FluentAssertions;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.Cryptography;
+
+namespace Neo.UnitTests.Cryptography
+{
+ [TestClass]
+ public class UT_Murmur3
+ {
+ [TestMethod]
+ public void TestGetHashSize()
+ {
+ Murmur3 murmur3 = new Murmur3(1);
+ murmur3.HashSize.Should().Be(32);
+ }
+
+ [TestMethod]
+ public void TestHashCore()
+ {
+ byte[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1 };
+ array.Murmur32(10u).Should().Be(378574820u);
+ }
+ }
+}
\ No newline at end of file
diff --git a/neo.UnitTests/Cryptography/UT_Scrypt.cs b/neo.UnitTests/Cryptography/UT_SCrypt.cs
similarity index 93%
rename from neo.UnitTests/Cryptography/UT_Scrypt.cs
rename to neo.UnitTests/Cryptography/UT_SCrypt.cs
index 8ec603da48..afe41bf475 100644
--- a/neo.UnitTests/Cryptography/UT_Scrypt.cs
+++ b/neo.UnitTests/Cryptography/UT_SCrypt.cs
@@ -1,11 +1,10 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Neo.Cryptography;
-using System;
namespace Neo.UnitTests.Cryptography
{
[TestClass]
- public class UT_Scrypt
+ public class UT_SCrypt
{
[TestMethod]
public void DeriveKeyTest()
From 8768bf7f5a2b6e4754b64a44756cc0a5df6164b1 Mon Sep 17 00:00:00 2001
From: erikzhang
Date: Mon, 29 Jul 2019 23:44:55 +0800
Subject: [PATCH 056/305] Fix `System.Contract.Call`
---
neo/SmartContract/InteropService.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/neo/SmartContract/InteropService.cs b/neo/SmartContract/InteropService.cs
index fbb3a8655d..c4daa8a89b 100644
--- a/neo/SmartContract/InteropService.cs
+++ b/neo/SmartContract/InteropService.cs
@@ -54,7 +54,7 @@ public static partial class InteropService
public static readonly uint System_Block_GetTransactions = Register("System.Block.GetTransactions", Block_GetTransactions, 0_00010000, TriggerType.Application);
public static readonly uint System_Block_GetTransaction = Register("System.Block.GetTransaction", Block_GetTransaction, 0_00000400, TriggerType.Application);
public static readonly uint System_Transaction_GetHash = Register("System.Transaction.GetHash", Transaction_GetHash, 0_00000400, TriggerType.All);
- public static readonly uint System_Contract_Call = Register("System.Contract.Call", Contract_Call, 0_01000000, TriggerType.Application);
+ public static readonly uint System_Contract_Call = Register("System.Contract.Call", Contract_Call, 0_01000000, TriggerType.System | TriggerType.Application);
public static readonly uint System_Contract_Destroy = Register("System.Contract.Destroy", Contract_Destroy, 0_01000000, TriggerType.Application);
public static readonly uint System_Storage_GetContext = Register("System.Storage.GetContext", Storage_GetContext, 0_00000400, TriggerType.Application);
public static readonly uint System_Storage_GetReadOnlyContext = Register("System.Storage.GetReadOnlyContext", Storage_GetReadOnlyContext, 0_00000400, TriggerType.Application);
From c7bfb10bb739376022a85c1cbc593707fbf2c915 Mon Sep 17 00:00:00 2001
From: erikzhang
Date: Mon, 29 Jul 2019 23:57:24 +0800
Subject: [PATCH 057/305] Fix ProtocolSettings.cs
---
neo/ProtocolSettings.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/neo/ProtocolSettings.cs b/neo/ProtocolSettings.cs
index 478d5b71b3..381e56c8a7 100644
--- a/neo/ProtocolSettings.cs
+++ b/neo/ProtocolSettings.cs
@@ -71,7 +71,7 @@ private ProtocolSettings(IConfigurationSection section)
"seed4.neo.org:10333",
"seed5.neo.org:10333"
};
- this.MillisecondsPerBlock = section.GetValue("SecondsPerBlock", 15000u);
+ this.MillisecondsPerBlock = section.GetValue("MillisecondsPerBlock", 15000u);
this.MemoryPoolMaxTransactions = Math.Max(1, section.GetValue("MemoryPoolMaxTransactions", 50_000));
}
}
From 1064e772bf1dfcaab3f0f7cca8a606e20847e6b1 Mon Sep 17 00:00:00 2001
From: Erik Zhang
Date: Tue, 30 Jul 2019 13:00:52 +0800
Subject: [PATCH 058/305] Fixes #946 (#950)
---
neo.UnitTests/IO/UT_IOHelper.cs | 12 +--
neo.UnitTests/UT_DataCache.cs | 126 ++++++++++++++++++++++++
neo/IO/ByteArrayComparer.cs | 21 ++++
neo/IO/Caching/DataCache.cs | 54 ++++++++--
neo/IO/Helper.cs | 13 ++-
neo/SmartContract/InteropService.NEO.cs | 2 +-
6 files changed, 208 insertions(+), 20 deletions(-)
create mode 100644 neo.UnitTests/UT_DataCache.cs
create mode 100644 neo/IO/ByteArrayComparer.cs
diff --git a/neo.UnitTests/IO/UT_IOHelper.cs b/neo.UnitTests/IO/UT_IOHelper.cs
index e113ce8cd4..b0593c02ec 100644
--- a/neo.UnitTests/IO/UT_IOHelper.cs
+++ b/neo.UnitTests/IO/UT_IOHelper.cs
@@ -234,9 +234,9 @@ public void TestReadBytesWithGrouping()
else
{
byte[] caseArray = new byte[] { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
- 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x00,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x10,
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
- 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x00,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x10,
0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x11};
MemoryStream stream = new MemoryStream();
@@ -415,11 +415,11 @@ public void TestWriteBytesWithGrouping()
byte[] byteArray = new byte[stream.Length];
stream.Read(byteArray, 0, (int)stream.Length);
Assert.AreEqual(Encoding.Default.GetString(new byte[] { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
- 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x00,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x10,
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
- 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x00,
+ 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,0x10,
0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x0C}), Encoding.Default.GetString(byteArray));
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x04}), Encoding.Default.GetString(byteArray));
}
[TestMethod]
@@ -546,4 +546,4 @@ public void TestWriteVarString()
Assert.AreEqual(0x61, byteArray[1]);
}
}
-}
\ No newline at end of file
+}
diff --git a/neo.UnitTests/UT_DataCache.cs b/neo.UnitTests/UT_DataCache.cs
new file mode 100644
index 0000000000..85df272db5
--- /dev/null
+++ b/neo.UnitTests/UT_DataCache.cs
@@ -0,0 +1,126 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Neo.IO.Caching;
+using Neo.Ledger;
+using System.Linq;
+
+namespace Neo.UnitTests
+{
+ [TestClass]
+ public class UT_DataCache
+ {
+ [TestInitialize]
+ public void TestSetup()
+ {
+ TestBlockchain.InitializeMockNeoSystem();
+ }
+
+ [TestMethod]
+ public void TestCachedFind_Between()
+ {
+ var snapshot = TestBlockchain.GetStore().GetSnapshot();
+ var storages = snapshot.Storages;
+ var cache = new CloneCache(storages);
+
+ storages.DeleteWhere((k, v) => k.ScriptHash == UInt160.Zero);
+
+ storages.Add
+ (
+ new StorageKey() { Key = new byte[] { 0x01, 0x01 }, ScriptHash = UInt160.Zero },
+ new StorageItem() { IsConstant = false, Value = new byte[] { } }
+ );
+ storages.Add
+ (
+ new StorageKey() { Key = new byte[] { 0x00, 0x01 }, ScriptHash = UInt160.Zero },
+ new StorageItem() { IsConstant = false, Value = new byte[] { } }
+ );
+ storages.Add
+ (
+ new StorageKey() { Key = new byte[] { 0x00, 0x03 }, ScriptHash = UInt160.Zero },
+ new StorageItem() { IsConstant = false, Value = new byte[] { } }
+ );
+ cache.Add
+ (
+ new StorageKey() { Key = new byte[] { 0x01, 0x02 }, ScriptHash = UInt160.Zero },
+ new StorageItem() { IsConstant = false, Value = new byte[] { } }
+ );
+ cache.Add
+ (
+ new StorageKey() { Key = new byte[] { 0x00, 0x02 }, ScriptHash = UInt160.Zero },
+ new StorageItem() { IsConstant = false, Value = new byte[] { } }
+ );
+
+ CollectionAssert.AreEqual(
+ cache.Find(new byte[21]).Select(u => u.Key.Key[1]).ToArray(),
+ new byte[] { 0x01, 0x02, 0x03 }
+ );
+
+ storages.DeleteWhere((k, v) => k.ScriptHash == UInt160.Zero);
+ }
+
+ [TestMethod]
+ public void TestCachedFind_Last()
+ {
+ var snapshot = TestBlockchain.GetStore().GetSnapshot();
+ var storages = snapshot.Storages;
+ var cache = new CloneCache(storages);
+
+ storages.DeleteWhere((k, v) => k.ScriptHash == UInt160.Zero);
+
+ storages.Add
+ (
+ new StorageKey() { Key = new byte[] { 0x00, 0x01 }, ScriptHash = UInt160.Zero },
+ new StorageItem() { IsConstant = false, Value = new byte[] { } }
+ );
+ storages.Add
+ (
+ new StorageKey() { Key = new byte[] { 0x01, 0x01 }, ScriptHash = UInt160.Zero },
+ new StorageItem() { IsConstant = false, Value = new byte[] { } }
+ );
+ cache.Add
+ (
+ new StorageKey() { Key = new byte[] { 0x00, 0x02 }, ScriptHash = UInt160.Zero },
+ new StorageItem() { IsConstant = false, Value = new byte[] { } }
+ );
+ cache.Add
+ (
+ new StorageKey() { Key = new byte[] { 0x01, 0x02 }, ScriptHash = UInt160.Zero },
+ new StorageItem() { IsConstant = false, Value = new byte[] { } }
+ );
+
+ CollectionAssert.AreEqual(
+ cache.Find(new byte[21]).Select(u => u.Key.Key[1]).ToArray(),
+ new byte[] { 0x01, 0x02 }
+ );
+
+ storages.DeleteWhere((k, v) => k.ScriptHash == UInt160.Zero);
+ }
+
+ [TestMethod]
+ public void TestCachedFind_Empty()
+ {
+ var snapshot = TestBlockchain.GetStore().GetSnapshot();
+ var storages = snapshot.Storages;
+ var cache = new CloneCache(storages);
+
+ storages.DeleteWhere((k, v) => k.ScriptHash == UInt160.Zero);
+
+ cache.Add
+ (
+ new StorageKey() { Key = new byte[] { 0x00, 0x02 }, ScriptHash = UInt160.Zero },
+ new StorageItem() { IsConstant = false, Value = new byte[] { } }
+ );
+ cache.Add
+ (
+ new StorageKey() { Key = new byte[] { 0x01, 0x02 }, ScriptHash = UInt160.Zero },
+ new StorageItem() { IsConstant = false, Value = new byte[] { } }
+ );
+
+ CollectionAssert.AreEqual(
+ cache.Find(new byte[21]).Select(u => u.Key.Key[1]).ToArray(),
+ new byte[] { 0x02 }
+ );
+
+ storages.DeleteWhere((k, v) => k.ScriptHash == UInt160.Zero);
+ }
+ }
+}
diff --git a/neo/IO/ByteArrayComparer.cs b/neo/IO/ByteArrayComparer.cs
new file mode 100644
index 0000000000..956ab758e6
--- /dev/null
+++ b/neo/IO/ByteArrayComparer.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+
+namespace Neo.IO
+{
+ internal class ByteArrayComparer : IComparer
+ {
+ public static readonly ByteArrayComparer Default = new ByteArrayComparer();
+
+ public int Compare(byte[] x, byte[] y)
+ {
+ int length = Math.Min(x.Length, y.Length);
+ for (int i = 0; i < length; i++)
+ {
+ int r = x[i].CompareTo(y[i]);
+ if (r != 0) return r;
+ }
+ return x.Length.CompareTo(y.Length);
+ }
+ }
+}
diff --git a/neo/IO/Caching/DataCache.cs b/neo/IO/Caching/DataCache.cs
index 5e9886d10c..278c01d650 100644
--- a/neo/IO/Caching/DataCache.cs
+++ b/neo/IO/Caching/DataCache.cs
@@ -118,16 +118,58 @@ public void DeleteWhere(Func predicate)
}
}
+ ///
+ /// Find the entries that start with the `key_prefix`
+ ///
+ /// Must maintain the deserialized format of TKey
+ /// Entries found with the desired prefix
public IEnumerable> Find(byte[] key_prefix = null)
{
+ IEnumerable<(byte[], TKey, TValue)> cached;
lock (dictionary)
{
- foreach (var pair in FindInternal(key_prefix ?? new byte[0]))
- if (!dictionary.ContainsKey(pair.Key))
- yield return pair;
- foreach (var pair in dictionary)
- if (pair.Value.State != TrackState.Deleted && (key_prefix == null || pair.Key.ToArray().Take(key_prefix.Length).SequenceEqual(key_prefix)))
- yield return new KeyValuePair(pair.Key, pair.Value.Item);
+ cached = dictionary
+ .Where(p => p.Value.State != TrackState.Deleted && (key_prefix == null || p.Key.ToArray().Take(key_prefix.Length).SequenceEqual(key_prefix)))
+ .Select(p =>
+ (
+ KeyBytes: p.Key.ToArray(),
+ p.Key,
+ p.Value.Item
+ ))
+ .OrderBy(p => p.KeyBytes, ByteArrayComparer.Default)
+ .ToArray();
+ }
+ var uncached = FindInternal(key_prefix ?? new byte[0])
+ .Where(p => !dictionary.ContainsKey(p.Key))
+ .Select(p =>
+ (
+ KeyBytes: p.Key.ToArray(),
+ p.Key,
+ p.Value
+ ));
+ using (var e1 = cached.GetEnumerator())
+ using (var e2 = uncached.GetEnumerator())
+ {
+ (byte[] KeyBytes, TKey Key, TValue Item) i1, i2;
+ bool c1 = e1.MoveNext();
+ bool c2 = e2.MoveNext();
+ i1 = c1 ? e1.Current : default;
+ i2 = c2 ? e2.Current : default;
+ while (c1 || c2)
+ {
+ if (!c2 || (c1 && ByteArrayComparer.Default.Compare(i1.KeyBytes, i2.KeyBytes) < 0))
+ {
+ yield return new KeyValuePair(i1.Key, i1.Item);
+ c1 = e1.MoveNext();
+ i1 = c1 ? e1.Current : default;
+ }
+ else
+ {
+ yield return new KeyValuePair(i2.Key, i2.Item);
+ c2 = e2.MoveNext();
+ i2 = c2 ? e2.Current : default;
+ }
+ }
}
}
diff --git a/neo/IO/Helper.cs b/neo/IO/Helper.cs
index 647ae2cfb1..a306e297d5 100644
--- a/neo/IO/Helper.cs
+++ b/neo/IO/Helper.cs
@@ -92,17 +92,16 @@ public static byte[] ReadBytesWithGrouping(this BinaryReader reader)
{
using (MemoryStream ms = new MemoryStream())
{
- int padding = 0;
+ int count;
do
{
byte[] group = reader.ReadBytes(GroupingSizeInBytes);
- padding = reader.ReadByte();
- if (padding > GroupingSizeInBytes)
+ count = reader.ReadByte();
+ if (count > GroupingSizeInBytes)
throw new FormatException();
- int count = GroupingSizeInBytes - padding;
if (count > 0)
ms.Write(group, 0, count);
- } while (padding == 0);
+ } while (count == GroupingSizeInBytes);
return ms.ToArray();
}
}
@@ -200,7 +199,7 @@ public static void WriteBytesWithGrouping(this BinaryWriter writer, byte[] value
while (remain >= GroupingSizeInBytes)
{
writer.Write(value, index, GroupingSizeInBytes);
- writer.Write((byte)0);
+ writer.Write((byte)GroupingSizeInBytes);
index += GroupingSizeInBytes;
remain -= GroupingSizeInBytes;
}
@@ -209,7 +208,7 @@ public static void WriteBytesWithGrouping(this BinaryWriter writer, byte[] value
int padding = GroupingSizeInBytes - remain;
for (int i = 0; i < padding; i++)
writer.Write((byte)0);
- writer.Write((byte)padding);
+ writer.Write((byte)remain);
}
public static void WriteFixedString(this BinaryWriter writer, string value, int length)
diff --git a/neo/SmartContract/InteropService.NEO.cs b/neo/SmartContract/InteropService.NEO.cs
index 5787cebdb4..669a9b7073 100644
--- a/neo/SmartContract/InteropService.NEO.cs
+++ b/neo/SmartContract/InteropService.NEO.cs
@@ -353,7 +353,7 @@ private static bool Storage_Find(ApplicationEngine engine)
while (remain >= 16)
{
ms.Write(prefix, index, 16);
- ms.WriteByte(0);
+ ms.WriteByte(16);
index += 16;
remain -= 16;
}
From 81d6754e1d5aa61db272cab377ae5fa2cc928a0e Mon Sep 17 00:00:00 2001
From: Krain Chen
Date: Tue, 30 Jul 2019 22:20:55 +0800
Subject: [PATCH 059/305] Add NEO SDK RPC module (#850)
* Add NEO SDK based on RPC client
* add rpc interface methods for neo3
* update unit test
* add unit test
* Update TransactionHelper.cs
Changed for neo 3.0, not final yet.
* implement sdk rpc client methods
* backup files
* change class name
* remove uncompleted modules for pull request
* change json deserialize method with Neo JObject
* modified JSON implementation, added FromJson()
* more RPC change
* PR correction
* RPC module fix, remove newton.json
* fix
* fix getblock issue
* PR correction
* PR Correction
* PR Correction: rename RPC models
* PR Correction
* resolve conflicts
* Clean code
* Clean code
* Clean code
* Clean code
* Update RpcValidateAddressResult.cs
* Clean code
* PR correction
* Move test file to the right place
---
neo.UnitTests/Network/RPC/UT_RpcClient.cs | 540 ++++++++++++++++++
neo/Ledger/ContractState.cs | 8 +
neo/Network/P2P/Payloads/Block.cs | 11 +
neo/Network/P2P/Payloads/BlockBase.cs | 16 +-
neo/Network/P2P/Payloads/ConsensusData.cs | 10 +
neo/Network/P2P/Payloads/Header.cs | 14 +-
neo/Network/P2P/Payloads/Transaction.cs | 15 +
.../P2P/Payloads/TransactionAttribute.cs | 8 +
neo/Network/P2P/Payloads/Witness.cs | 8 +
neo/Network/RPC/Models/RpcBlock.cs | 37 ++
neo/Network/RPC/Models/RpcBlockHeader.cs | 37 ++
neo/Network/RPC/Models/RpcInvokeResult.cs | 69 +++
neo/Network/RPC/Models/RpcNep5Balances.cs | 57 ++
neo/Network/RPC/Models/RpcPeers.cs | 55 ++
neo/Network/RPC/Models/RpcPlugin.cs | 32 ++
neo/Network/RPC/Models/RpcRawMemPool.cs | 32 ++
neo/Network/RPC/Models/RpcRequest.cs | 37 ++
neo/Network/RPC/Models/RpcResponse.cs | 72 +++
neo/Network/RPC/Models/RpcTransaction.cs | 41 ++
.../RPC/Models/RpcValidateAddressResult.cs | 27 +
neo/Network/RPC/Models/RpcValidator.cs | 32 ++
neo/Network/RPC/Models/RpcVersion.cs | 35 ++
neo/Network/RPC/RpcClient.cs | 292 ++++++++++
23 files changed, 1482 insertions(+), 3 deletions(-)
create mode 100644 neo.UnitTests/Network/RPC/UT_RpcClient.cs
create mode 100644 neo/Network/RPC/Models/RpcBlock.cs
create mode 100644 neo/Network/RPC/Models/RpcBlockHeader.cs
create mode 100644 neo/Network/RPC/Models/RpcInvokeResult.cs
create mode 100644 neo/Network/RPC/Models/RpcNep5Balances.cs
create mode 100644 neo/Network/RPC/Models/RpcPeers.cs
create mode 100644 neo/Network/RPC/Models/RpcPlugin.cs
create mode 100644 neo/Network/RPC/Models/RpcRawMemPool.cs
create mode 100644 neo/Network/RPC/Models/RpcRequest.cs
create mode 100644 neo/Network/RPC/Models/RpcResponse.cs
create mode 100644 neo/Network/RPC/Models/RpcTransaction.cs
create mode 100644 neo/Network/RPC/Models/RpcValidateAddressResult.cs
create mode 100644 neo/Network/RPC/Models/RpcValidator.cs
create mode 100644 neo/Network/RPC/Models/RpcVersion.cs
create mode 100644 neo/Network/RPC/RpcClient.cs
diff --git a/neo.UnitTests/Network/RPC/UT_RpcClient.cs b/neo.UnitTests/Network/RPC/UT_RpcClient.cs
new file mode 100644
index 0000000000..955c481248
--- /dev/null
+++ b/neo.UnitTests/Network/RPC/UT_RpcClient.cs
@@ -0,0 +1,540 @@
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Moq;
+using Moq.Protected;
+using Neo.IO;
+using Neo.IO.Json;
+using Neo.Ledger;
+using Neo.Network.P2P.Payloads;
+using Neo.Network.RPC;
+using Neo.Network.RPC.Models;
+using Neo.SmartContract;
+using Neo.SmartContract.Manifest;
+using Neo.VM;
+using System;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Neo.UnitTests.Network.RPC
+{
+ [TestClass]
+ public class UT_RpcClient
+ {
+ RpcClient rpc;
+ Mock handlerMock;
+
+ [TestInitialize]
+ public void TestSetup()
+ {
+ handlerMock = new Mock(MockBehavior.Strict);
+
+ // use real http client with mocked handler here
+ var httpClient = new HttpClient(handlerMock.Object)
+ {
+ BaseAddress = new Uri("http://seed1.neo.org:10331"),
+ };
+
+ rpc = new RpcClient(httpClient);
+ }
+
+ private void MockResponse(string content)
+ {
+ handlerMock.Protected()
+ // Setup the PROTECTED method to mock
+ .Setup>(
+ "SendAsync",
+ ItExpr.IsAny(),
+ ItExpr.IsAny()
+ )
+ // prepare the expected response of the mocked http call
+ .ReturnsAsync(new HttpResponseMessage()
+ {
+ StatusCode = HttpStatusCode.OK,
+ Content = new StringContent(content),
+ })
+ .Verifiable();
+ }
+
+ private JObject CreateErrorResponse(JObject id, int code, string message, JObject data = null)
+ {
+ JObject response = CreateResponse(id);
+ response["error"] = new JObject();
+ response["error"]["code"] = code;
+ response["error"]["message"] = message;
+ if (data != null)
+ response["error"]["data"] = data;
+ return response;
+ }
+
+ private JObject CreateResponse(JObject id)
+ {
+ JObject response = new JObject();
+ response["jsonrpc"] = "2.0";
+ response["id"] = id;
+ return response;
+ }
+
+ [TestMethod]
+ public void TestErrorResponse()
+ {
+ JObject response = CreateErrorResponse(null, -32700, "Parse error");
+ MockResponse(response.ToString());
+ try
+ {
+ var result = rpc.GetBlockHex("773dd2dae4a9c9275290f89b56e67d7363ea4826dfd4fc13cc01cf73a44b0d0e");
+ }
+ catch (RpcException ex)
+ {
+ Assert.AreEqual(-32700, ex.HResult);
+ Assert.AreEqual("Parse error", ex.Message);
+ }
+ }
+
+ [TestMethod]
+ public void TestGetBestBlockHash()
+ {
+ JObject response = CreateResponse(1);
+ response["result"] = "000000002deadfa82cbc4682f5800";
+ MockResponse(response.ToString());
+
+ var result = rpc.GetBestBlockHash();
+ Assert.AreEqual("000000002deadfa82cbc4682f5800", result);
+ }
+
+ [TestMethod]
+ public void TestGetBlockHex()
+ {
+ JObject response = CreateResponse(1);
+ response["result"] = "000000002deadfa82cbc4682f5800";
+ MockResponse(response.ToString());
+
+ var result = rpc.GetBlockHex("773dd2dae4a9c9275290f89b56e67d7363ea4826dfd4fc13cc01cf73a44b0d0e");
+ Assert.AreEqual("000000002deadfa82cbc4682f5800", result);
+ }
+
+ [TestMethod]
+ public void TestGetBlock()
+ {
+ // create block
+ var block = new Block();
+ TestUtils.SetupBlockWithValues(block, UInt256.Zero, out UInt256 merkRootVal, out UInt160 val160, out ulong timestampVal, out uint indexVal, out Witness scriptVal, out Transaction[] transactionsVal, 0);
+
+ block.Transactions = new[]
+ {
+ TestUtils.GetTransaction(),
+ TestUtils.GetTransaction(),
+ TestUtils.GetTransaction()
+ };
+
+ JObject json = block.ToJson();
+ JObject response = CreateResponse(1);
+ response["result"] = json;
+ MockResponse(response.ToString());
+
+ var result = rpc.GetBlock("773dd2dae4a9c9275290f89b56e67d7363ea4826dfd4fc13cc01cf73a44b0d0e");
+ Assert.AreEqual(block.Hash.ToString(), result.Block.Hash.ToString());
+ Assert.IsNull(result.Confirmations);
+ Assert.AreEqual(block.Transactions.Length, result.Block.Transactions.Length);
+ Assert.AreEqual(block.Transactions[0].Hash.ToString(), result.Block.Transactions[0].Hash.ToString());
+
+ // verbose with confirmations
+ json["confirmations"] = 20;
+ json["nextblockhash"] = "773dd2dae4a9c9275290f89b56e67d7363ea4826dfd4fc13cc01cf73a44b0d0e";
+ MockResponse(response.ToString());
+ result = rpc.GetBlock("773dd2dae4a9c9275290f89b56e67d7363ea4826dfd4fc13cc01cf73a44b0d0e");
+ Assert.AreEqual(block.Hash.ToString(), result.Block.Hash.ToString());
+ Assert.AreEqual(20, result.Confirmations);
+ Assert.AreEqual(block.Transactions.Length, result.Block.Transactions.Length);
+ Assert.AreEqual(block.Transactions[0].Hash.ToString(), result.Block.Transactions[0].Hash.ToString());
+ }
+
+ [TestMethod]
+ public void TestGetBlockCount()
+ {
+ JObject response = CreateResponse(1);
+ response["result"] = 100;
+ MockResponse(response.ToString());
+
+ var result = rpc.GetBlockCount();
+ Assert.AreEqual(100, result);
+ }
+
+ [TestMethod]
+ public void TestGetBlockHash()
+ {
+ JObject response = CreateResponse(1);
+ response["result"] = "0x4c1e879872344349067c3b1a30781eeb4f9040d3795db7922f513f6f9660b9b2";
+ MockResponse(response.ToString());
+
+ var result = rpc.GetBlockHash(100);
+ Assert.AreEqual("0x4c1e879872344349067c3b1a30781eeb4f9040d3795db7922f513f6f9660b9b2", result);
+ }
+
+ [TestMethod]
+ public void TestGetBlockHeaderHex()
+ {
+ JObject response = CreateResponse(1);
+ response["result"] = "0x4c1e879872344349067c3b1a30781eeb4f9040d3795db7922f513f6f9660b9b2";
+ MockResponse(response.ToString());
+
+ var result = rpc.GetBlockHeaderHex("100");
+ Assert.AreEqual("0x4c1e879872344349067c3b1a30781eeb4f9040d3795db7922f513f6f9660b9b2", result);
+ }
+
+ [TestMethod]
+ public void TestGetBlockHeader()
+ {
+ Header header = new Header();
+ TestUtils.SetupHeaderWithValues(header, UInt256.Zero, out UInt256 merkRootVal, out UInt160 val160, out ulong timestampVal, out uint indexVal, out Witness scriptVal);
+
+ JObject json = header.ToJson();
+ JObject response = CreateResponse(1);
+ response["result"] = json;
+ MockResponse(response.ToString());
+
+ var result = rpc.GetBlockHeader("100");
+ Assert.AreEqual(header.Hash.ToString(), result.Header.Hash.ToString());
+ Assert.IsNull(result.Confirmations);
+
+ json["confirmations"] = 20;
+ json["nextblockhash"] = "4c1e879872344349067c3b1a30781eeb4f9040d3795db7922f513f6f9660b9b2";
+ MockResponse(response.ToString());
+ result = rpc.GetBlockHeader("100");
+ Assert.AreEqual(header.Hash.ToString(), result.Header.Hash.ToString());
+ Assert.AreEqual(20, result.Confirmations);
+ }
+
+ [TestMethod]
+ public void TestGetBlockSysFee()
+ {
+ JObject response = CreateResponse(1);
+ response["result"] = "195500";
+ MockResponse(response.ToString());
+
+ var result = rpc.GetBlockSysFee(100);
+ Assert.AreEqual("195500", result);
+ }
+
+ [TestMethod]
+ public void TestGetConnectionCount()
+ {
+ JObject response = CreateResponse(1);
+ response["result"] = 9;
+ MockResponse(response.ToString());
+
+ var result = rpc.GetConnectionCount();
+ Assert.AreEqual(9, result);
+ }
+
+ [TestMethod]
+ public void TestGetContractState()
+ {
+ var sb = new ScriptBuilder();
+ sb.EmitSysCall(InteropService.System_Runtime_GetInvocationCounter);
+
+ ContractState state = new ContractState
+ {
+ Script = new byte[] { (byte)OpCode.DROP, (byte)OpCode.DROP }.Concat(sb.ToArray()).ToArray(),
+ Manifest = ContractManifest.CreateDefault(UInt160.Parse("0xa400ff00ff00ff00ff00ff00ff00ff00ff00ff01"))
+ };
+
+ JObject response = CreateResponse(1);
+ response["result"] = state.ToJson();
+ MockResponse(response.ToString());
+
+ var result = rpc.GetContractState("17694b31cc7ee215cea2ded146e0b2b28768fc46");
+
+ Assert.AreEqual(state.Script.ToHexString(), result.Script.ToHexString());
+ Assert.AreEqual(state.Manifest.Abi.EntryPoint.Name, result.Manifest.Abi.EntryPoint.Name);
+ }
+
+ [TestMethod]
+ public void TestGetPeers()
+ {
+ JObject response = CreateResponse(1);
+ response["result"] = JObject.Parse(@"{
+ ""unconnected"": [
+ {
+ ""address"": ""::ffff:70.73.16.236"",
+ ""port"": 10333
+ },
+ {
+ ""address"": ""::ffff:82.95.77.148"",
+ ""port"": 10333
+ },
+ {
+ ""address"": ""::ffff:49.50.215.166"",
+ ""port"": 10333
+ }
+ ],
+ ""bad"": [],
+ ""connected"": [
+ {
+ ""address"": ""::ffff:139.219.106.33"",
+ ""port"": 10333
+ },
+ {
+ ""address"": ""::ffff:47.88.53.224"",
+ ""port"": 10333
+ }
+ ]
+ }");
+ MockResponse(response.ToString());
+
+ var result = rpc.GetPeers();
+ Assert.AreEqual("::ffff:139.219.106.33", result.Connected[0].Address);
+ Assert.AreEqual("::ffff:82.95.77.148", result.Unconnected[1].Address);
+ }
+
+ [TestMethod]
+ public void TestGetRawMempool()
+ {
+ JObject response = CreateResponse(1);
+ response["result"] = JObject.Parse(@"[
+ ""0x9786cce0dddb524c40ddbdd5e31a41ed1f6b5c8a683c122f627ca4a007a7cf4e"",
+ ""0xb488ad25eb474f89d5ca3f985cc047ca96bc7373a6d3da8c0f192722896c1cd7"",
+ ""0xf86f6f2c08fbf766ebe59dc84bc3b8829f1053f0a01deb26bf7960d99fa86cd6""
+ ]");
+ MockResponse(response.ToString());
+
+ var result = rpc.GetRawMempool();
+ Assert.AreEqual("0xb488ad25eb474f89d5ca3f985cc047ca96bc7373a6d3da8c0f192722896c1cd7", result[1]);
+ }
+
+ [TestMethod]
+ public void TestGetRawMempoolBoth()
+ {
+ JObject json = new JObject();
+ json["height"] = 65535;
+ json["verified"] = new JArray(new[] { "0x9786cce0dddb524c40ddbdd5e31a41ed1f6b5c8a683c122f627ca4a007a7cf4e" }.Select(p => (JObject)p));
+ json["unverified"] = new JArray(new[] { "0xb488ad25eb474f89d5ca3f985cc047ca96bc7373a6d3da8c0f192722896c1cd7", "0xf86f6f2c08fbf766ebe59dc84bc3b8829f1053f0a01deb26bf7960d99fa86cd6" }.Select(p => (JObject)p));
+
+ JObject response = CreateResponse(1);
+ response["result"] = json;
+ MockResponse(response.ToString());
+
+ var result = rpc.GetRawMempoolBoth();
+ Assert.AreEqual((uint)65535, result.Height);
+ Assert.AreEqual("0x9786cce0dddb524c40ddbdd5e31a41ed1f6b5c8a683c122f627ca4a007a7cf4e", result.Verified[0]);
+ Assert.AreEqual("0xf86f6f2c08fbf766ebe59dc84bc3b8829f1053f0a01deb26bf7960d99fa86cd6", result.UnVerified[1]);
+ }
+
+ [TestMethod]
+ public void TestGetRawTransactionHex()
+ {
+ var json = TestUtils.GetTransaction().ToArray().ToHexString();
+
+ JObject response = CreateResponse(1);
+ response["result"] = json;
+ MockResponse(response.ToString());
+
+ //var result = rpc.GetRawTransactionHex("0x9786cce0dddb524c40ddbdd5e31a41ed1f6b5c8a683c122f627ca4a007a7cf4e");
+ var result = rpc.GetRawTransactionHex(TestUtils.GetTransaction().Hash.ToString());
+ Assert.AreEqual(json, result);
+ }
+
+ [TestMethod]
+ public void TestGetRawTransaction()
+ {
+ var transaction = TestUtils.GetTransaction();
+ JObject json = transaction.ToJson();
+ JObject response = CreateResponse(1);
+ response["result"] = json;
+ MockResponse(response.ToString());
+
+ var result = rpc.GetRawTransaction("0x9786cce0dddb524c40ddbdd5e31a41ed1f6b5c8a683c122f627ca4a007a7cf4e");
+ Assert.AreEqual(transaction.Hash, result.Transaction.Hash);
+ Assert.AreEqual(json.ToString(), result.ToJson().ToString());
+
+ json["blockhash"] = UInt256.Zero.ToString();
+ json["confirmations"] = 100;
+ json["blocktime"] = 10;
+ MockResponse(response.ToString());
+
+ result = rpc.GetRawTransaction("0x9786cce0dddb524c40ddbdd5e31a41ed1f6b5c8a683c122f627ca4a007a7cf4e");
+ Assert.AreEqual(transaction.Hash, result.Transaction.Hash);
+ Assert.AreEqual(100, result.Confirmations);
+ Assert.AreEqual(json.ToString(), result.ToJson().ToString());
+ }
+
+ [TestMethod]
+ public void TestGetStorage()
+ {
+ JObject json = "4c696e";
+ JObject response = CreateResponse(1);
+ response["result"] = json;
+ MockResponse(response.ToString());
+
+ var result = rpc.GetStorage("03febccf81ac85e3d795bc5cbd4e84e907812aa3", "5065746572");
+ Assert.AreEqual("4c696e", result);
+ }
+
+ [TestMethod]
+ public void TestGetTransactionHeight()
+ {
+ JObject json = 10000;
+ JObject response = CreateResponse(1);
+ response["result"] = json;
+ MockResponse(response.ToString());
+
+ var result = rpc.GetTransactionHeight("9c909e1e3ba03290553a68d862e002c7a21ba302e043fc492fe069bf6a134d29");
+ Assert.AreEqual(json.ToString(), result.ToString());
+ }
+
+ [TestMethod]
+ public void TestGetValidators()
+ {
+ JObject json = JObject.Parse(@"[
+ {
+ ""publickey"": ""02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70"",
+ ""votes"": ""46632420"",
+ ""active"": true
+ },
+ {
+ ""publickey"": ""024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d"",
+ ""votes"": ""46632420"",
+ ""active"": true
+ }
+ ]");
+ JObject response = CreateResponse(1);
+ response["result"] = json;
+ MockResponse(response.ToString());
+
+ var result = rpc.GetValidators();
+ Assert.AreEqual(((JArray)json)[0].ToString(), (result[0]).ToJson().ToString());
+ }
+
+ [TestMethod]
+ public void TestGetVersion()
+ {
+ JObject json = new JObject();
+ json["tcpPort"] = 30001;
+ json["wsPort"] = 30002;
+ json["nonce"] = 1546258664;
+ json["useragent"] = "/NEO:2.7.5/";
+
+ var json1 = JObject.Parse(@"{
+ ""tcpPort"": 30001,
+ ""wsPort"": 30002,
+ ""nonce"": 1546258664,
+ ""useragent"": ""/NEO:2.7.5/""
+ }");
+ Assert.AreEqual(json.ToString(), json1.ToString());
+
+ JObject response = CreateResponse(1);
+ response["result"] = json;
+ MockResponse(response.ToString());
+
+ var result = rpc.GetVersion();
+ Assert.AreEqual(30001, result.TcpPort);
+ Assert.AreEqual("/NEO:2.7.5/", result.UserAgent);
+ }
+
+ [TestMethod]
+ public void TestInvokeFunction()
+ {
+ JObject json = JObject.Parse(@"
+ {
+ ""script"": ""1426ae7c6c9861ec418468c1f0fdc4a7f2963eb89151c10962616c616e63654f6667be39e7b562f60cbfe2aebca375a2e5ee28737caf"",
+ ""state"": ""HALT"",
+ ""gas_consumed"": ""0.311"",
+ ""stack"": [
+ {
+ ""type"": ""ByteArray"",
+ ""value"": ""262bec084432""
+ }
+ ],
+ ""tx"":""d101361426ae7c6c9861ec418468c1f0fdc4a7f2963eb89151c10962616c616e63654f6667be39e7b562f60cbfe2aebca375a2e5ee28737caf000000000000000000000000""
+ }");
+ JObject response = CreateResponse(1);
+ response["result"] = json;
+ MockResponse(response.ToString());
+
+ var result = rpc.InvokeFunction("af7c7328eee5a275a3bcaee2bf0cf662b5e739be", "balanceOf", new[] { new RpcStack { Type = "Hash160", Value = "91b83e96f2a7c4fdf0c1688441ec61986c7cae26" } });
+ Assert.AreEqual(json.ToString(), result.ToJson().ToString());
+ }
+
+ [TestMethod]
+ public void TestInvokeScript()
+ {
+ JObject json = JObject.Parse(@"
+ {
+ ""script"": ""1426ae7c6c9861ec418468c1f0fdc4a7f2963eb89151c10962616c616e63654f6667be39e7b562f60cbfe2aebca375a2e5ee28737caf"",
+ ""state"": ""HALT"",
+ ""gas_consumed"": ""0.311"",
+ ""stack"": [
+ {
+ ""type"": ""ByteArray"",
+ ""value"": ""262bec084432""
+ }
+ ],
+ ""tx"":""d101361426ae7c6c9861ec418468c1f0fdc4a7f2963eb89151c10962616c616e63654f6667be39e7b562f60cbfe2aebca375a2e5ee28737caf000000000000000000000000""
+ }");
+ JObject response = CreateResponse(1);
+ response["result"] = json;
+ MockResponse(response.ToString());
+
+ var result = rpc.InvokeScript("00046e616d656724058e5e1b6008847cd662728549088a9ee82191");
+ Assert.AreEqual(json.ToString(), result.ToJson().ToString());
+ }
+
+ [TestMethod]
+ public void TestListPlugins()
+ {
+ JObject json = JObject.Parse(@"[{
+ ""name"": ""SimplePolicyPlugin"",
+ ""version"": ""2.10.1.0"",
+ ""interfaces"": [
+ ""ILogPlugin"",
+ ""IPolicyPlugin""
+ ]
+ }]");
+ JObject response = CreateResponse(1);
+ response["result"] = json;
+ MockResponse(response.ToString());
+
+ var result = rpc.ListPlugins();
+ Assert.AreEqual(((JArray)json)[0].ToString(), result[0].ToJson().ToString());
+ }
+
+ [TestMethod]
+ public void TestSendRawTransaction()
+ {
+ JObject json = true;
+ JObject response = CreateResponse(1);
+ response["result"] = json;
+ MockResponse(response.ToString());
+
+ var result = rpc.SendRawTransaction("80000001195876cb34364dc38b730077156c6bc3a7fc570044a66fbfeeea56f71327e8ab0000029b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc500c65eaf440000000f9a23e06f74cf86b8827a9108ec2e0f89ad956c9b7cffdaa674beae0f930ebe6085af9093e5fe56b34a5c220ccdcf6efc336fc50092e14b5e00000030aab52ad93f6ce17ca07fa88fc191828c58cb71014140915467ecd359684b2dc358024ca750609591aa731a0b309c7fb3cab5cd0836ad3992aa0a24da431f43b68883ea5651d548feb6bd3c8e16376e6e426f91f84c58232103322f35c7819267e721335948d385fae5be66e7ba8c748ac15467dcca0693692dac");
+ Assert.AreEqual(json.ToString(), ((JObject)result).ToString());
+ }
+
+ [TestMethod]
+ public void TestSubmitBlock()
+ {
+ JObject json = true;
+ JObject response = CreateResponse(1);
+ response["result"] = json;
+ MockResponse(response.ToString());
+
+ var result = rpc.SubmitBlock("03febccf81ac85e3d795bc5cbd4e84e907812aa3");
+ Assert.AreEqual(json.ToString(), ((JObject)result).ToString());
+ }
+
+ [TestMethod]
+ public void TestValidateAddress()
+ {
+ JObject json = new JObject();
+ json["address"] = "AQVh2pG732YvtNaxEGkQUei3YA4cvo7d2i";
+ json["isvalid"] = false;
+ JObject response = CreateResponse(1);
+ response["result"] = json;
+ MockResponse(response.ToString());
+
+ var result = rpc.ValidateAddress("AQVh2pG732YvtNaxEGkQUei3YA4cvo7d2i");
+ Assert.AreEqual(json.ToString(), result.ToJson().ToString());
+ }
+ }
+}
diff --git a/neo/Ledger/ContractState.cs b/neo/Ledger/ContractState.cs
index 8f97d4b363..da02db912f 100644
--- a/neo/Ledger/ContractState.cs
+++ b/neo/Ledger/ContractState.cs
@@ -64,5 +64,13 @@ public JObject ToJson()
json["manifest"] = Manifest.ToJson();
return json;
}
+
+ public static ContractState FromJson(JObject json)
+ {
+ ContractState contractState = new ContractState();
+ contractState.Script = json["script"].AsString().HexToBytes();
+ contractState.Manifest = ContractManifest.FromJson(json["manifest"]);
+ return contractState;
+ }
}
}
diff --git a/neo/Network/P2P/Payloads/Block.cs b/neo/Network/P2P/Payloads/Block.cs
index 58faf54cb1..3f29bb9428 100644
--- a/neo/Network/P2P/Payloads/Block.cs
+++ b/neo/Network/P2P/Payloads/Block.cs
@@ -2,6 +2,7 @@
using Neo.IO;
using Neo.IO.Json;
using Neo.Ledger;
+using Neo.Wallets;
using System;
using System.Collections.Generic;
using System.IO;
@@ -106,6 +107,16 @@ public override JObject ToJson()
return json;
}
+ public new static Block FromJson(JObject json)
+ {
+ Block block = new Block();
+ BlockBase blockBase = block;
+ blockBase.FromJson(json);
+ block.ConsensusData = ConsensusData.FromJson(json["consensus_data"]);
+ block.Transactions = ((JArray)json["tx"]).Select(p => Transaction.FromJson(p)).ToArray();
+ return block;
+ }
+
public TrimmedBlock Trim()
{
return new TrimmedBlock
diff --git a/neo/Network/P2P/Payloads/BlockBase.cs b/neo/Network/P2P/Payloads/BlockBase.cs
index 22ef72d021..8820c95538 100644
--- a/neo/Network/P2P/Payloads/BlockBase.cs
+++ b/neo/Network/P2P/Payloads/BlockBase.cs
@@ -6,6 +6,7 @@
using Neo.Wallets;
using System;
using System.IO;
+using System.Linq;
namespace Neo.Network.P2P.Payloads
{
@@ -32,7 +33,7 @@ public UInt256 Hash
}
}
- public virtual int Size =>
+ public virtual int Size =>
sizeof(uint) + //Version
PrevHash.Size + //PrevHash
MerkleRoot.Size + //MerkleRoot
@@ -41,7 +42,7 @@ public UInt256 Hash
NextConsensus.Size + //NextConsensus
1 + //
Witness.Size; //Witness
-
+
Witness[] IVerifiable.Witnesses
{
get
@@ -111,6 +112,17 @@ public virtual JObject ToJson()
return json;
}
+ public void FromJson(JObject json)
+ {
+ Version = (uint)json["version"].AsNumber();
+ PrevHash = UInt256.Parse(json["previousblockhash"].AsString());
+ MerkleRoot = UInt256.Parse(json["merkleroot"].AsString());
+ Timestamp = (ulong)json["time"].AsNumber();
+ Index = (uint)json["index"].AsNumber();
+ NextConsensus = json["nextconsensus"].AsString().ToScriptHash();
+ Witness = ((JArray)json["witnesses"]).Select(p => Witness.FromJson(p)).FirstOrDefault();
+ }
+
public virtual bool Verify(Snapshot snapshot)
{
Header prev_header = snapshot.GetHeader(PrevHash);
diff --git a/neo/Network/P2P/Payloads/ConsensusData.cs b/neo/Network/P2P/Payloads/ConsensusData.cs
index a48a8f1304..622c42e464 100644
--- a/neo/Network/P2P/Payloads/ConsensusData.cs
+++ b/neo/Network/P2P/Payloads/ConsensusData.cs
@@ -2,6 +2,7 @@
using Neo.IO;
using Neo.IO.Json;
using Neo.Ledger;
+using System.Globalization;
using System.IO;
namespace Neo.Network.P2P.Payloads
@@ -45,5 +46,14 @@ public JObject ToJson()
json["nonce"] = Nonce.ToString("x16");
return json;
}
+
+ public static ConsensusData FromJson(JObject json)
+ {
+ ConsensusData block = new ConsensusData();
+ block.PrimaryIndex = (uint)json["primary"].AsNumber();
+ block.Nonce = ulong.Parse(json["nonce"].AsString(), NumberStyles.HexNumber);
+ return block;
+ }
+
}
}
diff --git a/neo/Network/P2P/Payloads/Header.cs b/neo/Network/P2P/Payloads/Header.cs
index 149f4a020f..abd7fbd370 100644
--- a/neo/Network/P2P/Payloads/Header.cs
+++ b/neo/Network/P2P/Payloads/Header.cs
@@ -1,6 +1,9 @@
-using Neo.Ledger;
+using Neo.IO.Json;
+using Neo.Ledger;
+using Neo.Wallets;
using System;
using System.IO;
+using System.Linq;
namespace Neo.Network.P2P.Payloads
{
@@ -51,5 +54,14 @@ public TrimmedBlock Trim()
Hashes = new UInt256[0]
};
}
+
+ public new static Header FromJson(JObject json)
+ {
+ Header header = new Header();
+ BlockBase blockBase = header;
+ blockBase.FromJson(json);
+ return header;
+ }
+
}
}
diff --git a/neo/Network/P2P/Payloads/Transaction.cs b/neo/Network/P2P/Payloads/Transaction.cs
index 923fe6447f..40efe0e9d3 100644
--- a/neo/Network/P2P/Payloads/Transaction.cs
+++ b/neo/Network/P2P/Payloads/Transaction.cs
@@ -177,6 +177,21 @@ public JObject ToJson()
return json;
}
+ public static Transaction FromJson(JObject json)
+ {
+ Transaction tx = new Transaction();
+ tx.Version = byte.Parse(json["version"].AsString());
+ tx.Nonce = uint.Parse(json["nonce"].AsString());
+ tx.Sender = json["sender"].AsString().ToScriptHash();
+ tx.SystemFee = long.Parse(json["sys_fee"].AsString());
+ tx.NetworkFee = long.Parse(json["net_fee"].AsString());
+ tx.ValidUntilBlock = uint.Parse(json["valid_until_block"].AsString());
+ tx.Attributes = ((JArray)json["attributes"]).Select(p => TransactionAttribute.FromJson(p)).ToArray();
+ tx.Script = json["script"].AsString().HexToBytes();
+ tx.Witnesses = ((JArray)json["witnesses"]).Select(p => Witness.FromJson(p)).ToArray();
+ return tx;
+ }
+
bool IInventory.Verify(Snapshot snapshot)
{
return Verify(snapshot, Enumerable.Empty());
diff --git a/neo/Network/P2P/Payloads/TransactionAttribute.cs b/neo/Network/P2P/Payloads/TransactionAttribute.cs
index 2f384fa046..99d1671ebd 100644
--- a/neo/Network/P2P/Payloads/TransactionAttribute.cs
+++ b/neo/Network/P2P/Payloads/TransactionAttribute.cs
@@ -33,5 +33,13 @@ public JObject ToJson()
json["data"] = Data.ToHexString();
return json;
}
+
+ public static TransactionAttribute FromJson(JObject json)
+ {
+ TransactionAttribute transactionAttribute = new TransactionAttribute();
+ transactionAttribute.Usage = (TransactionAttributeUsage)(byte.Parse(json["usage"].AsString()));
+ transactionAttribute.Data = json["data"].AsString().HexToBytes();
+ return transactionAttribute;
+ }
}
}
diff --git a/neo/Network/P2P/Payloads/Witness.cs b/neo/Network/P2P/Payloads/Witness.cs
index 237a954642..d352882e17 100644
--- a/neo/Network/P2P/Payloads/Witness.cs
+++ b/neo/Network/P2P/Payloads/Witness.cs
@@ -45,5 +45,13 @@ public JObject ToJson()
json["verification"] = VerificationScript.ToHexString();
return json;
}
+
+ public static Witness FromJson(JObject json)
+ {
+ Witness witness = new Witness();
+ witness.InvocationScript = json["invocation"].AsString().HexToBytes();
+ witness.VerificationScript = json["verification"].AsString().HexToBytes();
+ return witness;
+ }
}
}
diff --git a/neo/Network/RPC/Models/RpcBlock.cs b/neo/Network/RPC/Models/RpcBlock.cs
new file mode 100644
index 0000000000..0d49b3b53a
--- /dev/null
+++ b/neo/Network/RPC/Models/RpcBlock.cs
@@ -0,0 +1,37 @@
+using Neo.IO.Json;
+using Neo.Network.P2P.Payloads;
+
+namespace Neo.Network.RPC.Models
+{
+ public class RpcBlock
+ {
+ public Block Block { get; set; }
+
+ public int? Confirmations { get; set; }
+
+ public UInt256 NextBlockHash { get; set; }
+
+ public JObject ToJson()
+ {
+ JObject json = Block.ToJson();
+ if (Confirmations != null)
+ {
+ json["confirmations"] = Confirmations;
+ json["nextblockhash"] = NextBlockHash.ToString();
+ }
+ return json;
+ }
+
+ public static RpcBlock FromJson(JObject json)
+ {
+ RpcBlock block = new RpcBlock();
+ block.Block = Block.FromJson(json);
+ if (json["confirmations"] != null)
+ {
+ block.Confirmations = (int)json["confirmations"].AsNumber();
+ block.NextBlockHash = UInt256.Parse(json["nextblockhash"].AsString());
+ }
+ return block;
+ }
+ }
+}
diff --git a/neo/Network/RPC/Models/RpcBlockHeader.cs b/neo/Network/RPC/Models/RpcBlockHeader.cs
new file mode 100644
index 0000000000..250acfd818
--- /dev/null
+++ b/neo/Network/RPC/Models/RpcBlockHeader.cs
@@ -0,0 +1,37 @@
+using Neo.IO.Json;
+using Neo.Network.P2P.Payloads;
+
+namespace Neo.Network.RPC.Models
+{
+ public class RpcBlockHeader
+ {
+ public Header Header { get; set; }
+
+ public int? Confirmations { get; set; }
+
+ public UInt256 NextBlockHash { get; set; }
+
+ public JObject ToJson()
+ {
+ JObject json = Header.ToJson();
+ if (Confirmations != null)
+ {
+ json["confirmations"] = Confirmations;
+ json["nextblockhash"] = NextBlockHash.ToString();
+ }
+ return json;
+ }
+
+ public static RpcBlockHeader FromJson(JObject json)
+ {
+ RpcBlockHeader block = new RpcBlockHeader();
+ block.Header = Header.FromJson(json);
+ if (json["confirmations"] != null)
+ {
+ block.Confirmations = (int)json["confirmations"].AsNumber();
+ block.NextBlockHash = UInt256.Parse(json["nextblockhash"].AsString());
+ }
+ return block;
+ }
+ }
+}
diff --git a/neo/Network/RPC/Models/RpcInvokeResult.cs b/neo/Network/RPC/Models/RpcInvokeResult.cs
new file mode 100644
index 0000000000..9a0f646588
--- /dev/null
+++ b/neo/Network/RPC/Models/RpcInvokeResult.cs
@@ -0,0 +1,69 @@
+using Neo.IO.Json;
+using Newtonsoft.Json;
+using System.Linq;
+
+namespace Neo.Network.RPC.Models
+{
+ public class RpcInvokeResult
+ {
+ [JsonProperty(PropertyName = "script")]
+ public string Script { get; set; }
+
+ [JsonProperty(PropertyName = "state")]
+ public string State { get; set; }
+
+ [JsonProperty(PropertyName = "gas_consumed")]
+ public string GasConsumed { get; set; }
+
+ [JsonProperty(PropertyName = "stack")]
+ public RpcStack[] Stack { get; set; }
+
+ [JsonProperty(PropertyName = "tx")]
+ public string Tx { get; set; }
+
+ public JObject ToJson()
+ {
+ JObject json = new JObject();
+ json["script"] = Script;
+ json["state"] = State;
+ json["gas_consumed"] = GasConsumed;
+ json["stack"] = new JArray(Stack.Select(p => p.ToJson()));
+ json["tx"] = Tx;
+ return json;
+ }
+
+ public static RpcInvokeResult FromJson(JObject json)
+ {
+ RpcInvokeResult invokeScriptResult = new RpcInvokeResult();
+ invokeScriptResult.Script = json["script"].AsString();
+ invokeScriptResult.State = json["state"].AsString();
+ invokeScriptResult.GasConsumed = json["gas_consumed"].AsString();
+ invokeScriptResult.Tx = json["tx"].AsString();
+ invokeScriptResult.Stack = ((JArray)json["stack"]).Select(p => RpcStack.FromJson(p)).ToArray();
+ return invokeScriptResult;
+ }
+ }
+
+ public class RpcStack
+ {
+ public string Type { get; set; }
+
+ public string Value { get; set; }
+
+ public JObject ToJson()
+ {
+ JObject json = new JObject();
+ json["type"] = Type;
+ json["value"] = Value;
+ return json;
+ }
+
+ public static RpcStack FromJson(JObject json)
+ {
+ RpcStack stackJson = new RpcStack();
+ stackJson.Type = json["type"].AsString();
+ stackJson.Value = json["value"].AsString();
+ return stackJson;
+ }
+ }
+}
diff --git a/neo/Network/RPC/Models/RpcNep5Balances.cs b/neo/Network/RPC/Models/RpcNep5Balances.cs
new file mode 100644
index 0000000000..edcf8d7f5e
--- /dev/null
+++ b/neo/Network/RPC/Models/RpcNep5Balances.cs
@@ -0,0 +1,57 @@
+using Neo.IO.Json;
+using System.Linq;
+using System.Numerics;
+
+namespace Neo.Network.RPC.Models
+{
+ public class RpcNep5Balances
+ {
+ public string Address { get; set; }
+
+ public RpcNep5Balance[] Balances { get; set; }
+
+ public JObject ToJson()
+ {
+ JObject json = new JObject();
+ json["address"] = Address;
+ json["balance"] = Balances.Select(p => p.ToJson()).ToArray();
+ return json;
+ }
+
+ public static RpcNep5Balances FromJson(JObject json)
+ {
+ RpcNep5Balances nep5Balance = new RpcNep5Balances();
+ nep5Balance.Address = json["address"].AsString();
+ //List listBalance = new List();
+ nep5Balance.Balances = ((JArray)json["balance"]).Select(p => RpcNep5Balance.FromJson(p)).ToArray();
+ return nep5Balance;
+ }
+ }
+
+ public class RpcNep5Balance
+ {
+ public UInt160 AssetHash { get; set; }
+
+ public BigInteger Amount { get; set; }
+
+ public uint LastUpdatedBlock { get; set; }
+
+ public JObject ToJson()
+ {
+ JObject json = new JObject();
+ json["asset_hash"] = AssetHash.ToArray().ToHexString();
+ json["amount"] = Amount.ToString();
+ json["last_updated_block"] = LastUpdatedBlock.ToString();
+ return json;
+ }
+
+ public static RpcNep5Balance FromJson(JObject json)
+ {
+ RpcNep5Balance balance = new RpcNep5Balance();
+ balance.AssetHash = UInt160.Parse(json["asset_hash"].AsString());
+ balance.Amount = BigInteger.Parse(json["amount"].AsString());
+ balance.LastUpdatedBlock = uint.Parse(json["last_updated_block"].AsString());
+ return balance;
+ }
+ }
+}
diff --git a/neo/Network/RPC/Models/RpcPeers.cs b/neo/Network/RPC/Models/RpcPeers.cs
new file mode 100644
index 0000000000..5caa99a66a
--- /dev/null
+++ b/neo/Network/RPC/Models/RpcPeers.cs
@@ -0,0 +1,55 @@
+using Neo.IO.Json;
+using System.Linq;
+
+namespace Neo.Network.RPC.Models
+{
+ public class RpcPeers
+ {
+ public RpcPeer[] Unconnected { get; set; }
+
+ public RpcPeer[] Bad { get; set; }
+
+ public RpcPeer[] Connected { get; set; }
+
+ public JObject ToJson()
+ {
+ JObject json = new JObject();
+ json["unconnected"] = new JArray(Unconnected.Select(p => p.ToJson()));
+ json["bad"] = new JArray(Bad.Select(p => p.ToJson()));
+ json["connected"] = new JArray(Connected.Select(p => p.ToJson()));
+ return json;
+ }
+
+ public static RpcPeers FromJson(JObject json)
+ {
+ RpcPeers result = new RpcPeers();
+ result.Unconnected = ((JArray)json["unconnected"]).Select(p => RpcPeer.FromJson(p)).ToArray();
+ result.Bad = ((JArray)json["bad"]).Select(p => RpcPeer.FromJson(p)).ToArray();
+ result.Connected = ((JArray)json["connected"]).Select(p => RpcPeer.FromJson(p)).ToArray();
+ return result;
+ }
+ }
+
+ public class RpcPeer
+ {
+ public string Address { get; set; }
+
+ public int Port { get; set; }
+
+ public JObject ToJson()
+ {
+ JObject json = new JObject();
+ json["address"] = Address;
+ json["port"] = Port;
+ return json;
+ }
+
+ public static RpcPeer FromJson(JObject json)
+ {
+ RpcPeer peer = new RpcPeer();
+ peer.Address = json["address"].AsString();
+ peer.Port = int.Parse(json["port"].AsString());
+ return peer;
+ }
+ }
+}
diff --git a/neo/Network/RPC/Models/RpcPlugin.cs b/neo/Network/RPC/Models/RpcPlugin.cs
new file mode 100644
index 0000000000..465b3f2d17
--- /dev/null
+++ b/neo/Network/RPC/Models/RpcPlugin.cs
@@ -0,0 +1,32 @@
+using Neo.IO.Json;
+using System.Linq;
+
+namespace Neo.Network.RPC.Models
+{
+ public class RpcPlugin
+ {
+ public string Name { get; set; }
+
+ public string Version { get; set; }
+
+ public string[] Interfaces { get; set; }
+
+ public JObject ToJson()
+ {
+ JObject json = new JObject();
+ json["name"] = Name;
+ json["version"] = Version;
+ json["interfaces"] = new JArray(Interfaces.Select(p => (JObject)p));
+ return json;
+ }
+
+ public static RpcPlugin FromJson(JObject json)
+ {
+ RpcPlugin plugin = new RpcPlugin();
+ plugin.Name = json["name"].AsString();
+ plugin.Version = json["version"].AsString();
+ plugin.Interfaces = ((JArray)json["interfaces"]).Select(p => p.AsString()).ToArray();
+ return plugin;
+ }
+ }
+}
diff --git a/neo/Network/RPC/Models/RpcRawMemPool.cs b/neo/Network/RPC/Models/RpcRawMemPool.cs
new file mode 100644
index 0000000000..1841916ff2
--- /dev/null
+++ b/neo/Network/RPC/Models/RpcRawMemPool.cs
@@ -0,0 +1,32 @@
+using Neo.IO.Json;
+using System.Linq;
+
+namespace Neo.Network.RPC.Models
+{
+ public class RpcRawMemPool
+ {
+ public uint Height { get; set; }
+
+ public string[] Verified { get; set; }
+
+ public string[] UnVerified { get; set; }
+
+ public JObject ToJson()
+ {
+ JObject json = new JObject();
+ json["height"] = Height;
+ json["verified"] = new JArray(Verified.Select(p=>(JObject)p));
+ json["unverified"] = new JArray(UnVerified.Select(p => (JObject)p));
+ return json;
+ }
+
+ public static RpcRawMemPool FromJson(JObject json)
+ {
+ RpcRawMemPool rawMemPool = new RpcRawMemPool();
+ rawMemPool.Height = uint.Parse(json["height"].AsString());
+ rawMemPool.Verified = ((JArray)json["verified"]).Select(p => p.AsString()).ToArray();
+ rawMemPool.UnVerified = ((JArray)json["unverified"]).Select(p => p.AsString()).ToArray();
+ return rawMemPool;
+ }
+ }
+}
diff --git a/neo/Network/RPC/Models/RpcRequest.cs b/neo/Network/RPC/Models/RpcRequest.cs
new file mode 100644
index 0000000000..9c2d2f05ec
--- /dev/null
+++ b/neo/Network/RPC/Models/RpcRequest.cs
@@ -0,0 +1,37 @@
+using Neo.IO.Json;
+using System.Linq;
+
+namespace Neo.Network.RPC.Models
+{
+ public class RpcRequest
+ {
+ public int Id { get; set; }
+
+ public string Jsonrpc { get; set; }
+
+ public string Method { get; set; }
+
+ public JObject[] Params { get; set; }
+
+ public static RpcRequest FromJson(JObject json)
+ {
+ return new RpcRequest
+ {
+ Id = (int)json["id"].AsNumber(),
+ Jsonrpc = json["jsonrpc"].AsString(),
+ Method = json["method"].AsString(),
+ Params = ((JArray)json["params"]).ToArray()
+ };
+ }
+
+ public JObject ToJson()
+ {
+ var json = new JObject();
+ json["id"] = Id;
+ json["jsonrpc"] = Jsonrpc;
+ json["method"] = Method;
+ json["params"] = new JArray(Params);
+ return json;
+ }
+ }
+}
diff --git a/neo/Network/RPC/Models/RpcResponse.cs b/neo/Network/RPC/Models/RpcResponse.cs
new file mode 100644
index 0000000000..ff20200519
--- /dev/null
+++ b/neo/Network/RPC/Models/RpcResponse.cs
@@ -0,0 +1,72 @@
+using Neo.IO.Json;
+
+namespace Neo.Network.RPC.Models
+{
+ public class RpcResponse
+ {
+ public int? Id { get; set; }
+
+ public string Jsonrpc { get; set; }
+
+ public RpcResponseError Error { get; set; }
+
+ public JObject Result { get; set; }
+
+ public string RawResponse { get; set; }
+
+ public static RpcResponse FromJson(JObject json)
+ {
+ var response = new RpcResponse
+ {
+ Id = (int?)json["id"]?.AsNumber(),
+ Jsonrpc = json["jsonrpc"].AsString(),
+ Result = json["result"]
+ };
+
+ if (json["error"] != null)
+ {
+ response.Error = RpcResponseError.FromJson(json["error"]);
+ }
+
+ return response;
+ }
+
+ public JObject ToJson()
+ {
+ var json = new JObject();
+ json["id"] = Id;
+ json["jsonrpc"] = Jsonrpc;
+ json["error"] = Error.ToJson();
+ json["result"] = Result;
+ return json;
+ }
+ }
+
+ public class RpcResponseError
+ {
+ public int Code { get; set; }
+
+ public string Message { get; set; }
+
+ public JObject Data { get; set; }
+
+ public static RpcResponseError FromJson(JObject json)
+ {
+ return new RpcResponseError
+ {
+ Code = (int)json["code"].AsNumber(),
+ Message = json["message"].AsString(),
+ Data = json["data"],
+ };
+ }
+
+ public JObject ToJson()
+ {
+ var json = new JObject();
+ json["code"] = Code;
+ json["message"] = Message;
+ json["data"] = Data;
+ return json;
+ }
+ }
+}
diff --git a/neo/Network/RPC/Models/RpcTransaction.cs b/neo/Network/RPC/Models/RpcTransaction.cs
new file mode 100644
index 0000000000..3e45830ae6
--- /dev/null
+++ b/neo/Network/RPC/Models/RpcTransaction.cs
@@ -0,0 +1,41 @@
+using Neo.IO.Json;
+using Neo.Network.P2P.Payloads;
+
+namespace Neo.Network.RPC.Models
+{
+ public class RpcTransaction
+ {
+ public Transaction Transaction { get; set; }
+
+ public UInt256 BlockHash { get; set; }
+
+ public int? Confirmations { get; set; }
+
+ public uint? BlockTime { get; set; }
+
+ public JObject ToJson()
+ {
+ JObject json = Transaction.ToJson();
+ if (Confirmations != null)
+ {
+ json["blockhash"] = BlockHash.ToString();
+ json["confirmations"] = Confirmations;
+ json["blocktime"] = BlockTime;
+ }
+ return json;
+ }
+
+ public static RpcTransaction FromJson(JObject json)
+ {
+ RpcTransaction transaction = new RpcTransaction();
+ transaction.Transaction = Transaction.FromJson(json);
+ if (json["confirmations"] != null)
+ {
+ transaction.BlockHash = UInt256.Parse(json["blockhash"].AsString());
+ transaction.Confirmations = (int)json["confirmations"].AsNumber();
+ transaction.BlockTime = (uint)json["blocktime"].AsNumber();
+ }
+ return transaction;
+ }
+ }
+}
diff --git a/neo/Network/RPC/Models/RpcValidateAddressResult.cs b/neo/Network/RPC/Models/RpcValidateAddressResult.cs
new file mode 100644
index 0000000000..5e59bf8eaf
--- /dev/null
+++ b/neo/Network/RPC/Models/RpcValidateAddressResult.cs
@@ -0,0 +1,27 @@
+using Neo.IO.Json;
+
+namespace Neo.Network.RPC.Models
+{
+ public class RpcValidateAddressResult
+ {
+ public string Address { get; set; }
+
+ public bool IsValid { get; set; }
+
+ public JObject ToJson()
+ {
+ JObject json = new JObject();
+ json["address"] = Address;
+ json["isvalid"] = IsValid;
+ return json;
+ }
+
+ public static RpcValidateAddressResult FromJson(JObject json)
+ {
+ RpcValidateAddressResult validateAddress = new RpcValidateAddressResult();
+ validateAddress.Address = json["address"].AsString();
+ validateAddress.IsValid = json["isvalid"].AsBoolean();
+ return validateAddress;
+ }
+ }
+}
diff --git a/neo/Network/RPC/Models/RpcValidator.cs b/neo/Network/RPC/Models/RpcValidator.cs
new file mode 100644
index 0000000000..b694a6dfcd
--- /dev/null
+++ b/neo/Network/RPC/Models/RpcValidator.cs
@@ -0,0 +1,32 @@
+using Neo.IO.Json;
+using System.Numerics;
+
+namespace Neo.Network.RPC.Models
+{
+ public class RpcValidator
+ {
+ public string PublicKey { get; set; }
+
+ public BigInteger Votes { get; set; }
+
+ public bool Active { get; set; }
+
+ public JObject ToJson()
+ {
+ JObject json = new JObject();
+ json["publickey"] = PublicKey;
+ json["votes"] = Votes.ToString();
+ json["active"] = Active;
+ return json;
+ }
+
+ public static RpcValidator FromJson(JObject json)
+ {
+ RpcValidator validator = new RpcValidator();
+ validator.PublicKey = json["publickey"].AsString();
+ validator.Votes = BigInteger.Parse(json["votes"].AsString());
+ validator.Active = json["active"].AsBoolean();
+ return validator;
+ }
+ }
+}
diff --git a/neo/Network/RPC/Models/RpcVersion.cs b/neo/Network/RPC/Models/RpcVersion.cs
new file mode 100644
index 0000000000..02f4dc3407
--- /dev/null
+++ b/neo/Network/RPC/Models/RpcVersion.cs
@@ -0,0 +1,35 @@
+using Neo.IO.Json;
+
+namespace Neo.Network.RPC.Models
+{
+ public class RpcVersion
+ {
+ public int TcpPort { get; set; }
+
+ public int WsPort { get; set; }
+
+ public uint Nonce { get; set; }
+
+ public string UserAgent { get; set; }
+
+ public JObject ToJson()
+ {
+ JObject json = new JObject();
+ json["topPort"] = TcpPort.ToString();
+ json["wsPort"] = WsPort.ToString();
+ json["nonce"] = Nonce.ToString();
+ json["useragent"] = UserAgent;
+ return json;
+ }
+
+ public static RpcVersion FromJson(JObject json)
+ {
+ RpcVersion version = new RpcVersion();
+ version.TcpPort = int.Parse(json["tcpPort"].AsString());
+ version.WsPort = int.Parse(json["wsPort"].AsString());
+ version.Nonce = uint.Parse(json["nonce"].AsString());
+ version.UserAgent = json["useragent"].AsString();
+ return version;
+ }
+ }
+}
diff --git a/neo/Network/RPC/RpcClient.cs b/neo/Network/RPC/RpcClient.cs
new file mode 100644
index 0000000000..4b968163c7
--- /dev/null
+++ b/neo/Network/RPC/RpcClient.cs
@@ -0,0 +1,292 @@
+using Neo.IO.Json;
+using Neo.Ledger;
+using Neo.Network.RPC.Models;
+using System;
+using System.Linq;
+using System.Net.Http;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Neo.Network.RPC
+{
+ public class RpcClient : IDisposable
+ {
+ private readonly HttpClient httpClient;
+
+ public RpcClient(string url)
+ {
+ httpClient = new HttpClient() { BaseAddress = new Uri(url) };
+ }
+
+ public RpcClient(HttpClient client)
+ {
+ httpClient = client;
+ }
+
+ public void Dispose()
+ {
+ httpClient?.Dispose();
+ }
+
+ public async Task SendAsync(RpcRequest request)
+ {
+ var requestJson = request.ToJson().ToString();
+ var result = await httpClient.PostAsync(httpClient.BaseAddress, new StringContent(requestJson, Encoding.UTF8));
+ var content = await result.Content.ReadAsStringAsync();
+ var response = RpcResponse.FromJson(JObject.Parse(content));
+ response.RawResponse = content;
+
+ if (response.Error != null)
+ {
+ throw new RpcException(response.Error.Code, response.Error.Message);
+ }
+
+ return response;
+ }
+
+ public RpcResponse Send(RpcRequest request)
+ {
+ try
+ {
+ return SendAsync(request).Result;
+ }
+ catch (AggregateException ex)
+ {
+ throw ex.GetBaseException();
+ }
+ }
+
+ private JObject RpcSend(string method, params JObject[] paraArgs)
+ {
+ var request = new RpcRequest
+ {
+ Id = 1,
+ Jsonrpc = "2.0",
+ Method = method,
+ Params = paraArgs.Select(p => p).ToArray()
+ };
+ return Send(request).Result;
+ }
+
+ ///
+ /// Returns the hash of the tallest block in the main chain.
+ ///
+ public string GetBestBlockHash()
+ {
+ return RpcSend("getbestblockhash").AsString();
+ }
+
+ ///
+ /// Returns the hash of the tallest block in the main chain.
+ /// The serialized information of the block is returned, represented by a hexadecimal string.
+ ///
+ public string GetBlockHex(string hashOrIndex)
+ {
+ if (int.TryParse(hashOrIndex, out int index))
+ {
+ return RpcSend("getblock", index).AsString();
+ }
+ return RpcSend("getblock", hashOrIndex).AsString();
+ }
+
+ ///
+ /// Returns the hash of the tallest block in the main chain.
+ ///
+ public RpcBlock GetBlock(string hashOrIndex)
+ {
+ if (int.TryParse(hashOrIndex, out int index))
+ {
+ return RpcBlock.FromJson(RpcSend("getblock", index, true));
+ }
+ return RpcBlock.FromJson(RpcSend("getblock", hashOrIndex, true));
+ }
+
+ ///
+ /// Gets the number of blocks in the main chain.
+ ///
+ public int GetBlockCount()
+ {
+ return (int)RpcSend("getblockcount").AsNumber();
+ }
+
+ ///
+ /// Returns the hash value of the corresponding block, based on the specified index.
+ ///
+ public string GetBlockHash(int index)
+ {
+ return RpcSend("getblockhash", index).AsString();
+ }
+
+ ///
+ /// Returns the corresponding block header information according to the specified script hash.
+ ///
+ public string GetBlockHeaderHex(string hashOrIndex)
+ {
+ if (int.TryParse(hashOrIndex, out int index))
+ {
+ return RpcSend("getblockheader", index).AsString();
+ }
+ return RpcSend("getblockheader", hashOrIndex).AsString();
+ }
+
+ ///
+ /// Returns the corresponding block header information according to the specified script hash.
+ ///
+ public RpcBlockHeader GetBlockHeader(string hashOrIndex)
+ {
+ if (int.TryParse(hashOrIndex, out int index))
+ {
+ return RpcBlockHeader.FromJson(RpcSend("getblockheader", index, true));
+ }
+ return RpcBlockHeader.FromJson(RpcSend("getblockheader", hashOrIndex, true));
+ }
+
+ ///
+ /// Returns the system fees of the block, based on the specified index.
+ ///
+ public string GetBlockSysFee(int height)
+ {
+ return RpcSend("getblocksysfee", height).AsString();
+ }
+
+ ///
+ /// Gets the current number of connections for the node.
+ ///
+ public int GetConnectionCount()
+ {
+ return (int)RpcSend("getconnectioncount").AsNumber();
+ }
+
+ ///
+ /// Queries contract information, according to the contract script hash.
+ ///
+ public ContractState GetContractState(string hash)
+ {
+ return ContractState.FromJson(RpcSend("getcontractstate", hash));
+ }
+
+ ///
+ /// Gets the list of nodes that the node is currently connected/disconnected from.
+ ///
+ public RpcPeers GetPeers()
+ {
+ return RpcPeers.FromJson(RpcSend("getpeers"));
+ }
+
+ ///
+ /// Obtains the list of unconfirmed transactions in memory.
+ ///
+ public string[] GetRawMempool()
+ {
+ return ((JArray)RpcSend("getrawmempool")).Select(p => p.AsString()).ToArray();
+ }
+
+ ///
+ /// Obtains the list of unconfirmed transactions in memory.
+ /// shouldGetUnverified = true
+ ///
+ public RpcRawMemPool GetRawMempoolBoth()
+ {
+ return RpcRawMemPool.FromJson(RpcSend("getrawmempool"));
+ }
+
+ ///
+ /// Returns the corresponding transaction information, based on the specified hash value.
+ ///
+ public string GetRawTransactionHex(string txid)
+ {
+ return RpcSend("getrawtransaction", txid).AsString();
+ }
+
+ ///
+ /// Returns the corresponding transaction information, based on the specified hash value.
+ /// verbose = true
+ ///
+ public RpcTransaction GetRawTransaction(string txid)
+ {
+ return RpcTransaction.FromJson(RpcSend("getrawtransaction", txid, true));
+ }
+
+ ///
+ /// Returns the stored value, according to the contract script hash and the stored key.
+ ///
+ public string GetStorage(string script_hash, string key)
+ {
+ return RpcSend("getstorage", script_hash, key).AsString();
+ }
+
+ ///
+ /// Returns the block index in which the transaction is found.
+ ///
+ public uint GetTransactionHeight(string txid)
+ {
+ return uint.Parse(RpcSend("gettransactionheight", txid).AsString());
+ }
+
+ ///
+ /// Returns the current NEO consensus nodes information and voting status.
+ ///
+ public RpcValidator[] GetValidators()
+ {
+ return ((JArray)RpcSend("getvalidators")).Select(p => RpcValidator.FromJson(p)).ToArray();
+ }
+
+ ///
+ /// Returns the version information about the queried node.
+ ///
+ public RpcVersion GetVersion()
+ {
+ return RpcVersion.FromJson(RpcSend("getversion"));
+ }
+
+ ///
+ /// Returns the result after calling a smart contract at scripthash with the given operation and parameters.
+ /// This RPC call does not affect the blockchain in any way.
+ ///
+ public RpcInvokeResult InvokeFunction(string address, string function, RpcStack[] stacks)
+ {
+ return RpcInvokeResult.FromJson(RpcSend("invokefunction", address, function, stacks.Select(p => p.ToJson()).ToArray()));
+ }
+
+ ///
+ /// Returns the result after passing a script through the VM.
+ /// This RPC call does not affect the blockchain in any way.
+ ///
+ public RpcInvokeResult InvokeScript(string script)
+ {
+ return RpcInvokeResult.FromJson(RpcSend("invokescript", script));
+ }
+
+ ///
+ /// Returns a list of plugins loaded by the node.
+ ///
+ public RpcPlugin[] ListPlugins()
+ {
+ return ((JArray)RpcSend("listplugins")).Select(p => RpcPlugin.FromJson(p)).ToArray();
+ }
+
+ ///
+ /// Broadcasts a transaction over the NEO network.
+ ///
+ public bool SendRawTransaction(string rawTransaction)
+ {
+ return RpcSend("sendrawtransaction", rawTransaction).AsBoolean();
+ }
+
+ ///
+ /// Broadcasts a raw block over the NEO network.
+ ///
+ public bool SubmitBlock(string block)
+ {
+ return RpcSend("submitblock", block).AsBoolean();
+ }
+
+ ///
+ /// Verifies that the address is a correct NEO address.
+ ///
+ public RpcValidateAddressResult ValidateAddress(string address)
+ {
+ return RpcValidateAddressResult.FromJson(RpcSend("validateaddress", address));
+ }
+ }
+}
From 0f1bb13968055e727b2e3224df6f382263edeec0 Mon Sep 17 00:00:00 2001
From: Erik Zhang
Date: Wed, 31 Jul 2019 20:29:24 +0800
Subject: [PATCH 060/305] Remove `IPolicyPlugin` (#971)
---
neo/Consensus/ConsensusContext.cs | 8 +++-----
neo/Consensus/ConsensusService.cs | 3 ++-
neo/Ledger/Blockchain.cs | 4 ++--
neo/Plugins/IPolicyPlugin.cs | 11 -----------
neo/Plugins/Plugin.cs | 11 -----------
neo/SmartContract/Native/PolicyContract.cs | 9 +++++++++
6 files changed, 16 insertions(+), 30 deletions(-)
delete mode 100644 neo/Plugins/IPolicyPlugin.cs
diff --git a/neo/Consensus/ConsensusContext.cs b/neo/Consensus/ConsensusContext.cs
index 270536fc89..ba7edf66c5 100644
--- a/neo/Consensus/ConsensusContext.cs
+++ b/neo/Consensus/ConsensusContext.cs
@@ -4,7 +4,6 @@
using Neo.Ledger;
using Neo.Network.P2P.Payloads;
using Neo.Persistence;
-using Neo.Plugins;
using Neo.SmartContract;
using Neo.SmartContract.Native;
using Neo.Wallets;
@@ -210,10 +209,9 @@ public ConsensusPayload MakePrepareRequest()
{
byte[] buffer = new byte[sizeof(ulong)];
random.NextBytes(buffer);
- IEnumerable memoryPoolTransactions = Blockchain.Singleton.MemPool.GetSortedVerifiedTransactions();
- foreach (IPolicyPlugin plugin in Plugin.Policies)
- memoryPoolTransactions = plugin.FilterForBlock(memoryPoolTransactions);
- List transactions = memoryPoolTransactions.ToList();
+ List transactions = Blockchain.Singleton.MemPool.GetSortedVerifiedTransactions()
+ .Take((int)NativeContract.Policy.GetMaxTransactionsPerBlock(Snapshot))
+ .ToList();
TransactionHashes = transactions.Select(p => p.Hash).ToArray();
Transactions = transactions.ToDictionary(p => p.Hash);
Block.Timestamp = Math.Max(TimeProvider.Current.UtcNow.ToTimestampMS(), PrevHeader.Timestamp + 1);
diff --git a/neo/Consensus/ConsensusService.cs b/neo/Consensus/ConsensusService.cs
index 2e850807e4..08cf41e8b9 100644
--- a/neo/Consensus/ConsensusService.cs
+++ b/neo/Consensus/ConsensusService.cs
@@ -8,6 +8,7 @@
using Neo.Network.P2P.Payloads;
using Neo.Persistence;
using Neo.Plugins;
+using Neo.SmartContract.Native;
using Neo.Wallets;
using System;
using System.Collections.Generic;
@@ -66,7 +67,7 @@ private bool AddTransaction(Transaction tx, bool verify)
RequestChangeView(ChangeViewReason.TxInvalid);
return false;
}
- if (!Plugin.CheckPolicy(tx))
+ if (!NativeContract.Policy.CheckPolicy(tx, context.Snapshot))
{
Log($"reject tx: {tx.Hash}{Environment.NewLine}{tx.ToArray().ToHexString()}", LogLevel.Warning);
RequestChangeView(ChangeViewReason.TxRejectedByPolicy);
diff --git a/neo/Ledger/Blockchain.cs b/neo/Ledger/Blockchain.cs
index ee8e114701..663d142d62 100644
--- a/neo/Ledger/Blockchain.cs
+++ b/neo/Ledger/Blockchain.cs
@@ -228,7 +228,7 @@ private void OnFillMemoryPool(IEnumerable transactions)
{
if (Store.ContainsTransaction(tx.Hash))
continue;
- if (!Plugin.CheckPolicy(tx))
+ if (!NativeContract.Policy.CheckPolicy(tx, currentSnapshot))
continue;
// First remove the tx if it is unverified in the pool.
MemPool.TryRemoveUnVerified(tx.Hash, out _);
@@ -361,7 +361,7 @@ private RelayResultReason OnNewTransaction(Transaction transaction)
return RelayResultReason.OutOfMemory;
if (!transaction.Verify(currentSnapshot, MemPool.GetVerifiedTransactions()))
return RelayResultReason.Invalid;
- if (!Plugin.CheckPolicy(transaction))
+ if (!NativeContract.Policy.CheckPolicy(transaction, currentSnapshot))
return RelayResultReason.PolicyFail;
if (!MemPool.TryAdd(transaction.Hash, transaction))
diff --git a/neo/Plugins/IPolicyPlugin.cs b/neo/Plugins/IPolicyPlugin.cs
deleted file mode 100644
index 812d418ee2..0000000000
--- a/neo/Plugins/IPolicyPlugin.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using Neo.Network.P2P.Payloads;
-using System.Collections.Generic;
-
-namespace Neo.Plugins
-{
- public interface IPolicyPlugin
- {
- bool FilterForMemoryPool(Transaction tx);
- IEnumerable FilterForBlock(IEnumerable transactions);
- }
-}
diff --git a/neo/Plugins/Plugin.cs b/neo/Plugins/Plugin.cs
index 862ff6ae9a..72c7ce3b14 100644
--- a/neo/Plugins/Plugin.cs
+++ b/neo/Plugins/Plugin.cs
@@ -1,5 +1,4 @@
using Microsoft.Extensions.Configuration;
-using Neo.Network.P2P.Payloads;
using System;
using System.Collections.Generic;
using System.IO;
@@ -13,7 +12,6 @@ public abstract class Plugin
{
public static readonly List Plugins = new List();
private static readonly List Loggers = new List();
- internal static readonly List