跨链技术方案中典型的有:哈希时间锁定(HTLC) 、公证人机制、侧链、中继链、分布式秘钥控制等。本篇主要讲解哈希时间锁定(HTLC)实现跨链的技术特性,在后续的文章中会相继介绍其他跨链的技术。

HTLC 的核心是时间锁和哈希锁。时间锁 指,交易双方约定在某个时间内提交才有效,超时则承诺方案失效(无论是提出方或接受方)。哈希锁 指,对一个哈希值 H,如果提供原像 R 使得 Hash(R) = H,则承诺有效,否则失效。如果交易因为各种原因未能成功,时间锁能够让交易参与各方拿回自己资金,避免因欺诈或交易失败造成的损失。

哈希时间锁定最早出现在比特币的闪电网络,跨链资产交换支持一定数量的 A 链资产和一定数量的 B 链资产进行原子交换。哈希时间锁定巧妙地采用了哈希锁和时间锁,迫使资产的接收方在最后期限内确定收款并产生一种收款证明给打款人,否则资产会归还给打款人。收款证明能够被付款人用来获取接收人区块链上的等量价值的数量资产或触发其他事件。

阅读全文

对于联盟链的业务中搭建一个私有网络的 IPFS 集群还是很有必要的,私有网络集群允许 IPFS 节点只连接到拥有共享密钥的其他对等节点,网络中的节点不响应来自网络外节点的通信。 IPFS-Cluster 是一个独立的应用程序和一个 CLI 客户端,它跨一组 IPFS 守护进程分配、复制和跟踪 pin。它使用基于 Raft 一致性算法来协调存储,将数据集分布到参与节点上。对于我们要将一个 peer 上的存储同步备份到所有集群上其他的 peers 时,或者对集群的节点管理,这时 IPFS-Cluster 就会起到一个很好的作用。 下面简单描述一下 IPFS 私有网络以及 IPFS-Cluster 集群的搭建配置过程(Ubuntu16.04)。 IPFS 和 IPFS-Cluster 默认的端口: IPFS: 4001 – 与其他节点同学端口 5001 – API server 8080 – Gateway server IPFS-CLUSTER: 9094 – HTTP API endpoint 9095 – IPFS proxy endpoint 9096 – Cluster swarm 集群几点通信端口 Golang 安装 IPFS 官方提供的安装方式有安装包方式,ipfs-update 方式,源码编译安装方式,具体可以查看 https://docs.ipfs.io/guides/guides/install/ 这里为了 ipfs 版本选择和升级,所以使用ipfs-update方式安装,Go 是必须的,对于 Go 的安装这里不再赘述。

阅读全文

所需依赖以及安装 Nodejs 8.11.x (Note that v9.x is not yet supported) PostgreSQL 9.5 or greater jq docker-ce docker-compose git 在上一篇的《Hyperledger Fabric 多机部署》已经部署好了 Fabric 网络,这里用 CLI 那台机器来部署 Hyperledger Explorer,所以有些依赖已经安装好了。 安装 PostgreSQL sudo apt-get install wget ca-certificates wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main" >> /etc/apt/sources.list.d/pgdg.list' sudo apt-get update sudo apt-get install postgresql postgresql-contrib ##修改密码 sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';" 安装 jq apt-get install jq jq --version 代码配置 Clone 项目代码 git clone https://github.

阅读全文

官方的first-network执行一个脚本单机 docker 就可以启动 fabric 网络环 很多书和网络上也都是基于first-network教学,下面教程基于拆解first-network,不但对我们更深入了解 fabric 网络搭建有很大帮助,也有利于我们真实生产环境的搭建操作。 主机列表 节点 IP order.example.com 192.168.11.11 peer0.org0.example.com 192.168.11.12 peer1.org0.example.com 192.168.11.13 peer0.org1.example.com 192.168.11.14 peer1.org1.example.com 192.168.11.15 由于域名并非真实解析的公网,所以需要将以上加入各个主机的/etc/hosts 环境依赖安装 以下依赖安装没有特别说明需要在各个主机中安装操作 docker 安装 apt-get update apt-get install \ apt-transport-https \ ca-certificates \ curl \ gnupg-agent \ software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - add-apt-repository \ "deb [arch=arm64] https://download.

阅读全文

MPT(Merkle Patricia Tries)是以太坊中存储区块数据的核心数据结构,它是 Merkle Tree 和 Patricia Tree 融合一个树形结构,理解 MPT 结构对之后学习以太坊区块 header 以及智能合约状态存储结构的模块源码很有帮助。 首先来看下 Merkle 树: 它的叶子是数据块的 hash,从图中可以看出非叶子节点是其子节点串联字符串的 hash,底层数据的任何变动都会影响父节点,这棵树的 Merkle Root 代表对底层所有数据的“摘要”。 这样的树有一个很大的好处,比如我们把交易信息写入这样的树形结构,当需要证明一个交易是否存在这颗树中的时候,就不需要重新计算所有交易的 hash 值。比如证明图中 Hash 1-1,我们可以借助 Hash 1-0 重新计算出 Hash 1,然后再借助 Hash 0 重新计算出 Top Hash,这样就可以根据算出来的 Top Hash 和原来的 Top Hash 是否一样,如果一样的话那么 Hash 1-1 就属于这棵树。 所以想象一下,我们将这个 Top Hash 储存在区块头中,那么有了区块头就可以对区块信息进行验证了。同时 Hash 计算的过程可以十分快速,预处理可以在短时间内完成。利用 Merkle 树结构能带来巨大的比较性能提升。 再来看下 Patricia 树: 从它的名字压缩前缀树再结合上图就可以猜出来 Patricia 树的特点了,这种树形结构比将每一个字符作为一个节点的普通 trie 树形结构,它的键值可以使用多个字符,降低了树的高度,也节省了空间,再看个例子: 图中可以很容易看出数中所存储的键值对: 6c0a5c71ec20bq3w => 5 6c0a5c71ec20CX7j => 27 6c0a5c71781a1FXq => 18 6c0a5c71781a9Dog => 64 6c0a8f743b95zUfe => 30 6c0a8f743b95jx5R => 2 6c0a8f740d16y03G => 43 6c0a8f740d16vcc1 => 48 以太坊中的 MPT: 在以太坊中 MPT 的节点的规格主要有一下几个:

阅读全文

RLP(Recursive Length Prefix),递归长度前缀编码,它是以太坊序列化所采用的序列化和反序列化的主要方式。区块、交易等数据结构在 网络传输和持久化时会先经过 RLP 编码后再存储到数据库中。rlp 适用于任意的二进制数据数组的编码,在以太坊中,rpl 接受的数据分为两类:1.字节数组 2.类 list 数据结构。 以太坊中 rlp 的具体定义和规则我们可以在黄皮书中找到(Appendix B. Recursive Length Prefix): 序列化定义 * O 所有byte的集合 * B 所有可能字节数组 * L 不只单一节点的树形结构(比如结构体或者树节点分支节点,非叶子节点) * T 所有字节数组的树形结构组合 序列化处理 通过两个子函数定义 RLP 分别处理上面说的两种数据类型 Rb(x)字节数组序列化处理规则 如果字节数组只包含一个字节(对于 [0x00, 0x7f] 范围内的单个字节),而且这个字节的大小小于 128,那么不对数据进行处理,处理结果就是原数据,比如:a 的编码是 97。 如果字节数组的长度小于 56,那么处理结果就等于在原始数据前面加上(128+字节数据的长度)的前缀,比如 abc 编码结果是 131 97 98 99,其中 131=128+len(“abc”),97 98 99 依次是 a b c。 如果不是上面两种情况,那么处理结果就等于在原始数据前面加上原始数据长度的大端表示,然后在前面加上(183 + 原始数据大端表示的长度),比如编码下面这段字符串The length of this sentence is more than 55 bytes, I know it because I pre-designed it编码结果如下184 86 84 104 101 32 108 101 110 103 116 104 32 111 102 32 116 104 105 115 32 115 101 110 116 101 110 99 101 32 105 115 32 109 111 114 101 32 116 104 97 110 32 53 53 32 98 121 116 101 115 44 32 73 32 107 110 111 119 32 105 116 32 98 101 99 97 117 115 101 32 73 32 112 114 101 45 100 101 115 105 103 110 101 100 32 105 116,其中前三个字节的计算方式如下:1.

阅读全文

这里假设已经存在 bootnodes 服务节点了,需要给私有网络中添加一个以太坊节点,用 docker 来部署比较方便,不用手动去添加。这里只是写了个简单的 demo,并不是一个完整基于 bootnodes 来部署以太坊私有网络的方法。 当然创建一个 bootnode 也很简单,大致步骤如下: bootnode -genkey boot.key bootnode -nodekey boot.key -verbosity 9 -addr :30310 如果需要一个完整的基于 docker 的一台私有网络,可以通过 docker-compose 将 bootnode 和节点来编排,后面有空来完善一下。 具体源码 => https://github.com/yuansir/bootnodes-ethereum-peer-docker Usage genesis.json 复制 bootnodes 链接所有节点的共同 genesis.json 文件 Dockerfile 根据需求修改 Dockerfile 中的环境变量 build image 比如 tag 为 eth-peer:1.0 docker build -t eth-peer:1.0 . run // docker run -it --rm --name your-name eth-peer:1.0 /bin/bash docker run -d --name your-name eth-peer:1.

阅读全文

ERC721 官方简介是:A standard interface for non-fungible tokens, also known as deeds.也叫非同质代币,或者不可置换代币(NFTs)。提到 ERC721,一个好理解的例子就是CryptoKitties 迷恋猫,每一只猫都是独一无二的拥有不同基因,有收藏价值属性。ERC721 对于虚拟资产收藏品领域会有很好的应用价值和市场需求。 它和我写的上一篇《OpenZeppelin ERC20 源码分析》介绍的 ERC20 有所不同,ERC721 最小的单位为 1 无法再分割,代表独一无二的,针对不可置换的 Token 的智能合约标准接口。从 ERC721 标准草案中可以看到,兼容 ERC20 的方法有 4 个:name,symbol,totalSupply,balanceOf 添加的新方法:ownerOf,takeOwnership ERC721 还重写了approve和transfer。 分析 OpenZeppelin ERC721 源码前同样我画了一个继承和调用关系的思维导图,可以帮助更容易地看源码。 ERC721Basic.sol pragma solidity ^0.4.23; /** * @title ERC721 标准的基本接口 * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ contract ERC721Basic { event Transfer( address indexed _from, address indexed _to, uint256 _tokenId ); event Approval( address indexed _owner, address indexed _approved, uint256 _tokenId ); event ApprovalForAll( address indexed _owner, address indexed _operator, bool _approved ); function balanceOf(address _owner) public view returns (uint256 _balance); function ownerOf(uint256 _tokenId) public view returns (address _owner); function exists(uint256 _tokenId) public view returns (bool _exists); function approve(address _to, uint256 _tokenId) public; function getApproved(uint256 _tokenId) public view returns (address _operator); function setApprovalForAll(address _operator, bool _approved) public; function isApprovedForAll(address _owner, address _operator) public view returns (bool); function transferFrom(address _from, address _to, uint256 _tokenId) public; function safeTransferFrom(address _from, address _to, uint256 _tokenId) public; function safeTransferFrom( address _from, address _to, uint256 _tokenId, bytes _data ) public; } ERC721Basic 合约定义了基本的接口方法:

阅读全文

ERC20:Ethereum Request for Comments 20,是一个基于以太坊代币的接口标准(协议)。所有符合 ERC-20 标准的代币都能立即兼容以太坊钱包,它能让用户和交易所,都能非常方便的管理多种代币,转账、存储、ICO 等等。 OpenZeppelin 的 Token 中实现了 ERC20 的一个安全的合约代码,本篇主要来分析一下源码,了解一下 ERC20 的实现,由于代码之间的调用可能略复杂,直接每个文件每个文件的来看会有点绕,我直接画了一个继承和调用关系的思维导图,可以帮助更容易地看源码。 ERC20Basic.sol pragma solidity ^0.4.23; contract ERC20Basic { function totalSupply() public view returns (uint256); function balanceOf(address who) public view returns (uint256); function transfer(address to, uint256 value) public returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); } ERC20Basic 合约主要定义了 ERC20 的基本接口,定义了必须要实现的方法: totalSupply 返回总共发行量 balanceOf 查询指定 address 的余额 transfer 发送指定数目的 token 到指定账户,同时发送后需要触发Transfer事件 Transfer事件,任何 token 发送发生时,必须触发该事件,即使是 0 额度。 当一个 token 合约创建时,应该触发一个 Transfer 事件,token 的发送方是 0x0,也就是说凭空而来的 token,简称空气币。

阅读全文

以太坊中除了基于运算能力的 POW(Ethash)外,还有基于权利证明的 POA 共识机制,Clique是以太坊的 POA 共识算法的实现,这里主要对 POA 的Clique相关源码做一个解读分析。 Clique 的初始化在 Ethereum.StartMining中,如果 Ethereum.engine 配置为 clique.Clique, 根据当前节点的矿工地址(默认是 acounts[0]), 配置 clique 的 签名者 : clique.Authorize(eb, wallet.SignHash) ,其中签名函数是 SignHash,对给定的 hash 进行签名。 func (s *Ethereum) StartMining(local bool) error { eb, err := s.Etherbase()//用户地址 if err != nil { log.Error("Cannot start mining without etherbase", "err", err) return fmt.Errorf("etherbase missing: %v", err) } if clique, ok := s.engine.(*clique.Clique); ok { //如果是clique共识算法 wallet, err := s.accountManager.Find(accounts.Account{Address: eb}) // 根据用它胡地址获取wallet对象 if wallet == nil || err !

阅读全文

作者的图片

Ryan是菜鸟 | 技术栈笔记

一步一个脚印,一直在路上!记录LNMP技术栈,Web架构,区块链等笔记

菜鸟码农

南京