探索比特币的区块和交易体结构

一、区块结构

Block #476060 一个高度为476060的块,区块高度从 1 开始,依次累加

Number Of Transactions      1757                    表示这个区块中的交易记录总数

Output Total         14663.80477993 BTC         本区块的输出总金额

Estimated Transaction Volume      4086.01378568       预估交易量

Transaction Fees        1.20988498       交易总手续费

Height         476060        本区块的高度

Timestamp          2017-07-16 10:13:10        生成区块的时间戳 

Received Time    2017-07-16 10:13:10        收到区块的时间 

Relayed By           F2Pool             本区块的打包者(开采者) F2Pool是比特币的矿池

Difficulty        804525194568.13       开采难度,要每 10 分钟出一个区块,需要调整难度

Bits             402742748        Bit位数表示区块开采难度的指数和系数,后面详细解释   

Size            999.981KB      本区块的数据大小,不到1M

Version        0x20000002       本区块开采所遵循的协议的版本号

Nonce          2859714985       参与 Hash碰撞计算成功的随机数

Block Reward 12.5 BTC      开采奖励:      12.5个比特币

最后三个哈希值:本区块的哈希值,上个区块的哈希值,下个区块的哈希值

Merkle Root 交易默克尔树的根,用来分段验证区块中包含交易的正确性、真实性、完整性。

重点解释一下开采难度:

在比特币区块头中的"Bits"字段是一个紧凑的表示形式,用来表示区块的难度目标(difficulty target)。这个难度目标是挖矿过程中必须要达到的一个数值,以确保新产生的区块符合网络的难度要求。

难度目标是一个256位的数,但是为了节省空间,比特币协议使用了一种称为“紧凑格式”(compact format)的方法来表示这个数。Bits字段是一个32位的字段,由两部分组成:

  1. 指数部分(Exponent): Bits字段的前两位字节表示难度目标的指数部分。
  2. 系数部分(Coefficient): Bits字段的后六位字节表示难度目标的系数部分。

Bits字段实际上是一个科学记数法表示的数,其中系数部分是一个24位的数,指数部分则决定将这个数值乘以2的多少次幂。这允许网络以一个相对较小的数值来表示一个非常大的难度目标。

例如,如果Bits的值是0x1b0404cb,这个值可以被分解为:

  • 系数(Coefficient): 0x0404cb(即263235十进制)
  • 指数(Exponent): 0x1b(即27十进制)

要将这个紧凑表示的数转换为难度目标,我们将系数乘以2的(指数-3)次幂(因为系数是3个字节,所以要减去3)。所以实际的难度目标是:

这个计算结果是一个非常大的数,它表示了挖矿时有效区块哈希值的上限。有效的哈希值必须小于或等于这个难度目标,这样的哈希值被认为是“在目标之下”("below the target"),从而使区块有效。

随着时间的推移,比特币网络会根据前2016个区块的产生速度调整难度目标,以确保平均大约每10分钟产生一个新区块。这个调整通过改变Bits字段的值来实现。

【扩展说明】

一个比特币区块可以被视为一个数据包,它包含了一段时间内发生的所有交易记录。每个区块都有一个严格的结构,以下是一个区块通常包含的所有数据内容:

  1. 区块头(Block Header):

    • 版本号(Version): 指示遵循的特定区块链规则。
    • 前一个区块的哈希值(Previous Block Hash): 这是一个哈希指针,指向链中前一个区块的头部,用于将区块串联起来形成区块链。
    • 默克尔根(Merkle Root): 这是一个由区块中所有交易的哈希值经过特定算法处理得到的单一哈希值,用于快速验证区块中交易数据的完整性。
    • 时间戳(Timestamp): 区块创建的大致时间。
    • 难度目标(Difficulty Target): 表示挖矿的难度,用于确保区块产生的速率大致恒定。
    • 随机数(Nonce): 一个只能使用一次的随机数,矿工在挖矿过程中不断变更随机数,直到找到一个符合难度目标的区块哈希值。
  2. 交易计数器(Transaction Counter):

    • 表明该区块包含多少笔交易。
  3. 交易列表(Transactions):

    • 每笔交易包含以下信息:
      • 交易版本号(Version): 指示交易遵循的规则。
      • 输入(Inputs):
        • 前一个交易的引用(Previous Tx Hash): 引用之前一笔交易的哈希值。
        • 输出索引(Output Index): 指出特定的输出。
        • 解锁脚本/见证(ScriptSig/Witness): 提供证明以证实交易发起者有权使用引用的比特币。
        • 序列号(Sequence): 通常用于表示交易的版本,或者在某些类型的交易中用于替代时间锁定。
      • 输出(Outputs):
        • 价值(Value): 要发送的比特币数量。
        • 锁定脚本(ScriptPubKey): 设置接收这些比特币的条件。
      • 锁定时间(Locktime): 指定交易可以被添加到区块链的最早时间。

每个区块的大小上限是1MB(虽然随着隔离见证(SegWit)的实施,这个上限在一定程度上变得更加复杂),因此一个区块能包含的交易数量取决于这些交易的大小。

这些数据结合起来,使得比特币区块不仅可以记录转移价值的交易,还能确保整个网络的安全和一致性。通过将区块连成链,比特币网络可以防止双重支付并保证交易不可篡改。

二、交易结构

下面是在区块浏览器中找的一笔真是交易(Transaction: 547db737e911687488c7cc4118e0ad03a6f0165c02678592f32835a3be54d557 | Blockchain.com

我以 json 格式进行各个字段的注释说明

{
  "txid": "547db737e911687488c7cc4118e0ad03a6f0165c02678592f32835a3be54d557", // 交易的唯一标识符(哈希值)
  "size": 225, // 交易的大小(字节)
  "version": 1, // 交易的版本号
  "locktime": 476049, // 交易的锁定时间,表明这笔交易在该区块高度或时间戳之前不能被确认
  "fee": 200000, // 交易的手续费(聪)
  "inputs": [ // 交易输入列表
    {
      "coinbase": false, // 表明这不是一个coinbase交易(非挖矿产生的交易)
      "txid": "21f6f5cb19eac94fb054f17d468a316e2e26e3ef139d2a0988fd61ac3c1b9b42", // 引用的前一笔交易ID
      "output": 62, // 引用的前一笔交易的输出索引号
      "sigscript": "4730440220435a59772e13b2b4b744028c716ac8acd27390b30718082df568f3cfeb59176a02202c8dcd6c2ee1677800297b865ae1e2f9c6fa18308eec0cb1cda6ac12b6aa4020012102909e6eb6adfc4dc2e8f7360738196d48f82ed55dc46e6d4e169a5ad7e82d4d4c", // 解锁脚本,包含签名等信息
      "sequence": 4294967294, // 输入的序列号
      "pkscript": "76a914cc24db7b01a585dd9365480a001e754990846f6f88ac", // 前一笔交易的锁定脚本
      "value": 3054223, // 输入的比特币数量(聪)
      "address": "1KcR12YkNLiFc7Px7TGvYv32DfuQxhLnWq", // 发送比特币的地址
      "witness": [] // 隔离见证数据,这里为空表示非隔离见证交易
    }
  ],
  "outputs": [ // 交易输出列表
    {
      "address": "1B8MmQnEPnb3Vi6pBJVk3xfXwA8EcQ9ikQ", // 接收比特币的地址
      "pkscript": "76a9146f1580ff43db9efd163aec3c67a58060a9dc596f88ac", // 锁定脚本
      "value": 1750000, // 输出的比特币数量(聪)
      "spent": true, // 是否已经被花费
      "spender": { // 花费这个输出的交易信息
        "txid": "1980488a3341c5022a17e6fabaf581187206334e2db02d45c78d89c82b41dfb0", // 花费交易的ID
        "input": 154 // 花费交易中的输入索引
      }
    },
    {
      "address": "16vokiX7ABVH2GCEm4ESH4Rnr6TGzhWHxU", // 接收比特币的地址
      "pkscript": "76a9144105b3f38bec4a4328d7ee7075576215bcbed8f988ac", // 锁定脚本,指定了如何花费这个输出,通常包含一个哈希值,只有提供了正确签名的交易才能解锁这些币
      "value": 1104223, // 输出的比特币数量,以聪为单位
      "spent": true,  // 这个字段表示这个输出是否已经被花费
      "spender": { // 如果这个输出已经被花费,这个对象提供了花费它的交易的信息
        "txid": "1208b7b40f9e07567f9d6f5216334be46b185cdb9699058830cbd9e09d186e6f", // 花费这个输出的交易的ID
        "input": 3 // 指示这个输出是花费交易中的第几个输入
      }
    }
  ],
  "block": { // 包含交易所在区块的信息
    "height": 476060, // 区块的高度
    "position": 1 // 交易在区块中的位置
  },
  "deleted": false, // 是否已删除,用于某些区块链的数据管理
  "time": 1500199990, // 交易的UNIX时间戳
  "rbf": false, // 是否可替代(Replace-By-Fee)
  "weight": 900 // 交易的权重,影响交易费用和区块中的位置
}

这个交易记录展示了一笔具体的交易,包括它的输入、输出、费用、所在区块以及其他元数据。

三、最小单位

  • 比特币的最小单位是聪 1 聪= 0.00000001 个比特币,对没错,就是中本聪的聪。

四、关于 UTXO 的说明

比特币的交易模型是基于所谓的UTXO(Unspent Transaction Outputs,未花费交易输出)结构的。在这个模型中,用户的比特币余额不是存储在一个"账户"或"钱包"中,而是由一系列未花费的交易输出组成。每个UTXO都代表了比特币网络上的一定数量的比特币,这些比特币可以被UTXO的所有者花费。

UTXO 结构

一个UTXO包含以下信息:

  • 金额(Value):这表示了UTXO所代表的比特币数量。
  • 所有者(Owner):这不是所有者的身份信息,而是一个加密密钥(通常是公钥的哈希),UTXO的所有者需要提供相应的私钥签名才能花费这些比特币。
  • 来源(Source):这通常是一个指向产生这个UTXO的交易ID和输出索引的引用,用于表明这个UTXO是从哪个特定的交易输出产生的。

UTXO 规则

UTXO遵循以下基本规则:

  1. 不可分割性:UTXO不能被部分花费。如果你想花费部分UTXO,你必须花费整个UTXO,然后找零给自己。
  2. 创建与消费:交易中的每个输入都是在之前交易中未花费的输出,即UTXO。每个交易输出可能成为未来交易的输入,即新的UTXO。
  3. 唯一性:一个UTXO一旦被花费,就不能再被使用。网络通过检查UTXO集合来防止双重支出。
  4. 不变性:UTXO一旦创建,在它被花费之前不会改变。它们只有两种状态:未花费或已花费。

举例说明

假设Alice拥有1个比特币,这1个比特币是一个UTXO,来源于交易A。现在Alice想要支付0.3个比特币给Bob。Alice会创建一个新的交易,交易B,具有以下特点:

  • 输入:引用交易A的输出,即Alice的UTXO。
  • 输出
    • 第一个输出是支付给Bob的0.3个比特币,这个输出将成为Bob的UTXO。
    • 第二个输出是0.7个比特币的找零,支付给Alice自己,这个输出将成为Alice新的UTXO。

一旦交易B被网络确认,原来的1个比特币UTXO就被消费了,不能再次使用。现在有两个新的UTXO:0.3个比特币属于Bob,0.7个比特币属于Alice。

这个过程可以用以下简化的JSON结构表示(假设每个字段都是经过简化的):

{
  "transactionA": { // 原始的交易,Alice获得1个比特币
    "outputs": [
      {
        "value": 1.0,
        "address": "Alice's Address",
        "spent": false
      }
    ]
  },
  "transactionB": { // Alice支付给Bob的交易
    "inputs": [
      {
        "txid": "transactionA ID",
        "output_index": 0,
        "sig": "Alice's Signature"
      }
    ],
    "outputs": [
      {
        "value": 0.3,
        "address": "Bob's Address",
        "spent": false
      },
      {
        "value": 0.7,
        "address": "Alice's New Address",
        "spent": false
      }
    ]
  }
}

在这个例子中,transactionA的输出被transactionB的输入引用,并且transactionB创建了两个新的输出,一个给Bob,一个作为Alice的找零。这些输出现在是新的UTXO,可以在未来的交易中被花费。

  • 22
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值