作者: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。
像往常一样,如果你是中途加入的,建议从头开始看我们的文章。
不像 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),但 Cairo 目前一般不支持字符串。Cairo 支持的是我们称之为短字符串 (Short Strings) 的东西。
短字符串是指长度最多为 31 个字符的字符串,因此可以放入一个字段元素。虽然它们看起来像字符串,但它们在内部用 ASCII 码编码,因此可以用 felts 表示。
这个练习会返回一系列的变量,我们要指定短字符串来通过这些变量测试。
为了通过这个测试我们只需复制粘贴测试中的短字符串:
成功通过!
但这样我们就会错过一些隐含的重要信息。我们更应该做的是创建一个 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,因此可以用等价的整数和十六进制数进行互换。
你知道短字符串可以进行数学运算吗?它们只是被编码的 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 教程的其他部分,期待我们的下一节课。
下篇文章,我们将学习数据存储。如果觉得本教程对你有帮助,转发分享给其他人吧~