zoukankan      html  css  js  c++  java
  • 区块链存证的技术实现

    众所周知,区块链具有时间戳特性和不可篡改特性,这两个特性就用于数据的存证,这是区块链诞生除了CryptoCurrency之外,人们最容易想到的应用。区块链存证的技术原理很简单,在用户签名和发送交易前,用户将要存证的数据(如果数据量小,而且不用担心隐私问题,可以直接存储正文,如果数据量大,则计算该数据的Hash)附加到交易中,然后再进行签名广播。记账节点在验证了交易的合法性后,将该交易打包到区块中,并在区块中附加上时间戳信息。

    存证的区块链写入

    目前主流的区块链都具有将数据附加到交易中的特性。以比特币为例,其支持在Output中使用OP_RETURN来存放数据,不过由于比特币网络比较拥堵,所以比特币网络接受OP_RETURN存放的数据很有限,最多存放40个字节,后来又有版本调整,改成了80字节,总之是非常非常小,不过用于存放一个Hash值32字节还是足够了。以太坊是在交易中支持inputdata字段,如果以太坊交易的接受地址是外部地址,那么inputdata就是用于存证的数据内容,该数据内容就可以很长,而不是80字节的限制,可以是一整篇文章、公开信等。PalletOne的交易是由不同类型的Message组成,PaymentPayload负责Token的流转,DataPayload负责数据存放。当我们需要在PalletOne存证时,只需要创建具有PaymentPayload和DataPayload的交易,然后进行签名,广播。

    使用区块链进行数据存证,我们可以得到以下几点共识:

    1. 在存证所在区块的时间戳之前,该数据已经存在(区块的时间戳特性)
    2. 拿到数据的内容,可以判断该数据在存证后是否更改(Hash函数的特性)
    3. 存证数据是由持有某私钥的人存证的,该人不可抵赖,别人也不可冒充(区块链的不可篡改和数字签名的特性)

    虽然区块链存证具有以上的优势,但是比特币、以太坊等毕竟不是为数据存证而设计的链,所以在存证上只有一个字段,对索引、扩展、引用的支持都没有,需要第三方应用来实现。

    存证安全性的加强

    基于区块链的存证,主要是利用了区块链的不可篡改特性和时间戳特性,但是我们怎么能保证区块链的不可篡改和时间戳是正确的呢?

    区块链的二次存证

    如果存证数据是保存在一个私有链、联盟链或者是DPOS公链上,那么从理论上来说,该区块链没有完全的去中心化,一旦联合作恶,仍然有篡改历史数据的可能。而以POW为共识算法的比特币、以太坊网络则更去中心化,更难以篡改历史数据。所以,为了进一步加强存证所在链的安全性,我们可以定期将该区块链的最新区块Hash,在比特币或者以太坊进行存证,由他们来证明本存证链没有被篡改,从而证明该链上的所有存证数据没有被联合作恶篡改,Factom就是采用了类似的方式保证了本链的数据没有被篡改的。以下图右下角是Factom进行比特币网络的二次存证的示例:

    clipboard

    可信时间戳

    区块链的时间戳是指在每个区块头上,记账节点在产块时,写入的一个时间值。这个时间值并不要求十分精确,只要在一定的范围内,其他节点也是可以接受的。以比特币为例,大约每10分钟产一个块,而且比特币网络十分拥堵,所以要用比特币进行存证,而费用给的不是很高的话,可能几个小时,甚至几天都不被打包。从发起存证交易到被最终打包花了几天的时间,时间戳的误差范围就太大了。

    对于要求更精确时间的存证,我们一方面使用高性能的公链或者联盟链,另一方面可以国家认可的可信时间服务,比如:https://www.tsa.cn/ 等。我们并不需要对每个存证都请求时间戳服务,我们可以根据存证所需要精确到的时间范围,每几分钟、几小时请求一次可信时间服务,获得签名的证书,并将证书包含到区块中即可。

    以下是WoSign的时间戳服务示意图:

    clipboard

    存证的索引

    首先我们说索引,加入我有一张照片,我记得之前在区块上进行了存证,也就是将这张照片文件的hash放到了区块链上,但是我并不记得是什么时候放的了,那么我怎么查询这张照片的存证结果呢?因为比特币和以太坊在底层数据结构上不支持,所以只有靠第三方的区块链浏览器,或者写个工具扫描全账本,将所有存证数据放入数据库建立索引,然后依靠数据库索引来实现存证数据的查询。

    而PalletOne上进行存证数据则不需要依赖第三方工具,PalletOne在存证数据所使用的DataPayload进行了专门的存证设计,其结构如下:

    type DataPayload struct {
        MainData  []byte `json:"main_data"`
        ExtraData []byte `json:"extra_data"`
        Reference []byte `json:"reference"`
    }

    我们只需要将需要存证的照片Hash放到MainData中,签名并广播交易。当一个全账本在收到一个新区块,并存储到本地账本时,会解析其中包含的DataPayload.MainData,并建立MainData与TxHash的索引。而TxHash本身也具有和UnitHeader之间的索引,所以我们只需要知道MainData,就可以很快的查询到该存证所在的交易Hash,所在的单元Hash、高度、时间戳等。而通过交易Hash作为Key,又可以查询到交易本身(包括存证人、存证花费的Token、其他交易信息等)。

    存证的扩展

    在实际存证的过程中,大多数情况下,我们不可能只存储一个Hash就完了,而是希望将该Hash所对应的文件的特征、描述、标签等作为附加信息也存证起来。比如我们在做照片的版权存证时,我们在MainData中存入照片的Hash,在ExtraData中以json格式存入了照片的名字、作者、拍摄时间、拍摄地点以及其他的描述信息,这些信息不用太长,但也对照片起到了很好的描述作用。扩展信息由于是非标准化的,存证不同的内容,其ExtraData的格式和内容也千差万别,所以并不需要建立通用的索引。

    存证的引用

    除了常见的对最终结果的存证,对一个数据的多个版本进行存证也是常见的需求。比如我们有个多人协同写作的文档,每个人都可以在别人完成的文档的基础上进行进一步的修改和完善,而每一次修改的发布就是一个版本,我们可以将该文档的所有版本每次在发布时都存证起来。对文档的多个版本进行存证,就要求每次存证时,指定一个引用关系,比如我们必须指定本次存证的上一个版本Hash是什么,如果没有指定就可以认为是该文档的第一个版本,这是一种链式引用关系。当然我们也可以使用另一种引用方法,即第一个版本存证时没有引用关系,接下来所有版本的存证,都指定引用为第一个版本的Hash;因为区块链本身提供了时间戳服务,所以我们可以通过时间戳对所有后续版本进行排序,而确定先后顺序。Reference字段不仅仅可以和其他存证建立引用关系,也可以和TokenID建立引用关系,我们甚至可以进一步扩展Reference字段的内容,形成引用的DAG结构,以适配更复杂的应用场景。

    存证与通证的结合——溯源

    对区块链和比特币有点了解的都知道,UTXO是比特币的记账模型,在一笔交易中采用input和output来表示比特币的流转情况,每个input指向另一个output。而UTXO这种链式模型,就天然适合于溯源的底层模型。

    如果我们要对某个物品进行溯源跟踪,那么首先要给该物品进行唯一标识,可以给该物品贴上全球唯一的二维码/条形码,然后在区块链系统中,我们有一个与该物品唯一标识对应的Token被创造出来。接下来只要该物品流转到下一个环节,那么区块链系统中也对该Token进行一次转账,交给下一个人。

    既然这里涉及到Token的转账交易,那么就可以在这次转账交易中将DataPayload也附加上去,为溯源增加更多信息。

    以基于PalletOne区块链为基础的“艺溯链”为例,该区块链应用主要是实现了对艺术品、工艺品的溯源。比如玉雕的溯源。当一个玉雕大师(工作室)完成了一个玉雕作品时,玉雕大师会为作品拍照,测量、填写材质、尺寸、重量等信息,并以此信息创建一个唯一的Token。创建后的Token是在玉雕大师的地址账户下,当玉雕要投放市场时,玉雕大师将玉雕交到门店,同时将Token转移给门店的地址。门店如果希望对玉雕进行鉴定,可以将Token自己转移给自己,同时在本次交易中,把鉴定证书的照片Hash,证书链接等作为DataPayload添加到Token的交易中。最终消费者在购买玉雕时,可以查询该玉雕对应Token的流转历史和存证信息,并在购买玉雕后,由商家将玉雕的Token转移到用户的地址账户名下。这样可以增加消费者对玉雕作品的信任。

    总结

    基于区块链的存证,可以使用比特币网络的二次存证实现存证链的不可篡改的可信。配合国家认可的可信时间戳服务,对区块的时间戳进行可信证明,保证了从法律层面认可区块链的存证时间戳。将存证数据分为可索引的MainData,可附加更多数据的ExtraData和可以建立引用关系的ReferenceData,可以实现大部分企业级的存证需求。存证数据和Token的UTXO模型结合,以及非同质化通证的支持,可以实现溯源功能的原生支持。

    在溯源的技术实现上,虽然和UTXO结合,使用非同质化Token的方式进行溯源具有底层优势,但是对于大批量的商品并不合适。比如药品的溯源,如果我们为每一盒药都创建一个对应的Token,那么在药品出厂,一卡车一卡车的运到经销商时,相当于要做几万几十万个Token的转账,这种大批量的Token转移,每一个都需要单独签名和验签,严重制约了溯源的并发数,所以Token化的溯源更适合艺术品、珠宝等高价值,但量不大的场景。

    如果针对单纯的存证场景,在联盟链中,Token和Gas就不是必须的了,如果每次存证都需要Token的转移或者Gas的消耗,则严重影响并发。所以联盟链的存证,是可以去掉对Token的依赖,用户发起的交易只需要包含2条Message:DataPayload和SignaturePayload即可。当然在公链场景下,Gas仍然是必须的!

  • 相关阅读:
    c:forTokens标签循环输出
    jsp转long类型为date,并且格式化
    spring中@Param和mybatis中@Param使用区别(暂时还没接触)
    734. Sentence Similarity 有字典数组的相似句子
    246. Strobogrammatic Number 上下对称的数字
    720. Longest Word in Dictionary 能连续拼接出来的最长单词
    599. Minimum Index Sum of Two Lists两个餐厅列表的索引和最小
    594. Longest Harmonious Subsequence强制差距为1的最长连续
    645. Set Mismatch挑出不匹配的元素和应该真正存在的元素
    409. Longest Palindrome 最长对称串
  • 原文地址:https://www.cnblogs.com/studyzy/p/11982452.html
Copyright © 2011-2022 走看看