Compare commits

..

No commits in common. "dfe2a85d69d49c6d00bf4e484552d2808a8e6195" and "a3e385480d3018e432efe74cae6eeda8f1fbce89" have entirely different histories.

11 changed files with 206 additions and 3389 deletions

View File

@ -65,7 +65,6 @@ impl BytecodeGenerator {
crate::parser::Type::U32 => 0x02,
crate::parser::Type::F64 => 0x03,
crate::parser::Type::String => 0x04,
crate::parser::Type::U128 => 0x05,
};
self.emit_byte(type_byte);
}
@ -118,7 +117,7 @@ impl BytecodeGenerator {
}
crate::parser::Literal::Int(i) => {
self.emit_byte(0x11); // PUSH_INT
self.emit_u64(*i as u64);
self.emit_u64(*i);
}
crate::parser::Literal::Float(f) => {
self.emit_byte(0x12); // PUSH_FLOAT
@ -199,9 +198,6 @@ impl BytecodeGenerator {
self.emit_byte(0x10); // PUSH_BOOL
self.emit_byte(1); // true
}
Expression::Raw(_) => {
self.emit_byte(0x00);
}
}
Ok(())
@ -255,15 +251,11 @@ mod tests {
id: "TEST".to_string(),
level: ClauseLevel::Eternal,
title: "Test".to_string(),
name: None,
version: None,
description: None,
parameters: vec![],
predicates: vec![],
obligations: vec![],
depends_on: vec![],
}],
tests: vec![],
};
let bytecode = generator.generate_program(&program).expect("Bytecode generation failed");

View File

@ -1,52 +1,169 @@
//! CNNL抽象语法树AST定义
use serde::{Deserialize, Serialize};
/// 程序(顶层节点)
/// CNNL抽象语法树根节点
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Program {
pub clauses: Vec<Clause>,
/// 测试块test "..." { assert ... }
#[serde(default)]
pub tests: Vec<TestBlock>,
}
/// 宪法条款
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Clause {
/// 条款标识符(全大写)
pub id: String,
/// 条款层级
pub level: ClauseLevel,
/// 条款标题
pub title: String,
/// 条款名称name: 字段,可选)
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
/// 版本号version: 字段,可选)
#[serde(skip_serializing_if = "Option::is_none")]
pub version: Option<String>,
/// 描述description: 字段,可选)
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
/// 依赖的其他条款
pub depends_on: Vec<String>,
/// 参数列表
pub parameters: Vec<Parameter>,
/// 谓词列表
pub predicates: Vec<Predicate>,
/// 义务列表
pub obligations: Vec<Obligation>,
}
/// 条款层级
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ClauseLevel {
/// 永恒条款(不可修改)
Eternal,
/// 战略条款(需要超级多数修改)
Strategic,
/// 战术条款(普通多数修改)
Tactical,
Eternal, // 永恒条款
Strategic, // 战略条款
Tactical, // 战术条款
}
/// 宪法参数
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Parameter {
pub name: String,
pub ty: Type,
pub value: Literal,
pub description: Option<String>,
}
/// 宪法谓词
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Predicate {
pub name: String,
pub params: Vec<(String, Type)>,
pub return_type: Type,
pub body: Expression,
}
/// 宪法义务
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Obligation {
pub name: String,
pub frequency: ObligationFrequency,
pub enforcer: String,
pub penalty: String,
}
/// 义务频率
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ObligationFrequency {
Continuous, // 持续
Periodic, // 周期性
OnDemand, // 按需
}
/// 类型
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Type {
Bool,
U64,
U32,
F64,
String,
}
/// 字面量
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Literal {
Bool(bool),
Int(u64),
Float(f64),
String(String),
}
/// 表达式
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Expression {
// 字面量
Literal(Literal),
// 变量引用
Variable(String),
// 二元运算
Binary {
op: BinaryOp,
left: Box<Expression>,
right: Box<Expression>,
},
// 一元运算
Unary {
op: UnaryOp,
operand: Box<Expression>,
},
// 函数调用
Call {
name: String,
args: Vec<Expression>,
},
// if表达式
If {
condition: Box<Expression>,
then_branch: Box<Expression>,
else_branch: Option<Box<Expression>>,
},
// 代码块
Block(Vec<Statement>),
}
/// 二元运算符
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum BinaryOp {
// 算术运算
Add,
Sub,
Mul,
Div,
Mod,
// 比较运算
Eq,
Ne,
Lt,
Le,
Gt,
Ge,
// 逻辑运算
And,
Or,
}
/// 一元运算符
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum UnaryOp {
Not,
Neg,
}
/// 语句
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Statement {
// 表达式语句
Expression(Expression),
// 返回语句
Return(Expression),
// 变量声明
Let {
name: String,
ty: Option<Type>,
value: Expression,
},
}
impl std::fmt::Display for ClauseLevel {
@ -59,167 +176,18 @@ impl std::fmt::Display for ClauseLevel {
}
}
/// 参数
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Parameter {
pub name: String,
/// 参数类型
pub ty: Type,
pub value: Literal,
/// 参数描述(可选)
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
}
/// 谓词
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Predicate {
pub name: String,
pub params: Vec<(String, Type)>,
pub return_type: Type,
/// 函数体AST 表达式)
pub body: Expression,
}
/// 义务
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Obligation {
pub name: String,
pub frequency: ObligationFrequency,
pub enforcer: String,
pub penalty: String,
/// 义务描述(可选)
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
}
/// 义务频率
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ObligationFrequency {
Continuous, // 持续
Periodic, // 周期性
OnDemand, // 按需
}
impl std::fmt::Display for ObligationFrequency {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
ObligationFrequency::Continuous => write!(f, "continuous"),
ObligationFrequency::Periodic => write!(f, "periodic"),
ObligationFrequency::OnDemand => write!(f, "on_demand"),
}
}
}
/// 类型
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Type {
Bool,
U64,
U32,
U128,
F64,
String,
}
impl std::fmt::Display for Type {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Type::Bool => write!(f, "bool"),
Type::U64 => write!(f, "u64"),
Type::U32 => write!(f, "u32"),
Type::U128 => write!(f, "u128"),
Type::F64 => write!(f, "f64"),
Type::String => write!(f, "string"),
}
}
}
/// 字面量
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Literal {
Bool(bool),
Int(i64),
Float(f64),
String(String),
}
impl std::fmt::Display for Literal {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Literal::Bool(b) => write!(f, "{}", b),
Literal::Int(n) => write!(f, "{}", n),
Literal::Float(n) => write!(f, "{}", n),
Literal::String(s) => write!(f, "\"{}\"", s),
}
}
}
/// 表达式
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Expression {
// 字面量
Literal(Literal),
// 变量引用
Variable(String),
// 二元运算
Binary {
op: BinaryOp,
left: Box<Expression>,
right: Box<Expression>,
},
// 一元运算
Unary {
op: UnaryOp,
operand: Box<Expression>,
},
// 函数调用
Call {
name: String,
args: Vec<Expression>,
},
// if表达式
If {
condition: Box<Expression>,
then_branch: Box<Expression>,
else_branch: Option<Box<Expression>>,
},
// 代码块
Block(Vec<Statement>),
// 原始字符串(解析器无法完整解析时的降级表示)
Raw(String),
}
/// 二元运算符
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum BinaryOp {
// 算术运算
Add,
Sub,
Mul,
Div,
Mod,
// 比较运算
Eq,
Ne,
Lt,
Le,
Gt,
Ge,
// 逻辑运算
And,
Or,
}
impl std::fmt::Display for BinaryOp {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
@ -240,13 +208,6 @@ impl std::fmt::Display for BinaryOp {
}
}
/// 一元运算符
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum UnaryOp {
Not,
Neg,
}
impl std::fmt::Display for UnaryOp {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
@ -256,30 +217,6 @@ impl std::fmt::Display for UnaryOp {
}
}
/// 语句
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Statement {
// 表达式语句
Expression(Expression),
// 返回语句
Return(Expression),
// 变量声明
Let {
name: String,
ty: Option<Type>,
value: Expression,
},
}
/// 测试块
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TestBlock {
pub description: String,
pub assertions: Vec<String>,
}
#[cfg(test)]
mod tests {
use super::*;
@ -290,9 +227,6 @@ mod tests {
id: "XTZH_GOLD_COVERAGE".to_string(),
level: ClauseLevel::Eternal,
title: "黄金储备覆盖率底线".to_string(),
name: None,
version: None,
description: None,
depends_on: vec![],
parameters: vec![Parameter {
name: "XTZH_GOLD_COVERAGE_MIN".to_string(),

View File

@ -1,4 +1,5 @@
pub mod ast;
pub use ast::*;
use crate::lexer::{Lexer, Token};
use thiserror::Error;
@ -8,10 +9,13 @@ use thiserror::Error;
pub enum ParserError {
#[error("Unexpected token: expected {expected}, found {found}")]
UnexpectedToken { expected: String, found: String },
#[error("Unexpected end of file")]
UnexpectedEof,
#[error("Invalid syntax: {message}")]
InvalidSyntax { message: String },
#[error("Lexer error: {0}")]
LexerError(#[from] crate::lexer::LexerError),
}
@ -29,6 +33,7 @@ impl<'source> Parser<'source> {
let mut lexer = Lexer::new(source);
let current = lexer.next().transpose()?;
let peek = lexer.next().transpose()?;
Ok(Self {
lexer,
current,
@ -39,23 +44,12 @@ impl<'source> Parser<'source> {
/// 解析整个程序
pub fn parse(&mut self) -> Result<Program, ParserError> {
let mut clauses = Vec::new();
let mut tests = Vec::new();
while self.current.is_some() {
match &self.current {
Some(Token::Clause) => {
clauses.push(self.parse_clause()?);
}
Some(Token::Test) => {
tests.push(self.parse_test_block()?);
}
_ => {
return Err(ParserError::InvalidSyntax {
message: format!("Expected clause or test, found {:?}", self.current),
});
}
}
clauses.push(self.parse_clause()?);
}
Ok(Program { clauses, tests })
Ok(Program { clauses })
}
/// 解析条款
@ -67,9 +61,6 @@ impl<'source> Parser<'source> {
let mut level = ClauseLevel::Tactical;
let mut title = String::new();
let mut name: Option<String> = None;
let mut version: Option<String> = None;
let mut description: Option<String> = None;
let mut depends_on = Vec::new();
let mut parameters = Vec::new();
let mut predicates = Vec::new();
@ -88,25 +79,6 @@ impl<'source> Parser<'source> {
self.expect(Token::Colon)?;
title = self.expect_string_literal()?;
}
Some(Token::Name) => {
self.advance();
self.expect(Token::Colon)?;
let n = self.expect_string_literal()?;
if title.is_empty() {
title = n.clone();
}
name = Some(n);
}
Some(Token::Version) => {
self.advance();
self.expect(Token::Colon)?;
version = Some(self.expect_string_literal()?);
}
Some(Token::Description) => {
self.advance();
self.expect(Token::Colon)?;
description = Some(self.expect_string_literal()?);
}
Some(Token::DependsOn) => {
self.advance();
self.expect(Token::Colon)?;
@ -128,15 +100,13 @@ impl<'source> Parser<'source> {
}
}
}
self.expect(Token::RBrace)?;
Ok(Clause {
id,
level,
title,
name,
version,
description,
depends_on,
parameters,
predicates,
@ -175,10 +145,7 @@ impl<'source> Parser<'source> {
let ty = self.parse_type()?;
self.expect(Token::Assign)?;
let value = self.parse_literal()?;
// 可选分号
if self.check(&Token::Semicolon) {
self.advance();
}
Ok(Parameter {
name,
ty,
@ -193,23 +160,29 @@ impl<'source> Parser<'source> {
self.expect(Token::Predicate)?;
let name = self.expect_ident()?;
self.expect(Token::LParen)?;
let mut params = Vec::new();
while !self.check(&Token::RParen) {
let param_name = self.expect_ident()?;
self.expect(Token::Colon)?;
let param_type = self.parse_type()?;
params.push((param_name, param_type));
if self.check(&Token::Comma) {
self.advance();
}
}
self.expect(Token::RParen)?;
self.expect(Token::Arrow)?;
let return_type = self.parse_type()?;
self.expect(Token::LBrace)?;
// 简化:只解析单个返回表达式
let body = self.parse_expression()?;
self.expect(Token::RBrace)?;
Ok(Predicate {
name,
params,
@ -228,7 +201,6 @@ impl<'source> Parser<'source> {
let mut frequency = ObligationFrequency::OnDemand;
let mut enforcer = String::new();
let mut penalty = String::new();
let mut description: Option<String> = None;
while !self.check(&Token::RBrace) {
match &self.current {
@ -247,21 +219,18 @@ impl<'source> Parser<'source> {
self.expect(Token::Colon)?;
penalty = self.expect_ident()?;
}
Some(Token::Description) => {
self.advance();
self.expect(Token::Colon)?;
description = Some(self.expect_string_literal()?);
}
_ => {
return Err(ParserError::InvalidSyntax {
message: format!("Unexpected token in obligation: {:?}", self.current),
});
}
}
if self.check(&Token::Comma) {
self.advance();
}
}
self.expect(Token::RBrace)?;
Ok(Obligation {
@ -269,7 +238,6 @@ impl<'source> Parser<'source> {
frequency,
enforcer,
penalty,
description,
})
}
@ -295,50 +263,6 @@ impl<'source> Parser<'source> {
}
}
/// 解析测试块
fn parse_test_block(&mut self) -> Result<TestBlock, ParserError> {
// test "DESCRIPTION" { assert EXPR ; ... }
self.expect(Token::Test)?;
let description = self.expect_string_literal()?;
self.expect(Token::LBrace)?;
let mut assertions = Vec::new();
while !self.check(&Token::RBrace) {
if self.check(&Token::Assert) {
self.advance();
let expr_str = self.collect_until_semicolon()?;
assertions.push(expr_str);
} else {
return Err(ParserError::InvalidSyntax {
message: format!("Expected assert in test block, found {:?}", self.current),
});
}
}
self.expect(Token::RBrace)?;
Ok(TestBlock { description, assertions })
}
/// 收集 token 直到分号
fn collect_until_semicolon(&mut self) -> Result<String, ParserError> {
let mut tokens = Vec::new();
loop {
match &self.current {
Some(Token::Semicolon) => {
self.advance();
break;
}
Some(Token::RBrace) => {
break;
}
Some(t) => {
tokens.push(format!("{}", t));
self.advance();
}
None => break,
}
}
Ok(tokens.join(" "))
}
/// 解析表达式(简化版)
fn parse_expression(&mut self) -> Result<Expression, ParserError> {
self.parse_comparison()
@ -347,6 +271,7 @@ impl<'source> Parser<'source> {
/// 解析比较表达式
fn parse_comparison(&mut self) -> Result<Expression, ParserError> {
let mut left = self.parse_term()?;
while let Some(token) = &self.current {
let op = match token {
Token::Eq => BinaryOp::Eq,
@ -357,6 +282,7 @@ impl<'source> Parser<'source> {
Token::Ge => BinaryOp::Ge,
_ => break,
};
self.advance();
let right = self.parse_term()?;
left = Expression::Binary {
@ -365,18 +291,21 @@ impl<'source> Parser<'source> {
right: Box::new(right),
};
}
Ok(left)
}
/// 解析项
fn parse_term(&mut self) -> Result<Expression, ParserError> {
let mut left = self.parse_factor()?;
while let Some(token) = &self.current {
let op = match token {
Token::Plus => BinaryOp::Add,
Token::Minus => BinaryOp::Sub,
_ => break,
};
self.advance();
let right = self.parse_factor()?;
left = Expression::Binary {
@ -385,80 +314,60 @@ impl<'source> Parser<'source> {
right: Box::new(right),
};
}
Ok(left)
}
/// 解析因子
fn parse_factor(&mut self) -> Result<Expression, ParserError> {
let mut left = self.parse_unary()?;
let mut left = self.parse_primary()?;
while let Some(token) = &self.current {
let op = match token {
Token::Star => BinaryOp::Mul,
Token::Slash => BinaryOp::Div,
Token::Percent => BinaryOp::Mod,
_ => break,
};
self.advance();
let right = self.parse_unary()?;
let right = self.parse_primary()?;
left = Expression::Binary {
op,
left: Box::new(left),
right: Box::new(right),
};
}
Ok(left)
}
/// 解析一元表达式
fn parse_unary(&mut self) -> Result<Expression, ParserError> {
match &self.current {
Some(Token::Not) => {
self.advance();
let operand = self.parse_primary()?;
Ok(Expression::Unary {
op: UnaryOp::Not,
operand: Box::new(operand),
})
}
Some(Token::Minus) => {
self.advance();
let operand = self.parse_primary()?;
Ok(Expression::Unary {
op: UnaryOp::Neg,
operand: Box::new(operand),
})
}
_ => self.parse_primary(),
}
Ok(left)
}
/// 解析基本表达式
fn parse_primary(&mut self) -> Result<Expression, ParserError> {
match &self.current {
Some(Token::IntLiteral(_))
| Some(Token::FloatLiteral(_))
| Some(Token::BoolLiteral(_))
| Some(Token::StringLiteral(_)) => {
let lit = self.parse_literal()?;
Ok(Expression::Literal(lit))
Some(Token::IntLiteral(n)) => {
let n = *n;
self.advance();
Ok(Expression::Literal(Literal::Int(n)))
}
Some(Token::Ident(_)) | Some(Token::ConstantIdent(_)) => {
let name = self.expect_ident()?;
// 检查是否是函数调用
if self.check(&Token::LParen) {
self.advance();
let mut args = Vec::new();
while !self.check(&Token::RParen) {
args.push(self.parse_expression()?);
if self.check(&Token::Comma) {
self.advance();
}
}
self.expect(Token::RParen)?;
Ok(Expression::Call { name, args })
} else {
Ok(Expression::Variable(name))
}
Some(Token::FloatLiteral(f)) => {
let f = *f;
self.advance();
Ok(Expression::Literal(Literal::Float(f)))
}
Some(Token::BoolLiteral(b)) => {
let b = *b;
self.advance();
Ok(Expression::Literal(Literal::Bool(b)))
}
Some(Token::StringLiteral(s)) => {
let s = s.clone();
self.advance();
Ok(Expression::Literal(Literal::String(s)))
}
Some(Token::Ident(name)) | Some(Token::ConstantIdent(name)) => {
let name = name.clone();
self.advance();
Ok(Expression::Variable(name))
}
Some(Token::LParen) => {
self.advance();
@ -488,10 +397,6 @@ impl<'source> Parser<'source> {
self.advance();
Ok(Type::U32)
}
Some(Token::U128) => {
self.advance();
Ok(Type::U128)
}
Some(Token::F64) => {
self.advance();
Ok(Type::F64)
@ -541,12 +446,15 @@ impl<'source> Parser<'source> {
fn parse_string_array(&mut self) -> Result<Vec<String>, ParserError> {
self.expect(Token::LBracket)?;
let mut strings = Vec::new();
while !self.check(&Token::RBracket) {
strings.push(self.expect_string_literal()?);
if self.check(&Token::Comma) {
self.advance();
}
}
self.expect(Token::RBracket)?;
Ok(strings)
}
@ -638,41 +546,16 @@ mod tests {
parameter XTZH_GOLD_COVERAGE_MIN: f64 = 1.25
}
"#;
let mut parser = Parser::new(source).expect("Parser creation failed");
let program = parser.parse().expect("Parse failed");
assert_eq!(program.clauses.len(), 1);
assert_eq!(program.clauses[0].id, "XTZH_GOLD_COVERAGE");
assert_eq!(program.clauses[0].level, ClauseLevel::Eternal);
assert_eq!(program.clauses[0].parameters.len(), 1);
}
#[test]
fn test_parse_name_version() {
let source = r#"
clause CORE_GOVERNANCE {
name: "核心治理条款"
version: "1.0.0"
level: eternal
title: "核心治理"
parameter MAX_VALIDATORS: u32 = 100
parameter MIN_STAKE: u128 = 1000000000000000000
obligation VALIDATOR_REGISTRATION {
frequency: continuous
enforcer: ai
penalty: suspension
description: "验证者必须质押最小金额"
}
}
"#;
let mut parser = Parser::new(source).expect("Parser creation failed");
let program = parser.parse().expect("Parse failed");
assert_eq!(program.clauses.len(), 1);
assert_eq!(program.clauses[0].id, "CORE_GOVERNANCE");
assert_eq!(program.clauses[0].name, Some("核心治理条款".to_string()));
assert_eq!(program.clauses[0].version, Some("1.0.0".to_string()));
assert_eq!(program.clauses[0].parameters.len(), 2);
}
#[test]
fn test_parse_predicate() {
let source = r#"
@ -684,24 +567,11 @@ mod tests {
}
}
"#;
let mut parser = Parser::new(source).expect("Parser creation failed");
let program = parser.parse().expect("Parse failed");
assert_eq!(program.clauses[0].predicates.len(), 1);
assert_eq!(program.clauses[0].predicates[0].name, "check_value");
}
#[test]
fn test_parse_test_block() {
let source = r#"
test "核心治理参数一致性" {
assert MAX_VALIDATORS > 0 ;
assert MIN_STAKE >= 1000000000000000000 ;
}
"#;
let mut parser = Parser::new(source).expect("Parser creation failed");
let program = parser.parse().expect("Parse failed");
assert_eq!(program.tests.len(), 1);
assert_eq!(program.tests[0].description, "核心治理参数一致性");
assert_eq!(program.tests[0].assertions.len(), 2);
}
}

View File

@ -124,9 +124,6 @@ mod tests {
id: "TEST".to_string(),
level: ClauseLevel::Eternal,
title: "Test".to_string(),
name: None,
version: None,
description: None,
parameters: vec![],
predicates: vec![],
obligations: vec![Obligation {
@ -134,7 +131,6 @@ mod tests {
frequency: crate::parser::ObligationFrequency::Continuous,
enforcer: "ai_system".to_string(),
penalty: "suspension".to_string(),
description: None,
}],
depends_on: vec![],
};
@ -150,9 +146,6 @@ mod tests {
id: "TEST".to_string(),
level: ClauseLevel::Eternal,
title: "Test".to_string(),
name: None,
version: None,
description: None,
parameters: vec![],
predicates: vec![],
obligations: vec![Obligation {
@ -160,7 +153,6 @@ mod tests {
frequency: crate::parser::ObligationFrequency::Continuous,
enforcer: "".to_string(),
penalty: "suspension".to_string(),
description: None,
}],
depends_on: vec![],
};
@ -176,9 +168,6 @@ mod tests {
id: "TEST".to_string(),
level: ClauseLevel::Eternal,
title: "Test".to_string(),
name: None,
version: None,
description: None,
parameters: vec![],
predicates: vec![],
obligations: vec![Obligation {
@ -186,7 +175,6 @@ mod tests {
frequency: crate::parser::ObligationFrequency::Continuous,
enforcer: "manual".to_string(),
penalty: "suspension".to_string(),
description: None,
}],
depends_on: vec![],
};

View File

@ -161,7 +161,6 @@ impl ScopeResolver {
Expression::Literal(_) => {
// 字面量不需要解析
}
crate::parser::Expression::Raw(_) => {}
}
}
}
@ -256,9 +255,6 @@ mod tests {
id: "TEST".to_string(),
level: ClauseLevel::Eternal,
title: "Test".to_string(),
name: None,
version: None,
description: None,
parameters: vec![Parameter {
name: "x".to_string(),
ty: Type::U64,

View File

@ -132,7 +132,6 @@ impl TypeChecker {
Expression::Call { name: _, args: _ } => Type::Bool,
Expression::If { .. } => Type::Bool,
Expression::Block(_) => Type::Bool,
crate::parser::Expression::Raw(_) => Type::Bool,
}
}
}
@ -156,9 +155,6 @@ mod tests {
id: "TEST".to_string(),
level: crate::parser::ClauseLevel::Eternal,
title: "Test".to_string(),
name: None,
version: None,
description: None,
parameters: vec![Parameter {
name: "x".to_string(),
ty: Type::U64,
@ -186,9 +182,6 @@ mod tests {
id: "TEST".to_string(),
level: crate::parser::ClauseLevel::Eternal,
title: "Test".to_string(),
name: None,
version: None,
description: None,
parameters: vec![Parameter {
name: "x".to_string(),
ty: Type::U64,

View File

@ -95,7 +95,6 @@ impl ConstraintGenerator {
Expression::Block(_) => {
"true".to_string() // 简化处理
}
Expression::Raw(s) => s.clone(),
}
}
@ -138,9 +137,6 @@ mod tests {
id: "TEST".to_string(),
level: ClauseLevel::Eternal,
title: "Test".to_string(),
name: None,
version: None,
description: None,
parameters: vec![],
predicates: vec![Predicate {
name: "test_pred".to_string(),

2314
cnnl-service/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,39 +0,0 @@
[package]
name = "nac-cnnl-service"
version = "0.1.0"
edition = "2021"
authors = ["NAC Core Team <dev@newassetchain.io>"]
description = "CNNL HTTP Service - RESTful API for CNNL Compiler"
[dependencies]
# HTTP 框架
actix-web = "4"
actix-rt = "2"
# 序列化
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
# 错误处理
thiserror = "1.0"
anyhow = "1.0"
# 日志
log = "0.4"
env_logger = "0.11"
# 时间
chrono = { version = "0.4", features = ["serde"] }
hex = "0.4"
# CNNL 编译器库(本地路径)
cnnl-compiler = { path = "../cnnl-compiler" }
[[bin]]
name = "nac-cnnl-service"
path = "src/main.rs"
[profile.release]
opt-level = 3
lto = true
codegen-units = 1

View File

@ -1,432 +0,0 @@
//! NAC CNNL HTTP 服务
//!
//! 将 CNNL 编译器封装为 RESTful HTTP API供立法 IDE、宪法沙箱等工具调用。
//!
//! # 接口列表
//! - POST /api/v1/compile - 编译 CNNL 源代码
//! - POST /api/v1/parse - 解析 CNNL 源代码(仅返回 AST
//! - POST /api/v1/validate - 验证 CNNL 语法(不生成字节码)
//! - GET /api/v1/health - 健康检查
//! - GET /api/v1/version - 版本信息
use actix_web::{web, App, HttpServer, HttpResponse, Responder, middleware};
use serde::{Deserialize, Serialize};
use std::time::Instant;
use chrono::Utc;
use log::{info, warn, error};
// ============================================================
// 请求/响应数据结构
// ============================================================
/// 编译请求
#[derive(Debug, Deserialize)]
pub struct CompileRequest {
/// CNNL 源代码
pub source: String,
/// 是否启用形式化验证
#[serde(default)]
pub enable_verification: bool,
/// 是否生成调试信息
#[serde(default)]
pub debug_info: bool,
/// 是否生成宪法状态文件
#[serde(default = "default_true")]
pub generate_state: bool,
}
fn default_true() -> bool {
true
}
/// 解析请求
#[derive(Debug, Deserialize)]
pub struct ParseRequest {
/// CNNL 源代码
pub source: String,
}
/// 验证请求
#[derive(Debug, Deserialize)]
pub struct ValidateRequest {
/// CNNL 源代码
pub source: String,
}
/// 通用 API 响应
#[derive(Debug, Serialize)]
pub struct ApiResponse<T: Serialize> {
pub success: bool,
pub data: Option<T>,
pub error: Option<String>,
pub timestamp: String,
pub duration_ms: u64,
}
impl<T: Serialize> ApiResponse<T> {
pub fn ok(data: T, duration_ms: u64) -> Self {
Self {
success: true,
data: Some(data),
error: None,
timestamp: Utc::now().to_rfc3339(),
duration_ms,
}
}
pub fn err(msg: String, duration_ms: u64) -> ApiResponse<serde_json::Value> {
ApiResponse {
success: false,
data: None,
error: Some(msg),
timestamp: Utc::now().to_rfc3339(),
duration_ms,
}
}
}
/// 编译结果
#[derive(Debug, Serialize)]
pub struct CompileResult {
/// 字节码hex 编码)
pub bytecode_hex: String,
/// 字节码长度(字节)
pub bytecode_size: usize,
/// 宪法状态 JSON可选
pub state_json: Option<serde_json::Value>,
/// 条款数量
pub clause_count: usize,
/// 条款摘要
pub clauses: Vec<ClauseSummary>,
}
/// 解析结果
#[derive(Debug, Serialize)]
pub struct ParseResult {
/// 条款数量
pub clause_count: usize,
/// 测试块数量
pub test_count: usize,
/// 条款详情
pub clauses: Vec<ClauseDetail>,
}
/// 验证结果
#[derive(Debug, Serialize)]
pub struct ValidateResult {
/// 是否有效
pub valid: bool,
/// 错误列表
pub errors: Vec<String>,
/// 警告列表
pub warnings: Vec<String>,
/// 条款数量
pub clause_count: usize,
}
/// 条款摘要
#[derive(Debug, Serialize)]
pub struct ClauseSummary {
pub id: String,
pub level: String,
pub title: String,
pub parameter_count: usize,
pub predicate_count: usize,
pub obligation_count: usize,
}
/// 条款详情
#[derive(Debug, Serialize)]
pub struct ClauseDetail {
pub id: String,
pub level: String,
pub title: String,
pub name: Option<String>,
pub version: Option<String>,
pub description: Option<String>,
pub depends_on: Vec<String>,
pub parameters: Vec<ParameterDetail>,
pub predicates: Vec<PredicateDetail>,
pub obligations: Vec<ObligationDetail>,
}
/// 参数详情
#[derive(Debug, Serialize)]
pub struct ParameterDetail {
pub name: String,
pub type_name: String,
pub value: String,
pub description: Option<String>,
}
/// 谓词详情
#[derive(Debug, Serialize)]
pub struct PredicateDetail {
pub name: String,
pub params: Vec<(String, String)>,
pub return_type: String,
}
/// 义务详情
#[derive(Debug, Serialize)]
pub struct ObligationDetail {
pub name: String,
pub frequency: String,
pub enforcer: String,
pub penalty: String,
pub description: Option<String>,
}
/// 版本信息
#[derive(Debug, Serialize)]
pub struct VersionInfo {
pub service: String,
pub version: String,
pub compiler_version: String,
pub build_time: String,
}
/// 健康状态
#[derive(Debug, Serialize)]
pub struct HealthStatus {
pub status: String,
pub uptime_seconds: u64,
}
// ============================================================
// 全局状态
// ============================================================
pub struct AppState {
pub start_time: Instant,
}
// ============================================================
// API 处理函数
// ============================================================
/// POST /api/v1/compile - 编译 CNNL 源代码
async fn handle_compile(
state: web::Data<AppState>,
req: web::Json<CompileRequest>,
) -> impl Responder {
let start = Instant::now();
info!("收到编译请求,源代码长度: {} 字节", req.source.len());
let options = cnnl_compiler::CompilerOptions {
enable_verification: req.enable_verification,
debug_info: req.debug_info,
output_dir: None,
generate_state_file: req.generate_state,
};
match cnnl_compiler::compile(&req.source, options) {
Ok(result) => {
let bytecode_hex = hex::encode(&result.bytecode);
let state_json = result.state_json.as_ref().and_then(|s| {
serde_json::from_str(s).ok()
});
let clauses: Vec<ClauseSummary> = result.ast.clauses.iter().map(|c| ClauseSummary {
id: c.id.clone(),
level: c.level.to_string(),
title: c.title.clone(),
parameter_count: c.parameters.len(),
predicate_count: c.predicates.len(),
obligation_count: c.obligations.len(),
}).collect();
let clause_count = clauses.len();
let compile_result = CompileResult {
bytecode_hex,
bytecode_size: result.bytecode.len(),
state_json,
clause_count,
clauses,
};
let duration_ms = start.elapsed().as_millis() as u64;
info!("编译成功,字节码大小: {} 字节,耗时: {}ms", compile_result.bytecode_size, duration_ms);
HttpResponse::Ok().json(ApiResponse::ok(compile_result, duration_ms))
}
Err(e) => {
let duration_ms = start.elapsed().as_millis() as u64;
warn!("编译失败: {}", e);
HttpResponse::BadRequest().json(ApiResponse::<serde_json::Value>::err(
format!("{}", e),
duration_ms,
))
}
}
}
/// POST /api/v1/parse - 解析 CNNL 源代码
async fn handle_parse(
_state: web::Data<AppState>,
req: web::Json<ParseRequest>,
) -> impl Responder {
let start = Instant::now();
info!("收到解析请求,源代码长度: {} 字节", req.source.len());
match cnnl_compiler::Parser::new(&req.source) {
Ok(mut parser) => {
match parser.parse() {
Ok(ast) => {
let clauses: Vec<ClauseDetail> = ast.clauses.iter().map(|c| ClauseDetail {
id: c.id.clone(),
level: c.level.to_string(),
title: c.title.clone(),
name: c.name.clone(),
version: c.version.clone(),
description: c.description.clone(),
depends_on: c.depends_on.clone(),
parameters: c.parameters.iter().map(|p| ParameterDetail {
name: p.name.clone(),
type_name: p.ty.to_string(),
value: format!("{}", p.value),
description: p.description.clone(),
}).collect(),
predicates: c.predicates.iter().map(|pred| PredicateDetail {
name: pred.name.clone(),
params: pred.params.iter().map(|(n, t)| (n.clone(), t.to_string())).collect(),
return_type: pred.return_type.to_string(),
}).collect(),
obligations: c.obligations.iter().map(|o| ObligationDetail {
name: o.name.clone(),
frequency: format!("{:?}", o.frequency),
enforcer: o.enforcer.clone(),
penalty: o.penalty.clone(),
description: o.description.clone(),
}).collect(),
}).collect();
let test_count = ast.tests.len();
let clause_count = clauses.len();
let parse_result = ParseResult {
clause_count,
test_count,
clauses,
};
let duration_ms = start.elapsed().as_millis() as u64;
info!("解析成功,条款数: {},测试块数: {},耗时: {}ms", clause_count, test_count, duration_ms);
HttpResponse::Ok().json(ApiResponse::ok(parse_result, duration_ms))
}
Err(e) => {
let duration_ms = start.elapsed().as_millis() as u64;
warn!("解析失败: {}", e);
HttpResponse::BadRequest().json(ApiResponse::<serde_json::Value>::err(
format!("{}", e),
duration_ms,
))
}
}
}
Err(e) => {
let duration_ms = start.elapsed().as_millis() as u64;
warn!("词法分析失败: {}", e);
HttpResponse::BadRequest().json(ApiResponse::<serde_json::Value>::err(
format!("{}", e),
duration_ms,
))
}
}
}
/// POST /api/v1/validate - 验证 CNNL 语法
async fn handle_validate(
_state: web::Data<AppState>,
req: web::Json<ValidateRequest>,
) -> impl Responder {
let start = Instant::now();
info!("收到验证请求,源代码长度: {} 字节", req.source.len());
let mut errors = Vec::new();
let warnings = Vec::new();
let mut clause_count = 0;
match cnnl_compiler::Parser::new(&req.source) {
Ok(mut parser) => {
match parser.parse() {
Ok(ast) => {
clause_count = ast.clauses.len();
// 语义分析
let mut analyzer = cnnl_compiler::semantic::SemanticAnalyzer::new();
if let Err(e) = analyzer.analyze(&ast) {
errors.push(format!("语义错误: {}", e));
}
}
Err(e) => {
errors.push(format!("语法错误: {}", e));
}
}
}
Err(e) => {
errors.push(format!("词法错误: {}", e));
}
}
let valid = errors.is_empty();
let validate_result = ValidateResult {
valid,
errors,
warnings,
clause_count,
};
let duration_ms = start.elapsed().as_millis() as u64;
info!("验证完成,有效: {},耗时: {}ms", valid, duration_ms);
HttpResponse::Ok().json(ApiResponse::ok(validate_result, duration_ms))
}
/// GET /api/v1/health - 健康检查
async fn handle_health(state: web::Data<AppState>) -> impl Responder {
let uptime_seconds = state.start_time.elapsed().as_secs();
let health = HealthStatus {
status: "ok".to_string(),
uptime_seconds,
};
HttpResponse::Ok().json(ApiResponse::ok(health, 0))
}
/// GET /api/v1/version - 版本信息
async fn handle_version(_state: web::Data<AppState>) -> impl Responder {
let version = VersionInfo {
service: "nac-cnnl-service".to_string(),
version: env!("CARGO_PKG_VERSION").to_string(),
compiler_version: "0.1.0".to_string(),
build_time: env!("CARGO_PKG_VERSION").to_string(),
};
HttpResponse::Ok().json(ApiResponse::ok(version, 0))
}
// ============================================================
// 主函数
// ============================================================
#[actix_web::main]
async fn main() -> std::io::Result<()> {
env_logger::init_from_env(env_logger::Env::default().default_filter_or("info"));
let host = std::env::var("CNNL_HOST").unwrap_or_else(|_| "0.0.0.0".to_string());
let port: u16 = std::env::var("CNNL_PORT")
.unwrap_or_else(|_| "8080".to_string())
.parse()
.unwrap_or(8080);
info!("NAC CNNL HTTP 服务启动中...");
info!("监听地址: {}:{}", host, port);
let app_state = web::Data::new(AppState {
start_time: Instant::now(),
});
HttpServer::new(move || {
App::new()
.app_data(app_state.clone())
.app_data(web::JsonConfig::default().limit(1024 * 1024)) // 1MB 请求体限制
// API 路由
.route("/api/v1/compile", web::post().to(handle_compile))
.route("/api/v1/parse", web::post().to(handle_parse))
.route("/api/v1/validate", web::post().to(handle_validate))
.route("/api/v1/health", web::get().to(handle_health))
.route("/api/v1/version", web::get().to(handle_version))
})
.bind(format!("{}:{}", host, port))?
.run()
.await
}

View File

@ -1,167 +0,0 @@
# NAC 公链多服务器体系架构规划
**文档编号**ARCH-001
**版本**v1.0
**日期**2026-02-28
**状态**:规划草案
---
## 一、架构原则
NAC 公链的多服务器体系建立在以下核心原则之上:
**参与即是共识**。区块链的本质不是集中式服务,而是每个服务节点独立运行、独立验证、独立扩展。当前将所有服务集中在一台或两台服务器上,违背了这一原则,也带来了单点故障风险。未来的目标是将每一类服务部署到独立的服务器,通过 NRPC 4.0 协议通信,形成真正的分布式服务网络。
**服务边界清晰**。每台服务器只负责一类核心职责,不承担其他服务的运行压力。这既符合微服务架构的最佳实践,也符合区块链节点独立性的要求。
**数据主权分离**。用户数据注册系统、链上数据CBPP 节点、合规数据AI 知识引擎)、交易数据(交易所)各自存储在独立的数据库服务器上,互不干扰,互不依赖。
---
## 二、目标多服务器体系(七层架构)
### 第一层链核心层Chain Core
这是整个体系的基础,负责区块生产、共识和链上状态维护。
| 服务器角色 | 部署服务 | 域名 | 当前状态 |
|-----------|---------|------|---------|
| **主链节点服务器** | CBPP 节点nac-cbpp-node、NRPC 4.0 网关 | `rpc.newassetchain.io` | 已部署(备份服务器) |
| **备用链节点服务器** | CBPP 节点副本(热备) | — | 待规划 |
**独立理由**CBPP 节点是整个公链的心脏,必须独立运行,不能与任何应用层服务共享服务器资源。链节点的 CPU 和 I/O 需求与应用服务完全不同,混合部署会导致出块延迟。
---
### 第二层身份层Identity Layer
负责用户注册、KYC 验证、DID 身份管理。
| 服务器角色 | 部署服务 | 域名 | 当前状态 |
|-----------|---------|------|---------|
| **注册系统服务器** | nac-id-systemLaravel/PHP、MySQLnac_id 数据库) | `id.newassetchain.io` | 已部署(备份服务器),**待迁出** |
| **认证网关** | nac-auth-service端口 8081 | — | 已部署(备份服务器),随注册系统迁移 |
**独立理由**注册系统存储用户的最敏感数据身份证、KYC 文件),必须部署在专用服务器上,配备独立的数据库备份策略和更严格的访问控制。注册系统与链节点的耦合应通过 NRPC 4.0 协议完成,而非直接数据库访问。
---
### 第三层AI 智能层AI Intelligence Layer
负责合规分析、资产估值、审批辅助、知识库管理。
| 服务器角色 | 部署服务 | 域名 | 当前状态 |
|-----------|---------|------|---------|
| **AI 知识引擎服务器** | nac-adminNode.js、MongoDBnac_knowledge_engine | `admin.newassetchain.io` | 已部署(备份服务器),**待迁出** |
| **AI 估值服务器**(未来) | nac-ai-valuationRust、xtzh-aiTransformer 模型) | `aivl.newassetchain.io` | 待规划 |
**独立理由**AI 推理(尤其是 Transformer 模型)对 GPU/CPU 的需求远高于普通 Web 服务。将 AI 服务独立到专用服务器可以在不影响其他服务的情况下进行模型升级和算力扩展。MongoDB 知识库35 条规则,持续增长)也需要独立的存储和索引优化。
---
### 第四层资产上链层Asset Onboarding Layer
负责 RWA 资产的上链流程、合规验证、DNA 生成。
| 服务器角色 | 部署服务 | 域名 | 当前状态 |
|-----------|---------|------|---------|
| **资产上链服务器** | nac-onboardingPython FastAPI、CIB 服务 | `onboarding.newassetchain.io`、`cib.newassetchain.io` | 已部署(备份服务器),待迁出 |
**独立理由**:资产上链是 NAC 的核心业务流程涉及文件上传、AI 合规验证、链上交易提交等多个步骤,处理时间长、资源消耗大,必须独立运行以保证服务质量。
---
### 第五层数据服务层Data Service Layer
负责链上数据的聚合、查询、可视化。
| 服务器角色 | 部署服务 | 域名 | 当前状态 |
|-----------|---------|------|---------|
| **区块浏览器服务器** | nac-quantum-browserPHP WorkerMan + WebSocket | `explorer.newassetchain.io` | 已部署(备份服务器),待迁出 |
| **数据服务器** | NAC LensNode.js、NAC API ServerRust | `lens.newassetchain.io`、`api.newassetchain.io` | 已部署(备份服务器),待迁出 |
**独立理由**:区块浏览器和数据服务是面向公众的高流量服务,需要独立的 CDN 加速和负载均衡,不能与链节点共享带宽。
---
### 第六层金融服务层Financial Service Layer
负责 XTZH 稳定币、钱包、交易所。
| 服务器角色 | 部署服务 | 域名 | 当前状态 |
|-----------|---------|------|---------|
| **钱包与稳定币服务器** | nac-wallet-serviceRust、xtzh-pricing-servicePython | `wallet.newassetchain.io` | 已部署(备份服务器),待迁出 |
| **交易所服务器** | nac-exchange-serviceRust | `exchange.newassetchain.io`、`exchange-admin.newassetchain.io` | 已部署(备份服务器),待迁出 |
**独立理由**:金融服务涉及资金安全,必须部署在符合金融级安全标准的服务器上,配备独立的 HSM硬件安全模块和审计日志系统。
---
### 第七层展示与门户层Portal Layer
负责公开网站、ICO 门户、营销页面。
| 服务器角色 | 部署服务 | 域名 | 当前状态 |
|-----------|---------|------|---------|
| **主站服务器** | www.newassetchain.ioNode.js | `www.newassetchain.io` | 已部署(主服务器 103.43.188.244 |
| **ICO 门户服务器** | NILA Token 购买页面(静态 HTML | `ico.newassetchain.io`、`trc-ico.newassetchain.io` | 已部署(主服务器) |
---
## 三、服务间通信规范
所有服务器之间的通信必须通过 **NRPC 4.0 协议**,禁止直接数据库访问跨服务器调用。
| 通信场景 | 发起方 | 接收方 | 协议 | 说明 |
|---------|--------|--------|------|------|
| 注册用户上链 | 注册系统服务器 | 主链节点服务器 | NRPC 4.0 `nac_sendTx` | 工单 REG-001 |
| AI 合规查询链上状态 | AI 知识引擎服务器 | 主链节点服务器 | NRPC 4.0 `nac_getBlock` | — |
| 资产上链提交交易 | 资产上链服务器 | 主链节点服务器 | NRPC 4.0 `nac_sendTx` | — |
| 区块浏览器读取数据 | 数据服务层 | 主链节点服务器 | NRPC 4.0 `nac_getBlock` | — |
| 钱包发送交易 | 金融服务层 | 主链节点服务器 | NRPC 4.0 `nac_sendTx` | — |
---
## 四、迁移优先级与路线图
迁移应按照对链核心的影响程度从低到高进行,优先迁移独立性最强的服务。
| 优先级 | 服务 | 迁移难度 | 预计工期 | 前置条件 |
|--------|------|---------|---------|---------|
| **P1立即** | AI 知识引擎nac-admin | 低 | 1 天 | 新服务器 + MongoDB + MySQL |
| **P2近期** | 注册系统nac-id-system | 中 | 2 天 | 新服务器 + MySQL + 工单 REG-001 完成 |
| **P3中期** | 区块浏览器 + 数据服务 | 中 | 3 天 | 新服务器 + NRPC 4.0 网关稳定 |
| **P4中期** | 资产上链服务 | 高 | 5 天 | 新服务器 + AI 知识引擎迁移完成 |
| **P5远期** | 金融服务(钱包/交易所) | 高 | 7 天 | 金融级安全审计完成 |
| **P6远期** | 链节点独立扩展(多节点) | 极高 | 持续 | CSNP 网络协议完善 |
---
## 五、数据库独立化策略
当前所有数据库MySQL + MongoDB集中在备份服务器上这是单点故障的最大风险。未来应建立独立的数据服务器
| 数据库 | 当前位置 | 目标位置 | 数据内容 |
|--------|---------|---------|---------|
| `nac_id`MySQL | 备份服务器 | 独立数据服务器 | 用户账号、KYC 信息 |
| `nac_knowledge_engine`MongoDB | 备份服务器 | AI 知识引擎服务器本地 | 35 条合规规则、对话历史 |
| `gnacs_db`MongoDB | 备份服务器 | 独立数据服务器 | GNACS 编码、资产分类 |
| `nac_onboarding`MongoDB | 备份服务器 | 资产上链服务器本地 | 上链申请、合规记录 |
| 链上状态RocksDB | 备份服务器 | 主链节点服务器本地 | 区块数据、账户状态 |
---
## 六、与区块链去中心化原则的对应关系
| 区块链原则 | NAC 多服务器体系的实现方式 |
|-----------|------------------------|
| **节点独立性** | 每台服务器独立运行,单台服务器故障不影响整体网络 |
| **数据主权** | 每类数据存储在对应职责的服务器上,无跨服务器直接访问 |
| **协议通信** | 所有服务间通信通过 NRPC 4.0 协议,而非内网直连 |
| **参与即是共识** | 注册系统通过 `nac_sendTx` 将每次注册写入链上,每台服务器的运行本身就是对网络的贡献 |
| **可扩展性** | 每层服务可独立横向扩展,无需整体重构 |
---
*文档归档路径:`nac-docs-center/docs/architecture/ARCH-001-multi-server-plan.md`*