Empty Blocks in the Bitcoin Blockchain?
In this notebook we'll have a brief look at a peculiar case: empty blocks in the Bitcoin Blockchain.
Pretty interesting there are "empty" blocks in the Bitcoin Blockchain. Well, they are not entirely empty. They just have only one transaction, which is the coinbase reward.
No other transactions. Miners earn fees from transactions, so why they should mine empty blocks?
Here's a brief explanation:
When a mining pool receives a new block, it needs to download the full block, validate its transactions and define a new block to mine on. To avoid wasting hashing power, they just start mining a new block with only the coinbase transaction. By mining an empty block, a miner removes the risk of duplicate transactions in their new block, which would instantly be rejected by the Bitcoin network. If the Bitcoin network rejects a block due to duplicate transactions, the miner that mined the block loses out on the coinbase reward, hence the incentive to mine empty blocks.
But let's start playing our favourite game.
In [1]:
# First we import blocksci import blocksci # We import Counter from collections, which we will use to count items in the lists we'll create from collections import Counter # we instantiate the chain object chain = blocksci.Blockchain("/BlockSci/config_file") # we also import import pandas as pd import matplotlib.pyplot as plt import seaborn as sns %matplotlib inline sns.set() %time
CPU times: user 2 µs, sys: 2 µs, total: 4 µs Wall time: 7.63 µs
Let's start to collect all miners information from all the Blockchain. We will use the function miner() that returns the name of the Miner if he chose to write it in the Block.
In [2]:
#instantiate the list of Miners of all Blocks in Bitcon Blockchain list_of_Miners = [] #collect all Miners from Blockchain for x in chain : list_of_Miners.append(x.miner())
Let's see what we found:
In [3]:
#print list of blocks of the Blockchain print(len(list_of_Miners))
684080
In [4]:
#Enumerate Miners and Blocks mined each one Counter(list_of_Miners)
Out[4]:
Counter({'Unknown': 329360, 'Eligius': 11425, 'BitMinter': 6464, 'BTC Guild': 32935, 'NMCbit': 105, 'Yourbtc.net': 226, 'simplecoin.us': 43, 'OzCoin': 4845, 'BTCServ': 9, 'poolserverj': 5596, 'SlushPool': 34600, 'EclipseMC': 5791, 'BitLC': 326, 'pool.mkalinin.ru': 83, 'MaxBTC': 449, 'TripleMining': 333, 'CoinLab': 346, 'HHTT': 623, 'stratum': 394, 'stratumPool': 1802, 'Mt Red': 77, '50BTC': 6392, 'Bitparking': 583, 'ASICMiner': 3127, 'F2Pool': 34915, 'ST Mining Corp': 48, 'GHash.IO': 789, '175btc': 22, 'Pierce and Paul': 548, 'MegaBigPower': 282, '50btc.com': 14, 'Polmine': 1069, 'AntPool': 54913, 'mmpool': 40, 'nodeStratum': 837, 'KnCMiner': 6290, 'digitalBTC': 612, 'bcpool.io': 8, 'Bitcoin Affiliate Network': 438, 'Solo CKPool': 245, 'KanoPool': 2432, 'BTCC Pool': 17964, 'TangPool': 297, 'BW.COM': 12414, 'HASHPOOL': 1, 'BitClub Network': 5671, '21 Inc.': 42, 'BitFury': 17268, '8baochi': 51, 'TBDice': 4, 'NiceHash Solo': 20, 'A-XBT': 7, 'Nexious': 1, 'Bravo Mining': 13, 'HotPool': 11, 'BCMonster': 15, 'ViaBTC': 21384, 'Bixin': 2374, 'GBMiners': 2093, 'BTC.com': 31616, 'Bitcoin.com': 2475, 'shawnp0wers': 4, 'Bitcoin India': 114, 'PHash.IO': 44, 'BTC.TOP': 16647, 'ConnectBTC': 153, 'BATPOOL': 441, 'xbtc.exx.com&bw.com': 116, 'CANOE': 321, 'MiningKings': 41, 'HAOZHUZHU': 25, 'BitcoinRussia': 127, 'Waterhole': 35, '7pool': 1, 'CKPool': 86, '58COIN': 745, 'DCExploration': 3, 'HashBX': 1, 'DPOOL': 1918, 'Haominer': 10, 'SigmaPool.com': 91})
Now let's show the data in a chart:
In [5]:
data1 = dict(Counter(list_of_Miners)) # Data to plot labels = [] sizes = [] for x, y in data1.items(): labels.append(x) sizes.append(y) # Plot plt.figure(figsize=(30,30)) plt.pie(sizes, labels=labels) plt.axis('equal') plt.show() #Bars names = list(data1.keys()) values = list(data1.values()) #tick_label does the some work as plt.xticks() plt.bar(range(len(data1)),values,tick_label=names) plt.savefig('bar.png') # plotting a line plot after changing it's width and height plt.xticks(rotation='vertical') fig = plt.gcf() fig.set_size_inches(20,10) plt.show()
So 329360 blocks on a total of 684080 blocks shows 'Unknown' as Miner. That's 48.14% of the total.
In [6]:
#Now We exclude 'Unknown', in order to make the chart more readable data1.pop('Unknown', None) # Data to plot labels = [] sizes = [] for x, y in data1.items(): labels.append(x) sizes.append(y) # Plot plt.figure(figsize=(30,30)) plt.pie(sizes, labels=labels) plt.axis('equal') plt.show() #Bars names = list(data1.keys()) values = list(data1.values()) #tick_label does the some work as plt.xticks() plt.bar(range(len(data1)),values,tick_label=names) plt.savefig('bar.png') # plotting a line plot after changing it's width and height plt.xticks(rotation='vertical') fig = plt.gcf() fig.set_size_inches(20,10) plt.show()
Now we'll check the number of empty blocks and see its distribution between the miners.
In [7]:
# Let's collect all blocks with zero fees (except coinbase reward) # We instantiate a list variable to collect blocks with zero fees zero_fees_blocks = [] # collect blocks with zero fees for x in chain : if x.fee == 0 : zero_fees_blocks.append(x)
In [8]:
# We print the lenght of the list of blocks with zero fees and the lenght of the used blockchain data print("Number of blocks without fees:", len(zero_fees_blocks)) print("On a total number of blocks: ", len(chain))
Number of blocks without fees: 125451 On a total number of blocks: 684080
So we found 125.451 blocks with zero fees. On a total of 684080 blocks analyzed, it’s about 18,33% of the blocks.In [9]:
# So we instantiate a list variable to collect miners name from the list of the blocks with zero fees list_zero_fee_block_miners = [] # Collect names of miners that have mined zero fee blocks for x in zero_fees_blocks : list_zero_fee_block_miners.append(x.miner())
In [10]:
# Eumerate list of Miners of zero fees Blocks and put in a dict call data data = dict(Counter(list_zero_fee_block_miners)) data
Out[10]:
{'Unknown': 120078, 'Eligius': 454, 'BitMinter': 192, 'BTC Guild': 78, 'Yourbtc.net': 2, 'OzCoin': 8, 'SlushPool': 280, 'EclipseMC': 86, 'BitLC': 7, 'poolserverj': 5, 'CoinLab': 1, 'TripleMining': 2, '50BTC': 3, 'F2Pool': 883, 'ASICMiner': 9, 'HHTT': 1, 'Pierce and Paul': 31, 'Polmine': 2, 'AntPool': 1746, 'KnCMiner': 220, 'TangPool': 7, 'BTCC Pool': 422, 'Bitcoin Affiliate Network': 2, 'BW.COM': 319, 'Bixin': 42, 'ViaBTC': 66, 'BTC.com': 384, 'PHash.IO': 1, 'BTC.TOP': 83, 'CANOE': 1, 'Bitcoin.com': 7, 'Waterhole': 1, '58COIN': 27, 'GBMiners': 1}
On a total of 125451 blocks without fees, 120078 are labeled as ‘Unknown’. It makes the 95.71%. So most of the empty blocks are mined by Unknown entities. It is quite a different percentage between the distribution between known and unknown miners for all the Blocks. Let’s see the data in charts.In [11]:
# Data to plot labels = [] sizes = [] for x, y in data.items(): labels.append(x) sizes.append(y) # Plot plt.figure(figsize=(20,20)) plt.pie(sizes, labels=labels) plt.axis('equal') plt.show() #Bars names = list(data.keys()) values = list(data.values()) #tick_label does the some work as plt.xticks() plt.bar(range(len(data)),values,tick_label=names) plt.savefig('bar.png') # plotting a line plot after changing it's width and height plt.xticks(rotation='vertical') fig = plt.gcf() fig.set_size_inches(20,10) plt.show()
In [ ]:
In [12]:
#Now We exclude 'Unknown', in order to make the chart more readable data.pop('Unknown', None) # Data to plot labels = [] sizes = [] for x, y in data.items(): labels.append(x) sizes.append(y) # Plot plt.figure(figsize=(20,20)) plt.pie(sizes, labels=labels) plt.axis('equal') plt.show() #Bars names = list(data.keys()) values = list(data.values()) #tick_label does the some work as plt.xticks() plt.bar(range(len(data)),values,tick_label=names) plt.savefig('bar.png') # plotting a line plot after changing it's width and height plt.xticks(rotation='vertical') fig = plt.gcf() fig.set_size_inches(20,10) plt.show()
For this tutorial we finish here. There are many things that can be discovered and analyzed in the Bitcoin Blockchain. If you are curious, join our beta tester program, and join the fray! :) And don't forget to smile!