diff --git a/src/Neo/Network/P2P/Peer.cs b/src/Neo/Network/P2P/Peer.cs index 074c5cf3ba..bf6b23901f 100644 --- a/src/Neo/Network/P2P/Peer.cs +++ b/src/Neo/Network/P2P/Peer.cs @@ -146,7 +146,7 @@ static Peer() /// Tries to add a set of peers to the immutable ImmutableHashSet of UnconnectedPeers. /// /// Peers that the method will try to add (union) to (with) UnconnectedPeers. - protected void AddPeers(IEnumerable peers) + protected internal void AddPeers(IEnumerable peers) { if (UnconnectedPeers.Count < UnconnectedMax) { diff --git a/src/Plugins/RpcServer/RpcServer.Node.cs b/src/Plugins/RpcServer/RpcServer.Node.cs index 716125e2cf..c1b5397c5b 100644 --- a/src/Plugins/RpcServer/RpcServer.Node.cs +++ b/src/Plugins/RpcServer/RpcServer.Node.cs @@ -24,13 +24,13 @@ namespace Neo.Plugins.RpcServer partial class RpcServer { [RpcMethod] - protected virtual JToken GetConnectionCount(JArray _params) + protected internal virtual JToken GetConnectionCount(JArray _params) { return localNode.ConnectedCount; } [RpcMethod] - protected virtual JToken GetPeers(JArray _params) + protected internal virtual JToken GetPeers(JArray _params) { JObject json = new(); json["unconnected"] = new JArray(localNode.GetUnconnectedPeers().Select(p => diff --git a/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Blockchain.cs b/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Blockchain.cs index 2fbb2f6f3f..b04b5e33d4 100644 --- a/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Blockchain.cs +++ b/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Blockchain.cs @@ -11,7 +11,9 @@ using Akka.Actor; using Akka.Util.Internal; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography.ECC; using Neo.IO; using Neo.Json; using Neo.Ledger; @@ -23,6 +25,8 @@ using Neo.UnitTests.Extensions; using System; using System.Linq; +using System.Security.Policy; +using static Neo.SmartContract.Native.NeoToken; namespace Neo.Plugins.RpcServer.Tests { @@ -61,6 +65,11 @@ public void TestGetBlockByHash() { Assert.AreEqual(VerifyResult.Succeed, tx.VerifyStateIndependent(UnitTests.TestProtocolSettings.Default)); }); + + result = _rpcServer.GetBlock(new BlockHashOrIndex(block.Hash), true); + var block3 = block.ToJson(UnitTests.TestProtocolSettings.Default); + block3["confirmations"] = NativeContract.Ledger.CurrentIndex(snapshot) - block.Index + 1; + result.ToString().Should().Be(block3.ToString()); } [TestMethod] @@ -78,6 +87,11 @@ public void TestGetBlockByIndex() { Assert.AreEqual(VerifyResult.Succeed, tx.VerifyStateIndependent(UnitTests.TestProtocolSettings.Default)); }); + + result = _rpcServer.GetBlock(new BlockHashOrIndex(block.Index), true); + var block3 = block.ToJson(UnitTests.TestProtocolSettings.Default); + block3["confirmations"] = NativeContract.Ledger.CurrentIndex(snapshot) - block.Index + 1; + result.ToString().Should().Be(block3.ToString()); } [TestMethod] @@ -120,6 +134,11 @@ public void TestGetBlockHeader() var header = block.Header.ToJson(_neoSystem.Settings); header["confirmations"] = NativeContract.Ledger.CurrentIndex(snapshot) - block.Index + 1; Assert.AreEqual(header.ToString(), result.ToString()); + + result = _rpcServer.GetBlockHeader(new BlockHashOrIndex(block.Hash), false); + var headerArr = Convert.FromBase64String(result.AsString()); + var header2 = headerArr.AsSerializable
(); + header2.ToJson(_neoSystem.Settings).ToString().Should().Be(block.Header.ToJson(_neoSystem.Settings).ToString()); } [TestMethod] @@ -129,9 +148,23 @@ public void TestGetContractState() var contractState = TestUtils.GetContract(); snapshot.AddContract(contractState.Hash, contractState); snapshot.Commit(); + var result = _rpcServer.GetContractState(new ContractNameOrHashOrId(contractState.Hash)); + Assert.AreEqual(contractState.ToJson().ToString(), result.ToString()); + result = _rpcServer.GetContractState(new ContractNameOrHashOrId(contractState.Id)); Assert.AreEqual(contractState.ToJson().ToString(), result.ToString()); + + var byId = _rpcServer.GetContractState(new ContractNameOrHashOrId(-1)); + var byName = _rpcServer.GetContractState(new ContractNameOrHashOrId("ContractManagement")); + byId.ToString().Should().Be(byName.ToString()); + + snapshot.DeleteContract(contractState.Hash); + snapshot.Commit(); + Action act = () => _rpcServer.GetContractState(new ContractNameOrHashOrId(contractState.Hash)); + act.Should().Throw().WithMessage(RpcError.UnknownContract.Message); + act = () => _rpcServer.GetContractState(new ContractNameOrHashOrId(contractState.Id)); + act.Should().Throw().WithMessage(RpcError.UnknownContract.Message); } [TestMethod] @@ -143,8 +176,10 @@ public void TestGetRawMemPool() _neoSystem.MemPool.TryAdd(tx, snapshot); var result = _rpcServer.GetRawMemPool(); - Assert.IsTrue(((JArray)result).Any(p => p.AsString() == tx.Hash.ToString())); + + result = _rpcServer.GetRawMemPool(true); + Assert.IsTrue(((JArray)result["verified"]).Any(p => p.AsString() == tx.Hash.ToString())); } [TestMethod] @@ -154,10 +189,14 @@ public void TestGetRawTransaction() var tx = TestUtils.CreateValidTx(snapshot, _wallet, _walletAccount); _neoSystem.MemPool.TryAdd(tx, snapshot); snapshot.Commit(); - var result = _rpcServer.GetRawTransaction(tx.Hash, true); + var result = _rpcServer.GetRawTransaction(tx.Hash, true); var json = Utility.TransactionToJson(tx, _neoSystem.Settings); Assert.AreEqual(json.ToString(), result.ToString()); + + result = _rpcServer.GetRawTransaction(tx.Hash, false); + var tx2 = Convert.FromBase64String(result.AsString()).AsSerializable(); + tx2.ToJson(_neoSystem.Settings).ToString().Should().Be(tx.ToJson(_neoSystem.Settings).ToString()); } [TestMethod] @@ -197,6 +236,15 @@ public void TestFindStorage() json["next"] = 1; json["results"] = jarr; Assert.AreEqual(json.ToString(), result.ToString()); + + var result2 = _rpcServer.FindStorage(new ContractNameOrHashOrId(contractState.Hash), Convert.ToBase64String(key)); + result2.ToString().Should().Be(result.ToString()); + + Enumerable.Range(0, 51).ToList().ForEach(i => TestUtils.StorageItemAdd(snapshot, contractState.Id, new byte[] { 0x01, (byte)i }, new byte[] { 0x02 })); + snapshot.Commit(); + var result4 = _rpcServer.FindStorage(new ContractNameOrHashOrId(contractState.Hash), Convert.ToBase64String(new byte[] { 0x01 }), 0); + result4["next"].Should().Be(RpcServerSettings.Default.FindStoragePageSize); + (result4["truncated"]).AsBoolean().Should().Be(true); } [TestMethod] @@ -232,12 +280,16 @@ public void TestGetNextBlockValidators() public void TestGetCandidates() { var snapshot = _neoSystem.GetSnapshotCache(); + var result = _rpcServer.GetCandidates(); var json = new JArray(); var validators = NativeContract.NEO.GetNextBlockValidators(snapshot, _neoSystem.Settings.ValidatorsCount); + + var key = new KeyBuilder(NativeContract.NEO.Id, 33).Add(ECPoint.Parse("02237309a0633ff930d51856db01d17c829a5b2e5cc2638e9c03b4cfa8e9c9f971", ECCurve.Secp256r1)); + snapshot.Add(key, new StorageItem(new CandidateState() { Registered = true, Votes = 10000 })); snapshot.Commit(); var candidates = NativeContract.NEO.GetCandidates(_neoSystem.GetSnapshotCache()); - + result = _rpcServer.GetCandidates(); foreach (var candidate in candidates) { var item = new JObject(); @@ -350,7 +402,8 @@ public void TestGetBlockHashInvalidIndex() var block = TestUtils.CreateBlockWithValidTransactions(snapshot, _wallet, _walletAccount, 3); TestUtils.BlocksAdd(snapshot, block.Hash, block); snapshot.Commit(); - Assert.ThrowsException(() => _rpcServer.GetBlockHash(block.Index + 1)); + Action act = () => _rpcServer.GetBlockHash(block.Index + 1); + act.Should().Throw(); } [TestMethod] diff --git a/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Node.cs b/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Node.cs index c8b655024c..cf674a449c 100644 --- a/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Node.cs +++ b/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Node.cs @@ -9,18 +9,50 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using Akka.Actor; +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO; using Neo.Json; +using Neo.Network.P2P; using Neo.Network.P2P.Payloads; using Neo.SmartContract.Native; using Neo.UnitTests; using System; +using System.Collections.Generic; +using System.Net; namespace Neo.Plugins.RpcServer.Tests { partial class UT_RpcServer { + [TestMethod] + public void TestGetConnectionCount() + { + var result = _rpcServer.GetConnectionCount(new JArray()); + result.GetType().Should().Be(typeof(JNumber)); + } + + [TestMethod] + public void TestGetPeers() + { + var settings = TestProtocolSettings.SoleNode; + var neoSystem = new NeoSystem(settings, _memoryStoreProvider); + var localNode = neoSystem.LocalNode.Ask(new LocalNode.GetInstance()).Result; + localNode.AddPeers(new List() { new IPEndPoint(new IPAddress(new byte[] { 127, 0, 0, 1 }), 11332) }); + localNode.AddPeers(new List() { new IPEndPoint(new IPAddress(new byte[] { 127, 0, 0, 1 }), 12332) }); + localNode.AddPeers(new List() { new IPEndPoint(new IPAddress(new byte[] { 127, 0, 0, 1 }), 13332) }); + var rpcServer = new RpcServer(neoSystem, RpcServerSettings.Default); + + var result = rpcServer.GetPeers(new JArray()); + Assert.IsInstanceOfType(result, typeof(JObject)); + var json = (JObject)result; + json.ContainsProperty("unconnected").Should().BeTrue(); + (json["unconnected"] as JArray).Count.Should().Be(3); + json.ContainsProperty("bad").Should().BeTrue(); + json.ContainsProperty("connected").Should().BeTrue(); + } + [TestMethod] public void TestGetVersion() { diff --git a/tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs b/tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs index 9a282759a9..c205a7e4bd 100644 --- a/tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs +++ b/tests/Neo.UnitTests/Extensions/NativeContractExtensions.cs @@ -9,6 +9,8 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using FluentAssertions; +using Neo.IO; using Neo.Network.P2P.Payloads; using Neo.Persistence; using Neo.SmartContract; @@ -100,14 +102,26 @@ public static void DestroyContract(this DataCache snapshot, UInt160 callingScrip public static void AddContract(this DataCache snapshot, UInt160 hash, ContractState state) { + //key: hash, value: ContractState var key = new KeyBuilder(NativeContract.ContractManagement.Id, 8).Add(hash); snapshot.Add(key, new StorageItem(state)); + //key: id, value: hash + var key2 = new KeyBuilder(NativeContract.ContractManagement.Id, 12).AddBigEndian(state.Id); + if (!snapshot.Contains(key2)) snapshot.Add(key2, new StorageItem(hash.ToArray())); } public static void DeleteContract(this DataCache snapshot, UInt160 hash) { + //key: hash, value: ContractState var key = new KeyBuilder(NativeContract.ContractManagement.Id, 8).Add(hash); + var value = snapshot.TryGet(key)?.GetInteroperable(); snapshot.Delete(key); + if (value != null) + { + //key: id, value: hash + var key2 = new KeyBuilder(NativeContract.ContractManagement.Id, 12).AddBigEndian(value.Id); + snapshot.Delete(key2); + } } public static StackItem Call(this NativeContract contract, DataCache snapshot, string method, params ContractParameter[] args)