ANALYSIS OF THE GENESIS BLOCK INTEGRITY
It is important to verify that the genesis block is absolutely correct, does not contain malicious entries and does not lack any entries that should be there. To verify this, I have written a genesis block integrity checker. The source code will be at the end of this message:
1. What Adresses Were Used for Donations:Address
3Q2aKEGFTKDw3hghsBifXp39CZVMtZukxn has
449 tx in total
Address
1ELC1CgH9jcuQtzXRfmSNKtTiRYKqwjr9q has
49 tx in total
Address
3Qnj4QtdD4qtZcP82xyLq2paAEPDgfwezd has
75 tx in total
In total we have seen 573 tx.2. Incoming and Outgoing Transactions:Out of these
573 tx we have ...
Total legit incoming tx:
508Total legit outgoing tx:
36Then we have 24 ignored transactions. Ignored means that funds were just moved between the local wallets
("3Q2aKEGFTKDw3hghsBifXp39CZVMtZukxn","3Qnj4QtdD4qtZcP82xyLq2paAEPDgfwezd","1ELC1CgH9jcuQtzXRfmSNKtTiRYKqwjr9q", "1NETgKnhsGzpN3sW3vid6bhTjBM4o2iaKi","3AVhok6gvrgSbTXfGEksYKEWBdxS9qo8E6")And we have 5 fucked up transactions, these are TX that have sent less than 0.01 BTC and therefore (according to the terms and conditions) got nothing. Lannister you should offer refunds on that, but this just my personal opinion.
3. Hashes of ignored transactions: -> 1d35329ea9e8dc7a5c1548e6edae5529e6b07ce8bcad650e7e53032e561cdfc9
-> 6695b2796551099ac2450ec58fca699485659498a2807aec40cd8817a61e08a3
-> c79f6028d73ea68cd16e01eaa8f2f227871c8f964c31ca37c28b1f5da9c63e14
-> 889d3430eea8b1569da529e29161e54ad3b61245db282eff4b4ee5cc14af115b
-> 9c98f78f35b986be8741c59eb4c50b1c46b0296f85e75391b9e7fd330d105e83
-> 6cf76f5bd2f6a315b2cf40726c4dee022b5b6ebe7e2da42e2558a1b128b659a8
-> 6c37aef010c5a88da0cfe42f7371f82dcc7fce34e30ac022c61f344ac096be9d
-> 1cf1c550e1921a6e2949e729f83fd8b147c35256730a5075ed1fdbf79bc0f1c7
-> 11f1c5ea10e9736197ac971c799e583d915ab89ea6f2bc019216b6193d90f07c
-> e32b9362af4f79ce91f6a491ef72f85f0ed17db3584d7dedaa1e4ab1bb0182c3
-> f66c6e7bb94c2d5c0b676ab4ba396180edb4174911dc02e079559f1e15da173b
-> ee1ac2c929358c737ba5c34a576478a1cfe76c04530c41d8cfc8ff25bda79479
-> 518a8ece2c3c47cc56770584afe350a5021e3c3ca0c55a485f5f3dbff2218ae8
-> f3569fdfac1da427902d3017e3afa4237a9ea5a069621cf357cba1ca830c57f6
-> 7af8b806e35c941d52501e95ceaca73aaa80e8c3f8645a47444b6308b802eb5b
-> 46134c30005e93d30c10e9a0758ae6ddc9aa26f3bcb72b270657980f9cb0b776
-> daf257b2206e85069cca7e02f373e6d1eeb2d6f13850a11e17ab447ad67b75c7
-> 35f8db04c7d20efa2394fb40784211d6d6c854f0e6baec0f2155f59893e0a10d
-> 5eed7014dc0df1e5c544df75ddc832d53018aed53e7de227c7ccbd1292a85fed
-> 89c5fe5094b49271a0f04e56b4e16d4dcf66b2646cf38f88132109dc47d69126
-> b8f5144ecc503802eb95d4f243706b1c838fcded4931250172563fac5d66fd06
-> b9c0c7d45d00d7085b406dd4c5be97d039bb69fe39189cadc2fedceaaca9900a
-> 3af3171ba5460d76dae60e4f7e8425df502eb30350646b381eeb518b37639974
-> e51ed51928cf83ffde2927ca11905e71f2cc1ead7e78ddf79e80ac6c54c99ce7
4. Fucked up transactions list: -> df2ce20673b75a73f50a43232f42db2fcdc14fa4fade62d7ca7e64c72e5565c6
-> 551d2953bfca100b2c6788c1ce8dd327f88ee1cff57b7174aacdac9e449ae7b5
-> b8ef265cd8f2569919c19ebb9ee73ea78d9c697870957f6bf3e542b2ed133d06
-> 13c018ad6def3c56e35a9b09428b8acf5a342bacb6ef755800a3578d07abb4a0
-> 0ae2ec45b00f82525448008e1ed40cb77a41a28302d64dc62e6b55073ba47de4
!!! DISCREPANCY: We have 508 legit incoming transactions but only 497 entries in the genesis block !!!5. List of TX that are in the blockchain (in those 508 legit tx) but not in the genesis block (in the 497 entires): -> c091160dcaaaac6879cdfd7726a200801670a9f31bf7a7c531e0ae7b77f6e70e [1P4LiqFF5kP96cAuM2WoEVfyoiYYxnLhyU] = 0.8082131 BTC in total (dont count addrs twice)
-> 17e06c6b0ebc8356d4ab1007d123c74d9d0e79d129a7017135e64cb290cba5e7 [1SdoAbypnx1NKMpsC6VbmVBGCJyX3hP3K]
-> 7fed267c0c108c7a1e8288ad1c9f9eb3f1bc275e8d646b87e3da0ed41d1488d1 [1SdoAbypnx1NKMpsC6VbmVBGCJyX3hP3K] = 1.97 BTC in total (dont count addrs twice)
-> 0fa55082975c3a9a4fd838881ce653fdb079cdcd8a14583862125f6f106e1bbb [1AKo8QK11FurGNvCnKuHvDFEFdavDRMZGo] = 0.2767 BTC in total (dont count addrs twice)
-> 9712be14e37f28307874d8507d68e648ddd776c1f8ed12de779e87119aa9895e [3De41NGxSHuDgEcGXq8757HUK6m5tJfvdP] = 0.051 BTC in total (dont count addrs twice)
-> 0ce3a952c09df4ba66f9d5181b640b4f1e224e0d9a377035ec30bdf040fee897 [1GUrpXQySkMghpWEgfpGnMc7HTNeTe6hBn] = 0.454962 BTC in total (dont count addrs twice)
-> 38eb02515975f5fc4024a09f58663a1ade2dfadf1ee5bacba6ab68f5f8f1acbe [17kGd5dKGSssNn477Rjd8kmJdsrUSM626Q] = 0.0103 BTC in total (dont count addrs twice)
-> c9c25ec07b37ec2cd6849f7de3c64706da84a3394b45fa5a9e0cb5c14cdaf111 [16MmuQWvJuNqJRLgoYfwvBeqVHr3BqmFwk] = 1.5 BTC in total (dont count addrs twice)
-> 1e2fb7b8ebd921de452334a863661ce7b105e7cea7275f7ec3908f391fdcbb9f [13HfJkxPLJhTrCJEQSP3h6AZ23f63HpRGM]
-> 4965a221f2a945fcb21c814afc737ef31748cc0fa52f989f16ac12edb9968bae [13HfJkxPLJhTrCJEQSP3h6AZ23f63HpRGM] = 2.418 BTC in total (dont count addrs twice)
-> 13e5c99a85ae8995d0e518f7f24b3800f993fc581457eaeb255720b9d74f54d6 [19g9GuHbmJJLi7VwrhkAQJeebdKyXsKYAX] = 1.003 BTC in total (dont count addrs twice)
-> bcad11d4c3c671554ffe1e0cd9f10db35668e3989ca55a1383184446286c4f8c [1KkUA1YrU6d6kU348rGZFxsNAdDezaSpEQ] = 0.5007 BTC in total (dont count addrs twice)
!!! TRYING TO EXPLAIN THE DISCREPANCIES !!!6. Missing Entries in Genesisblock that got Refunded from Official AdressesAutomatic blockchain parsing revealed refunds from the donation addresses that explain why certain inbound TX do not end up in the genesis block:
Explained missing 0.808213 BTC from 1P4LiqFF5kP96cAuM2WoEVfyoiYYxnLhyU, we saw refunds as high as 0.808023 BTC
-> 5312f91d3839125ac2fedcb205b9ae1939edc457f36b6509a909cc9d8cfd8f08 refunded 0.80802271 BTC
Explained missing 1.003000 BTC from 19g9GuHbmJJLi7VwrhkAQJeebdKyXsKYAX, we saw refunds as high as 1.003000 BTC
-> ea3b875e5a9c9cc789fcb6bddd270042b1202481b5bedeaa01b59294379fbdc5 refunded 1.003 BTC
Explained missing 0.500700 BTC from 1KkUA1YrU6d6kU348rGZFxsNAdDezaSpEQ, we saw refunds as high as 0.500700 BTC
-> 3550fda47fd9527c0a0b8f04034af06317a83767dcc6f378ec4c557ef3337790 refunded 0.5007 BTC
Explained missing 0.454962 BTC from 1GUrpXQySkMghpWEgfpGnMc7HTNeTe6hBn, we saw refunds as high as 0.454987 BTC
-> 842a849f860fb9b72ad06dcbd455bd1d1c970a3764eef27a46200ecf336bdb1f refunded 0.45498688 BTC
Explained missing 1.970000 BTC from 1SdoAbypnx1NKMpsC6VbmVBGCJyX3hP3K, we saw refunds as high as 1.969960 BTC
-> de1a2d337c7e92e13c5e216cc39bf8f8bb38215fd167660c63bdc6ba69242f8c refunded 1.96995956 BTC
7. Missing Entries in Genesisblock that got Refunded from other sourcesTo sum up, these missing entries are still to be explained:
-> 0fa55082975c3a9a4fd838881ce653fdb079cdcd8a14583862125f6f106e1bbb [1AKo8QK11FurGNvCnKuHvDFEFdavDRMZGo] = 0.2767 BTC in total (dont count addrs twice)
-> 9712be14e37f28307874d8507d68e648ddd776c1f8ed12de779e87119aa9895e [3De41NGxSHuDgEcGXq8757HUK6m5tJfvdP] = 0.051 BTC in total (dont count addrs twice)
-> 38eb02515975f5fc4024a09f58663a1ade2dfadf1ee5bacba6ab68f5f8f1acbe [17kGd5dKGSssNn477Rjd8kmJdsrUSM626Q] = 0.0103 BTC in total (dont count addrs twice)
-> c9c25ec07b37ec2cd6849f7de3c64706da84a3394b45fa5a9e0cb5c14cdaf111 [16MmuQWvJuNqJRLgoYfwvBeqVHr3BqmFwk] = 1.5 BTC in total (dont count addrs twice)
-> 1e2fb7b8ebd921de452334a863661ce7b105e7cea7275f7ec3908f391fdcbb9f [13HfJkxPLJhTrCJEQSP3h6AZ23f63HpRGM]
-> 4965a221f2a945fcb21c814afc737ef31748cc0fa52f989f16ac12edb9968bae [13HfJkxPLJhTrCJEQSP3h6AZ23f63HpRGM] = 2.418 BTC in total (dont count addrs twice)
Let's do it manually:
1.) 1AKo received a refund for the whole 0.2767 BTC in this transaction:
54a7fbb765713967ef314dda087b2239d86e16292b9d881652632706db22f2732.) 13Hfjkx received a refund for the whole 2.418 BTC in this transaction:
846326c8efe979976248967b117b09dbb11b08278bd5f71d8f20d8b84ecaa0c03. 16Mmu received a refund for the whole 1.5 BTC in this transaction:
6caad238d66ce67cc1ff2d0e8df8a0bbed9ca36bbe8a6636bcee321b93c6c00e8. People who SHOULD have gotten XEL:These people are not in the genesis block but should be there!
We MUST(!!!!!!!) patch it by hand!17kGd5dKGSssNn477Rjd8kmJdsrUSM626Q - 0.0103 BTC in block 400661
3De41NGxSHuDgEcGXq8757HUK6m5tJfvdP - 0.051 BTC in block 401570
All in all, this is very positive. The genesis block is just off by 0.0613 BTC9. The Python Scriptimport urllib2
import os.path
import json
import time
import sys
def ensure_is_present(url, file_name):
exists = os.path.isfile(file_name)
if not exists:
time.sleep(2)
u = urllib2.urlopen(url)
f = open(file_name, 'wb')
meta = u.info()
try:
file_size = int(meta.getheaders("Content-Length")[0])
except:
file_size = 1000
print "Downloading: %s Bytes: %s" % (file_name, file_size)
file_size_dl = 0
block_sz = 8192
while True:
buffer = u.read(block_sz)
if not buffer:
break
file_size_dl += len(buffer)
f.write(buffer)
status = r"%10d [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
status = status + chr(8)*(len(status)+1)
print status,
f.close()
print ""
addresses = ["3Q2aKEGFTKDw3hghsBifXp39CZVMtZukxn","3Qnj4QtdD4qtZcP82xyLq2paAEPDgfwezd","1ELC1CgH9jcuQtzXRfmSNKtTiRYKqwjr9q"]
internals_ignore = ["1NETgKnhsGzpN3sW3vid6bhTjBM4o2iaKi","3AVhok6gvrgSbTXfGEksYKEWBdxS9qo8E6"]
estimations = {}
loaded = {}
outgoing = []
incoming = []
ignored = []
failures = []
def ensure_is_present_with_offset(url, file_name, offset=0):
global estimations
global loaded
global outgoing
global incoming
global ignored
global failures
innerfname = "offset-" + str(offset) + "-" + file_name
exists = os.path.isfile(innerfname)
if not exists:
time.sleep(2)
u = urllib2.urlopen(url.replace("offset=0","offset="+str(offset)))
f = open(innerfname, 'wb')
meta = u.info()
try:
file_size = int(meta.getheaders("Content-Length")[0])
except:
file_size = 1000
print "Downloading: %s Bytes: %s" % (innerfname, file_size)
file_size_dl = 0
block_sz = 8192
while True:
buffer = u.read(block_sz)
if not buffer:
break
file_size_dl += len(buffer)
f.write(buffer)
status = r"%10d [%3.2f%%]" % (file_size_dl, file_size_dl * 100. / file_size)
status = status + chr(8)*(len(status)+1)
print status,
f.close()
print ""
with open(innerfname) as data_file:
data = json.load(data_file)
if data["address"] not in estimations:
estimations[data["address"]] = int(data["n_tx"])
loaded[data["address"]] = 0
if "txs" in data:
loaded[data["address"]] += len(data["txs"])
for x in data["txs"]:
is_outgoing = False
is_ignored = False
for n in x["inputs"]:
for uu in internals_ignore:
if n["prev_out"]["addr"] == uu:
is_ignored = True
break
if n["prev_out"]["addr"] == data["address"]:
is_outgoing = True
break
elif n["prev_out"]["addr"] == addresses[0] or n["prev_out"]["addr"] == addresses[1] or n["prev_out"]["addr"] == addresses[2]:
is_ignored = True
if is_outgoing and not is_ignored:
for pp in x["out"]:
if "addr" not in pp:
continue
for uu in internals_ignore:
if pp["addr"] == uu:
is_ignored = True
break
if pp["addr"] == data["address"]:
total_out += pp["value"]
if is_ignored == True:
ignored.append(x)
else:
outgoing.append(x)
elif not is_outgoing and not is_ignored:
# check if the output was 0.01BTC or higher
is_failure = False
total_out = 0
for pp in x["out"]:
if "addr" not in pp:
continue
for uu in internals_ignore:
if pp["addr"] == uu:
is_ignored = True
break
if pp["addr"] == data["address"]:
total_out += pp["value"]
if is_ignored == True:
ignored.append(x)
elif total_out<1000000: # 1 mio satoshi = 0.01 BTC
failures.append(x)
else:
incoming.append(x)
else:
ignored.append(x)
# trigger next offset loading
if len(data["txs"])==50:
ensure_is_present_with_offset(url,file_name, offset+50)
# JSON Genesis Block
url = "https://raw.githubusercontent.com/elastic-project/genesis-block/master/genesis-block.json"
file_name = url.split('/')[-1]
ensure_is_present(url, file_name)
# All TX from 3Q2 address
url2 = "https://blockchain.info/address/3Q2aKEGFTKDw3hghsBifXp39CZVMtZukxn?format=json&offset=0&/3q2address.json"
file_name2 = url2.split('/')[-1]
ensure_is_present_with_offset(url2, file_name2)
# All TX from 3Qnj address
url3 = "https://blockchain.info/address/3Qnj4QtdD4qtZcP82xyLq2paAEPDgfwezd?format=json&offset=0&/3qnjaddress.json"
file_name3 = url3.split('/')[-1]
ensure_is_present_with_offset(url3, file_name3)
# All TX from 3Qnj address
url4 = "https://blockchain.info/address/1ELC1CgH9jcuQtzXRfmSNKtTiRYKqwjr9q?format=json&offset=0&/1elcjaddress.json"
file_name4 = url4.split('/')[-1]
ensure_is_present_with_offset(url4, file_name4)
# Did the loading go well?
print "Checking if the downloaded json files from blockchain.info are correct"
for x in estimations:
print "Address %s\tshould have %d tx\tloaded %d tx" % (x,estimations[x],loaded[x])
if estimations[x] != loaded[x]:
print "!! FATAL ERROR, fix this first."
sys.exit(1)
print "Total incoming tx:\t%d" % len(incoming)
print "Total outgoing tx:\t%d" % len(outgoing)
print "Total ignored tx:\t%d (Those should be these, that move the funds from one address to another address)" % len(ignored)
for i in ignored:
print " ->",i["hash"]
print "Total fucked up tx:\t%d (Those are these sending less than 0.01 BTC to the burn address)" % len(failures)
for i in failures:
print " ->",i["hash"]
print ""
print "Looking for suspicious activity (missing TX in genesis, too many TX in genesis, ...)"
def parse_real_tx(file_name):
global all_inputs_plausible
with open(file_name) as data_file:
data = json.load(data_file)
if "txs" not in data:
return
we_want_this_many = int(data["n_tx"])
data = data["txs"]
print "%s TX history has %d entries, should have %d" % (file_name,len(data), we_want_this_many)
print data[0]
print "Parsing JSON file"
import json
from pprint import pprint
abnormal = []
hashes_missing_in_history = []
btc_not_counted_in_genesis = 0.0
hashes_missing_in_genesis_block = []
loaded_hashes = []
btc_normal = 0
with open(file_name) as data_file:
data = json.load(data_file)
print "Genesis Block has %d entries" % len(data)
for x in data:
amount = float(x["mir_amount"])
if amount <= 0:
continue
loaded_hashes.append(x["btc_tx"])
pubkey = x["owner_pubkey"]
if pubkey[0:2]=="02" or pubkey[0:2]=="03" or pubkey[0:2]=="04" and ' ' not in pubkey:
# print "Pubkey [%s...] burned for [%.6f] XEL" % (pubkey[0:12], amount)
btc_normal += float(x["btc_amount"])
else:
abnormal.append(x)
missing_addresses = {}
missing_amounts_per_address = {}
for x in incoming:
if x["hash"] not in loaded_hashes:
hashes_missing_in_genesis_block.append(x["hash"])
total_missing = 0.0
for l in x["out"]:
if "addr" in l and l["addr"] in addresses:
total_missing += float(l["value"])
missing_addresses[x["hash"]] = x["inputs"][0]["prev_out"]["addr"]
if x["inputs"][0]["prev_out"]["addr"] not in missing_amounts_per_address:
missing_amounts_per_address[x["inputs"][0]["prev_out"]["addr"]] = 0
missing_amounts_per_address[x["inputs"][0]["prev_out"]["addr"]] += total_missing/100000000.0
btc_not_counted_in_genesis += total_missing/100000000.0
for x in loaded_hashes:
is_gone = True
for ja in incoming:
if ja["hash"]==x:
is_gone = False
if is_gone:
hashes_missing_in_history.append(x["hash"])
print "Found %d suspicious tx" % (len(hashes_missing_in_genesis_block)+len(hashes_missing_in_history))
print "Hashes in blockchain but not in genesis block:"
for x in hashes_missing_in_genesis_block:
print " ->",x,"[" + missing_addresses[x] + "] =",missing_amounts_per_address[missing_addresses[x]],"BTC in total (dont count addrs twice)"
print " =","total missing:",btc_not_counted_in_genesis,"BTC"
print "Hashes in genesis block but never seen on blockchain:"
for x in hashes_missing_in_history:
print " ->",x
print "Trying to explain discrepancies ..."
print "Step 1: Looking for refunds"
explained = []
for x in missing_amounts_per_address:
found = False
outputs = {}
total = 0.0
for ou in outgoing:
for xx in ou["out"]:
if xx["addr"] == x:
found = True
outputs[ou["hash"]] = float(xx["value"])/100000000.0
total += float(xx["value"])/100000000.0
if len(outputs)==0:
continue
print "Explained missing %.6f BTC from %s, we saw refunds as high as %.6f BTC" % (missing_amounts_per_address[x],x,total)
explained.append(x)
for xy in outputs:
print " ->",xy,"refunded",outputs[xy],"BTC"
print "\nREBUILDING THE LIST OF MISSING ENTRIES IN GENESIS BLOCK!!\n"
tokill=[]
for k in hashes_missing_in_genesis_block:
if missing_addresses[k] in explained:
tokill.append(k)
for pao in tokill:
hashes_missing_in_genesis_block.remove(pao)
print "Found %d suspicious tx" % (len(hashes_missing_in_genesis_block)+len(hashes_missing_in_history))
print "Hashes in blockchain but not in genesis block **AND NOT EXPLAINED SO FAR**:"
for x in hashes_missing_in_genesis_block:
print " ->",x,"[" + missing_addresses[x] + "] =",missing_amounts_per_address[missing_addresses[x]],"BTC in total (dont count addrs twice)"
sys.exit(5)
print "Now, Handing the Abnormal ..."
# Now handling the abnormals
btc_abnormal = 0
for x in abnormal:
btc_abnormal += float(x["btc_amount"])
print ""
print "STATISTICS"
print "=========="
print "In total, %.6f BTC came from abnormal transactions" % btc_abnormal
print " -> %d are save 1-of-many multisig transactions" % 0
print " -> %d are regular multisig transactions" % 0
print " -> %d are cosigned by some creepy wallet" % 0
print "In total, %.6f BTC came from normal transactions" % btc_normal