Skip to content

Commit da0650c

Browse files
authored
Merge branch 'master' into new-storage
2 parents 621a643 + 79f0d78 commit da0650c

File tree

19 files changed

+522
-214
lines changed

19 files changed

+522
-214
lines changed

.devcontainer/devcontainer.json

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
2+
// README at: https://github.com/devcontainers/templates/tree/main/src/dotnet
3+
{
4+
"name": "C# (.NET)",
5+
"image": "mcr.microsoft.com/devcontainers/dotnet:1-7.0-jammy",
6+
"onCreateCommand": "./scripts/load_submodule.sh",
7+
"postCreateCommand": "dotnet restore && dotnet build",
8+
"customizations": {
9+
"vscode": {
10+
"extensions": [
11+
"ms-dotnettools.csdevkit"
12+
]
13+
}
14+
}
15+
}

.github/workflows/main.yml

-8
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,6 @@ jobs:
4848
- name: Checkout Repo
4949
uses: actions/checkout@v4
5050

51-
- name: AI Code Reviewer
52-
uses: freeedcom/ai-codereviewer@a9a064dfa1db8c83f40ef63f6e247fa09c935ed6
53-
with:
54-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
55-
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
56-
OPENAI_API_MODEL: "gpt-4" # Optional: defaults to "gpt-4"
57-
exclude: "**/*.json, **/*.md" # Optional: exclude patterns separated by commas
58-
5951
Release:
6052
needs: Test
6153
if: github.ref == 'refs/heads/master' && startsWith(github.repository, 'neo-project/')

scripts/load_submodule.sh

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
3+
# Check if the current directory is a git repository
4+
if [ ! -d ".git" ]; then
5+
echo "Error: This script must be run from the root of a Git repository."
6+
exit 1
7+
fi
8+
9+
# Initialize and update git submodules
10+
git submodule update --init --recursive
11+
12+
echo "Git submodules have been updated."

src/DBFTPlugin/Consensus/ConsensusService.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ private void OnStart()
157157
return;
158158
}
159159
}
160-
InitializeConsensus(0);
160+
InitializeConsensus(context.ViewNumber);
161161
// Issue a recovery request on start-up in order to possibly catch up with other nodes
162162
if (!context.WatchOnly)
163163
RequestRecovery();

src/OracleService/OracleService.cs

+9-11
Original file line numberDiff line numberDiff line change
@@ -220,24 +220,22 @@ private async void OnTimer(object state)
220220
[RpcMethod]
221221
public JObject SubmitOracleResponse(JArray _params)
222222
{
223-
if (status != OracleStatus.Running) throw new InvalidOperationException();
223+
status.Equals(OracleStatus.Running).True_Or(RpcError.OracleDisabled);
224224
ECPoint oraclePub = ECPoint.DecodePoint(Convert.FromBase64String(_params[0].AsString()), ECCurve.Secp256r1);
225-
ulong requestId = (ulong)_params[1].AsNumber();
226-
byte[] txSign = Convert.FromBase64String(_params[2].AsString());
227-
byte[] msgSign = Convert.FromBase64String(_params[3].AsString());
225+
ulong requestId = Result.Ok_Or(() => (ulong)_params[1].AsNumber(), RpcError.InvalidParams.WithData($"Invalid requestId: {_params[1]}"));
226+
byte[] txSign = Result.Ok_Or(() => Convert.FromBase64String(_params[2].AsString()), RpcError.InvalidParams.WithData($"Invalid txSign: {_params[2]}"));
227+
byte[] msgSign = Result.Ok_Or(() => Convert.FromBase64String(_params[3].AsString()), RpcError.InvalidParams.WithData($"Invalid msgSign: {_params[3]}"));
228228

229-
if (finishedCache.ContainsKey(requestId)) throw new RpcException(-100, "Request has already finished");
229+
finishedCache.ContainsKey(requestId).False_Or(RpcError.OracleRequestFinished);
230230

231231
using (var snapshot = System.GetSnapshot())
232232
{
233233
uint height = NativeContract.Ledger.CurrentIndex(snapshot) + 1;
234234
var oracles = NativeContract.RoleManagement.GetDesignatedByRole(snapshot, Role.Oracle, height);
235-
if (!oracles.Any(p => p.Equals(oraclePub))) throw new RpcException(-100, $"{oraclePub} isn't an oracle node");
236-
if (NativeContract.Oracle.GetRequest(snapshot, requestId) is null)
237-
throw new RpcException(-100, "Request is not found");
235+
oracles.Any(p => p.Equals(oraclePub)).True_Or(RpcErrorFactory.OracleNotDesignatedNode(oraclePub));
236+
NativeContract.Oracle.GetRequest(snapshot, requestId).NotNull_Or(RpcError.OracleRequestNotFound);
238237
var data = Neo.Helper.Concat(oraclePub.ToArray(), BitConverter.GetBytes(requestId), txSign);
239-
if (!Crypto.VerifySignature(data, msgSign, oraclePub)) throw new RpcException(-100, "Invalid sign");
240-
238+
Crypto.VerifySignature(data, msgSign, oraclePub).True_Or(RpcErrorFactory.InvalidSignature($"Invalid oracle response transaction signature from '{oraclePub}'."));
241239
AddResponseTxSign(snapshot, requestId, oraclePub, txSign);
242240
}
243241
return new JObject();
@@ -497,7 +495,7 @@ private void AddResponseTxSign(DataCache snapshot, ulong requestId, ECPoint orac
497495
else if (Crypto.VerifySignature(task.BackupTx.GetSignData(System.Settings.Network), sign, oraclePub))
498496
task.BackupSigns.TryAdd(oraclePub, sign);
499497
else
500-
throw new RpcException(-100, "Invalid response transaction sign");
498+
throw new RpcException(RpcErrorFactory.InvalidSignature($"Invalid oracle response transaction signature from '{oraclePub}'."));
501499

502500
if (CheckTxSign(snapshot, task.Tx, task.Signs) || CheckTxSign(snapshot, task.BackupTx, task.BackupSigns))
503501
{

src/RpcServer/Result.cs

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// Copyright (C) 2015-2024 The Neo Project.
2+
//
3+
// Result.cs file belongs to the neo project and is free
4+
// software distributed under the MIT software license, see the
5+
// accompanying file LICENSE in the main directory of the
6+
// repository or http://www.opensource.org/licenses/mit-license.php
7+
// for more details.
8+
//
9+
// Redistribution and use in source and binary forms with or without
10+
// modifications are permitted.
11+
12+
using System;
13+
namespace Neo.Plugins
14+
{
15+
public static class Result
16+
{
17+
/// <summary>
18+
/// Checks the execution result of a function and throws an exception if it is null or throw an exception.
19+
/// </summary>
20+
/// <param name="function">The function to execute</param>
21+
/// <param name="err">The rpc error</param>
22+
/// <param name="withData">Append extra base exception message</param>
23+
/// <typeparam name="T">The return type</typeparam>
24+
/// <returns>The execution result</returns>
25+
/// <exception cref="RpcException">The Rpc exception</exception>
26+
public static T Ok_Or<T>(this Func<T> function, RpcError err, bool withData = false)
27+
{
28+
try
29+
{
30+
var result = function();
31+
if (result == null) throw new RpcException(err);
32+
return result;
33+
}
34+
catch (Exception ex)
35+
{
36+
if (withData)
37+
throw new RpcException(err.WithData(ex.GetBaseException().Message));
38+
throw new RpcException(err);
39+
}
40+
}
41+
42+
/// <summary>
43+
/// Checks the execution result and throws an exception if it is null.
44+
/// </summary>
45+
/// <param name="result">The execution result</param>
46+
/// <param name="err">The rpc error</param>
47+
/// <typeparam name="T">The return type</typeparam>
48+
/// <returns>The execution result</returns>
49+
/// <exception cref="RpcException">The Rpc exception</exception>
50+
public static T NotNull_Or<T>(this T result, RpcError err)
51+
{
52+
if (result == null) throw new RpcException(err);
53+
return result;
54+
}
55+
56+
/// <summary>
57+
/// The execution result is true or throws an exception or null.
58+
/// </summary>
59+
/// <param name="function">The function to execute</param>
60+
/// <param name="err">the rpc exception code</param>
61+
/// <returns>the execution result</returns>
62+
/// <exception cref="RpcException">The rpc exception</exception>
63+
public static bool True_Or(Func<bool> function, RpcError err)
64+
{
65+
try
66+
{
67+
var result = function();
68+
if (!result.Equals(true)) throw new RpcException(err);
69+
return result;
70+
}
71+
catch
72+
{
73+
throw new RpcException(err);
74+
}
75+
}
76+
77+
/// <summary>
78+
/// Checks if the execution result is true or throws an exception.
79+
/// </summary>
80+
/// <param name="result">the execution result</param>
81+
/// <param name="err">the rpc exception code</param>
82+
/// <returns>the execution result</returns>
83+
/// <exception cref="RpcException">The rpc exception</exception>
84+
public static bool True_Or(this bool result, RpcError err)
85+
{
86+
if (!result.Equals(true)) throw new RpcException(err);
87+
return result;
88+
}
89+
90+
/// <summary>
91+
/// Checks if the execution result is false or throws an exception.
92+
/// </summary>
93+
/// <param name="result">the execution result</param>
94+
/// <param name="err">the rpc exception code</param>
95+
/// <returns>the execution result</returns>
96+
/// <exception cref="RpcException">The rpc exception</exception>
97+
public static bool False_Or(this bool result, RpcError err)
98+
{
99+
if (!result.Equals(false)) throw new RpcException(err);
100+
return result;
101+
}
102+
103+
/// <summary>
104+
/// Check if the execution result is null or throws an exception.
105+
/// </summary>
106+
/// <param name="result">The execution result</param>
107+
/// <param name="err">the rpc error</param>
108+
/// <typeparam name="T">The execution result type</typeparam>
109+
/// <returns>The execution result</returns>
110+
/// <exception cref="RpcException">the rpc exception</exception>
111+
public static void Null_Or<T>(this T result, RpcError err)
112+
{
113+
if (result != null) throw new RpcException(err);
114+
}
115+
}
116+
}

src/RpcServer/RpcError.cs

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright (C) 2015-2024 The Neo Project.
2+
//
3+
// RpcError.cs file belongs to the neo project and is free
4+
// software distributed under the MIT software license, see the
5+
// accompanying file LICENSE in the main directory of the
6+
// repository or http://www.opensource.org/licenses/mit-license.php
7+
// for more details.
8+
//
9+
// Redistribution and use in source and binary forms with or without
10+
// modifications are permitted.
11+
12+
using Neo.Json;
13+
14+
namespace Neo.Plugins
15+
{
16+
public class RpcError
17+
{
18+
#region Default Values
19+
20+
// https://www.jsonrpc.org/specification
21+
// | code | message | meaning |
22+
// |--------------------|-----------------|-----------------------------------------------------------------------------------|
23+
// | -32700 | Parse error | Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text. |
24+
// | -32600 | Invalid request | The JSON sent is not a valid Request object. |
25+
// | -32601 | Method not found| The method does not exist / is not available. |
26+
// | -32602 | Invalid params | Invalid method parameter(s). |
27+
// | -32603 | Internal error | Internal JSON-RPC error. |
28+
// | -32000 to -32099 | Server error | Reserved for implementation-defined server-errors. |
29+
public static readonly RpcError InvalidRequest = new(-32600, "Invalid request");
30+
public static readonly RpcError MethodNotFound = new(-32601, "Method not found");
31+
public static readonly RpcError InvalidParams = new(-32602, "Invalid params");
32+
public static readonly RpcError InternalServerError = new(-32603, "Internal server RpcError");
33+
public static readonly RpcError BadRequest = new(-32700, "Bad request");
34+
35+
// https://github.com/neo-project/proposals/pull/156/files
36+
public static readonly RpcError UnknownBlock = new(-101, "Unknown block");
37+
public static readonly RpcError UnknownContract = new(-102, "Unknown contract");
38+
public static readonly RpcError UnknownTransaction = new(-103, "Unknown transaction");
39+
public static readonly RpcError UnknownStorageItem = new(-104, "Unknown storage item");
40+
public static readonly RpcError UnknownScriptContainer = new(-105, "Unknown script container");
41+
public static readonly RpcError UnknownStateRoot = new(-106, "Unknown state root");
42+
public static readonly RpcError UnknownSession = new(-107, "Unknown session");
43+
public static readonly RpcError UnknownIterator = new(-108, "Unknown iterator");
44+
public static readonly RpcError UnknownHeight = new(-109, "Unknown height");
45+
46+
public static readonly RpcError InsufficientFundsWallet = new(-300, "Insufficient funds in wallet");
47+
public static readonly RpcError WalletFeeLimit = new(-301, "Wallet fee limit exceeded", "The necessary fee is more than the Max_fee, this transaction is failed. Please increase your Max_fee value.");
48+
public static readonly RpcError NoOpenedWallet = new(-302, "No opened wallet");
49+
public static readonly RpcError WalletNotFound = new(-303, "Wallet not found");
50+
public static readonly RpcError WalletNotSupported = new(-304, "Wallet not supported");
51+
52+
public static readonly RpcError VerificationFailed = new(-500, "Inventory verification failed");
53+
public static readonly RpcError AlreadyExists = new(-501, "Inventory already exists");
54+
public static readonly RpcError MempoolCapReached = new(-502, "Memory pool capacity reached");
55+
public static readonly RpcError AlreadyInPool = new(-503, "Already in pool");
56+
public static readonly RpcError InsufficientNetworkFee = new(-504, "Insufficient network fee");
57+
public static readonly RpcError PolicyFailed = new(-505, "Policy check failed");
58+
public static readonly RpcError InvalidScript = new(-509, "Invalid transaction script");
59+
public static readonly RpcError InvalidAttribute = new(-507, "Invalid transaction attribute");
60+
public static readonly RpcError InvalidSignature = new(-508, "Invalid signature");
61+
public static readonly RpcError InvalidSize = new(-509, "Invalid inventory size");
62+
public static readonly RpcError ExpiredTransaction = new(-510, "Expired transaction");
63+
public static readonly RpcError InsufficientFunds = new(-511, "Insufficient funds for fee");
64+
public static readonly RpcError InvalidContractVerification = new(-512, "Invalid contract verification function");
65+
66+
public static readonly RpcError AccessDenied = new(-600, "Access denied");
67+
public static readonly RpcError SessionsDisabled = new(-601, "State iterator sessions disabled");
68+
public static readonly RpcError OracleDisabled = new(-602, "Oracle service disabled");
69+
public static readonly RpcError OracleRequestFinished = new(-603, "Oracle request already finished");
70+
public static readonly RpcError OracleRequestNotFound = new(-604, "Oracle request not found");
71+
public static readonly RpcError OracleNotDesignatedNode = new(-605, "Not a designated oracle node");
72+
public static readonly RpcError UnsupportedState = new(-606, "Old state not supported");
73+
public static readonly RpcError InvalidProof = new(-607, "Invalid state proof");
74+
public static readonly RpcError ExecutionFailed = new(-608, "Contract execution failed");
75+
76+
#endregion
77+
78+
public int Code { get; set; }
79+
public string Message { get; set; }
80+
public string Data { get; set; }
81+
82+
public RpcError(int code, string message, string data = null)
83+
{
84+
Code = code;
85+
Message = message;
86+
Data = data;
87+
}
88+
89+
public override string ToString() => string.IsNullOrEmpty(Data) ? $"{Message} ({Code})" : $"{Message} ({Code}) - {Data}";
90+
91+
public JToken ToJson()
92+
{
93+
JObject json = new();
94+
json["code"] = Code;
95+
json["message"] = ErrorMessage;
96+
if (!string.IsNullOrEmpty(Data))
97+
json["data"] = Data;
98+
return json;
99+
}
100+
101+
public string ErrorMessage => string.IsNullOrEmpty(Data) ? $"{Message}" : $"{Message} - {Data}";
102+
}
103+
}

src/RpcServer/RpcErrorFactory.cs

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (C) 2015-2024 The Neo Project.
2+
//
3+
// RpcErrorFactory.cs file belongs to the neo project and is free
4+
// software distributed under the MIT software license, see the
5+
// accompanying file LICENSE in the main directory of the
6+
// repository or http://www.opensource.org/licenses/mit-license.php
7+
// for more details.
8+
//
9+
// Redistribution and use in source and binary forms with or without
10+
// modifications are permitted.
11+
12+
using Neo.Cryptography.ECC;
13+
14+
namespace Neo.Plugins
15+
{
16+
public static class RpcErrorFactory
17+
{
18+
public static RpcError WithData(this RpcError error, string data = null)
19+
{
20+
return new RpcError(error.Code, error.Message, data);
21+
}
22+
23+
public static RpcError NewCustomError(int code, string message, string data = null)
24+
{
25+
return new RpcError(code, message, data);
26+
}
27+
28+
#region Require data
29+
30+
public static RpcError MethodNotFound(string method) => RpcError.MethodNotFound.WithData($"The method '{method}' doesn't exists.");
31+
public static RpcError AlreadyExists(string data) => RpcError.AlreadyExists.WithData(data);
32+
public static RpcError InvalidParams(string data) => RpcError.InvalidParams.WithData(data);
33+
public static RpcError BadRequest(string data) => RpcError.BadRequest.WithData(data);
34+
public static RpcError InsufficientFundsWallet(string data) => RpcError.InsufficientFundsWallet.WithData(data);
35+
public static RpcError VerificationFailed(string data) => RpcError.VerificationFailed.WithData(data);
36+
public static RpcError InvalidContractVerification(UInt160 contractHash) => RpcError.InvalidContractVerification.WithData($"The smart contract {contractHash} haven't got verify method.");
37+
public static RpcError InvalidContractVerification(string data) => RpcError.InvalidContractVerification.WithData(data);
38+
public static RpcError InvalidSignature(string data) => RpcError.InvalidSignature.WithData(data);
39+
public static RpcError OracleNotDesignatedNode(ECPoint oraclePub) => RpcError.OracleNotDesignatedNode.WithData($"{oraclePub} isn't an oracle node.");
40+
41+
#endregion
42+
}
43+
}

src/RpcServer/RpcException.cs

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ namespace Neo.Plugins
1515
{
1616
public class RpcException : Exception
1717
{
18-
public RpcException(int code, string message) : base(message)
18+
public RpcException(RpcError error) : base(error.ErrorMessage)
1919
{
20-
HResult = code;
20+
HResult = error.Code;
2121
}
2222
}
2323
}

0 commit comments

Comments
 (0)