# Charter语言规范要点 **来源**: Charter语言规范扩展(增补).docx --- ## 1. 多ZK证明系统的内置支持 ### 1.1 设计动机 - XTZH汇率收据的零知识证明目前仅支持**Groth16 (BN254曲线)** - 需扩展支持**Plonk**(任意门限)、**Halo2**(无需可信设置)等主流zkSNARK系统 - 必须保持上层API统一,允许证明类型在运行时或编译期选择 ### 1.2 语法扩展:@zk标记与多后端抽象 ```charter /// 零知识证明方案枚举 public enum ZKProtocol { Groth16Bn254, PlonkBn254, PlonkBls12_381, Halo2Kzg, Halo2IPA } /// 统一的ZK证明验证接口(编译器内联多路分发) @zk(protocol: ZKProtocol) public func verify_zk_proof( proof: bytes, public_inputs: []uint64, vk: bytes /// 验证密钥,格式取决于协议 ) -> bool; ``` ### 1.3 NVM指令扩展 | 操作码 | 指令名称 | 功能 | Gas成本 | |--------|----------|------|---------| | 0xF8 | ZK_VERIFY_PLONK | 验证Plonk证明(BN254/Bls12-381) | 25,000 | | 0xF9 | ZK_VERIFY_HALO2 | 验证Halo2证明(KZG/IPA) | 35,000 | | 0xFA | ZK_AGGREGATE | 聚合多个ZK证明(用于批量汇率收据) | 15,000 + 每证明5,000 | ### 1.4 标准库封装 (xtzh/zk.charter) ```charter /// 通用ZK验证函数(协议在编译期常量时零开销) public func verify_proof( proof: bytes, inputs: []uint64, vk: bytes ) -> bool { // 编译器优化:若协议为编译期常量,直接内联对应指令 return __builtin_zk_verify(proof, inputs, vk); } /// 批量验证多个证明(用于同一批汇率收据) public func verify_batch( proofs: []bytes, inputs_list: [][]uint64, vks: []bytes, protocol: ZKProtocol ) -> bool { return __builtin_zk_aggregate(proofs, inputs_list, vks, protocol); } ``` ### 1.5 使用示例(预言机代码) ```charter import "xtzh/zk.charter"; @oracle func submit_zk_rate_with_plonk( receipt: ConstitutionalReceipt, proof: bytes, inputs: []uint64, vk: bytes ) { // 选择Plonk协议(编译期常量) const ZKProtocol PROTOCOL = ZKProtocol.PlonkBn254; require(xtzh::zk::verify_proof(proof, inputs, vk), "ZK proof invalid"); xtzh::submit_rate(receipt); } ``` --- ## 2. @system_constant 支持复杂结构体常量 ### 2.1 问题 现有@system_constant仅支持基本类型(整数、字节数组、公钥列表)。但汇率系统需要存储更复杂的配置,如: 1. 商品权重向量(18个uint16) 2. 多协议验证密钥集合(每个协议对应一个bytes) 3. 预言机节点元数据(地址、公钥、权重) ### 2.2 语法扩展 ```charter /// 商品权重配置 public struct CommodityConfig { beta: [18]uint16; // 静态权重(基点,和=5000) names: [18]bytes32; // 商品名称(固定长度字节) enabled: [18]bool; // 是否激活 } /// 预言机节点信息 public struct OracleNode { pubkey: bytes48; // BLS公钥 weight: uint16; // 投票权重(1-100) endpoint: bytes; // API地址(仅链下使用) } /// 系统常量声明 @system_constant(key = "XTZH_COMMODITY_CONFIG") public func commodity_config() -> CommodityConfig; @system_constant(key = "XTZH_ORACLE_NODES") public func oracle_nodes() -> []OracleNode; @system_constant(key = "XTZH_ZK_VKS") public struct ZKVerificationKeys { groth16: bytes, plonk_bn254: bytes, halo2_kzg: bytes } ``` **语义**: 1. 编译器为每个@system_constant结构体生成一个全局只读存储槽,该槽在合约部署时由系统状态树加载一次,并缓存在内存中(类似immutable) 2. 若结构体较大,编译器可选择惰性加载(首次访问时加载) ### 2.3 实现方案 1. **编译时生成**:对于每个@system_constant函数,编译器生成一个对应的全局变量,并在构造函数中插入从系统状态树读取并反序列化的代码 2. **反序列化代码自动生成**:根据结构体定义生成对应的from_bytes函数 3. **访问开销**:首次访问触发一次SYSTEM_STATE_READ指令,后续访问为内存加载(零成本) ### 2.4 使用示例 ```charter import "xtzh/governance.charter"; func get_gold_weight() -> uint16 { let config = xtzh::governance::commodity_config(); return config.beta[0]; // 假设黄金是第一个商品 } func verify_with_latest_vk(proof: bytes, inputs: []uint64) -> bool { let vks = xtzh::governance::zk_vks(); return xtzh::zk::verify_proof(proof, inputs, vks.groth16); } ``` --- ## 3. xtzh::simulate_rate 沙箱函数(链下测试) ### 3.1 需求 开发者(尤其是RWA资产发行方)需要在链下环境测试XTZH汇率变化对资产估值、清算线的影响,而无需部署主网合约或依赖预言机网络。要求: 1. 完全模拟链上汇率计算逻辑(相同权重模型、相同价格输入) 2. 支持历史回测与假设情景 3. 无需实际支付Gas ### 3.2 设计:条件编译 + 模拟运行时 Charter编译器提供链下执行模式(--mode=offchain),在该模式下: 1. 所有@oracle、@system_constant调用被重定向到本地模拟环境 2. 区块链状态(账户余额、存储)从快照加载或手动构造 3. Gas计量被禁用(或仅记录不扣费) ### 3.3 标准库扩展 ```charter /// 仅在offchain模式可用,主网编译时报错 #[cfg(mode = "offchain")] public func simulate_rate( commodity_prices: [18]uint64, // 输入18种商品的美元价格(6位小数) gold_price: uint64 // 黄金价格(美元/盎司,6位小数) ) -> uint64 { // 1. 加载权重配置(offchain模式下从本地JSON读取) let config = __offchain_load_config("xtzh_commodity_config.json"); // 2. 计算加权平均价格 let mut weighted_sum: uint128 = 0; for i in 0..18 { if config.enabled[i] { weighted_sum += (commodity_prices[i] as uint128) * (config.beta[i] as uint128); } } let basket_price = weighted_sum / 5000; // 归一化(权重和=5000基点) // 3. 计算XTZH汇率(1 XTZH = basket_price / gold_price) return (basket_price * 1_000_000) / gold_price; } /// 批量回测历史数据 #[cfg(mode = "offchain")] public func backtest_rates( historical_data: []HistoricalSnapshot ) -> []uint64 { let mut rates = []; for snapshot in historical_data { rates.push(simulate_rate(snapshot.prices, snapshot.gold_price)); } return rates; } ``` --- ## 关键要点总结 ### Charter语言特性 1. **@zk标记**:支持多种ZK证明系统(Groth16/Plonk/Halo2) 2. **@system_constant**:支持复杂结构体作为系统常量 3. **@oracle**:预言机函数标记 4. **#[cfg(mode)]**:条件编译支持链下测试 5. **内置函数**: - `__builtin_zk_verify()`: ZK证明验证 - `__builtin_zk_aggregate()`: 批量ZK证明聚合 - `__offchain_load_config()`: 链下配置加载 ### 数据类型 - `bytes`: 动态字节数组 - `bytes32`, `bytes48`: 固定长度字节数组 - `[N]T`: 固定长度数组 - `[]T`: 动态数组 - `map`: 映射 - `uint16`, `uint64`, `uint128`, `uint256`: 无符号整数 - `bool`: 布尔值 - `DID`: 去中心化身份标识符 - `Address`: NAC地址(32字节) ### 合约结构 ```charter contract ContractName { storage { // 存储变量 } constructor(params) { // 构造函数 } pub fn function_name(params) -> ReturnType { // 公共函数 } } ``` ### Asset定义 ```charter asset AssetName { gnacs: 0xXXXXXXXXXXXX; // GNACS编码 sovereignty: C2; // 主权级别 owner: DID; // 其他字段 } ``` --- **重要提醒**: - NAC公链使用Charter语言,**不是Solidity** - 不要继承ERC-20、ERC-721等以太坊标准 - 使用ACC-20协议作为NAC的资产标准 - 所有合约必须使用Charter语言编写