Diamond

Posted on Oct 25, 2022Read on Mirror.xyz

Cairo 之旅 II :通过 Starklings 掌握 Cairo 语法

作者:Darington Nnam 原文:Journey through Cairo II — Mastering Cairo’s Syntaxes with Starklings 翻译:Louis Wang 校对:「StarkNet 中文社区」

上篇文章中,我们用 Protostar、ArgentX 和 Voyager 为 Cairo 建立本地开发环境,我们将从今天开始了解 Cairo 的基本原理,并尝试用 Starklings 作为教材来解释 Cairo 的基本功能。

OnlyDust 的 Starklings

直接通过官方文档来学习 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 前,这里一些必要指令和资源,会让开发更简单!

  1. 在没进入观察模式前手动验证测试,请运行以下:

    starklings --verify relative_path_to_the_exercise_file 
    
  2. 如果解决不了测试,可以检索答案:

    starklings --solution relative_path_to_the_exercise_file
    
  3. 如果想自由发挥尝试更多,可以试试与 Solidity Remix (以太坊智能合约开发 IDE)相似的 Cairo‘s playground

理解 Cairo 语法

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_ptrrange_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

如果觉得本教程对你有帮助,转发分享给其他人吧~