万向区块链技术研究报告 | EOS.IO技术调研(二)

区块链技术迅猛发展,新想法、新概念、新名词层出不穷。万向区块链因此推出“技术研究报告”专栏,定期与大家分享在区块链行业创新及热门技术方面的研究成果,带领大家第一时间研究学习新技术,紧跟技术发展趋势,探索发掘技术的应用价值。

在上周的《EOS.IO技术调研》一文中,我们分享了关于EOS.IO概况、共识、出块、验证等方面的研究结果。这周我们将带大家更加深入地了解EOS.IO账户体系、公私钥使用、存储等方面的内容。

本文作者:万向区块链通用架构技术部 吴超尘

特色

1.账户体系

  • 账户名(字符串展示, 实质会通过base32编码,转化成底层的uint64_t)

    • 普通账户:必须12位字符 ,允许字符 a~z, 1~5 和 .

    • 短账户:少于12个字符,但没有’.'的 , 需要参与系统合约拍卖

    • 带后缀账户: 字符中带’.'的,可以少于12位, 但符号的后缀必须等于创建者的名称

    • eosio创建账号只要不超过12位都行

    • 短账户拍卖机制: 每天竞拍一个, 价高者得

  • 账户权限

    • owner: 一级最高权限

    • active: 二级权限

    • 权限可分配给指定的公钥或账户名

    • 支持多签, 权重和阈值 (加权阈值多重签名 )

      • 一个账户可以定义一个阈值和一组加权的公钥,可以用其中的一个或者多个私钥进行交易签名

      • 1-of-N 多重签名 或 M-of-N 多重签名

    • 自定义权限

      /*The authority JSON object*/
      {
        "threshold"       : 100,    /*An integer that defines cumulative signature weight required for authorization*/
        "keys"            : [],     /*An array made up of individual permissions defined with an EOS PUBLIC KEY*/
        "accounts"        : []      /*An array made up of individual permissions defined with an EOS ACCOUNT*/
      }
      ​
      /*Set Permission with Key*/
      {
        "permission" : {
          "key"           : "EOS8X7Mp7apQWtL6T2sfSZzBcQNUqZB7tARFEm9gA9Tn9nbMdsvBB",
          "permission"    : "active"
        },
        weight            : 25      /*Set the weight of a signature from this permission*/
      }
      ​
      /*Set Permission with Account*/
      {
        "permission" : {
          "account"       : "sandwich",
          "permission"    : "active"
        },
        weight            : 75      /*Set the weight of a signature from this permission*/
      }

2.免费(其实会按资源收费)

  • stake 原生兑换物 获得 cpu, net

    • CPU和NET转账的时候会消耗,但是会随着时间的增长面慢慢恢复

  • 用 原生兑换物 购买 ram

    • RAM用来支付存储到内存数据库的费用

    • 但凡涉及到数据存储的操作都会消耗RAM

  • 交易时不再收取 gas 费用, 但需要拥有所需数量的资源

    • 计算量和速度需要带宽和CPU资源

    • 持久信息的存储需要RAM资源

  • token与资源使用的关系

3.多种类型的公私钥可以同时使用

  • secp256k1, secp256r1

  • YubiKey(硬件签名设备)

  • 技术实现:

    • 采用模板

    • 通过前缀区分

      constexpr const char* public_key_prefix[] = {
          "K1",
          "R1",
          "WA"
      };
      ​
      constexpr const char* private_key_prefix[] = {
          "K1",
          "R1"
      };
      ​
      constexpr const char* signature_prefix[] = {
          "K1",
          "R1",
          "WA"
      };

版本迭代

2.0

  • EOS VM:高性能 WebAssembly (WASM) 引擎

  • EOSIO Quickstart Web IDE:基于 Web 的集成开发环境,已在容器内部署一条链(单节点),且安装了智能合约编译器和EOS SDK,降低新 EOSIO 区块链开发人员的进入门槛

  • 支持加权阈值多重签名区块生产:区块生产者应该为其生产区块的核心服务提供高可用性,避免单点故障。提高区块生产者的安全性和可扩展性。

    • 原来的共识规则要求每个区块生产者只有一个区块签名密钥

    • 新的共识规则支持每个区块生产者拥有多个加密区块签名密钥

      • 允许 1个BP 拥有不共享私钥的冗余区块生产节点

      • 单个逻辑生产者可以集群化部署,避免单点故障

      • 一个区块生产者可以定义一个阈值和一组加权的公钥,用尽可能多的签名对一个块进行签名

        • 1-of-N 不能满足

        • 采用 M-of-N 方案

    • WTMSIG_BLOCK_SIGNATURES:增加了对块生产的加权阈值多重签名(WTMsig)授权的支持

      • eosio.system合同中添加了一个新操作,使块生产者候选者可以注册WTMsig块签名授权。(只能部署在已激活WTMSIG_BLOCK_SIGNATURES协议)

  • 优化:

    • net_plugin 网络代码添加了多线程支持(包括块传播、事务处理、块/事务打包/解包)

      • 可由参数 net-threads 配置(默认为2)控制net_plugin线程池工作线程数

2.1

  • 修剪上下文无关数据(context_free_data(CFD)): 节点数据瘦身, 仅适用于私有链

    Context-Free Data (CFD)

    How to prune context-free data

    上下文无关数据的一些示例包括:

    • 本质上是暂时或临时的二级区块链数据

    • 与交易消息相关的短期、非关键数据

    • 用户对存储在区块链上的在线文章的评论

    完成以下步骤以从事务中修剪上下文无关数据:

    1. 找到要从中修剪上下文无关数据的事务 ID,例如<trx_id>。交易 ID 也可以id在交易字段中找到。

    2. 找到包含交易的区块号,例如<block_num>。确保区块编号与block_num交易字段匹配。

    3. 分别找到块目录和状态历史目录(如果适用),例如<blocks_dir><state_hist_dir>

    4. eosio-blocklog按如下方式启动该实用程序:

      eosio-blocklog [--blocks-dir <blocks_dir>] [--state-history-dir <state_hist_dir>] --prune-transactions --block-num <block_num> --transaction <trx_id> [--transaction <trx_id2> ...]
    5. 如果成功,实用程序将静默返回。如果不成功,它会向stderr输出错误

    6. 请注意修剪后的交易中的以下修改字段:

      • prunable_data["prunable_data"][0]字段为1。

      • signatures字段现在包含一个空数组。

      • context_free_data字段包含一个空数组。

      • packed_context_free_data字段被删除。

    7. 包含修剪后事务的区块, 不能再进行完整的区块验证(包括交易签名验证和权限授权检查)

2.2 rc

  • 私有访问控制

    • 第一层控制“连接”访问

      • 使用 P2P over TLS

    • 第二层管理“数据”访问

      • 用特权智能合约来添加或撤销访问权限, 构成安全组

    • 启用条件:

      • 激活SECURITY_GROUP协议

    • 撤销:

      • 安全组中删除参与者意味着尽管拥有有效证书,但不能再从安全组的对等点上获取任何数据。但是,它仍然能够接收点对点 (p2p) 握手数据,例如 head number、lib number和其他非必要数据。

存储

存储和读取模式

GitHub - EOSIO/chainbase: Snapshot of Last Open Source version of Chainbase from Steem

内存映射文件

Nodeos存储交易历史和当前状态。交易历史存储在blocks.log磁盘上的文件中。当前状态通过交易的执行而改变,当前使用 chainbase 或 RocksDB 存储 (可配置)。

  • 内存块 (预生产的块)

    • pending block是一个内存块,包含处理并推送到块中的事务;这可能将成为head block(如果是区块生产者)。

  • 缓存 (区块链状态)

    • Chainbase 是一个专有的内存事务数据库,由 Block.one 构建,它使用内存映射文件(reversible_blocks)进行持久化。

      • 支持多索引 和 撤消历史记录, 是一个带版本控制的事务性数据库

      • 内存映射文件 - 通常是将物理上存在于磁盘上的文件, 映射到操作系统内核的页面缓存

        • 性能强于LevelDB

        • 默认情况下,仅在请求或程序退出时才将数据刷新到磁盘 (如果中途断电,或者程序不正常关闭, 需要reply此块日志(blocks.log)以重新生成完整的数据库状态)

    • RocksDB 是一个开源的持久键值存储。在内存中存储状态很快,但受可用 RAM 量的限制。RocksDB 利用闪存驱动器和高速磁盘驱动器等低延迟存储来持久化数据和内存缓存,以实现快速数据访问。

  • 持久化 (正式块)

    • 可逆: reversible_blocks是一个内存映射文件,包含已写入区块链但尚未变为不可逆转的块。这些区块包含有效的推送交易,这些交易仍在等待通过共识协议确认成为最终交易。头块是写入区块链的最后一个块,存储在reversible_blocks.

    • 不可逆: blocks.log是写入磁盘的块的仅附加日志,包含所有不可逆块。这些区块包含最终确认的交易。

多线程处理

节点的工作线程包括:一个主线程,一个信号处理线程和四个线程池。

  • 主线程:main函数启动线程,该线程执行完程序初始化工作后,会调用app().io_service.run(), 启动boost::asio::io_service的异步io服务,通过异步io方式完成节点块生产,交易处理等主要业务工作。

  • 信号处理线程:子线程,通过异步io服务,接收系统信号并处理。

  • 线程池,线程池启动的工作线程数可通过启动参数配置。 (默认池内2条工作线程)

    • controller线程池:异步执行块block_state创建,块中交易验证时的交易解签名计算。

      • 块交易验证时的解签名操作 (节点收到块)

      • 块状态block_state数据创建操作(两轮共识计算都在这里完成)

    • producer_plugin线程池:负责异步执行交易解签名计算。

      • 为接收到的投递交易进行异步解签名计算(在节点收到其它节点/客户端广播的交易时被调用, 提前进行验签与权限判断, 多线程并行)

      • 等待解签名计算完成,将交易投递到主线程的异步io服务中处理。

    • http_plugin线程池: RPC服务支持多线程

    • net_plugin线程池: P2P服务支持多线程

nodeos(主线程&信号处理线程) :
    ─┬─{nodeos}(controller线程池_线程1: 异步执行块block_state创建,块中交易验证时的交易解签名计算)
      ├─{nodeos}(controller线程池_线程2)
      ├─{nodeos}(producer_plugin线程池_线程1: 异步执行交易解签名计算)
      ├─{nodeos}(producer_plugin线程池_线程2)
      ├─{nodeos}(http_plugin线程池_线程1: http服务)
      ├─{nodeos}(http_plugin线程池_线程2)
      └─{nodeos}(net_plugin线程池_线程1: p2p服务)

EOS VM (WASM虚拟机)

https://github.com/EOSIO/eos-vm

智能合约编译的工具链是clang/LLVM及其C/C++编译器

已解决的问题:

  • 非确定性行为 - 确定性执行

    • 区块链上的所有程序都必须是确定性的, 比如浮点运算, 为了确保所有支持平台上的确定性浮点运算, 使用了softfloat类型, 这是 IEEE-754 浮点运算标准的软件实现

  • 无限制计算 - 限时执行

    • 确保执行不会超过为给定程序分配的 CPU 时间, 采用看门狗定时器系统

      看门狗定时器(WDT,Watch Dog Timer)是单片机的一个组成部分,它实际上是一个计数器,一般给看门狗一个数字程序开始运行后看门狗开始计数。如果程序运行正常,过一段时间CPU应发出指令让看门狗置零,重新开始计数。如果看门狗增加设定值就认为程序没有正常工作,强制整个系统复位。

  • 无限制内存分配 - 设计安全

    • 内存操作使用了保护分页机制, 不允许访问到沙盒内存之外

    • 防止堆栈溢出

    • 限制递归调用深度

  • 溢出漏洞处理

    • 可将uint类型的数据先转换成double类型的数据,然后使用EOS区块链提供Math API中的double_adddouble_mult等函数进行计算,最后将计算结果再转换成uint类型数据输出。

    • double_mult函数在进行大数相乘出现溢出的时候,会返回设定的最大值(2的63次方),不会发生溢出,可以有效避免以上智能合约漏洞。

  • 合约部署时需要指定一个账户, 一个账户只能与一个智能合约相关联,可以在同一账户上部署,更改或升级智能合约代码

EOSIO的不足之处

  • 共识模块没有插件化

  • 最终确定的时间太久(325个块, 163秒)

  • 没有像truffle一样方便的本地脚本级开发环境

  • 并行验签与鉴权,但合约事务与智能合约只能串行执行

  • P2P没有采用Gossip算法,不带自动发现与自动连接,需要手动配置对端的ip与端口

  • 对于块生产者的作恶行为没有自动的惩罚措施 (比如: 同时在两条分叉链上都生产区块的生产者, 如果没被选民发现,他就不会出局)

猜你喜欢

转载自blog.csdn.net/Venachain/article/details/122577206
今日推荐