Cairo学习专题 III:通过 Starkling 学习 Felt 和 String

in Cairo with 0 comment

欢迎来到我们 「Cairo 之旅」系列的第三课!在上篇文章中,我们完成了 Starklings 语法部分的挑战,了解 Cairo 基本内容,包括命名空间 (Namespace)、结构体 (Struct) 等。今天我们将深入研究字符串 (Strings) 和整数 Felts。

像往常一样,如果你是中途加入的,建议从头开始看我们的文章。

Felts

不像 Solidity 有相当多的各种数据类型,如 uints、strings、bools 等,Cairo 只有一个数据类型:felts。

Felts 代表字段元素。简单来说,它们是无符号的整数,最高精度 76 位小数。

虽然使用 felts 有很多优点,但我觉得它们也有一些恼人的缺点。比如说:

1. 它们是一个 252 位的整数,当我们想把一个 uint256 的值放入其中时,就会出现问题。我们可以把 felts 组合成 tuples 来解决这个问题。

2. 据 Cairo 的官方文档,在 Cairo 中,基本的数据类型是一个范围为 0≤x<P 的整数,其中 P 是一个素数(一般为 2^192+1)。这可能会给除法带来一些非常严重的问题,因为所有的除法运算 (x/y),都必须满足这个条件:

(x/y) * y == x

对于那些没有数学背景的人来说,上面的等式意味着,如果我们说 10 除以 5,其中 x=10,y=5,无论我们得到什么答案,当乘以 y(也就是5)时,必须返回 x(也就是10)。所以 10/5=2,而 2*5=10。

但如果我们要做 10/3 呢?在其他 CPU 中,这应该是 3(忽略余数)或 3.333333333。但它不满足我们上面的方程式,所以 Cairo 这里的结果是一串奇怪的数字(实际上是2/(P+1))。

1206167596222043737899107594365023368541035738443865566657697352045290673497

为了解决这个问题,Cairo 有一个库,其中包含一组预写的 Cairo 代码,我们可以导入并直接在代码中使用。这些预写函数的一个例子是这里的 unsigned_div_rem,它可以用于安全除法,同时返回整数和除法后的剩余部分。

如果你想更深入地了解 Felts 是如何工作的,可以查看这里的文档。在了解 Felts 的一般功能后,让我们直接深入到字符串中去吧!

Strings

虽然我们称它们为字符串 (Strings),但 Cairo 目前一般不支持字符串。Cairo 支持的是我们称之为短字符串 (Short Strings) 的东西。

短字符串是指长度最多为 31 个字符的字符串,因此可以放入一个字段元素。虽然它们看起来像字符串,但它们在内部用 ASCII 码编码,因此可以用 felts 表示。

1. strings00.cairo

这个练习会返回一系列的变量,我们要指定短字符串来通过这些变量测试。

为了通过这个测试我们只需复制粘贴测试中的短字符串:

成功通过!

但这样我们就会错过一些隐含的重要信息。我们更应该做的是创建一个 Python 脚本,将 felt 转换为字符串,将十六进制转换为字符串,这样我们就可以看到短字符串的生成。

为了完成这项工作,需要:

1. 确保你的设备中安装了 python3。

2. 创建一个名为 utils.py 的文件,并在其中粘贴下面的代码。

MAX_LEN_FELT = 31

def str_to_felt(text):
if len(text) > MAX_LEN_FELT:
raise Exception("Text length too long to convert to felt.")
return int.from_bytes(text.encode(), "big")

def felt_to_str(felt):
length = (felt.bit_length() + 7) // 8
return felt.to_bytes(length, byteorder="big").decode("utf-8")

def str_to_felt_array(text):
return [str_to_felt(text[i:i+MAX_LEN_FELT]) for i in range(0, len(text), MAX_LEN_FELT)]

def uint256_to_int(uint256):
return uint256[0] + uint256[1]2*128

def uint256(val):
return (val & 2128-1, (val & (2256-2**128)) >> 128)

def hex_to_felt(val):
return int(val, 16)

打开终端运行以下命令:

python3 -i utils.py

终端应该这样显示:

接着我们尝试将 felt 转换成短字符串:

下一步将十六进制数转换成字符串,不过需要先将十六进制转换成 felt,再转换成短字符串:

很好!这证明了短字符串只是编码的 ASCII,因此可以用等价的整数和十六进制数进行互换。

2. strings01.cairo

你知道短字符串可以进行数学运算吗?它们只是被编码的 ASCII 码,因此你可以用它们做任何你可以用整数做的事情,非常神奇!

现在让我们对短字符串做一些数学运算,传递给 decode_cipher1 函数。

如果这看起来很奇怪,我希望你能忘记这些是短字符串,把它们当作数字就好,而且它也遵循四则运算:

plaintext = ciphertext + key
key = plaintext - ciphertext

已知 plaintext =‘Twinkle Twinkle Little Star’,那么:

key = 'Twinkle Twinkle Little Star' - ciphertext

类似的在 decode_cipher2 函数中,我们需要求解 ciphertext:

已知 plaintext = ‘Magic Starknet Money’,根据四则运算求解:

plaintext = 1337 * ciphertext + 0xc0de
ciphertext = (plaintext - 0xc0de) / 1337

OK!通过测试!

最后

恭喜你在成为 Cairo 专家的道路上取得了重大进展!你可以继续尝试 Starklings 教程的其他部分,期待我们的下一节课。

下篇文章,我们将学习数据存储。如果觉得本教程对你有帮助,转发分享给其他人吧~

The article has been posted for too long and comments have been automatically closed.