暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

比特币与区块链

生有可恋 2022-07-10
1500

基于 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 ==
    getbestblockhash
    getblock "blockhash" ( verbosity )
    getblockchaininfo
    getblockcount
    getblockfilter "blockhash" ( "filtertype" )
    getblockfrompeer "blockhash" peer_id
    getblockhash height
    getblockheader "blockhash" ( verbose )
    getblockstats hash_or_height ( stats )
    getchaintips
    getchaintxstats ( nblocks "blockhash" )
    getdeploymentinfo ( "blockhash" )
    getdifficulty
    getmempoolancestors "txid" ( verbose )
    getmempooldescendants "txid" ( verbose )
    getmempoolentry "txid"
    getmempoolinfo
    getrawmempool ( verbose mempool_sequence )
    gettxout "txid" n ( include_mempool )
    gettxoutproof ["txid",...] ( "blockhash" )
    gettxoutsetinfo ( "hash_type" hash_or_height use_index )
    preciousblock "blockhash"
    pruneblockchain height
    savemempool
    scantxoutset "action" ( [scanobjects,...] )
    verifychain ( checklevel nblocks )
    verifytxoutproof "proof"


    == Control ==
    getmemoryinfo ( "mode" )
    getrpcinfo
    help ( "command" )
    logging ( ["include_category",...] ["exclude_category",...] )
    stop
    uptime


    == Mining ==
    getblocktemplate ( "template_request" )
    getmininginfo
    getnetworkhashps ( nblocks height )
    prioritisetransaction "txid" ( dummy ) fee_delta
    submitblock "hexdata" ( "dummy" )
    submitheader "hexdata"


    == Network ==
    addnode "node" "command"
    clearbanned
    disconnectnode ( "address" nodeid )
    getaddednodeinfo ( "node" )
    getconnectioncount
    getnettotals
    getnetworkinfo
    getnodeaddresses ( count "network" )
    getpeerinfo
    listbanned
    ping
    setban "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"
    abortrescan
    addmultisigaddress 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 )
    getbalances
    getnewaddress ( "label" "address_type" )
    getrawchangeaddress ( "address_type" )
    getreceivedbyaddress "address" ( minconf include_immature_coinbase )
    getreceivedbylabel "label" ( minconf include_immature_coinbase )
    gettransaction "txid" ( include_watchonly verbose )
    getunconfirmedbalance
    getwalletinfo
    importaddress "address" ( "label" rescan p2sh )
    importdescriptors "requests"
    importmulti "requests" ( "options" )
    importprivkey "privkey" ( "label" rescan )
    importprunedfunds "rawtransaction" "txoutproof"
    importpubkey "pubkey" ( "label" rescan )
    importwallet "filename"
    keypoolrefill ( newsize )
    listaddressgroupings
    listdescriptors ( private )
    listlabels ( "purpose" )
    listlockunspent
    listreceivedbyaddress ( 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 )
    listwalletdir
    listwallets
    loadwallet "filename" ( load_on_startup )
    lockunspent unlock ( [{"txid":"hex","vout":n},...] persistent )
    newkeypool
    psbtbumpfee "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 amount
    setwalletflag "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 )
    walletlock
    walletpassphrase "passphrase" timeout
    walletpassphrasechange "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.ldb
      2022-07-09T04:58:05Z Fatal LevelDB error: Corruption: block checksum mismatch: D:\Bitcoin\chainstate/004337.ldb
      2022-07-09T04:58:05Z You can use -debug=leveldb to get more complete diagnostic messages
      2022-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 Bitcoin
        c:\Program Files\Bitcoin>bitcoin-qt.exe -reindex


        再次观察 debug.log 文件,可以看到开始重新对下载下来的 blk00xx.dat 进行索引。

          2022-07-09T05:01:59Z Loaded 119211 blocks from external file in 37906ms
          2022-07-09T05:01:59Z Reindexing block file blk00001.dat...
          2022-07-09T05:02:05Z Loaded 11513 blocks from external file in 6416ms
          2022-07-09T05:02:05Z Reindexing block file blk00002.dat...
          2022-07-09T05:02:10Z Loaded 5810 blocks from external file in 4740ms
          2022-07-09T05:02:10Z Reindexing block file blk00003.dat...
          2022-07-09T05:02:15Z Loaded 5854 blocks from external file in 4660ms
          2022-07-09T05:02:15Z Reindexing block file blk00004.dat...
          2022-07-09T05:02:19Z Loaded 6304 blocks from external file in 4934ms
          2022-07-09T05:02:19Z Reindexing block file blk00005.dat...
          2022-07-09T05:02:25Z Loaded 7308 blocks from external file in 5129ms
          2022-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/使用比特币


          全文完。


          如果转发本文,文末务必注明:“转自微信公众号:生有可恋”。



          文章转载自生有可恋,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

          评论