news 2026/9/11 8:59:57

Linera 协议共享基础层 linera-base:贯穿 Native 与 Wasm 应用的类型与密码学基座

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linera 协议共享基础层 linera-base:贯穿 Native 与 Wasm 应用的类型与密码学基座

Linera 协议共享基础层 linera-base:贯穿 Native 与 Wasm 应用的类型与密码学基座

【免费下载链接】linera-protocolMain repository for the Linera protocol项目地址: https://gitcode.com/GitHub_Trending/li/linera-protocol

linera-base 是 Linera 协议(一个以"多链并行执行"为核心理念的分层链协议)中的基础 crate,为协议核心(编译为原生代码运行)与链上应用(编译为 Wasm 运行)提供一套通用的类型定义与库函数。阅读本文后,你将掌握 linera-base 的模块划分、核心标识符与密码学原语的实现原理、双序列化格式设计,以及它是如何通过条件编译与 WIT 桥接同时服务于原生节点和 Wasm 智能合约的。

linera-base 在 Linera 生态中的定位

linera-base/README.md 开宗明义地定义了该模块的职责:

This module provides a common set of types and library functions that are shared between the Linera protocol (compiled from Rust to native code) and Linera applications (compiled from Rust to Wasm).

这句话点明了 linera-base 的核心价值:一份代码、两个运行环境。Linera 协议节点(validator、客户端、存储层)以原生二进制运行,而链上应用(如 examples/ 目录下的 counter、fungible、amm 等示例)则被编译成 Wasm 字节码部署到链上。二者必须对"链 ID、账户、余额、块高、时间戳、签名、哈希"等概念持有完全一致的语义与字节表示,否则跨环境的数据交换(如签名验证、消息投递、GraphQL 查询)就会失败。

因此,linera-base 承担的角色是"协议内共享内核",它被 Linera 生态中几乎所有其他 crate 依赖,包括:

  • linera-chain:链数据结构(块、收件箱、出件箱),大量使用ChainIdBlockHeightCryptoHash
  • linera-core:节点与客户端核心逻辑,依赖AccountOwner、签名验证等;
  • linera-sdk:应用开发 SDK,应用端看到的所有基础类型(如ApplicationIdAmountChainId)都来自 linera-base;
  • linera-execution:执行引擎,使用ResourcesVmRuntime等执行原语。

该 crate 的 Cargo 描述与 README 一致:linera-base/Cargo.toml 中写着 "Base definitions, including cryptography, used by the Linera protocol."

模块全景:从模块列表看 linera-base 的能力边界

linera-base/src/lib.rs 是 crate 的入口,#![deny(missing_docs)]强制所有公开项必须带文档注释,保证了该库的可维护性。通过模块声明可以完整看到它的能力版图:

模块职责
crypto密码学原语:Keccak256 哈希、Ed25519 / secp256k1 / EVM 签名、密钥对、BCS 签名基础设施
identifiers核心标识符:ChainIdAccountOwnerAccountApplicationIdModuleIdBlobIdStreamId
data_types业务数据类型:AmountBlockHeightRoundTimestampTimeDeltaResourcesCursorSendMessageRequest
hashedHashed<T>包装类型:缓存"值 + 哈希",避免重复计算
abi应用 ABI(接口)描述相关类型
ownership链所有权模型(ChainOwnership
http/command/port/panic_hook节点运行辅助:HTTP 客户端、CLI 命令解析、端口选择、panic 钩子、信号处理(listen_for_shutdown_signals)等
task/task_processor任务调度(Wasm 目标下不可用,见条件编译)
vm虚拟机运行时枚举(VmRuntime,区分 Wasm / EVM)
time/util/limited_writer时间抽象、工具函数、带限制的写入器

其中prometheus_util仅在启用metricsfeature 时编译。值得注意的是 lib.rs 顶部有一处强制约束:

const _: () = assert!( usize::BITS >= u32::BITS, "linera-base requires a target with usize of at least 32 bits", );

这是编译期断言:协议代码中大量存在u32usize之间的隐式转换(长度、计数等),因此从编译期就排除了 16 位目标平台。

密码学基座:哈希、密钥与签名的三种形态

crypto 是 linera-base 最重要的子模块之一,包含hash.rsed25519.rssecp256k1/signer.rs等文件。

CryptoHash:Keccak256 内容寻址

crypto/hash.rs 定义了全协议最核心的哈希类型CryptoHash,它包装alloy-primitives::B256(32 字节),底层是Keccak256(以太坊同款哈希,便于与 EVM 生态互通):

pub struct CryptoHash(B256); impl CryptoHash { /// Computes a hash. pub fn new<'de, T: BcsHashable<'de>>(value: &T) -> Self { let mut hasher = Keccak256Ext(Keccak256::new()); value.write(&mut hasher); CryptoHash(hasher.0.finalize()) } }

关键的实现细节在于哈希的输入:value.write(&mut hasher)写入的不仅是 BCS 序列化字节,还以类型名(serde_name提取的 seed)作为前缀(见 crypto/mod.rs):

impl<'de, T, Hasher> Hashable<Hasher> for T { fn write(&self, hasher: &mut Hasher) { let name = <Self as HasTypeName>::type_name(); write!(hasher, "{name}::").expect("Hasher should not fail"); bcs::serialize_into(hasher, &self).expect("Message serialization should not fail"); } }

也就是说,哈希值 =Keccak256(类型名 + "::" + BCS 字节)。这带来一个重要性质:相同字节内容但不同类型的数据不会碰撞出相同的哈希,从而避免了类型混淆攻击(type confusion)。CryptoHash还提供了make_evm_compatible(),将后 12 字节清零,用于 EVM 兼容场景。

三种密钥体系

crypto/mod.rs 通过枚举统一了三种密钥/签名方案:

  • Ed25519:适用于账户所有者(chain owner),对应AccountSecretKey::Ed25519
  • secp256k1:也适用于账户所有者,对应AccountSecretKey::Secp256k1
  • EVM secp256k1:兼容以太坊地址体系,对应AccountSecretKey::EvmSecp256k1,签名中直接携带 20 字节的 EVM 地址。

同时定义了协议的别名体系:验证者(validator)固定使用 secp256k1(ValidatorPublicKey等类型别名),而链所有者则可以在上述三种方案中选择。AccountSecretKey::sign()AccountSignature::verify()提供了统一的签名/验签入口,AccountSignature::owner()还能直接从签名恢复出对应的AccountOwner。签名与公钥都提供to_bytes()/from_slice(),统一走 BCS 编码,且具备 Display(十六进制字符串)与 FromStr 往返能力,单元测试roundtrip_account_pk_bytes_reprroundtrip_signature_bytes_repr(crypto/mod.rs)验证了这几种方案的字节往返一致性。

标识符体系:账户、链、应用与 Blob

identifiers.rs 是 1500 余行的标识符大本营,定义了协议中一切"地址"类概念。

AccountOwner:三种所有者形态

AccountOwner枚举定义了账户所有者的三种形态(identifiers.rs):

pub enum AccountOwner { /// Short addresses reserved for the protocol. Reserved(u8), /// 32-byte account address. Address32(CryptoHash), /// 20-byte account EVM-compatible address. Address20([u8; 20]), }
  • Reserved(0)AccountOwner::CHAIN,表示"链共享账户"(链上余额的共同所有者);
  • Address32CryptoHash(如公钥的哈希)派生;
  • Address20直接承载 EVM 地址,是 Linera 与 EVM 世界互操作的桥梁。

AccountOwner有很实用的From<[u8; 32]>转换:若前 12 字节全零,则取后 20 字节作为Address20,否则作为Address32(identifiers.rs)。Account结构则把chain_idowner组合起来,其Display格式为owner@chain-idFromStr也支持只写链 ID 表示链共享账户(identifiers.rs)。

ChainId:链的唯一标识

ChainId(pub CryptoHash)是链的唯一标识,文档注释明确说明:它当前由ChainDescription的哈希计算得到。由于链可以动态创建(微链模式是 Linera 的核心设计),ChainId天然是内容寻址的。

ApplicationId 与 ModuleId:应用与模块的标识

  • ApplicationId<A>包装application_description_hash: CryptoHash(identifiers.rs),即应用描述(ApplicationDescription)的哈希;
  • ModuleId<Abi, Parameters, InstantiationArgument>则包含四个字段:合约字节码 blob 哈希、服务字节码 blob 哈希、虚拟机运行时(VmRuntime),以及可选的Formats描述 blob 哈希(identifiers.rs)——后者用于承载应用的 BCS 编码格式描述,与合约/服务 blob 一起发布;
  • GenericApplicationId区分系统应用(System)与用户应用(User(ApplicationId))。

ApplicationId还能转换为AccountOwner:EVM 应用取描述哈希的前 20 字节作为Address20,非 EVM 应用直接作为Address32(identifiers.rs),这支撑了"应用本身也可以成为账户"的模型。

BlobType 与 BlobId:内容寻址的字节块

Blob 是 Linera 内容寻址存储的基本单元。BlobType枚举(identifiers.rs)区分了九种 blob 类型:

变体含义
Data通用数据 blob
ContractBytecode/ServiceBytecode压缩的合约 / 服务 Wasm 字节码
EvmBytecode压缩的 EVM 字节码
ApplicationDescription应用描述
Committee验证者委员会
ChainDescription链描述
ApplicationFormats应用 BCS 格式描述
CheckpointExecutionState检查点执行状态转储的分块(用于节点引导,免于重放链历史)

BlobId { blob_type, hash }是 blob 的完整标识,其字符串形式为BlobType:hash(如Data:0x...),同样支持 Display / FromStr 往返;在人类可读的序列化格式中它输出为字符串,在二进制 BCS 格式中输出为结构体(identifiers.rs)。

数据原语:余额、块高、轮次、时间与资源

data_types.rs 定义了链上业务逻辑必须依赖的数值与时间类型,它们都被设计为newtype 包装,在类型层面杜绝"余额当块高用"这类错误。

Amount:定点数余额

Amount(u128)是"非负代币数量",内部以定点小数表示,DECIMAL_PLACES指定小数点后的位数,Amount::ONE是一个完整代币。它的序列化是"双格式"的:人类可读格式(JSON/GraphQL)输出十进制字符串,二进制格式(BCS)输出裸u128(data_types.rs)。Amount支持与U256(alloy 类型)互相转换——U256 -> Amount可能失败(超过 128 位),因此使用TryFrom

AmountU128BlockHeightTimeDelta通过宏impl_wrapped_number!统一获得一整套checked / saturating 算术try_addtry_subsaturating_mulmidpointabs_diff等,溢出时返回ArithmeticErrorOverflow/Underflow),而不是 panic(data_types.rs)。

BlockHeight、Round 与 Cursor:链上的定位系统

  • BlockHeight(u64)标识链中块的高度;
  • Round枚举标识共识协议中"第几轮尝试",包含四种形态:Fast(初始快速轮)、MultiLeader(u32)(多领导者轮)、SingleLeader(u32)(单领导者轮)、Validator(u32)(验证者轮流当领导者的轮次)(data_types.rs),反映了 Linera 分层共识的多阶段设计;
  • Cursor { height, index }定位链出站消息流中的逻辑位置:产出消息的块高 + 块内交易索引(data_types.rs)。

Timestamp 与 TimeDelta:微秒精度的时间

Timestamp(u64)自 Unix 纪元起的微秒数表示,提供now()delta_sincesaturating_add/saturating_sub等方法;其Display输出可读的YYYY-MM-DD HH:MM:SS(UTC)格式,FromStr支持%Y-%m-%dT%H:%M:%S%Y-%m-%d %H:%M:%S两种解析格式(data_types.rs)。TimeDelta(u64)是微秒计数的时长,提供from_micros/from_millis/from_secs构造。

Resources:应用的执行预算

Resources结构是交易/应用调用执行期间可消耗的资源清单(data_types.rs),字段覆盖两个执行后端:

  • 燃料类wasm_fuel(Wasm 执行燃料)、evm_fuel(EVM 执行燃料);
  • I/O 类read_operations/write_operationsbytes_to_read/bytes_to_writeblobs_to_read/blobs_to_publishblob_bytes_to_read/blob_bytes_to_publish
  • 通信类messages(消息条数)、message_sizeservice_as_oracle_queries(服务作为预言机的查询次数)、http_requests(HTTP 请求次数)。

SendMessageRequest<Message>则包装一次跨链消息投递请求:目的地链、是否认证、是否被跟踪、转发的资源授权(grant)与消息体(data_types.rs)。代码注释中还留下了 TODO(#1531 相关),说明消息大小统计粒度等仍待精细化。

此外,data_types.rs 还定义了NonCanonicalBTreeMap/CanonicalBTreeSet/CanonicalBTreeMap/NonCanonicalBTreeSet一组针对BCS 规范序编码的优化容器:BCS 对 map 的规范编码会在每次序列化时按序列化后的键字节重新排序(O(n log n)),而 BTreeMap 本身已经有序,因此NonCanonicalBTreeMap值位置(如RegisterView<Value>MapView<_, Value>)按普通序列对编码以省去重复排序;而键位置MapView<Key, _>)必须保持规范序,所以使用CanonicalBTreeSet(以T -> ()的 map 形式触发 BCS 规范排序)。

哈希缓存:Hashed<T>

hashed.rs 定义了Hashed<T>包装类型,将值与预先计算的哈希打包在一起:

pub struct Hashed<T> { value: T, hash: CryptoHash, }
  • Hashed::new(value):计算并缓存哈希;
  • Hashed::with_hash(value, hash):使用预先给定的哈希(调用方必须保证该哈希是 value 的规范哈希),避免重复计算,这在区块/证书的传播与验证场景中能显著减少哈希计算开销;
  • PartialEq只比较hash(),即两个Hashed<T>只要哈希相同就相等。

其单元测试with_hash_stores_provided_hash验证了with_hash会原样存储给定的哈希(hashed.rs)。Hashed同时实现了 async-graphql 的输出类型,可无缝暴露到 GraphQL 查询中。

双序列化设计:JSON/GraphQL 可读、BCS 紧凑

linera-base 中几乎所有核心类型(CryptoHashBlobIdAmountU128StreamIdAccountChainId等)都实现了"双格式序列化":

  • 人类可读格式(JSON、GraphQL、CLI 输出):序列化为十六进制 / 十进制字符串。例如CryptoHash序列化为 64 位十六进制字符串,反序列化时校验长度(错误为IncorrectHashSize,见 crypto/hash.rs);
  • 二进制格式(BCS):序列化为紧凑的固定长度字节。CryptoHash在 BCS 下是裸 32 字节,Amount是裸u128BlobId是结构体。

实现模式统一为serializer.is_human_readable()分支判断(例如 identifiers.rs 中BlobId的实现)。这种设计让节点之间走紧凑高效的 BCS 线格式,同时让 CLI、GraphQL API 与日志对人友好——linera-base/src/graphql.rs 中的doc_scalar!宏即为这些标量提供 GraphQL Schema 文档。

一库双端:Wasm 与原生环境的条件编译

回到 README 的主题,linera-base 是如何做到"一份代码服务于原生协议与 Wasm 应用"的?答案是系统的条件编译(lib.rs):

  • #[cfg(not(target_arch = "wasm32"))]command(CLI 解析)、panic_hookport(端口选择)以及listen_for_shutdown_signals(Unix 下监听 SIGINT/SIGTERM/SIGHUP,Windows 下监听 Ctrl+C,见 lib.rs)仅在原生环境编译;
  • #[cfg(not(chain))]task/task_processor任务调度模块在"链内(Wasm 应用)"目标下被排除;
  • #[cfg(with_metrics)]prometheus_utilinit_metrics()(提前注册所有指标,避免冷路径导致面板空白)仅在启用 metrics feature 时编译。

同时,Cargo.toml 中[target.'cfg(target_arch = "wasm32")'.dependencies][target.'cfg(not(target_arch = "wasm32"))'.dependencies]分别引入不同的依赖:Wasm 目标使用web-timetracing-webruzstd等轻量替代;原生目标则引入tokio(含signalfsprocess)、prometheuszstd等。webfeature 还引入了wasm-bindgengetrandom/js等,使类型可以通过tsify直接导出为 TypeScript 类型(如export type ApplicationId = string;,见 identifiers.rs),支撑 web/ 目录下的浏览器端开发。

跨 Wasm 边界的类型桥接:WIT 接口

让同一组类型在原生协议与 Wasm 应用间传递的另一个关键机制是WIT(WebAssembly Interface Types)桥接:linera-base 中的核心类型(CryptoHashChainIdAccountOwnerAmountBlockHeightTimestampApplicationId等)都实现了 linera-witty 提供的WitLoad/WitStore/WitTypetrait。

CryptoHash为例(crypto/hash.rs):它在 WIT 世界中表示为record crypto-hash { part1: u64, part2: u64, part3: u64, part4: u64 },即把 32 字节哈希拆成四个u64作为线性内存布局,并提供load/lift_from/store/lower四个方向的转换。这样,应用 Wasm 与节点原生代码之间传递哈希、账户、余额等数据时,可以复用同一套类型定义,且编译期即可验证内存布局的一致。

在应用中的落地:从示例看 linera-base 的日常使用

linera-base 的类型在 examples/ 中的应用中随处可见。以 examples/counter/(经典计数器应用)为例,其应用代码引入的ApplicationApplicationCallService等 SDK 抽象底层,以及CounterAbi等 ABI 类型,最终都依赖 linera-base 提供的AmountChainIdApplicationIdModuleId等基础类型。再如 examples/fungible/(同质化代币)直接在链上逻辑中使用AccountOwnerAmount管理账户余额,examples/fungible/src/lib.rs 中的转账逻辑正是基于 linera-base 定义的账户模型。

读者若想深入 linera-base 的细节,可以:

  • 阅读 linera-base/README.md(模块定位概述);
  • 浏览 linera-base/src/lib.rs(模块组织与条件编译全貌);
  • 研读 linera-base/src/crypto/mod.rs、linera-base/src/crypto/hash.rs(密码学实现);
  • 查阅 linera-base/src/identifiers.rs 与 linera-base/src/data_types.rs(标识符与数据原语);
  • 在 linera-base/tests/command_tests.rs 与 linera-base/src/unit_tests.rs 中查看测试示例。

如需参与贡献,请参照 CONTRIBUTING 指南;该 crate 以 Apache 2.0 license 发布。

【免费下载链接】linera-protocolMain repository for the Linera protocol项目地址: https://gitcode.com/GitHub_Trending/li/linera-protocol

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/11 8:53:31

YOLOv8多GPU训练:DP与DDP模式深度对比与优化

1. 项目概述在计算机视觉领域&#xff0c;YOLOv8作为当前最先进的实时目标检测算法之一&#xff0c;其训练效率直接影响模型迭代速度。多GPU训练是提升训练效率的核心手段&#xff0c;但实际应用中存在Data Parallel(DP)和Distributed Data Parallel(DDP)两种主流方案的选择困惑…

作者头像 李华
网站建设 2026/9/11 8:52:11

中小团队AI-native落地指南:从智能体到RAG的避坑实践

这几年“AI-native”这个词被炒得很热&#xff0c;但我在实际接触了十几个声称AI-native的中小型项目之后发现&#xff0c;绝大多数团队把AI-native理解成了“在系统里接入AI”&#xff0c;而不是“让AI成为系统的原生组成部分”。这个差别直接决定了项目是在进化还是在换壳。今…

作者头像 李华
网站建设 2026/9/11 8:48:54

ARM optimized-routines源码审计:从汇编优化到系统级基础库替换

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/11 8:47:10

ARMxy开发板与Node-RED、FUXA构建工业物联网一体化方案

1. 为什么需要一体化设备解决方案在工业自动化和物联网领域&#xff0c;我们经常面临一个典型困境&#xff1a;数据采集、逻辑控制和可视化展示往往需要部署多套独立系统。这不仅增加了硬件成本&#xff0c;还带来了复杂的系统集成问题。想象一下&#xff0c;一个简单的温湿度监…

作者头像 李华