From da193e9e4edcebcaa58ae356880922bb47968376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=BF=97=E5=90=8C?= Date: Thu, 5 Sep 2024 22:43:26 +0800 Subject: [PATCH 1/4] Add some UT (#3476) * Update UT_Utility.cs * TestGetContractState --- tests/Neo.Network.RPC.Tests/RpcTestCases.json | 952 +++++++++++++++--- tests/Neo.Network.RPC.Tests/UT_RpcClient.cs | 13 +- tests/Neo.Network.RPC.Tests/UT_Utility.cs | 139 +++ 3 files changed, 958 insertions(+), 146 deletions(-) diff --git a/tests/Neo.Network.RPC.Tests/RpcTestCases.json b/tests/Neo.Network.RPC.Tests/RpcTestCases.json index c2e4f4b5a2..623b59f0d9 100644 --- a/tests/Neo.Network.RPC.Tests/RpcTestCases.json +++ b/tests/Neo.Network.RPC.Tests/RpcTestCases.json @@ -355,7 +355,7 @@ "jsonrpc": "2.0", "id": 1, "result": { - "id": -4, + "id": -6, "updatecounter": 0, "hash": "0xd2a4cff31913016155e38e474a2c06d08be276cf", "nef": { @@ -363,8 +363,8 @@ "compiler": "neo-core-v3.0", "source": "", "tokens": [], - "script": "APxBGvd7Zw==", - "checksum": 3155977747 + "script": "EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=", + "checksum": 2663858513 }, "manifest": { "name": "GasToken", @@ -391,21 +391,21 @@ "name": "decimals", "parameters": [], "returntype": "Integer", - "offset": 0, + "offset": 7, "safe": true }, { "name": "symbol", "parameters": [], "returntype": "String", - "offset": 0, + "offset": 14, "safe": true }, { "name": "totalSupply", "parameters": [], "returntype": "Integer", - "offset": 0, + "offset": 21, "safe": true }, { @@ -429,7 +429,7 @@ } ], "returntype": "Boolean", - "offset": 0, + "offset": 28, "safe": false } ], @@ -470,14 +470,14 @@ "Request": { "jsonrpc": "2.0", "method": "getcontractstate", - "params": [ "0xd2a4cff31913016155e38e474a2c06d08be276cf" ], + "params": [ -6 ], "id": 1 }, "Response": { "jsonrpc": "2.0", "id": 1, "result": { - "id": -4, + "id": -6, "updatecounter": 0, "hash": "0xd2a4cff31913016155e38e474a2c06d08be276cf", "nef": { @@ -485,8 +485,8 @@ "compiler": "neo-core-v3.0", "source": "", "tokens": [], - "script": "APxBGvd7Zw==", - "checksum": 3155977747 + "script": "EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=", + "checksum": 2663858513 }, "manifest": { "name": "GasToken", @@ -513,21 +513,21 @@ "name": "decimals", "parameters": [], "returntype": "Integer", - "offset": 0, + "offset": 7, "safe": true }, { "name": "symbol", "parameters": [], "returntype": "String", - "offset": 0, + "offset": 14, "safe": true }, { "name": "totalSupply", "parameters": [], "returntype": "Integer", - "offset": 0, + "offset": 21, "safe": true }, { @@ -551,7 +551,7 @@ } ], "returntype": "Boolean", - "offset": 0, + "offset": 28, "safe": false } ], @@ -591,27 +591,27 @@ "Name": "getcontractstateasync", "Request": { "jsonrpc": "2.0", - "id": 1, "method": "getcontractstate", - "params": [ "neotoken" ] + "params": [ "0xd2a4cff31913016155e38e474a2c06d08be276cf" ], + "id": 1 }, "Response": { "jsonrpc": "2.0", "id": 1, "result": { - "id": -3, + "id": -6, "updatecounter": 0, - "hash": "0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5", + "hash": "0xd2a4cff31913016155e38e474a2c06d08be276cf", "nef": { "magic": 860243278, "compiler": "neo-core-v3.0", "source": "", "tokens": [], - "script": "AP1BGvd7Zw==", - "checksum": 3921333105 + "script": "EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=", + "checksum": 2663858513 }, "manifest": { - "name": "NeoToken", + "name": "GasToken", "groups": [], "features": {}, "supportedstandards": [ @@ -635,73 +635,21 @@ "name": "decimals", "parameters": [], "returntype": "Integer", - "offset": 0, - "safe": true - }, - { - "name": "getCandidates", - "parameters": [], - "returntype": "Array", - "offset": 0, - "safe": true - }, - { - "name": "getCommittee", - "parameters": [], - "returntype": "Array", - "offset": 0, - "safe": true - }, - { - "name": "getGasPerBlock", - "parameters": [], - "returntype": "Integer", - "offset": 0, - "safe": true - }, - { - "name": "getNextBlockValidators", - "parameters": [], - "returntype": "Array", - "offset": 0, + "offset": 7, "safe": true }, - { - "name": "registerCandidate", - "parameters": [ - { - "name": "pubkey", - "type": "ByteArray" - } - ], - "returntype": "Boolean", - "offset": 0, - "safe": false - }, - { - "name": "setGasPerBlock", - "parameters": [ - { - "name": "gasPerBlock", - "type": "Integer" - } - ], - "returntype": "Boolean", - "offset": 0, - "safe": false - }, { "name": "symbol", "parameters": [], "returntype": "String", - "offset": 0, + "offset": 14, "safe": true }, { "name": "totalSupply", "parameters": [], "returntype": "Integer", - "offset": 0, + "offset": 21, "safe": true }, { @@ -725,51 +673,7 @@ } ], "returntype": "Boolean", - "offset": 0, - "safe": false - }, - { - "name": "unclaimedGas", - "parameters": [ - { - "name": "account", - "type": "Hash160" - }, - { - "name": "end", - "type": "Integer" - } - ], - "returntype": "Integer", - "offset": 0, - "safe": true - }, - { - "name": "unregisterCandidate", - "parameters": [ - { - "name": "pubkey", - "type": "ByteArray" - } - ], - "returntype": "Boolean", - "offset": 0, - "safe": false - }, - { - "name": "vote", - "parameters": [ - { - "name": "account", - "type": "Hash160" - }, - { - "name": "voteTo", - "type": "ByteArray" - } - ], - "returntype": "Boolean", - "offset": 0, + "offset": 28, "safe": false } ], @@ -811,22 +715,22 @@ "jsonrpc": "2.0", "id": 1, "method": "getcontractstate", - "params": [ "0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5" ] + "params": [ "neotoken" ] }, "Response": { "jsonrpc": "2.0", "id": 1, "result": { - "id": -3, - "updatecounter": 0, + "id": -5, + "updatecounter": 1, "hash": "0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5", "nef": { "magic": 860243278, "compiler": "neo-core-v3.0", "source": "", "tokens": [], - "script": "AP1BGvd7Zw==", - "checksum": 3921333105 + "script": "EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=", + "checksum": 1325686241 }, "manifest": { "name": "NeoToken", @@ -853,35 +757,80 @@ "name": "decimals", "parameters": [], "returntype": "Integer", - "offset": 0, + "offset": 7, + "safe": true + }, + { + "name": "getAccountState", + "parameters": [ + { + "name": "account", + "type": "Hash160" + } + ], + "returntype": "Array", + "offset": 14, + "safe": true + }, + { + "name": "getAllCandidates", + "parameters": [], + "returntype": "InteropInterface", + "offset": 21, + "safe": true + }, + { + "name": "getCandidateVote", + "parameters": [ + { + "name": "pubKey", + "type": "PublicKey" + } + ], + "returntype": "Integer", + "offset": 28, "safe": true }, { "name": "getCandidates", "parameters": [], "returntype": "Array", - "offset": 0, + "offset": 35, "safe": true }, { "name": "getCommittee", "parameters": [], "returntype": "Array", - "offset": 0, + "offset": 42, + "safe": true + }, + { + "name": "getCommitteeAddress", + "parameters": [], + "returntype": "Hash160", + "offset": 49, "safe": true }, { "name": "getGasPerBlock", "parameters": [], "returntype": "Integer", - "offset": 0, + "offset": 56, "safe": true }, { "name": "getNextBlockValidators", "parameters": [], "returntype": "Array", - "offset": 0, + "offset": 63, + "safe": true + }, + { + "name": "getRegisterPrice", + "parameters": [], + "returntype": "Integer", + "offset": 70, "safe": true }, { @@ -889,11 +838,11 @@ "parameters": [ { "name": "pubkey", - "type": "ByteArray" + "type": "PublicKey" } ], "returntype": "Boolean", - "offset": 0, + "offset": 77, "safe": false }, { @@ -904,22 +853,34 @@ "type": "Integer" } ], - "returntype": "Boolean", - "offset": 0, + "returntype": "Void", + "offset": 84, + "safe": false + }, + { + "name": "setRegisterPrice", + "parameters": [ + { + "name": "registerPrice", + "type": "Integer" + } + ], + "returntype": "Void", + "offset": 91, "safe": false }, { "name": "symbol", "parameters": [], "returntype": "String", - "offset": 0, + "offset": 98, "safe": true }, { "name": "totalSupply", "parameters": [], "returntype": "Integer", - "offset": 0, + "offset": 105, "safe": true }, { @@ -943,7 +904,7 @@ } ], "returntype": "Boolean", - "offset": 0, + "offset": 112, "safe": false }, { @@ -959,7 +920,7 @@ } ], "returntype": "Integer", - "offset": 0, + "offset": 119, "safe": true }, { @@ -967,11 +928,11 @@ "parameters": [ { "name": "pubkey", - "type": "ByteArray" + "type": "PublicKey" } ], "returntype": "Boolean", - "offset": 0, + "offset": 126, "safe": false }, { @@ -983,11 +944,11 @@ }, { "name": "voteTo", - "type": "ByteArray" + "type": "PublicKey" } ], "returntype": "Boolean", - "offset": 0, + "offset": 133, "safe": false } ], @@ -1008,6 +969,709 @@ "type": "Integer" } ] + }, + { + "name": "CandidateStateChanged", + "parameters": [ + { + "name": "pubkey", + "type": "PublicKey" + }, + { + "name": "registered", + "type": "Boolean" + }, + { + "name": "votes", + "type": "Integer" + } + ] + }, + { + "name": "Vote", + "parameters": [ + { + "name": "account", + "type": "Hash160" + }, + { + "name": "from", + "type": "PublicKey" + }, + { + "name": "to", + "type": "PublicKey" + }, + { + "name": "amount", + "type": "Integer" + } + ] + }, + { + "name": "CommitteeChanged", + "parameters": [ + { + "name": "old", + "type": "Array" + }, + { + "name": "new", + "type": "Array" + } + ] + } + ] + }, + "permissions": [ + { + "contract": "*", + "methods": "*" + } + ], + "trusts": [], + "extra": null + } + } + } + }, + { + "Name": "getcontractstateasync", + "Request": { + "jsonrpc": "2.0", + "id": 1, + "method": "getcontractstate", + "params": [ -5 ] + }, + "Response": { + "jsonrpc": "2.0", + "id": 1, + "result": { + "id": -5, + "updatecounter": 1, + "hash": "0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5", + "nef": { + "magic": 860243278, + "compiler": "neo-core-v3.0", + "source": "", + "tokens": [], + "script": "EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=", + "checksum": 1325686241 + }, + "manifest": { + "name": "NeoToken", + "groups": [], + "features": {}, + "supportedstandards": [ + "NEP-17" + ], + "abi": { + "methods": [ + { + "name": "balanceOf", + "parameters": [ + { + "name": "account", + "type": "Hash160" + } + ], + "returntype": "Integer", + "offset": 0, + "safe": true + }, + { + "name": "decimals", + "parameters": [], + "returntype": "Integer", + "offset": 7, + "safe": true + }, + { + "name": "getAccountState", + "parameters": [ + { + "name": "account", + "type": "Hash160" + } + ], + "returntype": "Array", + "offset": 14, + "safe": true + }, + { + "name": "getAllCandidates", + "parameters": [], + "returntype": "InteropInterface", + "offset": 21, + "safe": true + }, + { + "name": "getCandidateVote", + "parameters": [ + { + "name": "pubKey", + "type": "PublicKey" + } + ], + "returntype": "Integer", + "offset": 28, + "safe": true + }, + { + "name": "getCandidates", + "parameters": [], + "returntype": "Array", + "offset": 35, + "safe": true + }, + { + "name": "getCommittee", + "parameters": [], + "returntype": "Array", + "offset": 42, + "safe": true + }, + { + "name": "getCommitteeAddress", + "parameters": [], + "returntype": "Hash160", + "offset": 49, + "safe": true + }, + { + "name": "getGasPerBlock", + "parameters": [], + "returntype": "Integer", + "offset": 56, + "safe": true + }, + { + "name": "getNextBlockValidators", + "parameters": [], + "returntype": "Array", + "offset": 63, + "safe": true + }, + { + "name": "getRegisterPrice", + "parameters": [], + "returntype": "Integer", + "offset": 70, + "safe": true + }, + { + "name": "registerCandidate", + "parameters": [ + { + "name": "pubkey", + "type": "PublicKey" + } + ], + "returntype": "Boolean", + "offset": 77, + "safe": false + }, + { + "name": "setGasPerBlock", + "parameters": [ + { + "name": "gasPerBlock", + "type": "Integer" + } + ], + "returntype": "Void", + "offset": 84, + "safe": false + }, + { + "name": "setRegisterPrice", + "parameters": [ + { + "name": "registerPrice", + "type": "Integer" + } + ], + "returntype": "Void", + "offset": 91, + "safe": false + }, + { + "name": "symbol", + "parameters": [], + "returntype": "String", + "offset": 98, + "safe": true + }, + { + "name": "totalSupply", + "parameters": [], + "returntype": "Integer", + "offset": 105, + "safe": true + }, + { + "name": "transfer", + "parameters": [ + { + "name": "from", + "type": "Hash160" + }, + { + "name": "to", + "type": "Hash160" + }, + { + "name": "amount", + "type": "Integer" + }, + { + "name": "data", + "type": "Any" + } + ], + "returntype": "Boolean", + "offset": 112, + "safe": false + }, + { + "name": "unclaimedGas", + "parameters": [ + { + "name": "account", + "type": "Hash160" + }, + { + "name": "end", + "type": "Integer" + } + ], + "returntype": "Integer", + "offset": 119, + "safe": true + }, + { + "name": "unregisterCandidate", + "parameters": [ + { + "name": "pubkey", + "type": "PublicKey" + } + ], + "returntype": "Boolean", + "offset": 126, + "safe": false + }, + { + "name": "vote", + "parameters": [ + { + "name": "account", + "type": "Hash160" + }, + { + "name": "voteTo", + "type": "PublicKey" + } + ], + "returntype": "Boolean", + "offset": 133, + "safe": false + } + ], + "events": [ + { + "name": "Transfer", + "parameters": [ + { + "name": "from", + "type": "Hash160" + }, + { + "name": "to", + "type": "Hash160" + }, + { + "name": "amount", + "type": "Integer" + } + ] + }, + { + "name": "CandidateStateChanged", + "parameters": [ + { + "name": "pubkey", + "type": "PublicKey" + }, + { + "name": "registered", + "type": "Boolean" + }, + { + "name": "votes", + "type": "Integer" + } + ] + }, + { + "name": "Vote", + "parameters": [ + { + "name": "account", + "type": "Hash160" + }, + { + "name": "from", + "type": "PublicKey" + }, + { + "name": "to", + "type": "PublicKey" + }, + { + "name": "amount", + "type": "Integer" + } + ] + }, + { + "name": "CommitteeChanged", + "parameters": [ + { + "name": "old", + "type": "Array" + }, + { + "name": "new", + "type": "Array" + } + ] + } + ] + }, + "permissions": [ + { + "contract": "*", + "methods": "*" + } + ], + "trusts": [], + "extra": null + } + } + } + }, + { + "Name": "getcontractstateasync", + "Request": { + "jsonrpc": "2.0", + "id": 1, + "method": "getcontractstate", + "params": [ "0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5" ] + }, + "Response": { + "jsonrpc": "2.0", + "id": 1, + "result": { + "id": -5, + "updatecounter": 1, + "hash": "0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5", + "nef": { + "magic": 860243278, + "compiler": "neo-core-v3.0", + "source": "", + "tokens": [], + "script": "EEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0AQQRr3e2dAEEEa93tnQBBBGvd7Z0A=", + "checksum": 1325686241 + }, + "manifest": { + "name": "NeoToken", + "groups": [], + "features": {}, + "supportedstandards": [ + "NEP-17" + ], + "abi": { + "methods": [ + { + "name": "balanceOf", + "parameters": [ + { + "name": "account", + "type": "Hash160" + } + ], + "returntype": "Integer", + "offset": 0, + "safe": true + }, + { + "name": "decimals", + "parameters": [], + "returntype": "Integer", + "offset": 7, + "safe": true + }, + { + "name": "getAccountState", + "parameters": [ + { + "name": "account", + "type": "Hash160" + } + ], + "returntype": "Array", + "offset": 14, + "safe": true + }, + { + "name": "getAllCandidates", + "parameters": [], + "returntype": "InteropInterface", + "offset": 21, + "safe": true + }, + { + "name": "getCandidateVote", + "parameters": [ + { + "name": "pubKey", + "type": "PublicKey" + } + ], + "returntype": "Integer", + "offset": 28, + "safe": true + }, + { + "name": "getCandidates", + "parameters": [], + "returntype": "Array", + "offset": 35, + "safe": true + }, + { + "name": "getCommittee", + "parameters": [], + "returntype": "Array", + "offset": 42, + "safe": true + }, + { + "name": "getCommitteeAddress", + "parameters": [], + "returntype": "Hash160", + "offset": 49, + "safe": true + }, + { + "name": "getGasPerBlock", + "parameters": [], + "returntype": "Integer", + "offset": 56, + "safe": true + }, + { + "name": "getNextBlockValidators", + "parameters": [], + "returntype": "Array", + "offset": 63, + "safe": true + }, + { + "name": "getRegisterPrice", + "parameters": [], + "returntype": "Integer", + "offset": 70, + "safe": true + }, + { + "name": "registerCandidate", + "parameters": [ + { + "name": "pubkey", + "type": "PublicKey" + } + ], + "returntype": "Boolean", + "offset": 77, + "safe": false + }, + { + "name": "setGasPerBlock", + "parameters": [ + { + "name": "gasPerBlock", + "type": "Integer" + } + ], + "returntype": "Void", + "offset": 84, + "safe": false + }, + { + "name": "setRegisterPrice", + "parameters": [ + { + "name": "registerPrice", + "type": "Integer" + } + ], + "returntype": "Void", + "offset": 91, + "safe": false + }, + { + "name": "symbol", + "parameters": [], + "returntype": "String", + "offset": 98, + "safe": true + }, + { + "name": "totalSupply", + "parameters": [], + "returntype": "Integer", + "offset": 105, + "safe": true + }, + { + "name": "transfer", + "parameters": [ + { + "name": "from", + "type": "Hash160" + }, + { + "name": "to", + "type": "Hash160" + }, + { + "name": "amount", + "type": "Integer" + }, + { + "name": "data", + "type": "Any" + } + ], + "returntype": "Boolean", + "offset": 112, + "safe": false + }, + { + "name": "unclaimedGas", + "parameters": [ + { + "name": "account", + "type": "Hash160" + }, + { + "name": "end", + "type": "Integer" + } + ], + "returntype": "Integer", + "offset": 119, + "safe": true + }, + { + "name": "unregisterCandidate", + "parameters": [ + { + "name": "pubkey", + "type": "PublicKey" + } + ], + "returntype": "Boolean", + "offset": 126, + "safe": false + }, + { + "name": "vote", + "parameters": [ + { + "name": "account", + "type": "Hash160" + }, + { + "name": "voteTo", + "type": "PublicKey" + } + ], + "returntype": "Boolean", + "offset": 133, + "safe": false + } + ], + "events": [ + { + "name": "Transfer", + "parameters": [ + { + "name": "from", + "type": "Hash160" + }, + { + "name": "to", + "type": "Hash160" + }, + { + "name": "amount", + "type": "Integer" + } + ] + }, + { + "name": "CandidateStateChanged", + "parameters": [ + { + "name": "pubkey", + "type": "PublicKey" + }, + { + "name": "registered", + "type": "Boolean" + }, + { + "name": "votes", + "type": "Integer" + } + ] + }, + { + "name": "Vote", + "parameters": [ + { + "name": "account", + "type": "Hash160" + }, + { + "name": "from", + "type": "PublicKey" + }, + { + "name": "to", + "type": "PublicKey" + }, + { + "name": "amount", + "type": "Integer" + } + ] + }, + { + "name": "CommitteeChanged", + "parameters": [ + { + "name": "old", + "type": "Array" + }, + { + "name": "new", + "type": "Array" + } + ] } ] }, diff --git a/tests/Neo.Network.RPC.Tests/UT_RpcClient.cs b/tests/Neo.Network.RPC.Tests/UT_RpcClient.cs index 4af0f557e3..b87960e76d 100644 --- a/tests/Neo.Network.RPC.Tests/UT_RpcClient.cs +++ b/tests/Neo.Network.RPC.Tests/UT_RpcClient.cs @@ -220,8 +220,17 @@ public async Task TestGetContractState() var tests = TestUtils.RpcTestCases.Where(p => p.Name == nameof(rpc.GetContractStateAsync).ToLower()); foreach (var test in tests) { - var result = await rpc.GetContractStateAsync(test.Request.Params[0].AsString()); - Assert.AreEqual(test.Response.Result.ToString(), result.ToJson().ToString()); + var type = test.Request.Params[0].GetType().Name; + if (type == "JString") + { + var result = await rpc.GetContractStateAsync(test.Request.Params[0].AsString()); + Assert.AreEqual(test.Response.Result.ToString(), result.ToJson().ToString()); + } + if (type == "JNumber") + { + var result = await rpc.GetContractStateAsync((int)test.Request.Params[0].AsNumber()); + Assert.AreEqual(test.Response.Result.ToString(), result.ToJson().ToString()); + } } } diff --git a/tests/Neo.Network.RPC.Tests/UT_Utility.cs b/tests/Neo.Network.RPC.Tests/UT_Utility.cs index 53e381b836..3c30069219 100644 --- a/tests/Neo.Network.RPC.Tests/UT_Utility.cs +++ b/tests/Neo.Network.RPC.Tests/UT_Utility.cs @@ -9,12 +9,16 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using FluentAssertions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.Extensions; +using Neo.Network.P2P.Payloads; using Neo.SmartContract; +using Neo.SmartContract.Native; using Neo.Wallets; using System; using System.Numerics; +using System.Security.Cryptography; namespace Neo.Network.RPC.Tests { @@ -33,6 +37,16 @@ public void TestSetup() protocolSettings = ProtocolSettings.Load("protocol.json"); } + [TestMethod] + public void TestAsScriptHash() + { + var scriptHash1 = Utility.AsScriptHash(NativeContract.NEO.Id.ToString()); + var scriptHash2 = Utility.AsScriptHash(NativeContract.NEO.Hash.ToString()); + var scriptHash3 = Utility.AsScriptHash(NativeContract.NEO.Name); + scriptHash2.Should().Be(scriptHash1); + scriptHash3.Should().Be(scriptHash1); + } + [TestMethod] public void TestGetKeyPair() { @@ -46,6 +60,13 @@ public void TestGetKeyPair() string privateKey = keyPair.PrivateKey.ToHexString(); result = Utility.GetKeyPair(privateKey); Assert.AreEqual(keyPair, result); + + string hexWith0x = $"0x{result.PrivateKey.ToHexString()}"; + result = Utility.GetKeyPair(hexWith0x); + Assert.AreEqual(keyPair, result); + + var action = () => { Utility.GetKeyPair("00"); }; + action.Should().Throw(); } [TestMethod] @@ -65,6 +86,124 @@ public void TestGetScriptHash() string publicKey = keyPair.PublicKey.ToString(); result = Utility.GetScriptHash(publicKey, protocolSettings); Assert.AreEqual(scriptHash, result); + + var action = () => { Utility.GetScriptHash("00", protocolSettings); }; + action.Should().Throw(); + } + + [TestMethod] + public void TestTransactionAttribute() + { + var attribute = new Conflicts(); + attribute.Hash = UInt256.Zero; + var json = attribute.ToJson(); + var result = Utility.TransactionAttributeFromJson(json).ToJson(); + result.ToString().Should().Be(json.ToString()); + + var attribute2 = new OracleResponse(); + attribute2.Id = 1234; + attribute2.Code = 0; + attribute2.Result = new ReadOnlyMemory { }; + json = attribute2.ToJson(); + result = Utility.TransactionAttributeFromJson(json).ToJson(); + result.ToString().Should().Be(json.ToString()); + + var attribute3 = new NotValidBefore(); + attribute3.Height = 10000; + json = attribute3.ToJson(); + result = Utility.TransactionAttributeFromJson(json).ToJson(); + result.ToString().Should().Be(json.ToString()); + + var attribute4 = new HighPriorityAttribute(); + json = attribute4.ToJson(); + result = Utility.TransactionAttributeFromJson(json).ToJson(); + result.ToString().Should().Be(json.ToString()); + } + + [TestMethod] + public void TestWitnessRule() + { + var rule = new WitnessRule(); + rule.Action = WitnessRuleAction.Allow; + rule.Condition = new Neo.Network.P2P.Payloads.Conditions.CalledByEntryCondition(); + var json = rule.ToJson(); + var result = Utility.RuleFromJson(json, ProtocolSettings.Default).ToJson(); + result.ToString().Should().Be(json.ToString()); + + rule.Condition = new Neo.Network.P2P.Payloads.Conditions.OrCondition() + { + Expressions = new P2P.Payloads.Conditions.WitnessCondition[] + { + new Neo.Network.P2P.Payloads.Conditions.BooleanCondition() + { + Expression = true + }, + new Neo.Network.P2P.Payloads.Conditions.BooleanCondition() + { + Expression = false + } + } + }; + json = rule.ToJson(); + result = Utility.RuleFromJson(json, ProtocolSettings.Default).ToJson(); + result.ToString().Should().Be(json.ToString()); + + rule.Condition = new Neo.Network.P2P.Payloads.Conditions.AndCondition() + { + Expressions = new P2P.Payloads.Conditions.WitnessCondition[] + { + new Neo.Network.P2P.Payloads.Conditions.BooleanCondition() + { + Expression = true + }, + new Neo.Network.P2P.Payloads.Conditions.BooleanCondition() + { + Expression = false + } + } + }; + json = rule.ToJson(); + result = Utility.RuleFromJson(json, ProtocolSettings.Default).ToJson(); + result.ToString().Should().Be(json.ToString()); + + rule.Condition = new Neo.Network.P2P.Payloads.Conditions.BooleanCondition() { Expression = true }; + json = rule.ToJson(); + result = Utility.RuleFromJson(json, ProtocolSettings.Default).ToJson(); + result.ToString().Should().Be(json.ToString()); + + rule.Condition = new Neo.Network.P2P.Payloads.Conditions.NotCondition() + { + Expression = new Neo.Network.P2P.Payloads.Conditions.BooleanCondition() + { + Expression = true + } + }; + json = rule.ToJson(); + result = Utility.RuleFromJson(json, ProtocolSettings.Default).ToJson(); + result.ToString().Should().Be(json.ToString()); + + var kp = Utility.GetKeyPair("KyXwTh1hB76RRMquSvnxZrJzQx7h9nQP2PCRL38v6VDb5ip3nf1p"); + rule.Condition = new Neo.Network.P2P.Payloads.Conditions.GroupCondition() { Group = kp.PublicKey }; + json = rule.ToJson(); + result = Utility.RuleFromJson(json, ProtocolSettings.Default).ToJson(); + result.ToString().Should().Be(json.ToString()); + + rule.Condition = new Neo.Network.P2P.Payloads.Conditions.CalledByContractCondition() { Hash = UInt160.Zero }; + json = rule.ToJson(); + result = Utility.RuleFromJson(json, ProtocolSettings.Default).ToJson(); + result.ToString().Should().Be(json.ToString()); + + rule.Condition = new Neo.Network.P2P.Payloads.Conditions.ScriptHashCondition() { Hash = UInt160.Zero }; + json = rule.ToJson(); + result = Utility.RuleFromJson(json, ProtocolSettings.Default).ToJson(); + result.ToString().Should().Be(json.ToString()); + result.ToString().Should().Be(json.ToString()); + + rule.Condition = new Neo.Network.P2P.Payloads.Conditions.CalledByGroupCondition() { Group = kp.PublicKey }; + json = rule.ToJson(); + result = Utility.RuleFromJson(json, ProtocolSettings.Default).ToJson(); + result.ToString().Should().Be(json.ToString()); + result.ToString().Should().Be(json.ToString()); } [TestMethod] From 3d663f21ecfd02130e3f1dd4b49da90521ab494b Mon Sep 17 00:00:00 2001 From: Mirage Mouse Date: Thu, 5 Sep 2024 23:58:39 -0400 Subject: [PATCH 2/4] Update ConstantTimeUtility.cs (#3472) - Fix typo Co-authored-by: Shargon Co-authored-by: Jimmy Co-authored-by: NGD Admin <154295625+NGDAdmin@users.noreply.github.com> --- src/Neo.Cryptography.BLS12_381/ConstantTimeUtility.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo.Cryptography.BLS12_381/ConstantTimeUtility.cs b/src/Neo.Cryptography.BLS12_381/ConstantTimeUtility.cs index 70517edeb1..fefde72b67 100644 --- a/src/Neo.Cryptography.BLS12_381/ConstantTimeUtility.cs +++ b/src/Neo.Cryptography.BLS12_381/ConstantTimeUtility.cs @@ -26,7 +26,7 @@ public static bool ConstantTimeEq(in T a, in T b) where T : unmanaged for (int i = 0; i < a_u64.Length; i++) f |= a_u64[i] ^ b_u64[i]; for (int i = a_u64.Length * sizeof(ulong); i < a_bytes.Length; i++) - f |= (ulong)a_bytes[i] ^ a_bytes[i]; + f |= (ulong)a_bytes[i] ^ b_bytes[i]; return f == 0; } From 2b118b45a38f3c69793c1d01f986fb04f5572b50 Mon Sep 17 00:00:00 2001 From: Hecate2 <2474101468@qq.com> Date: Sat, 7 Sep 2024 06:46:19 +0800 Subject: [PATCH 3/4] Test OracleService (#3475) * trigger https oracle * make it internal * return Task.CompletedTask --------- Co-authored-by: Jimmy Co-authored-by: Jimmy Co-authored-by: Shargon --- src/Plugins/OracleService/OracleService.cs | 22 ++-- .../OracleService/OracleService.csproj | 4 + src/Plugins/OracleService/Settings.cs | 3 + .../E2E_Https.cs | 104 ++++++++++++++++++ .../TestBlockchain.cs | 62 ++++++++++- .../TestUtils.cs | 25 +++++ .../UT_OracleService.cs | 6 - .../config.json | 26 +---- 8 files changed, 207 insertions(+), 45 deletions(-) create mode 100644 tests/Neo.Plugins.OracleService.Tests/E2E_Https.cs diff --git a/src/Plugins/OracleService/OracleService.cs b/src/Plugins/OracleService/OracleService.cs index 27ced4e04c..fbdee148db 100644 --- a/src/Plugins/OracleService/OracleService.cs +++ b/src/Plugins/OracleService/OracleService.cs @@ -53,7 +53,7 @@ public class OracleService : Plugin, ICommittingHandler, IServiceAddedHandler, I private readonly ConcurrentDictionary pendingQueue = new ConcurrentDictionary(); private readonly ConcurrentDictionary finishedCache = new ConcurrentDictionary(); private Timer timer; - private readonly CancellationTokenSource cancelSource = new CancellationTokenSource(); + internal readonly CancellationTokenSource cancelSource = new CancellationTokenSource(); private OracleStatus status = OracleStatus.Unstarted; private IWalletProvider walletProvider; private int counter; @@ -123,25 +123,25 @@ private void OnStart() Start(walletProvider?.GetWallet()); } - public void Start(Wallet wallet) + public Task Start(Wallet wallet) { - if (status == OracleStatus.Running) return; + if (status == OracleStatus.Running) return Task.CompletedTask; if (wallet is null) { ConsoleHelper.Warning("Please open wallet first!"); - return; + return Task.CompletedTask; } - if (!CheckOracleAvaiblable(_system.StoreView, out ECPoint[] oracles)) + if (!CheckOracleAvailable(_system.StoreView, out ECPoint[] oracles)) { ConsoleHelper.Warning("The oracle service is unavailable"); - return; + return Task.CompletedTask; } if (!CheckOracleAccount(wallet, oracles)) { ConsoleHelper.Warning("There is no oracle account in wallet"); - return; + return Task.CompletedTask; } this.wallet = wallet; @@ -150,7 +150,7 @@ public void Start(Wallet wallet) status = OracleStatus.Running; timer = new Timer(OnTimer, null, RefreshIntervalMilliSeconds, Timeout.Infinite); ConsoleHelper.Info($"Oracle started"); - ProcessRequestsAsync(); + return ProcessRequestsAsync(); } [ConsoleCommand("stop oracle", Category = "Oracle", Description = "Stop oracle service")] @@ -180,7 +180,7 @@ void ICommittingHandler.Blockchain_Committing_Handler(NeoSystem system, Block bl OnStart(); } if (status != OracleStatus.Running) return; - if (!CheckOracleAvaiblable(snapshot, out ECPoint[] oracles) || !CheckOracleAccount(wallet, oracles)) + if (!CheckOracleAvailable(snapshot, out ECPoint[] oracles) || !CheckOracleAccount(wallet, oracles)) OnStop(); } @@ -325,7 +325,7 @@ private async Task ProcessRequestAsync(DataCache snapshot, OracleRequest req) } } - private async void ProcessRequestsAsync() + private async Task ProcessRequestsAsync() { while (!cancelSource.IsCancellationRequested) { @@ -553,7 +553,7 @@ private bool CheckTxSign(DataCache snapshot, Transaction tx, ConcurrentDictionar return false; } - private static bool CheckOracleAvaiblable(DataCache snapshot, out ECPoint[] oracles) + private static bool CheckOracleAvailable(DataCache snapshot, out ECPoint[] oracles) { uint height = NativeContract.Ledger.CurrentIndex(snapshot) + 1; oracles = NativeContract.RoleManagement.GetDesignatedByRole(snapshot, Role.Oracle, height); diff --git a/src/Plugins/OracleService/OracleService.csproj b/src/Plugins/OracleService/OracleService.csproj index bb5cde6754..c77ddb75d8 100644 --- a/src/Plugins/OracleService/OracleService.csproj +++ b/src/Plugins/OracleService/OracleService.csproj @@ -24,4 +24,8 @@ + + + + diff --git a/src/Plugins/OracleService/Settings.cs b/src/Plugins/OracleService/Settings.cs index db93c1c400..08c074d363 100644 --- a/src/Plugins/OracleService/Settings.cs +++ b/src/Plugins/OracleService/Settings.cs @@ -9,6 +9,7 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using Akka.Util.Internal; using Microsoft.Extensions.Configuration; using System; using System.Linq; @@ -59,6 +60,8 @@ private Settings(IConfigurationSection section) : base(section) MaxOracleTimeout = TimeSpan.FromMilliseconds(section.GetValue("MaxOracleTimeout", 15000)); AllowPrivateHost = section.GetValue("AllowPrivateHost", false); AllowedContentTypes = section.GetSection("AllowedContentTypes").GetChildren().Select(p => p.Get()).ToArray(); + if (AllowedContentTypes.Count() == 0) + AllowedContentTypes = AllowedContentTypes.Concat("application/json").ToArray(); Https = new HttpsSettings(section.GetSection("Https")); NeoFS = new NeoFSSettings(section.GetSection("NeoFS")); AutoStart = section.GetValue("AutoStart", false); diff --git a/tests/Neo.Plugins.OracleService.Tests/E2E_Https.cs b/tests/Neo.Plugins.OracleService.Tests/E2E_Https.cs new file mode 100644 index 0000000000..c404f3f982 --- /dev/null +++ b/tests/Neo.Plugins.OracleService.Tests/E2E_Https.cs @@ -0,0 +1,104 @@ +// Copyright (C) 2015-2024 The Neo Project. +// +// UT_OracleService.cs file belongs to the neo project and is free +// software distributed under the MIT software license, see the +// accompanying file LICENSE in the main directory of the +// repository or http://www.opensource.org/licenses/mit-license.php +// for more details. +// +// Redistribution and use in source and binary forms with or without +// modifications are permitted. + +using Akka.Actor; +using Akka.TestKit.Xunit2; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Cryptography; +using Neo.Cryptography.ECC; +using Neo.Network.P2P.Payloads; +using Neo.SmartContract; +using Neo.SmartContract.Native; +using Neo.VM; +using Neo.Wallets; +using System; +using System.Linq; +using System.Threading.Tasks; +using static Neo.Plugins.OracleService.Tests.TestBlockchain; +using static Neo.Plugins.OracleService.Tests.TestUtils; + +namespace Neo.Plugins.OracleService.Tests +{ + [TestClass] + public class E2E_Https : TestKit + { + UInt160 customContract; + + [TestInitialize] + public void TestSetup() + { + customContract = InitializeContract(); + } + + [TestMethod] + public void TestE2EHttps() + { + byte[] script; + using (ScriptBuilder sb = new()) + { + sb.EmitDynamicCall(NativeContract.RoleManagement.Hash, "designateAsRole", + [Role.Oracle, + new ContractParameter() + { + Type = ContractParameterType.Array, + Value = settings.StandbyCommittee.Select( + p => new ContractParameter() { Type = ContractParameterType.PublicKey, Value = p }).ToList() + }]); + // Expected result: 12685221 + sb.EmitDynamicCall(customContract, "createRequest", + ["https://api.github.com/orgs/neo-project", "$.id", "callback", new byte[] { }, 1_0000_0000]); + script = sb.ToArray(); + } + Transaction[] txs = [ + new Transaction + { + Nonce = 233, + ValidUntilBlock = NativeContract.Ledger.CurrentIndex(s_theNeoSystem.GetSnapshotCache()) + s_theNeoSystem.Settings.MaxValidUntilBlockIncrement, + Signers = [new Signer() { Account = MultisigScriptHash, Scopes = WitnessScope.CalledByEntry }], + Attributes = Array.Empty(), + Script = script, + NetworkFee = 1000_0000, + SystemFee = 2_0000_0000, + } + ]; + byte[] signature = txs[0].Sign(s_walletAccount.GetKey(), settings.Network); + txs[0].Witnesses = [new Witness + { + InvocationScript = new byte[] { (byte)OpCode.PUSHDATA1, (byte)signature.Length }.Concat(signature).ToArray(), + VerificationScript = MultisigScript, + }]; + Block block = new Block + { + Header = new Header + { + Version = 0, + PrevHash = s_theNeoSystem.GenesisBlock.Hash, + Timestamp = s_theNeoSystem.GenesisBlock.Timestamp + 15_000, + Index = 1, + NextConsensus = s_theNeoSystem.GenesisBlock.NextConsensus, + }, + Transactions = txs, + }; + block.Header.MerkleRoot ??= MerkleTree.ComputeRoot(block.Transactions.Select(t => t.Hash).ToArray()); + signature = block.Sign(s_walletAccount.GetKey(), settings.Network); + block.Header.Witness = new Witness + { + InvocationScript = new byte[] { (byte)OpCode.PUSHDATA1, (byte)signature.Length }.Concat(signature).ToArray(), + VerificationScript = MultisigScript, + }; + s_theNeoSystem.Blockchain.Ask(block).Wait(); + Task t = s_oracle.Start(s_wallet); + t.Wait(TimeSpan.FromMilliseconds(900)); + s_oracle.cancelSource.Cancel(); + t.Wait(); + } + } +} diff --git a/tests/Neo.Plugins.OracleService.Tests/TestBlockchain.cs b/tests/Neo.Plugins.OracleService.Tests/TestBlockchain.cs index a4cc2f6fbf..160ac0407e 100644 --- a/tests/Neo.Plugins.OracleService.Tests/TestBlockchain.cs +++ b/tests/Neo.Plugins.OracleService.Tests/TestBlockchain.cs @@ -11,31 +11,83 @@ using Akka.Actor; using Neo.Ledger; +using Neo.Network.P2P.Payloads; using Neo.Persistence; +using Neo.SmartContract; +using Neo.SmartContract.Native; +using Neo.VM; +using Neo.VM.Types; +using Neo.Wallets; +using Neo.Wallets.NEP6; using System; namespace Neo.Plugins.OracleService.Tests { public static class TestBlockchain { - private static readonly NeoSystem s_theNeoSystem; - private static readonly MemoryStore s_store = new(); + public static readonly NeoSystem s_theNeoSystem; + public static readonly MemoryStore s_store = new(); + public static readonly NEP6Wallet s_wallet; + public static readonly WalletAccount s_walletAccount; + public static readonly OracleService s_oracle; private class StoreProvider : IStoreProvider { public string Name => "TestProvider"; - public IStore GetStore(string path) => s_store; } static TestBlockchain() { Console.WriteLine("initialize NeoSystem"); - s_theNeoSystem = new NeoSystem(ProtocolSettings.Load("config.json"), new StoreProvider()); + StoreProvider _memoryStoreProvider = new(); + s_oracle = new(); + s_theNeoSystem = new NeoSystem(TestUtils.settings, _memoryStoreProvider); + s_wallet = TestUtils.GenerateTestWallet("123"); + s_walletAccount = s_wallet.Import("KxuRSsHgJMb3AMSN6B9P3JHNGMFtxmuimqgR9MmXPcv3CLLfusTd"); } - public static void InitializeMockNeoSystem() + public static UInt160 InitializeContract() { + string _oracleContractSrc = """ +using System.Numerics;using Neo.SmartContract.Framework;using Neo.SmartContract.Framework.Native;using Neo.SmartContract.Framework.Services; +namespace oracle_demo{public class OracleDemo:SmartContract{ +const byte PREFIX_COUNT = 0xcc; +const byte PREFIX_DATA = 0xdd; +public static string GetRequstData() => Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_DATA }); +public static BigInteger GetRequstCount() => (BigInteger)Storage.Get(Storage.CurrentContext, new byte[] { PREFIX_COUNT }); +public static void CreateRequest(string url, string filter, string callback, byte[] userData, long gasForResponse) => Oracle.Request(url, filter, callback, userData, gasForResponse); +public static void Callback(string url, byte[] userData, int code, byte[] result) +{ + ExecutionEngine.Assert(Runtime.CallingScriptHash == Oracle.Hash, "Unauthorized!"); + StorageContext currentContext = Storage.CurrentContext; + Storage.Put(currentContext, new byte[] { PREFIX_DATA }, (ByteString)result); + Storage.Put(currentContext, new byte[] { PREFIX_COUNT }, + (BigInteger)Storage.Get(currentContext, new byte[] { PREFIX_DATA }) + 1); +}}} +"""; + string base64NefFile = "TkVGM05lby5Db21waWxlci5DU2hhcnAgMy43LjQrNjAzNGExODIxY2E3MDk0NjBlYzMxMzZjNzBjMmRjYzNiZWEuLi4AAAFYhxcRfgqoEHKvq3HS3Yn+fEuS/gdyZXF1ZXN0BQAADwAAmAwB3dswQZv2Z85Bkl3oMUAMAczbMEGb9mfOQZJd6DFK2CYERRDbIUBXAAV8e3p5eDcAAEBXAQRBOVNuPAwUWIcXEX4KqBByr6tx0t2J/nxLkv6XDA1VbmF1dGhvcml6ZWQh4UGb9mfOcHvbKAwB3dswaEHmPxiEDAHd2zBoQZJd6DFK2CYERRDbIRGeDAHM2zBoQeY/GIRAnIyFhg=="; + string manifest = """{"name":"OracleDemo","groups":[],"features":{},"supportedstandards":[],"abi":{"methods":[{"name":"getRequstData","parameters":[],"returntype":"String","offset":0,"safe":false},{"name":"getRequstCount","parameters":[],"returntype":"Integer","offset":16,"safe":false},{"name":"createRequest","parameters":[{"name":"url","type":"String"},{"name":"filter","type":"String"},{"name":"callback","type":"String"},{"name":"userData","type":"ByteArray"},{"name":"gasForResponse","type":"Integer"}],"returntype":"Void","offset":40,"safe":false},{"name":"callback","parameters":[{"name":"url","type":"String"},{"name":"userData","type":"ByteArray"},{"name":"code","type":"Integer"},{"name":"result","type":"ByteArray"}],"returntype":"Void","offset":52,"safe":false}],"events":[]},"permissions":[{"contract":"0xfe924b7cfe89ddd271abaf7210a80a7e11178758","methods":["request"]}],"trusts":[],"extra":{"nef":{"optimization":"All"}}}"""; + byte[] script; + using (ScriptBuilder sb = new()) + { + sb.EmitDynamicCall(NativeContract.ContractManagement.Hash, "deploy", Convert.FromBase64String(base64NefFile), manifest); + script = sb.ToArray(); + } + SnapshotCache snapshot = s_theNeoSystem.GetSnapshotCache(); + Transaction? tx = new Transaction + { + Nonce = 233, + ValidUntilBlock = NativeContract.Ledger.CurrentIndex(snapshot) + s_theNeoSystem.Settings.MaxValidUntilBlockIncrement, + Signers = [new Signer() { Account = TestUtils.ValidatorScriptHash, Scopes = WitnessScope.CalledByEntry }], + Attributes = System.Array.Empty(), + Script = script, + Witnesses = null, + }; + var engine = ApplicationEngine.Run(tx.Script, snapshot, container: tx, settings: s_theNeoSystem.Settings, gas: 1200_0000_0000); + engine.SnapshotCache.Commit(); + var result = (Neo.VM.Types.Array)engine.ResultStack.Peek(); + return new UInt160(result[2].GetSpan()); } internal static void ResetStore() diff --git a/tests/Neo.Plugins.OracleService.Tests/TestUtils.cs b/tests/Neo.Plugins.OracleService.Tests/TestUtils.cs index 7f1c3a58d5..a82be3ff9b 100644 --- a/tests/Neo.Plugins.OracleService.Tests/TestUtils.cs +++ b/tests/Neo.Plugins.OracleService.Tests/TestUtils.cs @@ -9,14 +9,27 @@ // Redistribution and use in source and binary forms with or without // modifications are permitted. +using FluentAssertions; using Neo.IO; +using Neo.Json; using Neo.SmartContract; using Neo.SmartContract.Native; +using Neo.Wallets; +using Neo.Wallets.NEP6; +using System; namespace Neo.Plugins.OracleService.Tests { public static class TestUtils { + public static readonly ProtocolSettings settings = ProtocolSettings.Load("config.json"); + public static readonly byte[] ValidatorScript = Contract.CreateSignatureRedeemScript(settings.StandbyCommittee[0]); + public static readonly UInt160 ValidatorScriptHash = ValidatorScript.ToScriptHash(); + public static readonly string ValidatorAddress = ValidatorScriptHash.ToAddress(ProtocolSettings.Default.AddressVersion); + public static readonly byte[] MultisigScript = Contract.CreateMultiSigRedeemScript(1, settings.StandbyCommittee); + public static readonly UInt160 MultisigScriptHash = MultisigScript.ToScriptHash(); + public static readonly string MultisigAddress = MultisigScriptHash.ToAddress(ProtocolSettings.Default.AddressVersion); + public static StorageKey CreateStorageKey(this NativeContract contract, byte prefix, ISerializable key) { var k = new KeyBuilder(contract.Id, prefix); @@ -28,5 +41,17 @@ public static StorageKey CreateStorageKey(this NativeContract contract, byte pre { return new KeyBuilder(contract.Id, prefix).AddBigEndian(value); } + + public static NEP6Wallet GenerateTestWallet(string password) + { + JObject wallet = new JObject(); + wallet["name"] = "noname"; + wallet["version"] = new Version("1.0").ToString(); + wallet["scrypt"] = new ScryptParameters(2, 1, 1).ToJson(); + wallet["accounts"] = new JArray(); + wallet["extra"] = null; + wallet.ToString().Should().Be("{\"name\":\"noname\",\"version\":\"1.0\",\"scrypt\":{\"n\":2,\"r\":1,\"p\":1},\"accounts\":[],\"extra\":null}"); + return new NEP6Wallet(null, password, settings, wallet); + } } } diff --git a/tests/Neo.Plugins.OracleService.Tests/UT_OracleService.cs b/tests/Neo.Plugins.OracleService.Tests/UT_OracleService.cs index 33d82c618c..3276c40c2f 100644 --- a/tests/Neo.Plugins.OracleService.Tests/UT_OracleService.cs +++ b/tests/Neo.Plugins.OracleService.Tests/UT_OracleService.cs @@ -21,12 +21,6 @@ namespace Neo.Plugins.OracleService.Tests [TestClass] public class UT_OracleService : TestKit { - [TestInitialize] - public void TestSetup() - { - TestBlockchain.InitializeMockNeoSystem(); - } - [TestMethod] public void TestFilter() { diff --git a/tests/Neo.Plugins.OracleService.Tests/config.json b/tests/Neo.Plugins.OracleService.Tests/config.json index 67bc3a62fa..edcd76127a 100644 --- a/tests/Neo.Plugins.OracleService.Tests/config.json +++ b/tests/Neo.Plugins.OracleService.Tests/config.json @@ -28,7 +28,7 @@ } }, "ProtocolConfiguration": { - "Network": 860833102, + "Network": 5195086, "AddressVersion": 53, "MillisecondsPerBlock": 15000, "MaxTransactionsPerBlock": 512, @@ -39,29 +39,9 @@ "HF_Basilisk": 4120000 }, "InitialGasDistribution": 5200000000000000, - "ValidatorsCount": 7, + "ValidatorsCount": 1, "StandbyCommittee": [ - "03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c", - "02df48f60e8f3e01c48ff40b9b7f1310d7a8b2a193188befe1c2e3df740e895093", - "03b8d9d5771d8f513aa0869b9cc8d50986403b78c6da36890638c3d46a5adce04a", - "02ca0e27697b9c248f6f16e085fd0061e26f44da85b58ee835c110caa5ec3ba554", - "024c7b7fb6c310fccf1ba33b082519d82964ea93868d676662d4a59ad548df0e7d", - "02aaec38470f6aad0042c6e877cfd8087d2676b0f516fddd362801b9bd3936399e", - "02486fd15702c4490a26703112a5cc1d0923fd697a33406bd5a1c00e0013b09a70", - "023a36c72844610b4d34d1968662424011bf783ca9d984efa19a20babf5582f3fe", - "03708b860c1de5d87f5b151a12c2a99feebd2e8b315ee8e7cf8aa19692a9e18379", - "03c6aa6e12638b36e88adc1ccdceac4db9929575c3e03576c617c49cce7114a050", - "03204223f8c86b8cd5c89ef12e4f0dbb314172e9241e30c9ef2293790793537cf0", - "02a62c915cf19c7f19a50ec217e79fac2439bbaad658493de0c7d8ffa92ab0aa62", - "03409f31f0d66bdc2f70a9730b66fe186658f84a8018204db01c106edc36553cd0", - "0288342b141c30dc8ffcde0204929bb46aed5756b41ef4a56778d15ada8f0c6654", - "020f2887f41474cfeb11fd262e982051c1541418137c02a0f4961af911045de639", - "0222038884bbd1d8ff109ed3bdef3542e768eef76c1247aea8bc8171f532928c30", - "03d281b42002647f0113f36c7b8efb30db66078dfaaa9ab3ff76d043a98d512fde", - "02504acbc1f4b3bdad1d86d6e1a08603771db135a73e61c9d565ae06a1938cd2ad", - "0226933336f1b75baa42d42b71d9091508b638046d19abd67f4e119bf64a7cfb4d", - "03cdcea66032b82f5c30450e381e5295cae85c5e6943af716cc6b646352a6067dc", - "02cd5a5547119e24feaa7c2a0f37b8c9366216bab7054de0065c9be42084003c8a" + "0278ed78c917797b637a7ed6e7a9d94e8c408444c41ee4c0a0f310a256b9271eda" ], "SeedList": [ "seed1.neo.org:10333", From 978828005474dce455fe368e6e275f30293a5411 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Sat, 7 Sep 2024 07:00:40 +0800 Subject: [PATCH 4/4] [Neo Plugin RPC] update rpc node methods signatures to use explicit parameter types. (#3479) * update rpc node methods signatures to use explicit parameter types. * fix attribute place --------- Co-authored-by: Christopher Schuchardt Co-authored-by: Shargon --- src/Plugins/RpcServer/RpcServer.Node.cs | 60 +++++++++++++++---- .../UT_RpcServer.Node.cs | 44 +++++++------- 2 files changed, 69 insertions(+), 35 deletions(-) diff --git a/src/Plugins/RpcServer/RpcServer.Node.cs b/src/Plugins/RpcServer/RpcServer.Node.cs index c1b5397c5b..23c731d01e 100644 --- a/src/Plugins/RpcServer/RpcServer.Node.cs +++ b/src/Plugins/RpcServer/RpcServer.Node.cs @@ -23,14 +23,23 @@ namespace Neo.Plugins.RpcServer { partial class RpcServer { - [RpcMethod] - protected internal virtual JToken GetConnectionCount(JArray _params) + + /// + /// Gets the current number of connections to the node. + /// + /// The number of connections as a JToken. + [RpcMethodWithParams] + protected internal virtual JToken GetConnectionCount() { return localNode.ConnectedCount; } - [RpcMethod] - protected internal virtual JToken GetPeers(JArray _params) + /// + /// Gets information about the peers connected to the node. + /// + /// A JObject containing information about unconnected, bad, and connected peers. + [RpcMethodWithParams] + protected internal virtual JToken GetPeers() { JObject json = new(); json["unconnected"] = new JArray(localNode.GetUnconnectedPeers().Select(p => @@ -51,9 +60,14 @@ protected internal virtual JToken GetPeers(JArray _params) return json; } + /// + /// Processes the result of a transaction or block relay and returns appropriate response or throws an exception. + /// + /// The verification result of the relay. + /// The hash of the transaction or block. + /// A JObject containing the hash if successful, otherwise throws an RpcException. private static JObject GetRelayResult(VerifyResult reason, UInt256 hash) { - switch (reason) { case VerifyResult.Succeed: @@ -109,8 +123,12 @@ private static JObject GetRelayResult(VerifyResult reason, UInt256 hash) } } - [RpcMethod] - protected internal virtual JToken GetVersion(JArray _params) + /// + /// Gets version information about the node, including network, protocol, and RPC settings. + /// + /// A JObject containing detailed version and configuration information. + [RpcMethodWithParams] + protected internal virtual JToken GetVersion() { JObject json = new(); json["tcpport"] = localNode.ListenerTcpPort; @@ -146,23 +164,39 @@ protected internal virtual JToken GetVersion(JArray _params) return json; } + /// + /// Removes a specified prefix from a string if it exists. + /// + /// The input string. + /// The prefix to remove. + /// The string with the prefix removed if it existed, otherwise the original string. private static string StripPrefix(string s, string prefix) { return s.StartsWith(prefix) ? s.Substring(prefix.Length) : s; } - [RpcMethod] - protected internal virtual JToken SendRawTransaction(JArray _params) + /// + /// Sends a raw transaction to the network. + /// + /// The base64-encoded transaction. + /// A JToken containing the result of the transaction relay. + [RpcMethodWithParams] + protected internal virtual JToken SendRawTransaction(string base64Tx) { - Transaction tx = Result.Ok_Or(() => Convert.FromBase64String(_params[0].AsString()).AsSerializable(), RpcError.InvalidParams.WithData($"Invalid Transaction Format: {_params[0]}")); + Transaction tx = Result.Ok_Or(() => Convert.FromBase64String(base64Tx).AsSerializable(), RpcError.InvalidParams.WithData($"Invalid Transaction Format: {base64Tx}")); RelayResult reason = system.Blockchain.Ask(tx).Result; return GetRelayResult(reason.Result, tx.Hash); } - [RpcMethod] - protected internal virtual JToken SubmitBlock(JArray _params) + /// + /// Submits a new block to the network. + /// + /// The base64-encoded block. + /// A JToken containing the result of the block submission. + [RpcMethodWithParams] + protected internal virtual JToken SubmitBlock(string base64Block) { - Block block = Result.Ok_Or(() => Convert.FromBase64String(_params[0].AsString()).AsSerializable(), RpcError.InvalidParams.WithData($"Invalid Block Format: {_params[0]}")); + Block block = Result.Ok_Or(() => Convert.FromBase64String(base64Block).AsSerializable(), RpcError.InvalidParams.WithData($"Invalid Block Format: {base64Block}")); RelayResult reason = system.Blockchain.Ask(block).Result; return GetRelayResult(reason.Result, block.Hash); } diff --git a/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Node.cs b/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Node.cs index cf674a449c..042bde0d30 100644 --- a/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Node.cs +++ b/tests/Neo.Plugins.RpcServer.Tests/UT_RpcServer.Node.cs @@ -29,7 +29,7 @@ partial class UT_RpcServer [TestMethod] public void TestGetConnectionCount() { - var result = _rpcServer.GetConnectionCount(new JArray()); + var result = _rpcServer.GetConnectionCount(); result.GetType().Should().Be(typeof(JNumber)); } @@ -44,7 +44,7 @@ public void TestGetPeers() 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()); + var result = rpcServer.GetPeers(); Assert.IsInstanceOfType(result, typeof(JObject)); var json = (JObject)result; json.ContainsProperty("unconnected").Should().BeTrue(); @@ -56,7 +56,7 @@ public void TestGetPeers() [TestMethod] public void TestGetVersion() { - var result = _rpcServer.GetVersion(new JArray()); + var result = _rpcServer.GetVersion(); Assert.IsInstanceOfType(result, typeof(JObject)); var json = (JObject)result; @@ -87,7 +87,7 @@ public void TestSendRawTransaction_Normal() var tx = TestUtils.CreateValidTx(snapshot, _wallet, _walletAccount); var txString = Convert.ToBase64String(tx.ToArray()); - var result = _rpcServer.SendRawTransaction(new JArray(txString)); + var result = _rpcServer.SendRawTransaction(txString); Assert.IsInstanceOfType(result, typeof(JObject)); Assert.IsTrue(((JObject)result).ContainsProperty("hash")); } @@ -96,7 +96,7 @@ public void TestSendRawTransaction_Normal() public void TestSendRawTransaction_InvalidTransactionFormat() { Assert.ThrowsException(() => - _rpcServer.SendRawTransaction(new JArray("invalid_transaction_string")), + _rpcServer.SendRawTransaction("invalid_transaction_string"), "Should throw RpcException for invalid transaction format"); } @@ -108,7 +108,7 @@ public void TestSendRawTransaction_InsufficientBalance() var txString = Convert.ToBase64String(tx.ToArray()); var exception = Assert.ThrowsException(() => - _rpcServer.SendRawTransaction(new JArray(txString)), + _rpcServer.SendRawTransaction(txString), "Should throw RpcException for insufficient balance"); Assert.AreEqual(RpcError.InsufficientFunds.Code, exception.HResult); } @@ -121,7 +121,7 @@ public void TestSendRawTransaction_InvalidSignature() var txString = Convert.ToBase64String(tx.ToArray()); var exception = Assert.ThrowsException(() => - _rpcServer.SendRawTransaction(new JArray(txString)), + _rpcServer.SendRawTransaction(txString), "Should throw RpcException for invalid signature"); Assert.AreEqual(RpcError.InvalidSignature.Code, exception.HResult); } @@ -134,7 +134,7 @@ public void TestSendRawTransaction_InvalidScript() var txString = Convert.ToBase64String(tx.ToArray()); var exception = Assert.ThrowsException(() => - _rpcServer.SendRawTransaction(new JArray(txString)), + _rpcServer.SendRawTransaction(txString), "Should throw RpcException for invalid script"); Assert.AreEqual(RpcError.InvalidScript.Code, exception.HResult); } @@ -147,7 +147,7 @@ public void TestSendRawTransaction_InvalidAttribute() var txString = Convert.ToBase64String(tx.ToArray()); var exception = Assert.ThrowsException(() => - _rpcServer.SendRawTransaction(new JArray(txString)), + _rpcServer.SendRawTransaction(txString), "Should throw RpcException for invalid attribute"); // Transaction with invalid attribute can not pass the Transaction deserialization // and will throw invalid params exception. @@ -162,7 +162,7 @@ public void TestSendRawTransaction_Oversized() var txString = Convert.ToBase64String(tx.ToArray()); var exception = Assert.ThrowsException(() => - _rpcServer.SendRawTransaction(new JArray(txString)), + _rpcServer.SendRawTransaction(txString), "Should throw RpcException for invalid format transaction"); // Oversized transaction will not pass the deserialization. Assert.AreEqual(RpcError.InvalidParams.Code, exception.HResult); @@ -176,7 +176,7 @@ public void TestSendRawTransaction_Expired() var txString = Convert.ToBase64String(tx.ToArray()); var exception = Assert.ThrowsException(() => - _rpcServer.SendRawTransaction(new JArray(txString)), + _rpcServer.SendRawTransaction(txString), "Should throw RpcException for expired transaction"); Assert.AreEqual(RpcError.ExpiredTransaction.Code, exception.HResult); } @@ -191,7 +191,7 @@ public void TestSendRawTransaction_PolicyFailed() snapshot.Commit(); var exception = Assert.ThrowsException(() => - _rpcServer.SendRawTransaction(new JArray(txString)), + _rpcServer.SendRawTransaction(txString), "Should throw RpcException for conflicting transaction"); Assert.AreEqual(RpcError.PolicyFailed.Code, exception.HResult); } @@ -205,7 +205,7 @@ public void TestSendRawTransaction_AlreadyInPool() var txString = Convert.ToBase64String(tx.ToArray()); var exception = Assert.ThrowsException(() => - _rpcServer.SendRawTransaction(new JArray(txString)), + _rpcServer.SendRawTransaction(txString), "Should throw RpcException for transaction already in memory pool"); Assert.AreEqual(RpcError.AlreadyInPool.Code, exception.HResult); } @@ -218,7 +218,7 @@ public void TestSendRawTransaction_AlreadyInBlockchain() TestUtils.AddTransactionToBlockchain(snapshot, tx); snapshot.Commit(); var txString = Convert.ToBase64String(tx.ToArray()); - var exception = Assert.ThrowsException(() => _rpcServer.SendRawTransaction(new JArray(txString))); + var exception = Assert.ThrowsException(() => _rpcServer.SendRawTransaction(txString)); Assert.AreEqual(RpcError.AlreadyExists.Code, exception.HResult); } @@ -233,7 +233,7 @@ public void TestSubmitBlock_Normal() var block = TestUtils.CreateBlockWithValidTransactions(snapshot, _wallet, _walletAccount, 1); var blockString = Convert.ToBase64String(block.ToArray()); - var result = _rpcServer.SubmitBlock(new JArray(blockString)); + var result = _rpcServer.SubmitBlock(blockString); Assert.IsInstanceOfType(result, typeof(JObject)); Assert.IsTrue(((JObject)result).ContainsProperty("hash")); } @@ -244,7 +244,7 @@ public void TestSubmitBlock_InvalidBlockFormat() string invalidBlockString = TestUtils.CreateInvalidBlockFormat(); var exception = Assert.ThrowsException(() => - _rpcServer.SubmitBlock(new JArray(invalidBlockString)), + _rpcServer.SubmitBlock(invalidBlockString), "Should throw RpcException for invalid block format"); Assert.AreEqual(RpcError.InvalidParams.Code, exception.HResult); @@ -261,7 +261,7 @@ public void TestSubmitBlock_AlreadyExists() var blockString = Convert.ToBase64String(block.ToArray()); var exception = Assert.ThrowsException(() => - _rpcServer.SubmitBlock(new JArray(blockString)), + _rpcServer.SubmitBlock(blockString), "Should throw RpcException when block already exists"); Assert.AreEqual(RpcError.AlreadyExists.Code, exception.HResult); } @@ -275,7 +275,7 @@ public void TestSubmitBlock_InvalidBlock() var blockString = Convert.ToBase64String(block.ToArray()); var exception = Assert.ThrowsException(() => - _rpcServer.SubmitBlock(new JArray(blockString)), + _rpcServer.SubmitBlock(blockString), "Should throw RpcException for invalid block"); Assert.AreEqual(RpcError.VerificationFailed.Code, exception.HResult); } @@ -288,7 +288,7 @@ public void TestSubmitBlock_InvalidBlock() public void TestSendRawTransaction_NullInput() { var exception = Assert.ThrowsException(() => - _rpcServer.SendRawTransaction(new JArray((string)null)), + _rpcServer.SendRawTransaction((string)null), "Should throw RpcException for null input"); Assert.AreEqual(RpcError.InvalidParams.Code, exception.HResult); } @@ -297,7 +297,7 @@ public void TestSendRawTransaction_NullInput() public void TestSendRawTransaction_EmptyInput() { var exception = Assert.ThrowsException(() => - _rpcServer.SendRawTransaction(new JArray(string.Empty)), + _rpcServer.SendRawTransaction(string.Empty), "Should throw RpcException for empty input"); Assert.AreEqual(RpcError.InvalidParams.Code, exception.HResult); } @@ -306,7 +306,7 @@ public void TestSendRawTransaction_EmptyInput() public void TestSubmitBlock_NullInput() { var exception = Assert.ThrowsException(() => - _rpcServer.SubmitBlock(new JArray((string)null)), + _rpcServer.SubmitBlock((string)null), "Should throw RpcException for null input"); Assert.AreEqual(RpcError.InvalidParams.Code, exception.HResult); } @@ -315,7 +315,7 @@ public void TestSubmitBlock_NullInput() public void TestSubmitBlock_EmptyInput() { var exception = Assert.ThrowsException(() => - _rpcServer.SubmitBlock(new JArray(string.Empty)), + _rpcServer.SubmitBlock(string.Empty), "Should throw RpcException for empty input"); Assert.AreEqual(RpcError.InvalidParams.Code, exception.HResult); }