Dash Core  0.12.2.1
P2P Digital Currency
generate-seeds.py
Go to the documentation of this file.
1 #!/usr/bin/python
2 # Copyright (c) 2014 Wladimir J. van der Laan
3 # Distributed under the MIT software license, see the accompanying
4 # file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 '''
6 Script to generate list of seed nodes for chainparams.cpp.
7 
8 This script expects two text files in the directory that is passed as an
9 argument:
10 
11  nodes_main.txt
12  nodes_test.txt
13 
14 These files must consist of lines in the format
15 
16  <ip>
17  <ip>:<port>
18  [<ipv6>]
19  [<ipv6>]:<port>
20  <onion>.onion
21  0xDDBBCCAA (IPv4 little-endian old pnSeeds format)
22 
23 The output will be two data structures with the peers in binary format:
24 
25  static SeedSpec6 pnSeed6_main[]={
26  ...
27  }
28  static SeedSpec6 pnSeed6_test[]={
29  ...
30  }
31 
32 These should be pasted into `src/chainparamsseeds.h`.
33 '''
34 from __future__ import print_function, division
35 from base64 import b32decode
36 from binascii import a2b_hex
37 import sys, os
38 import re
39 
40 # ipv4 in ipv6 prefix
41 pchIPv4 = bytearray([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff])
42 # tor-specific ipv6 prefix
43 pchOnionCat = bytearray([0xFD,0x87,0xD8,0x7E,0xEB,0x43])
44 
45 def name_to_ipv6(addr):
46  if len(addr)>6 and addr.endswith('.onion'):
47  vchAddr = b32decode(addr[0:-6], True)
48  if len(vchAddr) != 16-len(pchOnionCat):
49  raise ValueError('Invalid onion %s' % s)
50  return pchOnionCat + vchAddr
51  elif '.' in addr: # IPv4
52  return pchIPv4 + bytearray((int(x) for x in addr.split('.')))
53  elif ':' in addr: # IPv6
54  sub = [[], []] # prefix, suffix
55  x = 0
56  addr = addr.split(':')
57  for i,comp in enumerate(addr):
58  if comp == '':
59  if i == 0 or i == (len(addr)-1): # skip empty component at beginning or end
60  continue
61  x += 1 # :: skips to suffix
62  assert(x < 2)
63  else: # two bytes per component
64  val = int(comp, 16)
65  sub[x].append(val >> 8)
66  sub[x].append(val & 0xff)
67  nullbytes = 16 - len(sub[0]) - len(sub[1])
68  assert((x == 0 and nullbytes == 0) or (x == 1 and nullbytes > 0))
69  return bytearray(sub[0] + ([0] * nullbytes) + sub[1])
70  elif addr.startswith('0x'): # IPv4-in-little-endian
71  return pchIPv4 + bytearray(reversed(a2b_hex(addr[2:])))
72  else:
73  raise ValueError('Could not parse address %s' % addr)
74 
75 def parse_spec(s, defaultport):
76  match = re.match('\[([0-9a-fA-F:]+)\](?::([0-9]+))?$', s)
77  if match: # ipv6
78  host = match.group(1)
79  port = match.group(2)
80  elif s.count(':') > 1: # ipv6, no port
81  host = s
82  port = ''
83  else:
84  (host,_,port) = s.partition(':')
85 
86  if not port:
87  port = defaultport
88  else:
89  port = int(port)
90 
91  host = name_to_ipv6(host)
92 
93  return (host,port)
94 
95 def process_nodes(g, f, structname, defaultport):
96  g.write('static SeedSpec6 %s[] = {\n' % structname)
97  first = True
98  for line in f:
99  comment = line.find('#')
100  if comment != -1:
101  line = line[0:comment]
102  line = line.strip()
103  if not line:
104  continue
105  if not first:
106  g.write(',\n')
107  first = False
108 
109  (host,port) = parse_spec(line, defaultport)
110  hoststr = ','.join(('0x%02x' % b) for b in host)
111  g.write(' {{%s}, %i}' % (hoststr, port))
112  g.write('\n};\n')
113 
114 def main():
115  if len(sys.argv)<2:
116  print(('Usage: %s <path_to_nodes_txt>' % sys.argv[0]), file=sys.stderr)
117  exit(1)
118  g = sys.stdout
119  indir = sys.argv[1]
120  g.write('#ifndef DASH_CHAINPARAMSSEEDS_H\n')
121  g.write('#define DASH_CHAINPARAMSSEEDS_H\n')
122  g.write('/**\n')
123  g.write(' * List of fixed seed nodes for the dash network\n')
124  g.write(' * AUTOGENERATED by contrib/seeds/generate-seeds.py\n')
125  g.write(' *\n')
126  g.write(' * Each line contains a 16-byte IPv6 address and a port.\n')
127  g.write(' * IPv4 as well as onion addresses are wrapped inside a IPv6 address accordingly.\n')
128  g.write(' */\n')
129  with open(os.path.join(indir,'nodes_main.txt'),'r') as f:
130  process_nodes(g, f, 'pnSeed6_main', 9999)
131  g.write('\n')
132  with open(os.path.join(indir,'nodes_test.txt'),'r') as f:
133  process_nodes(g, f, 'pnSeed6_test', 19999)
134  g.write('#endif // DASH_CHAINPARAMSSEEDS_H\n')
135 
136 if __name__ == '__main__':
137  main()
138 
def parse_spec(s, defaultport)
def process_nodes(g, f, structname, defaultport)
def name_to_ipv6(addr)