NAC_Blockchain/nac-nrpc/src/protocol.rs

254 lines
6.2 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//! NRPC 3.0协议类型定义
//!
//! 定义NRPC 3.0协议的核心数据结构
use nac_udm::primitives::{Hash, Timestamp};
use serde::{Deserialize, Serialize};
use serde_json::Value;
/// NRPC 3.0请求
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NRPC3Request {
/// JSON-RPC版本固定为"3.0"
pub jsonrpc: String,
/// 请求ID
pub id: RequestId,
/// 方法名
pub method: String,
/// 参数
pub params: Value,
/// 时间戳NAC扩展
#[serde(skip_serializing_if = "Option::is_none")]
pub timestamp: Option<Timestamp>,
/// 资产DNA哈希NAC扩展
#[serde(skip_serializing_if = "Option::is_none")]
pub dna_hash: Option<Hash>,
/// 签名NAC扩展
#[serde(skip_serializing_if = "Option::is_none")]
pub signature: Option<String>,
}
/// NRPC 3.0响应
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NRPC3Response {
/// JSON-RPC版本
pub jsonrpc: String,
/// 请求ID
pub id: RequestId,
/// 结果(成功时)
#[serde(skip_serializing_if = "Option::is_none")]
pub result: Option<Value>,
/// 错误(失败时)
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<NRPC3Error>,
/// 时间戳NAC扩展
#[serde(skip_serializing_if = "Option::is_none")]
pub timestamp: Option<Timestamp>,
/// 服务器签名NAC扩展
#[serde(skip_serializing_if = "Option::is_none")]
pub server_signature: Option<String>,
}
/// NRPC 3.0错误
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NRPC3Error {
/// 错误代码
pub code: i32,
/// 错误消息
pub message: String,
/// 错误数据(可选)
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<Value>,
}
/// 请求ID类型
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
#[serde(untagged)]
pub enum RequestId {
/// 数字ID
Number(u64),
/// 字符串ID
String(String),
/// 空ID通知
Null,
}
/// NRPC 3.0批量请求
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NRPC3BatchRequest {
/// 批量请求列表
pub requests: Vec<NRPC3Request>,
}
/// NRPC 3.0批量响应
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NRPC3BatchResponse {
/// 批量响应列表
pub responses: Vec<NRPC3Response>,
}
/// NRPC 3.0错误代码
pub mod error_codes {
/// 解析错误
pub const PARSE_ERROR: i32 = -32700;
/// 无效请求
pub const INVALID_REQUEST: i32 = -32600;
/// 方法不存在
pub const METHOD_NOT_FOUND: i32 = -32601;
/// 无效参数
pub const INVALID_PARAMS: i32 = -32602;
/// 内部错误
pub const INTERNAL_ERROR: i32 = -32603;
/// 服务器错误范围
pub const SERVER_ERROR_START: i32 = -32000;
pub const SERVER_ERROR_END: i32 = -32099;
// NAC扩展错误代码
/// 时间戳过期
pub const TIMESTAMP_EXPIRED: i32 = -33001;
/// DNA验证失败
pub const DNA_VERIFICATION_FAILED: i32 = -33002;
/// 签名无效
pub const INVALID_SIGNATURE: i32 = -33003;
/// 合规检查失败
pub const COMPLIANCE_CHECK_FAILED: i32 = -33004;
/// 权限不足
pub const INSUFFICIENT_PERMISSIONS: i32 = -33005;
}
impl NRPC3Request {
/// 创建新请求
pub fn new(id: RequestId, method: impl Into<String>, params: Value) -> Self {
Self {
jsonrpc: "3.0".to_string(),
id,
method: method.into(),
params,
timestamp: Some(Timestamp::now()),
dna_hash: None,
signature: None,
}
}
/// 验证请求
pub fn validate(&self) -> Result<(), String> {
if self.jsonrpc != "3.0" {
return Err("Invalid JSON-RPC version".to_string());
}
if self.method.is_empty() {
return Err("Method name cannot be empty".to_string());
}
// 验证时间戳(如果存在)
if let Some(ts) = self.timestamp {
let now = Timestamp::now();
let diff = if now > ts { now - ts } else { ts - now };
// 允许5分钟的时间偏差
if diff > 300 {
return Err("Timestamp expired or too far in future".to_string());
}
}
Ok(())
}
}
impl NRPC3Response {
/// 创建成功响应
pub fn success(id: RequestId, result: Value) -> Self {
Self {
jsonrpc: "3.0".to_string(),
id,
result: Some(result),
error: None,
timestamp: Some(Timestamp::now()),
server_signature: None,
}
}
/// 创建错误响应
pub fn error(id: RequestId, code: i32, message: impl Into<String>) -> Self {
Self {
jsonrpc: "3.0".to_string(),
id,
result: None,
error: Some(NRPC3Error {
code,
message: message.into(),
data: None,
}),
timestamp: Some(Timestamp::now()),
server_signature: None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_request_creation() {
let req = NRPC3Request::new(
RequestId::Number(1),
"test_method",
json!({"param": "value"}),
);
assert_eq!(req.jsonrpc, "3.0");
assert_eq!(req.method, "test_method");
assert!(req.timestamp.is_some());
}
#[test]
fn test_request_validation() {
let req = NRPC3Request::new(
RequestId::Number(1),
"test_method",
json!({}),
);
assert!(req.validate().is_ok());
}
#[test]
fn test_response_creation() {
let resp = NRPC3Response::success(
RequestId::Number(1),
json!({"result": "success"}),
);
assert_eq!(resp.jsonrpc, "3.0");
assert!(resp.result.is_some());
assert!(resp.error.is_none());
}
}