教你用Dfinity实现一个开放式二维码服务

前言
Dfinity 的互联网计算机是一个安全的网络协议,它允许我们将代码直接当作服务部署在网络中,这些软件就像在本地一样,被运行在这台无缝共享的超级计算机上。
想象一下,就好像你把代码传上到一个超级 Github 上,不用管操作系统等等一些复杂度,后端就可以永不宕机的提供服务了!当然这些都需要用 Dfinity 的 token 来计价。
 
接下来将演示如何在互联网上建立一个永久的微服务。
实现目标
准备实现一些简单的服务,但也得展示互联网计算机的特性。所以只做“hello world”或简单算式是远远不够的。我们需要去实现一些真正有用,并能集成到现有的服务里的东西。
所以深思熟虑之后,我最终决定写一个二维码生成服务,用它来显示加密货币钱包的地址。
如何搭建
互联网计算机上的程序运行在 WebAssembly 虚拟机中,因此要构建微服务,只需要写好代码后编译成 WebAssembly 运行即可。
C 和 Rust 里面都有现成的库可以产生二维码,只需要再成 WebAssembly 运行即可。
 
虽然这样比较快,但是这里想做点有趣的尝试,所以决定通过 Motoko 开发。
什么是 Motoko
Motoko 是由 WebAssembly 标准的原作者设计的一门高级语言。它在语法上类似于 Swift 和 unique,独特之处在于它为互联网计算机上的特性提供了很好的支持。
 
只需下载并安装互联网计算机的 SDK,就可以获得 Motoko 的最新版本:
$ wget https://sdk.dfinity.org/install.sh
$ yes Y | sh install.sh
预备工作
在用 Motoko 为微服务定义接口之前,先回顾一下二维码的标准,构成二维码的相关组件如下: 

教你用Dfinity实现一个开放式二维码服务

这些组件所需的相关参数包括:版本号(1到40)、LMQH的四种纠错级别(分别表示数据丢失容忍度为7%、15%、25%和30%)和编码方案(可以是数字、字母数字、八位或汉字)。
定义接口
将二维码的组件类型转换为 Motoko 的类型:
public type Version = { #Version : Nat };    
public type ErrorCorrection = { #L; #M; #Q; #H };
public type Mode = { #Alphanumeric; #EightBit; #Kanji; #Numeric };
public type Matrix = { #Matrix : [[Bool]] };
 
我们可以使用这些类型,在 Motoko 中定义一个函数来生成二维码:
/**
 * Encodes the input text according to the QR code specification or
 * returns null if the input text is invalid for the given mode.
 */
public func encode(
  version : Version,       // Version number. 
  level : ErrorCorrection, // Error correction level.
  mode : Mode,             // Encoding scheme.
  input : Text             // Input text.
) : async ?Matrix { .. };
 
将以上代码封装在 Motoko actor 声明中定义接口。
实现
我把实现代码放到了 GitHub 上,总共2000多行代码,需要十几个模块支持。可以 git 下来后在 Visual Studio 中打开,Visual Studio 上有一个可以高亮 Motoko 语法的插件,比较方便。
$ git clone https://github.com/enzoh/qr
$ code qr
 
这个二维码服务在很大程度上依赖于 Motoko 的标准代码库。之前我一直不感冒,用了才知道, Motoko 已经足够成熟了,并且功能强大。Motoko的 API 和 Rust 与 SML 提供的很相似,所以如果你很熟悉这些语言,那用 Motoko 的时候基本不需要查阅任何的文档。虽然文档网站仍在开发中,然而,通过直接在 Visual Studio 中打开标准库,始终可以找到最新的详细信息。
 
$ code $HOME/.cache/dfinity/versions/$DFX_VERSION/stdlib
演示
启动本地互联网计算机节点:
$ dfx start
 
在另一个窗口中执行以下命令
$ dfx build
$ dfx canister install –all
$ dfx canister call demo encode \
$   ‘(variant{Version=2}, variant{M}, variant{Alphanumeric}, “HTTPS://SDK.DFINITY.ORG”)’ \
$   | sed ‘s/[(“)]//g’ \
$   | sed ‘s/#/█/g’
 
结果就输出来了:

教你用Dfinity实现一个开放式二维码服务