#smart-contracts #cargo #concordium #cargo-build #building #source #blockchain

app cargo-concordium

用于在Concordium区块链上构建和测试智能合约的工具

7个稳定版本

3.3.0 2024年3月25日
3.2.0 2024年1月22日
3.1.4 2023年10月27日
3.0.0 2023年8月21日
2.8.1 2023年5月22日

#732 in 神奇豆

每月下载量 28次

自定义许可证

165KB
3.5K SLoC

Cargo Concordium

cargo-concordium 是一个用于在Concordium区块链上构建和测试智能合约的工具。

请参阅开发者文档,了解如何详细使用此工具的指南。

此crate是一个二进制文件,其版本适用于命令行API。不保证内部crate API。

创建新的Concordium智能合约项目

要启动一个新的Concordium智能合约项目,请运行以下命令

cargo concordium init

此命令将从模板文件夹中的模板生成一个新的项目。

编译智能合约

cargo concordium build -e --out contract.wasm.v1

将构建合约,嵌入模式,并将生成的工件输出到 contract.wasm.v1。这可以部署到链上或本地测试。

编译选项

由于链上运行的合约通常无法从恐慌中恢复,并且不会报告错误跟踪,因此不将这些错误跟踪添加到代码大小中是有用的。设置 panic=abort 将使得编译器在发生任何恐慌时生成简单的 Wasm 陷阱。此选项可以在 .cargo/config 或在 Cargo.toml 文件中指定为

[profile.release]
# Don't unwind on panics, just trap.
panic = "abort"

后者将在 release 构建中设置此选项,对于调试构建,请使用以下替代方案

[profile.dev]
# Don't unwind on panics, just trap.
panic = "abort"

代替。

请注意,目前wasm32-unknown-unknown目标是默认设置。

为了最小化代码大小,在某种程度上可能以性能为代价,可以考虑以下附加选项:

[profile.release]
# Tell `rustc` to optimize for small code size.
opt-level = "s"

或者甚至是 opt-level = "z"

在某些情况下,使用 opt-level=3 实际上可以减小代码大小,这可能是由于内联和死代码移除更多所致。

可重复和可验证的构建。

使用 cargo concordium build 的常规构建通常是不可重复的,因为某些主机信息已嵌入到生成的二进制文件中。因此,cargo concordium 支持所谓的可验证或可重复构建,该构建始终在指定的Docker镜像的固定环境中构建合约。可在 DockerHub 找到可用的镜像列表。

请注意,用于验证构建的镜像构成了信任链的一部分。在验证构建时,您必须只使用您信任的镜像。

cargo concordium buildcargo concordium test 都支持可验证构建,可以通过在构建命令中添加选项 --verifiable 来请求。此选项的值应为上述列出的Docker镜像。例如

cargo concordium build --verifiable docker.io/concordium/verifiable-sc:1.70.0 -o contract.wasm.v1 -e

这将构建智能合约,嵌入模式(-e)并将其输出到 contract.wasm.v1 文件。此外,cargo concordium 还将生成一个包含构建合约所使用的确切源代码的文件 contract.wasm.v1.tar

在构建 tar 存档时,cargo concordium 将包括以下内容的包根目录:

  • .gitignore 中列出的文件将被忽略(包目录及其父目录中的 .gitignore
  • 包构建目录(通常为 target)将被忽略
  • 在任意的 .ignore 文件中列出的额外文件将被忽略。此文件的格式应与 .gitignore 文件相同。
  • 隐藏文件将被忽略。

有关源代码和构建的信息将被嵌入到 contract.wasm.v1 文件中。这些信息包括

  • tar 文件的SHA2-256散列
  • 构建过程中使用的Docker镜像(例如,上面的 docker.io/concordium/verifiable-sc:1.700
  • 在镜像内部实际执行的精确构建命令
  • 如果提供了 --source 标志,则可以选择链接到源代码。如果没有提供,则可以在稍后嵌入链接。源代码链接应指向 tar 文件或文件的 gzip 压缩版本。

发布源代码

tar 归档打算发布,并且其链接应嵌入到放入链中的源代码中。在将模块注册到链上之前,应将 tar 文件上传到可通过 http GET 请求访问的位置。然后应使用 edit-build-info 命令将链接嵌入到 wasm.v1 文件中。

cargo concordium edit-build-info --module contract.wasm.v1 --source-link https://domain.com/contract.wasm.v1.tar --verify

--verify 标志是可选的,如果设置了该标志,则 cargo concordium 将下载提供的链接中的内容,并验证其是否与模块中已嵌入的构建元数据匹配。如果匹配,则将链接添加到元数据中。

验证构建

要验证部署的模块是否由给定的源代码构建,可以使用 cargo concordium verify-build 命令。此命令需要一个模块的路径,以及可选的源 tar 归档的路径。如果没有提供 tar 归档,则如果模块中存在链接,将从该链接下载。源代码链接也可能指向压缩的 tar 归档。

例如

cargo concordium verify-build --module contract.wasm.v1

打印构建信息

cargo concordium print-build-info --module contract.wasm.v1

将打印任何嵌入的构建信息。

限制

  • 为了可重复构建,必须保持 Cargo.lock 文件是最新的。
  • 合同源代码必须位于远程包仓库上,例如 crates.io,或者完全位于包根目录下。
  • 不支持 crypto-primitives 功能。此功能仅用于运行测试,可以在构建时禁用。

本地执行合同

以下是一些对 cargo concordium 二进制文件的子命令 run 的示例调用。

cargo concordium run init --context init-context.json --parameter parameter.bin --source ./simple_game.wasm --out state.bin --amount 123

使用输入文件

{
    "metadata": {
        "slotNumber": 1,
        "blockHeight": 1,
        "finalizedHeight": 1,
        "slotTime": "2021-01-01T00:00:01Z"
    },
    "initOrigin": "3uxeCZwa3SxbksPWHwXWxCsaPucZdzNaXsRbkztqUUYRo1MnvF"
}

parameter.bin 作为

00001111aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

(作为一个没有换行的文本文件)。

cargo concordium run receive --context receive-context.json --parameter parameter-receive.bin --source ./simple_game.wasm --state state-in.bin --amount 0 --name "receive_help_yourself" --balance 13 --out state-out.bin

其中示例接收上下文是

{
    "metadata": {
        "slotNumber": 1,
        "blockHeight": 1,
        "finalizedHeight": 1,
        "slotTime": "2021-01-01T00:00:01Z"
    },
    "invoker": "3uxeCZwa3SxbksPWHwXWxCsaPucZdzNaXsRbkztqUUYRo1MnvF",
    "selfAddress": {"index": 0, "subindex": 0},
    "selfBalance": 0,
    "sender": {
        "type": "Account",
        "address": "3uxeCZwa3SxbksPWHwXWxCsaPucZdzNaXsRbkztqUUYRo1MnvF"
    },
    "owner": "3uxeCZwa3SxbksPWHwXWxCsaPucZdzNaXsRbkztqUUYRo1MnvF"
}

请参阅 --helphelp 选项来解释 cargo concordium run 的选项。

从二进制中移除主机信息

默认情况下,从 rust crate 编译的二进制文件包含来自主机的一些信息,例如 rust 相关路径,如 .cargo 的路径。这可以通过检查生成的二进制文件来看到。

假设您的用户名为 tom,并且您在主目录中有一个名为 foo 的智能合约,您已经以发布模式将其编译成 WASM32。在 foo 文件夹内运行以下命令后,您将能够看到二进制文件中的路径:strings target/wasm32-unknown-unknown/release/foo.wasm | grep tom

要删除主机信息,可以使用编译器提供的标志来重映射路径前缀。RUSTFLAGS=--remap-path-prefix=/home/tom=secret cargo build --release --target wasm32-unknown-unknown,其中 /home/tom 是您想要更改的前缀,将其改为 secret。该标志可以多次指定以重映射多个前缀。

标志还可以在您的包的 .cargo/config 文件的 build 部分中永久设置

[build]
rustflags = ["--remap-path-prefix=/home/tom=secret"]

依赖项

~31–47MB
~735K SLoC