Skip to content

Commit 9be7fe4

Browse files
committed
Merge #21560: net: Add Tor v3 hardcoded seeds
b2ee8b2 net: Deserialize hardcoded seeds from BIP155 blob (W. J. van der Laan) 9b29d5d contrib: Add explicit port numbers for testnet seeds (W. J. van der Laan) 2a257de contrib: Add a few TorV3 seed nodes (W. J. van der Laan) 06030f7 contrib: generate-seeds.py generates output in BIP155 format (W. J. van der Laan) Pull request description: Closes #20239 and mitigates my node's problem in #21351. - Add a few hardcoded seeds for TorV3 - As the [bitcoin-seeder](https://github.com/sipa/bitcoin-seeder) doesn't collect TorV3 addresses yet, I have extracted these from my own node using [a script](https://gist.github.com/laanwj/b3d7b01ef61ce07c2eff0a72a6b90183) and added them manually. This is intended to be a temporary stop gap until 22.0's seeds update. - Change hardcoded seeds to variable length BIP155 binary format. - It is stored as a single serialized blob in a byte array, instead of pseudo-IPv6 address slots. This is more flexible and, assuming most of the list is IPv4, more compact. - Only the (networkID, addr, port) subset (CService). Services and time are construed on the fly as before. - Change input format for `nodes_*.txt`. - Drop legacy `0xAABBCCDD` format for IPv4. It is never generated by `makeseeds.py`. - Stop interpreting lack of port as default port, interpret it as 'no port', to accomodate I2P and other port-less protocols (not handled in this PR). An explicit port is always generated by `makeseeds.py` so in practice this makes no difference right now. A follow-up to this PR could do the same for I2P. ACKs for top commit: jonatack: ACK b2ee8b2 Tree-SHA512: 11a6b54f9fb0192560f2bd7b218f798f86c1abe01d1bf37f734cb88b91848124beb2de801ca4e6f856e9946aea5dc3ee16b0dbb9863799e42eec1b239d40d59d
2 parents 1a7dec7 + b2ee8b2 commit 9be7fe4

File tree

7 files changed

+1306
-1240
lines changed

7 files changed

+1306
-1240
lines changed

contrib/seeds/generate-seeds.py

Lines changed: 62 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/env python3
2-
# Copyright (c) 2014-2017 Wladimir J. van der Laan
2+
# Copyright (c) 2014-2021 The Bitcoin Core developers
33
# Distributed under the MIT software license, see the accompanying
44
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
55
'''
@@ -13,44 +13,47 @@
1313
1414
These files must consist of lines in the format
1515
16-
<ip>
1716
<ip>:<port>
18-
[<ipv6>]
1917
[<ipv6>]:<port>
20-
<onion>.onion
21-
0xDDBBCCAA (IPv4 little-endian old pnSeeds format)
18+
<onion>.onion:<port>
2219
2320
The output will be two data structures with the peers in binary format:
2421
25-
static SeedSpec6 pnSeed6_main[]={
26-
...
27-
}
28-
static SeedSpec6 pnSeed6_test[]={
22+
static const uint8_t chainparams_seed_{main,test}[]={
2923
...
3024
}
3125
3226
These should be pasted into `src/chainparamsseeds.h`.
3327
'''
3428

3529
from base64 import b32decode
36-
from binascii import a2b_hex
30+
from enum import Enum
31+
import struct
3732
import sys
3833
import os
3934
import re
4035

41-
# ipv4 in ipv6 prefix
42-
pchIPv4 = bytearray([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff])
43-
# tor-specific ipv6 prefix
44-
pchOnionCat = bytearray([0xFD,0x87,0xD8,0x7E,0xEB,0x43])
45-
46-
def name_to_ipv6(addr):
47-
if len(addr)>6 and addr.endswith('.onion'):
36+
class BIP155Network(Enum):
37+
IPV4 = 1
38+
IPV6 = 2
39+
TORV2 = 3
40+
TORV3 = 4
41+
I2P = 5
42+
CJDNS = 6
43+
44+
def name_to_bip155(addr):
45+
'''Convert address string to BIP155 (networkID, addr) tuple.'''
46+
if addr.endswith('.onion'):
4847
vchAddr = b32decode(addr[0:-6], True)
49-
if len(vchAddr) != 16-len(pchOnionCat):
48+
if len(vchAddr) == 10:
49+
return (BIP155Network.TORV2, vchAddr)
50+
elif len(vchAddr) == 35:
51+
assert(vchAddr[34] == 3)
52+
return (BIP155Network.TORV3, vchAddr[:32])
53+
else:
5054
raise ValueError('Invalid onion %s' % vchAddr)
51-
return pchOnionCat + vchAddr
5255
elif '.' in addr: # IPv4
53-
return pchIPv4 + bytearray((int(x) for x in addr.split('.')))
56+
return (BIP155Network.IPV4, bytes((int(x) for x in addr.split('.'))))
5457
elif ':' in addr: # IPv6
5558
sub = [[], []] # prefix, suffix
5659
x = 0
@@ -67,13 +70,12 @@ def name_to_ipv6(addr):
6770
sub[x].append(val & 0xff)
6871
nullbytes = 16 - len(sub[0]) - len(sub[1])
6972
assert((x == 0 and nullbytes == 0) or (x == 1 and nullbytes > 0))
70-
return bytearray(sub[0] + ([0] * nullbytes) + sub[1])
71-
elif addr.startswith('0x'): # IPv4-in-little-endian
72-
return pchIPv4 + bytearray(reversed(a2b_hex(addr[2:])))
73+
return (BIP155Network.IPV6, bytes(sub[0] + ([0] * nullbytes) + sub[1]))
7374
else:
7475
raise ValueError('Could not parse address %s' % addr)
7576

76-
def parse_spec(s, defaultport):
77+
def parse_spec(s):
78+
'''Convert endpoint string to BIP155 (networkID, addr, port) tuple.'''
7779
match = re.match(r'\[([0-9a-fA-F:]+)\](?::([0-9]+))?$', s)
7880
if match: # ipv6
7981
host = match.group(1)
@@ -85,32 +87,52 @@ def parse_spec(s, defaultport):
8587
(host,_,port) = s.partition(':')
8688

8789
if not port:
88-
port = defaultport
90+
port = 0
8991
else:
9092
port = int(port)
9193

92-
host = name_to_ipv6(host)
94+
host = name_to_bip155(host)
9395

94-
return (host,port)
96+
return host + (port, )
9597

96-
def process_nodes(g, f, structname, defaultport):
97-
g.write('static SeedSpec6 %s[] = {\n' % structname)
98-
first = True
98+
def ser_compact_size(l):
99+
r = b""
100+
if l < 253:
101+
r = struct.pack("B", l)
102+
elif l < 0x10000:
103+
r = struct.pack("<BH", 253, l)
104+
elif l < 0x100000000:
105+
r = struct.pack("<BI", 254, l)
106+
else:
107+
r = struct.pack("<BQ", 255, l)
108+
return r
109+
110+
def bip155_serialize(spec):
111+
'''
112+
Serialize (networkID, addr, port) tuple to BIP155 binary format.
113+
'''
114+
r = b""
115+
r += struct.pack('B', spec[0].value)
116+
r += ser_compact_size(len(spec[1]))
117+
r += spec[1]
118+
r += struct.pack('>H', spec[2])
119+
return r
120+
121+
def process_nodes(g, f, structname):
122+
g.write('static const uint8_t %s[] = {\n' % structname)
99123
for line in f:
100124
comment = line.find('#')
101125
if comment != -1:
102126
line = line[0:comment]
103127
line = line.strip()
104128
if not line:
105129
continue
106-
if not first:
107-
g.write(',\n')
108-
first = False
109130

110-
(host,port) = parse_spec(line, defaultport)
111-
hoststr = ','.join(('0x%02x' % b) for b in host)
112-
g.write(' {{%s}, %i}' % (hoststr, port))
113-
g.write('\n};\n')
131+
spec = parse_spec(line)
132+
blob = bip155_serialize(spec)
133+
hoststr = ','.join(('0x%02x' % b) for b in blob)
134+
g.write(f' {hoststr},\n')
135+
g.write('};\n')
114136

115137
def main():
116138
if len(sys.argv)<2:
@@ -124,14 +146,13 @@ def main():
124146
g.write(' * List of fixed seed nodes for the bitcoin network\n')
125147
g.write(' * AUTOGENERATED by contrib/seeds/generate-seeds.py\n')
126148
g.write(' *\n')
127-
g.write(' * Each line contains a 16-byte IPv6 address and a port.\n')
128-
g.write(' * IPv4 as well as onion addresses are wrapped inside an IPv6 address accordingly.\n')
149+
g.write(' * Each line contains a BIP155 serialized (networkID, addr, port) tuple.\n')
129150
g.write(' */\n')
130151
with open(os.path.join(indir,'nodes_main.txt'), 'r', encoding="utf8") as f:
131-
process_nodes(g, f, 'pnSeed6_main', 8333)
152+
process_nodes(g, f, 'chainparams_seed_main')
132153
g.write('\n')
133154
with open(os.path.join(indir,'nodes_test.txt'), 'r', encoding="utf8") as f:
134-
process_nodes(g, f, 'pnSeed6_test', 18333)
155+
process_nodes(g, f, 'chainparams_seed_test')
135156
g.write('#endif // BITCOIN_CHAINPARAMSSEEDS_H\n')
136157

137158
if __name__ == '__main__':

contrib/seeds/nodes_main.txt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,3 +1162,29 @@ zuytrfevzjcpizli.onion:8333
11621162
zvq6dpt3i2ofdp3g.onion:8333
11631163
zwwm6ga7u2hqe2sd.onion:8333
11641164
zyqb4lenfspntj5m.onion:8333
1165+
1166+
# manually added 2021-03 for minimal torv3 bootstrap support
1167+
2g5qfdkn2vvcbqhzcyvyiitg4ceukybxklraxjnu7atlhd22gdwywaid.onion:8333
1168+
2jmtxvyup3ijr7u6uvu7ijtnojx4g5wodvaedivbv74w4vzntxbrhvad.onion:8333
1169+
37m62wn7dz3uqpathpc4qfmgrbupachj52nt3jbtbjugpbu54kbud7yd.onion:8333
1170+
5g72ppm3krkorsfopcm2bi7wlv4ohhs4u4mlseymasn7g7zhdcyjpfid.onion:8333
1171+
7cgwjuwi5ehvcay4tazy7ya6463bndjk6xzrttw5t3xbpq4p22q6fyid.onion:8333
1172+
7pyrpvqdhmayxggpcyqn5l3m5vqkw3qubnmgwlpya2mdo6x7pih7r7id.onion:8333
1173+
b64xcbleqmwgq2u46bh4hegnlrzzvxntyzbmucn3zt7cssm7y4ubv3id.onion:8333
1174+
ejxefzf5fpst4mg2rib7grksvscl7p6fvjp6agzgfc2yglxnjtxc3aid.onion:8333
1175+
fjdyxicpm4o42xmedlwl3uvk5gmqdfs5j37wir52327vncjzvtpfv7yd.onion:8333
1176+
fpz6r5ppsakkwypjcglz6gcnwt7ytfhxskkfhzu62tnylcknh3eq6pad.onion:8333
1177+
fzhn4uoxfbfss7h7d6ffbn266ca432ekbbzvqtsdd55ylgxn4jucm5qd.onion:8333
1178+
gxo5anvfnffnftfy5frkgvplq3rpga2ie3tcblo2vl754fvnhgorn5yd.onion:8333
1179+
ifdu5qvbofrt4ekui2iyb3kbcyzcsglazhx2hn4wfskkrx2v24qxriid.onion:8333
1180+
itz3oxsihs62muvknc237xabl5f6w6rfznfhbpayrslv2j2ubels47yd.onion:8333
1181+
lrjh6fywjqttmlifuemq3puhvmshxzzyhoqx7uoufali57eypuenzzid.onion:8333
1182+
m7cbpjolo662uel7rpaid46as2otcj44vvwg3gccodnvaeuwbm3anbyd.onion:8333
1183+
opnyfyeiibe5qo5a3wbxzbb4xdiagc32bbce46owmertdknta5mi7uyd.onion:8333
1184+
owjsdxmzla6d7lrwkbmetywqym5cyswpihciesfl5qdv2vrmwsgy4uqd.onion:8333
1185+
q7kgmd7n7h27ds4fg7wocgniuqb3oe2zxp4nfe4skd5da6wyipibqzqd.onion:8333
1186+
rp7k2go3s5lyj3fnj6zn62ktarlrsft2ohlsxkyd7v3e3idqyptvread.onion:8333
1187+
sys54sv4xv3hn3sdiv3oadmzqpgyhd4u4xphv4xqk64ckvaxzm57a7yd.onion:8333
1188+
tddeij4qigtjr6jfnrmq6btnirmq5msgwcsdpcdjr7atftm7cxlqztid.onion:8333
1189+
vi5bnbxkleeqi6hfccjochnn65lcxlfqs4uwgmhudph554zibiusqnad.onion:8333
1190+
xqt25cobm5zqucac3634zfght72he6u3eagfyej5ellbhcdgos7t2had.onion:8333

contrib/seeds/nodes_test.txt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# List of fixed seed nodes for testnet
22

33
# Onion nodes
4-
thfsmmn2jbitcoin.onion
5-
it2pj4f7657g3rhi.onion
6-
nkf5e6b7pl4jfd4a.onion
7-
4zhkir2ofl7orfom.onion
8-
t6xj6wilh4ytvcs7.onion
9-
i6y6ivorwakd7nw3.onion
10-
ubqj4rsu3nqtxmtp.onion
4+
thfsmmn2jbitcoin.onion:18333
5+
it2pj4f7657g3rhi.onion:18333
6+
nkf5e6b7pl4jfd4a.onion:18333
7+
4zhkir2ofl7orfom.onion:18333
8+
t6xj6wilh4ytvcs7.onion:18333
9+
i6y6ivorwakd7nw3.onion:18333
10+
ubqj4rsu3nqtxmtp.onion:18333
1111

src/chainparams.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ class CMainParams : public CChainParams {
134134

135135
bech32_hrp = "bc";
136136

137-
vFixedSeeds = std::vector<SeedSpec6>(std::begin(pnSeed6_main), std::end(pnSeed6_main));
137+
vFixedSeeds = std::vector<uint8_t>(std::begin(chainparams_seed_main), std::end(chainparams_seed_main));
138138

139139
fDefaultConsistencyChecks = false;
140140
fRequireStandard = true;
@@ -239,7 +239,7 @@ class CTestNetParams : public CChainParams {
239239

240240
bech32_hrp = "tb";
241241

242-
vFixedSeeds = std::vector<SeedSpec6>(std::begin(pnSeed6_test), std::end(pnSeed6_test));
242+
vFixedSeeds = std::vector<uint8_t>(std::begin(chainparams_seed_test), std::end(chainparams_seed_test));
243243

244244
fDefaultConsistencyChecks = false;
245245
fRequireStandard = false;

src/chainparams.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,6 @@
1414
#include <memory>
1515
#include <vector>
1616

17-
struct SeedSpec6 {
18-
uint8_t addr[16];
19-
uint16_t port;
20-
};
21-
2217
typedef std::map<int, uint256> MapCheckpoints;
2318

2419
struct CCheckpointData {
@@ -105,7 +100,7 @@ class CChainParams
105100
const std::vector<std::string>& DNSSeeds() const { return vSeeds; }
106101
const std::vector<unsigned char>& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; }
107102
const std::string& Bech32HRP() const { return bech32_hrp; }
108-
const std::vector<SeedSpec6>& FixedSeeds() const { return vFixedSeeds; }
103+
const std::vector<uint8_t>& FixedSeeds() const { return vFixedSeeds; }
109104
const CCheckpointData& Checkpoints() const { return checkpointData; }
110105

111106
//! Get allowed assumeutxo configuration.
@@ -127,7 +122,7 @@ class CChainParams
127122
std::string bech32_hrp;
128123
std::string strNetworkID;
129124
CBlock genesis;
130-
std::vector<SeedSpec6> vFixedSeeds;
125+
std::vector<uint8_t> vFixedSeeds;
131126
bool fDefaultConsistencyChecks;
132127
bool fRequireStandard;
133128
bool m_is_test_chain;

0 commit comments

Comments
 (0)