【区块链】查询-vChain

论文主要贡献

vChain框架:减轻用户的存储和查询计算成本,并使用可验证的查询来保证结果的完整性

  • 基于累加器的可验证数据结构(ADS: authenticated data structure):支持对任意查询属性进行动态聚合,实现可验证布尔范围查询

  • 两个索引:聚合块间和块内的数据,提供高效查询和验证

  • 倒排前缀树结构:加速大量订阅查询的处理

Introduction

fig1

分为全节点(普通全节点和挖矿节点)和轻节点。轻节点向全节点发送查询请求Q,全节点向轻节点提供查询结果集合R和验证对象VO(verification object),其中VO是由SP构造的用于让轻节点验证查询结果的完整性和健全性的验证对象。

ADS数据结构由现有的外包数据库可验证查询技术而来,进行的变化和调整如下:

  • 不可篡改性:

    • 外包数据库:由数据所有者私钥签名来保障
    • 区块链:不存在数据所有者
  • 数据集合大小:

    • 外包数据库:数据集合大小有限
    • 区块链:数据量无限大
  • 生成:

    • 外包数据库:需要即可创建生成
    • 区块链:由于数据存储的持久性,需要一个万能的ADS来满足查询需求

问题描述及模型

模型描述

fig2

区块链中保存的数据看作一个集合 $\{o_1,o_2,…,o_n\}$,其中 $o_i=$ ,$t_i$ 代表timestamp,$V_i$ 表示一个或多个数值属性的多维向量,$W_i$ 是集值属性set-valued attribute,轻节点提交查询q,全节点返回结果集合和验证VO(verification object)。

针对两种布尔范围查询

时间序列窗口查询

用户搜索在某个时间段内出现的记录

一条查询可以表示如下

其中 $t_s t_e$ 分别是时间段的开始和结束时间,$[\alpha, \beta]$ 表示数字属性的多维范围选择谓词(人话:n个属性值的数值范围),$\Upsilon$ 表示集值属性值的单调布尔函数,可以看作是一个合取范式

返回 $O$ 要满足 $\{o_i = ⟨t_i,V_i,W_i⟩ | t_i \in [t_s, t_e]\land Vi \in [\alpha, \beta] \land \Upsilon(W_i) = 1\}$

订阅查询

用户注册自己感兴趣的查询内容,SP为用户提供结果(新块确认完成后推送新信息以及验证对象)

一条查询可以表示如下

SP持续返回查询结果 $O$ 直到查询被用户取消,满足 $\{o_i = ⟨t_i,V_i,W_i⟩ | Vi \in [\alpha, \beta] \land \Upsilon(W_i) = 1\}$

需要解决的问题:SP不可信

解决方法:让SP证明查询结果的完整性。

在查询处理过程中,让SP检查嵌入在链上的ADS,构建一个VO,包含结果的验证信息。VO连同结果一起返回给user。user可以利用VO确定查询结果的正确性和完整性。

密码学知识

哈希加密函数,双线性配对(Bilinear Pairing),多重集(Multiset),加密多重集累加器。

加密多重集累加器

一个函数acc(·),以抗碰撞方式将多重集映射到循环乘法群中

基本解决方案

选择传统的MHT作为ADS的缺点:

  • 为了支持涉及任意属性集的查询,需要为每个块构造指数数量的MHT
  • 不适用于集值属性
  • 不同块的MHT无法有效聚合,使其无法进行块间优化

为了克服这些缺点,提出了基于新的基于累加器的ADS方案的新型身份验证技术,该方案将数值属性转换为集值属性,并支持对任意查询属性进行动态聚合。

ADS的生成

在区块中加入新属性AttDigest,用ObjectHash来表示原来的MerkleRoot

fig3

使用多重集累加器作为AttDigest:

集值属性布尔查询的可验证查询过程

查询条件$“Sedan” \land (“Benz” \vee “BMW”)$

SP可以应用$ProveDisjoint(\{“Van “,” Benz”\},\{ “ Sedan “ \},pk)$ 生成一个不相交的证明$\pi$作为不匹配对象的VO(验证对象)。

相应地,用户可以从区块头中检索$AttDigest_i= acc(\{“Van”,“Benz”\})$,并使用$VerifyDisjoint(AttDigesti,acc(\{“Sedan”\}),π,pk)$来验证不匹配。

多重集累加器的结构

基于双线性配对和q-SDH假设

公钥长度和最大多重集的大小成线性关系

基于双线性配对和q-DHE假设

允许聚合多个累加值或多个不相交的证明

公钥长度和系统中可能的最大属性值的大小成线性关系

扩展到范围查询

需要将数值属性转化为集值属性:

  • 将数值改为二进制后再改为前缀集合

    • 例如4表示为$trans(4)=\{1,10,100\}$,*为通配符
    • 向量 $(4,2)$ 表示为 $\{1∗_1, 10∗_1, 100_1, 0∗_2, 01∗_2, 010_2\}$
  • 将范围查询条件转化为布尔查询

    • $[0,6]$ 转化为 $\{ 0 \vee 10 \vee 110 \}$

      fig4

    • 查找某个取值是否在查找范围内:判断二者交集是否为空,为空即不在范围内

批量验证

块内索引

fig5

最大化每个节点下对象的相似性:计算Jaccard相似系数,在构造Merkle Tree时将较为相似的节点作为左右叶子节点进行结合,构造一棵二叉平衡树

非叶子节点的各个属性值赋值如下:

  • $W_n=W_{nl}\cup W_{nr}$
  • $AttDigest_n=acc(W_n)$
  • $hash_n=hash(hash(hash_{nl}|hash_{nr})|AttDigest_n)$

块间索引

fig6

使用跳表,其搜索、删除和添加的平均时间复杂度是$O(logn)$

按照指数来建立索引

在块属性中添加$SkipListRoot$用于保存块间索引内容:

  • $SkipListRoot=hash(hash_{L_{2}}|hash_{L_{4}}|hash_{L_{8}}|…)$

  • $hash_{L_{k}}=hash(PreSkippedHash_{L_{k}}|AttDigest_{L_{k}})$

  • $AttDigest_{L_k}= acc(W_{L_k})$

  • $W_{L_k}=\sum^i_{j=i-k+1}W_j$

在线批量验证

使用累加器construction2中的sum函数,将以相同理由mismatch的结果聚合起来

fig7

可验证订阅查询

由查询用户注册,并持续处理,直到取消注册为止。当SP看到新确认的区块时,需要将结果与VO一起发布给注册用户。

主要难点在于,需要在新的区块到达后同时进行大量的查询,生成很多结果。此时为了节约查询的时间,可以暂时推迟数据的不匹配验证。

索引

查询处理的主要开销来自SP对不匹配对象的证明的生成
不同的订阅查询可能有相同的不匹配原因,这类查询可以共享不匹配证明

结构

使用倒排前缀树结构:TP-Tree,由以下部分组成

  • 前缀树结构
  • 倒排文件:前缀树的每个节点都与一个倒排文件相关联,该文件是基于该节点下索引的订阅查询而构建的
    • 数值范围文件RCIF(Range Condition Inverted File),用于查询数值范围是否匹配,包含以下内容
      • 查询q
      • 覆盖类型:q全部/部分 覆盖了所有节点的数值范围$S$
    • 布尔函数文件BCIF(Boolean Condition Inverted File),只记录全部覆盖了节点空间的查询,用于检查布尔集合是否匹配,包含以下内容
      • 查询条件集合
      • 相对应的查询q

fig8

IP-Tree由SP自上而下的构建:

  • 创建根节点,把所有查询作为部分覆盖加入节点
  • 将根节点拆分成四个等大的子结点
  • 对于子结点:
    • 如果某个数值范围查询部分或全部覆盖了节点空间,则加入到RCIF中
    • 如果某个布尔集合全部覆盖了该结点的空间,则加入到BCIF中
    • 出现部分覆盖的情况时,进一步拆分当前结点
  • 当所有叶子节点中都没有部分覆盖的查询时,不需要再拆分节点
  • 注意当树变得过于深,超过某一个给定阈值后,将会变成没有TP-Tree的情况

查询过程

查询—>树的遍历

当新的数据对象o被添加后:

  • 从根节点开始自上而下开始遍历

  • 到达节点$n_q$后:

    • 如果RCIF中的某条查询范围达到了全覆盖
      • 符合BCIF中的查询条件,则将对象o添加到该查询的结果中
      • 不符合BCIF中的查询条件,则调用ProveDisjoint(·)函数并且将不匹配证明添加到结果中
    • 如果RCIF中的某条查询范围是部分覆盖
      • 什么都不做

将订阅查询的索引扩展到块内索引

依然以之前的查询过程进行查询,但是需要一直遍历到叶子节点

延迟验证

延迟不匹配的验证以减少查询验证的成本

采取的做法:当有符合条件的结果时,或距离上次返回结果已经过了一段时间(阈值)时,返回不匹配结果。此时VO应该证明当前数据对象是匹配的,并且该结果和上一次结果之间的所有查询都不匹配

如果等待有结果产生后再使用时间窗口查询生成证明,会造成:无法共享不匹配证明;用户将需要同时验证很多证明。

因此使用块间索引来生成不匹配证明。但是新块还不可用,不知道未来的数据对象是否共享同一个不匹配证明

使用一个栈来保存不匹配的块。首先找到跳表的最大跳过距离$L_i$,其中跳过的块覆盖了栈顶的m个元素,区块的AttDigest被替代为$AttDigest_{L_i}$,使用ProofSum函数来聚合不匹配证明,这样当找到匹配结果后,SP不需要从头聚合不匹配证明。

Author: iwannaeat
Link: https://iwannaeat.github.io/2022/09/17/【区块链】查询-vChain/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.