区块链的时间戳 timelock区块链

古泉财经 95 0

今天给各位分享timelock区块链的知识,其中也会对区块链的时间戳进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!

lock contract在区块链里是什么意思

意思是锁定合约。

锁定合约包含哈希锁定(Hashlock)以及时间锁定(Timelock)两个部分,哈希时间锁定合约最典型的代表就是比特币的闪电网络,闪电网络提供一个可扩展的微支付通道,用以提升链外的交易处理能力,使用哈希锁定将发起方的交易代币进行锁定,并通过时间锁定让接收方在某个约定的时刻前生成支付的密码学证明,并与先前约定的哈希值一致,则可完成交易。

怎样通过RPC命令实现区块链的查询

基本架构如下:

前端web基于socket.io或者REST实现,

后端加一层mongodb/mysql等数据库来代替单机leveldb做数据存储

目的应该是:

1. 加速查询

2. 做更高层的数据分析

3.做分布式数据库

思考:

这些online的查询固然可以方便我们的日常用, 那如何与相关应用集成呢? 我们是否可以通过简单的rpc命令实现同等的效果?

有几个用处:

1 . 大家都可以做自己的qukuai.com或blockchain.info的查询:)

2. 集成RPC命令到自己的店铺,收款后查询用

3. 集成到钱包应用

4. 其他应用场景

cmd分析:

根据高度height查block hash

./bitcoin-cli getblockhash 19999

00000000ba36eb929dc90170a96ee3efb76cbebee0e0e5c4da9eb0b6e74d9124

2. 然后根据block hash查block 信息

./bitcoin-cli getblock 00000000ba36eb929dc90170a96ee3efb76cbebee0e0e5c4da9eb0b6e74d9124

{

"hash" : "00000000ba36eb929dc90170a96ee3efb76cbebee0e0e5c4da9eb0b6e74d9124",

"confirmations" : 263032,

"size" : 215,

"height" : 19999,

"version" : 1,

"merkleroot" : "c1b09fa6bdc0b12b15cc1400d598ffed29dd33b2e282093a48646d1b7b380c98",

"tx" : [

"c1b09fa6bdc0b12b15cc1400d598ffed29dd33b2e282093a48646d1b7b380c98"

],

"time" : 1248291140,

"nonce" : 1085206531,

"bits" : "1d00ffff",

"difficulty" : 1.00000000,

"chainwork" : "00000000000000000000000000000000000000000000000000004e204e204e20",

"previousblockhash" : "000000006eb5c2799b0f5fafab6435daeecef8e7f609b731c9879c3f74f28c73",

"nextblockhash" : "00000000770ebe897270ca5f6d539d8afb4ea4f4e757761a34ca82e17207d886"

}

3. 根据tx查询单笔交易的信息:

没建index时,只能查询自己钱包的信息,若不是钱包的交易,则返回如下:

./bitcoin-cli getrawtransaction c1b09fa6bdc0b12b15cc1400d598ffed29dd33b2e282093a48646d1b7b380c98

error: {"code":-5,"message":"Invalid or non-wallet transaction id"}

那怎么办呢? 直接分析代码找原因:

// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock

bool GetTransaction(const uint256 hash, CTransaction txOut, uint256 hashBlock, bool fAllowSlow)

{

CBlockIndex *pindexSlow = NULL;

{

LOCK(cs_main);

{

if (mempool.lookup(hash, txOut))

{

return true;

}

}

if (fTxIndex) {

CDiskTxPos postx;

if (pblocktree-ReadTxIndex(hash, postx)) {

CAutoFile file(OpenBlockFile(postx, true), SER_DISK, CLIENT_VERSION);

CBlockHeader header;

try {

file header;

fseek(file, postx.nTxOffset, SEEK_CUR);

file txOut;

} catch (std::exception e) {

return error("%s : Deserialize or I/O error - %s", __func__, e.what());

}

hashBlock = header.GetHash();

if (txOut.GetHash() != hash)

return error("%s : txid mismatch", __func__);

return true;

}

}

if (fAllowSlow) { // use coin database to locate block that contains transaction, and scan it

int nHeight = -1;

{

CCoinsViewCache view = *pcoinsTip;

CCoins coins;

if (view.GetCoins(hash, coins))

nHeight = coins.nHeight;

}

if (nHeight 0)

pindexSlow = chainActive[nHeight];

}

}

if (pindexSlow) {

CBlock block;

if (ReadBlockFromDisk(block, pindexSlow)) {

BOOST_FOREACH(const CTransaction tx, block.vtx) {

if (tx.GetHash() == hash) {

txOut = tx;

hashBlock = pindexSlow-GetBlockHash();

return true;

}

}

}

}

return false;

}

详解比特币挖矿原理

可以将区块链看作一本记录所有交易的公开总帐簿(列表),比特币网络中的每个参与者都把它看作一本所有权的权威记录。

比特币没有中心机构,几乎所有的完整节点都有一份公共总帐的备份,这份总帐可以被视为认证过的记录。

至今为止,在主干区块链上,没有发生一起成功的攻击,一次都没有。

通过创造出新区块,比特币以一个确定的但不断减慢的速率被铸造出来。大约每十分钟产生一个新区块,每一个新区块都伴随着一定数量从无到有的全新比特币。每开采210,000个块,大约耗时4年,货币发行速率降低50%。

在2016年的某个时刻,在第420,000个区块被“挖掘”出来之后降低到12.5比特币/区块。在第13,230,000个区块(大概在2137年被挖出)之前,新币的发行速度会以指数形式进行64次“二等分”。到那时每区块发行比特币数量变为比特币的最小货币单位——1聪。最终,在经过1,344万个区块之后,所有的共20,999,999.9769亿聪比特币将全部发行完毕。换句话说, 到2140年左右,会存在接近2,100万比特币。在那之后,新的区块不再包含比特币奖励,矿工的收益全部来自交易费。

在收到交易后,每一个节点都会在全网广播前对这些交易进行校验,并以接收时的相应顺序,为有效的新交易建立一个池(交易池)。

每一个节点在校验每一笔交易时,都需要对照一个长长的标准列表:

交易的语法和数据结构必须正确。

输入与输出列表都不能为空。

交易的字节大小是小于MAX_BLOCK_SIZE的。

每一个输出值,以及总量,必须在规定值的范围内 (小于2,100万个币,大于0)。

没有哈希等于0,N等于-1的输入(coinbase交易不应当被中继)。

nLockTime是小于或等于INT_MAX的。

交易的字节大小是大于或等于100的。

交易中的签名数量应小于签名操作数量上限。

解锁脚本(Sig)只能够将数字压入栈中,并且锁定脚本(Pubkey)必须要符合isStandard的格式 (该格式将会拒绝非标准交易)。

池中或位于主分支区块中的一个匹配交易必须是存在的。

对于每一个输入,如果引用的输出存在于池中任何的交易,该交易将被拒绝。

对于每一个输入,在主分支和交易池中寻找引用的输出交易。如果输出交易缺少任何一个输入,该交易将成为一个孤立的交易。如果与其匹配的交易还没有出现在池中,那么将被加入到孤立交易池中。

对于每一个输入,如果引用的输出交易是一个coinbase输出,该输入必须至少获得COINBASE_MATURITY (100)个确认。

对于每一个输入,引用的输出是必须存在的,并且没有被花费。

使用引用的输出交易获得输入值,并检查每一个输入值和总值是否在规定值的范围内 (小于2100万个币,大于0)。

如果输入值的总和小于输出值的总和,交易将被中止。

如果交易费用太低以至于无法进入一个空的区块,交易将被拒绝。

每一个输入的解锁脚本必须依据相应输出的锁定脚本来验证。

以下挖矿节点取名为 A挖矿节点

挖矿节点时刻监听着传播到比特币网络的新区块。而这些新加入的区块对挖矿节点有着特殊的意义。矿工间的竞争以新区块的传播而结束,如同宣布谁是最后的赢家。对于矿工们来说,获得一个新区块意味着某个参与者赢了,而他们则输了这场竞争。然而,一轮竞争的结束也代表着下一轮竞争的开始。

验证交易后,比特币节点会将这些交易添加到自己的内存池中。内存池也称作交易池,用来暂存尚未被加入到区块的交易记录。

A节点需要为内存池中的每笔交易分配一个优先级,并选择较高优先级的交易记录来构建候选区块。

一个交易想要成为“较高优先级”,需满足的条件:优先值大于57,600,000,这个值的生成依赖于3个参数:一个比特币(即1亿聪),年龄为一天(144个区块),交易的大小为250个字节:

High Priority 100,000,000 satoshis * 144 blocks / 250 bytes = 57,600,000

区块中用来存储交易的前50K字节是保留给较高优先级交易的。 节点在填充这50K字节的时候,会优先考虑这些最高优先级的交易,不管它们是否包含了矿工费。这种机制使得高优先级交易即便是零矿工费,也可以优先被处理。

然后,A挖矿节点会选出那些包含最小矿工费的交易,并按照“每千字节矿工费”进行排序,优先选择矿工费高的交易来填充剩下的区块。

如区块中仍有剩余空间,A挖矿节点可以选择那些不含矿工费的交易。有些矿工会竭尽全力将那些不含矿工费的交易整合到区块中,而其他矿工也许会选择忽略这些交易。

在区块被填满后,内存池中的剩余交易会成为下一个区块的候选交易。因为这些交易还留在内存池中,所以随着新的区块被加到链上,这些交易输入时所引用UTXO的深度(即交易“块龄”)也会随着变大。由于交易的优先值取决于它交易输入的“块龄”,所以这个交易的优先值也就随之增长了。最后,一个零矿工费交易的优先值就有可能会满足高优先级的门槛,被免费地打包进区块。

UTXO(Unspent Transaction Output) : 每笔交易都有若干交易输入,也就是资金来源,也都有若干笔交易输出,也就是资金去向。一般来说,每一笔交易都要花费(spend)一笔输入,产生一笔输出,而其所产生的输出,就是“未花费过的交易输出”,也就是 UTXO。

块龄:UTXO的“块龄”是自该UTXO被记录到区块链为止所经历过的区块数,即这个UTXO在区块链中的深度。

区块中的第一笔交易是笔特殊交易,称为创币交易或者coinbase交易。这个交易是由挖矿节点构造并用来奖励矿工们所做的贡献的。假设此时一个区块的奖励是25比特币,A挖矿的节点会创建“向A的地址支付25.1个比特币(包含矿工费0.1个比特币)”这样一个交易,把生成交易的奖励发送到自己的钱包。A挖出区块获得的奖励金额是coinbase奖励(25个全新的比特币)和区块中全部交易矿工费的总和。

A节点已经构建了一个候选区块,那么就轮到A的矿机对这个新区块进行“挖掘”,求解工作量证明算法以使这个区块有效。比特币挖矿过程使用的是SHA256哈希函数。

用最简单的术语来说, 挖矿节点不断重复进行尝试,直到它找到的随机调整数使得产生的哈希值低于某个特定的目标。 哈希函数的结果无法提前得知,也没有能得到一个特定哈希值的模式。举个例子,你一个人在屋里打台球,白球从A点到达B点,但是一个人推门进来看到白球在B点,却无论如何是不知道如何从A到B的。哈希函数的这个特性意味着:得到哈希值的唯一方法是不断的尝试,每次随机修改输入,直到出现适当的哈希值。

需要以下参数

• block的版本 version

• 上一个block的hash值: prev_hash

• 需要写入的交易记录的hash树的值: merkle_root

• 更新时间: ntime

• 当前难度: nbits

挖矿的过程就是找到x使得

SHA256(SHA256(version + prev_hash + merkle_root + ntime + nbits + x )) TARGET

上式的x的范围是0~2^32, TARGET可以根据当前难度求出的。

简单打个比方,想象人们不断扔一对色子以得到小于一个特定点数的游戏。第一局,目标是12。只要你不扔出两个6,你就会赢。然后下一局目标为11。玩家只能扔10或更小的点数才能赢,不过也很简单。假如几局之后目标降低为了5。现在有一半机率以上扔出来的色子加起来点数会超过5,因此无效。随着目标越来越小,要想赢的话,扔色子的次数会指数级的上升。最终当目标为2时(最小可能点数),只有一个人平均扔36次或2%扔的次数中,他才能赢。

如前所述,目标决定了难度,进而影响求解工作量证明算法所需要的时间。那么问题来了:为什么这个难度值是可调整的?由谁来调整?如何调整?

比特币的区块平均每10分钟生成一个。这就是比特币的心跳,是货币发行速率和交易达成速度的基础。不仅是在短期内,而是在几十年内它都必须要保持恒定。在此期间,计算机性能将飞速提升。此外,参与挖矿的人和计算机也会不断变化。为了能让新区块的保持10分钟一个的产生速率,挖矿的难度必须根据这些变化进行调整。事实上,难度是一个动态的参数,会定期调整以达到每10分钟一个新区块的目标。简单地说,难度被设定在,无论挖矿能力如何,新区块产生速率都保持在10分钟一个。

那么,在一个完全去中心化的网络中,这样的调整是如何做到的呢?难度的调整是在每个完整节点中独立自动发生的。每2,016个区块(2周产生的区块)中的所有节点都会调整难度。难度的调整公式是由最新2,016个区块的花费时长与20,160分钟(两周,即这些区块以10分钟一个速率所期望花费的时长)比较得出的。难度是根据实际时长与期望时长的比值进行相应调整的(或变难或变易)。简单来说,如果网络发现区块产生速率比10分钟要快时会增加难度。如果发现比10分钟慢时则降低难度。

为了防止难度的变化过快,每个周期的调整幅度必须小于一个因子(值为4)。如果要调整的幅度大于4倍,则按4倍调整。由于在下一个2,016区块的周期不平衡的情况会继续存在,所以进一步的难度调整会在下一周期进行。因此平衡哈希计算能力和难度的巨大差异有可能需要花费几个2,016区块周期才会完成。

举个例子,当前A节点在挖277,316个区块,A挖矿节点一旦完成计算,立刻将这个区块发给它的所有相邻节点。这些节点在接收并验证这个新区块后,也会继续传播此区块。当这个新区块在网络中扩散时,每个节点都会将它作为第277,316个区块(父区块为277,315)加到自身节点的区块链副本中。当挖矿节点收到并验证了这个新区块后,它们会放弃之前对构建这个相同高度区块的计算,并立即开始计算区块链中下一个区块的工作。

比特币共识机制的第三步是通过网络中的每个节点独立校验每个新区块。当新区块在网络中传播时,每一个节点在将它转发到其节点之前,会进行一系列的测试去验证它。这确保了只有有效的区块会在网络中传播。

每一个节点对每一个新区块的独立校验,确保了矿工无法欺诈。在前面的章节中,我们看到了矿工们如何去记录一笔交易,以获得在此区块中创造的新比特币和交易费。为什么矿工不为他们自己记录一笔交易去获得数以千计的比特币?这是因为每一个节点根据相同的规则对区块进行校验。一个无效的coinbase交易将使整个区块无效,这将导致该区块被拒绝,因此,该交易就不会成为总账的一部分。

比特币去中心化的共识机制的最后一步是将区块集合至有最大工作量证明的链中。一旦一个节点验证了一个新的区块,它将尝试将新的区块连接到到现存的区块链,将它们组装起来。

节点维护三种区块:

· 第一种是连接到主链上的,

· 第二种是从主链上产生分支的(备用链),

· 第三种是在已知链中没有找到已知父区块的。

有时候,新区块所延长的区块链并不是主链,这一点我们将在下面“ 区块链分叉”中看到。

如果节点收到了一个有效的区块,而在现有的区块链中却未找到它的父区块,那么这个区块被认为是“孤块”。孤块会被保存在孤块池中,直到它们的父区块被节点收到。一旦收到了父区块并且将其连接到现有区块链上,节点就会将孤块从孤块池中取出,并且连接到它的父区块,让它作为区块链的一部分。当两个区块在很短的时间间隔内被挖出来,节点有可能会以相反的顺序接收到它们,这个时候孤块现象就会出现。

选择了最大难度的区块链后,所有的节点最终在全网范围内达成共识。随着更多的工作量证明被添加到链中,链的暂时性差异最终会得到解决。挖矿节点通过“投票”来选择它们想要延长的区块链,当它们挖出一个新块并且延长了一个链,新块本身就代表它们的投票。

因为区块链是去中心化的数据结构,所以不同副本之间不能总是保持一致。区块有可能在不同时间到达不同节点,导致节点有不同的区块链视角。解决的办法是, 每一个节点总是选择并尝试延长代表累计了最大工作量证明的区块链,也就是最长的或最大累计难度的链。

当有两个候选区块同时想要延长最长区块链时,分叉事件就会发生。正常情况下,分叉发生在两名矿工在较短的时间内,各自都算得了工作量证明解的时候。两个矿工在各自的候选区块一发现解,便立即传播自己的“获胜”区块到网络中,先是传播给邻近的节点而后传播到整个网络。每个收到有效区块的节点都会将其并入并延长区块链。如果该节点在随后又收到了另一个候选区块,而这个区块又拥有同样父区块,那么节点会将这个区块连接到候选链上。其结果是,一些节点收到了一个候选区块,而另一些节点收到了另一个候选区块,这时两个不同版本的区块链就出现了。

分叉之前

分叉开始

我们看到两个矿工几乎同时挖到了两个不同的区块。为了便于跟踪这个分叉事件,我们设定有一个被标记为红色的、来自加拿大的区块,还有一个被标记为绿色的、来自澳大利亚的区块。

假设有这样一种情况,一个在加拿大的矿工发现了“红色”区块的工作量证明解,在“蓝色”的父区块上延长了块链。几乎同一时刻,一个澳大利亚的矿工找到了“绿色”区块的解,也延长了“蓝色”区块。那么现在我们就有了两个区块:一个是源于加拿大的“红色”区块;另一个是源于澳大利亚的“绿色”。这两个区块都是有效的,均包含有效的工作量证明解并延长同一个父区块。这个两个区块可能包含了几乎相同的交易,只是在交易的排序上有些许不同。

比特币网络中邻近(网络拓扑上的邻近,而非地理上的)加拿大的节点会首先收到“红色”区块,并建立一个最大累计难度的区块,“红色”区块为这个链的最后一个区块(蓝色-红色),同时忽略晚一些到达的“绿色”区块。相比之下,离澳大利亚更近的节点会判定“绿色”区块胜出,并以它为最后一个区块来延长区块链(蓝色-绿色),忽略晚几秒到达的“红色”区块。那些首先收到“红色”区块的节点,会即刻以这个区块为父区块来产生新的候选区块,并尝试寻找这个候选区块的工作量证明解。同样地,接受“绿色”区块的节点会以这个区块为链的顶点开始生成新块,延长这个链。

分叉问题几乎总是在一个区块内就被解决了。网络中的一部分算力专注于“红色”区块为父区块,在其之上建立新的区块;另一部分算力则专注在“绿色”区块上。即便算力在这两个阵营中平均分配,也总有一个阵营抢在另一个阵营前发现工作量证明解并将其传播出去。在这个例子中我们可以打个比方,假如工作在“绿色”区块上的矿工找到了一个“粉色”区块延长了区块链(蓝色-绿色-粉色),他们会立刻传播这个新区块,整个网络会都会认为这个区块是有效的,如上图所示。

所有在上一轮选择“绿色”区块为胜出者的节点会直接将这条链延长一个区块。然而,那些选择“红色”区块为胜出者的节点现在会看到两个链: “蓝色-绿色-粉色”和“蓝色-红色”。 如上图所示,这些节点会根据结果将 “蓝色-绿色-粉色” 这条链设置为主链,将 “蓝色-红色” 这条链设置为备用链。 这些节点接纳了新的更长的链,被迫改变了原有对区块链的观点,这就叫做链的重新共识 。因为“红”区块做为父区块已经不在最长链上,导致了他们的候选区块已经成为了“孤块”,所以现在任何原本想要在“蓝色-红色”链上延长区块链的矿工都会停下来。全网将 “蓝色-绿色-粉色” 这条链识别为主链,“粉色”区块为这条链的最后一个区块。全部矿工立刻将他们产生的候选区块的父区块切换为“粉色”,来延长“蓝色-绿色-粉色”这条链。

从理论上来说,两个区块的分叉是有可能的,这种情况发生在因先前分叉而相互对立起来的矿工,又几乎同时发现了两个不同区块的解。然而,这种情况发生的几率是很低的。单区块分叉每周都会发生,而双块分叉则非常罕见。

比特币将区块间隔设计为10分钟,是在更快速的交易确认和更低的分叉概率间作出的妥协。更短的区块产生间隔会让交易清算更快地完成,也会导致更加频繁地区块链分叉。与之相对地,更长的间隔会减少分叉数量,却会导致更长的清算时间。

比特币如何防止篡改

比特币网络主要会通过以下两种技术保证用户签发的交易和历史上发生的交易不会被攻击者篡改:

非对称加密可以保证攻击者无法伪造账户所有者的签名;

共识算法可以保证网络中的历史交易不会被攻击者替换;

非对称加密

非对称加密算法3是目前广泛应用的加密技术,TLS 证书和电子签名等场景都使用了非对称的加密算法保证安全。非对称加密算法同时包含一个公钥(Public Key)和一个私钥(Secret Key),使用私钥加密的数据只能用公钥解密,而使用公钥解密的数据也只能用私钥解密。

请点击输入图片描述

图 2 - 非对称加密特性

比特币使用了非对称加密算法保证每一笔交易的安全,网络中的每一个账户(地址)都是一对秘钥中的公钥,账户的所有者会持有私钥,下面就是一对刚刚生成的比特币地址和私钥4:

Address:     13RTT8MsbAj7o4zL7w4DNNuuwhgGgHqLnK

Private Key: 469d998dd4db3dfdd411fa56574e52b6be318f993ca696cc5c683c45e8e147eb

需要注意的是,使用网站生成比特币地址和私钥是极其危险的做法,我们并不清楚网站是否会存储私钥,所以建议使用比特币的客户端生成公私钥对。

任何人通过上面的地址 13RTT8MsbAj7o4zL7w4DNNuuwhgGgHqLnK 都可以向该账号转账;账号的持有者也可以使用私钥签名交易向其他地址转账,当我们想要向比特币网络中提交一笔新的交易时,需要先构建一个如下所示的交易结构:

{

  "txid":"5be7a9e47f56c98e5297a44df52da0475f448ece98bb51489103cdf70653092f",

  "hash":"5be7a9e47f56c98e5297a44df52da0475f448ece98bb51489103cdf70653092f",

  "version":1,

  "size":224,

  "vsize":224,

  "locktime":0,

  "vin": [...],

  "vout": [...],

  "hex":"0100000001a90b4101e6cbb75e1ff885b6358264627581e9f96db9ae609acec98d72422067000000006b483045022100c42c89eb2b10aeefe27caea63f562837b20290f0a095bda39bec37f2651af56b02204ee4260e81e31947d9297e7e9e027a231f5a7ae5e21015aabfdbdb9c6bbcc76e0121025e6e9ba5111117d49cfca477b9a0a5fba1dfcd18ef91724bc963f709c52128c4ffffffff02a037a0000000000017a91477df4f8c95e3d35a414d7946362460d3844c2c3187e6f6030b000000001976a914aba7915d5964406e8a02c3202f1f8a4a63e95c1388ac00000000",

  "blockhash":"0000000000000000000c23ca00756364067ce5e815deb5982969df476bfc0b5c",

  "confirmations":5,

  "time":1521981077,

  "blocktime":1521981077

}

接下来,我们可以使用持有的私钥对整个交易中的全部字段进行签名,然后将签名与交易打包并发送到网络中等待比特币网络的确认就可以了。

在比特币的所有地址中,35hK24tcLEWcgNA4JxpvbkNkoAcDGqQPsP 地址中目前持有 250,000 多个 Bitcoin5,目前的市值大概为 20 亿美元。在只知道地址的情况下,我们来算一下获取该地址对应的私钥需要多长时间。比特币的私钥总共有 256 位,即 22562256 中可能性:

115792089237316195423570985008687907853269984665640564039457584007913129639936115792089237316195423570985008687907853269984665640564039457584007913129639936

目前我们没有较为快捷的破解手段,只能使用暴力破解计算私钥。假设我们使用 IBM 在 2018 年推出的超级计算机 Summit6,它能每秒能做 1.4∗10171.4∗1017 次浮点数计算,假设该计算机可以每秒计算相同次数的公私钥对(计算公私钥对远比一次浮点数计算复杂),想要找到存放 20 亿美元资产的地址对应的私钥需要如下所示的时间:

1.15∗1077365∗86400∗1.4∗1017=2.9∗1052年1.15∗1077365∗86400∗1.4∗1017=2.9∗1052年

我们整个宇宙的存在时间也只是破解该私钥时间的几十亿分之一,所以在目前的计算能力没有革命性突破的前提下,想要通过暴力破解的方式获取公钥对应的私钥只有理论上的可能性,在实践中是完全不可能的7。

共识算法

MySQL 等数据库以行为单位存储数据,而比特币这个分布式数据库中存储的基本单位是区块,区块通过哈希指针连接就会构成一棵树,如下图所示,图中绿色的最长链就是网络的主链。

请点击输入图片描述

图 3 - 区块链和主链

如何让网络中的所有节点对下一个区块中的内容达成共识是比特币需要解决的关键问题,只有让节点对数据达成一致才会保证过去的交易不会被篡改,但是作为在公网运行的分布式数据库,它面对的场景非常复杂,需要解决拜占庭将军问题下的分布式一致性问题。

拜占庭将军问题是 Leslie Lamport 在 The Byzantine Generals Problem 论文中提出的分布式领域的容错问题,它是分布式领域中最复杂、最严格的容错模型8。在该模型下,系统不会对集群中的节点做任何的限制,它们可以向其他节点发送随机数据、错误数据,也可以选择不响应其他节点的请求,这些无法预测的行为使得容错这一问题变得更加复杂。

拜占庭将军问题描述了一个如下的场景,有一组将军分别指挥一部分军队,每一个将军都不知道其它将军是否是可靠的,也不知道其他将军传递的信息是否可靠,但是它们需要通过投票选择是否要进攻或者撤退:

请点击输入图片描述

图 4 - 拜占庭将军问题

区块链技术使用 共识算法 和激励让多个节点在拜占庭将军场景下实现分布式一致性。比特币使用如下的规则让多个节点实现分布式一致性:

引入工作量证明 — 让节点在提交新的区块之前计算满足特定条件的哈希,取代传统分布式一致性算法中,一人一票(或者一节点一票)的设定;

引入最长链是主链的设定 — 只有主链上的交易才被认为是合法交易;

引入激励 — 提交区块的节点可以获得比特币奖励;

通过以上的规则,各个节点会在最长的链上计算哈希,努力提交合法的区块。然而一旦节点中有人掌握了 51% 以上的计算能力,它能通过强大的算力改变区块链的历史。因为区块具有连续性,所以前一个区块的改变会使后一个区块计算的哈希失效,如图 4 所示,如果攻击者需要改变主链中的倒数第三个黄色区块,它需要连续构建四个区块才能完成对历史的篡改,其他的节点才会在这条更长的链上继续计算:

请点击输入图片描述

图 4 - 51% 攻击

1使用如下所示的代码可以计算在无限长的时间中,攻击者持有 51% 算力时,改写历史 0 ~ 9 个区块的概率9:

#include

#include

double attackerSuccessProbability(double q, int z) {

   double p = 1.0 - q;

   double lambda = z * (q / p);

   double sum = 1.0;

   int i, k;

   for (k = 0; k = z; k++) {

       double poisson = exp(-lambda);

       for (i = 1; i = k; i++)

           poisson *= lambda / i;

       sum -= poisson * (1 - pow(q / p, z - k));

   }

   return sum;

}

int main() {

   for (int i = 0; i 10; i++) {

       printf("z=%d, p=%f\\n", i, attackerSuccessProbability(0.51, i));

   }

   return 0;

}

通过上述的计算我们会发现,在无限长的时间中,占有全网算力的节点能够发起 51% 攻击修改历史的概率是 100%;但是在有限长的时间中,因为比特币中的算力是相对动态的,比特币网络的节点也在避免出现单节点占有 51% 以上算力的情况,所以想要篡改比特币的历史还是比较困难的,不过在一些小众的、算力没有保证的一些区块链网络中,51% 攻击还是极其常见的10。

防范 51% 攻击方法也很简单,在多数的区块链网络中,刚刚加入区块链网络中的交易都是未确认的,只要这些区块后面追加了数量足够的区块,区块中的交易才会被确认。比特币中的交易确认数就是 6 个,而比特币平均 10 分钟生成一个块,所以一次交易的确认时间大概为 60 分钟,这也是为了保证安全性不得不做出的牺牲。不过,这种增加确认数的做法也不能保证 100% 的安全,我们也只能在不影响用户体验的情况下,尽可能增加攻击者的成本。

总结

研究比特币这样的区块链技术还是非常有趣的,作为一个分布式的数据库,它也会遇到分布式系统经常会遇到的问题,例如节点不可靠等问题;同时作为一个金融系统和账本,它也会面对更加复杂的交易确认和验证场景。比特币网络的设计非常有趣,它是技术和金融两个交叉领域结合后的产物,非常值得我们花时间研究背后的原理。

比特币并不能 100% 防止交易和数据的篡改,文中提到的两种技术都只能从一定概率上保证安全,而降低攻击者成功的可能性也是安全领域需要面对的永恒问题。我们可以换一个更严谨的方式阐述今天的问题 — 比特币使用了哪些技术来增加攻击者的成本、降低交易被篡改的概率:

比特币使用了非对称加密算法,保证攻击者在有限时间内无法伪造账户所有者的签名;

比特币使用了工作量证明的共识算法并引入了记账的激励,保证网络中的历史交易不会被攻击者快速替换;

通过上述的两种方式,比特币才能保证历史的交易不会被篡改和所有账户中资金的安全。

什么是比特币的扩容?为什么要扩容?

每个区块大小是一兆,大概能容纳一千多条交易的信息,如果你上一个比特币区块链浏览器上去观看的话,你会查到现在每一个区块大概都是一兆左右,已经达到了区块容量的上限,如果比特币的网络的转账越来越多,很多交易就不会在交易发生后第一个发生的区块被打包和确认。可能要等好几个区块或者时间更长,在比特币的历史上曾经遭遇过几次粉尘攻击,其中就有很多交易者在交易所(币汇)制造大量的小额转账,粉尘攻击就是有人制造出大量的小额转账,使得网络中有大量的待确认的交易,导致正常的转账不能够被确认,确认时间被延迟,影响网络的正常运转。

很多交易者的交易等待两天或者是更久才得到确认,虽然粉尘攻击是非常极端的例子,但是看现在的比特币的网络,正常的转账量,已经远远超出了他能够承受的最大的容量,每个区块大小现在都是一兆,所以扩大比特币区块容量,突破现有一兆大小的限制,这个过程叫做扩容。

Payment Channel是什么?

微支付通道将是后面闪电网络、隔离见证timelock区块链的基础,微支付通道不能搞透彻,后面的闪电网络、隔离见证就更晕菜timelock区块链了。

现在的比特币网络每秒钟最多处理6到7笔交易,并且每笔交易还需要手续费。

如果买卖双方有大量的小额交易,微额交易,比如1个宽带提供商向外提供带宽服务,按小时付费。那大量的小额交易,不仅会让比特币网络负担沉重,而且手续费也不划算。

所以有人就提出了,在买卖双方,建立1个支付通道,专门支持双方的小额支付,不需要经过比特币网络。这个通道除了建立、关闭的时候,要和比特币网络通信,其timelock区块链他时间,都是双方点到点的通信。

我们知道,比特币网络至所以是可靠的、值得信任的,1个很重要的原因是因为每笔交易都是公开的,每1笔交易都是on-chain,都会得到网络上每个节点的认可,所以交易的任何1方没办法反悔、抵赖。

现在timelock区块链你要搞链下交易,off-chain Transaction,交易只有你们俩自己知道,没有了区块链网络这个信任的第3方,怎么保证交易的1方不会反悔、抵赖?

这个问题很有意思,接下来我们看看,微支付通道是如何解决这个问题的。

nLockTime

nLockTime(CLTV)与Sequence number(CSV),介绍了Transaction数据结构里面的1个关键属性。微支付通道的建立,必须依赖这个属性。下面就看一下这个过程是怎么建立的。

微支付通道建立过程

考虑如下场景:A是用户,B是一个数据提供商,B需要把1个100G的大数据文件发给A,价值是100元。

为了降低风险,A不想1次性把100元给B,而是每接收到1G的数据,给B支付1元。

那就需要100次的交易。现在看一下,微支付通道如何解决这个问题:

Step1:

用户A发起1笔交易,把100元打到1个公共账号上面(这个公共账号同时需要A,B的公钥,也就是前面所说的多重签名)。这笔钱,需要A,B2个人同时出具私钥,才能把钱取出来。这笔交易叫做保证金交易(Funding Transaction)。

Step2:

以此同时,用户A发起1笔退款交易(Refund Transaction)。这笔退款交易的输入,就是Step1里面的交易,其目的是把Step1里面的100元,再返回给用户A。这笔交易的nLockTime为一个0的值,也就是该笔交易是Hold在那的,不会立即生效。

具体怎么做呢? 用户A先把这笔交易发给B,让B用B的死钥签名(也就是写在scriptSig里面),再返回给A,A把这个Refund Transaction 攒在手上,这笔交易其实是A的一个保底的措施,保证前面的100元不会永远拿不回来。

Step3:

我们知道,在Step2的Refund Transaction里面,有2个输出:A,100元;B,0元。

现在把Step2的Refund Transaction拷贝1份,调整一下输出:A, 99元;B, 1元。也就是付给B1元。

然后A把这个交易发给B,B保留这个交易,不广播到网络上。

等A收到B的新的1G文件之后,重新调整输出,变成: A,98;B,2元。A,B重新签名,A再把这个交易发给B。

如此,不断继续下去:

A: 98,B,2;

A:97,B,3;

。。

A:1, 99。

这些交易,称为updated Transaction(或者叫做Commitment Transaction),只会在A,B之间传递,不会广播到网络上。

Step4:

等A收到最后的1个G的文件,发起1个Settlement Transaction。这里交易里面,

A:0元, B:100元。

其nLockTime = 0,B收到这个交易,广播到网络上,交易立即生效,B收到100元。

(1)整个过程,我们会看到,只有Step1的Funding Transaction和Step4的Settlement Transaction会广播到网络上,1头1尾,2个交易。

(2)如何避免B跑路,A的钱永远锁死在公共账号里面?

在第1步里面,A把钱打到了1个公共账号上面。如果B跑了,A的钱不是永远提不出来了?实际不是这样操作的:实际是,A会等到Step2里面,拿到Refunding Transaction之后,A才会把Step1里面的Transaction发给B,同时广播到网络上面。

Refunding Transaction就相当于A攒在手里的,B的把柄。A不用把这个交易广播出去,等到B跑路了,再拿出来广播到网络上。

(3)如何避免A跑路,B拿不到自己的钱?

在Step3里面,每个update Transaction,都有A,B共同的签名。如果A跑路了,B就把最新的update Transaction广播到网络上,该交易被执行,B就会拿到最新的钱。

update Transaction,就相当于B攒在手里的,A的把柄。

update transaction有个特点,每1次update transaction的nLockTime,都是逐级减小的,所以B把最新的update transaction广播到网络上之后,肯定会被最先打包,最先执行。先前其他的update transaction就不会被执行了。

(4)如何避免B篡改交易内容,比如调大给自己的分成比例?

任何1笔交易里面,都是先让B签名,再返回给A,A再签名,再发给B。

每笔交易里面都有A,B的双重签名,B改了交易内容,和A的签名就对不上了,反过来,A改了交易内容,就和B的签名对不上了。

所以A,B都不可能更改篡改交易内容!!

(5)如何防止A双花这笔钱?

在Step2里面,A拿到了Refund Transaction,A把这个交易广播到网络上,拿回这100元,再花到别处呢?

做不到。因为Refund Transaction有nLockTime,处于锁定状态。并且这个nLockTime 后面的任何1笔updated Transaction的值。

说到这,我们就明白了,A,B如何做到在off-chain的情况下,保证双方都没办法反悔、抵赖交易:

A手上拿的有B的把柄,B手上拿的有A的把柄。任何1方中途中断,另我1方,把这个把柄广播到区块链网络,就可以执行合约,拿到属于自己的钱。

上面说的微支付通道,解决了A给B转账的,大量小额交易问题,但它也有几个缺点:

(1)它是单向的,只能用来A给B转账。如果反过来,需要另外再建立1个B到A的通道。

(2)nLockTime的限制。假设B跑路了,A也要等到Refund Transaction的nLockTime到期了,才能拿回自己的钱;同样,假设A跑路了,B也要等到updated Transaction的nLockTime到期了,拿到属于自己的钱。

这些问题都如何解决呢,这就要看接下来的“闪电网络”了。

关于timelock区块链和区块链的时间戳的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。

标签: #timelock区块链

  • 评论列表

留言评论