首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Bitcoin 序列化库使用

bitcoin 的序列化功能主要实现在 serialize.h 文件,整个代码主要是围绕 stream

和参与序列化反序列化的类型 T 展开。

stream 这个模板形参表达具有 read(char, size_t) 和 write(char, size_t) 方法的对象, 类似 golang 的 io.reader 和 io.writer。

简单的使用例子:

需要在用户的自定义类型内部 添加ADD_SERIALIZE_METHODS;调用, 宏展开后:

这个宏为用户自定义类型添加了两个成员函数:SerializeUnserialize, 它们内部调用需要用户自定义的模板成员函数SerializationOp, 在SerializationOp函数内部, 主要使用READWRITEREADWRITEMANY宏,完成对自定义类型每个数据成员的序列化与反序列化。

这里SerReadWrite 和 SerReadWriteMany 各自有两个overload 实现, 区别是末尾分别传入了不同的类型CSerActionSerializeCSerActionUnserialize, 而且 形参 ser_action 根本没有在内部使用, 查阅了相关资料, 这里使用了c++ 泛型编程常用的一种模式:

tag dispatch 技术, 另一个解释,

通过携带不同的类型,在编译时选择不同的overload 实现, CSerActionSerialize 对应序列化的实现, CSerActionUnserialize 对应反序列化的实现。

SerializeManySerializeMany是通过变长模板 parameter pack 展开技术来实现, 以SerializeMany为例子:

SerializeMany有三个 overload 实现, 假设从上倒下,分别编号为 1、 2、3; 当我们传入两个以上的实参是, 编译器选择版本 3,版本 3 内部从 parameter pack 弹出一个参数, 然后传给版本 2 调用, 剩下的参数列表,传给版本 3,递归调用, 直到 parameter pack 为空时, 选择版本 1。

迂回这么长, 最终序列化真正使用全局名称空间的Serialize来完成, 反序列化通过调用Unserialize实现。

SerializeUnserialize又有一堆的 overload 实现, bitcoin 作者实现一些常见类型的模板特化,比如,std::string, 主要设计表达脚本

的 prevector , std::vector, std::pair, std::map, std::set, std::unique_ptr, std::share_ptr , c++ 的模板匹配根据参数列表的匹配程度选择不同的实现, 优先精准匹配,最后选择类型T的成员函数实现:

在序列化 string, map, set, vector, prevector 等可能包含多元素的集合类型时, 内部会调用ReadCompactSizeWriteCompactSize读取写入紧凑编码的元素个数:

针对位宽 1,2,4,8 的基础类型,SerializeUnserialize最终调用 ser_writedata, ser_readdata8完成实现。

另外代码开始处的

作为 tag 类型, tag 对象, 主要为多个实现签名有以下形式:

的反序列化构造器做分发, 目前主要是CTransaction, CMutableTransaction 类型:

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180126G0MJ2V00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券