通过一人了解 关于Cairo 1.0 新特性和改进的所有信息
- 原文链接: https://www.argent.xyz/blog/getting-started-with-cairo-1.0/
- 译文出自:登链翻译计划
- 译者:翻译小组 校对:Tiny 熊
- 本文永久链接:learnblockchain.cn/article…
去年9月,StarkWare 发布了两个重要的公告,这将大大改善网络上的开发者体验。
它们是:
许多开发人员在使用旧版本的Cairo编写代码时面临的繁琐体验将成为过去,因为Cairo 1.0使编写代码明显变得更容易、更整洁,因为该语言变得与Rust相似。
随着Cairo的这一变化,它还有一个额外的好处,就是让熟悉Rust的新开发者进入Starknet生态系统。
这就是为什么Cairo 1.0,随着Sierra的引入,让Starknet开发者社区兴奋,而且是有理由的。
在这篇文章中,我们将教你如何编写和编译你的第一个Cairo 1.0合约,并探索所有随着改进而来的新功能。现在,让我们一起开始吧。
在我们开始写代码之前,我们需要建立开发环境。不幸的是,你可能熟悉的Starknet工具,如Protostar、Nile或官方Starknet CLI开发,目前不支持Cairo 1.0。这意味着我们需要使用一个替代的解决方案...
我们已经解决了这个问题,通过克隆和修改官方 repo,创建了一个Cairo 1.0的自定义开发环境。你将需要克隆这个 repo 来编写和编译你的 Cairo 1.0 合约。
我们所有的合约都将被放入src文件夹。我们已经创建了一个模板合约,我们将在本文的下一节将其编译为sierra和casm。
一旦我们克隆了 repo,我们就可以继续激活 Cairo 1.0 VS代码扩展来实现语法高亮。
要做到这一点:
安装Node.js 18 LTS
导航到vscode-cairo文件夹中
在终端中运行以下命令:
sudo npm install --global @vscode/vsce
npm install
vsce package
code --install-extension cairo1*.vsix
cargo build --bin cairo-language-server --release
运行这些命令:
npm install
npm run compile
PS: 你应该在VScode中的settings.json文件中添加这个额外的代码片段,以确保事情正确运行。
"cairo1.languageServerPath": "/Some/Path/target/release/cairo-language-server",
如果你的安装成功了,前往src/hello.cairo,你应该激活了语法高亮,如上图所示。
在建立了开发环境之后,现在可以开始编译我们的Cairo 1.0合约。
我们将使用位于src/hello.cairo的一个简单的合约:
#[contract]
mod HelloStarknet {
struct Storage {
balance: felt,
}
#[external]
fn increase_balance(amount: felt) {
balance::write(balance::read() + amount);
}
#[view]
fn get_balance() -> felt {
balance::read()
}
}
这个合约实现了简单的函数来增加和获得余额变量。#[contract]标志着我们正在编写一个Starknet合约,而不是一个Cairo程序。
与版本0.x合约不同的是,0.x 直接编译成Cairo汇编(casm),在Cairo 1.0中,编译我们的合约将分两个阶段进行。
Sierra代表安全中间表示法,旨在构成Cairo程序和其字节码之间的表示层。Sierra开启证明每个Cairo运行的可能性,从而允许强大的拒绝服务攻击(DoS)保护。
要编译到Sierra,请运行下面的命令:
cargo run --bin starknet-compile -- src/hello.cairo src/hello.sierra --replace-ids
如果编译成功,你应该在你的 src/hello.sierra中看到Sierra的输出。
要进一步从Sierra编译到Casm,请运行下面的命令:
cargo run --bin starknet-sierra-compile -- src/hello.sierra src/hello.casm
如果编译成功,你应该在你的 src/hello.casm中看到casm的输出。
Starknet Alpha v0.11.0还没有发布,所以我们不能把我们编译的合约部署到testnet或mainnet上。然而,这个网络升级预计将在2023年2月底发生。
要想了解Cairo 1.0的所有新功能,一篇文章是不够的,但我们将在本节中探讨一些关键功能:
如前所述,Cairo 1.0带有一个更干净、更好的语法,其灵感来自Rust。这包括采用类似Rust的特性,如traits和它们的实现,模式匹配,panic等。
通过Cairo 1.0,要开始编写Starknet合约,你必须指定宏:
#[contract]
虽然每个Cairo程序都必须实现一个主函数,但导入一个函数也变得更加容易。
你可以像这样做:
use starknet::get_caller_address;
另外,你也可以导入整个 "包":
use starknet;
并像这样使用它:
starknet::get_caller_address()
Starknet生态系统的标志是felt数据类型,当然,它们也不会很快消失!
除了felt数据类型外,还支持其他Integer类型,如u256、u128、u64、u32和u8。
虽然这些Integer类型是在幕后使用felts实现的,但它们被认为使用起来更安全,现在可以支持算术运算,而不需要自定义库。例如,你现在可以执行如下操作。
let sum = 1_u128 + 2_u128;
let product = 5_u256 * 10_u256;
这些运算符的使用是有溢出保护的,如果检测到溢出,会引起panic。
还支持类似于Solidity地址的contractAddress数据类型,该类型最近才在Cairo 0.1中实现。
数字常量,如1,2,3,默认为felt。然而,你可以通过附加数据类型为它们指定一个不同的数据类型,就像这样:
let num_u256 = 1_u256
在Cairo 1.0中,我们最终消除了多种变量声明模式(tempvar、local等),而只接受使用let关键字。
这非常有帮助,因为我们终于告别了撤销引用(revoked references) 的编译器错误。
现在你也可以使用mut关键字来创建可变的变量。
Cairo 1.0没有使用@storage_var修饰器,而是将一个合约分为三个主要部分:一个存储结构、合约接口(traits)和其实现。
所有的存储变量都被打包到一个名为Storage的结构中,尽管这可能会被改变。
在写这篇文章的时候,它看起来是这样的:
struct Storage {
name: felt,
symbol: felt,
decimals: u8,
total_supply: u256,
balances: LegacyMap::<felt, u256>,
allowances: LegacyMap::<(felt, felt), u256>,
}
并可以用这种方式读或写:
let name = name::read()
let name = name::write(_name)
可以使用LegacyMap关键字创建映射,其中映射变量的数据类型被插入到<和>之间。你也可以映射元组(tuples)。
事件允许合约在其执行过程中发出信息,这些信息可以在Starknet之外使用。
一个事件可以像这样创建:
#[event]
fn Transfer(from_: felt, to: felt, value: u256) {}
并随后以这种方式发出:
Transfer(sender, recipient, amount);
Cairo 1.0中的函数与0.x版本相似,只是省略了隐含参数,并按照Rust的惯例将func关键字改为fn。下面是一个Cairo 1.0中基本函数签名的例子:
fn balance_of(account: felt) -> u256 {
...
}
你还会注意到,返回变量不再包含变量名,而只是其数据类型。
就像Rust一样,Cairo 1.0中的函数既可以通过省略结尾的分号来隐含地返回值,就像这样:
#[view]
fn get_name() -> felt {
name::read()
}
在此案例中,函数的最终表达式会自动返回,或者通过使用return关键字显式返回,像这样:
#[view]
fn get_name() -> felt {
return name::read();
}
修饰器在Cairo 1.0中仍然存在,但有一个类似于Rust的宏的新语法。
你可以像这样声明一个修饰器:
#[external]
#[view]
枚举(Enum)是一种特殊的数据类型,由你定义的一组固定的常数组成。
你可以在Cairo 1.0中创建一个Enum,像这样:
enum Animals { Goat: felt, Dog: felt, Cat: felt }
Cairo 1.0 也使我们能够使用 match 关键字创建类似于 Rust 的模式匹配。当与Enum结合时,模式匹配可以让我们根据遇到的数据变量来调整函数的行为:
enum Colors { Red: felt, Green: felt, Blue: felt }
func get_favorite_color() -> Colors {
Colors::Green(0)
}
func main() -> felt {
let my_color = get_favorite_color();
let result = match my_color {
Colors::Red(_) => {
1
},
Colors::Green(_) => {
2
},
Colors::Blue(_) => {
3
},
};
result // returns 2
}
Cairo 1.0使数组操作变得更加容易,因为核心库除了导出一个数组类型外,还有一些相关的函数,如append, array_at, 和array_len。一些基本的数组操作包括向现有的数组添加新元素,获得元素索引,获得数组长度等。这些都可以通过ArrayTrait访问。
fn fib(n: usize) -> (Array::<felt>, felt, usize) {
let mut arr = ArrayTrait::new();
arr.append(1);
arr.append(1);
let mut arr = fib_inner(:n, :arr);
let len = arr.len();
let last = arr.at(len - 1_usize);
return (arr, last, len);
}
你可以在Cairo中创建自定义错误,在执行失败时输出给用户。这对于实现检查和适当的访问控制机制非常有用。
在Cairo 1.0中,你可以很容易地使用assert语句来做到这一点,其模式与Solidity中的require语句相似。
assert(sender != 0, 'ERC20: transfer from 0');
其中错误信息必须小于31个字符。
Cairo 1.0引入了traits和实现。把traits看作是一种特殊的合约接口,因为它们定义了一个特定类型的功能,并且可以与其他类型共享。它们是用trait关键字定义的:
trait IContract{
fn set_something(num: felt, pair: felt);
fn get_something(num: felt) -> felt;
}
另一方面,一个实现了特定的trait行为的实现中,需要包含 trait中的所有定义函数。
它们是用impl关键字定义的,像这样:
impl Contract of IContract {
fn set_something(num: felt, pair: felt) {
number_pair::write(num, pair)
}
fn get_something(num: felt) -> felt {
number_pair::read(num)
}
}
Cairo 1.0与Rust类似,也支持泛型,这使你能够编写灵活的代码,可以与多种类型一起工作,而不是被束缚在一个特定的类型上。
一个类型参数通过使用角括号<>来指定为泛型,像这样:
fn foo<T>(arg: T) -> T {
…
}
在Cairo 1.0和Starknet v0.11中,将增加一个新的syscall,使你能够在不改变合约的入口点的情况下交换底层的合约实现(class hash)。想想看,一个默认的代理!
最重要的是,你只需用一行代码就可以做到这一点:
#[contract]
mod upgradeable {
use starknet::replace_class;
. ….
#[external]
fn upgradeable(cls_hash: felt) {
replace_class(cls_hash);
}
}
恭喜你,你刚刚编写并编译了你的第一个Cairo 1.0合约,并了解了Cairo 1.0的关键特性
再次强调,Cairo 1.0仍然是一项正在进行中的工作,而且发展很快。新的功能每天都在增加,所以要经常查看官方版本和Discord讨论频道,以保持最新的信息!
这里有一些额外的资源,我们认为会对你的Cairo 0.10之旅有所帮助。
https://github.com/starkware-libs/cairo/blob/main/docs/reference/src/SUMMARY.adoc
https://github.com/argentlabs/starknet-build/tree/main/cairo1.0/examples
[Cairo 1.0 by StarkWare](https://medium.com/starkware/cairo-1-0-aa96eefb19a0#:~:text=Introducing Sierra%3A ensuring every Cairo run can be proven)
如果你对此有任何问题,请联系我@0xdarlington,我很乐意帮助你用Argent X建立Starknet。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!