基于 block chain 的 bitcoin 从 2009 年上线至今已经十来年了。只知道它是一套基于加密算法的系统,但对其并没有太深的认识。我花了一点时间试着去理解它是如何运作的。
2008年11月,一份署名中本聪(satoshi)的论文被发表在网络上,其标题为《比特币:对等网络电子现金系统》(Bitcoin: A Peer-to-Peer Electronic Cash System)。论文中详细描述了如何使用对等网络来创造一种“不需依赖信任的电子交易系统”。2009年1月比特币网络上线,推出了第一个开源的比特币客户端软件,中本聪使用该软件对第一个比特币“区块”(block,又称为创始区块,genesis block)进行“采矿”(mining),并获得了第一批的50个比特币。最初比特币交易的价值由“bitcointalk”论坛上的使用者彼此协商,其中包括以10,000比特币兑换一整个披萨。
以上是来自WiKi的比特币的诞生史。在这里有几个概念需要搞清楚,第一,比特币是基于P2P的。即交易是在用户和用户之间完成的,不需要银行参与。比特币用到的区块链技术,可以理解为类似Git这种分布式文件系统,任何一个人提交的请求都会被所有人收到。而要支持这个系统运行,需要有一套系统来搭建这个P2P网络,于是就出现了挖矿这个概念。对于运行这套系统的程序,被称为挖矿。系统对挖矿者即运行这套程序的机器进行奖励,而主动运行这套系统的人或机器被称为矿工。
那么P2P网络中的人们如何交易呢?这里又多出一个概念叫比特币钱包。而比特币就是放在钱包中的。钱包类似一个收件地址,可以与其他人交易。而比特币就是一串存在钱包中的字符串,当与其他人交易之后会进行扣费处理,交易记录会同步到比特币的所有网络,即被所有人承认。
我们下载一个钱包看看这个过程是怎么执行的。官方的钱包叫 “Bitcoin Core",在官网可以下载到:
https://bitcoincore.org/en/download/

下载下来的安装包只有 20M 左右,直接安装:


使用默认位置进行安装即可:

安装完成后,首次使用会让选择数据存放目录。这个目录会存放从2009年至今(2022.7)的所有 Block Chain,即所有的交易记录。这个数据量巨大,大概有 460G 。

首次运行会同步区块,过程非常缓慢。

在同步的同时,可以观察一下这个钱包程序的其它功能,比如它有一个命令行的控制台,可以在其中敲命令。

在控制台中输入 help 可以看到命令帮助。从 help 我们可以了解到,这个 bitcoin core 程序不仅仅运行钱包功能,它是一个全功能的,非常复杂。

命令help的内容:
help== Blockchain ==getbestblockhashgetblock "blockhash" ( verbosity )getblockchaininfogetblockcountgetblockfilter "blockhash" ( "filtertype" )getblockfrompeer "blockhash" peer_idgetblockhash heightgetblockheader "blockhash" ( verbose )getblockstats hash_or_height ( stats )getchaintipsgetchaintxstats ( nblocks "blockhash" )getdeploymentinfo ( "blockhash" )getdifficultygetmempoolancestors "txid" ( verbose )getmempooldescendants "txid" ( verbose )getmempoolentry "txid"getmempoolinfogetrawmempool ( verbose mempool_sequence )gettxout "txid" n ( include_mempool )gettxoutproof ["txid",...] ( "blockhash" )gettxoutsetinfo ( "hash_type" hash_or_height use_index )preciousblock "blockhash"pruneblockchain heightsavemempoolscantxoutset "action" ( [scanobjects,...] )verifychain ( checklevel nblocks )verifytxoutproof "proof"== Control ==getmemoryinfo ( "mode" )getrpcinfohelp ( "command" )logging ( ["include_category",...] ["exclude_category",...] )stopuptime== Mining ==getblocktemplate ( "template_request" )getmininginfogetnetworkhashps ( nblocks height )prioritisetransaction "txid" ( dummy ) fee_deltasubmitblock "hexdata" ( "dummy" )submitheader "hexdata"== Network ==addnode "node" "command"clearbanneddisconnectnode ( "address" nodeid )getaddednodeinfo ( "node" )getconnectioncountgetnettotalsgetnetworkinfogetnodeaddresses ( count "network" )getpeerinfolistbannedpingsetban "subnet" "command" ( bantime absolute )setnetworkactive state== Rawtransactions ==analyzepsbt "psbt"combinepsbt ["psbt",...]combinerawtransaction ["hexstring",...]converttopsbt "hexstring" ( permitsigdata iswitness )createpsbt [{"txid":"hex","vout":n,"sequence":n},...] [{"address":amount,...},{"data":"hex"},...] ( locktime replaceable )createrawtransaction [{"txid":"hex","vout":n,"sequence":n},...] [{"address":amount,...},{"data":"hex"},...] ( locktime replaceable )decodepsbt "psbt"decoderawtransaction "hexstring" ( iswitness )decodescript "hexstring"finalizepsbt "psbt" ( extract )fundrawtransaction "hexstring" ( options iswitness )getrawtransaction "txid" ( verbose "blockhash" )joinpsbts ["psbt",...]sendrawtransaction "hexstring" ( maxfeerate )signrawtransactionwithkey "hexstring" ["privatekey",...] ( [{"txid":"hex","vout":n,"scriptPubKey":"hex","redeemScript":"hex","witnessScript":"hex","amount":amount},...] "sighashtype" )testmempoolaccept ["rawtx",...] ( maxfeerate )utxoupdatepsbt "psbt" ( ["",{"desc":"str","range":n or [n,n]},...] )== Util ==createmultisig nrequired ["key",...] ( "address_type" )deriveaddresses "descriptor" ( range )estimatesmartfee conf_target ( "estimate_mode" )getdescriptorinfo "descriptor"getindexinfo ( "index_name" )signmessagewithprivkey "privkey" "message"validateaddress "address"verifymessage "address" "signature" "message"== Wallet ==abandontransaction "txid"abortrescanaddmultisigaddress nrequired ["key",...] ( "label" "address_type" )backupwallet "destination"bumpfee "txid" ( options )createwallet "wallet_name" ( disable_private_keys blank "passphrase" avoid_reuse descriptors load_on_startup external_signer )dumpprivkey "address"dumpwallet "filename"encryptwallet "passphrase"getaddressesbylabel "label"getaddressinfo "address"getbalance ( "dummy" minconf include_watchonly avoid_reuse )getbalancesgetnewaddress ( "label" "address_type" )getrawchangeaddress ( "address_type" )getreceivedbyaddress "address" ( minconf include_immature_coinbase )getreceivedbylabel "label" ( minconf include_immature_coinbase )gettransaction "txid" ( include_watchonly verbose )getunconfirmedbalancegetwalletinfoimportaddress "address" ( "label" rescan p2sh )importdescriptors "requests"importmulti "requests" ( "options" )importprivkey "privkey" ( "label" rescan )importprunedfunds "rawtransaction" "txoutproof"importpubkey "pubkey" ( "label" rescan )importwallet "filename"keypoolrefill ( newsize )listaddressgroupingslistdescriptors ( private )listlabels ( "purpose" )listlockunspentlistreceivedbyaddress ( minconf include_empty include_watchonly "address_filter" include_immature_coinbase )listreceivedbylabel ( minconf include_empty include_watchonly include_immature_coinbase )listsinceblock ( "blockhash" target_confirmations include_watchonly include_removed )listtransactions ( "label" count skip include_watchonly )listunspent ( minconf maxconf ["address",...] include_unsafe query_options )listwalletdirlistwalletsloadwallet "filename" ( load_on_startup )lockunspent unlock ( [{"txid":"hex","vout":n},...] persistent )newkeypoolpsbtbumpfee "txid" ( options )removeprunedfunds "txid"rescanblockchain ( start_height stop_height )restorewallet "wallet_name" "backup_file" ( load_on_startup )send [{"address":amount,...},{"data":"hex"},...] ( conf_target "estimate_mode" fee_rate options )sendmany "" {"address":amount,...} ( minconf "comment" ["address",...] replaceable conf_target "estimate_mode" fee_rate verbose )sendtoaddress "address" amount ( "comment" "comment_to" subtractfeefromamount replaceable conf_target "estimate_mode" avoid_reuse fee_rate verbose )sethdseed ( newkeypool "seed" )setlabel "address" "label"settxfee amountsetwalletflag "flag" ( value )signmessage "address" "message"signrawtransactionwithwallet "hexstring" ( [{"txid":"hex","vout":n,"scriptPubKey":"hex","redeemScript":"hex","witnessScript":"hex","amount":amount},...] "sighashtype" )unloadwallet ( "wallet_name" load_on_startup )upgradewallet ( version )walletcreatefundedpsbt ( [{"txid":"hex","vout":n,"sequence":n,"weight":n},...] ) [{"address":amount,...},{"data":"hex"},...] ( locktime options bip32derivs )walletlockwalletpassphrase "passphrase" timeoutwalletpassphrasechange "oldpassphrase" "newpassphrase"walletprocesspsbt "psbt" ( sign "sighashtype" bip32derivs finalize )== Zmq ==getzmqnotifications
同时还有流量监控窗口:

同步的数据是基于P2P网络的,可以看到所有节点的信息:

其中主窗口是当前客户端的信息:

试着下载的过程中,频繁报错:

从日志中可以看到进行 block checksum 时失败,此时程序打开就报错,没法再同步。
2022-07-09T04:58:05Z LevelDB read failure: Corruption: block checksum mismatch: D:\Bitcoin\chainstate/004337.ldb2022-07-09T04:58:05Z Fatal LevelDB error: Corruption: block checksum mismatch: D:\Bitcoin\chainstate/004337.ldb2022-07-09T04:58:05Z You can use -debug=leveldb to get more complete diagnostic messages2022-07-09T04:58:05Z Error: Error reading from database, shutting down.2022-07-09T05:00:13Z Error reading from database: Fatal LevelDB error: Corruption: block checksum mismatch: D:\Bitcoin\chainstate/004337.ldb
网上找到解决方案,进到安装目录,执行 -reindex 重新编译索引:
C:\Users\Administrator>cd d "c:\Program Files"c:\Program Files>cd Bitcoinc:\Program Files\Bitcoin>bitcoin-qt.exe -reindex
再次观察 debug.log 文件,可以看到开始重新对下载下来的 blk00xx.dat 进行索引。
2022-07-09T05:01:59Z Loaded 119211 blocks from external file in 37906ms2022-07-09T05:01:59Z Reindexing block file blk00001.dat...2022-07-09T05:02:05Z Loaded 11513 blocks from external file in 6416ms2022-07-09T05:02:05Z Reindexing block file blk00002.dat...2022-07-09T05:02:10Z Loaded 5810 blocks from external file in 4740ms2022-07-09T05:02:10Z Reindexing block file blk00003.dat...2022-07-09T05:02:15Z Loaded 5854 blocks from external file in 4660ms2022-07-09T05:02:15Z Reindexing block file blk00004.dat...2022-07-09T05:02:19Z Loaded 6304 blocks from external file in 4934ms2022-07-09T05:02:19Z Reindexing block file blk00005.dat...2022-07-09T05:02:25Z Loaded 7308 blocks from external file in 5129ms2022-07-09T05:02:25Z Reindexing block file blk00006.dat......
执行上面的命令后,窗口恢复正常,开始重新同步。

挂着不知道多久,客户端又挂了,点开就开始重放区块:

程序启动后又开始同步:

此时可以把同步窗口隐藏,在程序主窗口会提示未加载钱包,是否需要创建一个。

我们新建一个钱包:

选择加密钱包会要求输入钱包的密码:

如果钱包丢了,那么钱包中的钱也无法用了。

加密的钱包,在打开时需要输入密码,相对来说更安全一点。

创建完钱包就可以显示当前的账户信息了,钱包中是零蛋,没有钱。

在主窗口上有两个按钮,一个叫发送,一个叫接收。这两个是付款用的。从界面上看,付款就像发电子邮件,输入对方钱包地址就可以把钱包中的钱付给对方了,看起来还是很方便的。

收款界面也一样,建一个收款地址会生成一串字符,把这个给对方就可以了。

除了挖矿获得比特币,也可以购买比特币。这个与所使用的交易平台有关,比如下面这个,最小交易金额为230元。

230 元只能买到 0.00126 比特币。
https://bitcoin.org/zh_CN/buy

我们再回到区块链,在下载下来的区块数据,有一个目录中全是区块。

目前只同步了37G数据,全部同步完要 460G。上面说的区块链就是这个东西,所有参考交易的人都要存一份,相当于一块硬盘大小的交易凭证。每交易一次,所有人的目录中都会加上一笔。每个文件为128M大小。

比特币和区块链从诞生到现在已经不是什么新东西了,但对于这种新事物我从来没有对其产生过好奇。这可能就是人年龄越大对外界事物接受度越低,越老越固执。为重捨那份好奇心,花点时间重新了解下这个已经听说了十来年的新东西是如何运作的。
参考:
https://github.com/bitcoin/bitcoin
https://zh.wikihow.com/使用比特币
全文完。
如果转发本文,文末务必注明:“转自微信公众号:生有可恋”。




