Analyse bitcoin blockchain using sql functions​
​by Damian Calin
The objective is to analyse blockchain data available via BlockchainBlockData .
Once blocks data are collected and transformed in tabular format we could use SQL functions to structure, transform , aggregate and visualize blocks attributes.
​
SQL functions for Wolfram are described and defined in previous post (https://community.wolfram.com/groups/-/m/t/2195893)
In order to load SQL functions evaluate “Main Code” cell from SQL_Operators notebook ( https://www.wolframcloud.com/obj/damcalrom/Published/SQL_Operators.nb )​
​
Get the last available block number
In[]:=
lastBlockNo=BlockchainBlockData[-1,{"BlockNumber"}]//First
Out[]=
687937
Check the structure of bitcoin block
In[]:=
BlockchainBlockData[lastBlockNo]//Dataset
Out[]=
BlockHash
00000000000000000006667ef9ede66e6e1c874006ee52b7aec5c5a21e54b578
BlockNumber
687937
Timestamp
Thu 17 Jun 2021 14:37:41
Amounts
BlockReward
₿
6.25
,TotalFee
₿
0.133
,TotalInput
₿
25281.
,TotalOutput
₿
25280.9

ByteCount
648867
Nonce
2137493012
Version
545259524
Confirmations
1
PreviousBlockHash
00000000000000000007bc61c6fd6aaca05a72074128159cd0e90103a1b9880e
MerkleRoot
d3ece8c86cdef1f8ba4807b406217bdd95346cccc162cdaf4d6fcdd736df4542
TotalTransactions
1312
TransactionList
{
…
1312
}
Select some attributes of interests
In[]:=
props={"Timestamp","BlockNumber","TotalTransactions","ByteCount","Amounts"};
Get the block attributes into a sql table structure. - We take the last 1000 generated blocks starting from last block backwards (takes aprox 250 seconds , most of the time being spent in block retrieval func BlockchainBlockData) - Converts the association type column “Amount” into a values list and then creates corresponding columns
In[]:=
tbLastBlocks=Range[lastBlockNo-1000,lastBlockNo]//​​ Map[BlockchainBlockData[#,props]&,#]&//​​ tableSQL[#,props]&//​​ rowMapSQL[#,{All},ReplaceAll[#,x_Association({x//Values})]&]&//​​ unnestSQL[#,{Amounts},{"BlockReward","TotalFee","TotalInput","TotalOutput"}]&;//AbsoluteTiming
Out[]=
{290.413,Null}
Browse sql table data as a dataset
In[]:=
tbLastBlocks//​​tableSQLAsDataset​​
Out[]=
Timestamp
BlockNumber
TotalTransactions
ByteCount
BlockReward
TotalFee
TotalInput
TotalOutput
Wed 9 Jun 2021
11:24:34
686937
2495
1230781
฿6.25
฿0.0526852
฿4477.11
฿4477.06
Wed 9 Jun 2021
11:38:58
686938
2565
1370108
฿6.25
฿0.256031
฿28420.7
฿28420.4
Wed 9 Jun 2021
11:39:20
686939
648
915599
฿6.25
฿0.0154144
฿170.969
฿170.954
Wed 9 Jun 2021
11:42:10
686940
636
350656
฿6.25
฿0.0601953
฿947.014
฿946.954
Wed 9 Jun 2021
11:50:52
686941
1675
939707
฿6.25
฿0.242946
฿3247.91
฿3247.67
Wed 9 Jun 2021
11:51:07
686942
98
76707
฿6.25
฿0.00787015
฿194.577
฿194.569
Wed 9 Jun 2021
12:00:53
686943
918
1174515
฿6.25
฿0.251815
฿3014.29
฿3014.04
Wed 9 Jun 2021
12:48:56
686944
2945
1393425
฿6.25
฿0.52046
฿33104.5
฿33103.9
Wed 9 Jun 2021
12:59:56
686945
2272
1512837
฿6.25
฿0.256758
฿6941.74
฿6941.49
Wed 9 Jun 2021
13:15:46
686946
2548
1385459
฿6.25
฿0.284221
฿15347.
฿15346.7
rows 1–10 of 1001
​
Once retrieved in table structure data could be exported locally in csv file to avoid reusing BlockchainBlockData.
The blocks in blockchain are immutable.
tbLastBlocks["data"]//​​Prepend[#,tbLastBlocks["header"]//Keys]&//​​Export["Blockchain.csv",#,"CSV","FieldSeparators"";"]&​​
Out[]=
Blockchain.csv
Out[]=
C:\Users\relat
Aggregate data by hour
In[]:=
tbLastBlocks//​​groupBySQL[#,{DateObject[Timestamp,"Hour"]}]&//​​summarySQL[#,Association["BlocksMined"(BlockNumber//Length),​​ "TotalTransactions"(TotalTransactions//Total),​​ "BlockReward"(BlockReward//Total)]]&//​​showTableSQL
Total Rows:193 Elapsed:0.0581299
Out[]//TableForm=
Aggregate data by day
In[]:=
tbLastBlocks//​​groupBySQL[#,{DateObject[Timestamp,"Day"]}]&//​​summarySQL[#,Association["BlocksMined"(BlockNumber//Length),​​ "TotalTransactions"(TotalTransactions//Total),​​ "BlockReward"(BlockReward//Total)]]&//​​showTableSQL
Total Rows:9 Elapsed:0.0409658
Out[]//TableForm=
Timestamp
BlocksMined
TotalTransactions
BlockReward
Day: Wed 9 Jun 2021
73
146972
Missing[NotAvailable]+
฿
450.
Day: Thu 10 Jun 2021
124
266379
6Missing[NotAvailable]+
฿
737.5
Day: Fri 11 Jun 2021
104
218358
3Missing[NotAvailable]+
฿
631.25
Day: Sat 12 Jun 2021
130
223244
4Missing[NotAvailable]+
฿
787.5
Day: Sun 13 Jun 2021
128
185447
8Missing[NotAvailable]+
฿
750.
Day: Mon 14 Jun 2021
132
226511
8Missing[NotAvailable]+
฿
775.
Day: Tue 15 Jun 2021
140
255658
5Missing[NotAvailable]+
฿
843.75
Day: Wed 16 Jun 2021
123
256886
Missing[NotAvailable]+
฿
762.5
Day: Thu 17 Jun 2021
47
74370
฿
293.75
We have some missing values . Is it because the blocks are invalid ? or BlockchainBlockData function retrieval issue? Have no idea :)
Here some blocks having missing rewards
In[]:=
tbLastBlocks//​​whereSQL[#,MissingQ[BlockReward]]&//​​showTableSQL
Total Rows:36 Elapsed:0.0045233
Out[]//TableForm=
Plot daily data aggregations
Even is irrelevant we check some correlation between block attribute and BTC price as an exercise