比特币的所有权是通过数字密钥、比特币地址和数字签名来确立的。数字密钥实际上并不是存储在网络中,而是由用户生成并存储在一个文件或简单的数据库 中,称为钱包。存储在用户钱包中的数字密钥完全独立于比特币协议,可由用户的钱包软件生成并管理,而无需区块链或网络连接。密钥实现了比特币的许多有趣特性,包括去中心化信任和控制、所有权认证和基于密码学证明的安全模型。
比特币钱包只包含私钥而不是比特币。
一、比特币地址和钱包是什么
每一个用户有一个包含多个私钥的钱包。钱包中包含成对的私钥和公钥。用户用这些私钥来签名交易,从而证明它们拥有交易的输出(也就是其中的比特币)。比特币是以交易输出的形式来储存在区块链中(通常记为vout或txout)。
1. 首先使用随机数发生器生成一个『私钥』。一般来说这是一个256bits的数据,拥有了这串数字就可以对相应『钱包地址』中的比特币进行操作,所以必须被安全地保存起来。
2. 『私钥』经过SECP256K1算法处理生成了『公钥』。SECP256K1是一种椭圆曲线算法,通过一个已知『私钥』时可以算得『公钥』,而『公钥』已知时却无法反向计算出『私钥』。这是保障比特币安全的算法基础。
3. 同SHA256一样,RIPEMD160也是一种Hash算法,由『公钥』可以计算得到『公钥哈希』,而反过来是行不通的。
4. 将一个字节的地址版本号连接到『公钥哈希』头部(对于比特币网络的pubkey地址,这一字节为“0”),然后对其进行两次SHA256运算,将结果的前4字节作为『公钥哈希』的校验值,连接在其尾部。
5. 将上一步结果使用BASE58进行编码(比特币定制版本),就得到了『钱包地址』。 比如,1A1zP1eP5QGefi2DMPTfTL5TTmv7DivfNa。
二、比特币中的交易
简单来说,交易就是告知全网:比特币的持有者已授权把比特币转账给其他人。而新持有者能够再次授权,转移给该比特币所有权链中的其他人。
注意, 在比特币的世界里既没有账户,也没有余额,只有分散到区块链里的UTXO(Unspent Transaction Outputs)。
怎么理解这个UTXO呢?没有账户也没有余额,那么钱包里面的金额是怎么计算出来的呢?
别急,让我们一一道来。
话说,在比特币中,比特币钱包间的转账是通过交易(Transaction)实现的。
我们看一个标准的交易流程。
那么问题来了,世界上第一个比特币是哪里来的呢?
答,是挖矿来的。好了,我们的001交易表示的就是一个挖矿的过程,在这个交易中,输入就是挖矿,输出编号1,BTC数目是50,目的地址是A,表示这50个BTC给A了。
接下来,A想发25个BTC给B,怎么构造这个交易呢?
同样的,我们需要一个输入,这个输入就是001交易的1号输出,我们用001.1来表示。输出分为两个,第一个输出编号1,表示要付25个BTC给B。第二个输出编号2,表示剩下的BTC要还给A。
大家可能会问了,输入是50BTC,两个输出加起来才45个BTC,好像还少了5个BTC?没错,这个5个BTC就是给矿工的挖矿所得。
接下来,A又继续转账给C,同样的道理,把一个一个的交易连接起来。
从上面的例子我们可以看到,实际上钱是存在一个一个的交易记录里面的,那些未被花费的输出,就叫做UTXO(Unspent Transaction Outputs)。
那么怎么保证转账给B的钱,不会被其他的人消费呢?这就涉及交易的加密过程了。
我们以单个输入和输出为例来详细了解一下交易的构成:
上图中,交易的输入就是txid,也就是之前生成的还有未花费输出的交易ID。output index就是交易的输出id。
一个非常重要的ScriptSig是输入交易的验证,表明这个用户拥有这个账户的转账权限。
输出是一个脚本,只有满足脚本运行条件的人才能花费这个output。这也就是ScriptSig需要验证的脚本。
三、我们看下脚本是怎么做认证的吧。
比特币的标准输出形式有两种。Pay To Public Key Hash (P2PKH) 和 Pay To Script Hash (P2SH)。两者的区别在于,一个是输出到public key的hash,一个是输出到任意的一个脚本输出hash。
为了保证输出只能由特定的人来花费,一般的情况下是直接输出到对方的public key hash。由于只有对方拥有的私钥能够生成这个public key hash,也就是说只有对方才能够对这个输出进行验证。
但每次都需要知道对方的public key hash还是比较麻烦的,更简单的做法就是,发送者直接输出到一个特定的hash值就行了,只要对方能够生成这个hash就可以。
四、下面的例子是一个P2PKH的脚本形式。
P2PKH的输出是一个脚本,里面一个重要的值就是PK hash。
怎么验证呢?
验证方提供两个值,一个是sig,一个是PubKey。因为比特币的虚拟机是栈结构的,我们先把这两个值入栈。
然后调用OP_DUP对最上层的PubKey进行拷贝,然后调用OP_HASH160算法来计算Pk Hash,然后将发送方保存的Pk Hash入栈。接下来调用OP_EQUALVERIFY对两个PK Hash进行对比。
如果对比成功,最后一步就是验证Sig和PubKey是否匹配。
如果都成功,说明接收方的确是这个PK Hash的拥有者。那么对方就可以尽情使用了。