【首杀达成】Nervos Script 初体验

【首杀达成】Nervos Script 初体验

起因

一直很好奇 Nervos 的 Script 到底是怎么运行的,也想了解CKB的 Risc-V 的神奇之处,想自己亲手体验下,但是目前还没找到这方面的文档,我们就打算把这实践当做一个CKB的高难度的副本,来做一次开荒抢首杀的体验~

合约编写

理论上,CKB底层是Risc-V,任何可以编译的语言都可以使用,这里我们使用了C来写一个简单的Demo:

int main(int argc, char* argv[])
{
  if (argc == 3) {
    return -2;
  } else if (argc == 5 ) {
   return -3;
  } else {
   return 0;
  }
}

简单描述下,合约接受参数,如果参数数量 = 3 ,就返回-2,如果参数数量等于5,就返回-3,其他任意参数都可以返回0.

合约使用了riscv-tools编译,编译之后为6.1KB,已知1CKB = 1Bytes…所以我们大概需要6100CKB 来存储这个合约… (貌似有点大…)

本来挖到了2个块一共3800CKB…然后发现钱不够…也再挖不出了…就默默寻求场外帮助了…丹妞赞助了1100WCKB…(如果是主网Token多好…)

合约部署

有钱了做事情就有底气了…(我要打10个!)

接下来就需要把编译好的合约部署到网络里。首先读取这个二进制文件,转成16进制,然后构造一笔交易,塞到Output 的 Data里面去,效果如下:

交易TX

这笔交易我们构造了一个1100W的Cell空间,有钱就是NB!

合约调用

接下来我们构造了一笔交易,将这个 Cell 空间 作为Input,分成了5个Output,也就是创建了5个新的Cell,这5个Cell的 LockScriptCodehash都引用了上面部署的Data的Hash, 调用了上面Data的代码;args分别给了0-4个参数,来校验能不能正确解锁。

交易TX

知识点:VM在尝试解锁的时候,会默认帮我带一个参数进去,所以这5个Cell的参数个数分别是:1-5,所以我应该是可以解锁1,2,4个Cell的…另外…3个Cell 任何人都能解锁…他不会验证私钥的…

合约验证

现在我们尝试解锁第1个Cell,把他们作为Input!

当当当~成功了!入链了!

交易TX

接着我们尝试解锁第3个Cell~

这时候报错了:

Error: {"code":-3,"message":"InvalidTx(ScriptFailure(ValidationFailure(-3)))"}

说明解锁失败~我们的代码生效了!

到此,合约调用和验证的完整流程结束撒花~~

最后

最后附上吐槽和总结…

这次的首杀过程中,Nervos的VM的灵活性带给我们无限的可能,我们可以更加灵活的创造,不受VM的限制。

但是…这种灵活性会给安全性带来一系列的挑战,所以开发者需要更谨慎的开发,避免出现风险。

彩蛋环节

我们留了2个 Cell 未解锁,如果你能成功解锁并留言TX的话,我个人赠送1个木猿~一共2枚~

一起来玩吧~

20 Likes

:+1: 橙哥的 first blood

恭喜橘哥拿到首杀,牛皮牛皮 :+1:

那个 6K 的尺寸是 gcc 默认配置的坑。其实可以压缩:

$ cat m.c
int main(int argc, char* argv[])
{
  if (argc == 3) {
return -2;
  } else if (argc == 5 ) {
return -3;
  } else {
return 0;
  }
}

void _start(int argc, char* argv[])
{
  register long a0 asm("a0") = main(argc, argv);
  register long syscall_id asm("a7") = 93;

  asm volatile ("scall" : "+r"(a0) : "r"(syscall_id));
}
$ riscv64-unknown-elf-gcc -nostdlib -nostartfiles -Os m.c -o m -Wl,-static -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,-s
$ ls -l m
-rwxrwxr-x 1 ubuntu 576 Jul  9 05:46 m*
$ riscv64-unknown-elf-strip -R .comment -R .riscv.attributes -R .shstrtab m -o m_strip                                                 
$ ls -l m_strip
-rwxrwxr-x 1 ubuntu 360 Jul  9 05:46 m_strip*

360 字节里实际的代码只有 30 bytes,剩下的基本上就是 ELF 本身的开销了。

9 Likes

永远对编译保持敬畏之心…:mask:

0xb3ee0463e22592837e6ce6f7d1171265c782f826df23dd70cb53b724082df817

@Orange 下次吃饭带上木猿 :wink:

3 Likes

世界FD

向大佬致敬!!牛

刚点了一下交易hash,已经被测试网络清除了。说下解锁思路吧,请橙哥指正。
1、demo代码检查的是输入参数数量,如果为3和5个参数,则不能解锁,其他个数都能解锁。
2、参数由 args in script + args in inputs + witness三部分组成,第一和三参数数量是固定的(共1-5)。
3、改变args in inputs 数量,避开总数3和5,即可解锁。

有个疑问,文中解锁第3个cell时,error返回-3。按照C代码不应该是返回-2吗?测试网被清除了,没法验证了。

我也成功部署合约和引用了! !不太容易啊:see_no_evil:
感谢橘哥的这篇分享! !

2 Likes

膜拜xuejie大神