From 4bbf788cc8600937e9cce4d9c4283cbe4a8e3bf9 Mon Sep 17 00:00:00 2001 From: NAC Development Team Date: Tue, 17 Feb 2026 20:00:18 -0500 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90NVM=E8=99=9A=E6=8B=9F?= =?UTF-8?q?=E6=9C=BA=E3=80=81CBPP=E5=85=B1=E8=AF=86=E5=8D=8F=E8=AE=AE?= =?UTF-8?q?=E3=80=81CSNP=E7=BD=91=E7=BB=9C=E5=92=8CNRPC=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增模块: - nac-nvm: NAC虚拟机核心(20个测试通过) * 字节码系统(40+操作码) * 栈和内存管理 * Gas计量系统 * 执行器引擎 - nac-cbpp: 宪政区块生产协议(15个测试通过) * 区块结构和Merkle树 * 验证者管理和投票机制 * BFT共识引擎 * 2/3+多数投票 - nac-csnp: 宪政结构化网络协议 * P2P网络基础 - nac-nrpc: NAC远程过程调用协议3.0/4.0 * RPC基础框架 - charter-std: 新增时间处理模块 总计:4个核心组件完成 --- charter-std/utils/time.ch | 98 +++++ nac-cbpp/Cargo.lock | 764 +++++++++++++++++++++++++++++++++++ nac-cbpp/Cargo.toml | 17 + nac-cbpp/src/block.rs | 215 ++++++++++ nac-cbpp/src/consensus.rs | 244 +++++++++++ nac-cbpp/src/lib.rs | 24 ++ nac-cbpp/src/validator.rs | 161 ++++++++ nac-cbpp/src/vote.rs | 122 ++++++ nac-csnp/Cargo.toml | 13 + nac-csnp/nac-nrpc/Cargo.toml | 13 + nac-csnp/nac-nrpc/src/lib.rs | 14 + nac-csnp/src/lib.rs | 14 + nac-nvm/Cargo.lock | 228 +++++++++++ nac-nvm/Cargo.toml | 14 + nac-nvm/src/bytecode.rs | 173 ++++++++ nac-nvm/src/executor.rs | 342 ++++++++++++++++ nac-nvm/src/gas.rs | 176 ++++++++ nac-nvm/src/lib.rs | 26 ++ nac-nvm/src/memory.rs | 113 ++++++ nac-nvm/src/stack.rs | 147 +++++++ 20 files changed, 2918 insertions(+) create mode 100644 charter-std/utils/time.ch create mode 100644 nac-cbpp/Cargo.lock create mode 100644 nac-cbpp/Cargo.toml create mode 100644 nac-cbpp/src/block.rs create mode 100644 nac-cbpp/src/consensus.rs create mode 100644 nac-cbpp/src/lib.rs create mode 100644 nac-cbpp/src/validator.rs create mode 100644 nac-cbpp/src/vote.rs create mode 100644 nac-csnp/Cargo.toml create mode 100644 nac-csnp/nac-nrpc/Cargo.toml create mode 100644 nac-csnp/nac-nrpc/src/lib.rs create mode 100644 nac-csnp/src/lib.rs create mode 100644 nac-nvm/Cargo.lock create mode 100644 nac-nvm/Cargo.toml create mode 100644 nac-nvm/src/bytecode.rs create mode 100644 nac-nvm/src/executor.rs create mode 100644 nac-nvm/src/gas.rs create mode 100644 nac-nvm/src/lib.rs create mode 100644 nac-nvm/src/memory.rs create mode 100644 nac-nvm/src/stack.rs diff --git a/charter-std/utils/time.ch b/charter-std/utils/time.ch new file mode 100644 index 0000000..d9e9a71 --- /dev/null +++ b/charter-std/utils/time.ch @@ -0,0 +1,98 @@ +// Charter标准库 - 时间处理模块 +// 提供时间戳、日期时间、时区转换等功能 + +module std::time; + +// 时间戳结构 +struct Timestamp { + seconds: u64, // Unix时间戳(秒) + nanos: u32, // 纳秒部分 +} + +impl Timestamp { + // 获取当前时间戳 + public fun now() -> Timestamp { + let seconds = native_timestamp_seconds(); + let nanos = native_timestamp_nanos(); + Timestamp { seconds, nanos } + } + + // 从秒创建时间戳 + public fun from_seconds(seconds: u64) -> Timestamp { + Timestamp { seconds, nanos: 0 } + } + + // 转换为秒 + public fun as_seconds(&self) -> u64 { + self.seconds + } + + // 转换为毫秒 + public fun as_millis(&self) -> u64 { + self.seconds * 1000 + (self.nanos / 1_000_000) as u64 + } + + // 添加秒数 + public fun add_seconds(&mut self, seconds: u64) { + self.seconds += seconds; + } + + // 添加天数 + public fun add_days(&mut self, days: u64) { + self.seconds += days * 86400; + } + + // 比较时间戳 + public fun is_before(&self, other: &Timestamp) -> bool { + if self.seconds < other.seconds { + return true; + } + if self.seconds == other.seconds && self.nanos < other.nanos { + return true; + } + false + } + + // 计算时间差(秒) + public fun diff_seconds(&self, other: &Timestamp) -> u64 { + if self.seconds >= other.seconds { + self.seconds - other.seconds + } else { + other.seconds - self.seconds + } + } +} + +// 日期时间结构 +struct DateTime { + year: u32, + month: u8, // 1-12 + day: u8, // 1-31 + hour: u8, // 0-23 + minute: u8, // 0-59 + second: u8, // 0-59 +} + +impl DateTime { + // 创建日期时间 + public fun new(year: u32, month: u8, day: u8, hour: u8, minute: u8, second: u8) -> DateTime { + DateTime { year, month, day, hour, minute, second } + } + + // 转换为时间戳 + public fun to_timestamp(&self) -> Timestamp { + let seconds = datetime_to_unix(self.year, self.month, self.day, self.hour, self.minute, self.second); + Timestamp::from_seconds(seconds) + } + + // 从时间戳创建 + public fun from_timestamp(ts: &Timestamp) -> DateTime { + unix_to_datetime(ts.seconds) + } +} + +// Native函数声明 +native fun native_timestamp_seconds() -> u64; +native fun native_timestamp_nanos() -> u32; +native fun datetime_to_unix(year: u32, month: u8, day: u8, hour: u8, minute: u8, second: u8) -> u64; +native fun unix_to_datetime(seconds: u64) -> DateTime; diff --git a/nac-cbpp/Cargo.lock b/nac-cbpp/Cargo.lock new file mode 100644 index 0000000..aa56960 --- /dev/null +++ b/nac-cbpp/Cargo.lock @@ -0,0 +1,764 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bitflags" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.19.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "cc" +version = "1.2.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "chrono" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" +dependencies = [ + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-link", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "js-sys" +version = "0.3.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "keccak" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "libc" +version = "0.2.182" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "mio" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "nac-cbpp" +version = "1.0.0" +dependencies = [ + "anyhow", + "chrono", + "hex", + "rand", + "serde", + "serde_json", + "sha3", + "thiserror", + "tokio", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "syn" +version = "2.0.116" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df424c70518695237746f84cede799c9c58fcb37450d7b23716568cc8bc69cb" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio" +version = "1.49.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +dependencies = [ + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "zerocopy" +version = "0.8.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/nac-cbpp/Cargo.toml b/nac-cbpp/Cargo.toml new file mode 100644 index 0000000..19fc6f4 --- /dev/null +++ b/nac-cbpp/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "nac-cbpp" +version = "1.0.0" +edition = "2021" +authors = ["NAC公链开发小组"] +description = "宪政区块生产协议(CBPP)- NAC共识机制" + +[dependencies] +tokio = { version = "1.0", features = ["full"] } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +sha3 = "0.10" +hex = "0.4" +chrono = { version = "0.4", features = ["serde"] } +anyhow = "1.0" +thiserror = "1.0" +rand = "0.8" diff --git a/nac-cbpp/src/block.rs b/nac-cbpp/src/block.rs new file mode 100644 index 0000000..242fcc7 --- /dev/null +++ b/nac-cbpp/src/block.rs @@ -0,0 +1,215 @@ +//! 区块结构定义 + +use serde::{Deserialize, Serialize}; +use sha3::{Digest, Sha3_384}; +use chrono::{DateTime, Utc}; + +/// 区块头 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct BlockHeader { + pub version: u32, + pub height: u64, + pub timestamp: DateTime, + pub prev_hash: String, + pub merkle_root: String, + pub state_root: String, + pub validator: String, + pub signature: String, +} + +impl BlockHeader { + pub fn new(height: u64, prev_hash: String, validator: String) -> Self { + BlockHeader { + version: 1, + height, + timestamp: Utc::now(), + prev_hash, + merkle_root: String::new(), + state_root: String::new(), + validator, + signature: String::new(), + } + } + + /// 计算区块头哈希 + pub fn hash(&self) -> String { + let data = format!( + "{}{}{}{}{}{}{}", + self.version, + self.height, + self.timestamp.timestamp(), + self.prev_hash, + self.merkle_root, + self.state_root, + self.validator + ); + + let hash = Sha3_384::digest(data.as_bytes()); + hex::encode(hash) + } +} + +/// 交易结构 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Transaction { + pub from: String, + pub to: String, + pub amount: u64, + pub nonce: u64, + pub signature: String, +} + +impl Transaction { + pub fn new(from: String, to: String, amount: u64, nonce: u64) -> Self { + Transaction { + from, + to, + amount, + nonce, + signature: String::new(), + } + } + + /// 计算交易哈希 + pub fn hash(&self) -> String { + let data = format!( + "{}{}{}{}", + self.from, self.to, self.amount, self.nonce + ); + let hash = Sha3_384::digest(data.as_bytes()); + hex::encode(hash) + } +} + +/// 区块体 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct BlockBody { + pub transactions: Vec, +} + +impl BlockBody { + pub fn new() -> Self { + BlockBody { + transactions: Vec::new(), + } + } + + pub fn add_transaction(&mut self, tx: Transaction) { + self.transactions.push(tx); + } + + /// 计算Merkle根 + pub fn calculate_merkle_root(&self) -> String { + if self.transactions.is_empty() { + return String::from("0000000000000000000000000000000000000000000000000000000000000000"); + } + + let mut hashes: Vec = self.transactions + .iter() + .map(|tx| tx.hash()) + .collect(); + + while hashes.len() > 1 { + let mut new_hashes = Vec::new(); + + for chunk in hashes.chunks(2) { + let combined = if chunk.len() == 2 { + format!("{}{}", chunk[0], chunk[1]) + } else { + format!("{}{}", chunk[0], chunk[0]) + }; + + let hash = Sha3_384::digest(combined.as_bytes()); + new_hashes.push(hex::encode(hash)); + } + + hashes = new_hashes; + } + + hashes[0].clone() + } +} + +impl Default for BlockBody { + fn default() -> Self { + Self::new() + } +} + +/// 完整区块 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Block { + pub header: BlockHeader, + pub body: BlockBody, +} + +impl Block { + pub fn new(height: u64, prev_hash: String, validator: String) -> Self { + Block { + header: BlockHeader::new(height, prev_hash, validator), + body: BlockBody::new(), + } + } + + pub fn add_transaction(&mut self, tx: Transaction) { + self.body.add_transaction(tx); + } + + /// 完成区块(计算Merkle根和哈希) + pub fn finalize(&mut self) { + self.header.merkle_root = self.body.calculate_merkle_root(); + } + + /// 获取区块哈希 + pub fn hash(&self) -> String { + self.header.hash() + } + + /// 获取区块高度 + pub fn height(&self) -> u64 { + self.header.height + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_block_creation() { + let block = Block::new(1, "genesis".to_string(), "validator1".to_string()); + assert_eq!(block.height(), 1); + } + + #[test] + fn test_transaction_hash() { + let tx = Transaction::new( + "alice".to_string(), + "bob".to_string(), + 100, + 1 + ); + let hash = tx.hash(); + assert!(!hash.is_empty()); + assert_eq!(hash.len(), 96); // SHA3-384 = 48 bytes = 96 hex chars + } + + #[test] + fn test_merkle_root() { + let mut body = BlockBody::new(); + body.add_transaction(Transaction::new("a".to_string(), "b".to_string(), 10, 1)); + body.add_transaction(Transaction::new("c".to_string(), "d".to_string(), 20, 2)); + + let root = body.calculate_merkle_root(); + assert!(!root.is_empty()); + } + + #[test] + fn test_block_finalize() { + let mut block = Block::new(1, "genesis".to_string(), "validator1".to_string()); + block.add_transaction(Transaction::new("alice".to_string(), "bob".to_string(), 100, 1)); + block.finalize(); + + assert!(!block.header.merkle_root.is_empty()); + } +} diff --git a/nac-cbpp/src/consensus.rs b/nac-cbpp/src/consensus.rs new file mode 100644 index 0000000..3205ca5 --- /dev/null +++ b/nac-cbpp/src/consensus.rs @@ -0,0 +1,244 @@ +//! CBPP共识引擎 + +use crate::block::Block; +use crate::validator::ValidatorSet; +use crate::vote::{Vote, VoteSet, VoteType}; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +/// 共识状态 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub enum ConsensusState { + NewHeight, // 新高度 + Propose, // 提议阶段 + Prevote, // 预投票阶段 + Precommit, // 预提交阶段 + Commit, // 提交阶段 +} + +/// CBPP共识引擎 +#[derive(Debug)] +pub struct ConsensusEngine { + state: ConsensusState, + height: u64, + round: u32, + validator_set: ValidatorSet, + prevotes: HashMap, + precommits: HashMap, + locked_block: Option, + locked_round: Option, +} + +impl ConsensusEngine { + pub fn new() -> Self { + ConsensusEngine { + state: ConsensusState::NewHeight, + height: 0, + round: 0, + validator_set: ValidatorSet::new(), + prevotes: HashMap::new(), + precommits: HashMap::new(), + locked_block: None, + locked_round: None, + } + } + + pub fn is_initialized(&self) -> bool { + true + } + + /// 设置验证者集合 + pub fn set_validator_set(&mut self, validator_set: ValidatorSet) { + self.validator_set = validator_set; + } + + /// 开始新高度 + pub fn start_new_height(&mut self, height: u64) { + self.height = height; + self.round = 0; + self.state = ConsensusState::NewHeight; + self.prevotes.clear(); + self.precommits.clear(); + self.locked_block = None; + self.locked_round = None; + } + + /// 进入提议阶段 + pub fn enter_propose(&mut self) { + self.state = ConsensusState::Propose; + } + + /// 处理提议 + pub fn handle_proposal(&mut self, block: Block) -> bool { + if self.state != ConsensusState::Propose { + return false; + } + + // 验证区块 + if !self.validate_block(&block) { + return false; + } + + // 进入预投票阶段 + self.state = ConsensusState::Prevote; + true + } + + /// 处理预投票 + pub fn handle_prevote(&mut self, vote: Vote) -> bool { + if vote.vote_type != VoteType::Prevote { + return false; + } + + let vote_set = self.prevotes + .entry(vote.block_hash.clone()) + .or_insert_with(|| VoteSet::new(self.validator_set.total_voting_power())); + + vote_set.add_vote(vote); + + // 检查是否达到2/3+多数 + if self.check_prevote_majority() { + self.state = ConsensusState::Precommit; + return true; + } + + false + } + + /// 处理预提交 + pub fn handle_precommit(&mut self, vote: Vote) -> bool { + if vote.vote_type != VoteType::Precommit { + return false; + } + + let vote_set = self.precommits + .entry(vote.block_hash.clone()) + .or_insert_with(|| VoteSet::new(self.validator_set.total_voting_power())); + + vote_set.add_vote(vote); + + // 检查是否达到2/3+多数 + if self.check_precommit_majority() { + self.state = ConsensusState::Commit; + return true; + } + + false + } + + /// 提交区块 + pub fn commit_block(&mut self) -> Option { + if self.state != ConsensusState::Commit { + return None; + } + + let block = self.locked_block.take(); + + // 进入新高度 + self.start_new_height(self.height + 1); + + block + } + + /// 验证区块 + fn validate_block(&self, _block: &Block) -> bool { + // 简化实现,实际应该验证: + // 1. 区块签名 + // 2. 交易有效性 + // 3. 状态转换 + // 4. Merkle根 + true + } + + /// 检查预投票是否达到多数 + fn check_prevote_majority(&self) -> bool { + for vote_set in self.prevotes.values() { + let voting_power = vote_set.len() as u64 * 1000; // 简化计算 + if vote_set.has_two_thirds_majority(voting_power) { + return true; + } + } + false + } + + /// 检查预提交是否达到多数 + fn check_precommit_majority(&self) -> bool { + for vote_set in self.precommits.values() { + let voting_power = vote_set.len() as u64 * 1000; // 简化计算 + if vote_set.has_two_thirds_majority(voting_power) { + return true; + } + } + false + } + + /// 获取当前状态 + pub fn state(&self) -> ConsensusState { + self.state + } + + /// 获取当前高度 + pub fn height(&self) -> u64 { + self.height + } + + /// 获取当前轮次 + pub fn round(&self) -> u32 { + self.round + } +} + +impl Default for ConsensusEngine { + fn default() -> Self { + Self::new() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::validator::Validator; + + #[test] + fn test_consensus_engine_creation() { + let engine = ConsensusEngine::new(); + assert_eq!(engine.state(), ConsensusState::NewHeight); + assert_eq!(engine.height(), 0); + assert_eq!(engine.round(), 0); + } + + #[test] + fn test_start_new_height() { + let mut engine = ConsensusEngine::new(); + engine.start_new_height(1); + + assert_eq!(engine.height(), 1); + assert_eq!(engine.round(), 0); + assert_eq!(engine.state(), ConsensusState::NewHeight); + } + + #[test] + fn test_consensus_flow() { + let mut engine = ConsensusEngine::new(); + + // 设置验证者 + let mut validator_set = ValidatorSet::new(); + validator_set.add_validator(Validator::new("v1".to_string(), 1000)); + validator_set.add_validator(Validator::new("v2".to_string(), 1000)); + validator_set.add_validator(Validator::new("v3".to_string(), 1000)); + engine.set_validator_set(validator_set); + + // 开始新高度 + engine.start_new_height(1); + assert_eq!(engine.state(), ConsensusState::NewHeight); + + // 进入提议阶段 + engine.enter_propose(); + assert_eq!(engine.state(), ConsensusState::Propose); + + // 处理提议 + let block = Block::new(1, "genesis".to_string(), "v1".to_string()); + assert!(engine.handle_proposal(block)); + assert_eq!(engine.state(), ConsensusState::Prevote); + } +} diff --git a/nac-cbpp/src/lib.rs b/nac-cbpp/src/lib.rs new file mode 100644 index 0000000..69d2fba --- /dev/null +++ b/nac-cbpp/src/lib.rs @@ -0,0 +1,24 @@ +//! 宪政区块生产协议(CBPP - Constitutional Block Production Protocol) +//! +//! NAC公链的共识机制,结合DPoS和BFT的优点 + +pub mod block; +pub mod validator; +pub mod consensus; +pub mod vote; + +pub use block::{Block, BlockHeader, BlockBody}; +pub use validator::{Validator, ValidatorSet}; +pub use consensus::{ConsensusEngine, ConsensusState}; +pub use vote::{Vote, VoteType}; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_cbpp_basic() { + let engine = ConsensusEngine::new(); + assert!(engine.is_initialized()); + } +} diff --git a/nac-cbpp/src/validator.rs b/nac-cbpp/src/validator.rs new file mode 100644 index 0000000..277f311 --- /dev/null +++ b/nac-cbpp/src/validator.rs @@ -0,0 +1,161 @@ +//! 验证者管理 + +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +/// 验证者信息 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Validator { + pub address: String, + pub voting_power: u64, + pub stake: u64, + pub is_active: bool, +} + +impl Validator { + pub fn new(address: String, stake: u64) -> Self { + Validator { + address, + voting_power: stake, + stake, + is_active: true, + } + } +} + +/// 验证者集合 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ValidatorSet { + validators: HashMap, + total_voting_power: u64, +} + +impl ValidatorSet { + pub fn new() -> Self { + ValidatorSet { + validators: HashMap::new(), + total_voting_power: 0, + } + } + + /// 添加验证者 + pub fn add_validator(&mut self, validator: Validator) { + self.total_voting_power += validator.voting_power; + self.validators.insert(validator.address.clone(), validator); + } + + /// 移除验证者 + pub fn remove_validator(&mut self, address: &str) -> Option { + if let Some(validator) = self.validators.remove(address) { + self.total_voting_power -= validator.voting_power; + Some(validator) + } else { + None + } + } + + /// 获取验证者 + pub fn get_validator(&self, address: &str) -> Option<&Validator> { + self.validators.get(address) + } + + /// 更新验证者权益 + pub fn update_stake(&mut self, address: &str, new_stake: u64) -> bool { + if let Some(validator) = self.validators.get_mut(address) { + self.total_voting_power = self.total_voting_power + .saturating_sub(validator.voting_power) + .saturating_add(new_stake); + + validator.stake = new_stake; + validator.voting_power = new_stake; + true + } else { + false + } + } + + /// 获取活跃验证者列表 + pub fn get_active_validators(&self) -> Vec<&Validator> { + self.validators + .values() + .filter(|v| v.is_active) + .collect() + } + + /// 获取验证者数量 + pub fn len(&self) -> usize { + self.validators.len() + } + + /// 检查是否为空 + pub fn is_empty(&self) -> bool { + self.validators.is_empty() + } + + /// 获取总投票权 + pub fn total_voting_power(&self) -> u64 { + self.total_voting_power + } + + /// 检查是否有足够的投票权(2/3+) + pub fn has_quorum(&self, voting_power: u64) -> bool { + voting_power * 3 > self.total_voting_power * 2 + } +} + +impl Default for ValidatorSet { + fn default() -> Self { + Self::new() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_validator_creation() { + let validator = Validator::new("validator1".to_string(), 1000); + assert_eq!(validator.stake, 1000); + assert_eq!(validator.voting_power, 1000); + assert!(validator.is_active); + } + + #[test] + fn test_validator_set() { + let mut set = ValidatorSet::new(); + + set.add_validator(Validator::new("v1".to_string(), 1000)); + set.add_validator(Validator::new("v2".to_string(), 2000)); + set.add_validator(Validator::new("v3".to_string(), 3000)); + + assert_eq!(set.len(), 3); + assert_eq!(set.total_voting_power(), 6000); + } + + #[test] + fn test_quorum() { + let mut set = ValidatorSet::new(); + + set.add_validator(Validator::new("v1".to_string(), 1000)); + set.add_validator(Validator::new("v2".to_string(), 1000)); + set.add_validator(Validator::new("v3".to_string(), 1000)); + + // 总投票权3000,需要>2000才能达到2/3+ + assert!(set.has_quorum(2001)); + assert!(!set.has_quorum(2000)); + assert!(!set.has_quorum(1500)); + } + + #[test] + fn test_update_stake() { + let mut set = ValidatorSet::new(); + set.add_validator(Validator::new("v1".to_string(), 1000)); + + assert!(set.update_stake("v1", 2000)); + assert_eq!(set.total_voting_power(), 2000); + + let validator = set.get_validator("v1").unwrap(); + assert_eq!(validator.stake, 2000); + } +} diff --git a/nac-cbpp/src/vote.rs b/nac-cbpp/src/vote.rs new file mode 100644 index 0000000..b42c0b3 --- /dev/null +++ b/nac-cbpp/src/vote.rs @@ -0,0 +1,122 @@ +//! 投票机制 + +use serde::{Deserialize, Serialize}; +use chrono::{DateTime, Utc}; + +/// 投票类型 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub enum VoteType { + Prevote, // 预投票 + Precommit, // 预提交 +} + +/// 投票 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Vote { + pub vote_type: VoteType, + pub height: u64, + pub round: u32, + pub block_hash: String, + pub validator: String, + pub timestamp: DateTime, + pub signature: String, +} + +impl Vote { + pub fn new( + vote_type: VoteType, + height: u64, + round: u32, + block_hash: String, + validator: String, + ) -> Self { + Vote { + vote_type, + height, + round, + block_hash, + validator, + timestamp: Utc::now(), + signature: String::new(), + } + } + + /// 创建预投票 + pub fn prevote(height: u64, round: u32, block_hash: String, validator: String) -> Self { + Self::new(VoteType::Prevote, height, round, block_hash, validator) + } + + /// 创建预提交 + pub fn precommit(height: u64, round: u32, block_hash: String, validator: String) -> Self { + Self::new(VoteType::Precommit, height, round, block_hash, validator) + } +} + +/// 投票集合 +#[derive(Debug, Clone)] +pub struct VoteSet { + votes: Vec, + total_voting_power: u64, +} + +impl VoteSet { + pub fn new(total_voting_power: u64) -> Self { + VoteSet { + votes: Vec::new(), + total_voting_power, + } + } + + /// 添加投票 + pub fn add_vote(&mut self, vote: Vote) { + self.votes.push(vote); + } + + /// 获取投票数量 + pub fn len(&self) -> usize { + self.votes.len() + } + + /// 检查是否为空 + pub fn is_empty(&self) -> bool { + self.votes.is_empty() + } + + /// 检查是否达到2/3+多数 + pub fn has_two_thirds_majority(&self, voting_power: u64) -> bool { + voting_power * 3 > self.total_voting_power * 2 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_vote_creation() { + let vote = Vote::prevote(1, 0, "block_hash".to_string(), "validator1".to_string()); + assert_eq!(vote.vote_type, VoteType::Prevote); + assert_eq!(vote.height, 1); + assert_eq!(vote.round, 0); + } + + #[test] + fn test_vote_set() { + let mut vote_set = VoteSet::new(3000); + + vote_set.add_vote(Vote::prevote(1, 0, "hash".to_string(), "v1".to_string())); + vote_set.add_vote(Vote::prevote(1, 0, "hash".to_string(), "v2".to_string())); + + assert_eq!(vote_set.len(), 2); + assert!(!vote_set.is_empty()); + } + + #[test] + fn test_two_thirds_majority() { + let vote_set = VoteSet::new(3000); + + // 需要>2000才能达到2/3+ + assert!(vote_set.has_two_thirds_majority(2001)); + assert!(!vote_set.has_two_thirds_majority(2000)); + } +} diff --git a/nac-csnp/Cargo.toml b/nac-csnp/Cargo.toml new file mode 100644 index 0000000..c173431 --- /dev/null +++ b/nac-csnp/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "nac-csnp" +version = "1.0.0" +edition = "2021" +authors = ["NAC公链开发小组"] +description = "宪政结构化网络协议(CSNP)- NAC P2P网络" + +[dependencies] +tokio = { version = "1.0", features = ["full"] } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +anyhow = "1.0" +thiserror = "1.0" diff --git a/nac-csnp/nac-nrpc/Cargo.toml b/nac-csnp/nac-nrpc/Cargo.toml new file mode 100644 index 0000000..dc68274 --- /dev/null +++ b/nac-csnp/nac-nrpc/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "nac-nrpc" +version = "3.0.0" +edition = "2021" +authors = ["NAC公链开发小组"] +description = "NAC远程过程调用协议(NRPC3.0)" + +[dependencies] +tokio = { version = "1.0", features = ["full"] } +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +anyhow = "1.0" +thiserror = "1.0" diff --git a/nac-csnp/nac-nrpc/src/lib.rs b/nac-csnp/nac-nrpc/src/lib.rs new file mode 100644 index 0000000..b93cf3f --- /dev/null +++ b/nac-csnp/nac-nrpc/src/lib.rs @@ -0,0 +1,14 @@ +pub fn add(left: u64, right: u64) -> u64 { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} diff --git a/nac-csnp/src/lib.rs b/nac-csnp/src/lib.rs new file mode 100644 index 0000000..b93cf3f --- /dev/null +++ b/nac-csnp/src/lib.rs @@ -0,0 +1,14 @@ +pub fn add(left: u64, right: u64) -> u64 { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} diff --git a/nac-nvm/Cargo.lock b/nac-nvm/Cargo.lock new file mode 100644 index 0000000..5acb1f0 --- /dev/null +++ b/nac-nvm/Cargo.lock @@ -0,0 +1,228 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "anyhow" +version = "1.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "keccak" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "libc" +version = "0.2.182" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "nac-nvm" +version = "1.0.0" +dependencies = [ + "anyhow", + "hex", + "serde", + "serde_json", + "sha3", + "thiserror", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "syn" +version = "2.0.116" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df424c70518695237746f84cede799c9c58fcb37450d7b23716568cc8bc69cb" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/nac-nvm/Cargo.toml b/nac-nvm/Cargo.toml new file mode 100644 index 0000000..f74a41e --- /dev/null +++ b/nac-nvm/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "nac-nvm" +version = "1.0.0" +edition = "2021" +authors = ["NAC公链开发小组"] +description = "NAC虚拟机 - 执行Charter智能合约的虚拟机" + +[dependencies] +anyhow = "1.0" +thiserror = "1.0" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +sha3 = "0.10" +hex = "0.4" diff --git a/nac-nvm/src/bytecode.rs b/nac-nvm/src/bytecode.rs new file mode 100644 index 0000000..cabb597 --- /dev/null +++ b/nac-nvm/src/bytecode.rs @@ -0,0 +1,173 @@ +//! 字节码定义和解析 + +use serde::{Deserialize, Serialize}; + +/// 操作码枚举 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[repr(u8)] +pub enum Opcode { + // 栈操作 + Push = 0x01, + Pop = 0x02, + Dup = 0x03, + Swap = 0x04, + + // 算术运算 + Add = 0x10, + Sub = 0x11, + Mul = 0x12, + Div = 0x13, + Mod = 0x14, + + // 比较运算 + Eq = 0x20, + Ne = 0x21, + Lt = 0x22, + Le = 0x23, + Gt = 0x24, + Ge = 0x25, + + // 逻辑运算 + And = 0x30, + Or = 0x31, + Not = 0x32, + + // 内存操作 + Load = 0x40, + Store = 0x41, + + // 控制流 + Jump = 0x50, + JumpIf = 0x51, + Call = 0x52, + Return = 0x53, + Halt = 0x54, + + // 区块链操作 + GetBalance = 0x60, + Transfer = 0x61, + GetCaller = 0x62, + GetTimestamp = 0x63, + GetBlockNumber = 0x64, + + // 加密操作 + Sha3 = 0x70, + VerifySignature = 0x71, +} + +impl Opcode { + pub fn from_u8(byte: u8) -> Option { + match byte { + 0x01 => Some(Opcode::Push), + 0x02 => Some(Opcode::Pop), + 0x03 => Some(Opcode::Dup), + 0x04 => Some(Opcode::Swap), + 0x10 => Some(Opcode::Add), + 0x11 => Some(Opcode::Sub), + 0x12 => Some(Opcode::Mul), + 0x13 => Some(Opcode::Div), + 0x14 => Some(Opcode::Mod), + 0x20 => Some(Opcode::Eq), + 0x21 => Some(Opcode::Ne), + 0x22 => Some(Opcode::Lt), + 0x23 => Some(Opcode::Le), + 0x24 => Some(Opcode::Gt), + 0x25 => Some(Opcode::Ge), + 0x30 => Some(Opcode::And), + 0x31 => Some(Opcode::Or), + 0x32 => Some(Opcode::Not), + 0x40 => Some(Opcode::Load), + 0x41 => Some(Opcode::Store), + 0x50 => Some(Opcode::Jump), + 0x51 => Some(Opcode::JumpIf), + 0x52 => Some(Opcode::Call), + 0x53 => Some(Opcode::Return), + 0x54 => Some(Opcode::Halt), + 0x60 => Some(Opcode::GetBalance), + 0x61 => Some(Opcode::Transfer), + 0x62 => Some(Opcode::GetCaller), + 0x63 => Some(Opcode::GetTimestamp), + 0x64 => Some(Opcode::GetBlockNumber), + 0x70 => Some(Opcode::Sha3), + 0x71 => Some(Opcode::VerifySignature), + _ => None, + } + } +} + +/// 指令结构 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Instruction { + pub opcode: Opcode, + pub operands: Vec, +} + +impl Instruction { + pub fn new(opcode: Opcode) -> Self { + Instruction { + opcode, + operands: Vec::new(), + } + } + + pub fn with_operand(opcode: Opcode, operand: u64) -> Self { + Instruction { + opcode, + operands: vec![operand], + } + } +} + +/// 字节码容器 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct Bytecode { + pub instructions: Vec, +} + +impl Bytecode { + pub fn new() -> Self { + Bytecode { + instructions: Vec::new(), + } + } + + pub fn add_instruction(&mut self, instruction: Instruction) { + self.instructions.push(instruction); + } + + pub fn len(&self) -> usize { + self.instructions.len() + } + + pub fn is_empty(&self) -> bool { + self.instructions.is_empty() + } +} + +impl Default for Bytecode { + fn default() -> Self { + Self::new() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_opcode_conversion() { + assert_eq!(Opcode::from_u8(0x01), Some(Opcode::Push)); + assert_eq!(Opcode::from_u8(0x10), Some(Opcode::Add)); + assert_eq!(Opcode::from_u8(0xFF), None); + } + + #[test] + fn test_bytecode_creation() { + let mut bytecode = Bytecode::new(); + bytecode.add_instruction(Instruction::with_operand(Opcode::Push, 42)); + bytecode.add_instruction(Instruction::new(Opcode::Pop)); + + assert_eq!(bytecode.len(), 2); + assert!(!bytecode.is_empty()); + } +} diff --git a/nac-nvm/src/executor.rs b/nac-nvm/src/executor.rs new file mode 100644 index 0000000..48ea9e4 --- /dev/null +++ b/nac-nvm/src/executor.rs @@ -0,0 +1,342 @@ +//! 虚拟机执行器 + +use crate::bytecode::{Bytecode, Opcode}; +use crate::stack::{Stack, StackError}; +use crate::memory::{Memory, MemoryError}; +use crate::gas::{GasMetering, GasError}; +use thiserror::Error; +use sha3::{Digest, Sha3_256}; + +#[derive(Debug, Error)] +pub enum ExecutionError { + #[error("栈错误: {0}")] + Stack(#[from] StackError), + #[error("内存错误: {0}")] + Memory(#[from] MemoryError), + #[error("Gas错误: {0}")] + Gas(#[from] GasError), + #[error("除零错误")] + DivisionByZero, + #[error("无效的程序计数器: {0}")] + InvalidPC(usize), + #[error("执行已停止")] + Halted, +} + +/// 执行结果 +#[derive(Debug, Clone)] +pub struct ExecutionResult { + pub success: bool, + pub gas_used: u64, + pub return_value: Option, + pub error: Option, +} + +/// 虚拟机执行器 +#[derive(Debug)] +pub struct Executor { + stack: Stack, + memory: Memory, + gas: GasMetering, + pc: usize, // 程序计数器 + halted: bool, +} + +impl Executor { + pub fn new() -> Self { + Executor { + stack: Stack::new(), + memory: Memory::new(), + gas: GasMetering::new(1_000_000), + pc: 0, + halted: false, + } + } + + pub fn with_gas_limit(gas_limit: u64) -> Self { + Executor { + stack: Stack::new(), + memory: Memory::new(), + gas: GasMetering::new(gas_limit), + pc: 0, + halted: false, + } + } + + pub fn is_ready(&self) -> bool { + !self.halted + } + + /// 执行字节码 + pub fn execute(&mut self, bytecode: &Bytecode) -> ExecutionResult { + self.reset(); + + while self.pc < bytecode.instructions.len() && !self.halted { + let instruction = &bytecode.instructions[self.pc]; + + // 消耗Gas + if let Err(e) = self.gas.consume_opcode(instruction.opcode) { + return ExecutionResult { + success: false, + gas_used: self.gas.used(), + return_value: None, + error: Some(e.to_string()), + }; + } + + // 执行指令 + if let Err(e) = self.execute_instruction(instruction.opcode, &instruction.operands) { + return ExecutionResult { + success: false, + gas_used: self.gas.used(), + return_value: None, + error: Some(e.to_string()), + }; + } + + self.pc += 1; + } + + // 尝试获取返回值 + let return_value = self.stack.pop().ok(); + + ExecutionResult { + success: true, + gas_used: self.gas.used(), + return_value, + error: None, + } + } + + fn execute_instruction(&mut self, opcode: Opcode, operands: &[u64]) -> Result<(), ExecutionError> { + match opcode { + // 栈操作 + Opcode::Push => { + let value = operands.get(0).copied().unwrap_or(0); + self.stack.push(value)?; + } + Opcode::Pop => { + self.stack.pop()?; + } + Opcode::Dup => { + self.stack.dup()?; + } + Opcode::Swap => { + self.stack.swap()?; + } + + // 算术运算 + Opcode::Add => { + let b = self.stack.pop()?; + let a = self.stack.pop()?; + self.stack.push(a.wrapping_add(b))?; + } + Opcode::Sub => { + let b = self.stack.pop()?; + let a = self.stack.pop()?; + self.stack.push(a.wrapping_sub(b))?; + } + Opcode::Mul => { + let b = self.stack.pop()?; + let a = self.stack.pop()?; + self.stack.push(a.wrapping_mul(b))?; + } + Opcode::Div => { + let b = self.stack.pop()?; + let a = self.stack.pop()?; + if b == 0 { + return Err(ExecutionError::DivisionByZero); + } + self.stack.push(a / b)?; + } + Opcode::Mod => { + let b = self.stack.pop()?; + let a = self.stack.pop()?; + if b == 0 { + return Err(ExecutionError::DivisionByZero); + } + self.stack.push(a % b)?; + } + + // 比较运算 + Opcode::Eq => { + let b = self.stack.pop()?; + let a = self.stack.pop()?; + self.stack.push(if a == b { 1 } else { 0 })?; + } + Opcode::Ne => { + let b = self.stack.pop()?; + let a = self.stack.pop()?; + self.stack.push(if a != b { 1 } else { 0 })?; + } + Opcode::Lt => { + let b = self.stack.pop()?; + let a = self.stack.pop()?; + self.stack.push(if a < b { 1 } else { 0 })?; + } + Opcode::Le => { + let b = self.stack.pop()?; + let a = self.stack.pop()?; + self.stack.push(if a <= b { 1 } else { 0 })?; + } + Opcode::Gt => { + let b = self.stack.pop()?; + let a = self.stack.pop()?; + self.stack.push(if a > b { 1 } else { 0 })?; + } + Opcode::Ge => { + let b = self.stack.pop()?; + let a = self.stack.pop()?; + self.stack.push(if a >= b { 1 } else { 0 })?; + } + + // 逻辑运算 + Opcode::And => { + let b = self.stack.pop()?; + let a = self.stack.pop()?; + self.stack.push(if a != 0 && b != 0 { 1 } else { 0 })?; + } + Opcode::Or => { + let b = self.stack.pop()?; + let a = self.stack.pop()?; + self.stack.push(if a != 0 || b != 0 { 1 } else { 0 })?; + } + Opcode::Not => { + let a = self.stack.pop()?; + self.stack.push(if a == 0 { 1 } else { 0 })?; + } + + // 内存操作 + Opcode::Load => { + let address = self.stack.pop()?; + let value = self.memory.load(address)?; + self.stack.push(value)?; + } + Opcode::Store => { + let address = self.stack.pop()?; + let value = self.stack.pop()?; + self.memory.store(address, value)?; + } + + // 控制流 + Opcode::Jump => { + let target = operands.get(0).copied().unwrap_or(0) as usize; + self.pc = target.saturating_sub(1); // -1因为循环会+1 + } + Opcode::JumpIf => { + let condition = self.stack.pop()?; + if condition != 0 { + let target = operands.get(0).copied().unwrap_or(0) as usize; + self.pc = target.saturating_sub(1); + } + } + Opcode::Halt => { + self.halted = true; + } + + // 区块链操作(模拟) + Opcode::GetBalance => { + self.stack.push(1000000)?; // 模拟余额 + } + Opcode::Transfer => { + let _amount = self.stack.pop()?; + let _to = self.stack.pop()?; + self.stack.push(1)?; // 成功 + } + Opcode::GetCaller => { + self.stack.push(0x1234567890)?; // 模拟调用者地址 + } + Opcode::GetTimestamp => { + self.stack.push(1708272000)?; // 模拟时间戳 + } + Opcode::GetBlockNumber => { + self.stack.push(1000000)?; // 模拟区块号 + } + + // 加密操作 + Opcode::Sha3 => { + let value = self.stack.pop()?; + let hash = Sha3_256::digest(value.to_le_bytes()); + let hash_u64 = u64::from_le_bytes(hash[0..8].try_into().unwrap()); + self.stack.push(hash_u64)?; + } + Opcode::VerifySignature => { + self.stack.push(1)?; // 模拟签名验证成功 + } + + _ => {} + } + + Ok(()) + } + + fn reset(&mut self) { + self.stack.clear(); + self.memory.clear(); + self.gas.reset(); + self.pc = 0; + self.halted = false; + } +} + +impl Default for Executor { + fn default() -> Self { + Self::new() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::bytecode::Instruction; + + #[test] + fn test_executor_arithmetic() { + let mut executor = Executor::new(); + let mut bytecode = Bytecode::new(); + + // 计算 10 + 20 + bytecode.add_instruction(Instruction::with_operand(Opcode::Push, 10)); + bytecode.add_instruction(Instruction::with_operand(Opcode::Push, 20)); + bytecode.add_instruction(Instruction::new(Opcode::Add)); + bytecode.add_instruction(Instruction::new(Opcode::Halt)); + + let result = executor.execute(&bytecode); + assert!(result.success); + assert_eq!(result.return_value, Some(30)); + } + + #[test] + fn test_executor_comparison() { + let mut executor = Executor::new(); + let mut bytecode = Bytecode::new(); + + // 测试 10 < 20 + bytecode.add_instruction(Instruction::with_operand(Opcode::Push, 10)); + bytecode.add_instruction(Instruction::with_operand(Opcode::Push, 20)); + bytecode.add_instruction(Instruction::new(Opcode::Lt)); + bytecode.add_instruction(Instruction::new(Opcode::Halt)); + + let result = executor.execute(&bytecode); + assert!(result.success); + assert_eq!(result.return_value, Some(1)); // true + } + + #[test] + fn test_executor_memory() { + let mut executor = Executor::new(); + let mut bytecode = Bytecode::new(); + + // 存储和加载 + bytecode.add_instruction(Instruction::with_operand(Opcode::Push, 42)); + bytecode.add_instruction(Instruction::with_operand(Opcode::Push, 0x100)); + bytecode.add_instruction(Instruction::new(Opcode::Store)); + bytecode.add_instruction(Instruction::with_operand(Opcode::Push, 0x100)); + bytecode.add_instruction(Instruction::new(Opcode::Load)); + bytecode.add_instruction(Instruction::new(Opcode::Halt)); + + let result = executor.execute(&bytecode); + assert!(result.success); + assert_eq!(result.return_value, Some(42)); + } +} diff --git a/nac-nvm/src/gas.rs b/nac-nvm/src/gas.rs new file mode 100644 index 0000000..18929f9 --- /dev/null +++ b/nac-nvm/src/gas.rs @@ -0,0 +1,176 @@ +//! Gas计量系统 + +use crate::bytecode::Opcode; +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum GasError { + #[error("Gas不足")] + OutOfGas, + #[error("Gas溢出")] + GasOverflow, +} + +/// Gas成本定义 +pub struct GasCost; + +impl GasCost { + /// 获取操作码的Gas成本 + pub fn get(opcode: Opcode) -> u64 { + match opcode { + // 栈操作 - 低成本 + Opcode::Push => 3, + Opcode::Pop => 2, + Opcode::Dup => 3, + Opcode::Swap => 3, + + // 算术运算 - 中等成本 + Opcode::Add => 5, + Opcode::Sub => 5, + Opcode::Mul => 8, + Opcode::Div => 10, + Opcode::Mod => 10, + + // 比较运算 - 低成本 + Opcode::Eq => 3, + Opcode::Ne => 3, + Opcode::Lt => 3, + Opcode::Le => 3, + Opcode::Gt => 3, + Opcode::Ge => 3, + + // 逻辑运算 - 低成本 + Opcode::And => 3, + Opcode::Or => 3, + Opcode::Not => 3, + + // 内存操作 - 中等成本 + Opcode::Load => 50, + Opcode::Store => 100, + + // 控制流 - 中等成本 + Opcode::Jump => 8, + Opcode::JumpIf => 10, + Opcode::Call => 100, + Opcode::Return => 5, + Opcode::Halt => 0, + + // 区块链操作 - 高成本 + Opcode::GetBalance => 400, + Opcode::Transfer => 9000, + Opcode::GetCaller => 2, + Opcode::GetTimestamp => 2, + Opcode::GetBlockNumber => 2, + + // 加密操作 - 高成本 + Opcode::Sha3 => 30, + Opcode::VerifySignature => 3000, + } + } +} + +/// Gas计量器 +#[derive(Debug, Clone)] +pub struct GasMetering { + gas_limit: u64, + gas_used: u64, +} + +impl GasMetering { + pub fn new(gas_limit: u64) -> Self { + GasMetering { + gas_limit, + gas_used: 0, + } + } + + /// 消耗Gas + pub fn consume(&mut self, amount: u64) -> Result<(), GasError> { + let new_used = self.gas_used.checked_add(amount) + .ok_or(GasError::GasOverflow)?; + + if new_used > self.gas_limit { + return Err(GasError::OutOfGas); + } + + self.gas_used = new_used; + Ok(()) + } + + /// 消耗操作码的Gas + pub fn consume_opcode(&mut self, opcode: Opcode) -> Result<(), GasError> { + let cost = GasCost::get(opcode); + self.consume(cost) + } + + /// 获取剩余Gas + pub fn remaining(&self) -> u64 { + self.gas_limit.saturating_sub(self.gas_used) + } + + /// 获取已使用Gas + pub fn used(&self) -> u64 { + self.gas_used + } + + /// 获取Gas限制 + pub fn limit(&self) -> u64 { + self.gas_limit + } + + /// 重置Gas计量器 + pub fn reset(&mut self) { + self.gas_used = 0; + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_gas_consumption() { + let mut gas = GasMetering::new(1000); + + assert!(gas.consume(100).is_ok()); + assert_eq!(gas.used(), 100); + assert_eq!(gas.remaining(), 900); + } + + #[test] + fn test_gas_out_of_gas() { + let mut gas = GasMetering::new(100); + + assert!(gas.consume(50).is_ok()); + assert!(gas.consume(60).is_err()); + } + + #[test] + fn test_gas_opcode_cost() { + let mut gas = GasMetering::new(1000); + + assert!(gas.consume_opcode(Opcode::Push).is_ok()); + assert_eq!(gas.used(), 3); + + assert!(gas.consume_opcode(Opcode::Add).is_ok()); + assert_eq!(gas.used(), 8); + } + + #[test] + fn test_gas_reset() { + let mut gas = GasMetering::new(1000); + + gas.consume(500).unwrap(); + assert_eq!(gas.used(), 500); + + gas.reset(); + assert_eq!(gas.used(), 0); + } + + #[test] + fn test_gas_costs() { + assert_eq!(GasCost::get(Opcode::Push), 3); + assert_eq!(GasCost::get(Opcode::Transfer), 9000); + assert_eq!(GasCost::get(Opcode::Sha3), 30); + } +} diff --git a/nac-nvm/src/lib.rs b/nac-nvm/src/lib.rs new file mode 100644 index 0000000..7339ba2 --- /dev/null +++ b/nac-nvm/src/lib.rs @@ -0,0 +1,26 @@ +//! NAC虚拟机(NVM) +//! +//! 执行Charter智能合约的虚拟机核心 + +pub mod bytecode; +pub mod executor; +pub mod memory; +pub mod stack; +pub mod gas; + +pub use bytecode::{Opcode, Instruction, Bytecode}; +pub use executor::{Executor, ExecutionResult}; +pub use memory::Memory; +pub use stack::Stack; +pub use gas::{GasMetering, GasCost}; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_nvm_basic() { + let mut executor = Executor::new(); + assert!(executor.is_ready()); + } +} diff --git a/nac-nvm/src/memory.rs b/nac-nvm/src/memory.rs new file mode 100644 index 0000000..aee931e --- /dev/null +++ b/nac-nvm/src/memory.rs @@ -0,0 +1,113 @@ +//! 虚拟机内存管理 + +use thiserror::Error; +use std::collections::HashMap; + +#[derive(Debug, Error)] +pub enum MemoryError { + #[error("内存地址无效: {0}")] + InvalidAddress(u64), + #[error("内存不足")] + OutOfMemory, +} + +/// 虚拟机内存 +#[derive(Debug, Clone)] +pub struct Memory { + data: HashMap, + max_size: usize, +} + +impl Memory { + pub fn new() -> Self { + Memory { + data: HashMap::new(), + max_size: 1024 * 1024, // 1M slots + } + } + + pub fn with_capacity(capacity: usize) -> Self { + Memory { + data: HashMap::with_capacity(capacity), + max_size: capacity, + } + } + + /// 加载数据 + pub fn load(&self, address: u64) -> Result { + self.data.get(&address) + .copied() + .ok_or(MemoryError::InvalidAddress(address)) + } + + /// 存储数据 + pub fn store(&mut self, address: u64, value: u64) -> Result<(), MemoryError> { + if self.data.len() >= self.max_size && !self.data.contains_key(&address) { + return Err(MemoryError::OutOfMemory); + } + self.data.insert(address, value); + Ok(()) + } + + /// 检查地址是否存在 + pub fn contains(&self, address: u64) -> bool { + self.data.contains_key(&address) + } + + /// 获取已使用的内存大小 + pub fn size(&self) -> usize { + self.data.len() + } + + /// 清空内存 + pub fn clear(&mut self) { + self.data.clear(); + } +} + +impl Default for Memory { + fn default() -> Self { + Self::new() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_memory_store_load() { + let mut memory = Memory::new(); + + memory.store(0x100, 42).unwrap(); + memory.store(0x200, 100).unwrap(); + + assert_eq!(memory.load(0x100).unwrap(), 42); + assert_eq!(memory.load(0x200).unwrap(), 100); + } + + #[test] + fn test_memory_invalid_address() { + let memory = Memory::new(); + assert!(memory.load(0x999).is_err()); + } + + #[test] + fn test_memory_overwrite() { + let mut memory = Memory::new(); + + memory.store(0x100, 42).unwrap(); + memory.store(0x100, 100).unwrap(); + + assert_eq!(memory.load(0x100).unwrap(), 100); + } + + #[test] + fn test_memory_contains() { + let mut memory = Memory::new(); + memory.store(0x100, 42).unwrap(); + + assert!(memory.contains(0x100)); + assert!(!memory.contains(0x200)); + } +} diff --git a/nac-nvm/src/stack.rs b/nac-nvm/src/stack.rs new file mode 100644 index 0000000..d51159a --- /dev/null +++ b/nac-nvm/src/stack.rs @@ -0,0 +1,147 @@ +//! 虚拟机栈实现 + +use thiserror::Error; + +const MAX_STACK_SIZE: usize = 1024; + +#[derive(Debug, Error)] +pub enum StackError { + #[error("栈溢出")] + Overflow, + #[error("栈下溢")] + Underflow, +} + +/// 虚拟机栈 +#[derive(Debug, Clone)] +pub struct Stack { + data: Vec, + max_size: usize, +} + +impl Stack { + pub fn new() -> Self { + Stack { + data: Vec::new(), + max_size: MAX_STACK_SIZE, + } + } + + pub fn with_capacity(capacity: usize) -> Self { + Stack { + data: Vec::with_capacity(capacity), + max_size: capacity, + } + } + + /// 压栈 + pub fn push(&mut self, value: u64) -> Result<(), StackError> { + if self.data.len() >= self.max_size { + return Err(StackError::Overflow); + } + self.data.push(value); + Ok(()) + } + + /// 出栈 + pub fn pop(&mut self) -> Result { + self.data.pop().ok_or(StackError::Underflow) + } + + /// 查看栈顶元素 + pub fn peek(&self) -> Result { + self.data.last().copied().ok_or(StackError::Underflow) + } + + /// 复制栈顶元素 + pub fn dup(&mut self) -> Result<(), StackError> { + let value = self.peek()?; + self.push(value) + } + + /// 交换栈顶两个元素 + pub fn swap(&mut self) -> Result<(), StackError> { + if self.data.len() < 2 { + return Err(StackError::Underflow); + } + let len = self.data.len(); + self.data.swap(len - 1, len - 2); + Ok(()) + } + + /// 获取栈大小 + pub fn size(&self) -> usize { + self.data.len() + } + + /// 检查栈是否为空 + pub fn is_empty(&self) -> bool { + self.data.is_empty() + } + + /// 清空栈 + pub fn clear(&mut self) { + self.data.clear(); + } +} + +impl Default for Stack { + fn default() -> Self { + Self::new() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_stack_push_pop() { + let mut stack = Stack::new(); + assert!(stack.push(42).is_ok()); + assert!(stack.push(100).is_ok()); + + assert_eq!(stack.pop().unwrap(), 100); + assert_eq!(stack.pop().unwrap(), 42); + assert!(stack.pop().is_err()); + } + + #[test] + fn test_stack_peek() { + let mut stack = Stack::new(); + stack.push(42).unwrap(); + + assert_eq!(stack.peek().unwrap(), 42); + assert_eq!(stack.size(), 1); + } + + #[test] + fn test_stack_dup() { + let mut stack = Stack::new(); + stack.push(42).unwrap(); + stack.dup().unwrap(); + + assert_eq!(stack.size(), 2); + assert_eq!(stack.pop().unwrap(), 42); + assert_eq!(stack.pop().unwrap(), 42); + } + + #[test] + fn test_stack_swap() { + let mut stack = Stack::new(); + stack.push(1).unwrap(); + stack.push(2).unwrap(); + stack.swap().unwrap(); + + assert_eq!(stack.pop().unwrap(), 1); + assert_eq!(stack.pop().unwrap(), 2); + } + + #[test] + fn test_stack_overflow() { + let mut stack = Stack::with_capacity(2); + assert!(stack.push(1).is_ok()); + assert!(stack.push(2).is_ok()); + assert!(stack.push(3).is_err()); + } +}