Cairo 之旅 III:通过 Starkling 学习 Felt 和 String

作者:Darington Nnam
原文:Journey through Cairo III — A deep dive into Strings and Felts with Starkling
翻译:Louis Wang
校对:「StarkNet 中文社区」

欢迎来到我们 「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 教程的其他部分,期待我们的下一节课。

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

Subscribe to Starknet 中文
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.