作者:Darington Nnam
原文:Journey through Cairo II — Mastering Cairo’s Syntaxes with Starklings
翻译:Louis Wang
校对:「StarkNet 中文社区」
在上篇文章中,我们用 Protostar、ArgentX 和 Voyager 为 Cairo 建立本地开发环境,我们将从今天开始了解 Cairo 的基本原理,并尝试用 Starklings 作为教材来解释 Cairo 的基本功能。
直接通过官方文档来学习 Cairo,对普通人比较困难。刚开始我努力的去理解这些基础知识,直到发现了 Starklings。
Starklings 是由 OnlyDust 团队编写的互动式教程,其采纳流行的渐进互动式 Rust 教程 Rustlings 的长处。今天,我们将通过解决 Starklings 中的问题,开始了解 Cairo 如何工作。
为了高效学习本教程,需要提前设置你的计算机环境:
访问 Starklings 的官方 Github repo。
复制运行 git clone 指令到本地计算机上。
git clone --branch stable --single-branch
<https://github.com/onlydustxyz/starklings.git>
安装指令运行的必需工具:
curl -L
<https://raw.githubusercontent.com/onlydustxyz/starklings/master/install.sh> | bash
开始测试,打开终端并执行:
starklings --watch
现在我们已完成开发环境,在潜心编写 Cairo 前,这里一些必要指令和资源,会让开发更简单!
在没进入观察模式前手动验证测试,请运行以下:
starklings --verify relative_path_to_the_exercise_file
如果解决不了测试,可以检索答案:
starklings --solution relative_path_to_the_exercise_file
如果想自由发挥尝试更多,可以试试与 Solidity Remix (以太坊智能合约开发 IDE)相似的 Cairo‘s playground 。
syntax01.cairo — 从 Cairo 合约开始
开始使用 Cairo 时,如何区分 Cairo 程序和 Cairo 合约。为了避免相同的困惑,以下是两者的快速定义:
Cairo 程序:Cairo 程序可以理解为一种无状态合约,意味着在编写程序时,不能访问存储,不能与其他 Cairo 程序包括 L1 链进行交互。
Cairo 合约:简单来说,这是运行在 Starknet 虚拟机 (VM) 上的程序。由于在虚拟机上运行,因此他们可以访问 Starknet 的持续状态,改变或修改 Starknet 的变量状态,与其他合约交互,并与底层 L1 无缝交互。
理解后,就可以开始写一个 Cairo 合约,你必须指定它是一个合约并在最顶行写上:
%lang starknet
下一步,在 Starklings 的 Syntax01.cairo 中完成,并检查能否通过测试:
成功运行!
接下来是第二个测试,删掉 #I AM NOT DONE,Starkligns 会引导你进入下一个测试!
syntax02.cairo — Cairo 模块化
就像大部分现存的编程语言一样,把所有程序代码保存在一个文件里是非常不明智的做法。你也可能需要使用他人的代码,而不是重新发明轮子,所以每种语言都鼓励代码模块化,Cairo 也不例外。
在这个测试中,我们要研究 test_ok 函数,使该函数工作需要并导入所有重要文件。
在 Cairo 中导入一个文件:
from starkware.starknet.common.syscalls import get_contract_address
当你这样做时,Cairo 会在当前目录和相对于编译器路径的标准库目录中搜索文件 syscall.cairo,并从中导入 get_contract_address 函数。
我们的函数 test_ok 需要三个隐参数:syscall_ptr、pedersen_ptr 和 range_check_ptr(我们将在后文介绍隐参数)。但我们注意到,允许计算 Pedersen 哈希函数的 pedersen_ptr 需要一个 HashBuiltin,而这一参数并不存在于当前文件中,所以需要从 Cairo 函数库导入,我们要在代码中添加:
from starkware.cairo.common.cairo_builtins import HashBuiltin
成功运行!
func takes_two_arguments_and_returns_one(a: felt, b: felt) -> (c: felt):
return (a + b) # Do not change
end
正如你所看到的,我们给 a,b,c… 参数传递了一个奇怪的数据类型 **felt,**没错!不同于 Solidity 有许多数据类型,如 uint256,字符串等,Cairo 使用的是一种被称为 felt 的数据类型(我们会在以后的文章中深入讨论这个问题)。
从我们的函数签名中,能发现我们传入了一个不被函数使用的 c 参数。这个参数就是该函数的返回值。你的返回值通过 -> 来指定。
Cairo 命名空间是在合约中使用模块的一种非常强大的方式。当从多个模块导入时,它允许你在一个标识符下定义函数范围,有助于防止冲突。它还有助于提高代码可读性。
在 Cairo 执行一个命名空间,要使用 namespace 关键字,为命名空间指定一个名字:
namespace starklings
func starkling_exercise(a: felt, b:felt) -> (c: felt):
return (a+b)
end
end
从文件中使用命名空间中的函数:
starklings.starkling_exercise(3, 5)
为了通过执行了命名空间的测试,需要在命名空间 my_namespace 内调用 return_something 函数。
Cairo 和 Solidity 有着极度相似的结构体概念。
首先用 struct 关键字定义,然后用 member 关键字指定其属性。不同于 Solidity 的是,Cairo 中的结构体也有一个 size 属性,即其成员规模之和。
在 Cairo 中的结构体:
struct Starklings:
member first: felt
member second: felt
end
为了通过测试,我们要执行一个 Currency 结构体。
需要检查测试找出结构体的成员。调用结构体测试的第 13 行:
local euro : Currency = Currency('Euro', 2)
在此,我们注意到结构体有两个成员,可能分别是名称和 ID,但是 14 行出现:
assert euro.name = 'Euro'
修改结构体来通过测试:
struct Currency:
member name: felt
member id: felt
end
到这里,我想你现在已经很好理解了 Cairo 的基本语法、函数参数、命名空间、结构体等。
在下一讲中,将通过字符串挑战,并深入了解什么是 felt。
如果觉得本教程对你有帮助,转发分享给其他人吧~