diff --git a/neo.UnitTests/SDK/UT_RpcClient.cs b/neo.UnitTests/SDK/UT_RpcClient.cs index 91ec682af5..e76d8d3e2b 100644 --- a/neo.UnitTests/SDK/UT_RpcClient.cs +++ b/neo.UnitTests/SDK/UT_RpcClient.cs @@ -438,7 +438,7 @@ public void TestInvokeFunction() response["result"] = json; MockResponse(response.ToString()); - var result = rpc.InvokeFunction("af7c7328eee5a275a3bcaee2bf0cf662b5e739be", "balanceOf", new[] { new SDK_StackJson { Type = "Hash160", Value = "91b83e96f2a7c4fdf0c1688441ec61986c7cae26" } }); + var result = rpc.InvokeFunction("af7c7328eee5a275a3bcaee2bf0cf662b5e739be", "balanceOf", new[] { new SDK_Stack { Type = "Hash160", Value = "91b83e96f2a7c4fdf0c1688441ec61986c7cae26" } }); Assert.AreEqual(json.ToString(), result.ToJson().ToString()); } 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.UnitTests/UT_Transaction.cs b/neo.UnitTests/UT_Transaction.cs index 18aafb31bb..5b06a816a5 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(() => walletB.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 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/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; } 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(); } diff --git a/neo/Network/P2P/Payloads/Block.cs b/neo/Network/P2P/Payloads/Block.cs index f83a3b6093..b5fe689059 100644 --- a/neo/Network/P2P/Payloads/Block.cs +++ b/neo/Network/P2P/Payloads/Block.cs @@ -107,10 +107,10 @@ public override JObject ToJson() return json; } - public static Block FromJson(JObject json) + public new static Block FromJson(JObject json) { Block block = new Block(); - block.PraseFromJson(json); + (block as BlockBase).FromJson(json); block.ConsensusData = ConsensusData.FromJson(json["consensus_data"]); block.Transactions = ((JArray)json["tx"]).Select(p => Transaction.FromJson(p)).ToArray(); return block; diff --git a/neo/Network/P2P/Payloads/BlockBase.cs b/neo/Network/P2P/Payloads/BlockBase.cs index 8fe545115c..b2b1bf3d67 100644 --- a/neo/Network/P2P/Payloads/BlockBase.cs +++ b/neo/Network/P2P/Payloads/BlockBase.cs @@ -104,7 +104,7 @@ public virtual JObject ToJson() return json; } - public void PraseFromJson(JObject json) + public void FromJson(JObject json) { Version = (uint)json["version"].AsNumber(); PrevHash = UInt256.Parse(json["previousblockhash"].AsString()); diff --git a/neo/Network/P2P/Payloads/Header.cs b/neo/Network/P2P/Payloads/Header.cs index e32b1a5daa..52639ee1fb 100644 --- a/neo/Network/P2P/Payloads/Header.cs +++ b/neo/Network/P2P/Payloads/Header.cs @@ -55,10 +55,10 @@ public TrimmedBlock Trim() }; } - public static Header FromJson(JObject json) + public new static Header FromJson(JObject json) { Header header = new Header(); - header.PraseFromJson(json); + (header as BlockBase).FromJson(json); return header; } diff --git a/neo/SDK/RPC/HttpService.cs b/neo/SDK/RPC/HttpService.cs index 7f5df397a7..6fa7069413 100644 --- a/neo/SDK/RPC/HttpService.cs +++ b/neo/SDK/RPC/HttpService.cs @@ -26,22 +26,23 @@ public void Dispose() httpClient?.Dispose(); } - public async Task SendAsync(RPCRequest request) + 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 NeoSdkException(response.Error.Code, response.Error.Message, response.Error.Data); } - return response.Result; + return response; } - public JObject Send(RPCRequest request) + public RPCResponse Send(RPCRequest request) { try { diff --git a/neo/SDK/RPC/IRpcClient.cs b/neo/SDK/RPC/IRpcClient.cs index f62367cba4..a05afeb362 100644 --- a/neo/SDK/RPC/IRpcClient.cs +++ b/neo/SDK/RPC/IRpcClient.cs @@ -114,7 +114,7 @@ public interface IRpcClient /// 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. /// - SDK_InvokeScriptResult InvokeFunction(string address, string function, SDK_StackJson[] stacks); + SDK_InvokeScriptResult InvokeFunction(string address, string function, SDK_Stack[] stacks); /// /// Returns the result after passing a script through the VM. @@ -141,11 +141,6 @@ public interface IRpcClient /// Verifies that the address is a correct NEO address. /// SDK_ValidateAddressResult ValidateAddress(string address); - - /// - /// Returns the balance of all NEP-5 assets in the specified address. - /// - SDK_Nep5Balances GetNep5Balances(string address); - + } } diff --git a/neo/SDK/RPC/Model/RPCResponse.cs b/neo/SDK/RPC/Model/RPCResponse.cs index 402820f085..972e3bf829 100644 --- a/neo/SDK/RPC/Model/RPCResponse.cs +++ b/neo/SDK/RPC/Model/RPCResponse.cs @@ -8,13 +8,15 @@ namespace Neo.SDK.RPC.Model 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; } + /// /// Parse from json /// @@ -49,9 +51,9 @@ public JObject ToJson() public class RPCResponseError { public int Code { get; set; } - + public string Message { get; set; } - + public JObject Data { get; set; } /// diff --git a/neo/SDK/RPC/Model/SDK_InvokeScriptResult.cs b/neo/SDK/RPC/Model/SDK_InvokeScriptResult.cs index f24d5f1842..8d7ad87464 100644 --- a/neo/SDK/RPC/Model/SDK_InvokeScriptResult.cs +++ b/neo/SDK/RPC/Model/SDK_InvokeScriptResult.cs @@ -16,7 +16,7 @@ public class SDK_InvokeScriptResult public string GasConsumed { get; set; } [JsonProperty(PropertyName = "stack")] - public SDK_StackJson[] Stack { get; set; } + public SDK_Stack[] Stack { get; set; } [JsonProperty(PropertyName = "tx")] public string Tx { get; set; } @@ -39,12 +39,12 @@ public static SDK_InvokeScriptResult FromJson(JObject json) invokeScriptResult.State = json["state"].AsString(); invokeScriptResult.GasConsumed = json["gas_consumed"].AsString(); invokeScriptResult.Tx = json["tx"].AsString(); - invokeScriptResult.Stack = ((JArray)json["stack"]).Select(p => SDK_StackJson.FromJson(p)).ToArray(); + invokeScriptResult.Stack = ((JArray)json["stack"]).Select(p => SDK_Stack.FromJson(p)).ToArray(); return invokeScriptResult; } } - public class SDK_StackJson + public class SDK_Stack { public string Type { get; set; } @@ -58,9 +58,9 @@ public JObject ToJson() return json; } - public static SDK_StackJson FromJson(JObject json) + public static SDK_Stack FromJson(JObject json) { - SDK_StackJson stackJson = new SDK_StackJson(); + SDK_Stack stackJson = new SDK_Stack(); stackJson.Type = json["type"].AsString(); stackJson.Value = json["value"].AsString(); return stackJson; diff --git a/neo/SDK/RPC/RpcClient.cs b/neo/SDK/RPC/RpcClient.cs index 1d9ef4ef55..ed35c69fb7 100644 --- a/neo/SDK/RPC/RpcClient.cs +++ b/neo/SDK/RPC/RpcClient.cs @@ -33,7 +33,7 @@ private JObject RpcSend(string method, params JObject[] paraArgs) Method = method, Params = paraArgs.Select(p => p).ToArray() }; - return rpcHelper.Send(request); + return rpcHelper.Send(request).Result; } public string GetBestBlockHash() @@ -148,7 +148,7 @@ public SDK_Version GetVersion() return SDK_Version.FromJson(RpcSend("getversion")); } - public SDK_InvokeScriptResult InvokeFunction(string address, string function, SDK_StackJson[] stacks) + public SDK_InvokeScriptResult InvokeFunction(string address, string function, SDK_Stack[] stacks) { return SDK_InvokeScriptResult.FromJson(RpcSend("invokefunction", address, function, stacks.Select(p => p.ToJson()).ToArray())); } @@ -178,10 +178,5 @@ public SDK_ValidateAddressResult ValidateAddress(string address) return SDK_ValidateAddressResult.FromJson(RpcSend("validateaddress", address)); } - public SDK_Nep5Balances GetNep5Balances(string address) - { - return SDK_Nep5Balances.FromJson(RpcSend("getnep5balances", address)); - } - } } 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;