部署可编程合约

通用账本支持可在网络中部署的可编程合约,以自动执行并强制执行相关参与者之间的协议。

本教程向开发者展示了在通用账本网络中开发、部署可编程合约并与之互动的必要步骤。

准备工作

如需完成本教程,您需要:

  • 在 Google Cloud 控制台中,激活 Cloud Shell。

    激活 Cloud Shell

  • 具有 ROLE_CONTRACT_CREATOR 的 Universal Ledger 用户账号。此账号将成为合约所有者

  • 一个或多个具有 ROLE_CONTRACT_PARTICIPANT 的通用账本用户账号。它可以与合约所有者账号相同。

  • (可选)设置 Universal Ledger CLI,以便能够代表这些用户账号签署和提交交易。

通用账本角色可以在用户账号由其客户经理创建时分配,也可以在提交 CreateAccount 交易时分配,如果账号已存在,则可以通过 AddRoles 交易稍后修改。 为了进行实验,您还可以使用 Universal Ledger CLI 来管理账号

设置环境

为简化设置,本教程是针对 Cloud Shell 会话中提供的默认环境编写的。如果您使用的是其他环境,可能需要修改这些命令。

gculpyc 编译器接受使用 GCULpy 语言编写的源代码,并为 Universal Ledger 生成字节码。

运行以下每个命令,以拉取 gculpyc Docker 映像、定义用于运行二进制文件的别名,并确认二进制文件正常运行。

docker pull us-docker.pkg.dev/gcul-artifacts/images/client/gculpyc:preview
alias gculpyc="docker run --rm -i --user $(id -u):$(id -g) \
    --volume .:/workspace --workdir /workspace \
    us-docker.pkg.dev/gcul-artifacts/images/client/gculpyc:preview"
gculpyc --help

撰写合同

GCULpy 是用于为通用账本编写合约的语言。它是 Python 的静态类型化子集,经过优化,可实现清晰、可审核且易于理解的合约逻辑。此设计优先考虑编写安全的代码,并限制意外或不安全的行为。 如需了解详情,请参阅 GCULpy 语言参考文档。

由于 GCULpy 是 Python 的严格子集,因此您可以继续使用自己偏好的集成开发环境 (IDE),以及现有的工作流和开发实践。

例如,您的代码可能如下所示:

import gcul

class Counter(gcul.Contract):
    """Example contract implementing a counter."""

    value: int

    def increment(self) -> None:
        """Increments the counter value by 1."""
        self.value += 1

复制此示例代码并将其保存到名为 counter.py 的文件中。

在本地测试

在不久的将来,开发者将能够访问本地模拟环境。它作为 gcul Python 模块的一部分提供,旨在提供在 Python 环境中原生模拟通用账本网络所需的功能。因此,您将能够使用自己偏好的测试框架在本地运行合约并编写单元测试,从而在部署之前确保合约的可靠性和正确性。

编译合同

使用以下 gculpyc 命令将上述合约源代码编译为字节码:

gculpyc --source_file counter.py --output_file counter.bin

部署合约

通过提交由持有 ROLE_CONTRACT_CREATOR 的用户账号签名的 CreateContract 交易,将合约部署到通用账本网络。

如果使用 Universal Ledger CLI,您可以通过运行以下命令来执行此操作:

ul-cli contracts create \
    --alias counter-contract \
    --sender OWNER_ALIAS \
    counter.bin

替换以下内容:

  • OWNER_ALIAS:具有 ROLE_CONTRACT_CREATOR 的用户账号的别名。

交易最终确定后,此命令的输出将包含新部署的合约的 ID。例如:

Contract created: 1:CTR:005XvYfiSm3913Jwv4y8HVQucStJ2Ev15Sar6A1kNNX10

调用合约方法

合约部署后,任何具有 ROLE_CONTRACT_PARTICIPANT 的用户账号都可以提交 InvokeContractMethod 交易来调用合约中的任何公共方法。

如果使用 Universal Ledger CLI,您可以通过运行以下命令来执行此操作:

ul-cli contracts invoke \
    --alias counter-contract \
    --method-name increment \
    --sender PARTICIPANT_ALIAS

替换以下内容:

  • PARTICIPANT_ALIAS:具有 ROLE_CONTRACT_PARTICIPANT 的用户账号的别名。

读取合同状态

在本教程结束时,您可以提交 QueryAccount 请求,以读取并验证账本上存储的合约状态。此 API 方法与用于查询和检索任何通用账本账号的详细信息的 API 方法相同。

使用 Universal Ledger CLI,您可以运行:

ul-cli accounts describe --alias counter-contract

这应确认计数器值现在已设置为 1,并生成如下输出:

Account: 1:CTR:005XvYfiSm3913Jwv4y8HVQucStJ2Ev15Sar6A1kNNX10
Contract account details:
  Owner: 1:USR:XCL:022uF6cVkTJBaa6pViqTuYqP4455jnRbRc4bWannZGg0b
  Contract fields:
    value: int64_value:1

  Balances:
    None

后续步骤