GSoC 申请将在 UTC 时间 4月19日结束,如果你对 WasmEdge 的项目感兴趣,欢迎申请。这篇文章将为大家介绍 sonder-joker 通过 LFX Mentorship 为 WasmEdge 实现标准 WebAssembly 的经历。
我是 sonder-joker,一名软件工程专业的本科生,喜欢开源、软件基础架构和具有挑战性的工作。去年秋季,我申请了 2021 年秋季的 WasmEdge CNCF LFX Mentorship:在 WasmEdge 中实现 WASI-Crypto 提案。
在 WasmEdge 实现 Wasi-crypto 的代码已经基本完成,我想把 LFX mentorship 的经历和大家分享一下。希望这篇文章能为想要加入开源项目并为之做出贡献的人提供一些帮助。我会在这篇文章介绍 LFX mentorship 是如何工作的,我是如何完成任务,以及我在这其中的所思所想。
我之所以选择这个项目,是因为我想参与一个具有挑战的开源项目的开发,而虚拟机正是我感兴趣的一个领域。通过 LFX Mentorship 来申请加入一个开源项目正是开始做开源贡献的好选择。
在 LFX Mentorship 之前,我在密码学相关领域的知识为零。在参与了 wasi-crypto 的实现之后,我了解了不少关于密码学编程的知识。通过 LFX Mentorship,我将成为 WasmEdge Runtime 项目的贡献者(代码还没正式 merge)。更进一步,我还成为了 wasi-crypto 项目的 collaborator!
wasi-crypto 是一组可移植的、模块化的、运行时独立的 WebAssembly 原生的 API。在我们可以在保留 WebAssembly sandbox 特性的同时使用 wasi-crypto 来执行加密操作。
WasmEdge 提供了一个实验性的 WASI Socket API,用于支持 Wasm 中的 Berkeley Sockets API。 WasmEdge 提供了一种打开新 socket、侦听现有 socket 以及发送和接收数据的新方法。
在此之上,我们可以支持更多相关功能(例如 SSL)。要实现此功能,一种可选的方法是将 OpenSSL 库编译为 Wasm 并将其链接为库。但是,性能可能并不好,因为所有计算都是在 Wasm 级别完成的。而另一种可选的方法则是将 OpenSSL 库包装到 Wasm 的 external function 中,例如,将openssl 中的 ssl_connect
绑定到 (import "OpenSSL" "ssl_connect" .. . . )
。
然而,实现这个功能并不简单。为了简化工作量,我们决定先实现 WASI-crypto 提案,然后再通过这个提案来完成以上事情。
wasi-crypto 是一个比较复杂的项目。但是,我们可以先梳理整个工作,然后分解为几个子任务。我根据 wasi-crypto 提案的模块 和 WasmEdge 的需求对其进行了划分。
显然,从头开始实现加密库是不现实的,没有必要重新发明轮子。C/C++ 中有许多与加密相关的库,我们很容易就能找到一个开源加密库作为我们的底层实现。经过挑选和研究,我们选择了OpenSSL。
原因如下:
OpenSSL 是最著名的加密库,它足够强大和安全。大多数 Linux 发行版都预装了 OpenSSL 包。在大多数边缘设备上运行 Linux 系统和 WasmEdge 的情况下,使用 OpenSSL 库可以使 WasmEdge 的大小保持较小。而且,OpenSSL 的开源许可证不影响 WasmEdge 的开源许可证,OpenSSL 由两部分组成:libssl 和 libcrypto,其中的 libssl 提供了我们需要的算法。
当然,也有缺点。OpenSSL 的 API 设计对开发人员并不友好,这在 3.0 中已进行了改进。
此外,OpenSSL 3.0 的性能并不令太人满意。
因此,在与我的导师 Hydai(WasmEdge 的核心维护者)讨论后,我们选择了 OpenSSL v1.1.1。
我每周会与 WasmEdge 的 mentor Hydai 开会,讨论进展和下一步安排。每次会议结束后,我都会记录当前的进度,并将它们与最初的安排进行比较,看看我是否能够按时完成工作。在实施 wasi-crypto 过程中,我的计划发生了多次更改,但我认为这是不可避免的——动态调整任务的安排十分重要。
为了在 WasmEdge 中实现 wasi-crypto,我反复阅读了很多次规范。在此过程中,我发现了 wasi-crypto 规范中的一些问题,包括typo、示例和规范不一致的一些地方以及一些标准未覆盖的地方。
所以我在 wasi-crypto 创建了一些 issue 与社区沟通,而对于已经确定的问题,我会通过 pull request 来修复它们。在这个过程中,我收到了来自 wasi-cryotp 维护者的积极响应。直到某天,我收到为 wasi-crypto 编写测试的邀请,并且受邀成为一名 maintainer 以进一步改进 wasi-crypto。这真的很令人惊讶——开源不需要你特别的专业,你只需要保持热情。从简单的 typo 开始,然后更多地参与并提出一些示例/标准上的建议,社区将永远欢迎你并帮助你纠正错误。
在项目开始时,由于我对于 wasi-crypto 的了解还不够深入,经常有一些大规模的改动。这些改动有时候毫无相关性,但是粘连在一起,我提交了很多没有意义的 git commit,这让 reviewer 感到困惑。从这件事情,我学到的教训是,在编写代码之前,必须要建立起一个合适的模型并弄清楚如何设计,更好的做法是什么。否则,我们可能会在后面的阶段浪费大量的时间。
在大多数开源项目中,测试是必不可少的。例如,WasmEdge 使用测试覆盖率作为代码质量评估的关键指标。
wasi-crypto 有一个定义良好的类 POSIX 接口,并且很容易编写单元测试。但是我前期只写了几个简单的单元测试,显然还不够。
因此当我写了更多的单元测试来达成要求的覆盖率时,我发现了不少实现上的问题。藉此,我了解到单元测试和 TDD(Test-Driven Development)的必要性。
对于目前的设计,仍然有很多可以优化的的地方,我会去尝试重构以获得更好的性能。
另外,尽管我已经在 host side 做了很多测试,但 client side 的测试也是必不可少的。而且 wasi-crytpo 提案目前并没有通用的 .wasm
测试。所以我会将在 WasmEdge 中添加 .wasm
的测试,并且将其推进到 wasi-crypto 提案之中。
因为既要照顾到自己的学业,也要同时完成项目,以之前从未学习过密码学的基础,在为期 3 个月的指导期间内我并没有完成所有任务。但我仍然在努力在 WasmEdge 中实现 wasi-crypto - 我相信在社区的帮助下我将能够完成这一目标。现在这一工作即将到达尾声。
参与开源项目, 尤其是基础设施工作方面的开发是一种令人兴奋的体验,我希望这篇文章可以帮助那些想要申请类似 LFX MentorShip 项目的新开发者,比如正在进行中的 GSoC 以及即将开始的开源之夏。对于想要参与开源项目并尝试实现一些有意思的工作的每个人来说,这种社区项目是很好的第一步。
谷歌编程之夏即将开启,快来申请开源任务吧