区块链基础

区块链究竟是什么?狭义地说,区块链就是比特币的底层技术;不过,经过7年的发展,区块链已经不再“依附于”比特币,而是独立地发展成为了一种革命性的技术,比特币则是区块链最大、最成功的应用。

从技术层面来看,区块链是一个基于共识机制、去中心化的公开数据库。共识机制是指在分布式系统中保证数据一致性的算法;去中心化是指参与区块链的所有节点都是权力对等的,没有高低之分,同时也指所有人都可以平等自由地参与区块链网络,唯一的限制就是个人自己的选择;公开数据库则意味着所有人都可以看到过往的区块和交易,这也保证了无法造假和改写。基于以上特性,可以总结得出:区块链由许多对等的节点组成,通过共识算法保证区块数据和交易数据的一致性,从而形成一个统一的分布式账本。
从价值层面来看,区块链是一个价值互联网,用于传递价值。目前的互联网仅用来传递消息,但是还不能可靠地传递价值;而比特币区块链却可以在全球范围内自由地传递比特币,并且能够保证不被双花、不被冒用。从这个角度来说,区块链是记录价值、传递消息和价值本身转移的一个可信账本。

以区块链技术为核心的系统包括如下四大最主要的特点。

Distributed(分布式的)

1
区块链是全球化的,系统上的节点是运行在太平洋某个小岛的笔记本电脑上还是运行在中国某个小镇的服务器上,对系统本身来说都是一样的,除了网络连接速度有区别之外,其他没有任何区别。区块链没有中心节点,数据分布式地存储在各个节点上,即使绝大部分节点毁灭了,只要还有1个节点存在,就可以重新建立并还原区块链数据。

Autonomous(自治的)

1
区块链是一种去中心化的、自治的交易体系,这种自治性表现在两个方面:1)所有节点都是对等的,每个节点都可以自由加入和离开,并且这一行为对整个区块链系统的运行没有任何影响。所有的节点都是按照相同的规则来达成共识,且无需其他节点的参与。2)区块链系统本身一旦运行起来,就可自行产生区块并且同步数据,无需人工参与。

Contractual(按照合约执行的)

1
区块链是按照合约执行的,第一体现在各个节点的运行规则(指的是交易、区块链或协议)上,按照既定的规则执行,一旦出现违背规则的行为,就会被其他节点所抛弃;第二体现在智能合约上,智能合约是一种可程序化的合同条款、规则或规定,包含在每个交易中,交易验证时必须先运行智能合约,只有通过了验证的交易才能被接受。

Trackable(可追溯的)

1
2
区块链的数据是公开透明的,不能被篡改,而且相关交易之间有一定的关联性,因而很容易被追溯。比如比特币区块链,每一枚比特币都有其特定的来源,通过输入可以追溯到上一个交易,或者通过输出追溯到下一个交易。
此外,区块链代码本身也是可追溯的,区块链系统是开源软件,其对于所有的人都是公开的,因此任何人都可以查看并修改这些代码,不过修改后的代码需要经过开源社区上其他程序员的审核。

交易合交易链

交易是签过名的数据结构,该数据结构会在区块链网络中广播,并被收集到区块中。它会引用以前的交易,从该交易中发送特定数量的比特币到一个或多个公钥中(即比特币地址),并且交易未被加密(比特 币体系中没有加密任何数据)。多个交易可组成一个区块(block), 这些区块同样也会在区块链网络中传播,一个区块会引用上一个区块。

区块链就是由区块(block)用某种方式组织起来的链条 (chain)

比特币地址

比特币地址是一个由数字和字母组成的字符串,可以与任何想给你 比特币的人分享。由公钥(一个同样由数字和字母组成的字符串)生成 的比特币地址以数字“1”开头。例子:

1
1J7mdg5rbQyUHENYdx39WVWK7fsLpEoXZy

在交易中,比特币地址通常是以收款方的形式出现。比特币地址可以代表一对公钥和私钥的所有者,也可以代表其他东西。

比特币地址是由公钥经过单向的Hash函数生成的。用户通常所见到 的比特币地址是过“Base58Check”编码的,这种编码使用了58个字 (一种Base58数字系统)和校验码,提高了可读性、避免了歧义,并有效地防止了在地址转录和输入中产生错误。

交易的本质

交易实质上就是包含一组输入列表和输出列表的数据结构,也可称之为转账记录,这其中就包括了交易金额、来源和收款人等信息。

输入和输出

输入是对其他交易输出的引用,一个交易中通常列有多个输入。所有被引用的输出值相加,得出的总和值会在该交易A的输出中用到。

Previous tx:以前交易的Hash值

Index:被引用交易的特定输出号

ScriptSig:一个脚本的前一半

脚本包含两个部分,一个签名和一个公钥,公钥属于交易输出的收款人,并且表明交易创建者允许收款人获得的输出金额;另一个部分是 ECDSA签名,是通过对交易的Hash值进行ECDSA签名而得到的。

输出中包含了发送比特币的指令,金额(Value)是以聪(Satoshi,1BTC=100000000聪)为单位的数值。ScriptPubKey是脚本的另一半(这点将在后文中详细讨论),可以有多个输出,它们共享了输入金额。

交易类型

根据目标地址的不同,可以把交易分为如下几种类型:

  1. 支付到公钥Hash

一个比特币地址只是一个Hash值,因而发送者无法在scriptPubKey 中提供完整的公钥,当要赎回比特币时,接收者需要同时提供签名scriptSig和公钥scriptPubKey,脚本系统会验证公钥的Hash值与scriptPubKey中的Hash值是否匹配,同时还会检查公钥和签名是否匹配。

  1. 支付到脚本Hash

该类交易非常有意义,未来应该会在某些场合频繁使用。该类交易的接受地址不是通常意义上的地址,而是一个多签地址,以3开头。比如,三对公钥对可以生成一个多签地址。

地址以3开头,可以实现多方管理资产,极大地提高安全性,也可以轻松实现基于比特币原生的三方交易担保支付。一个m-of-n的模式如下:

1
m {pubkey}...{pubkey} n OP_CHECKMULTISIG

其中,m和n需要满足:1≤n≤20,m≤n。

1 of 3,最大程度私钥冗余。防丢私钥损失,3把私钥中任意一把即可签名发币,即使丢失2把也可以保障不受损失。

2 of 3,提高私钥冗余度的同时解决单点信任问题。3把私钥中的任 意2把私钥可签名发币,对于三方不完全信任的情形,即中介交易,非常适用。

3 of 3,最大程度解决资金信任问题,无私钥冗余。必须3把私钥全部签名才能发币,适用于多方共同管理的重要资产,但是任何一方遗失私钥均会造成严重损失。

  1. 挖矿交易

挖矿(coinbase)交易用于凭空产生比特币。

挖矿交易只有一个输 入,该输入有一个“coinbase”参数,没有scriptSig,“coinbase”中的数据可以是任意内容,它不会被使用。

挖矿交易的输出金额在一段时间内是固定值,现在是12.5个比特币。输出地址可以是任何地址,一般是矿工或矿池的比特币地址。

找零地址

在实际的交易中,假设A有一个比特币地址,并且包含着没有花费的10个比特币,B也有一个比特币地址,里面一分钱没有。当A向B支付10个比特币时,此时就不需要找零钱的问题。

假设A的地址上有35个比特币(如图1-2所示),当A想向B支付8个 比特币时,如图所示,只需要使用包含着20个比特币的那一笔未消费支出,并设置好要支持的金额即可,剩下的12个比特币则会返回给A,以便A在将来可以继续使用。

image-20230721170933653

这样就有了一个找零机制,实际上,比特币在交易时会把消费时所用的地址(消费地址)的余额设置为零。当需要支付的金额小于可用余额时,在交易信息中必须告诉比特币网络零钱将要被发送至哪个地址, 即“找零地址”。找零地址可能是也可能不是原先的发送地址。

隐私的保证 根据设计,每一笔比特币交易将在一个称为“区块链”的全球性的公共总账上永久可见,这就意味着任何人随时都可以在上面进行跟踪查询。通过将某个比特币地址与其使用者关联起来,好事者都可以据此绘制关于这个人与他人之间的资金转移的关系图。但如果是将找回的零钱发送至一个新创建的地址,那么就可以让这种追踪变得更加困难。

假设从地址A发送比特币到地址B后,零钱返回地址为A,则区块链会揭示地址A向地址B支付了一笔钱。 同样的道理,如果有两个或两个以上地址参与其中,任何涉及这个接收零钱的找零地址都会揭示A作为支付方的交易。假如某个控制着的任何接收地址或付款地址的人其身份是众所周知的,那么其他有过交易往来的各方的身份也有可能被推断出来。

但加入说交易后的找零地址是新的C地址,如果没有更多的信息,其他人所能知道的,只有一个差分了地址A的余额至地址B和C,而地址B或C的主人可能是也可能不是A。

image-20230721171853609

区块和区块链

比特币网络中,数据会以文件的形式被永久记录,我们称这些文件为区块。一个区块是一些或所有最新比特币交易的记录集,且未被其他先前的区块记录。

区块结构

每个区块都包括了一个被称为“魔法数”的常数0xD9B4BEF9、区块的大小、区块头、区块所包含的交易数量及部分或所有的近期新交易。

在每个区块中,对整个区块链起决定作用的是区块头。

image-20230724162029765

区块头描述:

每个 区块都必须要指向前一个区块,否则无法通过验证。这个区块链条会一 直追溯到源头,也就是指向创世区块。很显然,创世区块的hashPrevBlock的值为零或为空。在区块头中,最关键的一个数据项是一个随机数Nonce,这串数字是一个答案,而这个答案对于每一个区块来说都是唯一的。它的特点如下:

  • 这个答案很难获得。

  • 有效答案有多个,不过我们只需要找到一个答案就可以了。

  • 其他节点对有效答案的验证很容易。

没有固定的算法可以求出答案,所以唯一 的做法就是不断尝试,找寻这个答案的做法就是“挖矿”。

区块内包含许多交易,他们通过Mekle根节点间接被散列,以保证矿工能及时追踪一个正在打包的区块内交易的变化情况。Merkle树是Hash的二叉树,在比特币中会两次使用SHA-256算法来生成Merkle树,如果叶子个数为奇数,则要重复计算最后一个叶子的两次SHA-256值。

举例来说,有啊a,b,c三笔交易,Merkle根的生成过程如下:

1
2
3
4
5
6
7
d1 = dhash(a)
d2 = dhash(b)
d3 = dhash(c)
d4 = dhash(c) #奇数,计算两边
d5 = dhash(d1 concat d2)
d6 = dhash(d3 concat d4)
d7 = dhash(d5 concat d6)

创世块

创世块(Genesis Block)是指区块链的第一个区块,创世块的收益花不掉:比特币客户端把区块和交易分别存储在两个数据库中,当客户端发现区块数据库为空时,就会用代码直接生成一个创世块,但是没有把创世交易存储到交易数据库中,比特币网络一旦受到要花掉创世交易输出的交易时,因为在交易数据库中找不到创世交易,因而都会被拒绝。

区块链原理

区块链是所有比特币节点共享的交易数据库,这些节点基于比特币 协议参与到比特币网络中来。

由于每个区块包含前一个区块的Hash值,这就使得从创世块到当前 块形成了一条块链,每个区块必定按时间顺序跟随在前一个区块之后。

image-20230724163129833

如果一个区块是最长块链的最后一个区块,那么诚实的矿工只会在 这个区块的基础上生成后续块。如果一个区块链中的所有区块和交易均有效,则该区块链有效,并且要以创世块开头。当两个区块产生的时间仅相差几秒时,可能会产生包含一个区块的分叉,当出现以上现象时,矿工节点会根据收到区块的时间,在先收到的区块的基础上继续挖矿。

挖矿和矿池

挖矿原理与区块的产生

比特币的挖矿和节点软件是基于对等网络、数字签名来发起和验证交易的。节点向网络广播交易,这些广播出来的交易需要经过矿工的验证,矿工们会用自己的工作证明结果来表达确认,确认后的交易会被打包到数据块中,数据块回春起来形成连续的数据块链。

每一个比特币的节点都会收集所有尚未确认的交易,并且会将其归集到一个数据块中,这个数据块将和前面一个数据块集成在一起。矿工节点会附加一个随机调整数,并计算前一个数据块的SHA-256Hash运算 值。挖矿节点不断进行重复尝试,直到它找到的随机调整数使得产生的 Hash值低于某个特定的目标为止。

当挖矿时,你会经常对区块头进行散列,你正在挖的区块也会时常进行更新。

网络调整时间 如果当前区块的时间戳大于前11个区块的平均时间戳,并且小于“网络调整时间(Network-Adjusted Time)”+2小时,则认 为该时间戳是有效的。其中的“网络调整时间”是指与你相连接的所有节点的平均时间。当节点A连接到节点B时,A将从B处得到一个UTC的时间戳,A先将其转换成本地UTC并保存起来,网络调整时间等于所有节点的本地UTC时间+所有相连节点的偏移量平均值,然而,该网络时间永远不会调整到超过本地系统时间70分钟以上。

Nonce随机数通常都不会相同,但是它以严格的线性方式在增长,从0开始,每次执行散列时都会增长,当Nonce溢出时(此事经常发生),挖矿交易的extraNonce项就会增长,其将改变Merkle树的根节点。

挖矿难度

挖矿难度是对挖矿困难程度的度量,即指计算符合给定目标的一个Hash值的困难程度。比特币网络有一个全局的区块难度,有效的区域必须有一个Hash值,该Hash值必须小于给定的目标Hash值,矿池也会有一个自定义的共享难度。

难度每过2016块就会改变一次,计算公式为: difficulty=difficulty_1_target/current_target

其中,目标(target)是一个256位长的数值。

矿池原理与商业模式

为了激励计算力较低的用户继续参与挖矿,矿池就出现了。在一个矿池里,许多不同的人贡献出自己的计算力来生成一个区块,然后再根据每个人的贡献比例来分发奖励。

矿池是比特币(Bitcoin)等P2P密码学虚拟货币开采所必需的基础设施,一般是对外开放的团队开采服务器。其存在的意义是提升比特币开采的稳定性,使矿工薪酬趋于稳定。关于矿池挖矿的方式,目前存在有Slush,Pay-per-Share,Luke-Jr,Triplemining,P2Pool,Puddinpop,其中有代表性的两个是:

Pay-Per-Share:该方式为立即支付每一个share支付报酬,该支付来源于矿池现有的比特币资金,因此可以立即取现,但将风险转移给了矿池的运营者

P2Pool:P2Pool的挖矿节点工作在类似于比特币区块链的一种shares链上没由于没有中心,不会受到DoS攻击,99%的奖励(50BTC+交易费用)会平均分配给矿工,另外0.5%会奖励给生成区块的人。

脚本系统

比特币在交易中使用脚本系统脚本是简单的、基于堆栈的,并且是从左向右处理的。

一个典型的发送比特币到目标地址D的脚本,要求接收者提供以下两个条件,才能花掉发给他的比特币:

1)一个公钥,当进行散列生成比特币地址时,生成的地址是嵌入在脚本中的目标地址ID

2)一个签名,用于证明接收者保存了与上述公钥相对应的私钥。

原先发送比特币的一方,控制脚本运行,以便比特币在下一个交易中使用。想花掉币的另一方必须把以前记录的运行为真的脚本,放到输入区。

换句话说:在一个交易中,输出脚本是数学题,输入脚本是题解,但不是这道数学题的题解。

假设有这么一系列交易,如下:

image-20231201101108527

这一系列交易具有如下特征:

  • 都是单输入单输出交易
  • 每个输入交易输出交易中,都包含对应的脚本
  • 交易a为A转给B,交易b为B转给C,交易c为C转给D
  • 当前交易的输入都引用前一个交易的输出,如交易b的输入就是引用交易a的输出

合约应用案例

每个交易都有一个锁定时间,使得该交易处于特定状态并且可被新 交易替换,直至锁定时间来临。

示例1:提供押金证明

假设你注册了一个账号在某个网站,你希望在网站运营者出建立你的信用,一个可行的方法就是向网站付点钱购买信用,但如果你关闭了账号,可能想要回这部分钱,你对该网站的信任程度不足一将钱存到该网站,另一方面,该网站某天会消失。

建立信用度的目的是你做出某种贡献,让网站知道你不是一个垃圾机器人。对于该问题,可以通过合约来解决:

1)用户和网站相互发送各自新生成的公钥。

2)用户创建交易TX1(支付交易),该交易支出10个BTC到网站 地址,用户创建了TX1但不广播。

3)用户把TX1交易的Hash值发送给网站。

4)网站使用TX1的Hash值创建交易TX2(合约),TX2花掉TX1的 钱并且支付到用户地址。nLocKt ime被设置成未来时间(比如六个月之后),输入的序列号为0。

5)最终,这个不完整的交易TX2(一半已签名)被回送给用户, 用户检查合约是否如预期的一样在执行,即六个月后10BTC最终会回到 他的地址(除非情况有变)。

6)用户先广播TX1,再广播TX2。

在这个阶段,用户和网站都不能单独得到10BTC。六个月之后,合 约完成,即使网站消失了,用户也能得到币。

如果用户想要提早关闭账号,又该怎么处理呢?网站创建新版的 TX2,nLocKt ime设为0,并且输入的序列号设为UINT_MAX,重新签 名,把该交易发回用户,用户签名后广播该交易,就能提早结束合约并 且释放10BTC。

如果该用户被证明是存在恶意行为的(例如:垃圾邮件发送 者),那么网站不会同意提早结束合约。如果用户有太多的滥用行为, 则网站可以要求增加存款数量,或者要求延长合约时间。

示例2:担保和争端调解

一个买家想和他不认识或不信任的某人进行交易,当交易出现问题 时,他想有一个第三方——也许是一个专业的争端调解服务来决定谁能拿到钱。

该示例的实现步骤具体如下。

1)和商家一起引入一个调解员(如:ClearCoin)。

2)得到商家的公钥K1,得到调解员的公钥K2,创建自己的公钥 K3。

3)把K2发给商家,商家生成一个随机数挑战调解员,调解员用K2 的私钥签名,用来证明K2确实属于调解员。

4)创建一个交易TX1,使用如下输出脚本并且广播该交易。

1
2<K1><K2><K3>3CHECKMULTISIGVERIFY

现在这些币被锁定了,如果要解锁这些币,需要使用以下几种方 式。

客户和商家同意(无论是成功的交易,还是在没有调解的情况下 商家同意回退给客户)。

客户和调解者同意(失败的交易,调解者认同客户,客户得到退 款)。

调解者和商家同意(商品已经发送,尽管有争议,商家还是得到 币)。

示例3:保证合约

保证合约是建造公众商品时的集资办法,公众商品是指一旦建成, 任何人都可以免费享受到好处的商品。标准的例子是灯塔,所有人都认 同应该建造一个,但是对于航海者个人来说灯塔太贵了,而且灯塔不只 是他一个人用得着,同时也会方便其他的航海者。

一个解决方案就是向所有人集资,只有当筹集的资金超过所需的建 造成本时,每个人才真正付钱;如果集资款不足,则谁都不用付钱。

1)主办方创建新的捐赠地址,宣布如果筹集资金超过1000BTC, 则将建造该商品,任何人都可以捐赠。

2)捐赠者创建一个新交易,把一定数量的钱打到集资地址上,但 是他们并不广播该交易。该交易与常规的交易相似,但有三个不同点: 首先,不能做任何改变,如果你没有正确的输出金额1000BTC,那么你 必须先创建一个;第二,输入脚本要以 SIGHASH_ALL|SIGHASH_ANYONECANPAY的模式签名;最后,输出 值是1000BTC,注意,这不是一个有效的交易,因为输出值比输入值大 得多。

3)把交易上传到主办方的服务器上,他们把交易保存到磁盘上, 随时更新捐赠的币数量。

4)一旦服务器获得了足够的币,它将把所有捐赠者上传的独立交 易合并成一个新的交易,该交易只有一个输出,仅仅是把钱付到捐赠地 址,该输出与每个捐赠者的交易的输出部分相同,而输入部分则是所有 捐赠者输入的集合。

5)广播完整的交易,发送捐赠的币到捐赠地址中。

SIGHASH_ALL是默认模式,意味着要签名所有交易的内容,除了输入脚本。SIGHASH_ANYONECANPAY是附加的指示器,意味着签名仅覆盖自己的输入部分,而不会覆盖其他人的输入,这样一来,其他人的输 入可以留空。

示例4:使用外部状态

考虑一个例子,老人想让他的孙子继承遗产,继承时间是在他死后,或者在孙子年满18岁时,无论先满足哪个条件,他的孙子都可以得到遗产。

为了解决这个问题,老人首先向他自己发送孙子要继承的资产数量,以便有一个正确的继承数量的唯一输出;接着,他创建了一个带有锁定时间的交易,该交易的意思是:在孙子18岁生日时,把币支付到孙 子的地址中,老人对该交易签名,不进行广播,直接把该交易给了孙子。当过了孙子的18岁生日之后,孙子广播了这个交易并且得到他的币。孙子可以在这个时间之前广播该交易,但他不会提前得到币,有些节点会在内存池中把这种交易丢弃掉,因为锁定时间在遥远的将来。

示例5:跨链交易

比特币技术可以用来创建多个独立的货币,与比特币实现理念相同的山寨币,可以在有限信任的条件下与比特币进行自由交易。

1)A产生一些随机数据X(秘密)。

2)A产生TX1交易(支付)包含了带跨链交易脚本的输出。它允许 币以A和B共同签名的方式释放,也可以以私密X和B签名的方式释放, 该交易未广播,块链的释放脚本包含了私密的Hash值,并非真正的私密 X本身。

3)A产生TX2(合约),花掉TX1并且输出到A的地址,该交易有 个未来的锁定时间,输入的序列号为0,因而可以被替换。A签名TX2并 且发送给B,B给TX2签名后发送回A。

4)A广播TX1和TX2,B可以看到币但是不能花掉它们,因为并没 有输出到B的地址,该交易还没有终结。

5)B在山寨币块链上执行相同的操作,B的锁定时间应该大于A的 锁定时间,双方的交易都待定但未完全。

6)因为A知道私密X,A能马上申报他的币,然而,A在申报币的 过程中,向B释放了私密X,所以B可以以私密X和签名B来完成山寨币 块链的交易。

区块链进阶

挖矿算法解析

PoW挖矿算法及分析

PoW(Proof of Work),即工作证明。也就是说,你获得多少货币,取决于你挖矿贡献的有效工作,比如,你的电脑性能越好,分给你的矿就会越多,即根据你的工作证明来执行货币的分配。

挖矿算法的本质是通过一个Hash函数找到满足当前难度的Nonce,矿工用一些交易来构建候选区块,他会计算这个区块头Hash的值, 看其是否小于当前目标值,如果这个值小于目标值,矿工就会修改这个 Nonce的值,然后再试一次。通常来说一个矿工会做成千上万次Hash运算,从而得到一个合适的Nonce的值,使得区块头Hash满足当前难度。 这也是PoW(工作量证明)算法的由来。

一个可参考的解析:https://www.jianshu.com/p/b23cbafbbad2

PoS股权证明算法

PoS(Proof of Stake),即股权证明。它是根据你持有货币的量和时间,给你发利息的一个制度。在股权证明模式下,有一个名词叫币龄,每个币每天产生1币龄,例如你持有100个币,总共持有了30天,那么,此时你的币龄就为3000。

以现有的比特币运行发展情况来看,比特币每年的挖矿产量都在不断减半,我们可以预计,随着比特币产量的不断降低,矿工人数也会越来越少,这样就会导致整个比特币网络的稳定性出现问题。当矿工人数降低时,比特币很可能会被一 些高算力的人或团队进行51%攻击,如果采用PoS体系,你即便拥有了 全网51%的算力,也未必能够进行51%攻击,因为这还要求攻击者持有全球51%的货币量,而这是很难达到的。

Sidechains

Sidechains(侧链)实质上不是指特定的某个区块链,而是指那些遵守侧链协议的所有区块链,这个词是针对比特币主链来说的。侧链协议是指可以让比特币安全地从比特币主链转移到其他区块链,同时又可以让其他区块链上的货币安全返回到比特币主链的一种协议。

侧链的提出主要是基于以下几个原因。

(1)应对其他区块链的应用威胁

(2)比特币核心开发组不欢迎附生链

(3)Blockstream商业化的考虑