Mandos简单值
原文:https://docs.elrond.com/developers/mandos-reference/values-simple
我们讨论了Mandos测试的结构,你们可能已经注意到,在很多地方,价值有不同的表达方式。
VM 对它的输入和输出施加很少的限制,大多数字段被作为原始字节处理。人们所能想到的编写测试的最直接的方法是让实际的原始字节总是以一种简单的格式来表达(例如像十六进制编码)。事实上,我们第一个合约测试就是这样,但是我们很快发现准备它们花费了很长时间,甚至重构需要更长时间。因此,我们逐渐想出了越来越复杂的格式,以直观的人类可读的方式来表示值。
我们选择创建一个通用格式,在Mandos文件中随处使用。相同的格式用于表示:
- 地址,
- 余额,
- 交易和块随机数,
- 合约代码,
- 存储键和值,
- 日志标识符、主题和数据,
- 气体限制,气体成本,
- ESDT 元数据等。
这种独特的值格式的优点是,只需理解一次,就可以在任何地方使用。
Mandos值格式与Elrond序列化格式密切相关。这并非偶然,Mandos旨在使Elrond合约及其数据的交互变得容易。
例外:txId、comment、asyncCallData都是简单的字符串。asyncCallData将来可能会更改为默认值格式和/或返工。
重要
必须强调的是,无论值在Mandos中是如何表示的,与 VM 的通信总是通过原始字节完成的。当然,当Mandos值表达式和智能合约中的类型匹配时是最好的,但这不是强制的。
关于错误消息的说明:每当我们编写一个失败的测试时,Mandos都会尽最大努力将它发现的实际值从原始字节转换成更容易阅读的形式。它真的不知道该用什么格式,而是尽最大努力去寻找看似合理的东西。然而,它所有的都是一些启发,所以它并不总是正确的。它还显示原始字节,以便开发者可以研究正确的值。
关于值解析器和前缀使用的注意事项
Mandos值解释器并不复杂,大多数函数都使用简单的前缀。前缀的例子有"str:"和"u32:"。
我们用于连接的|(管道)操作符具有最高的优先级。更多信息请点击这里。
函数的参数开始于前缀之后(没有空格),结束于第一个管道(|)或字符串的末尾。
从右到左计算多个前缀,例如"keccak256:keccak256:str:abcd"将首先将"abcd"转换为字节,然后对其应用哈希函数两次。
也就是说,下面的部分将描述如何用Mandos表达不同的值类型。前缀的完整列表在本页的末尾。
空值
空字符串("")表示空字节数组。数字零也可以表示为空字节数组。其他转换成空字节数组的值是"0"和"0x"。
十六进制表示法
要提供这些值的原始十六进制表示,请使用前缀0x并在其后跟随以 16 为基数的字节。如"0x1234567890"。在0x前缀之后,应该是偶数位数,因为 2 位数= 1 字节。
例子
"0x""0x1234567890abcdef""0x0000000000000000"
独立数字表示法
无前缀数字被解释为基数为 10 的无符号数字。无符号数将以它们能够容纳的最小字节数来表示。
例子
"0""1""1000000"."255"与"0xff"相同"256"与"0x0100"相同"0"与""相同
提示
为了可读性,任何地方都允许使用数字分隔符,例如"1,000,000"。
独立有符号数字
小心
如果绝对需要,只使用带符号的数字。大有符号整数表示有一些缺陷,在与合约交互时会导致微妙和意外的问题。
有时合约争论被期望被签署。这些参数将以二进制补码的形式传输。在任何数字(基数为 10 或十六进制)前加一个负号会将它们转换成二进制补码。二进制补码根据第一位解释为正或负。
有时正数可能以“1”位开始,但却意外地被解释为负数。为了防止这种情况,我们可以在它们前面加上一个加号。几个例子应该可以使这一点更加清楚:
例子
"1"表示为"0x01",署名解释:1,一切 OK。"255"表示为"0xff",署名解读:"-1",这可能不是我们所期待的。"+255"表示为"0x00ff",有符号解释:"255".前置的零字节确保合约将其解释为正。+确保在必要时添加这些前导零。"+1"仍然表示为"0x01",这里不需要前导 0。尽管如此,如果我们知道论点预计会被签署,添加+是一个好的做法。"-1"表示为"0xff"。负数也用可能的最小字节数表示。
关于有符号数编码的更多信息,请参见大数序列化格式。
嵌套数字
每当我们在更大的结构中嵌套数字时,我们需要以某种方式编码它们的长度。否则,它们将不可能被反序列化。
Mandos帮助开发者也很容易表示嵌套数字。这些措施如下:
biguint:用于表示嵌套的 BigUint。它输出字节表示的长度,后面是大端字节表示本身。u64:u32:u16:u8:将参数解释为无符号整数,并转换为相应长度的大端字节(8/4/2/1 字节)i64:i32:i16:i8:将参数解释为带符号的 int 并转换为相应长度(8/4/2/1 字节)的 2 的补码大端字节
例子
"biguint:0"等于0x00000000"biguint:1"等于0x0000000101"biguint:256"等于0x00000020100u64:1等于0x0000000000000001i64:-1等于0xFFFFFFFFFFFFFFFFu32:1等于0x00000001u16:1等于0x0001u8:1等于0x01
嵌套项
前缀nested:决定了参数的长度。它类似于biguint:,但不期望一个数字。
例子
"nested:str:abc"等于0x00000003|str:abc"nested:0x01020304"等于0x0000000401020304
布尔
为了方便起见,Mandos提供了这两个常量:
"true"="1"="0x01""false"="0"=""。
小心
这是独立的表示。如果你的布尔值嵌入在一个结构或列表中,使用u8:0而不是false。
ASCII 字符串
表示 ASCII 字符串的首选方式是使用前缀str:。
重要
在旧的例子中,''和rust ``前缀很常见。它们相当于str:,但被认为是遗产。我们建议避免使用它们,因为它们与我们可能想要嵌入Mandos代码的语言的语法相冲突(特别是 Go 和 Markdown)。
用户地址
address:从一个单词中构造一个虚拟用户地址。
地址需要 32 字节长,所以
- 如果单词太长,它会在结尾被砍掉
- 如果单词更短,它会向右扩展
0x5f字节(字符"_")。
举例
"address:my_address"同:
"str:my_address______________________"或者"0x6d795f616464726573735f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f5f"。
智能合约地址
sc:构造一个虚拟智能合约地址。
在Elrond,智能合约地址与用户地址的格式不同——它们以 8 个字节的零开始。
重要
Mandos要求所有地址为 SC 格式的帐户必须具有非空代码。
Mandos禁止地址不是 SC 格式的账户拥有代码。
举例
"sc:my_address"同:
"0x0000000000000000|str:my_address______________"或者"0x00000000000000006d795f616464726573735f5f5f5f5f5f5f5f5f5f5f5f5f5f"。
有时,SC 地址的最后一个字节是相关的,因为它会影响合约将在哪个碎片中结束。它可以用一个散列字符#来指定,后跟十六进制的最后一个字节。
举例
"sc:my_address#a3"同:
"0x0000000000000000|str:my_address_____________|0xa3"和"0x00000000000000006d795f616464726573735f5f5f5f5f5f5f5f5f5f5f5f5fa3"。
文件内容
加载整个文件,并将整个文件的内容作为值。
文件的路径是相对于当前 mandos 文件给出的。
首先用于指定智能合约代码。但是,它可以用于在任何地方指定任何值。
举例
"file:../output/my-contract.wasm"
示例用法:
- 初始化合约代码,
- 要部署的合约代码,
- 作为间接部署参数传递给另一个合约的合约代码,
- 检查仓库里的一些合约代码,
- 任何大的争论
哈希函数
keccak256:计算参数的 Keccak256 哈希。结果总是 32 字节长。
Mandos值前缀的完整列表
前缀是:
str:从 ASCII 字符串转换成字节。address:虚拟用户地址sc:虚拟智能合约地址- 加载文件的全部内容
keccak256:计算参数的散列值u64:u32:u16:u8:将参数解释为无符号整数,并转换为相应长度的大端字节(8/4/2/1 字节)i64:i32:i16:i8:将参数解释为带符号的 int 并转换为相应长度(8/4/2/1 字节)的 2 的补码大端字节biguint:大数无符号字节长度后跟大数无符号字节本身nested:预设参数的长度
