优链的合约优化问题
现状 - Plugin 机制
Go 语言在加载 .so 格式的模块时,会对 调用方 和 模块 共同依赖的包做校验。
单个插件加载 - 前提说明
调用方和模块的二进制文件都会记录依赖包的hash 值 abc。在
调用方加载模块时,如果 调用方记录的共同依赖的包 hash 和 模块记录的共同依赖的包 hash 不一致,会发生错误。也就是要保证共同依赖的包不能有变动。
多个插件加载 - 实际情况
调用方也就是 优链节点 一旦上线,后续注册的模块.so必须保证 编译环境共同依赖的包 和当时上线时完全一致。(如果修改节点,将不兼容旧合约)编译
调用方和模块也就是编译 节点 和 合约 的 环境变量 GOPATH 必须一致。(当然包括 Go语言版本)
核心问题
对于希望 长期 稳定运行的系统,如何做到 具备兼容能力 的 功能升级。
问题根本原因
Go 语言在处理 Plugin 机制时偷了个大懒,在编译前就生硬地对 代码文件引入的依赖 做 文件级别的 hash 校验。不是对编译后的代码内容进行分析,所以也就无法针对函数级别的粒度,提供保持一致或者增量升级的能力。
总的来说,Go 语言相关机制不健全。
改进方式
现状
Go语言直接调用合约代码,函数的参数传递中包含高度定制化的结构体。
改进方式 1
实现方式:
- 不修改原有的合约机制,在合约中使用 虚拟机或者运行时环境 加载外部代码。
- 实现成本相对低
存在问题:
二层合约代码安全性不可控。
如何多方确认
保证代码完整性防篡改
在防篡改的前提下,可以升级(热部署)
改进方式 2
实现方式:
在原有合约机制的基础上,增加其他机制的支持
实现成本非常高
需要将 原有结构体格式 改为 通用数据格式