比特币&区块链与交易

— 交易与脚本 —

前言

区块的内容就是交易,下面介绍比特币的具体交易,也就是账单的内容。
但是对于其中脚本的部分,也了解甚微。在这里就提个大概。

比特币钱包

首先需要了解一些专用词

名词解释

比特币地址:比特币地址是一个由数字和字母组成的字符串,比特币“账户”的唯一标识,如: 1JwSSubhmg6iPtRjtyqhUYYH76Zg3Lfy1T (以1或3开头,长度25字节;base58解码后,为34或35个字符)。有地址对应“密钥”的人,拥有这个地址里的比特币

公钥:有两种形式:压缩与非压缩;早期使用非压缩(65字节,0x04开头),现在默认压缩(32字节,0x02/0x03开头)。非压缩公钥左右两个32字节有关联,因而可以压缩。
一个公钥具有两种形式,所以对应两个比特币地址。这两个比特币地址都可由同一私钥签署交易。

私钥:巨大的随机整数(256位、32字节),介于:1 ~ 0xFFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFE BAAE DCE6 AF48 A03B BFD2 5E8C D036 4141之间的数。

BASE58:Base58是用于比特币中使用的一种独特的编码方式,主要用于产生Bitcoin的钱包地址和私钥。相比Base64,Base58不使用数字”0”,字母大写”O”,字母大写”I”,和字母小写”l”,以及”+”和”/“符号。这样做的主要原因是为了肉眼容易识别,在输入的时候不容易打错,

私钥字符串:因为私钥太长,识别度低,不容易记忆。私钥字符串就是对于原始的随机数进行一定的转换,转换为识别率高的形式。通过BASE58转换成WIF(Wallet import Format)格式的私钥。也可以把私钥转换其他形式,比如以单词的形式(12或者24个单词),脑钱包的形式,又或者自己记住的某一句话来生成私钥,注意脑钱包生成的私钥随机的安全性并不高。

  • 私钥字符串开头的第一位的不同,是用来区分该私钥使用的公钥是否支持压缩格式
  • 老版本未压缩公钥的私钥字符串是33位byte数组,第一位存放私钥的Version信息,当前值为128,生成的Base58都是以5开头。

老版本未压缩私钥=Base58(version+32位随机数)

  • 支持压缩公钥的私钥字符串是34位byte数组,同样是第一位是version信息,它的值也是128,而多出来的一位是最后一个byte是用来存放是否压缩信息的信息,1就表示是支持压缩格式的公钥。经过Base58处理之后正好是L或者K开头

新版本私钥格式=Base58(version+32位随机数+是否支持压缩)

私钥到公钥:由私钥经过SECP256K1算法(椭圆曲线算法)处理得到。

私钥,公钥,私钥字符串

公钥到比特币地址:公钥到地址生成的过程是,先对公钥做一次SHA256(哈希算法)。
再经过hash160(一种原始完整性校验消息摘要,160标准对应20字节)处理。
在这个20位的byte数组前面再加上一个byte,这个byte就是地址的Version信息,地址的Version当前值为0,Version信息在比特币的test网络上会使用不同的值。
再在结尾加上验证信息checksum。在得到的hash160中加入地址的version信息 ,再对该信息做两次SHA-256之后取前4位就是checksum。

sha-256-hash= SHA-256(public key)
hash160=hash160(sha-256-hash)
checksum=get_front_four( SHA-256(SHA-256(version+hash160)))
address=Base58(version+hash160(SHA-256(public key))+checksum)

交易

一个数据块中会有多个交易
一个完整的交易由以下的元素构成的:

  • 版本号 :目前为1(4字节)
  • 输入数量 :正整数(1-9字节)
  • 输入列表 :每块的第一个交易的第一个输入叫做“coinbase”,早期版本中内容被忽略
  • 输出数量 :正整数(1-9字节)
  • 输出列表 :块中的第一个交易的输出是挖矿所得,一般是矿工自己的钱包地址
  • 锁定时间 :如果非0并且序列号小于0xFFFFFFFF,是指块序号;如果交易已经终结,则是指时间戳(4字节)

版本是明确一笔交易参照的规则,除非有重大升级的情况下,版本号基本无变化,是比较固定的一个值。
锁定时间是被该交易加到区块的最早时间,在大多数的情况下他的值都是0,表示需要立即被加入区块中。如果锁定时间大于0而小于5亿,它的值就表示区块高度。如果大于5亿就表示一个Unix时间戳。
以下详细说明输入输出列表
一个简单的交易输入如下:

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

先说明,每一笔交易的每一个输入都要指定是之前存在的哪一笔交易的哪一个输出(即从何处得到的钱)
那么看以上的结构,首先是前一笔交易的哈希值(Previous tx),然后是花费的是第几个输出(Index)也叫索引,通过交易Hash和索引(从0开始),即可唯一确定一个未花费的交易输出——UTXO(Unspent Transaction Output)。这样,每一个Tx Input都和之前的某个Tx Output关联了起来。
最后是解锁脚本(scriptSig),解锁脚本存在的意义在于验证成立这笔交易的人有权利使用他指定的UTXO。其中解锁脚本=签名+公钥,公钥是该比特币花费者的公钥,签名是对当前这笔交易的更改信息作为message的以私钥进行的签名

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

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

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

交易类型

比特币目前提供了两种不同的交易类型,如下所示。通过这两者类型的交易可以组合出更加复杂的交易,称之为合约。
(1)Pay-to-PubkeyHash
这个也是最常见的交易,目标地址就是比特币地址,花费时需要提供签名和公钥。
(2)Pay-to-Script-Hash(P2SH)
在P2SH中,目标地址由脚本哈希取代,解锁脚本中才包含签名和脚本内容。可以设定为类似解锁脚本中只需要5个公钥中任意两个私钥的签名即可。