可验证智能合约简介
- 原文链接:https://medium.com/coinmonks/introduction-to-provable-smart-contracts-dcea94c3d5b6
- 译者:AI翻译官,校对:翻译小组
- 本文永久链接:learnblockchain.cn/article…
可验证智能合约使用加密技术来验证在区块链外部完成的计算是正确的。这意味着,不需要在链上完成所有工作(这可能会很慢且昂贵),而是将繁重的计算工作放在链下完成,并且只将结果的证明存储在区块链上。
主要优势
- 可扩展性: 通过在链下处理计算,可验证智能合约减少了区块链的负载,从而允许以更低的成本处理更多的交易。
- 安全性: 加密证明确保只有有效的计算被接受,增强了智能合约的安全性。
- 隐私: 像零知识证明(ZKP)这样的技术可以在不透露任何敏感信息的情况下验证交易。
StarkNet 和 Cairo
StarkNet 是以太坊上的一个 Layer-2 网络,使用 STARK(可扩展透明知识论证)证明来提供可扩展性和安全性。它允许开发者构建能够处理每秒大量交易的 dApp,同时受益于以太坊的安全性。
StarkNet 架构
StarkNet 中的状态变化和 STARK 证明
当在 StarkNet 上执行智能合约时,会涉及状态变化。这些状态变化是执行合约功能后对合约存储所做的更新。为了确保这些状态变化的正确性,StarkNet 生成并验证 STARK 证明。
以下是此过程的逐步解释:
1. 智能合约执行
当用户与 StarkNet 上的智能合约交互时,例如调用一个函数 increase_counter
,会发生以下步骤:
- 函数调用: 使用特定输入调用函数。例如,调用
increase_counter(10)
将计数器增加 10。 - 计算: StarkNet 虚拟机(VM)执行该函数,进行必要的计算以更新合约的状态。这涉及读取当前状态,应用更改,并将新状态写回存储。
2. 生成跟踪(Trace)
在执行智能合约期间,StarkNet 生成一个 跟踪(Trace)。跟踪是执行期间每一步计算的详细日志,包括初始状态、执行的操作和结果状态。这个跟踪对于生成证明至关重要。
3. 生成 STARK 证明
使用前一步生成的跟踪,StarkNet 生成一个 STARK 证明。这个证明是一个加密证书,证明计算和结果状态变化的正确性。其工作原理如下:
- 数据表示: 将跟踪转换为适合加密操作的格式。
- 证明计算:使用 STARK 协议计算证明。这涉及复杂的数学运算,生成跟踪正确性的简洁表示。
4. 提交和验证证明
生成的 STARK 证明以及新的状态变化被提交到以太坊主网进行验证。这是 STARKs 高效性的体现:
- 链上验证: 以太坊智能合约(StarkNet 验证器)只需验证 STARK 证明,而不是重新执行整个计算。这个验证过程要快得多,并且需要的计算能力远少于重新执行。
- 状态承诺: 一旦证明被验证,新状态变化被接受并提交到 StarkNet 状态。
示例工作流程
让我们以计数器合约为例来说明这个过程:
- 初始状态: 假设计数器值为 0。
- 函数调用: 用户调用
increase_counter(10)
。 - 计算: StarkNet VM 计算新的计数器值,即 10。
- 生成跟踪: 生成一个跟踪,记录初始计数器值(0)、增量操作和结果计数器值(10)。
- 生成证明: 使用跟踪生成一个 STARK 证明,证明计算(0 + 10 = 10)是正确执行的。
- 提交证明: 将 STARK 证明和新的计数器值(10)提交到以太坊主网。
- 验证: 以太坊智能合约验证 STARK 证明。
- 状态承诺: 验证成功后,新的计数器值(10)被提交到 StarkNet 的状态。
什么是 Cairo 语言?
Cairo(计算机代数用于 RISC 操作)是一种专门为编写可验证程序而设计的编程语言。它是 StarkNet 上开发智能合约的本地语言,利用零知识证明确保计算完整性。
Cairo 的主要特点:
- 生成证明: Cairo 允许创建简洁的证明,证明计算的正确性。
- 高效性: 设计用于高性能计算,Cairo 能够高效处理复杂算法。
- 互操作性: Cairo 智能合约可以与以太坊和其他区块链平台无缝交互。
在本文中,我们将探讨在 StarkNet 上构建、部署和交互智能合约的步骤。
预备条件
在开始之前,请确保你已安装以下内容:
- Rust (>= 1.51.0)
cargo
(Rust 的包管理器)- Node.js (>= 12.x)
- npm (Node 包管理器)
starknet-devnet
(StarkNet 本地测试网)starknet
CLIscarb
(Cairo 的 Rust 包管理器)
你可以使用以下命令安装必要的工具:
# 安装 Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# 安装 Node.js 和 npm(如果尚未安装)
sudo apt-get install nodejs
sudo apt-get install npm
# 安装 StarkNet CLI
pip install starknet-devnet
# 安装 Scarb(Cairo 的 Rust 包管理器)
curl -L https://github.com/software-mansion/scarb/releases/download/latest/scarb-x86_64-unknown-linux-gnu.tar.gz | tar xz
sudo mv scarb /usr/local/bin
设置 StarkNet Devnet
使用以下命令启动 StarkNet Devnet:
starknet-devnet
此命令将在 http://localhost:5000
启动一个本地的 StarkNet Devnet 实例。
创建 Rust Cairo 项目
创建一个新的 Rust 项目并添加 Cairo 的必要依赖项。运行以下命令:
cargo new starknet\_counter
cd starknet\_counter
将以下依赖项添加到你的 Cargo.toml
文件中:
[dependencies]
cairo = "0.1"
starknet = { git = "https://github.com/starkware-libs/cairo.git" }
编写智能合约
创建一个名为 src/main.rs
的文件,并添加以下代码用于一个简单的计数器合约:
use cairo::contract;
use cairo::types::felt::Felt252;
use cairo::starknet::storage::Storage;
use cairo::starknet::types::Address;
#[contract]
mod counter {
use super::*;
#[storage]
struct Storage {
counter: Felt252,
}
#[constructor]
fn new() -> Storage {
Storage {
counter: Felt252::from(0),
}
}
#[external]
fn increase_counter(storage: &mut Storage, amount: Felt252) {
storage.counter += amount;
}
#[view]
fn get_counter(storage: &Storage) -> Felt252 {
storage.counter
}
}
这个合约定义了一个简单的计数器,包含两个函数:
increase_counter(amount: Felt252)
: 按指定数量增加计数器。get_counter() -> Felt252
: 获取计数器的当前值。
编译合约
使用 Scarb 工具编译合约:
scarb build
这将在 target
目录中生成必要的编译文件。
部署合约
使用 StarkNet CLI 将编译后的合约部署到 StarkNet Devnet:
starknet deploy --contract target/release/starknet_counter.sierra.json --abi target/release/starknet_counter.abi.json --network localhost
记录部署输出中的合约地址和交易哈希。你需要合约地址来与合约进行交互。
与合约交互
要与合约交互,我们将使用 StarkNet CLI。首先,让我们将计数器增加 10。
starknet invoke --function increase_counter --inputs 10 --address <contract_address> --abi target/release/starknet_counter.abi.json --network localhost
将 <contract_address>
替换为从部署步骤中获得的实际合约地址。
接下来,让我们查询计数器的当前值。
starknet call --function get_counter --address <contract_address> --abi target/release/starknet_counter.abi.json --network localhost
这应该返回 10
,因为我们刚刚将计数器增加了 10。
L1-L2 消息传递
L1-L2 消息传递是指 Layer-1 区块链与其 Layer-2 解决方案之间的通信协议。Layer-2 解决方案旨在处理主区块链之外的交易,以提高可扩展性、降低交易费用并增加吞吐量。这些解决方案仍然必须与 L1 区块链进行交互,以确保交易的安全性、互操作性和最终性。
L1-L2 消息传递如何工作?
L1-L2 消息传递通常涉及几个关键步骤:
- 在 L2 上发起交易:
- 用户在 L2 解决方案上发起交易,例如支付或智能合约执行。
- 交易在链下处理,利用 L2 的可扩展性和较低成本。
2. 生成证明:
- 处理交易后,L2 解决方案生成交易有效性的加密证明。
- 该证明是交易数据的简洁表示,确保可以在 L1 区块链上高效验证。
3. 向 L1 提交证明:
- 生成的证明提交到 L1 区块链。
- 这种提交可以定期进行,将多个交易批量处理以进一步降低成本。
4. 在 L1 上验证和最终确定:
- L1 区块链验证加密证明。
- 一旦验证通过,L2 上处理的交易被认为是最终的和安全的,利用 L1 区块链的安全性。
示例:StarkNet 和 Cairo
创建 Rust Cairo 项目
创建一个新的 Rust 项目并添加 Cairo 的必要依赖项。运行以下命令:
cargo new l1_l2_messaging
cd l1_l2_messaging
将以下依赖项添加到你的 Cargo.toml
文件中:
[dependencies]
cairo-lang = "0.6.2"
starknet = { git = "https://github.com/starkware-libs/starknet-rs.git" }
用 Rust 编写 Cairo 合约
创建一个名为 src/main.rs
的文件,并添加以下 L1-L2 消息传递合约代码:
use cairo::contract;
use cairo::types::felt::Felt252;
use cairo::starknet::storage::Storage;
use cairo::starknet::types::Address;
#[contract]
mod l1_l2_messaging {
use super::*;
#[storage]
struct Storage {
message: Felt252,
}
#[constructor]
fn new() -> Storage {
Storage {
message: Felt252::from(0),
}
}
#[external]
fn send_message(storage: &mut Storage, sender: Felt252, message: Felt252) {
storage.message = message;
emit_message_sent(sender, message);
}
#[view]
fn get_message(storage: &Storage) -> Felt252 {
storage.message
}
#[event]
fn emit_message_sent(sender: Felt252, message: Felt252);
}
编译合约
使用 Scarb 工具编译合约:
scarb build
部署合约
使用 StarkNet CLI 将编译后的合约部署到 StarkNet Devnet:
starknet deploy --contract target/release/l1_l2_messaging.sierra.json --abi target/release/l1_l2_messaging.abi.json --network localhost
记录部署输出中的合约地址。
与合约交互
- 发送消息:
starknet invoke --function send_message --inputs 123 456 --address <contract_address> --abi target/release/l1_l2_messaging.abi.json --network localhost
将 <contract_address>
替换为从部署步骤中获得的实际合约地址。这里,123
是发送者的地址,456
是消息。
2. 获取存储的消息:
starknet call --function get_message --address <contract_address> --abi target/release/l1_l2_messaging.abi.json --network localhost
解释
- send_message(sender: Felt252, message: Felt252): 此函数允许发送者发送消息,该消息随后存储在合约的存储中。它还会发出一个事件
emit_message_sent
,包含发送者和消息。 - get_message(): 此视图函数从合约的存储中检索存储的消息。
- emit_message_sent(sender: Felt252, message: Felt252): 此事件函数发出一个消息事件以进行跟踪。
StarkNet 和 Cairo 的有用资源
要进一步探索 StarkNet 和 Cairo,以下资源将为你提供全面的指南、文档和社区支持:
官方文档
- StarkNet 文档: StarkNet Docs
- Cairo 语言文档: Cairo Lang Docs
开发工具
- StarkNet CLI: StarkNet CLI GitHub
- Scarb (Cairo 的 Rust 包管理器): Scarb GitHub
学习资源
- StarkNet Base: StarkNet Base
- Cairo 教程: Cairo Tutorial
社区和支持
- StarkNet 社区: StarkNet Community
- StarkNet Discord: StarkNet Discord
- Cairo GitHub: Cairo GitHub
示例项目
- StarkNet 示例: StarkNet Examples GitHub
- Cairo 示例项目: Cairo Examples GitHub
这些资源将帮助你开始在 StarkNet 上进行开发,并使用 Cairo 编写智能合约,为你提供必要的工具、教程和社区支持,以构建可扩展和安全的 dApps。
与我联系: 在 Twitter 上关注
我是 AI 翻译官,为大家转译优秀英文文章,如有翻译不通的地方,在这里修改,还请包涵~
版权声明
本文仅代表作者观点,不代表区块链技术网立场。
本文系作者授权本站发表,未经许可,不得转载。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。