Initial Vexta Core v0.1.0 release

This commit is contained in:
Capri 2026-07-15 14:07:28 +00:00
commit 25c454329d
2481 changed files with 689289 additions and 0 deletions

1
contrib/seeds/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
seeds_main.txt

27
contrib/seeds/README.md Normal file
View file

@ -0,0 +1,27 @@
# Seeds
Utility to generate the seeds.txt list that is compiled into the client
(see [src/chainparamsseeds.h](/src/chainparamsseeds.h) and other utilities in [contrib/seeds](/contrib/seeds)).
Be sure to update `PATTERN_AGENT` in `makeseeds.py` to include the current version,
and remove old versions as necessary (at a minimum when GetDesirableServiceFlags
changes its default return value, as those are the services which seeds are added
to addrman with).
The seeds compiled into the release are created from sipa's DNS seed data, like this:
curl -s http://digibyte.sipa.be/seeds.txt.gz | gzip -dc > seeds_main.txt
python3 makeseeds.py < seeds_main.txt > nodes_main.txt
python3 generate-seeds.py . > ../../src/chainparamsseeds.h
## Dependencies
Ubuntu, Debian:
sudo apt-get install python3-dnspython
and/or for other operating systems:
pip install dnspython
See https://dnspython.readthedocs.io/en/latest/installation.html for more information.

171
contrib/seeds/generate-seeds.py Executable file
View file

@ -0,0 +1,171 @@
#!/usr/bin/env python3
# Copyright (c) 2014-2021 The DigiByte Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
'''
Script to generate list of seed nodes for chainparams.cpp.
This script expects two text files in the directory that is passed as an
argument:
nodes_main.txt
nodes_test.txt
These files must consist of lines in the format
<ip>:<port>
[<ipv6>]:<port>
<onion>.onion:<port>
<i2p>.b32.i2p:<port>
The output will be two data structures with the peers in binary format:
static const uint8_t chainparams_seed_{main,test}[]={
...
}
These should be pasted into `src/chainparamsseeds.h`.
'''
from base64 import b32decode
from enum import Enum
import struct
import sys
import os
import re
class BIP155Network(Enum):
IPV4 = 1
IPV6 = 2
TORV2 = 3 # no longer supported
TORV3 = 4
I2P = 5
CJDNS = 6
def name_to_bip155(addr):
'''Convert address string to BIP155 (networkID, addr) tuple.'''
if addr.endswith('.onion'):
vchAddr = b32decode(addr[0:-6], True)
if len(vchAddr) == 35:
assert vchAddr[34] == 3
return (BIP155Network.TORV3, vchAddr[:32])
elif len(vchAddr) == 10:
return (BIP155Network.TORV2, vchAddr)
else:
raise ValueError('Invalid onion %s' % vchAddr)
elif addr.endswith('.b32.i2p'):
vchAddr = b32decode(addr[0:-8] + '====', True)
if len(vchAddr) == 32:
return (BIP155Network.I2P, vchAddr)
else:
raise ValueError(f'Invalid I2P {vchAddr}')
elif '.' in addr: # IPv4
return (BIP155Network.IPV4, bytes((int(x) for x in addr.split('.'))))
elif ':' in addr: # IPv6
sub = [[], []] # prefix, suffix
x = 0
addr = addr.split(':')
for i,comp in enumerate(addr):
if comp == '':
if i == 0 or i == (len(addr)-1): # skip empty component at beginning or end
continue
x += 1 # :: skips to suffix
assert(x < 2)
else: # two bytes per component
val = int(comp, 16)
sub[x].append(val >> 8)
sub[x].append(val & 0xff)
nullbytes = 16 - len(sub[0]) - len(sub[1])
assert((x == 0 and nullbytes == 0) or (x == 1 and nullbytes > 0))
return (BIP155Network.IPV6, bytes(sub[0] + ([0] * nullbytes) + sub[1]))
else:
raise ValueError('Could not parse address %s' % addr)
def parse_spec(s):
'''Convert endpoint string to BIP155 (networkID, addr, port) tuple.'''
match = re.match(r'\[([0-9a-fA-F:]+)\](?::([0-9]+))?$', s)
if match: # ipv6
host = match.group(1)
port = match.group(2)
elif s.count(':') > 1: # ipv6, no port
host = s
port = ''
else:
(host,_,port) = s.partition(':')
if not port:
port = 0
else:
port = int(port)
host = name_to_bip155(host)
if host[0] == BIP155Network.TORV2:
return None # TORV2 is no longer supported, so we ignore it
else:
return host + (port, )
def ser_compact_size(l):
r = b""
if l < 253:
r = struct.pack("B", l)
elif l < 0x10000:
r = struct.pack("<BH", 253, l)
elif l < 0x100000000:
r = struct.pack("<BI", 254, l)
else:
r = struct.pack("<BQ", 255, l)
return r
def bip155_serialize(spec):
'''
Serialize (networkID, addr, port) tuple to BIP155 binary format.
'''
r = b""
r += struct.pack('B', spec[0].value)
r += ser_compact_size(len(spec[1]))
r += spec[1]
r += struct.pack('>H', spec[2])
return r
def process_nodes(g, f, structname):
g.write('static const uint8_t %s[] = {\n' % structname)
for line in f:
comment = line.find('#')
if comment != -1:
line = line[0:comment]
line = line.strip()
if not line:
continue
spec = parse_spec(line)
if spec is None: # ignore this entry (e.g. no longer supported addresses like TORV2)
continue
blob = bip155_serialize(spec)
hoststr = ','.join(('0x%02x' % b) for b in blob)
g.write(f' {hoststr},\n')
g.write('};\n')
def main():
if len(sys.argv)<2:
print(('Usage: %s <path_to_nodes_txt>' % sys.argv[0]), file=sys.stderr)
sys.exit(1)
g = sys.stdout
indir = sys.argv[1]
g.write('#ifndef DIGIBYTE_CHAINPARAMSSEEDS_H\n')
g.write('#define DIGIBYTE_CHAINPARAMSSEEDS_H\n')
g.write('/**\n')
g.write(' * List of fixed seed nodes for the digibyte network\n')
g.write(' * AUTOGENERATED by contrib/seeds/generate-seeds.py\n')
g.write(' *\n')
g.write(' * Each line contains a BIP155 serialized (networkID, addr, port) tuple.\n')
g.write(' */\n')
with open(os.path.join(indir,'nodes_main.txt'), 'r', encoding="utf8") as f:
process_nodes(g, f, 'chainparams_seed_main')
g.write('\n')
with open(os.path.join(indir,'nodes_test.txt'), 'r', encoding="utf8") as f:
process_nodes(g, f, 'chainparams_seed_test')
g.write('#endif // DIGIBYTE_CHAINPARAMSSEEDS_H\n')
if __name__ == '__main__':
main()

229
contrib/seeds/makeseeds.py Executable file
View file

@ -0,0 +1,229 @@
#!/usr/bin/env python3
# Copyright (c) 2013-2018 The Bitcoin Core developers
# Copyright (c) 2013-2020 The DigiByte Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
#
# Generate seeds.txt from Pieter's DNS seeder
#
import re
import sys
import dns.resolver
import collections
NSEEDS=512
MAX_SEEDS_PER_ASN=2
MIN_BLOCKS = 337600
# These are hosts that have been observed to be behaving strangely (e.g.
# aggressively connecting to every node).
with open("suspicious_hosts.txt", mode="r", encoding="utf-8") as f:
SUSPICIOUS_HOSTS = {s.strip() for s in f if s.strip()}
PATTERN_IPV4 = re.compile(r"^((\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})):(\d+)$")
PATTERN_IPV6 = re.compile(r"^\[([0-9a-z:]+)\]:(\d+)$")
PATTERN_ONION = re.compile(r"^([abcdefghijklmnopqrstuvwxyz234567]{16}\.onion):(\d+)$")
PATTERN_AGENT = re.compile(
r"^/Satoshi:("
r"0.14.(0|1|2|3|99)|"
r"0.15.(0|1|2|99)|"
r"0.16.(0|1|2|3|99)|"
r"0.17.(0|0.1|1|2|99)|"
r"0.18.(0|1|99)|"
r"0.19.(0|1|99)|"
r"0.20.(0|1|99)|"
r"0.21.99"
r")")
def parseline(line):
sline = line.split()
if len(sline) < 11:
return None
m = PATTERN_IPV4.match(sline[0])
sortkey = None
ip = None
if m is None:
m = PATTERN_IPV6.match(sline[0])
if m is None:
m = PATTERN_ONION.match(sline[0])
if m is None:
return None
else:
net = 'onion'
ipstr = sortkey = m.group(1)
port = int(m.group(2))
else:
net = 'ipv6'
if m.group(1) in ['::']: # Not interested in localhost
return None
ipstr = m.group(1)
sortkey = ipstr # XXX parse IPv6 into number, could use name_to_ipv6 from generate-seeds
port = int(m.group(2))
else:
# Do IPv4 sanity check
ip = 0
for i in range(0,4):
if int(m.group(i+2)) < 0 or int(m.group(i+2)) > 255:
return None
ip = ip + (int(m.group(i+2)) << (8*(3-i)))
if ip == 0:
return None
net = 'ipv4'
sortkey = ip
ipstr = m.group(1)
port = int(m.group(6))
# Skip bad results.
if sline[1] == 0:
return None
# Extract uptime %.
uptime30 = float(sline[7][:-1])
# Extract Unix timestamp of last success.
lastsuccess = int(sline[2])
# Extract protocol version.
version = int(sline[10])
# Extract user agent.
agent = sline[11][1:-1]
# Extract service flags.
service = int(sline[9], 16)
# Extract blocks.
blocks = int(sline[8])
# Construct result.
return {
'net': net,
'ip': ipstr,
'port': port,
'ipnum': ip,
'uptime': uptime30,
'lastsuccess': lastsuccess,
'version': version,
'agent': agent,
'service': service,
'blocks': blocks,
'sortkey': sortkey,
}
def dedup(ips):
'''deduplicate by address,port'''
d = {}
for ip in ips:
d[ip['ip'],ip['port']] = ip
return list(d.values())
def filtermultiport(ips):
'''Filter out hosts with more nodes per IP'''
hist = collections.defaultdict(list)
for ip in ips:
hist[ip['sortkey']].append(ip)
return [value[0] for (key,value) in list(hist.items()) if len(value)==1]
def lookup_asn(net, ip):
'''
Look up the asn for an IP (4 or 6) address by querying cymru.com, or None
if it could not be found.
'''
try:
if net == 'ipv4':
ipaddr = ip
prefix = '.origin'
else: # http://www.team-cymru.com/IP-ASN-mapping.html
res = str() # 2001:4860:b002:23::68
for nb in ip.split(':')[:4]: # pick the first 4 nibbles
for c in nb.zfill(4): # right padded with '0'
res += c + '.' # 2001 4860 b002 0023
ipaddr = res.rstrip('.') # 2.0.0.1.4.8.6.0.b.0.0.2.0.0.2.3
prefix = '.origin6'
asn = int([x.to_text() for x in dns.resolver.resolve('.'.join(
reversed(ipaddr.split('.'))) + prefix + '.asn.cymru.com',
'TXT').response.answer][0].split('\"')[1].split(' ')[0])
return asn
except Exception:
sys.stderr.write('ERR: Could not resolve ASN for "' + ip + '"\n')
return None
# Based on Greg Maxwell's seed_filter.py
def filterbyasn(ips, max_per_asn, max_per_net):
# Sift out ips by type
ips_ipv46 = [ip for ip in ips if ip['net'] in ['ipv4', 'ipv6']]
ips_onion = [ip for ip in ips if ip['net'] == 'onion']
# Filter IPv46 by ASN, and limit to max_per_net per network
result = []
net_count = collections.defaultdict(int)
asn_count = collections.defaultdict(int)
for ip in ips_ipv46:
if net_count[ip['net']] == max_per_net:
continue
asn = lookup_asn(ip['net'], ip['ip'])
if asn is None or asn_count[asn] == max_per_asn:
continue
asn_count[asn] += 1
net_count[ip['net']] += 1
result.append(ip)
# Add back Onions (up to max_per_net)
result.extend(ips_onion[0:max_per_net])
return result
def ip_stats(ips):
hist = collections.defaultdict(int)
for ip in ips:
if ip is not None:
hist[ip['net']] += 1
return '%6d %6d %6d' % (hist['ipv4'], hist['ipv6'], hist['onion'])
def main():
lines = sys.stdin.readlines()
ips = [parseline(line) for line in lines]
print('\x1b[7m IPv4 IPv6 Onion Pass \x1b[0m', file=sys.stderr)
print('%s Initial' % (ip_stats(ips)), file=sys.stderr)
# Skip entries with invalid address.
ips = [ip for ip in ips if ip is not None]
print('%s Skip entries with invalid address' % (ip_stats(ips)), file=sys.stderr)
# Skip duplicates (in case multiple seeds files were concatenated)
ips = dedup(ips)
print('%s After removing duplicates' % (ip_stats(ips)), file=sys.stderr)
# Skip entries from suspicious hosts.
ips = [ip for ip in ips if ip['ip'] not in SUSPICIOUS_HOSTS]
print('%s Skip entries from suspicious hosts' % (ip_stats(ips)), file=sys.stderr)
# Enforce minimal number of blocks.
ips = [ip for ip in ips if ip['blocks'] >= MIN_BLOCKS]
print('%s Enforce minimal number of blocks' % (ip_stats(ips)), file=sys.stderr)
# Require service bit 1.
ips = [ip for ip in ips if (ip['service'] & 1) == 1]
print('%s Require service bit 1' % (ip_stats(ips)), file=sys.stderr)
# Require at least 50% 30-day uptime for clearnet, 10% for onion.
req_uptime = {
'ipv4': 50,
'ipv6': 50,
'onion': 10,
}
ips = [ip for ip in ips if ip['uptime'] > req_uptime[ip['net']]]
print('%s Require minimum uptime' % (ip_stats(ips)), file=sys.stderr)
# Require a known and recent user agent.
ips = [ip for ip in ips if PATTERN_AGENT.match(ip['agent'])]
print('%s Require a known and recent user agent' % (ip_stats(ips)), file=sys.stderr)
# Sort by availability (and use last success as tie breaker)
ips.sort(key=lambda x: (x['uptime'], x['lastsuccess'], x['ip']), reverse=True)
# Filter out hosts with multiple digibyte ports, these are likely abusive
ips = filtermultiport(ips)
print('%s Filter out hosts with multiple digibyte ports' % (ip_stats(ips)), file=sys.stderr)
# Look up ASNs and limit results, both per ASN and globally.
ips = filterbyasn(ips, MAX_SEEDS_PER_ASN, NSEEDS)
print('%s Look up ASNs and limit results per ASN and per net' % (ip_stats(ips)), file=sys.stderr)
# Sort the results by IP address (for deterministic output).
ips.sort(key=lambda x: (x['net'], x['sortkey']))
for ip in ips:
if ip['net'] == 'ipv6':
print('[%s]:%i' % (ip['ip'], ip['port']))
else:
print('%s:%i' % (ip['ip'], ip['port']))
if __name__ == '__main__':
main()

View file

@ -0,0 +1,218 @@
# List of fixed seed nodes for DigiByte mainnet
# IP4 Full Nodes added from digibyteseed.com 2023-11-28
65.21.137.242:12024
51.89.40.32:12024
13.250.172.21:12024
173.212.197.63:12024
75.119.133.163:12024
64.227.97.247:12024
172.105.162.72:12024
5.9.193.21:12024
87.98.244.13:12024
3.109.136.67:12024
157.230.194.126:12024
54.39.129.199:12024
64.31.61.109:12024
168.119.147.118:12024
198.100.145.152:12024
54.250.145.150:12024
65.21.40.28:12024
54.37.139.32:12024
162.19.204.20:12024
136.144.215.219:12024
51.81.224.195:12024
18.142.54.200:12024
212.92.101.189:12024
80.120.148.66:12024
144.76.73.8:12024
144.91.104.184:12024
37.49.230.5:12024
134.195.198.250:12024
43.228.126.129:12024
95.217.78.79:12024
8.218.7.94:12024
159.89.206.87:12024
54.251.193.206:12024
82.200.205.30:12024
188.230.206.230:12024
134.195.198.126:12024
35.183.128.62:12024
47.243.23.126:12024
8.218.140.132:12024
47.75.194.174:12024
13.214.142.240:12024
54.37.81.148:12024
194.5.152.211:12024
73.176.72.165:12024
165.255.244.160:12024
91.206.16.214:12024
88.117.161.226:12024
85.15.179.171:12024
80.122.142.86:12024
37.59.32.10:12024
142.44.132.221:12024
67.49.56.18:12024
80.122.131.94:12024
124.181.36.127:12024
80.65.23.139:12024
94.130.130.144:12024
37.97.148.182:12024
99.148.47.138:12024
192.95.29.173:12024
144.91.99.72:12024
87.79.94.221:12024
65.21.132.187:12024
45.61.244.191:12024
88.116.128.130:12024
188.165.21.55:8288
51.222.152.48:8338
51.210.208.202:8834
3.132.46.228:8445
141.95.146.47:12024
142.132.202.124:8834
195.3.222.58:20002
195.3.222.58:21002
51.195.234.88:8338
157.90.88.178:9023
192.241.141.154:30008
51.210.216.76:8834
142.132.212.130:8834
157.90.89.105:9023
51.210.216.77:8834
51.222.152.238:8338
185.16.39.236:22006
95.179.161.251:31009
108.61.78.226:31009
154.49.137.70:12024
51.210.208.201:8834
188.165.21.55:8188
142.132.156.41:12024
146.59.118.2:12024
188.21.142.46:12024
199.38.86.26:6312
141.95.45.161:8338
124.181.36.127:12028
66.151.242.154:12029
50.220.121.211:6008
80.120.157.10:12024
193.203.191.182:12024
88.117.243.186:12024
83.221.211.116:12029
95.165.149.139:12024
109.70.186.58:12024
88.99.67.222:12024
31.25.241.224:12029
70.177.96.37:12024
176.66.77.224:12024
144.91.115.58:12024
49.176.223.136:12026
85.191.19.113:12024
5.199.133.17:12024
80.123.84.18:12024
104.174.241.200:12024
162.55.75.116:12024
80.121.188.138:12024
157.97.68.86:12024
88.116.245.118:12024
75.103.179.181:12024
188.127.242.23:12024
78.46.36.37:12024
95.216.33.251:12024
95.216.29.219:12024
8.217.73.91:12024
203.220.17.245:12024
80.122.107.230:12024
50.220.121.222:6008
179.0.59.241:12024
104.34.107.44:12024
95.168.136.121:12024
173.71.207.89:12024
198.27.82.41:12024
148.113.176.33:12024
89.134.59.170:12024
91.150.108.249:12024
5.189.140.212:21016
156.146.140.206:12024
85.10.202.167:12024
66.64.43.14:12024
187.67.9.246:12024
162.55.101.8:8369
164.115.43.140:12024
54.193.220.121:12024
171.6.136.139:12024
94.23.163.163:12024
67.140.202.77:12024
49.48.95.185:12024
86.144.61.189:12024
72.192.92.119:12024
45.226.80.102:12024
85.206.100.75:12024
24.158.249.19:12024
172.111.186.76:12024
# IP6 Full Nodes added from digibyteseed.com 2023-11-28
[2001:41d0:700:6f14::]:12024
[2a01:4f9:4a:1df0::2]:12024
[2602:fec3:101:5::3:40]:12024
[2602:fec3:101:6::4:40]:12024
[2a01:7c8:d002:10f:5054:ff:fe5c:dac7]:12024
[2a01:4f8:191:9102::2]:12024
[2a02:810d:700:1184:dea6:32ff:fefd:e82b]:12024
[2001:4dd0:3564::89a7:142:347f:fe33]:12024
[2001:41d0:700:3020::]:12024
[2001:41d0:203:2294::]:12024
[2001:4dd0:3564::b486:d08a:e2ef:b1e6]:12024
[2001:4dd0:3564::84c0:ac15:a5ab:8503]:12024
[2001:4dd0:3564::461:f577:e158:57a5]:12024
[2400:8907::f03c:91ff:fe5b:61e6]:12024
[2a01:7c8:aac7:2a4:2e2f:aa86:2e39:8c99]:12024
[2607:5300:60:2cad::1]:12024
[2620:a6:2000:1:2::6:4090]:12024
[2001:4dd0:3564:1::7676:8090]:12024
[2620:a6:2000:1:2::9:92d2]:12024
[2001:4dd0:af0e:3564::69:90]:12024
[2605:3800:0:210:0:26:0:1]:6312
[2001:41d0:203:8fca::]:8834
[2001:41d0:203:8fc9::]:8834
[2001:41d0:403:434d::]:8834
[2a03:cfc0:8000:13::c303:de3a]:20002
[2620:a6:2000:1:2:0:6:4090]:12024
[2a01:4f8:13a:4e::2]:9091
[2a01:4f8:261:4e8c::2]:8834
[2a01:4f8:262:5123::2]:8834
[2a01:4f8:212:1b49::2]:12024
[2a02:4780:c:1704::1]:12024
[2620:a6:2000:1:2:0:9:92d2]:12024
[2001:41d0:403:434c::]:8834
[2001:41d0:403:512f::]:12024
[2a02:4780:28:c53d::1]:12024
[2a03:cfc0:8000:13::c303:de3a]:21002
[2603:8001:ba00:7000:771a:4ef:d391:d852]:12024
[2001:4ba0:cafe:b8::1]:12024
[2a01:4f8:fff0:9e:1:0:d:6a4e]:12024
[2a01:4f8:fff0:9e:1::d:6a4e]:12024
[2603:8001:ba00:7000:7242:2c70:688b:1fc7]:12024
[2a06:dd00:10:0:225:90ff:fe0d:194]:12024
[2a06:dd00:10:6:225:90ff:fe0d:194]:12024
[2001:4dd0:3564:0:84c0:ac15:a5ab:8503]:12024
[2001:4dd0:3564:0:89a7:142:347f:fe33]:12024
[2001:4dd0:3564:0:461:f577:e158:57a5]:12024
[2001:4dd0:3564:0:b486:d08a:e2ef:b1e6]:12024
[2607:5300:203:c021::]:12024
[2a01:4f8:a0:5243::2]:12024
[2607:5300:60:2329::]:12024
[2603:8001:ba00:7000:49ad:7459:4653:7ec5]:12024
[2403:6200:88a0:bf40:2092:8d:5c8e:472e]:12024
# Onion / I2P Nodes
# We should add these! Examples:
# 2g5qfdkn2vvcbqhzcyvyiitg4ceukybxklraxjnu7atlhd22gdwywaid.onion:8333
# 2jmtxvyup3ijr7u6uvu7ijtnojx4g5wodvaedivbv74w4vzntxbrhvad.onion:8333
# 72l3ucjkuscrbiiepoehuwqgknyzgo7zuix5ty4puwrkyhtmnsga.b32.i2p:0
# c4gfnttsuwqomiygupdqqqyy5y5emnk5c73hrfvatri67prd7vyq.b32.i2p:0
# etc.

View file

@ -0,0 +1,25 @@
# List of fixed seed nodes for DigiByte testnet
# IP4 Full Nodes added from digibyteseed.com 2023-11-28
198.58.124.101:12026
157.245.63.215:12026
37.59.20.42:12026
86.144.61.189:12026
8.214.25.169:12026
217.72.6.241:12026
99.233.25.27:12026
86.144.61.212:12026
89.217.169.40:12026
# Onion / I2P Nodes
# We should add these! Examples:
# 2g5qfdkn2vvcbqhzcyvyiitg4ceukybxklraxjnu7atlhd22gdwywaid.onion:8333
# 2jmtxvyup3ijr7u6uvu7ijtnojx4g5wodvaedivbv74w4vzntxbrhvad.onion:8333
# 72l3ucjkuscrbiiepoehuwqgknyzgo7zuix5ty4puwrkyhtmnsga.b32.i2p:0
# c4gfnttsuwqomiygupdqqqyy5y5emnk5c73hrfvatri67prd7vyq.b32.i2p:0
# etc.

View file

@ -0,0 +1,16 @@
130.211.129.106
148.251.238.178
176.9.46.6
178.63.107.226
54.173.72.127
54.174.10.182
54.183.64.54
54.194.231.211
54.66.214.167
54.66.220.137
54.67.33.14
54.77.251.214
54.94.195.96
54.94.200.247
83.81.130.26
88.198.17.7