Skip to content

losxhve/midnight-compact-stdlib

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 

Repository files navigation

Compact 标准库实用指南

Bounty #293 — 对 Compact Standard Library 中约 30 个导出的全面介绍

语言版本: Compact 0.23+ | 编译器: 0.31.0 | 运行时: 0.16.0


目录

  1. 概述
  2. 通用类型:Maybe 与 Either
  3. Merkle 树相关
  4. 椭圆曲线
  5. 内核类型:ContractAddress 与 UserAddress
  6. 加密和哈希
  7. 铸币/代币操作
  8. Coin/Box 操作
  9. 余额与区块时间
  10. 板载注册

概述

Compact Standard Library (CompactStandardLibrary) 是 Midnight 区块链智能合约语言 Compact 的内置标准库。在使用 Compact 编写合约时,通过 import CompactStandardLibrary; 即可访问所有导出,无需额外安装依赖。

标准库提供了约 30 个导出,涵盖代数数据类型(MaybeEither)、Merkle 证明验证、椭圆曲线运算、哈希与承诺原语、代币铸币与转账、以及区块时间函数等核心功能。本文档按类别逐一介绍每个导出,并提供可直接参考的 Compact 代码示例。

所有示例代码文件位于 contracts/ 目录下。


1. 通用类型:Maybe 与 Either

Maybe<T>Either<A, B> 是 Compact 中最基本的代数数据类型,广泛用于表示可选值和二选一的场景。

Maybe<T> (struct)

封装一个可能存在或不存在的值。isSometruevalue 有效,否则 value 应视为 default<T>

struct Maybe<T> {
  isSome: Boolean;
  value: T;
}

some<T> (circuit) / none<T> (circuit)

构造 Maybe<T> 的两个工厂函数。

circuit some<T>(value: T): Maybe<T>;
circuit none<T>(): Maybe<T>;

示例: 根据条件选择性地返回值。

export circuit demoMaybe(value: Uint<64>): Maybe<Uint<64>> {
    if value > 0 {
        return some(value);
    } else {
        return none<Uint<64>>();
    }
}

Either<A, B> (struct)

不相交并集(disjoint union),表示要么是类型 A 的值,要么是类型 B 的值。

struct Either<A, B> {
  isLeft: Boolean;
  left: A;
  right: B;
}

left<A, B> (circuit) / right<A, B> (circuit)

构造 Either<A, B> 的两个工厂函数。

circuit left<A, B>(value: A): Either<A, B>;
circuit right<A, B>(value: B): Either<A, B>;

示例: 在合约地址和用户地址间选择。

export circuit demoEither(isContract: Boolean): Either<ContractAddress, UserAddress> {
    if isContract {
        return left<ContractAddress, UserAddress>(kernel.self());
    } else {
        return right<ContractAddress, UserAddress>(kernel.selfUserAddress());
    }
}

完整示例文件: contracts/generic-types.compact


2. Merkle 树相关

Compact 内建对 Merkle 树路径验证的支持,适用于零知识证明中证明某个叶子属于某棵树而不泄露具体位置。

MerkleTreeDigest (struct)

Merkle 树的根哈希值,由单个 Field 表示。

struct MerkleTreeDigest { field: Field; }

MerkleTreePathEntry (struct)

Merkle 路径中的一个条目,包含兄弟节点的哈希和方向指示。

struct MerkleTreePathEntry {
  sibling: MerkleTreeDigest;
  goesLeft: Boolean;
}

MerkleTreePath<n, T> (struct)

深度为 n 的 Merkle 树路径,指向类型为 T 的叶子。可以通过见证(witness)从编译器输出构造。

struct MerkleTreePath<#n, T> {
  leaf: T;
  path: Vector<n, MerkleTreePathEntry>;
}

merkleTreePathRoot<n, T> (circuit)

MerkleTreePath 推导出 Merkle 树根,用于验证叶子是否属于某棵树。

circuit merkleTreePathRoot<#n, T>(path: MerkleTreePath<n, T>): MerkleTreeDigest;

merkleTreePathRootNoLeafHash<n> (circuit)

merkleTreePathRoot 的变体,假设叶子已在外部哈希过。

circuit merkleTreePathRootNoLeafHash<#n>(path: MerkleTreePath<n, Bytes<32>>): MerkleTreeDigest;

示例: 验证 Merkle 证明。

export circuit verifyMerkleProof(
    path: MerkleTreePath<8, Bytes<32>>,
    expectedRoot: MerkleTreeDigest
): Boolean {
    const computedRoot = merkleTreePathRoot(path);
    return computedRoot.field == expectedRoot.field;
}

完整示例文件: contracts/merkle.compact


3. 椭圆曲线

Compact 提供对底层证明系统内嵌椭圆曲线的原生支持,用于密码学运算。

NativePoint (struct)

仿射坐标下的椭圆曲线点。

struct NativePoint { x: Field; y: Field; }

ecAdd (circuit)

椭圆曲线加法(两个 NativePoint 相加)。

circuit ecAdd(a: NativePoint, b: NativePoint): NativePoint;

ecMul (circuit)

椭圆曲线标量乘法(NativePoint 乘以标量 Field)。

circuit ecMul(a: NativePoint, b: Field): NativePoint;

ecMulGenerator (circuit)

主生成元与标量的乘法。

circuit ecMulGenerator(b: Field): NativePoint;

hashToCurve<T> (circuit)

将任意类型映射到 NativePoint。输出相对于群基点和任何其他输出具有未知离散对数。

circuit hashToCurve<T>(value: T): NativePoint;

完整示例文件: contracts/elliptic-curve.compact


4. 内核类型:ContractAddress 与 UserAddress

ContractAddress (struct)

合约的地址,封装在 Bytes<32> 中。通过 kernel.self() 获取当前合约地址。

struct ContractAddress { bytes: Bytes<32>; }

UserAddress (struct)

用户的公钥地址,封装在 Bytes<32> 中。通过 kernel.selfUserAddress() 获取当前调用者的用户地址。

struct UserAddress { bytes: Bytes<32>; }

示例:

export circuit demoContractIdentity(): ContractAddress {
    return kernel.self();
}

export circuit demoUserIdentity(): UserAddress {
    return kernel.selfUserAddress();
}

完整示例文件: contracts/address-types.compact


5. 加密和哈希

Compact 提供两套哈希/承诺原语:瞬态(电路高效,不保证跨版本持久)和持久(基于 SHA-256,保证一致性)。

transientHash<T> (circuit)

电路高效的哈希压缩函数,将任意值映射到 Field。适用于一致性检查,不应用于导出状态数据。

circuit transientHash<T>(value: T): Field;

transientCommit<T> (circuit)

电路高效的承诺函数。与 transientHash 不同,此函数在随机数足够随机的情况下足以保护输入不被泄露。

circuit transientCommit<T>(value: T, rand: Field): Field;

persistentHash<T> (circuit)

基于 SHA-256 的持久哈希函数,返回 Bytes<32>。保证跨版本持久,应 用于派生状态数据。

circuit persistentHash<T>(value: T): Bytes<32>;

persistentCommit<T> (circuit)

基于 SHA-256 的持久承诺函数。

circuit persistentCommit<T>(value: T, rand: Bytes<32>): Bytes<32>;

degradeToTransient (circuit)

persistentHashpersistentCommitBytes<32> 输出降级为 Field,以便在瞬态计算中使用。

circuit degradeToTransient(x: Bytes<32>): Field;

upgradeFromTransient (circuit)

Field 升级为 Bytes<32>,以便在持久计算中使用。

circuit upgradeFromTransient(x: Field): Bytes<32>;

完整示例文件: contracts/crypto-hash.compact


6. 铸币/代币操作

nativeToken (circuit)

返回原生代币的 token type(颜色)。

circuit nativeToken(): Bytes<32>;

tokenType (circuit)

将域分隔符转换为全局命名空间的代币类型。一个合约无法为另一个合约的域分隔符铸币。

circuit tokenType(domainSep: Bytes<32>, contract: ContractAddress): Bytes<32>;

mintUnshieldedToken (circuit)

铸造非屏蔽代币并发送给接收方,返回 coin color。需要公开披露域分隔符和金额。

export circuit mintUnshieldedToken(
  domainSep: Bytes<32>,
  value: Uint<64>,
  recipient: Either<ContractAddress, UserAddress>
): Bytes<32>;

mintShieldedToken (circuit)

铸造屏蔽代币并发送给接收方,返回 ShieldedCoinInfo。需要唯一的 nonce。

circuit mintShieldedToken(
  domainSep: Bytes<32>,
  value: Uint<64>,
  nonce: Bytes<32>,
  recipient: Either<ZswapCoinPublicKey, ContractAddress>
): ShieldedCoinInfo;

完整示例文件: contracts/minting.compact


7. Coin/Box 操作

数据结构

  • ShieldedCoinInfo:新创建的屏蔽代币描述 { nonce, color, value }
  • QualifiedShieldedCoinInfo:账本中已存在的可花费屏蔽代币 { nonce, color, value, mtIndex }
  • ShieldedSendResultsendShielded 的输出 { change, sent }
  • ZswapCoinPublicKey:用户接收屏蔽代币的公钥 { bytes }

发送与接收(屏蔽代币)

receiveShielded 接收一个屏蔽代币并添加验证条件,确保该代币作为本次交易的输出存在。sendShielded 从账本中已有的屏蔽代币发送指定金额,并返回找零(ShieldedSendResult)。sendImmediateShielded 用于发送在同一交易中刚创建的代币,无需账本索引。

函数 用途
receiveShielded 接收屏蔽代币,添加验证条件
sendShielded 从账本代币发送(返回找零)
sendImmediateShielded 从交易内代币发送

发送与接收(非屏蔽代币)

非屏蔽代币(unshielded token)的交易信息公开可见。sendUnshielded 发送指定金额的代币到合约或用户地址,不返回找零,因此需要精确匹配金额。receiveUnshielded 在当前合约中接收指定金额和类型的非屏蔽代币。

函数 用途
sendUnshielded 发送非屏蔽代币(不返回找零)
receiveUnshielded 接收非屏蔽代币

Nonce 与燃烧地址

evolveNonce 从计数器索引和之前的 nonce 值可确定性地派生出新的 ShieldedCoinInfo nonce,适合在批量铸币场景中按序生成唯一 nonce。shieldedBurnAddress 返回一个特殊的支付地址,任何发送到该地址的屏蔽代币都将被永久销毁,无法再被花费。

合并操作

当合约拥有多个代币时,mergeCoin 可以将两个账本上已存在的代币合并为一个新代币,mergeCoinImmediate 则允许将一个账本代币和一个当前交易中新创建的代币合并。合并有助于减少状态大小和降低后续操作的成本。

低级操作

ownPublicKey 返回发起当前交易的终端用户的 ZswapCoinPublicKey,可用于向自己发送屏蔽代币。createZswapInputcreateZswapOutput 是底层的 Zswap 输入/输出创建接口,通常不建议手动调用,而应通过 sendShieldedsendImmediateShieldedreceiveShielded 等高级别函数来操作。

完整示例文件: contracts/coin-operations.compact, contracts/unshielded-operations.compact, contracts/merge-operations.compact


8. 余额与区块时间

unshieldedBalance (circuit)

返回合约对于某代币类型的非屏蔽余额。注意合约执行期间余额不更新,精确匹配可能导致交易失败。

circuit unshieldedBalance(color: Bytes<32>): Uint<128>;

推荐使用比较函数避免精确匹配问题:

  • unshieldedBalanceLt(color, amount) — 余额小于
  • unshieldedBalanceGte(color, amount) — 余额大于等于
  • unshieldedBalanceGt(color, amount) — 余额大于
  • unshieldedBalanceLte(color, amount) — 余额小于等于

示例:

export circuit hasSufficientBalance(
    color: Bytes<32>,
    required: Uint<128>
): Boolean {
    return unshieldedBalanceGte(color, required);
}

9. 板载注册

基于区块时间的合约逻辑控制函数:

  • blockTimeLt(time) — 当前时间小于给定时间
  • blockTimeGte(time) — 当前时间大于等于给定时间
  • blockTimeGt(time) — 当前时间大于给定时间
  • blockTimeLte(time) — 当前时间小于等于给定时间

示例: 注册窗口和时间锁提现。

export circuit isRegistrationOpen(deadline: Uint<64>): Boolean {
    return blockTimeLt(deadline);
}

export circuit isWithdrawalAvailable(unlockTime: Uint<64>): Boolean {
    return blockTimeGte(unlockTime);
}

完整示例文件: contracts/onboard-registration.compact


项目结构

~/Work/bounties/293-compact-stdlib/
├── README.md                       # 本篇教程
├── contracts/
│   ├── generic-types.compact       # 通用类型:Maybe, Either
│   ├── merkle.compact              # Merkle 树相关
│   ├── elliptic-curve.compact      # 椭圆曲线
│   ├── address-types.compact       # 地址类型
│   ├── crypto-hash.compact         # 加密和哈希
│   ├── minting.compact             # 铸币/代币操作
│   ├── coin-operations.compact     # Coin 操作(屏蔽)
│   ├── unshielded-operations.compact  # Coin 操作(非屏蔽)
│   ├── merge-operations.compact    # 合并操作
│   └── onboard-registration.compact   # 板载注册
└── src/                            # (预留)TypeScript 集成代码

参考资料

About

Compact Standard Library: A Practical Guide to Every Export

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors