In [183]:
# Load all analyzers
import graph_analyzer
tickers = ['ANC', 'DGC', 'FTC', 'GLD', 'LKY', 'MNC', 'NMC', 'NVC', 'PPC', 'LTC', 'DRK', 'MEC']
analyzers = map(graph_analyzer.GraphAnalyzer, tickers)
In [529]:
nmc_analyzer = graph_analyzer.GraphAnalyzer('NMC')
In [530]:
# Let's just print out the five richest clusters at present
richest_clusters = nmc_analyzer.richest_n_clusters(5)
for (cluster_id, balance) in richest_clusters:
print 'Cluster %d: %d %s' % (cluster_id, balance, nmc_analyzer.ticker.upper())
In [531]:
# Now let's compute the ratio between adjacent balances
for i in range(len(richest_clusters) - 1):
(cluster_id1, balance1) = richest_clusters[i]
(cluster_id2, balance2) = richest_clusters[i + 1]
ratio = balance1 / float(balance2)
print 'Balance(Cluster %d)/Balance(Cluster %d): %f' % (cluster_id1, cluster_id2, ratio)
The richest cluster for Namecoin isthree times richer than the second richest, and over 11 times richer than the third richest.
In [34]:
# Now let's look at his mining activity. First, load all the miner IDs.
import mining
nmc_mining_analyzer = mining.MiningAnalyzer(nmc_analyzer)
pct_mined = nmc_mining_analyzer.pct_blocks_by_cluster(cluster_id)
print 'Cluster %d mined %.2f%% of blocks' % (cluster_id, pct_mined)
In [47]:
# Compute total wealth in separate cell
tx_ids = [1, 10, 100, 1000, 5000, 10000, 50000, 100000, 200000, 400000, 800000, 1600000]
total_wealth= [nmc_analyzer.balance_for_blockchain(tx_id=tx_id) for tx_id in tx_ids]
# Get 10,000 richest individuals -- this should always be enough
richest_clusters = [nmc_analyzer.richest_n_clusters(10000, tx_id=tx_id) for tx_id in tx_ids]
In [51]:
def num_entities_required(pct_wealth, tx_id):
idx = tx_ids.index(tx_id)
cutoff = pct_wealth * total_wealth[idx]
total = 0
for i, (_, balance) in enumerate(richest_clusters[idx]):
total += balance
if total >= cutoff:
return (i + 1)
In [58]:
pcts = [0.25, 0.50, 0.75, 0.90, 0.99]
data = [map(lambda tx_id: num_entities_required(pct, tx_id), tx_ids) for pct in pcts]
for i, series in enumerate(data):
plt.figure(i)
plt.title('# Entities to Hold %.2f%% of Coins' % pcts[i])
plt.ylabel('# Entities Required')
plt.xlabel('# Transactions')
plt.plot(tx_ids, series)
Now, what percentage of the wealth is controlled by the richest $n$ individuals?
In [65]:
def pct_held_by_top_n(n, tx_id):
idx = tx_ids.index(tx_id)
total = sum([balance for (_, balance) in richest_clusters[idx][:n]])
return 100.0 * total / total_wealth[idx]
In [66]:
ns = [1, 5, 10, 100, 1000]
data = [map(lambda tx_id: pct_held_by_top_n(n, tx_id), tx_ids) for n in ns]
for i, series in enumerate(data):
plt.figure(i)
plt.title('%% of Coins Held by Top %d Entities' % ns[i])
plt.ylabel('% of Coins')
plt.xlabel('# Transactions')
plt.plot(tx_ids, series)
In [18]:
# How about number of addresses?
largest_clusters = nmc_analyzer.largest_n_clusters(5)
for (cluster_id, size) in largest_clusters:
print 'Cluster %d: %d addresses' % (cluster_id, size)
In [19]:
# Compute the ratio between adjacent sizes
for i in range(len(largest_clusters) - 1):
(cluster_id1, size1) = largest_clusters[i]
(cluster_id2, size2) = largest_clusters[i + 1]
ratio = size1 / float(size2)
print 'Size(Cluster %d)/Size(Cluster %d): %f' % (cluster_id1, cluster_id2, ratio)
The same outlier effect isn't present when you sort by cluster size.
Interesting and points to scams.
In [236]:
mining_analyzers = map(mining.MiningAnalyzer, analyzers)
In [336]:
tx_id = 10000
pct_change = []
for (azr, mining_azr) in zip(analyzers, mining_analyzers):
# How many of the first 10,000 transactions were coin generation?
miner_pubkeys = mining_azr.miner_pubkeys(tx_id=tx_id)
print 'In %s, out of the first %d transactions, %d are coin generation' % (azr.ticker.upper(), tx_id, len(miner_pubkeys))
# Next, group these early miners by cluster
miner_clusters = set(azr.clusters_by_pubkey[pubkey_id] for pubkey_id in miner_pubkeys)
pct = len(miner_pubkeys) / float(len(miner_clusters))
print 'Of the first %d miners, there are %d distinct clusters (%.2f blocks per)' % (len(miner_pubkeys), len(miner_clusters), pct)
# Next, compute the balances of these clusters
total = sum(azr.balance_for_cluster(cluster_id, tx_id=tx_id) for cluster_id in miner_clusters)
total_rank = None
total_now = sum(azr.balance_for_cluster(cluster_id) for cluster_id in miner_clusters)
total_now_rank = None
for (i, (cluster_id, balance)) in enumerate(azr.richest_n_clusters(1000)):
if balance < total and total_rank == None:
total_rank = i + 1
if balance < total_now and total_now_rank == None:
total_now_rank = i + 1
if total_rank != None and total_now_rank != None:
break
print 'At the time, they held %d %s' % (total, azr.ticker.upper())
print 'Today, this would put them, as a group, %d on the %s richlist' % (total_rank, azr.ticker.upper())
print 'Today, they hold %d %s' % (total_now, azr.ticker.upper())
print 'This would put them, as a group, %d on the %s richlist' % (total_now_rank, azr.ticker.upper())
pct_change.append(100.0 * (total - total_now) / total)
if total_now > total:
print 'Their wealth has increased by %.8f%%' % (100.0 * (total_now - total) / total)
else:
print 'Their wealth has dropped by %.8f%%' % (100.0 * (total - total_now) / total)
print ''
In [ ]:
# Plot the number of miners over time
tx_ids = [10, 100, 500, 1000, 5000, 10000, 25000, 50000, 75000, 100000, 200000, 300000, 400000]
def mining_stats(azr, mining_azr, tx_id):
miner_keys = mining_azr.miner_pubkeys(tx_id=tx_id)
num_blocks = len(miner_keys)
distinct_miners = set(mining_azr.miner_pubkeys(tx_id=tx_id))
distinct_entities = set(azr.clusters_by_pubkey[pk] for pk in distinct_miners)
wealth_held = sum([azr.balance_for_cluster(cluster_id, tx_id=tx_id) for cluster_id in distinct_entities])
total_wealth = azr.balance_for_blockchain(tx_id=tx_id)
pct_held = wealth_held / float(total_wealth)
return (num_blocks, len(distinct_miners), len(distinct_entities), pct_held)
data = []
for (azr, mining_azr) in zip(analyzers, mining_analyzers):
tx_ids_adjusted = tx_ids + [azr.now_tx_id]
series = map(lambda tx_id: mining_stats(azr, mining_azr, tx_id), tx_ids_adjusted)
data.append(series)
In [282]:
for i, series in enumerate(data):
azr = analyzers[i]
mining_azr = mining_analyzers[i]
xs = map(lambda tx_id: min(tx_id, azr.now_tx_id), tx_ids + [azr.now_tx_id])
xs = map(lambda tx_id: len(mining_azr.miner_pubkeys(tx_id=tx_id)), xs)
ys = zip(*series)[2]
plt.figure(i)
plt.title('%s: # Distinct Miners Over Time' % azr.ticker.upper())
plt.ylabel('# Distinct Miners')
plt.xlabel('Block #')
plt.plot(xs, ys)
ys = zip(*series)[3]
plt.figure(len(data) + i)
plt.title('%s: Pct. Coins Held by Miners Over Time' % azr.ticker.upper())
plt.ylabel('Pct. of Coins')
plt.xlabel('Block #')
plt.plot(xs, ys)
In [193]:
def print_addr_stats(analyzer, name, address):
(cluster_id, balance) = balance_for_addr(analyzer, addr)
(rank, num_clusters) = ranking_for_cluster(analyzer, cluster_id)
print '%s owns %d %s' % (name, balance, analyzer.ticker.upper())
print 'Ranks %d out of %d' % (rank, num_clusters)
explorer.namecoin.info
lists address N1KHAL5C1CRzy58NdJwp1tbLze3XrkFxx9
for donations.
Coincidentally, this same address is listed as belonging to 'Khal' on bitcointalk.org.
Khal is the lead developer on the Namecoin project.
In [383]:
from graph_analyzer import GraphAnalyzer
nmc_analyzer = GraphAnalyzer('NMC')
In [533]:
khal_pubkey = 'N1KHAL5C1CRzy58NdJwp1tbLze3XrkFxx9'
khal_pubkey_id = nmc_analyzer.pubkey_for_address(khal_pubkey)
khal_cluster_id = nmc_analyzer.cluster_for_pubkey(khal_pubkey_id)
khal_balance = nmc_analyzer.balance_for_cluster(khal_cluster_id)
print 'Khal\'s balance: %d %s' % (khal_balance, nmc_analyzer.ticker)
In [535]:
# Where does this rank?
richest_clusters = nmc_analyzer.richest_n_clusters(10000)
richest_cluster_id = [cluster_id for (cluster_id, _) in richest_clusters]
khal_idx = richest_cluster_id.index(khal_cluster_id)
num_clusters = len(nmc_analyzer.clusters)
print 'Khal\'s cluster ranks %d on the wealth list (out of %d)' % (khal_idx, num_clusters)
Like Khal, Meeh is the lead developer for Anoncoin. He's also the creator.
On his BitcoinTalk profile, he lists public key AMeehr1AtpyMaZKVLv4Tb1wdRtVfx3wDj3
.
In [536]:
from graph_analyzer import GraphAnalyzer
anc_analyzer = GraphAnalyzer('ANC')
In [537]:
meeh_pubkey = 'AMeehr1AtpyMaZKVLv4Tb1wdRtVfx3wDj3'
meeh_pubkey_id = anc_analyzer.pubkey_for_address(meeh_pubkey)
meeh_cluster_id = anc_analyzer.cluster_for_pubkey(meeh_pubkey_id)
meeh_balance = anc_analyzer.balance_for_cluster(meeh_cluster_id)
print 'Meeh\'s balance: %d %s' % (meeh_balance / discount, anc_analyzer.ticker.upper())
In [538]:
# Where does this rank?
richest_clusters = anc_analyzer.richest_n_clusters(100)
richest_cluster_id = [id for (id, _) in richest_clusters]
meeh_idx = richest_cluster_id.index(meeh_cluster_id)
num_clusters = len(anc_analyzer.clusters)
print 'Meeh\'s cluster ranks %d on the wealth list (out of %d)' % (meeh_idx + 1, num_clusters)
The Novacoin bitcointalk thread lists active mining pools. One such pool, VIRPOOL, lists an address to which users can send donations: 4YMXC27BAfRTqHaWTRNi2aCAT84b83YFsC
.
We can track the addresses linked to this address to check the balance of the pool and its ranking within the network.
In [65]:
from graph_analyzer import GraphAnalyzer
nvc_analyzer = GraphAnalyzer('NVC')
In [98]:
def balance_for_addr(analyzer, addr):
pubkey_id = analyzer.pubkey_for_address(addr)
cluster_id = analyzer.cluster_for_pubkey(pubkey_id)
balance = analyzer.balance_for_cluster(cluster_id)
return (cluster_id, balance)
In [351]:
virpool_pubkey = '4YMXC27BAfRTqHaWTRNi2aCAT84b83YFsC'
(cluster_id, balance) = balance_for_addr(nvc_analyzer, virpool_pubkey)
print 'VIRPOOL (cluster %d) owns %d %s' % (cluster_id, balance, nvc_analyzer.ticker.upper())
In [405]:
def ranking_for_cluster(analyzer, cluster_id):
richest_clusters = analyzer.richest_n_clusters(100000)
richest_cluster_id = [id for (id, _) in richest_clusters]
idx = richest_cluster_id.index(cluster_id)
num_clusters = len(analyzer.clusters)
return (idx + 1, num_clusters)
In [113]:
(rank, num_clusters) = ranking_for_cluster(nvc_analyzer, cluster_id)
print 'VIRPOOL ranks %d on the wealth list (out of %d entities)' % (rank, num_clusters)
The leading Novacoin P2P mining pool, novaco.in
, also lists an address 4ZLoY6T8wXKgrbZM9gL8fQt48NUzGo2yAg
. It seems that this address is part of the same entity as VIRPOOL. This is further evidenced by this transaction, where an address on the left contains Vir
and the address on the right is the novaco.in
address.
In [349]:
novacoin_pubkey = '4ZLoY6T8wXKgrbZM9gL8fQt48NUzGo2yAg'
(cluster_id, balance) = balance_for_addr(nvc_analyzer, novacoin_pubkey)
print 'Novaco.in is in cluster %d' % cluster_id
Based on this thread, someone named svost
(who appears to be a core developer) may have control of this cluster.
In [350]:
svost_pubkey = '4SvostvrMWxU7hYR1aDij22AysKSG4QKeu '
(cluster_id, balance) = balance_for_addr(nvc_analyzer, svost_pubkey)
print 'svost is in cluster %d' % cluster_id
Finally, the creator of Novacoin, Balthazar, lists this address on his bitcointalk profile: 4RgnHWtnJWEyMhqhDdazW3Hdr7cx5ybF6i
.
In [120]:
balthazar_pubkey = '4RgnHWtnJWEyMhqhDdazW3Hdr7cx5ybF6i'
(cluster_id, balance) = balance_for_addr(nvc_analyzer, balthazar_pubkey)
(rank, num_clusters) = ranking_for_cluster(nvc_analyzer, cluster_id)
print 'Balthazar (cluster %d) owns %d %s' % (cluster_id, balance, nvc_analyzer.ticker.upper())
print 'Balthazar ranks %d on the wealth list (out of %d entities)' % (rank, num_clusters)
In [138]:
from graph_analyzer import GraphAnalyzer
ppc_analyzer = GraphAnalyzer('PPC')
Best I could find is Sentinelrv
, a member of the Peercoin team working on community.
In [155]:
sentinelrv_addr = 'PNH9rirzGKi6xAYKrrhAvnRE1pnJEQRPs8'
(rank, num_clusters) = ranking_for_cluster(nvc_analyzer, balance_for_addr(ppc_analyzer, sentinelrv_addr)[0])
print 'Sentinelrv ranks %d on the wealth list (out of %d entities)' % (rank, num_clusters)
In [157]:
from graph_analyzer import GraphAnalyzer
dgc_analyzer = GraphAnalyzer('DGC')
In [159]:
foundation_addr = 'DEhowBduoYuw2pPjQJ81XAPDx18jQbG1nj'
ranking_for_cluster(nvc_analyzer, balance_for_addr(dgc_analyzer, foundation_addr)[0])
Out[159]:
In [169]:
xawksow_addr = 'D8KU86c7sf8L9UPLU3jMLeadgaNsWrYMov'
ranking_for_cluster(nvc_analyzer, balance_for_addr(dgc_analyzer, xawksow_addr)[0])
Out[169]:
In [170]:
from graph_analyzer import GraphAnalyzer
mec_analyzer = GraphAnalyzer('MEC')
In [175]:
ethought_addr = 'MD63SLhdeV9DQfcQpQnP4eisDjVYL2H55G'
ranking_for_cluster(mec_analyzer, balance_for_addr(mec_analyzer, ethought_addr)[0])
Out[175]:
In [177]:
addr = 'MQVWq6pMkbACS7aMEjnYgggFr3Ziqr2mv5'
ranking_for_cluster(mec_analyzer, balance_for_addr(mec_analyzer, addr)[0])
Out[177]:
In [178]:
addr = 'MW11rq3aFtKE3kRACpd2TPmziu6WizPGYU'
ranking_for_cluster(mec_analyzer, balance_for_addr(mec_analyzer, addr)[0])
Out[178]:
In [179]:
addr = 'MGk8Jcf7wss4qUKfEgmeCMwnQjCHsFYQgp'
ranking_for_cluster(mec_analyzer, balance_for_addr(mec_analyzer, addr)[0])
Out[179]:
In [180]:
addr = 'MAK5Kod12QF8FY46LiQa7YUpYkvoC5WLLb'
ranking_for_cluster(mec_analyzer, balance_for_addr(mec_analyzer, addr)[0])
Out[180]:
In [181]:
addr = 'MDnML1znxhbfrSX5nU2GqP5FjbB4Gwpqsj'
ranking_for_cluster(mec_analyzer, balance_for_addr(mec_analyzer, addr)[0])
Out[181]:
According to the forum post, VR4Mines donated 5000 MEC to the developer fund. By looking at a block explorer, we can find the address for VR4Mines: MQNaAeu1LWFmBZLhAtzst3svyztKUBNwdV
.
In [182]:
addr = 'MQNaAeu1LWFmBZLhAtzst3svyztKUBNwdV'
ranking_for_cluster(mec_analyzer, balance_for_addr(mec_analyzer, addr)[0])
Out[182]:
Notice that ethought
and Janek
, big community members, appear to be in the same cluster.
After a lot of manual labor, I was able to trace the path by which they became connected:
In [ ]:
from graph_analyzer import GraphAnalyzer
ltc_analyzer = GraphAnalyzer('LTC')
Charlie Lee, also known as coblee
, is the creator of Litecoin. He claims on Reddit to own a modest amount of Litecoin. We can assess that claim by analyzing the addresses associated with the first few blocks (i.e., those blocks that only Charlie would be able to mine).
In [208]:
coblee_addrs = [
'LeL16MDWU5jS3oeHHwEZRBTDExwPbNgcvy',
'LSdTvMHRm8sScqwCi6x9wzYQae8JeZhx6y',
'LYAj2j9pzSCNPBg9A4dbWUgmMiQDfrrY5N',
'LKiiNMCKiGxfo1M5zqmHZQb5X1j3i69ZHX',
'LadVH7kj2BYB68rVtPfCtjkstkrBPX8mBc'
]
In [539]:
for addr in coblee_addrs:
print_addr_stats(ltc_analyzer, 'Charlie Lee', addr)
Notice that they all link to the same entity, and that the sum is indeed modest.
We can also find other public keys online that let us do additional analysis.
In [406]:
addrs_by_name = [
('Litecoin Core', 'LcUP7ZU3Xpk1BUR3qut3dTjC3aK5JoZMYx'),
('Syari', 'LgRdmdHNRaW2KeUttBfW5NHvaCfj2zSSRg'),
('Ozcoin Donation Link', 'LScBB865pq249wBVF21Y3yr4QVZZ95SRFV'),
('Ozcoin Coinbase', 'LdCE2MxB7sAXvewsRDUmpR1UDxc8jVR7MF'),
('Coinotron', 'LPkxsW2LWmbUj9UMY9W6ocwEzbEkJhpvEc'),
('litecoinpool', 'LTCPooLqTK1SANSNeTR63GbGwabTKEkuS7'),
('Discus Fish', 'LajyQBeZaBA1NkZDeY8YT5RYYVRkXMvb2T'),
('explorer.litecoin.net', 'LYmpJZm1WrP5FSnxwkV2TTo5SkAF4Eha31')
]
for (name, addr) in addrs_by_name:
try:
print_addr_stats(ltc_analyzer, name, addr)
except:
# If it throws here, the address's balance is too low to be of interest
pass
Mincoin started off with 500 MNC block rewards, which is a 250000% increase from the current block reward of 2 MNC. Some have labeled this a Scamcoin, as the early miners were able to take a quick stake in the coinage.
(An actual quote from their bitcointalk release: "With MinCoin only having 10 millions total coins to ever be produced compared to 21 millions for Bitcoin, it is pretty easy to see which one is more rare.")
Specifically, the first 1439 blocks gave a 500 MNC reward (see 1439 vs. 1440). This means that over 7% of the currency was mined in the first 1439 blocks.
In [540]:
# Get correct (azr, mining_azr) pair
for (azr, mining_azr) in zip(analyzers, mining_analyzers):
if azr.ticker.upper() == 'MNC':
break
In [329]:
# Note that block reward on block 1439 maps to transaction with ID 1440
tx_id = 1439
# How many of the first 10,000 transactions were coin generation?
miner_pubkeys = mining_azr.miner_pubkeys(tx_id=tx_id)
print 'In %s, out of the first %d transactions, %d are coin generation' % (azr.ticker.upper(), tx_id, len(miner_pubkeys))
# Next, group these early miners by cluster
miner_clusters = set(azr.clusters_by_pubkey[pubkey_id] for pubkey_id in miner_pubkeys)
pct = len(miner_pubkeys) / float(len(miner_clusters))
print 'Of the first %d miners, there are %d distinct clusters (%.2f blocks per)' % (len(miner_pubkeys), len(miner_clusters), pct)
print ''
# Next, compute the balances of these clusters at tx_id
total = sum(azr.balance_for_cluster(cluster_id, tx_id=tx_id) for cluster_id in miner_clusters)
for (i, (cluster_id, balance)) in enumerate(azr.richest_n_clusters(1000)):
if balance < total:
print 'After the first 1440 transactions, these miners controlled %d %s' % (total, azr.ticker.upper())
print 'Compared to today\'s richest, this would put them, as a group, %d on the %s richlist' % (i + 1, azr.ticker.upper())
print ''
break
# Finally, compare this to the balances of these clusters today
total_now = sum(azr.balance_for_cluster(cluster_id) for cluster_id in miner_clusters)
for (i, (cluster_id, balance)) in enumerate(azr.richest_n_clusters(1000)):
if balance < total_now:
print 'Today, these miners control %d %s' % (total_now, azr.ticker.upper())
print 'This puts them, as a group, %d on the %s richlist' % (i + 1, azr.ticker.upper())
print ''
break
diff = total - total_now
pct = diff / float(total)
print 'These miners have cashed out an estimated %d %s, or %.5f of their original holdings' % (diff, azr.ticker.upper(), pct)
You can get similar (but slightly less extreme) numbers by looking at Goldcoin up to transaction 371. Till then, the block reward was 1000000000000. The miners would, in today's world, have been fourth richest, and had cashed out over 99% of their holdings.
This analysis is useful, but it's possible that coins were simply moved to other addresses held by the same entity (i.e., that our clustering was too conservative to track movement). This alone is not evidence of a "pump and dump".
In [541]:
# People say that Mincoin is a scam because the first 4,319 blocks had huge rewards (500, then 200, then 50, and then 2).
block_idx = 4319
tx_id = mining_azr.tx_ids[block_idx]
pubkeys = mining_azr.miner_pubkeys(tx_id=tx_id)
miners = set(pubkeys)
clusters = set(azr.clusters_by_pubkey[pubkey] for pubkey in miners)
print 'In this early stage, there are %d unique miner public keys, but %d clusters' % (len(miners), len(clusters))
In [544]:
# The address MBodnedZArLoJSZ4ganaNGcccaPFbbk4Ne was found on a forum to be associated with Cryptsy, an exchange
pubkey = azr.pubkey_for_address('MBodnedZArLoJSZ4ganaNGcccaPFbbk4Ne')
cluster_id = azr.clusters_by_pubkey[pubkey]
for i, (cluster, balance) in enumerate(azr.richest_n_clusters(10)):
if cluster == cluster_id:
break
print 'Cryptsy holds %d %s, ranking it %d on the rich list' % (balance, azr.ticker.upper(), i + 1)
In [496]:
# Let's plot its balance over time
xs = [1, 10, 100, 1000, 10000, 20000, 30000, 50000, 75000, 85000, 100000, 150000, 200000, 250000, 300000, 320000, 330000, 340000, 350000, 400000, 450000, 500000, 550000, 600000, 650000, 700000, azr.now_tx_id]
ys = []
for tx_id in xs:
ys.append(azr.balance_for_cluster(3027, tx_id=tx_id))
plt.plot(xs, ys)
Out[496]:
In [549]:
# What causes the spike around transaction 300,000?
# In the blockchain, we find that a huge deposit is made from address MMCSrkbKCDgxZtw7v7cd4uhxtvYPkfNBhF.
pubkey = azr.pubkey_for_address('MMCSrkbKCDgxZtw7v7cd4uhxtvYPkfNBhF')
cluster_id = azr.clusters_by_pubkey[pubkey]
print 'Around the time of the transaction, this pubkey holds %d %s' % (azr.balance_for_cluster(cluster_id, tx_id=320000), azr.ticker.upper())
print 'It maps to cluster %d' % cluster_id
In [550]:
pubkey = azr.pubkey_for_address('MNRRNX3a7U1hFjVK9xhmDCNH1K4F5fLpTa')
cluster_id = azr.clusters_by_pubkey[pubkey]
print 'An address known to SuperTramp also maps to cluster %d' % cluster_id
In [554]:
# Smoking gun: http://mnc.cryptoexplore.com/tx/d74723fbfde248bbc82ad5579a535b7b8f8f8625f9768ba2ef7107b62cef03fe
# Maps to tx_id 308030
tx_id = 308030
supertramp_address = 'MNRRNX3a7U1hFjVK9xhmDCNH1K4F5fLpTa' # from forum
cryptsy_address = 'MBodnedZArLoJSZ4ganaNGcccaPFbbk4Ne' # output of DaveM's forum post
cryptsy_depositor_input_address = 'MMCSrkbKCDgxZtw7v7cd4uhxtvYPkfNBhF' # from tx_id 308030
cryptsy_depositor_output_address = 'MCUVuMmsVXDJAdNt7qJH9hXe82XDc2hyJW' # from tx_id 308030
if azr.clusters_by_pubkey[azr.pubkey_for_address(cryptsy_address)] == azr.clusters_by_pubkey[azr.pubkey_for_address(cryptsy_depositor_output_address)]:
print 'Crypty\'s pubkey (from the forum post) and the output of the large transaction map to the same cluster'
if azr.clusters_by_pubkey[azr.pubkey_for_address(supertramp_address)] == azr.clusters_by_pubkey[azr.pubkey_for_address(cryptsy_depositor_input_address)]:
print 'SuperTramp\'s pubkey and the input to the large transaction map to the same cluster'
print 'Therefore, it appears as if SuperTramp is exchanging over 50,000 MNC on Cryptsy in this transaction'
In [ ]: