跳转至

可重现的构建

原文:https://docs.elrond.com/developers/reproducible-contract-builds

通过利用 Docker 和 DockerHub 上的一组 冻结 Docker 镜像,该页面将引导您完成支持可复制合约构建的过程。

您还将学习如何重现一个合约构建,给出它的源代码和一个冻结的 Docker 映像的名称(标签),该映像用于它的前一个构建(我们想要重现)。

可复制构建,也称为确定性编译,是一个编译软件的过程,确保生成的二进制代码可以被复制。使用确定性编译编译的源代码将总是输出相同的二进制【维基百科】

重要

截至 2022 年 9 月,Rust 工具链不支持开箱即用的可再现构建,因此我们建议智能合约开发者遵循本教程,以实现确定性编译。

智能合约codehash

在深入合约构建可再现性之前,让我们先理解一下codehash的概念。

当部署智能合约时,网络存储字节码,并计算其blake2b校验和(使用 256 位的摘要长度)。这被称为codehash

假设我们对下面的合约感兴趣,部署在devnet:er D1 qqqqqqqqqpgqahertgz 4020 wegswus 8m 7 F2 AK 8 a 6d 0 gv 396 qw3t 2 zy。它的源代码公布在 GitHub 上。

我们可以从 API 中获取合约的 codehash :

curl -s https://devnet-api.elrond.com/accounts/erd1qqqqqqqqqqqqqpgqahertgz4020wegswus8m7f2ak8a6d0gv396qw3t2zy \
| jq -r -j .codeHash \
| base64 -d \
| xxd -p \
| tr -d '\n' 

输出是:

58c6e78f40bd6ccc30d8a01f952b34a13ebfdad796a2526678be17c5d7820174 

如果WASM文件是直接可用的,我们也可以使用实用程序b2sum来本地计算代码哈希:

b2sum -l 256 adder.wasm 

输出将是相同的:

58c6e78f40bd6ccc30d8a01f952b34a13ebfdad796a2526678be17c5d7820174 

总而言之,为了验证合约的两个给定构建的字节码相等性,我们可以简单地比较 codehash 属性。

支持可重现构建

截至 2022 年 10 月,为您的智能合约支持可复制构建的推荐方法是使用一个构建脚本,该脚本依赖于一个特别设计的、公开可用的、带标签的 Docker 映像,其中包括带标签的、显式版本的构建工具( Rustwasm-opt 等)。).

建议采用这种方法,以抵消与cargo(防锈工具链的基本组件)对环境的敏感性相关的最终非确定性。

重要

如果您的智能合约的代码源托管在 GitHub 上,那么定义一个类似于这个的 GitHub 工作流是一个很好的实践,它在发布过程中执行部署(生产就绪)构建。

选择一个图像标签

支持可再现构建的第一步是决定使用特定的 Docker 镜像标签。检查elrond network/build-contract-rust上列出的冻结标签,检查它们的标签——特别是标签rustwasm-opt-binaryen:

LABEL rust=nightly-2022-08-23
LABEL wasm-opt-binaryen=version_105 

对于尚未发布(部署在网络上)的新智能合约,建议选择具有最大索引号的标签,它通常包括rust的最新版本和其他必要的依赖项。

然而,对于较小的版本或补丁,坚持使用之前选择的 image 标记是明智的,出于同样的(细微的)原因,您不会在修复关键 bug 的过程中拥抱开发工具的更新(在任何开发环境中)。

所选择的、冻结的图像标签应伴随版本化的源代码(例如,通过发布说明),以便告知其他人如何再现特定的构建(特定源代码版本)。在这个上下文中,冻结图像标签指的是 Docker 镜像标签,它在首次发布后将不会得到任何更新。

提示

在你的合约的每个(主要)版本上切换到一个更新的图像标签是完全正常的。请确保您传播了这些信息——即使用发行说明

警告

永远不要为生产就绪的构建选择名为latest的标签。

通过 Docker 构建(可重复构建)

在这一节中,您将学习如何运行一个可重现的构建,或者换句话说,如何在本地机器上使用 Docker 来重现一个先前的构建(由您或其他人在过去创建的),而不需要安装其他工具,例如 erdpy (及其依赖项)。

获取源代码

让我们在本地克隆示例源代码,并切换到我们想要构建的某个版本:

mkdir -p ~/contracts && cd ~/contracts
git clone https://github.com/ElrondNetwork/reproducible-contract-build-example.git --branch=v0.1.4 --depth=1 

通过查看发行说明,我们看到 v0.1.4 是使用image:tag = elrondnetwork/build-contract-rust:v2.0.0构建的。

下载构建包装

构建过程(通过 Docker)被包装在一个易于使用、友好的 Python 脚本中。让我们下载它:

wget https://raw.githubusercontent.com/ElrondNetwork/elrond-sdk-images-build-contract-rust/main/build_with_docker.py 

准备环境变量

导出以下变量:

export PROJECT=~/contracts/reproducible-contract-build-example
export BUILD_OUTPUT=~/contracts/output-from-docker
export IMAGE=elrondnetwork/build-contract-rust:v2.0.0 

后面的导出语句明确地选择了要使用的、冻结的Docker 镜像标签

*### 执行构建

现在,让我们通过调用之前下载的构建包装器来构建合约:

python3 ./build_contract_rust_with_docker.py --image=${IMAGE} \
    --project=${PROJECT} \
    --output=${BUILD_OUTPUT} 

output文件夹中,您应该看到以下文件(示例):

  • adder.wasm:智能合约的实际字节码,将被部署在网络上;
  • adder.abi.json:智能合约的 ABI(端点和类型定义的列表),在开发 dApps 或简单地与合约交互时使用(例如,使用erdjs);
  • adder.codehash.txt:包含合约计算的codehash的文件。
  • adder.wat:字节码的文本表示,如有必要,将在文本编辑器中显示;
  • adder.imports.json:合约导入使用的 VM API 函数列表。
  • adder-v1.2.3.zip:包含用作构建输入的源代码的版本化档案。

TL;灾难恢复构建片段

话虽如此,让我们将上述步骤总结成一个 bash 片段:

wget https://raw.githubusercontent.com/ElrondNetwork/elrond-sdk-images-build-contract-rust/main/build_with_docker.py

export PROJECT=~/contracts/reproducible-contract-build-example
export BUILD_OUTPUT=~/contracts/output-from-docker
export IMAGE=elrondnetwork/build-contract-rust:v2.0.0

python3 ./build_contract_rust_with_docker.py --image=${IMAGE} \
    --project=${PROJECT} \
    --output=${BUILD_OUTPUT} 

比较代码哈希

一旦构建就绪,您就可以通过检查文件*.codehash.txt来检查生成的*.wasm的 codehash

对于我们的示例,应该是:

adder.codehash.txt: 58c6e78f40bd6ccc30d8a01f952b34a13ebfdad796a2526678be17c5d7820174 

我们可以看到它与之前获取(或计算)的 codehash 相匹配。也就是说,部署在erd1 qqqqqqqqqqpgqahertgz 4020 wegswus 8m 7 F2 AK 8 a 6d 0 gv 396 qw3t 2 zy的合约保证是从与我们签出的源代码版本相同的源代码版本构建的。

恭喜你!您已经完成了可重复的合约构建🎉*



回到顶部