藏川线前段

--- 摄于 2017 年 9 月 藏川线前段

前两个月,做了一些让 ckb-types 暴露接口更友好的事情,包括对 molecule 生成代码的行为优化 ,对一些数据结构增加 From trait 实现,ckb-types 以及整个 ckb 库弃用 Pack/Unpack trait 转向 From/Into trait,同时将大部分 builder 接口变成 generic 签名,这样在用户使用的时候,代码量减少,也更加易用。不过很遗憾,虽然改动已经实现完成,并且一度合入主分支,但在 0.119 发版之前,还是被 revert 了,因为 0.119 将开启 testnet 的第二次 hardfork,之后将进入 mainnet 的第二次 hardfork,在期间,用户必须强制升级依赖库,而易用性改动将带来大量的 break change,虽然我已经实现了 90% 以上代码自动修改的工具,但考虑到改动量太大,用户本身也会因为代码改动量而存疑,进而不得不将这些改动 revert 掉,等 hardfork 之后再合并回来。

当前状态

做完上面的事情之后,近一个月,我都在为 ckb on wasm 计划努力实现中,到现在,第一阶段的事情基本做完了,ckb-lightclient 已经可以彻底单独跑在浏览器网页中了,并且支持 indexdb 作为后端存储,目前实现在这个分支里,目前项目状态并没达到 production ready,想要玩的朋友,可以自己切到该分支,进入 light-client-wasm 目录进行调试,默认是实现是 dev 链,需要一些操作:

  1. 基于这个分支编译一个 ckb,创建 dev 链,然后在 ckb.toml 的 p2p listen 中增加 /ip4/127.0.0.1/tcp/8118/ws websocket 监听,并且配上 miner 信息,启动后,将该节点的监听信息包括 (peer id) 更新到 ckb-light-client/config/dev.toml 的 bootnode 上。

  2. 修改 light-client-wasm/src/lib.rs 第 41 行的内容,将它指向 ckb dev 节点的 data/specs/dev.toml 目录

  3. light-client-wasm/src/lib.rs 文件中,找到 fn get_script_example fn get_search_key_example 这两个函数,将它们的实现改成 ckb dev 链的 miner 信息

  4. 默认 js 运行的程序在 light-client-wasm/index.js 内,可以自行调整,默认示例是注册 miner script 并定时查询

  5. $ cd light-client-wasm
    $ npm install && npm run serve
    
  6. 打开 http://localhost:8080/ 开发者界面,可以看到 lightclient 正在工作

计划初期

当然,罗马不是一天建成的,在真正到达今天之前,我们也无法完全肯定 lightclient 一定能跑在 wasm 之上,一开始,我们的计划很简单:

  1. 用最简单的修改去验证,编译到 wasm 是有可行性的
  2. 然后实现一个最简单的 demo 证明必然可以实现
  3. 真正开始实现 ckb on wasm

lightclient 是一个基于 p2p 网络的应用,同时它也有持久化的需求,而目标是将 lightclient 跑在浏览器上。众所周知,浏览器对访问本地磁盘的限制是非常严格的,同时它的网络环境也比较受限,想要在上面重新实现完整的 p2p 网络是很困难的,存储也很受限,这些都需要重新调研方案,我们不可能因为需要在浏览器上执行,就将 Rocksdb wasm 化,这样工程太过浩大,不切实际。

调研 browser wasm rust 相关生态

browser

首先是存储,在浏览器上,能选的方案不多,加上有持久化和数据量需求,可选的就更少了,基本只有 opfsindexdb 两种方案,比较而言,虽然indexdb 是出了名的难用,但好歹还给了事务模型,opfs 是真的裸文件操作了,同时考虑到现在浏览器的支持程度,实际上 indexdb 的支持会更广一点(相对而言)。几乎属于没的选的选项。

wasm-rust

这里属于一言难尽的范畴,有关 wasm target 的讨论,延续了好几年,包括 WASI 支持,tokio 对 WASI 的支持,tokio 对 WASM on browser 的支持等等。rustc 最初的 target wasm32-unknown-unknown 默认实现是针对浏览器的,但并没有强调 web 端,而后续 wasm 发展出了 wasi 的 native 运行时,包括支持多线程等等操作,导致最初的 wasm32-unknown-unknown 目前处于一个尴尬的阶段,到底是单独开个 wasm-web target 还是让它继续这样,这个目前还没有定论,但毫无疑问,web 端的实现,目前只能使用这个 target 与 js/dom 交互。tokio 对 wasi 的支持,算是一种利好,至少部分东西在 wasm 全 target 通用,比如 sync mod 下的异步元语(channel/lock/permit)等等,在 rust 异步生态下,丢开 tokio 去单独实现一个 runtime 是很痛苦的一件事情。

同时,在早两年,tentacle 也已经实现了 web 端 websocket 的适配,网络通信上几乎已经是没有什么大问题了。剩下的就是 lightclient 自身的代码以及 ckb 相关依赖的 wasm 化问题。

验证

基于调研的情况,我们初步决定,从底层依赖开始,一点点向上将依赖库一步步进行 wasm 化,同时,由于处于项目验证初期,需要快速验证方案是否有可行性,我们并不打算在 demo 阶段引入持久化存储,而是使用 BtreeMap 作为替换方案进行 demo 验证,这样就能绕开一大部分问题,尽快验证可行性。

这个分支就是基于 BtreeMap 的 demo 实现,只有几个核心 api 实现,但已经完成了 lightclient 的绝大多数核心功能,有朋友想玩也可以去尝试一下,操作步骤和上面说的一样,就是代码比较 dirty,但 work。

最后

这一篇就先说这么多,下一篇应该是一些需要注意的地方,再下一篇就是 indexdb 爬坑日记了。

评论区

加载更多

登录后评论