zoukankan      html  css  js  c++  java
  • 区块链零知识证明:Zcash 基础知识普及帖,Zcash 技术分析

    ZCash 是 bitcoin 的分支,保留了 bitcoin 原有的模式,基于比特币 0.11.2 版代码修改的。 ZCash 钱包资金分 2 种:透明资金、私有资金,透明资金类似比特币资金;私有资金加强了 隐私性,涉及到私有资金的交易是保密不可查的,透明资金与透明资金的交易是公开可查的。

    ZCash 被称为零币,与‘灵’同音,不好听,且有归零的感觉,统一称为 Z   币。ZCash 主链 的币叫 ZEC,等同于 BTC,测试链的币称为 TAZ。

    目前 ZCash 仅支持 linux 系统(推荐 ubuntu),不支持 Windows、MAC,且只支持命令行, 没有图形界面(zcash 团队没人擅长 GUI)。

      地址 

    ZCash 中含有 2 种地址,实现 bitcoin 和 ZCash 的兼容。

    1、 透明资金地址 taddr  类 bitcoin 地址,保存在 UTXOs 中,长度为 34 位。   命令./src/zcash-cli getnewaddress 可以生成新的 taddr 地址。 例如:     msFgKsVAia4aFB1qFGX7iJ3XjMZv6c26Ab  

    2、 私有资金地址 zaddr  保存在 notes 对象中,长度为 96 位,前 2 位为标记,主链地址前 2 位是”zc”,spendingkey 的前 2 位是”SK”,测试链的地址前 2 位是”tn”。 notes 对象是加密的,解密才能查看,用的是 chacha20-poly1305 算法。 命令./src/zcash-cli z_getnewaddress 可以生成新的 zaddr 地址。 例如: tngBSug9xvpqudziMc3QbfReHG6BeufHDbv4vEZDmnYqSpRbqu5USZqBTXENQGdUbYMkxqHbb9j3 RmEr7Lza8q7hbTQxZnM

    具体生成过程看 z_getnewaddress 函数。

    命令 z_listaddresses 获取节点钱包中的 zaddr 列表。

    命令./src/zcash-cli zcrawkeygen 可以查看地址、key 等。

    地址 taddr 实现了原有的 bitcoin 的功能,zaddr 实现了 zcash 的功能。

    taddr 可以发送交易给 taddr、zaddr,zaddr 可以发送交易给 taddr、zaddr。taddr 与 taddr 的交易是透明可查的,涉及到 zddr 的交易就保密了。  

    零知识证明 

    零知识证明是在不泄漏信息的情况下,生成证明,验证者通过验证证明确定是否正确。

    Zcash 使用了 SCIPR 实验室的零知识证明库 libsnark,在此基础上做了修改。

    Zcash 团队 成员包含多个 libsnark 开发人员(不是全部)。修改如下:

    1、 libsnark 支持 4 种语言:"R1CS"、"BACS"、"USCS"、"TBCS",zcash 使用了"R1CS"。

    2、 libsnark 支持 3 种椭圆曲线:"edwards"、"bn128"、"alt_bn128",zcash 使用了"alt_bn128"。

    3、 libsnark 支持 2 个库:gadgetlib1、gadgetlib2,zcash 使用了 gadgetlib1,gadgetlib1 是底层 库,支持所有的 R1CS 预处理特征。

    SCIPR 实验室的 libsnark:https://github.com/scipr-lab/libsnark。

    Zcash 修改后的 libsnark:https://github.com/zcash/libsnark。

    当 zcash 交易涉及到私有资金时,使用零知识证明生成证明(函数 r1cs_ppzksnark_prover),保存到类 JSDescription 的 proof 中,校验交易时校验证明(函数 r1cs_ppzksnark_verifier_strong_IC)。

    libsnark 看了看,知道怎么用的,但详细的也没看懂。

    零知识证明白皮书:https://eprint.iacr.org/2013/507.pdf 


    交易 

    透明资金发送到透明资金地址,可以调用 bitcoin 的 RPC 命令发送交易,涉及到私有资 金、地址,只能用 zcash 的 RPC 命令了,目前是 z_sendmany 命令。

    格式:

    z_sendmany "fromaddress" [{"address":... ,"amount":...},...]

    交易分 3 种情况:

    1、 透明资金发送到透明地址

    延用 bitcoin 的交易方式,仅仅打签名即可。

    2、 透明资金发送到透明地址、私有地址

    透明资金发送到透明地址,依然延用 bitcoin 的方式,发送到私有地址的需要构造证明, 对整个交易签名发送。

    3、 私有资金发送到透明地址、私有地址

    每笔交易需要生成证明,涉及到找零、矿工费的处理,最后再签名发送。      交易中的透明地址、私有地址的输入、输出是不同的结构,涉及到私有地址的  采用了新 增的结构(JSInput、JSOutput), 涉及到的私有地址的数据需要先  签名解密解析数据。  

    详细过程参考函数 z_sendmany: https://github.com/zcash/zcash/blob/master/src/wallet/asyncrpcoperation_sendmany.cpp#L126  

    生成证明参考函数 perform_joinsplit: https://github.com/zcash/zcash/blob/master/src/wallet/asyncrpcoperation_sendmany.cpp#L804 

     交易签名

    ZCash 私有资金交易时,不仅仅依靠零知识证明,而且对交易打签名,采用了 ed25519 算法。

    ZCash 交易的零知识证明、签名需要的公钥、密钥使用 ed25519 算法生成的,详细参考 函数 crypto_sign_keypair。

    签名参考函数 sign_send_raw_transaction。

    https://github.com/zcash/zcash/blob/master/src/wallet/asyncrpcoperation_sendmany.cpp#L660 

    挖矿算法 

    ZCash的挖矿算法是 EquiHash,理论依据是广义生日悖论,目前有 2 个实现:BasicSolve、 OptimisedSolve,BasicSolve 主要用于测试用例,现在用的 OptimisedSolve 是优化后的,但依 然存在优化空间。

    EquiHash 算法需要高内存,最优算法每个挖矿线程需要 1G 内存,短时间内   ZCash 使用 EquiHash 计算解决方案,保存到区块头的 nSolution,接收区块时校验。 BasicSolve 实现: https://github.com/zcash/zcash/blob/master/src/crypto/equihash.cpp#L323 OptimisedSolve 实现: https://github.com/zcash/zcash/blob/master/src/crypto/equihash.cpp#L494

    块奖励 

    ZCash 总量是 2100 万个币,每隔 2.5 分钟出一个块,每天 576 个块。

     区块奖励分 2 个阶段:

    1、 慢慢开始挖矿阶段

    为了照顾在开始阶段不懂挖矿的,ZCash 采用了慢慢开始挖矿机制,前 20000 个块的奖 励比较少,线程递增到 12.5 个币。

    慢慢开始挖矿阶段也分 2 个阶段:

     (1) 前 10000 个块

    块 1 的奖励是 0.000625 币,随着高度线性递增,增加幅度是 0.000625 币,块 9999 的奖励是 6.249375 币。

    (2) 块 10000~19999  

    块 10000 的奖励是 6.250625,随着高度线性递增,增加幅度是 0.000625 币,块 19999 的奖励是 12.5 币。

    前 20000 个块的奖励总量是 125000 币,相当于 10000 个块奖励是 12.5 个币的总量。产 生 10000 个块需要的时间大约是 17.3 天,缓慢挖矿的时间周(20000 个块)大约是 34.7 天。  

    2、 正常块奖励

    从块 20000 开始,奖励是 12.5 个币,奖励按照每 840000 个块(每 4 年)减半,计算块 奖励时块高度减少 10000,即 940000 块是第一次减半,每隔 840000 个块减半,以此类推。  

    不懂挖矿的矿工也不必着急,因为即使懂了,前 20000 个块的奖励很少,有 1个月的时 间搞定挖矿。  

    创始人奖励 

    前 4 年(区块 0~840000)产生的区块奖励的 20%归 zcash 公司(总量的 10%),80%归 矿工。4 年后的区块奖励全部归矿工。

    创建区块时,构造 2 个输出,分别给矿工、创始人,当广播区块后,其他节点接受区块 时,检验区块有效性,当高度小于 840000 时,检验是否有对创始人的 20%的输出。

    创始人奖励地址采用 2/3 多重签名 FOUNDERS_REWARD_SCRIPT。  

    难度调整 

    每产生一个区块都需要重新计算难度,难度计算基于前 17 个块(42.5 分钟),前 17 个区块的难度是固定的(powLimit),从第 18 个区块开始调整难度,最大值是 powLimit。

    详细计算过程参考 GetNextWorkRequired 函数。

    Bitcoin 是每隔 2016 个块调整难度,关于 zcash 的每个块都要重新调整难度,有个讨论, 参考:https://github.com/zcash/zcash/issues/147  

    CoinBase 保护 

    矿工挖矿的奖励不能直接发送给透明资金地址,只能发送给私有资金地址,然后才可以 发送给透明资金地址。

    币成熟期是 100。  

    创建新块 

    ZCash每个挖矿线程都有自己的地址、计数器,每个线程挖出来的新块的块奖励的地址 是不同的,做矿池的需要注意,改成一个地址。  

    参考函数BitcoinMiner(https://github.com/zcash/zcash/blob/master/src/miner.cpp#L442) 。

    区块大小是 2M。  

    挖矿工具 

    ZCash 目前仅支持 CPU 挖矿,GPU 的挖矿工具在研发中,尚未有人公开。 ZCash支持 2 种挖矿方式:solo、矿池。

    1、 Solo 挖矿

    在 ZCash.conf 设置 gen=1,启动 zcashd 即可挖矿。

    2、 矿池

    Zcash 开发者 str4d 做了个矿池和挖矿工具,矿池地址:http://zmine.io/,挖矿工具 地址:https://github.com/str4d/zcash/tree/standalone-miner。            zcash-miner 是 zcash 的分支,主要添加了 stratum 协议、cpu 挖矿。

    (1) stratum 协议

    采用了 cpp-ethereum 的 stratum 的实现,V2 版,做了些修改,移除了 eth 协 议中的命令。

    参考 commit:       https://github.com/str4d/zcash/commit/c5ea2cfb190944dfa23566561d1cb37dcb 116833  

    (2) cpu 挖矿

     把 equihash 算法做了些修改,接受矿池下发的难度来计算。

    参考文件 standaloneminer.cpp。 https://github.com/str4d/zcash/blob/standalone-miner/src/standaloneminer.cpp  

    参数文件 

    ZCash有 2 个参数文件,包含了证明、验证 key,分别是: z9-proving.key、z9-verifying.key,

    在~/.zcash-params 目录下。z9-proving.key 大概 900M,z9-verifying.key 大约 14K。使 用./zcutil/fetch-params.sh 可以下载这 2 个文件。

    程序启动初始化时(AppInit2), 读取这 2 个文件中的证明、验证 key,生成证明时需要 证明 key,验证证明时需要验证 key。  

    API 和 RPC 

    ZCash 保留了 bitcoin 的 API、RPC,涉及到透明资金、地址的可以使用 bitcoin 的接口, 涉及到私有资金、地址的只能用ZCash 新增的接口。

    ZCash 新增的接口包括查询余额、生成地址、发送交易等,如下:

     Accounting: z_getbalance, z_gettotalbalance

     Addresses : z_getnewaddress, z_listaddresses  

     Keys : z_exportkey, z_importkey, z_exportwallet, z_importwallet

     Operation: z_getoperationresult, z_getoperationstatus, z_listoperationids  Payment : z_listreceivedbyaddress, z_sendmany 

    详细信息参考文档 https://github.com/zcash/zcash/blob/master/doc/payment-api.md。  

    挖矿硬件 

    EquiHash 白皮书讲了 2 点:

    1、 GPU 比 CPU 快 4 倍,

    2、 ASIC 是否可能实现

    详细信息参考白皮书第 10 页。 https://www.internetsociety.org/sites/default/files/blogs-media/equihash-asymmetric-proof-ofwork-based-generalized-birthday-problem.pdf  

    加密库 

    ZCash使用了开源加密库   libsodium(https://github.com/jedisct1/libsodium),ZCash 使用 了其中的 chacha20-poly1305、blake2b、ed25519 算法。

    chacha20-poly1305 算法: https://github.com/jedisct1/libsodium/blob/master/src/libsodium/include/sodium/crypto_aead_ chacha20poly1305.h  

    blake2b 算法: https://github.com/jedisct1/libsodium/blob/master/src/libsodium/include/sodium/crypto_gener ichash_blake2b.h  

    ed25519 算法: https://github.com/jedisct1/libsodium/blob/master/src/libsodium/include/sodium/crypto_sign.h 

    保护隐私技术比较 

     目前市场上有 3 种保护隐私的币,分别是达世币 DASH、门罗币 XMR、Z 币 ZCash。

    1、 达世币(暗黑币改名叫达世币) DASH 采用的混币 CoinJoin 的方案,把一些交易混合在一起,增加追踪的难度。 CoinJoin 参考 DASH 币白皮书 http://www.8btc.com/dash-whitepaper  

    2、 门罗币 XMR XMR 采用了环签名,签名者利用自己的私钥以及环成员的公钥进行签名,验证者 只能确定该签名来自环中的某个成员,但无法确定签名者的真实身份。 参考文档 http://www.doc88.com/p-1731949359328.html  

    3、 Z 币ZCash的交易采用了零知识证明,隐藏交易信息。  这 3 种技术相比较来看,ZCash 的隐私保护性更好。

      

    风险 

    1、ZCash 目前是由公司开发的,公司具有绝对的话语权,后续公司会成立基金会,ZCash 的 开发交给基金会推进。如果ZCash 社区与公司、基金会出现意见分歧,而代码是开源的, 可以硬分叉。 比如:有人对创始人奖励不满意,已经提议去掉创始人奖励。  

    2、ZCash 的顾问包括:前任比特币核心开发人员 Gavin、eth 创始人 Vitalik Buterin,zcash 的 发展会受到这 2 个人的影响。 比如:区块大小 2M 源于 bitcoin classic。 参考 Github: https://github.com/zcash/zcash/issues/765   

    本文由ZCash爱好者-龙少撰写。如需转载请标明作者和来源。

    来源:http://weibo.com/ttarticle/p/show?id=2309404026835414451754

  • 相关阅读:
    买了一个 站立式办公 桌子。
    AutoCppHeader AutoHeader 自动根据CPP 或C文件 来生成头文件。
    cplusplus 库 在线管理; 类似于 python的 pip install 、nodejs 的npm模块
    var this.value 可在任意地方 声明 类成员变量。如果可以利用在C++ 那该有多好啊
    最近遇到了 timer1sec 定时调用的函数,出现了 时间久了,就不是每秒一次了,可能会慢的情况。如何解决呢?
    【我的愿景】每个程序员都应该学习编译原理,而每个人都应该学习 编程 和 设计。
    [已解决]下载chromium源码 download_from_google_storage 无法下载文件
    突发奇想-取缔宏定义,用另外一种语言来做C++的部分外层封装
    我讨厌Apple Safari浏览器的一些地方。不想用
    unix时间戳time_t与UTC时区的关系
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13313269.html
Copyright © 2011-2022 走看看