Yuque Archive
工作资料 - 新

优链的合约优化问题

现状 - Plugin 机制

Go 语言在加载 .so 格式的模块时,会对 调用方模块 共同依赖的包做校验。

单个插件加载 - 前提说明

  1. 调用方模块 的二进制文件都会记录依赖包的 hash 值 abc

  2. 调用方 加载 模块 时,如果 调用方记录的共同依赖的包 hash 和 模块记录的共同依赖的包 hash 不一致,会发生错误。也就是要保证共同依赖的包不能有变动。

多个插件加载 - 实际情况

  1. 调用方 也就是 优链节点 一旦上线,后续注册的 模块.so 必须保证 编译环境共同依赖的包 和当时上线时完全一致。(如果修改节点,将不兼容旧合约)

  2. 编译 调用方模块 也就是编译 节点合约 的 环境变量 GOPATH 必须一致。(当然包括 Go语言版本)

核心问题

对于希望 长期 稳定运行的系统,如何做到 具备兼容能力 的 功能升级。

问题根本原因

Go 语言在处理 Plugin 机制时偷了个大懒,在编译前就生硬地对 代码文件引入的依赖 做 文件级别的 hash 校验。不是对编译后的代码内容进行分析,所以也就无法针对函数级别的粒度,提供保持一致或者增量升级的能力。

总的来说,Go 语言相关机制不健全。

改进方式

现状

Go语言直接调用合约代码,函数的参数传递中包含高度定制化的结构体。

改进方式 1

实现方式

  1. 不修改原有的合约机制,在合约中使用 虚拟机或者运行时环境 加载外部代码。
  2. 实现成本相对低

存在问题

  1. 二层合约代码安全性不可控。

  2. 如何多方确认

  3. 保证代码完整性防篡改

  4. 在防篡改的前提下,可以升级(热部署)

改进方式 2

实现方式

  1. 在原有合约机制的基础上,增加其他机制的支持

  2. 实现成本非常高

  3. 需要将 原有结构体格式 改为 通用数据格式