主页 > imtoken官方网址 > 比特币七笔交易的验证

比特币七笔交易的验证

imtoken官方网址 2023-03-08 07:18:20

7.交易验证7.1 前戏

下面描述的这些交易的验证其实是在区块体中,也就是一次次的交易,前面的就是区块头中的数据。

avatar

图片左上角的BTC-Output是指UTXO中前一个比特币的输出,右边的未花费为剩余的钱,已花费的为已花费的钱。本次交易共收到23笔交易,均为前文所述。

“以下是本次交易的具体内容”,肖先生说,我的理解是,这是merkle树中的一个节点。明确的交易内容。VIN和VOUT是数组,太长了,下面单独介绍。我认为下面的格式是不正确的,因为对于一个事务来说,vin 和 vout 并没有按照下面的方式存储。

avatar

**txid:** 交易id,交易id

**hash:** 交易的哈希值,不是nonce,那是什么?不知道

**version:** 使用的比特币协议的版本号

**size:** 本次交易的大小

**locktime:**交易的生效时间,一般为0,即刻生效。一些特殊的交易会使用这个值,比如一些交易会在 10 个区块后生效

**block hash:**这个block的hash值,这个必须是需要nonce的那个。

比特币买卖规则

**confirmations:**交易的确认信息,例如这里是23个区块的确认。

**time:** 交易产生的时间。时间和出块时间都和程序中的时间一样,都是绝对时间过去了多少秒。

**出块时间:**出块时间。

![头像][图片7.1-3]

**txid:** 每笔交易都必须注明币的来源。有些币可能有几个来源,因为一笔交易没有足够的钱比特币买卖规则,这里只有一个,数组中只有一个元素。

**vout:**表示上述txid交易的输出

**scriptSig:** 验证脚本,(不明白)这个值被输入脚本替换,不知道。解锁脚本。

![头像][图片7.1-4]

这个例子的输出有两个

**value:**转账金额,上面的单位是(/bitcoin),有些地方的单位是Satoshi,已经很小了,0.22684000 bitcoin是22684000Satoshi。不应小于 1 satoshi。

**n:** 前几个输出

**scriptPubkey:** 输出脚本,后面替换为输出脚本。锁定脚本

比特币买卖规则

交易的验证是通过脚本的成功执行来实现的。该脚本没有说使用 pthon 或 shell,而是使用 DSL 语言(领域特定语言)。该脚本非常简单,如下所述。

有两种类型的脚本,输出脚本(锁定脚本)和输入脚本(解锁脚本)。这两个名字比较形象。输出脚本是指有人转账给你时提供的vout,用于以后花这部分钱的时候验证。因此,这部分钱也可以“锁定”。在使用这部分钱的时候,根据加锁脚本的加锁方式,使用自己的私钥生成解锁脚本(即新交易的输入脚本)。如果组合脚本通过,说明提供解锁脚本的用户拥有UTXO,即有权使用这部分比特币。至于矿工会不会修改这部分交易的收款人,我不知道,

实际执行脚本时,两个脚本不会叠加,因为执行失败可能会导致锁脚本被污染,所以在执行10年更新的时候比特币买卖规则,分别执行两个脚本,结果两者是相同的。执行相反,首先执行输入脚本(解锁脚本),然后执行输出脚本(锁定脚本)。然而,为方便起见,将以下说明堆叠在一起。如果输入脚本有一条语句,输出脚本有两条,则相当于三个一起执行。详细请参考P2PK脚本的说明。A->B转移,B->C转移,输出脚本是指A->B的输出,输入脚本是指B->C的输入脚本。下面的解释以此为例。以下脚本的区别在于输出脚本和输入脚本需要提供不同的信息。

7.2 脚本指令

使用时请检查以下内容

7.3 P2PK 脚本(支付给公钥)

input script
    PUSHDATA(Sig)
output script
    PUSHDATA(PubKey)
    CHECKSIG

B 需要的只是他自己用私钥加密的签名。

先将签名Sig压栈,然后将公钥PubKey(B的公钥,因为Bibi需要证明他拥有那部分比特币)压栈,执行CHECKSIG,对PubKey进行哈希计算,检查是否它等于 Sig。

正如我之前所说,用私钥加密的东西只能用公钥解锁。所以b只需要用自己的私钥加密Sig,然后在解密的时候使用自己的PubKey,就可以了。既然两个键都可用,那么原文是什么?我不知道。

但是,这里有一个问题。如果输入脚本和输出脚本分开执行,CHECKSIG 检查时栈顶只有一个元素。如何检查?不过这个问题不是很重要,算了。

7.4 P2PKH(支付给公钥哈希)

比特币买卖规则

input script:
    PUSHDATA(Sig)
    PUSHDATA(PubKey)
output script:
    DUP
    HASH160
    PUSHDATA(PubKeyHash)
    EQUALVERIFY
    CHECKSIG

B 需要提供的只是用自己的私钥和自己的公钥加密的签名。输出脚本必须提供hash,因为hash不能从原文推导出来,而输入脚本提供了原文,但是可以得到hash。

1.将 B 的签名压入栈,在栈上:Sig

2.将B的公钥入栈,入栈:Sig, PubKey

3.复制栈顶元素,栈中:Sig,,PubKey,,PubKey

4. 计算栈顶元素的哈希值,栈中:Sig, PubKey, PubKeyHash

5.推送B的公钥哈希,入栈:Sig、PubKey、PubKeyHash、PubKeyHash

6.判断栈顶元素是否相等,栈内:Sig, PubKey

7.公钥解密签名验证

7.5 P2SH(支付到脚本哈希)和多重签名7.5.1 P2SH

这时,上一笔交易的输出脚本需要提供赎回脚本的哈希,而不是公钥的哈希。它分为两部分。第一步验证输入脚本给出的兑换脚本是否正确(如果你不知道兑换脚本是什么,你自然不会知道兑换脚本的hash是多少),第二步需要执行兑换脚本,验证成功。

输入脚本给的序列化redeemScript,什么是序列化和反序列化,看不懂。

比特币买卖规则

赎回脚本可以使用之前的方法,P2PK、P2PKH和多重签名的形式,因为P2SH的第二阶段和之前的没有区别。

input script
    PUSHDATA(Sig)
    PUSHDATA(serialized redeemScript)
output script
    HASH160
    PUSHDATA(redeemScriptHash)
    EQUAL

第一阶段:

1.将签名压入栈,在栈上:Sig

2.将脚本推入堆栈,堆栈:Sig,seriRs

3. 计算栈顶hash,栈内:Sig, RSH(redeemscript hash)

4.推送脚本哈希,入栈:Sig, RSH, RSH

5. 比较,堆栈:Sig

第二阶段:

例如兑换脚本使用P2PK

PUSHDATA(PubKey)
CHECHSIG

6.将公钥入栈,入栈:Sig, PubKey

比特币买卖规则

7.比较

7.5.2 已弃用的多重签名

我们先来谈谈多重签名。比如公司有5个人,4个人需要提供私钥才能花钱,或者7个人需要6个人才能花钱。它还提高了对丢失私钥的容错能力,一个人丢失私钥是可以的。

input script
    xxx
    PUSHDATA(Sig_1)
    PUSHDATA(Sig_2)
    ...
    PUSHDATA(Sig_M)
output script
    M
    PUSHDATA(pubkey_1)
    PUSHDATA(pubkey_2)
    ...
    PUSHDATA(pub_key_N)
    N
    CHECKMULTISIG

最上面的xxx是因为CHECKMULTISIG有bug,数据会被播放两次,所以给个xxx的浪费值。执行时,先输入M个签名,然后按M,N个公钥,N,最后执行CHECKMULTISIG进行多重签名。N>=M。

这种方法有一个缺点。例如,当向公司转账时,输出脚本由用户提供,因为用户支付了钱。如果公司的结构发生变化或转移到不同的公司,输出脚本将会改变。多重签名的复杂过程由接收方公司提供。

7.5.3 新的多重签名

如果使用 P2SH,用户只需要在生成交易时输入商店的兑换脚本哈希即可。如果修改了公司结构,用户只需要修改这个hash即可。当商店要花这部分钱时,他们提供兑换脚本。

avatar

过程不再赘述,同上。

7.8 燃烧证明

生成输出脚本时带上 RETURN。这个脚本的意思是,不管怎么执行,都会返回FALSE,意思就是把币送到了永远不能花掉的地方,不管输入脚本怎么写,都无法解锁。那么它有什么用呢?那里有两个。

有一个问题需要考虑。如果收款人的地址错了,比如地址可能根本不存在,钱就永远取不回来了?当然,所以有些人把需要记录的东西hash并写入收款人的地址,因为有些人经过hash后看起来像收款人的地址,所以节点看不到哪里出了问题。这样做肯定和使用 return Proof of Burn 一样,都省事,但这样好吗?答案是不。因为全节点根本不知道自己是死节点,会增加全节点的压力,所以不好返回。