加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

如何将Bitcoin比特币区块链数据导入关系数据库

发布时间:2020-12-15 21:16:49 所属栏目:asp.Net 来源:网络整理
导读:在接触了比特币和区块链后,我一直有一个想法,就是把所有比特币的区块链数据放入到关系数据库(比如SQL Server)中,然后当成一个数据仓库,做做比特币交易数据的各种分析。想法已经很久了,但是一直没有实施。最近正好有点时间,于是写了一个比特币区块链

在接触了比特币和区块链后,我一直有一个想法,就是把所有比特币的区块链数据放入到关系数据库(比如SQL Server)中,然后当成一个数据仓库,做做比特币交易数据的各种分析。想法已经很久了,但是一直没有实施。最近正好有点时间,于是写了一个比特币区块链的导出导入程序。

之前我的一篇博客:? 介绍了怎么发起一笔比特币的交易,今天我们仍然是使用C#+NBitcoin,读取比特币钱包Bitcoin Core下载到本地的全量区块链数据,并将这些数据写入数据库。如果有和我一样想法的朋友,可以参考下面是我的操作过程:

一、准备

我们要解析的是存储在本地硬盘上的Bitcoin Core钱包的全量比特币数据,那么首先就是要下载并安装好Bitcoin Core,下载地址: 然后就等着这个软件同步区块链数据吧。目前比特币的区块链数据大概130G,所以可能需要好几天,甚至一个星期才能将所有区块链数据同步到本地。当然如果你很早就安装了这个软件,那么就太好了,毕竟要等好几天甚至一个星期,真的很痛苦。

二、建立比特币区块链数据模型

要进行区块链数据的分析,那么必须得对区块链的数据模型了解才行。我大概研究了一下,可以总结出4个实体:区块、交易、输入、输出。而其中的关系是,一个区块对应多个交易,一个交易对应多个输入和多个输出。除了Coinbase的输入外,一笔输入对应另一笔交易中的输出。于是我们可以得出这样的数据模型:

image

需要特别说明几点的是:

1.TxId是自增的int,我没有用TxHash做Transaction的PK,那是因为TxHash根本就不唯一啊!有好几个不同区块里面的第一笔交易,也就是Coinbase交易是相同的。这其实应该是异常数据,因为相同的TxHash将导致只能花费一次,所以这个矿工杯具了。

2.对于一笔Coinbase 的Transaction,其输入的PreOutTxId是0000000000000000000000000000000000000000000000000000000000000000,而其PreOutIndex是-1,这是一条不存在的TxOutput,所以我并没有建立TXInput和TxOutput的外键关联。

3.对于Block,PreId就是上一个Block的ID,而创世区块的PreId是0000000000000000000000000000000000000000000000000000000000000000,也是一个不存在的BlockId,所以我没有建立Block的自引用外键。

4.有很多字段其实并不是区块链数据结构中的,这些字段是我添加为了接下来方便分析用的。在导入的时候并没有值,需要经过一定的SQL运算才能得到。比如Trans里面的TotalInAmount,TransFee等。

我用的是PowerDesigner,建模完成后,生成SQL语句,即可。这是我的建表SQL:

() () () () PK_BLOCK

<span style="color: #008080;">/<span style="color: #008080;">==============================================================<span style="color: #008080;">/
<span style="color: #008080;">/<span style="color: #008080;"> Index: Block_Height <span style="color: #008080;">/
<span style="color: #008080;">/<span style="color: #008080;">==============================================================<span style="color: #008080;">/
<span style="color: #0000ff;">create <span style="color: #0000ff;">unique <span style="color: #0000ff;">clustered <span style="color: #0000ff;">index Block_Height <span style="color: #0000ff;">on<span style="color: #000000;"> Block (
Height <span style="color: #0000ff;">ASC<span style="color: #000000;">
)
<span style="color: #0000ff;">go

<span style="color: #008080;">/<span style="color: #008080;">==============================================================<span style="color: #008080;">/
<span style="color: #008080;">/<span style="color: #008080;"> Table: Trans <span style="color: #008080;">/
<span style="color: #008080;">/<span style="color: #008080;">==============================================================<span style="color: #008080;">/
<span style="color: #0000ff;">create <span style="color: #0000ff;">table<span style="color: #000000;"> Trans (
TxId <span style="color: #0000ff;">int <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,TxHash <span style="color: #0000ff;">char(<span style="color: #800000; font-weight: bold;">64) <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,InputCount <span style="color: #0000ff;">int <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,OutputCount <span style="color: #0000ff;">int <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,TotalOutAmount <span style="color: #0000ff;">bigint <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,TotalInAmount <span style="color: #0000ff;">bigint <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,TransFee <span style="color: #0000ff;">bigint <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,IsCoinbase <span style="color: #0000ff;">bit <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,IsHeightLock <span style="color: #0000ff;">bit <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,IsTimeLock <span style="color: #0000ff;">bit <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,LockTimeValue <span style="color: #0000ff;">int <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,TransTime <span style="color: #0000ff;">datetime <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,<span style="color: #0000ff;">constraint PK_TRANS <span style="color: #0000ff;">primary <span style="color: #0000ff;">key<span style="color: #000000;"> (TxId)
)
<span style="color: #0000ff;">go

<span style="color: #008080;">/<span style="color: #008080;">==============================================================<span style="color: #008080;">/
<span style="color: #008080;">/<span style="color: #008080;"> Index: Relationship_1_FK <span style="color: #008080;">/
<span style="color: #008080;">/<span style="color: #008080;">==============================================================<span style="color: #008080;">/
<span style="color: #0000ff;">create <span style="color: #0000ff;">index Relationship_1_FK <span style="color: #0000ff;">on<span style="color: #000000;"> Trans (
BlkId <span style="color: #0000ff;">ASC<span style="color: #000000;">
)
<span style="color: #0000ff;">go

<span style="color: #008080;">/<span style="color: #008080;">==============================================================<span style="color: #008080;">/
<span style="color: #008080;">/<span style="color: #008080;"> Index: Trans_Hash <span style="color: #008080;">/
<span style="color: #008080;">/<span style="color: #008080;">==============================================================<span style="color: #008080;">/
<span style="color: #0000ff;">create <span style="color: #0000ff;">index Trans_Hash <span style="color: #0000ff;">on<span style="color: #000000;"> Trans (
TxHash <span style="color: #0000ff;">ASC<span style="color: #000000;">
)
<span style="color: #0000ff;">go

<span style="color: #008080;">/<span style="color: #008080;">==============================================================<span style="color: #008080;">/
<span style="color: #008080;">/<span style="color: #008080;"> Table: TxInput <span style="color: #008080;">/
<span style="color: #008080;">/<span style="color: #008080;">==============================================================<span style="color: #008080;">/
<span style="color: #0000ff;">create <span style="color: #0000ff;">table<span style="color: #000000;"> TxInput (
TxId <span style="color: #0000ff;">int <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,Idx <span style="color: #0000ff;">int <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,Amount <span style="color: #0000ff;">bigint <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,PrevOutTxId <span style="color: #0000ff;">char(<span style="color: #800000; font-weight: bold;">64) <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,PrevOutIndex <span style="color: #0000ff;">int <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,PaymentScriptLen <span style="color: #0000ff;">int <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,PaymentScript <span style="color: #0000ff;">varchar(<span style="color: #800000; font-weight: bold;">8000) <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,Address <span style="color: #0000ff;">char(<span style="color: #800000; font-weight: bold;">58) <span style="color: #0000ff;">null<span style="color: #000000;">,<span style="color: #0000ff;">constraint PK_TXINPUT <span style="color: #0000ff;">primary <span style="color: #0000ff;">key<span style="color: #000000;"> (TxId,Idx)
)
<span style="color: #0000ff;">go

<span style="color: #008080;">/<span style="color: #008080;">==============================================================<span style="color: #008080;">/
<span style="color: #008080;">/<span style="color: #008080;"> Index: Relationship_2_FK <span style="color: #008080;">/
<span style="color: #008080;">/<span style="color: #008080;">==============================================================<span style="color: #008080;">/
<span style="color: #0000ff;">create <span style="color: #0000ff;">index Relationship_2_FK <span style="color: #0000ff;">on<span style="color: #000000;"> TxInput (
TxId <span style="color: #0000ff;">ASC<span style="color: #000000;">
)
<span style="color: #0000ff;">go

<span style="color: #008080;">/<span style="color: #008080;">==============================================================<span style="color: #008080;">/
<span style="color: #008080;">/<span style="color: #008080;"> Table: TxOutput <span style="color: #008080;">/
<span style="color: #008080;">/<span style="color: #008080;">==============================================================<span style="color: #008080;">/
<span style="color: #0000ff;">create <span style="color: #0000ff;">table<span style="color: #000000;"> TxOutput (
TxId <span style="color: #0000ff;">int <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,ScriptPubKeyLen <span style="color: #0000ff;">int <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,ScriptPubKey <span style="color: #0000ff;">varchar(<span style="color: #800000; font-weight: bold;">8000) <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,IsUnspendable <span style="color: #0000ff;">bit <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,IsPayToScriptHash <span style="color: #0000ff;">bit <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,IsValid <span style="color: #0000ff;">bit <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,IsSpent <span style="color: #0000ff;">bit <span style="color: #808080;">not <span style="color: #0000ff;">null<span style="color: #000000;">,<span style="color: #0000ff;">constraint PK_TXOUTPUT <span style="color: #0000ff;">primary <span style="color: #0000ff;">key<span style="color: #000000;"> (TxId,Idx)
)
<span style="color: #0000ff;">go

<span style="color: #008080;">/<span style="color: #008080;">==============================================================<span style="color: #008080;">/
<span style="color: #008080;">/<span style="color: #008080;"> Index: Relationship_3_FK <span style="color: #008080;">/
<span style="color: #008080;">/<span style="color: #008080;">==============================================================<span style="color: #008080;">/
<span style="color: #0000ff;">create <span style="color: #0000ff;">index Relationship_3_FK <span style="color: #0000ff;">on<span style="color: #000000;"> TxOutput (
TxId <span style="color: #0000ff;">ASC<span style="color: #000000;">
)
<span style="color: #0000ff;">go

<span style="color: #0000ff;">alter <span style="color: #0000ff;">table<span style="color: #000000;"> Trans
<span style="color: #0000ff;">add <span style="color: #0000ff;">constraint FK_TRANS_RELATIONS_BLOCK <span style="color: #0000ff;">foreign <span style="color: #0000ff;">key<span style="color: #000000;"> (BlkId)
<span style="color: #0000ff;">references<span style="color: #000000;"> Block (BlkId)
<span style="color: #0000ff;">go

<span style="color: #0000ff;">alter <span style="color: #0000ff;">table<span style="color: #000000;"> TxInput
<span style="color: #0000ff;">add <span style="color: #0000ff;">constraint FK_TXINPUT_RELATIONS_TRANS <span style="color: #0000ff;">foreign <span style="color: #0000ff;">key<span style="color: #000000;"> (TxId)
<span style="color: #0000ff;">references<span style="color: #000000;"> Trans (TxId)
<span style="color: #0000ff;">go

<span style="color: #0000ff;">alter <span style="color: #0000ff;">table<span style="color: #000000;"> TxOutput
<span style="color: #0000ff;">add <span style="color: #0000ff;">constraint FK_TXOUTPUT_RELATIONS_TRANS <span style="color: #0000ff;">foreign <span style="color: #0000ff;">key<span style="color: #000000;"> (TxId)
<span style="color: #0000ff;">references<span style="color: #000000;"> Trans (TxId)
<span style="color: #0000ff;">go

三、导出区块链数据为CSV

数据模型有了,接下来我们就是建立对应的表,然后写程序将比特币的Block写入到数据库中。我本来用的是EntityFramework来实现插入数据库的操作。但是后来发现实在太慢,插入一个Block甚至要等10多20秒,这要等到何年何月才能插入完啊!我试了各种方案,比如写原生的SQL,用事务,用LINQToSQL等,性能都很不理想。最后终于找到了一个好办法,那就是直接导出为文本文件(比如CSV格式),然后用SQL Server的Bulk Insert命令来实现批量导入,这是我已知的最快的写入数据库的方法。

解析Bitcoin Core下载下来的所有比特币区块链数据用的还是NBitcoin这个开源库。只需要用到其中的BlockStore 类,即可轻松实现区块链数据的解析。

以下是我将区块链数据解析为我们的Block对象的代码:

LoadBlock2DB( localPath, store = i = -= </span><span style="color: #0000ff;"&gt;foreach</span> (<span style="color: #0000ff;"&gt;var</span> block <span style="color: #0000ff;"&gt;in</span> store.Enumerate(<span style="color: #0000ff;"&gt;false</span><span style="color: #000000;"&gt;)) { i</span>++<span style="color: #000000;"&gt;; </span><span style="color: #0000ff;"&gt;if</span> (i <<span style="color: #000000;"&gt; start) { </span><span style="color: #0000ff;"&gt;continue</span><span style="color: #000000;"&gt;; } </span><span style="color: #0000ff;"&gt;try</span><span style="color: #000000;"&gt; { log.Debug(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;Start load Block </span><span style="color: #800000;"&gt;"</span> + i + <span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;: </span><span style="color: #800000;"&gt;"</span> + block.Item.Header + <span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt; from file:</span><span style="color: #800000;"&gt;"</span> +<span style="color: #000000;"&gt; block.BlockPosition.ToString()); </span><span style="color: #0000ff;"&gt;var</span> blk = LoadBlock(block,i);<span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt;将NBitcoin的Block转换为我们建模的Block对象 </span> helper.WriteBitcoin2Csv(blk);<span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt;将我们的Block对象转换为CSV保存 </span>

<span style="color: #000000;"> }
<span style="color: #0000ff;">catch<span style="color: #000000;"> (Exception ex)
{
log.Error(<span style="color: #800000;">"<span style="color: #800000;">保存Block到数据库时异常,请手动载入,i=<span style="color: #800000;">" +<span style="color: #000000;"> i,ex);
}

} 
Console.WriteLine(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;--------End-----------</span><span style="color: #800000;"&gt;"</span><span style="color: #000000;"&gt;); 
Console.ReadLine(); 

}

<span style="color: #0000ff;">private <span style="color: #0000ff;">static Block LoadBlock(StoredBlock block,<span style="color: #0000ff;">int<span style="color: #000000;"> i)
{
<span style="color: #0000ff;">var blk = <span style="color: #0000ff;">new<span style="color: #000000;"> Block()
{
BlkId =<span style="color: #000000;"> block.Item.Header.ToString(),Difficulty =<span style="color: #000000;"> block.Item.Header.Bits.Difficulty,Bits =<span style="color: #000000;"> block.Item.Header.Bits.ToString(),Height =<span style="color: #000000;"> i,Nonce =<span style="color: #000000;"> block.Item.Header.Nonce,PreId =<span style="color: #000000;"> block.Item.Header.HashPrevBlock.ToString(),TxMerkleRoot =<span style="color: #000000;"> block.Item.GetMerkleRoot().ToString(),Size =<span style="color: #000000;"> block.Item.GetSerializedSize(),Version =<span style="color: #000000;"> block.Item.Header.Version,Timestamp =<span style="color: #000000;"> block.Item.Header.BlockTime.UtcDateTime,TxCount =<span style="color: #000000;"> block.Item.Transactions.Count
};
log.Debug(<span style="color: #800000;">"<span style="color: #800000;">Transaction Count=<span style="color: #800000;">" +<span style="color: #000000;"> block.Item.Transactions.Count);
<span style="color: #0000ff;">foreach (<span style="color: #0000ff;">var transaction <span style="color: #0000ff;">in<span style="color: #000000;"> block.Item.Transactions)
{
<span style="color: #0000ff;">var tx = <span style="color: #0000ff;">new<span style="color: #000000;"> Trans()
{
BlkId =<span style="color: #000000;"> blk.BlkId,TxHash =<span style="color: #000000;"> transaction.GetHash().ToString(),Version = (<span style="color: #0000ff;">int<span style="color: #000000;">)transaction.Version,InputCount =<span style="color: #000000;"> transaction.Inputs.Count,OutputCount =<span style="color: #000000;"> transaction.Outputs.Count,TotalOutAmount =<span style="color: #000000;"> transaction.TotalOut.Satoshi,TransTime =<span style="color: #000000;"> blk.Timestamp,IsCoinbase =<span style="color: #000000;"> transaction.IsCoinBase,IsHeightLock =<span style="color: #000000;"> transaction.LockTime.IsHeightLock,IsTimeLock =<span style="color: #000000;"> transaction.LockTime.IsTimeLock,LockTimeValue = (<span style="color: #0000ff;">int<span style="color: #000000;">)transaction.LockTime.Value,Size =<span style="color: #000000;"> transaction.GetSerializedSize()
};
blk.Trans.Add(tx);
<span style="color: #0000ff;">for (<span style="color: #0000ff;">var idx = <span style="color: #800080;">0; idx < transaction.Inputs.Count; idx++<span style="color: #000000;">)
{
<span style="color: #0000ff;">var input =<span style="color: #000000;"> transaction.Inputs[idx];
<span style="color: #0000ff;">var txInput = <span style="color: #0000ff;">new<span style="color: #000000;"> TxInput()
{
PaymentScript =<span style="color: #000000;"> input.ScriptSig.ToString(),PaymentScriptLen =<span style="color: #000000;"> input.ScriptSig.Length,PrevOutTxId =<span style="color: #000000;"> input.PrevOut.Hash.ToString(),PrevOutIndex = (<span style="color: #0000ff;">int<span style="color: #000000;">)input.PrevOut.N,Trans =<span style="color: #000000;"> tx,Idx =<span style="color: #000000;"> idx
};

        </span><span style="color: #0000ff;"&gt;if</span> (!<span style="color: #000000;"&gt;tx.IsCoinbase) 
        { 
            </span><span style="color: #0000ff;"&gt;var</span> addr =<span style="color: #000000;"&gt; input.ScriptSig.GetSignerAddress(Network.Main); 
            </span><span style="color: #0000ff;"&gt;if</span> (addr != <span style="color: #0000ff;"&gt;null</span><span style="color: #000000;"&gt;) 
            { 
                txInput.Address </span>=<span style="color: #000000;"&gt; addr.ToString(); 
            } 
        } 
         </span><span style="color: #0000ff;"&gt;if</span> (txInput.PaymentScript.Length > <span style="color: #800080;"&gt;8000</span><span style="color: #000000;"&gt;) 
        { 
             log.Error(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;Transaction Input PaymentScript异常,将被截断,TxHash: </span><span style="color: #800000;"&gt;"</span> +<span style="color: #000000;"&gt; tx.TxHash); 
            txInput.PaymentScript </span>= txInput.PaymentScript.Substring(<span style="color: #800080;"&gt;0</span>,<span style="color: #800080;"&gt;7999</span><span style="color: #000000;"&gt;); 
        } 
        tx.TxInput.Add(txInput); 
    } 
    </span><span style="color: #0000ff;"&gt;for</span> (<span style="color: #0000ff;"&gt;var</span> idx = <span style="color: #800080;"&gt;0</span>; idx < transaction.Outputs.Count; idx++<span style="color: #000000;"&gt;) 
    { 
        </span><span style="color: #0000ff;"&gt;var</span> output =<span style="color: #000000;"&gt; transaction.Outputs[idx]; 
        </span><span style="color: #0000ff;"&gt;var</span> txOutput = <span style="color: #0000ff;"&gt;new</span><span style="color: #000000;"&gt; TxOutput() 
        { 
            Amount </span>=<span style="color: #000000;"&gt; output.Value.Satoshi,ScriptPubKey </span>=<span style="color: #000000;"&gt; output.ScriptPubKey.ToString(),ScriptPubKeyLen </span>=<span style="color: #000000;"&gt; output.ScriptPubKey.Length,IsUnspendable </span>=<span style="color: #000000;"&gt; output.ScriptPubKey.IsUnspendable,IsPayToScriptHash </span>=<span style="color: #000000;"&gt; output.ScriptPubKey.IsPayToScriptHash,IsValid </span>=<span style="color: #000000;"&gt; output.ScriptPubKey.IsValid,Idx </span>=<span style="color: #000000;"&gt; idx

        }; 
        </span><span style="color: #0000ff;"&gt;if</span> (txOutput.ScriptPubKey.Length > <span style="color: #800080;"&gt;8000</span><span style="color: #000000;"&gt;) 
        { 
            log.Error(</span><span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;Transaction Output ScriptPubKey异常,TxHash: </span><span style="color: #800000;"&gt;"</span> +<span style="color: #000000;"&gt; tx.TxHash); 
            txOutput.ScriptPubKey </span>= txOutput.ScriptPubKey.Substring(<span style="color: #800080;"&gt;0</span>,<span style="color: #800080;"&gt;7999</span><span style="color: #000000;"&gt;); 
        } 
        </span><span style="color: #0000ff;"&gt;if</span> (!<span style="color: #000000;"&gt;output.ScriptPubKey.IsUnspendable) 
        { 
            </span><span style="color: #0000ff;"&gt;if</span><span style="color: #000000;"&gt; (output.ScriptPubKey.IsPayToScriptHash) 
            { 
                txOutput.Address </span>=<span style="color: #000000;"&gt; output.ScriptPubKey.GetScriptAddress(Network.Main).ToString(); 
            } 
            </span><span style="color: #0000ff;"&gt;else</span><span style="color: #000000;"&gt; 
            { 
                 </span><span style="color: #0000ff;"&gt;var</span> addr =<span style="color: #000000;"&gt; output.ScriptPubKey.GetDestinationAddress(Network.Main); 
                </span><span style="color: #0000ff;"&gt;if</span> (addr == <span style="color: #0000ff;"&gt;null</span><span style="color: #000000;"&gt;) 
                 { 
                    </span><span style="color: #0000ff;"&gt;var</span> keys =<span style="color: #000000;"&gt; output.ScriptPubKey.GetDestinationPublicKeys(); 
                    </span><span style="color: #0000ff;"&gt;if</span> (keys.Length == <span style="color: #800080;"&gt;0</span><span style="color: #000000;"&gt;) 
                    { 
                         </span><span style="color: #008000;"&gt;//</span><span style="color: #008000;"&gt;异常 </span>
                        log.Warn(<span style="color: #800000;"&gt;"</span><span style="color: #800000;"&gt;Transaction Output异常,TxHash: </span><span style="color: #800000;"&gt;"</span> +<span style="color: #000000;"&gt; tx.TxHash); 
                    } 
                     </span><span style="color: #0000ff;"&gt;else</span><span style="color: #000000;"&gt; 
                    { 
                         addr </span>= keys[<span style="color: #800080;"&gt;0</span><span style="color: #000000;"&gt;].GetAddress(Network.Main); 
                     } 
                } 
                </span><span style="color: #0000ff;"&gt;if</span> (addr != <span style="color: #0000ff;"&gt;null</span><span style="color: #000000;"&gt;) 
                { 
                    txOutput.Address </span>=<span style="color: #000000;"&gt; addr.ToString(); 
                } 
             } 
        } 
        tx.TxOutput.Add(txOutput); 
     } 
} 
</span><span style="color: #0000ff;"&gt;return</span><span style="color: #000000;"&gt; blk; 

}

至于WriteBitcoin2Csv方法,就是以一定的格式,把Block、Trans、TxInput、TxOutput这4个对象分别写入4个文本文件中即可。

四、将CSV导入SQL Server

在完成了CSV文件的导出后,接下来就是怎么将CSV文件导入到SQL Server中。这个很简单,只需要执行BULK INSERT命令。比如这是我在测试的时候用到的SQL语句:

Trans TxInput TxOutput ;

当然在实际的情况中,我并不是这么做的。我是每1000个Block就生成4个csv文件,然后使用C#连接到数据库,执行bulk insert命令。执行完成后再把这生成的4个csv文件删除,然后再循环继续导出下一批1000个Block。因为比特币的区块链数据实在太大了,如果我不分批,那么我的PC机硬盘就不够用了,而且在导入SQL Server的时候我也怀疑能不能导入那么大批量的数据。

最后,附上一张我正在导入中的进程图,已经导了一天了,还没有完成,估计还得再花一、两天时间吧。

image

所有区块链数据都进入数据库以后,就要发挥一下我的想象力,看能够分析出什么有意思的结果了。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读