-
Notifications
You must be signed in to change notification settings - Fork 0
/
leader_schedule.py
89 lines (71 loc) · 2.45 KB
/
leader_schedule.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
"""
This script helps measure decentralization in Solana
This script creates the file data/solana_leaders.csv
The output has the following three columns:
leader - The address of the leader
epoch - The epoch number
num_slots - The number of slots assigned to that leader in that epoch
"""
from solana.rpc.api import Client
import time
import os
import pandas as pd
import csv
from tqdm import tqdm
url = "https://api.mainnet-beta.solana.com";
web3 = Client(url)
outfile = "data/solana_leaders.csv"
slots_per_epoch = web3.get_epoch_schedule().value.slots_per_epoch #Should be 432,000
latest_epoch = web3.get_epoch_info().value.epoch
max_wait = 32 #Longest time to wait on RPC before giving up
columns = ['leader','epoch','num_slots'] #Columns to write to CSV
known_epochs = set()
if not os.path.exists( outfile ):
with open( outfile, 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow( columns )
else:
try:
df = pd.read_csv( outfile )
known_epochs = set( df.epoch.unique() )
del df
except Exception as e:
print( e )
current_wait = base_wait = 2
epochs = list( set( range( latest_epoch + 1 ) ).difference(known_epochs) )
epochs.sort( reverse=True )
progress = tqdm(epochs)
for epoch in progress:
progress.set_description( f'Processing {epoch}' )
try:
schedule = web3.get_leader_schedule(epoch*slots_per_epoch).value
except Exception as e:
print( f'Error!' )
print( e )
if current_wait > max_wait:
progress.set_description( f"Error: Skipping epoch {epoch}" )
current_wait = base_wait
epoch -= 1
else:
progress.set_description( f"Retrying epoch {epoch} in {current_wait}" )
time.sleep(current_wait)
current_wait *= 2
continue
if schedule is None:
if current_wait > max_wait:
progress.set_description( f"Skipping epoch {epoch}" )
current_wait = base_wait
epoch -= 1
else:
progress.set_description( f"Retrying epoch {epoch} in {current_wait}" )
time.sleep(current_wait)
current_wait *= 2
continue
for leader, slots in schedule.items():
row = [ leader, epoch, len(slots) ]
with open( outfile, 'a', newline='') as f:
writer = csv.writer(f)
writer.writerow( row )
current_wait = base_wait
epoch -= 1
time.sleep(1)