Component Name
2026/9/18 9:29:55 网站建设 项目流程

Component Name

【免费下载链接】aptos-coreAptos is a layer 1 blockchain built to support the widespread use of blockchain through better technology and user experience.项目地址: https://gitcode.com/GitHub_Trending/ap/aptos-core

[Summary line: Start with one sentence about this component.]

Overview

  • Describe the purpose of this component and how the code in this directory works.
  • Describe the interaction of the code in this directory with the other components.
  • Describe the security model and assumptions about the crates in this directory.

Implementation Details

  • Describe how the component is modeled. For example, why is the code organized the way it is?
  • Other relevant implementation details.
## 二进制、参数与 crate 命名 日常使用的工具(rustc、cargo、git、rg 等)均以连字符 `-` 作为二进制名与参数的单词分隔符;GNU 软件手册规定长选项应为"`--` 后跟由字母数字字符和连字符组成的名称"。因此: - 二进制名与命令行参数的分隔符统一使用连字符 `-`; - crate 名同样推荐使用连字符作为分隔符,例如 `x25519-dalek`。 这一约定与 [rustfmt.toml](https://link.gitcode.com/i/1b7a0ed20b578df5fc8289348f3b5e61) 中导入分组、`aptos-cargo-cli` 中 `cargo xclippy --all-targets` 这类命令的可读性保持一致。 ## 代码建议:面向统一代码库的最佳实践 以下小节是可逐步用 Clippy 强制执行的实践建议,随时间演进。 ### 属性(Attributes):正确处理死代码

// For code that is intended for production usage in the future #[allow(dead_code)] // For code that is only intended for testing and // has no intended production use #[cfg(test)]

`#[allow(dead_code)]` 用于未来计划投入生产使用的代码;`#[cfg(test)]` 用于仅服务于测试、无生产用途的代码。 ### 避免 Deref 多态 不要滥用 `Deref` trait 在结构体之间模拟继承并复用方法(可参考 Rust 反模式资料中的 deref 条目)。`Deref` 只应实现真正的智能指针语义。 ### 注释 推荐统一使用 `//` 与 `///` 行注释,而非块注释 `/* ... */`,以保证一致性并便于 grep 检索。 ### 并发类型(Concurrent types) `CHashMap`、`AtomicUsize` 等并发类型通过 `fn foo_mut(&self, ...)` 这类"对 self 的不可变借用 + 内部可变性"来支持并发访问。良好实践(如示例所示)应避免对外暴露同步原语(如 `Mutex`、`RwLock`),并清晰记录方法语义与不变量。 **何时用 channel,何时用并发类型?** 高层经验法则: - **Channel**:适用于所有权转移、类型解耦与粗粒度消息——转移数据所有权、分发工作单元、通信异步结果;还能帮助打破循环依赖(例如 `struct Foo` 持有 `Arc<Bar>` 且 `struct Bar` 持有 `Arc<Foo>` 导致的复杂初始化); - **并发类型**(如 `CHashMap`,或基于 `Mutex`、`RwLock` 构建内部可变性的结构体):更适合缓存(cache)与状态(state)场景。 ### 错误处理 遵循 Rust 官方书籍的指导:错误分为**可恢复**与**不可恢复**两类。可恢复错误用 `Result` 处理;不可恢复错误的建议如下: - `unwrap()`:仅应出现在测试代码中;其余场景优先使用 `expect()`。唯一例外是错误消息为动态生成时,使用 `.unwrap_or_else(|| panic!("error: {}", foo))`; - `expect()`:在系统不变量(invariant)应当成立时使用;`expect()` 优于 `unwrap()`,且多数情况下应包含详细的失败消息; - `assert!()`:该宏在 debug 与 release 构建中都保留,应用于保护系统必要的不变量; - `unreachable!()`:用于本不应到达的代码路径(违反不变量),可在适当位置使用。 在生产(非测试)代码中,除锁管理外,所有不可恢复错误都应被清晰记录,说明为何该事件不可恢复——例如系统进入何种坏状态、为何崩溃/重启比在运行中自行修复更有效、操作者需要采取哪些步骤来解决问题。 这一准则也反映在仓库配置中:[clippy.toml](https://link.gitcode.com/i/c58b3f8f6c676609551850457679ee85) 设置 `allow-unwrap-in-tests = true`,明确允许测试中 unwrap,与"unwrap 仅用于测试"的规范互相印证。 ### 泛型(Generics) 泛型支持类似 `trait` 方法动态行为的**静态分发**。随着泛型类型参数数量增加,类型/方法的使用难度也会上升(考虑所需的 trait 约束组合、相关类型上重复的约束等)。为避免这种复杂度,代码库通常避免使用大量泛型参数——实践表明,将大量泛型对象转换为带动态分发的 trait 对象往往能简化代码。 ### Getter / Setter getter 命名遵循 Rust 惯例(`xxx()` 形式),setter 遵循 `set_xxx` 形式。对于 C 风格的 `struct`(复合的、无内部不变量的被动数据结构),应避免添加 getter/setter——它们只会增加复杂度和代码行数,却不改善开发体验。 ```rust struct Foo { size: usize, key_to_value: HashMap<u32, u32> } impl Foo { /// Simple getter follows xxx pattern fn size(&self) -> usize { self.size } /// Setter follows set_xxx pattern fn set_foo(&mut self, size: usize){ self.size = size; } /// Complex getter follows get_xxx pattern fn get_value(&self, key: u32) -> Option<&u32> { self.key_to_value.get(&key) } }

注意:简单字段访问使用size()模式,而涉及计算的复杂访问使用get_value()模式。

整数算术:强制使用 checked 运算

每个整数运算(+-/*等)都隐含边界情况(例如u64::MAX + 1溢出、0u64 - 1下溢、除零等),因此代码库使用checked 算术而非直接使用数学符号,这迫使开发者显式思考并处理边界情况。各类函数简明指南:

  • checked_:需将溢出/下溢作为特殊边界情况处理时使用。溢出或下溢发生时返回None,否则返回Some(operation_result)
  • overflowing_:希望溢出结果可能回绕时使用(例如u64::MAX.overflow_add(10) == (9, true))。返回回绕后的结果以及是否发生溢出的标志;
  • wrapping_:与 overflowing 类似,但直接返回结果。当你确定要用回绕处理上下溢时使用;
  • saturating_:溢出时结果保持在类型边界内(例如u64::MAX.saturating_add(1) == u64::MAX)。

日志(Logging)

当前使用 log crate 记录日志,各级别语义如下:

  • error!:最高紧急级别。发生了意外错误(例如 RPC 重试超过最大次数、无法写入本地存储);
  • warn!:帮助管理员了解被自动处理的问题(例如重试失败的网络连接、多次收到相同消息);
  • info!:适合"一次性"事件(如启动/关闭时记录一次状态)或不频繁的周期性事件——例如每天变更 validator 集合;
  • debug!:可能频繁出现(潜在每秒多于一条),生产环境通常不开启;
  • trace!:通常仅用于函数入口/出口。

测试

单元测试遵循 Rust 官方测试组织指南。理想情况下所有代码都应有单元测试;单元测试与被测代码放在同一文件、独立模块中:

struct Foo { } impl Foo { pub fn magic_number() -> u8 { 42 } } #[cfg(test)] mod tests { #[test] fn verify_magic_number() { assert_eq!(Foo::magic_number(), 42); } }

基于属性的测试(Property-based tests):Move 使用 Rust 的proptest框架编写。属性测试随机生成测试用例,并断言代码在随机输入下始终满足某些属性(不变量)。Move 中实测的属性示例:

  • 每个序列化/反序列化配对都用随机输入验证正确性——任何互为逆函数的函数对都可这样测试;
  • 通过 VM 执行常见交易的结果使用随机生成场景测试,并用Oracle(预言机)验证。

测试的条件编译(Conditional compilation of tests)

Move 会条件编译仅与测试相关、但本身不是测试的代码(如 proptest 策略、特定 trait 的实现与派生如Clone、辅助函数等)。由于 Cargo 目前无法在测试/benchmark 中自动激活 features,代码库依赖两个条件:

  • test flag:由同 crate 内依赖该测试代码的测试代码激活;
  • fuzzing自定义 feature:用于在下游 crate 中启用 fuzzing 与测试相关代码。注意:必须显式传给cargo xtestcargo xbench;除非该 crate 仅用于测试,否则绝不要在[dependencies]中使用它。

对生产 crate(即产生对外发布产物的 crate)的推荐做法,以在foo_crate中定义测试专用辅助函数foo为例:

  1. foo_crate/Cargo.toml中定义非默认的fuzzingflag:
[features] default = [] fuzzing = []
  1. testflag(供同 crate 调用者)与"fuzzing"自定义 feature(供 crate 外调用者)同时注解测试辅助函数:
#[cfg(any(test, feature = "fuzzing"))] fn foo() { ... }
  1. (可选)用cfg_attr让测试专用 trait 派生成为条件性的:
#[cfg_attr(any(test, feature = "testing"), derive(FooTrait))] #[derive(Debug, Display, ...)] // inconditional derivations struct Foo { ... }
  1. (可选)为调用含测试专用成员 crate 的上游 crate 设置 feature 传递性。假设bar_crate通过其测试辅助代码调用foo_crate中的测试专用foo
[features] default = [] fuzzing = ["foo_crate/fuzzing"]

对纯测试 crate(不产生发布产物,仅包含测试、benchmark 或验证发布产物正确性/性能的代码,在x.toml[workspace.test-only]下列出):无需上述设置,可直接启用生产 crate 的fuzzingfeature:

[dependencies] foo_crate = { path = "...", features = ["fuzzing"] }

【免费下载链接】aptos-coreAptos is a layer 1 blockchain built to support the widespread use of blockchain through better technology and user experience.项目地址: https://gitcode.com/GitHub_Trending/ap/aptos-core

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询