什么是区块链?
- 一个由网络中的许多计算机更新和共享的公共数据库,
- "区块"指的是数据和状态是按顺序批量或"区块"存储的。 如果你向别人发送代币,需要将交易数据添加到一个区块中才算成功。
- "链"指的是每个区块加密引用其父块。 换句话说,区块被链接在一起。 在不改变所有后续区块的情况下,区块内数据是无法改变,但改变后续区块需要整个网络的共识。
名词解释
-
私钥、公钥、地址
- 公钥:公钥是经过椭圆曲线乘法得到的一个点 K = (x, y)。若:
x = F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A
y = 07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE52DDFE2E505BDB
则该公钥表示为:
K = 04F028892BAD7ED57D2FB57BF33081D5CFCF6F9ED3D3D7F159C2E2FFF579DC341A07CF33DA18BD734C600B96A72BBC4749D5141C90EC8AC328AE 52DDFE2E505BDB
- 加密货币之间的交易就是将加密货币从一个地址转移到另一个地址。
- 加密私钥:私钥必须高度保密,但这显然与可用性冲突。于是 BIP0038提案将私钥再次加密,用户必须输入密码解锁私钥后,才能使用私钥对交易进行签名。
- 公钥:公钥是经过椭圆曲线乘法得到的一个点 K = (x, y)。若:
-
transaction 交易:将加密货币从一个地址转移到另一个地址的过程。更准确地说,一个交易是经过签名的,代表价值传递的数据结构,这个数据结构中包括着加密货币发送地址/接收地址
- BTC 中不存在
余额
概念,每个新交易的输入皆是上一个交易的输出 - 创建交易:任何人都可以发起交易,这意味着,发起交易的人不一定是对交易签名的人。例如,财务创建交易,经由 CEO 签名后才有效。
- UTXO 未花费输出
- UTXO 是一个不可拆分的数据结构,每个 UTXO 锁定一个特定的所有者。
- BTC 中不存在余额,只有散布在区块链中的 UTXO。
- 向某人发送 BTC,即创建一个 UTXO 并注册到其地址。
- 若 UTXO 的金额比交易所需金额更大,也必须一次性消费完毕。简单来说,将 UTXO 支付到两个新创建的 UTXO 中,其中一个即收款方,另一个即地址为自己的 UTXO。
- Input & Output 输入 & 输出:每笔交易均包含了 1~n 个输出与 1~n 个输出。
- 输入:资金源,交易消费的 UTXO 即输入。
- 输出:收款方,交易创建的 UTXO 即输出。
- 输入/输出与账户、用户身份无关,应仅仅将其视为一笔笔被特定密钥锁定的资金。
- 交易脚本
- 锁定脚本/脚本公钥/ScriptPubKey:放置在输出上,锁定脚本设定 UTXO 被花费的条件。(通常来说,就是放置某人的公钥于其中,这样只有某人的私钥才能解锁)。
- 解锁脚本/脚本签名/ScriptSig:~~
- 交易类型
- P2PKH 支付到公钥哈希
- 锁定脚本中存储的是 PKH,由于PKH 比 PK 更短,故能降低交易难度。
- 解锁脚本需要同时提供 PK 与 SIG
- P2PK 支付到公钥
- 锁定脚本中存储的是 PK,解锁脚本仅需提供 SIG。
- 仅铸币时使用
- 多重签名
- P2SH 支付到脚本哈希
- 多重签名虽好,但由于需要提供多个公钥、私钥,导致脚本过大,增大交易难度。
- 生成脚本:首先,接收方会创建一个包含支出条件的脚本,这可能包括多重签名、时间锁等复杂逻辑(脚本非常大)。
- 计算脚本哈希:然后,对接收到的脚本进行哈希运算,得到一个脚本哈希值。
- 选择输入和输出:在交易输出部分,发送方将金额发送到前面生成的 P2SH 地址上,即发送到脚本哈希值对应的地址。
- 花费 P2SH 地址上的资金,当接收方需要花费存储在 P2SH 地址上的资金时,他们需要提供一个“赎回脚本”,这个脚本应该与最初创建 P2SH 地址时使用的脚本相匹配。
- P2PKH 支付到公钥哈希
- BTC 中不存在
-
wallet 加密货币钱包:保存个人所有加密货币地址和对应密钥的软件。
-
Double Spending Problem 双重支付问题:指的是同一笔资金被重复使用或花费多次的风险。加密货币采用如下方法避免双重支付。
- 区块链是一个分布式账本系统,记录了所有的交易。每一笔交易都会被广播到网络中的所有节点,然后通过共识机制(如工作量证明 PoW)来验证交易的合法性。只有当交易被多个节点验证并包含在区块中后,它才会被认为是有效的。这个过程确保了每个数字货币只能被使用一次。
- Proof-of-Work 工作量证明:矿工们通过竞争解决一个复杂的数学难题(通常是哈希函数问题)。这个难题需要大量的计算资源来解决,但验证解决方案的正确性却非常简单且迅速。当第一个正解被找到以后,其他节点验证该矿工所找到的解,如果解正确且符合网络的规则,该区块就会被添加到区块链中。通过这种方式,所有节点达成一致,即
共识
。
- Proof-of-Work 工作量证明:矿工们通过竞争解决一个复杂的数学难题(通常是哈希函数问题)。这个难题需要大量的计算资源来解决,但验证解决方案的正确性却非常简单且迅速。当第一个正解被找到以后,其他节点验证该矿工所找到的解,如果解正确且符合网络的规则,该区块就会被添加到区块链中。通过这种方式,所有节点达成一致,即
- Confirmations 确认:
交易确认
是指在区块链网络中,一个交易被矿工打包进区块并得到网络认可的过程。一旦一个交易被包含到区块中并被广播到网络上,它就有了一个确认
,后续每多一个区块被添加到链中,就多了一个确认
,通常 6 个以上确认就可认为该笔交易是不可撤销的。
- 区块链是一个分布式账本系统,记录了所有的交易。每一笔交易都会被广播到网络中的所有节点,然后通过共识机制(如工作量证明 PoW)来验证交易的合法性。只有当交易被多个节点验证并包含在区块中后,它才会被认为是有效的。这个过程确保了每个数字货币只能被使用一次。
- Hard Fork 硬分叉:是指当区块链软件协议发生改变时,未升级的节点将无法认可新的规则,因此会导致区块链分裂成两条不同的链。一条链继续遵循旧的规则,另一条链则遵循新的规则。这种情况通常发生在区块链社区内部就某些重大更新无法达成一致意见时,最终可能导致部分参与者选择跟随新的规则,而其他不愿意更新的参与者则继续维护原有的链,从而形成分叉。在这种情况下,如果节点不跟随大多数节点进行更新,它将无法与网络的其余部分同步,从而导致孤立。
比特币网络
- 完全节点和 SPV 节点的一个区别是:尽管二者都维护了区块链的全量副本(区块),但是 SPV 仅包括了每个区块的区块头;而完全节点还包括了每个区块的所有交易,因此完全节点可以独立验证任何交易。
SPV 节点验证交易
- 区块链深度:指的是本区块之上的新区块数量(把区块链想象成链栈)
- 区块链高度:指的是区块与创世区块之间的距离
- SPV 节点无法确定 UTXO 是否被花费,来确定交易的有效性,因此其验证交易的方式与完全节点不同
一个简单的例子:
A 游客带着城市的完整地图、攻略来旅游,对于任何一条巷子内是否有某家店,A 只需要查看地图、攻略即可。(完全节点)
B 游客空手来到城市旅游,对于任何一条巷子内是否有某家店,B 需要询问 A、以及其他手里有地图的人,以达到交叉应证,才能确定。(SPV 节点)
- 首先,利用默克尔路径建立
交易
和包含这笔交易的区块
间的联系; - 然后,SPV 节点一直等待直到当前区块上又堆叠了 6 个新区块,这样,就能确定该区块中的交易是有效的。
- 如果能满足堆叠 6 个区块的条件,SPV 节点能断定交易为真;但对于那些未能满足堆叠 6 个区块的条件,SPV 节点不能确定它们就是假的。
- 总而言之,完全节点通过检查当前区块以下的区块以确定 UTXO 是否未被使用;SPV 节点则通过检查当前区块以上是否新堆叠了 6 个区块来确定当前交易是否被其他人承认。
Bloom Filter 布隆过滤器
SPV 节点引入之后,为了避免这种特殊节点泄露用户信息,又继续引入了布隆过滤器。
回到上面那个例子
挖矿
- 节点收到交易后,若验证无误,则将其置入内存池(交易池),交易在这之中等待被纳入区块。
- 每个挖矿节点维护一个内存池,内存池中有许多交易,根据交易费用/交易额度/年龄,挖矿节点将交易划分为许多优先级,这个过程是动态的,并且每个挖矿节点的内存池,可能并不完全相同。
- 每个挖矿节点构建候选区块时,就按照优先级的顺序将交易纳入区块中。
- 之后,挖矿节点开始根据 PoW 竞争计算,第一个得出正确结果的挖矿节点 A,会将答案与候选区块一同向外传播。PoW 的特征就是计算答案特别复杂,但验证答案特别简单,因此,收到 A 发来的候选区块的其它节点,可以非常容易就验证其答案是否正确,若正确就向外传播。这样,就回到了第一步,形成闭环。
除此之外,这个过程中仍有一些注意点:
- BTC 网络非常巨大且复杂,因此,许多节点内维护的链条可能并不一致:这个不一致,不是指所有区块完全不一致,而是链条的最后几个区块不一致,这是由于网络传播的复杂环境导致的。不过,节点们最终会选择一条总和计算量最大的链为主链,以达成最终共识。这也与之前提到的,当前区块之后若再堆积了 6 个区块,则可视为稳定,道理一致。
Consesus 共识
比特币的去中心化共识是由4个过程的相互影响而自发产生的
- 各个完全节点独立验证每个交易。
- 通过证明 PoW 运算,挖矿节点独立将交易整合到新区块中。
- 每个节点独立验证新区块并将其整合进区块链。
- 每个节点独立选择累积进行了最多 PoW 计算的链条。
组装和选择区块链
比特币共识机制的第四个步骤是区块链的组装和选择最大累积工作量(最大难度)的区块链。
一旦节点完成一个新区块的验证,它将尝试将区块和已存在的区块链进行连接,形成新的链条。
节点维护着三套区块的集合:连接到主区块链的区块;形成主链分支的区块(次链);在已存在的链中均找不到父区块的新区块(孤儿)。只要不符合验证规则的任意一条,无效区块会立即被拒绝,不会被加入任何区块集合中。
“主链”在任何时候都是拥有最大累积难度的区块链。在大多数情况下,这也是含有区块最多的链,例外的情况是,同时存在两条长度一样的链,但其中一条的工作量证明更多。主链也可能存在分支,分支上有与主链区块存在同辈关系的区块。这些区块虽然同样是有效的,但不是主链的一部分。保留这些分支的目的在于,某些分支可能会在未来得以延伸,并在难度值上超过主链,那么后续的区块就会引用它们。在下一小节(“区块链分叉”)中,我们将看到由于几乎同时挖出了相同高度的区块,导致了次链的产生。
当节点接收到新区块时,会尝试将其插入已存在的区块链中。首先在区块中检查“前序区块哈希”字段,它是新区块对其父区块的引用。接着,在已存在的区块链中查找这个父区块。大多数时候,父区块会在主链的“顶端”,意味着新区块延长了主链。举例来说,新区块277316 有一个到其父区块277315的哈希的引用。大多数节点接收到区块277316前,在其主链上已经存在区块 277315,并处于区块链顶部,接收到277316 后将其链接在主链的最后。
每个节点均会独立验证交易,并且 只有在验证通过的情况下,才会继续向外传播
为什么说从公钥倒推私钥是不可能的
我们知道,私钥 X 生成点 = 公钥,生成点即选定椭圆曲线是上的一个点,曲线和生成点都是已知的。
那么为什么无法经由公钥得到私钥呢?
从简单的开始举例
如果问 7 + 7 = ? 自然是 14
难度升级后
如果问“几个七相加等于 56?” 我们当然能一口答出来, 8
个 7 相加就是 56。 因为这是九九乘法表。
难度再次升级后
如果问“几个七相加等于 8124814701956139841029841129060927509126581223941027350192751241341654132(私钥 256位二进制数,大小约等于七十多位十进制数)”,不借助纸笔/计算机,就很困难了。
与上述例子相同的是
,椭圆曲线密码也是一个基于加法阶数难求问题的密码方案
。
对于椭圆曲线密码来讲,椭圆曲线的基点就是例子里面的 7,而私钥就是基点的加法阶数(例子里面的 8),公钥是基点(7)进行对应阶数的加法(8次)得到的结果(56)。
与上述例子不同的是
,椭圆曲线密码里的加法建立在 “有限域上的二元三次曲线上的点”上 ,组成一个“有限加法循环群”。
具体的说,这个加法的几何定义如下面两个图:两个点的加法结果是指这两点的连线和曲线的交点关于 x 轴的镜像
。
可以看到,这里的加法是几何意义上的加法而非代数意义上的加法,不呈线性关系
此外,由于该加法的特殊定义两个点的加法结果是指这两点的连线和曲线的交点关于 x 轴的镜像
,P + Q 竟然 和 P + P 一样都等于 R。
之所以这么定义,原因有两个:
- 给求逆向运算(由公钥计算私钥)的时候制造困难。
- 为了构造一个封闭的“较好的”代数结构,简化正向运算(由私钥计算公钥的运算)。要是单纯为了求解困难,那可以定义五光十色的加法,但是加法定义的随性将导致了运算的复杂。为了能用一些最基本的运算:比如结合律、比如减法,才这么定义让这些点构成一个群。
(1)如何正向计算(由私钥计算公钥):
确定椭圆曲线一个点作为基点 P,由于所有的点构成一个有限群,那么基点 P 必然可以作为一个生成元生成一个子群。
记这个子群的阶数为 n,也就是说 P 点累加 n 次得到群的单位元(无穷远点),记做 nP = 0。(注意此处 0 只是一个代号,代指无穷远点,因为我们习惯了用 0 来表示加法单位元。)
正向计算的定义很简单,私钥为 0~2^256 ; 基点为点 P; 公钥点 Q 定义为 K 个 P 相加:
或者也可以写成 Q = P X K,但注意这里不是普通乘法,而是位于椭圆曲线上的点乘法。
由于椭圆曲线上的点相加并不是线性的,所以无法通过乘法直接相乘得到公钥(但在加法的基础上,可以利用双倍和加法、窗口法加速运算
),而通过公钥逆推私钥,就更不可能了。
(2)逆向计算(公钥反推私钥)有多难:
目前由椭圆曲线公钥求解私钥的最有效算法复杂度为
其中 P 是阶数 n 的最大素因子。当参数选的足够好让 P > 2^160 时,以目前的计算能力,攻破椭圆曲线是不现实的。