【Blockchain Development Guide】Blocks and Transactions of Blockchain Basics

Reprinted from: https://blog.csdn.net/pure_lady/article/details/78654570


In a blockchain network, all data is recorded on each node in the form of blocks. And each block is saved on the local disk of the node as a separate file. In Bitcoin (Linux system), all block information is saved in the ~/.bitcoin/blocks/directory and blk***.datmarked with the file name, as shown in the following figure:

blocks

block structure

According to https://en.bitcoin.it/wiki/Block , the block structure is as follows:

Field describe size
Magic no "magic number", constant 0xD9B4BEF9 4 bytes
Blocksize block size 4 bytes
Blockheader block header 80 bytes
Transaction counter number of transactions, positive integer 1 - 9 bytes
transactions Transaction list -many transactions

First a "magic number", which is described as a constant 4 bytes, then 4 bytes for the block size, then 80 bytes for the block header, then 1-9 bytes for the number of transactions, and finally is all transactions. But in the actual Bitcoin code, it is not so defined.

class CBlock : public CBlockHeader
{
public:
    // network and disk
    std::vector<CTransactionRef> vtx;

    // memory only
    mutable bool fChecked;

    // ...

    CBlockHeader GetBlockHeader() const
    {
        CBlockHeader block;
        block.nVersion       = nVersion;
        block.hashPrevBlock  = hashPrevBlock;
        block.hashMerkleRoot = hashMerkleRoot;
        block.nTime          = nTime;
        block.nBits          = nBits;
        block.nNonce         = nNonce;
        return block;
    }

    std::string ToString() const;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

It can be found that only the block header and all transactions are actually defined, which may be the difference between different versions, but the variables in the above table are not defined in the past versions of bitcoin code on github, so I think the actual structure should be defined in the code.

Let's take a look at the structure of the block header, https://en.bitcoin.it/wiki/Block_hashing_algorithm

Field Purpose update time Large and small (Bytes)
Version block version number When upgrading software and specifying a new version number 4
hashPrevBlock 前一个区块的256-bit 哈希值 产生新的区块 32
hashMerkleRoot Merkle树根的256-bit 哈希值 收到了新的交易 32
Time 从 1970-01-01 00:00 UTC到现在为止的时间间隔,单位为秒 每几秒 4
Bits 当前POW的目标哈希值的压缩形式 难度调整时 4
Nonce 32-bit 随机数 尝试新的hash时 4

每个区块头都包含前一个区块的哈希值,所以所有的区块就像链表一样连成了一条链,链的头部就是创世块(Genesis Block)。所有的交易都以Merkle tree的形式进行索引,并在block header中保存Merkle tree的树根,如果当前交易数量是奇数的话,那么最后一个交易将会被计算两次哈希值。当前POW的难度以压缩的形式保存在4个字节的Bits中,最后通过mining找到的随机数记录在最后的Nonce中。

交易结构

关于比特币交易,更好的参考是比特币官方文档https://en.bitcoin.it/wiki/Transaction,解释的很详细。

交易是在区块链网络中传输的最基本的数据结构,所有有效的交易最终都会被打包进区块中并保存在区块链上,比特币中交易的数据结构如下,

Field 描述 大小
Version no 版本号,当前为1 4 bytes
In-counter 输入交易数量,正整数 1 - 9 bytes
list of inputs 输入列表,每个区块中第一个交易被称为“Coinbase” -many inputs
Out-counter 输出交易数量,正整数 1 - 9 bytes
list of outputs 输出列表,每个区块中第一个输出交易是给矿工的奖励 -many outputs
lock_time 锁定时间,如果非0并且小于0xFFFFFFFF,那么就是指块序号;如果交易已经终结,那么就是指时间戳 4 bytes

一个简单的交易输入如下:

Input:
Previous tx: f5d8ee39a430901c91a5917b9f2dc19d6d1a0e9cea205b009ca73dd04470b9a6
Index: 0
scriptSig: 304502206e21798a42fae0e854281abd38bacd1aeed3ee3738d9e1446618c4571d10
90db022100e2ac980643b0b82c0e88ffdfec6b64e3e6ba35e7ba5fdd7d5d6cc8d25c6b241501
  • 1
  • 2
  • 3
  • 4
  • 5

首先是前一笔交易的哈希值(Previous tx),然后是花费的是第几个输出(Index),最后是解锁脚本(scriptSig),其中解锁脚本=签名+公钥,只有提供正确的解锁脚本,才能花费对应的交易。

一个简单的输出如下:

Output:
Value: 5000000000
scriptPubKey: OP_DUP OP_HASH160 404371705fa9bd789a2fcd52d2c580b65d35549d
OP_EQUALVERIFY OP_CHECKSIG
  • 1
  • 2
  • 3
  • 4

首先是输出金额(Value),然后是锁定脚本,锁定脚本包括脚本系统中的一系列操作符。

交易类型

比特币目前提供了两种不同的交易类型,如下所示。通过这两者类型的交易可以组合出更加复杂的交易,称之为合约。

(1)Pay-to-PubkeyHash

scriptPubKey: OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
scriptSig: <sig> <pubKey>
  • 1
  • 2

这个也是最常见的交易,目标地址就是比特币地址,花费时需要提供签名和公钥。

(2)Pay-to-Script-Hash(P2SH)

scriptPubKey: OP_HASH160 <scriptHash> OP_EQUAL 
scriptSig: ..signatures... <serialized script>
  • 1
  • 2

在P2SH中,目标地址由脚本哈希取代,解锁脚本中才包含签名和脚本内容。下面有两种类型的交易的对比,首先是普通的多签名脚本,解锁脚本中只需要5个公钥中任意两个私钥的签名即可。

Locking Script 2 PubKey1 PubKey2 PubKey3 PubKey4 PubKey5 5 OP_CHECKMULTISIG
Unlocking Script Sig1 Sig2

然后是P2SH脚本,

Redeem Script 2 PubKey1 PubKey2 PubKey3 PubKey4 PubKey5 5 OP_CHECKMULTISIG
Locking Script OP_HASH160 <20-byte hash of redeem script> OP_EQUAL
Unlocking Script Sig1 Sig2 redeem script

可以看出锁定脚本中只需要包括Redeem Script的哈希即可,而不用包含长长的一串公钥信息,具体的脚本内容由解锁脚本提供,相当于是将交易的大部分内容交给了交易花费者去处理,从而减少了网络传输的数据。根据《Master Bitcoin》所述,与直接使⽤复杂脚本以锁定输出的⽅式相⽐,P2SH具有以下特点:

  • 在交易输出中,复杂脚本由简短电⼦指纹取代,使得交易代码变短。
  • 脚本能被编译为地址,⽀付指令的发出者和⽀付者的⽐特币钱包不需要复杂⼯序就可以执⾏P2SH。
  • P2SH将构建脚本的重担转移⾄接收⽅,⽽⾮发送⽅。
  • P2SH shifts the burden of long script data storage from the output side (stored in the UTXO set, affecting memory) to the input side (stored only in the blockchain).
  • P2SH shifts the burden of long-script data storage from the present (when paid) to the future (when spent).
  • P2SH transfers the transaction fee cost of the long script from the sender to the receiver, and the receiver must include a redemption script when using the funds.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326042043&siteId=291194637