首先,注意本文的标题是《从零认识区块链》,而不是《从零认识虚拟货币》
对于虚拟货币,我是比较排斥的,尤其是以比特币为代表,基于 POW(proof of work) 的虚拟货币
浪费硬件资源和电能,做无用的计算,从发白皮书到割韭菜
那么区块链和虚拟货币的区别在哪里?
比特币作为区块链的第一个应用,我们可以说比特币是区块链,但是区块链并不是比特币
本文忽略了交易
的实现以及算法,重点在于阐释区块链的构造,以及一个应用价值较高的非数字货币的项目
本文在 NIST(National Institute of Standards and Technology) 于2018年1月的区块链技术综述上,结合作者之前了解的相关理论,以分析区块链的构造为宗旨、以作者的喜好为转移,实现了一个简易版本的区块链并在最后介绍了一个具有 实际价值
的落地项目
2008年中本聪发表了论文《Bitcoin: A Peer-to-Peero Electronic Cash System》。在该文认为在交易的过程中,两者之间缺乏信任需要引入第三方中介,这样会增加交易成本还会泄露给信息给第三方。于是他提出了比特币挖矿和交易方案
2009年1月3日,中本聪创世块诞生,留下了当时泰晤士报头版标题 “The Times 03/Jan/2009 Chancellor on brink of second bailout for banks”
每个用户都有一个自己的 Address,一个用户的 address
是一个简短的、字母+数字形式的字符串,由用户的公钥以及一些其他的数据(用于校验错误),使用 hash 推导而来,address 用来发送接收数字资产
大多数的区块链系统利用 to
和 from
作为交易的两端,地址是由公钥经过 hash 后生成的
用户可以生成许多对 private/public key 用来生成地址,允许不同程度的伪匿名
在一个区块链中,对于用户来说,地址就是他的 身份
,有时候 address 会被转化成二维码从而更方便的使用
当一个区块链分配数字资产的时候,它通过把资产分配到地址来实现
为了花费数字资产,一个用户必须证明该 address
对应的 私钥
的所有权
通过使用私钥来对一个 transaction
进行数字签名,该 transaction 可以通过公钥来验证
区块链在虚拟货币方向的应用主要是分布式记账,在传统的数据库中,通常由集中“可信”的第三方进行操作,换句话说,这个“第三方”就是账本的拥有者。
传统记账的缺点:
- 账本可能丢失或损坏,用户必须相信第三方备份系统的可靠性
- 交易可能不合法,用户必须相信第三方会合法的处理交易
- 交易列表可能不完整,用户必须相信第三方记录了完整的交易信息
- 交易内容可能被改变,用户必须相信第三方不会篡改历史记录
区块链的改进:
- 区块链为了解决这些问题,采用了分布式共识机制(distributed consensus mechanism)
- 区块链账本会被复制到系统中的每个节点
- 如果有一个新的交易请求提交到某个节点,会通知区块链系统中剩余的节点有一个交易的到达
- 当系统中有新的用户加入,他会收到一份完整的区块链账本复制
因此区块链系统丢失或者篡改账本与传统集中第三方处理相比,安全可靠的多
一个区块链系统为了创造一个新的 block,会采用一些策略
比如谁先算出 puzzle 的节点就获得生成下一个 block 的权利
一旦 puzzle 被解决,该节点会创造 block 的数据并存储同步
从图中可以看到,一个 block 是由以下组成的:
区块头:
- prevHash: 上一个区块 hash
- Merkle Tree Root Hash
- timestamp: 时间戳
- Nonce: 解决 puzzle 的随机数
区块体:
- Hash: 对当前区块头的哈希值
- Transaction List: 交易集合
从图中可以看到有一个 Merkle Tree,是一种哈希二叉树
常见的 Merkle Tree 应用方法是令每一个叶子节点都是 hash 值
两个叶子节点的父节点是他们求和再次哈希
Merkle Tree 用于记录一个区块中所有的交易信息
以比特币为例,每10分钟生成一个区块,在这十分钟内所有的比特币交易会写入 transaction list
区块中任何一笔交易的改变都会修改整个 Merkle Tree
Nonce 是一个随机数,创建一个 block 的时候会对区块头和 nonce 进行哈希计算
如果验证通过则挖矿成功
而为了验证通过,只能不断尝试各种随机数,比如难度设置为5,即 想要哈希值前缀为 00000
,会不断利用新的随机数进行尝试
因为区块头包含 timestamp,所以不会出现一劳永逸的答案
- Pow(proof of work) 工作量证明,浪费算力挖矿
- Pos(proof of stake) 权益证明,每个节点所占代币的比例越多,难度越低
- R-R(Round Robin) 轮询算法
Pow 与 Pos 都是一种随机选择下一个 block 上传者的方式
不同的是,Pow 根据计算能力随机 (如果攻击者伪造,需要 51% 的算力)
Pos 根据拥有财产随机 (如果攻击者伪造,需要拥有 51% 的货币)
比特币每2周调整一次 puzzle 难度,每十分钟生成一个新的 block,使用 SHA-256 算法,经测试,难度为 00000
时,需要计算 10,730,896 次,用时 54 秒;难度为 000000
时,计算了 934,224,175 次,用时 1h18min12s
根据不同的难度求解很难,但是验证很方便,只需要进行一次 hash ,查一下 hash 结果前缀0的个数就可以判断了
Pow 的缺点在于浪费了大量的算力、前后期贫富差异过大、浪费电力;优点在于可靠性
Pos 选择生成 block 节点的方案很有趣,他有一个多轮投票机制,系统会选择几个“股权”用户,然后让所有“股权”用户投票
Pos 的缺点在于“富人”可以更加容易地获取数字资产,但是在一个系统中获得 >50% 的资产成本极高
系统轮询,每个节点都有机会创造新的 block ,当被轮询的节点不可用时,系统会进行随机选择
轮询的优点在于无需确定一个复杂的共识机制来决定谁产出新 block、保证不会出现某一个节点成为“大多数”、不浪费资源;缺点在于系统中的节点处于某种程度上的互信,在开放式网络中的表现不好,因为恶意节点会持续增加
多数区块链系统采用 “长者优先” 原则
冲突一旦发生会很快解决,根据 “长者优先” 的策略确定一个 offical
链,再由他增加下一个合法的 block,非该链发生的交易会被添加进来
Transcation
就会被当作 Info
写入到区块链,例如 https://etherscan.io/tx/0x2d6a7b0f6adeff38423d4c62cd8b6ccb708ddad85da5d3d06756ad4d8a04a6a2
IPFS(InterPlanetary File System),星际文件系统
名字很好听,是一个 点对点的分布式版本文件系统
,目标是为了补充(取代) HTTP
把所有具有 相同文件
系统的计算设备连接在一起
用 基于内容
的地址替代基于域名
的地址
这样用户寻找的不是某个 地址
而是存储在某个地方的 内容
无需验证发送者的身份,只验证内容的 hash 值
从而提升网页速度、更快、更安全
可以把 IPFS 想象成所有文件数据是在同一个 BitTorrent 群并且通过同一个 Git 仓库存取
HTTP 可以视为一种集中化的协议,有以下几个缺点:
- 容易遭受 DDoS 攻击
- 过度依赖于骨干网
- 容易被监视审查控制
HTTP 首先 基于域名
寻找服务器 IP 地址,之后根据路径访问资源
IPFS 则是根据内容哈希,通过底层的 DHT(分布式哈希表) 来快速找到拥有数据的节点
可以把 IPFS 简单视作为 CDN
以下摘自 http://www.infoq.com/cn/articles/ipfs
前人写的已经够好了,无需我再废话
向 IPFS 分布式网络询问哈希的时候,它通过使用一个分布式哈希表
可以快速(在一个拥有 10,000,000 个节点的网络中只需要 20 跳)地找到拥有数据的节点
从而检索该数据,并使用哈希验证这是否是正确的数据IPFS 是通用的,并且存储限制很少。它服务的文件可大可小
对于一些大的文件,它会自动将其切割为一些小块,使 IPFS 节点不仅仅可以像 > > HTTP 一样从一台服务器上下载文件,而且可以从数百台服务器上进行同步下载
IPFS 网络是一个细粒度的、不可靠的、分布式的、易联合的内容分发网络(Content Delivery Network , CDN)
对于所有数据类型都是很有用的,包括图像、视频流、分布式数据库、操作系统、blockchains 等,而对于 IPFS 来说,最重要的是静态 web 网站IPFS 文件也可以是特殊的 IPFS 目录对象,它允许用户使用人类可读的文件名,透明地链接到其他 IPFS 哈希
用户可以通过默认方式加载目录中的 index.html,这也是标准的 HTTP 服务器采用的方式
使用目录对象,IPFS可允许用户采用完全相同的方式生成静态网站
将 web 网站添加到 IPFS 节点中只需要ipfs add -r yoursitedirectory
在此之后,用户可以从任何 IPFS 节点访问,而不需要链接到 HTML 上的任何哈希
简而言之就是结合 DHT 和 blockchain 组成了一个 "CDN"
- 自备翻墙 :L
- Mac | Linux (虽然 Windows 也支持,但是我并不想研究)
- Go Env (最好有,如果喜欢源码编译的话)
- GPG 的作用在于加密文件,如果不想对共享文件进行加密可以略过
brew install gnupg
gpg --gen-key
# 输入相关信息,结果如下:
# 我们需要生成大量的随机字节。这个时候您可以多做些琐事(像是敲打键盘、移动
# 鼠标、读写硬盘之类的),这会让随机数字发生器有更好的机会获得足够的熵数。
# 我们需要生成大量的随机字节。这个时候您可以多做些琐事(像是敲打键盘、移动
# 鼠标、读写硬盘之类的),这会让随机数字发生器有更好的机会获得足够的熵数。
# gpg: /Users/juntaran/.gnupg/trustdb.gpg:建立了信任度数据库
# gpg: 密钥 1ED9DF99E4F3A740 被标记为绝对信任
# gpg: directory '/Users/juntaran/.gnupg/openpgp-revocs.d' created
# gpg: revocation certificate stored as '/Users/juntaran/.gnupg/openpgp-revocs.d/07B03EDCEE49F5AFF4CE0C121ED9DF99E4F3A740.rev'
# 公钥和私钥已经生成并经签名。
# pub rsa2048 2018-03-12 [SC] [有效至:2020-03-11]
# 07B03EDCEE49F5AFF4CE0C121ED9DF99E4F3A740
# uid Juntaran <jacinthmail@gmail.com>
# sub rsa2048 2018-03-12 [E] [有效至:2020-03-11]
# 导出公钥
gpg --export --armor jacinthmail@gmail.com > Juntaran.pub.asc
# 导出私钥
gpg -o Juntaran.sec.key --export-secret-keys Juntaran
可以使用以下命令导入你生成的 pubkey:
gpg --import pubkey.asc
列出 key:
gpg --list-keys
参考 https://ipfs.io/docs/install/ 安装
# 源码编译(我建议还是算了)
go get github.com/jbenet/go-ipfs/cmd/ipfs
# Linux
wget https://dist.ipfs.io/go-ipfs/v0.4.13/go-ipfs_v0.4.13_linux-amd64.tar.gz
# Mac OS
wget https://dist.ipfs.io/go-ipfs/v0.4.13/go-ipfs_v0.4.13_darwin-amd64.tar.gz
tar xfz go-ipfs_v0.4.13_darwin-amd64.tar.gz
cd go-ipfs
./install.sh
# Test
ipfs help
初始化:
ipfs init
# 结果
initializing IPFS node at /Users/juntaran/.ipfs
generating 2048-bit RSA keypair...done
peer identity: QmdA8cVQeFEjTBFNvLQXzsJtYDCjD3HacaSjTCLVhN2Md1
to get started, enter:
ipfs cat /ipfs/QmS4ustL54uo8FzR9455qaxZwuMiUhyvMcX9Ba8nUH4uVv/readme
# 节点数据同步
ipfs daemon
# 结果
# Initializing daemon...
# Swarm listening on /ip4/10.232.64.161/tcp/4001
# Swarm listening on /ip4/10.37.129.2/tcp/4001
# Swarm listening on /ip4/127.0.0.1/tcp/4001
# Swarm listening on /ip6/::1/tcp/4001
# Swarm listening on /p2p-circuit/ipfs/QmdA8cVQeFEjTBFNvLQXzsJtYDCjD3HacaSjTCLVhN2Md1
# Swarm announcing /ip4/10.232.64.161/tcp/4001
# Swarm announcing /ip4/10.37.129.2/tcp/4001
# Swarm announcing /ip4/127.0.0.1/tcp/4001
# Swarm announcing /ip6/::1/tcp/4001
# API server listening on /ip4/127.0.0.1/tcp/5001
# Gateway (readonly) server listening on /ip4/127.0.0.1/tcp/8080
# Daemon is ready
随便找一个文件放到 ipfs
的目录里
gpg --encrypt --recipient "Juntaran" test.pdf
# md5检验
md5sum test.pdf
# 57f4e4fd59c28ea46a759e5886ef9df3 test.pdf
此时该文本已经被加密
上传到 ipfs
ipfs add test.pdf.gpg
# 结果
# added QmaAHZbevQL9wRUVAWEeUmxkkqftTrffnmRN2GszBVGKVr test.pdf.gpg
# 如果想上传一个目录 -r
# 检查是否上传成功
ipfs pin ls | grep QmaAHZbevQL9wRUVAWEeUmxkkqftTrffnmRN2GszBVGKVr
# 结果
# QmaAHZbevQL9wRUVAWEeUmxkkqftTrffnmRN2GszBVGKVr recursive
# 预览数据
ipfs cat QmaAHZbevQL9wRUVAWEeUmxkkqftTrffnmRN2GszBVGKVr
# 从 ipfs 下载(从当前节点下载,并非从 ipfs 网络下载)
ipfs get QmaAHZbevQL9wRUVAWEeUmxkkqftTrffnmRN2GszBVGKVr
# 结果
# Saving file(s) to QmaAHZbevQL9wRUVAWEeUmxkkqftTrffnmRN2GszBVGKVr
# 28.07 MB / 28.07 MB [===========================================================] 100.00% 0s
# 解密
gpg --decrypt QmaAHZbevQL9wRUVAWEeUmxkkqftTrffnmRN2GszBVGKVr > test.pdf
# 检查结果
du -sh *
# 28M QmaAHZbevQL9wRUVAWEeUmxkkqftTrffnmRN2GszBVGKVr
# 30M test.pdf
打开浏览器,输入 http://localhost:5001/webui 你会看到你存储的文件以及连接到 ipfs 服务器的信息
从 IPFS 网络查看数据: https://ipfs.io/ipfs/{hash值}
wget https://ipfs.io/ipfs/QmaAHZbevQL9wRUVAWEeUmxkkqftTrffnmRN2GszBVGKVr
等待一段时间后,你就会收到我的加密后的 pdf~
在另一台服务器下载后
# 首先要分发私钥,不建议这样做,我只是为了测试
# 正常流程应该是用A的公钥由B加密上传,A从 ipfs 网络下载后直接使用A的私钥解密
# 导入私钥
gpg --import Juntaran.sec.key
# 解密
gpg QmaAHZbevQL9wRUVAWEeUmxkkqftTrffnmRN2GszBVGKVr > test.pdf
# 检验
md5sum test.pdf
# 57f4e4fd59c28ea46a759e5886ef9df3 test.pdf
# 可以看到和最初的文档一致
上传了一个未 GPG 加密的 txt 文档
可以直接翻墙从 IPFS 访问,无需解密: https://ipfs.io/ipfs/QmSnyy9Z934Rwj11tVgyPiQq5v9TgdxPvzavgEfnQWECtm
wget https://ipfs.io/ipfs/QmSnyy9Z934Rwj11tVgyPiQq5v9TgdxPvzavgEfnQWECtm
cat QmSnyy9Z934Rwj11tVgyPiQq5v9TgdxPvzavgEfnQWECtm
# Hello IPFS from Juntaran
为什么把 IPFS 放在这里呢,因为这是一个落地的应用,而不是无谓的浪费电力
有人提出了 Filecoin
作为 IPFS 的激励系统,也就是 IPFS 的代币
Filecoin 也是基于区块链的产物,在 Filecoin 中,矿工不通过大量计算来进行工作证明
矿工的任务是存储,工作量也就等价于复制量
迅雷的 玩客云
也类似于 IPFS,搞了个 链克
作为数字资产
有一种 Filecoin 和 IPFS 关系的感觉
但是首先,你要花 500 块钱去京东抢一个 玩客云
回来
点开评论,总是给人一种刷评论的感觉,还有人在评论里 2-3 倍价钱倒卖
突然有了一种连韭菜苗都要割的感觉
IPFS 诞生已经几年了,希望能够借着区块链这波热度起飞~
成为真正的 InterPlanetary
gpg 的简单操作
查看公钥:gpg --list-key
查看私钥:gpg --list-secret-keys
提取公钥:gpg -a --export newkey > newkey.asc
提取私钥:gpg -a --export-secret-keys newkey > newkey_pirv.asc
导入公钥或私钥:gpg --import newkey
gpg -ea -r newkey filename
即会生成 filename.asc 的加密文件
gpg -o filename -d filename.asc
输入私钥密码
即可把 filename.asc 的加密文件解密成 filename 文件
删除私钥
gpg --delete-secret-key newkey
删除公钥
gpg --delete-key newkey
如果能看到最后说明你已经浪费了大约 1h 的时间在这里
本文介绍了区块链的构成以及一些主要的组成部件,在最后宣传了一下 IPFS
一个简易的区块链实现可以参考 https://github.com/Juntaran/EZChain 闲余时间参考了几个 gayhub 的源码写的 Demo,还未完全实现