Merge branch 'dev' into duke
This commit is contained in:
@@ -247,6 +247,9 @@ DISTCHECK_CONFIGURE_FLAGS = --enable-man
|
|||||||
clean-local:
|
clean-local:
|
||||||
rm -rf test_bitcoin.coverage/ total.coverage/
|
rm -rf test_bitcoin.coverage/ total.coverage/
|
||||||
|
|
||||||
|
seeds:
|
||||||
|
./contrib/seeds/generate-seeds.py contrib/seeds > src/chainparamsseeds.h
|
||||||
|
|
||||||
manpages:
|
manpages:
|
||||||
./util/gen-manpages.sh
|
./util/gen-manpages.sh
|
||||||
@echo "Please review the man pages changes to see if they look correct, then commit and push"
|
@echo "Please review the man pages changes to see if they look correct, then commit and push"
|
||||||
|
|||||||
34
configure.ac
34
configure.ac
@@ -221,6 +221,29 @@ if test "x$CXXFLAGS_overridden" = "xno"; then
|
|||||||
AX_CHECK_COMPILE_FLAG([-Wunused-local-typedef],[CXXFLAGS="$CXXFLAGS -Wno-unused-local-typedef"],,[[$CXXFLAG_WERROR]])
|
AX_CHECK_COMPILE_FLAG([-Wunused-local-typedef],[CXXFLAGS="$CXXFLAGS -Wno-unused-local-typedef"],,[[$CXXFLAG_WERROR]])
|
||||||
AX_CHECK_COMPILE_FLAG([-Wdeprecated-register],[CXXFLAGS="$CXXFLAGS -Wno-deprecated-register"],,[[$CXXFLAG_WERROR]])
|
AX_CHECK_COMPILE_FLAG([-Wdeprecated-register],[CXXFLAGS="$CXXFLAGS -Wno-deprecated-register"],,[[$CXXFLAG_WERROR]])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
TEMP_CXXFLAGS="$CXXFLAGS"
|
||||||
|
CXXFLAGS="$CXXFLAGS $SSE42_CXXFLAGS"
|
||||||
|
AC_MSG_CHECKING(for assembler crc32 support)
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
||||||
|
#include <stdint.h>
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#include <intrin.h>
|
||||||
|
#elif defined(__GNUC__) && defined(__SSE4_2__)
|
||||||
|
#include <nmmintrin.h>
|
||||||
|
#endif
|
||||||
|
]],[[
|
||||||
|
uint64_t l = 0;
|
||||||
|
l = _mm_crc32_u8(l, 0);
|
||||||
|
l = _mm_crc32_u32(l, 0);
|
||||||
|
l = _mm_crc32_u64(l, 0);
|
||||||
|
return l;
|
||||||
|
]])],
|
||||||
|
[ AC_MSG_RESULT(yes); enable_hwcrc32=yes],
|
||||||
|
[ AC_MSG_RESULT(no)]
|
||||||
|
)
|
||||||
|
CXXFLAGS="$TEMP_CXXFLAGS"
|
||||||
|
|
||||||
CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS"
|
CPPFLAGS="$CPPFLAGS -DHAVE_BUILD_INFO -D__STDC_FORMAT_MACROS"
|
||||||
|
|
||||||
AC_ARG_WITH([utils],
|
AC_ARG_WITH([utils],
|
||||||
@@ -241,6 +264,16 @@ AC_ARG_WITH([daemon],
|
|||||||
[build_bitcoind=$withval],
|
[build_bitcoind=$withval],
|
||||||
[build_bitcoind=yes])
|
[build_bitcoind=yes])
|
||||||
|
|
||||||
|
GCC_TARGET=`$CC -dumpmachine 2>&1`
|
||||||
|
case $GCC_TARGET in
|
||||||
|
arm*-*-*)
|
||||||
|
have_arm=true
|
||||||
|
;;
|
||||||
|
aarch64*-*-*)
|
||||||
|
have_arm=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
use_pkgconfig=yes
|
use_pkgconfig=yes
|
||||||
case $host in
|
case $host in
|
||||||
*mingw*)
|
*mingw*)
|
||||||
@@ -815,6 +848,7 @@ AM_CONDITIONAL([TARGET_WINDOWS], [test x$TARGET_OS = xwindows])
|
|||||||
AM_CONDITIONAL([ENABLE_WALLET],[test x$enable_wallet = xyes])
|
AM_CONDITIONAL([ENABLE_WALLET],[test x$enable_wallet = xyes])
|
||||||
AM_CONDITIONAL([ENABLE_MINING],[test x$enable_mining = xyes])
|
AM_CONDITIONAL([ENABLE_MINING],[test x$enable_mining = xyes])
|
||||||
AM_CONDITIONAL([ENABLE_TESTS],[test x$BUILD_TEST = xyes])
|
AM_CONDITIONAL([ENABLE_TESTS],[test x$BUILD_TEST = xyes])
|
||||||
|
AM_CONDITIONAL([ARCH_ARM], [test x$have_arm = xtrue])
|
||||||
AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes])
|
AM_CONDITIONAL([USE_LCOV],[test x$use_lcov = xyes])
|
||||||
AM_CONDITIONAL([GLIBC_BACK_COMPAT],[test x$use_glibc_compat = xyes])
|
AM_CONDITIONAL([GLIBC_BACK_COMPAT],[test x$use_glibc_compat = xyes])
|
||||||
AM_CONDITIONAL([HARDEN],[test x$use_hardening = xyes])
|
AM_CONDITIONAL([HARDEN],[test x$use_hardening = xyes])
|
||||||
|
|||||||
@@ -35,12 +35,6 @@ pre-start script
|
|||||||
echo
|
echo
|
||||||
echo "bash -c 'tr -dc a-zA-Z0-9 < /dev/urandom | head -c32 && echo'"
|
echo "bash -c 'tr -dc a-zA-Z0-9 < /dev/urandom | head -c32 && echo'"
|
||||||
echo
|
echo
|
||||||
echo "It is also recommended that you also set alertnotify so you are "
|
|
||||||
echo "notified of problems:"
|
|
||||||
echo
|
|
||||||
echo "ie: alertnotify=echo %%s | mail -s \"Hush Alert\"" \
|
|
||||||
"admin@foo.com"
|
|
||||||
echo
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -81,11 +81,6 @@ checkconfig()
|
|||||||
eerror ""
|
eerror ""
|
||||||
eerror "bash -c 'tr -dc a-zA-Z0-9 < /dev/urandom | head -c32 && echo'"
|
eerror "bash -c 'tr -dc a-zA-Z0-9 < /dev/urandom | head -c32 && echo'"
|
||||||
eerror ""
|
eerror ""
|
||||||
eerror "It is also recommended that you also set alertnotify so you are "
|
|
||||||
eerror "notified of problems:"
|
|
||||||
eerror ""
|
|
||||||
eerror "ie: alertnotify=echo %%s | mail -s \"Hush Alert\"" \
|
|
||||||
"admin@foo.com"
|
|
||||||
eerror ""
|
eerror ""
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
### Seeds ###
|
# Seeds
|
||||||
|
|
||||||
Utility to generate the seeds.txt list that is compiled into the client
|
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)).
|
(see [src/chainparamsseeds.h](hush/hush3/src/branch/master/src/chainparamsseeds.h) and other utilities in [contrib/seeds](hush/hush3/src/branch/master/contrib/seeds/)).
|
||||||
|
|
||||||
|
## Updating seeds
|
||||||
|
|
||||||
|
Update [contrib/seeds/nodes_main.txt](hush/hush3/src/branch/master/contrib/seeds/nodes_main.txt) and run `make seeds` in the root directory of this repo to update [src/chainparamsseeds.h](hush/hush3/src/branch/master/src/chainparamsseeds.h) then commit the result.
|
||||||
|
|
||||||
The 512 seeds compiled into the 0.10 release were created from sipa's DNS seed data, like this:
|
|
||||||
|
|
||||||
curl -s http://bitcoin.sipa.be/seeds.txt | makeseeds.py
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# Copyright (c) 2014 Wladimir J. van der Laan
|
# Copyright (c) 2016-2022 The Hush developers
|
||||||
|
# Copyright (c) 2014-2021 The Bitcoin Core developers
|
||||||
# Distributed under the GPLv3 software license, see the accompanying
|
# Distributed under the GPLv3 software license, see the accompanying
|
||||||
# file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
# file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
'''
|
'''
|
||||||
@@ -13,43 +14,61 @@ argument:
|
|||||||
|
|
||||||
These files must consist of lines in the format
|
These files must consist of lines in the format
|
||||||
|
|
||||||
<ip>
|
|
||||||
<ip>:<port>
|
<ip>:<port>
|
||||||
[<ipv6>]
|
<ip>
|
||||||
[<ipv6>]:<port>
|
[<ipv6>]:<port>
|
||||||
|
[<ipv6>]
|
||||||
|
<onion>.onion:<port>
|
||||||
<onion>.onion
|
<onion>.onion
|
||||||
0xDDBBCCAA (IPv4 little-endian old pnSeeds format)
|
<i2p>.b32.i2p:<port>
|
||||||
|
<i2p>.b32.i2p
|
||||||
|
|
||||||
The output will be two data structures with the peers in binary format:
|
The output will be two data structures with the peers in binary format:
|
||||||
|
|
||||||
static SeedSpec6 pnSeed6_main[]={
|
static const uint8_t chainparams_seed_{main,test}[]={
|
||||||
...
|
|
||||||
}
|
|
||||||
static SeedSpec6 pnSeed6_test[]={
|
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
These should be pasted into `src/chainparamsseeds.h`.
|
To update the generated code :
|
||||||
|
|
||||||
|
./contrib/seeds/generate-seeds.py contrib/seeds > src/chainparamsseeds.h
|
||||||
|
|
||||||
'''
|
'''
|
||||||
from __future__ import print_function, division
|
|
||||||
from base64 import b32decode
|
from base64 import b32decode
|
||||||
from binascii import a2b_hex
|
from enum import Enum
|
||||||
import sys, os
|
import struct
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
# ipv4 in ipv6 prefix
|
class BIP155Network(Enum):
|
||||||
pchIPv4 = bytearray([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff])
|
IPV4 = 1
|
||||||
# tor-specific ipv6 prefix
|
IPV6 = 2
|
||||||
pchOnionCat = bytearray([0xFD,0x87,0xD8,0x7E,0xEB,0x43])
|
TORV2 = 3 # no longer supported
|
||||||
|
TORV3 = 4
|
||||||
|
I2P = 5
|
||||||
|
CJDNS = 6
|
||||||
|
|
||||||
def name_to_ipv6(addr):
|
def name_to_bip155(addr):
|
||||||
if len(addr)>6 and addr.endswith('.onion'):
|
'''Convert address string to BIP155 (networkID, addr) tuple.'''
|
||||||
|
if addr.endswith('.onion'):
|
||||||
vchAddr = b32decode(addr[0:-6], True)
|
vchAddr = b32decode(addr[0:-6], True)
|
||||||
if len(vchAddr) != 16-len(pchOnionCat):
|
if len(vchAddr) == 35:
|
||||||
raise ValueError('Invalid onion %s' % s)
|
assert vchAddr[34] == 3
|
||||||
return pchOnionCat + vchAddr
|
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
|
elif '.' in addr: # IPv4
|
||||||
return pchIPv4 + bytearray((int(x) for x in addr.split('.')))
|
return (BIP155Network.IPV4, bytes((int(x) for x in addr.split('.'))))
|
||||||
elif ':' in addr: # IPv6
|
elif ':' in addr: # IPv6
|
||||||
sub = [[], []] # prefix, suffix
|
sub = [[], []] # prefix, suffix
|
||||||
x = 0
|
x = 0
|
||||||
@@ -66,14 +85,13 @@ def name_to_ipv6(addr):
|
|||||||
sub[x].append(val & 0xff)
|
sub[x].append(val & 0xff)
|
||||||
nullbytes = 16 - len(sub[0]) - len(sub[1])
|
nullbytes = 16 - len(sub[0]) - len(sub[1])
|
||||||
assert((x == 0 and nullbytes == 0) or (x == 1 and nullbytes > 0))
|
assert((x == 0 and nullbytes == 0) or (x == 1 and nullbytes > 0))
|
||||||
return bytearray(sub[0] + ([0] * nullbytes) + sub[1])
|
return (BIP155Network.IPV6, bytes(sub[0] + ([0] * nullbytes) + sub[1]))
|
||||||
elif addr.startswith('0x'): # IPv4-in-little-endian
|
|
||||||
return pchIPv4 + bytearray(reversed(a2b_hex(addr[2:])))
|
|
||||||
else:
|
else:
|
||||||
raise ValueError('Could not parse address %s' % addr)
|
raise ValueError('Could not parse address %s' % addr)
|
||||||
|
|
||||||
def parse_spec(s, defaultport):
|
def parse_spec(s):
|
||||||
match = re.match('\[([0-9a-fA-F:]+)\](?::([0-9]+))?$', s)
|
'''Convert endpoint string to BIP155 (networkID, addr, port) tuple.'''
|
||||||
|
match = re.match(r'\[([0-9a-fA-F:]+)\](?::([0-9]+))?$', s)
|
||||||
if match: # ipv6
|
if match: # ipv6
|
||||||
host = match.group(1)
|
host = match.group(1)
|
||||||
port = match.group(2)
|
port = match.group(2)
|
||||||
@@ -84,17 +102,42 @@ def parse_spec(s, defaultport):
|
|||||||
(host,_,port) = s.partition(':')
|
(host,_,port) = s.partition(':')
|
||||||
|
|
||||||
if not port:
|
if not port:
|
||||||
port = defaultport
|
port = 0
|
||||||
else:
|
else:
|
||||||
port = int(port)
|
port = int(port)
|
||||||
|
|
||||||
host = name_to_ipv6(host)
|
host = name_to_bip155(host)
|
||||||
|
|
||||||
return (host,port)
|
if host[0] == BIP155Network.TORV2:
|
||||||
|
return None # TORV2 is no longer supported, so we ignore it
|
||||||
|
else:
|
||||||
|
return host + (port, )
|
||||||
|
|
||||||
def process_nodes(g, f, structname, defaultport):
|
def ser_compact_size(l):
|
||||||
g.write('static SeedSpec6 %s[] = {\n' % structname)
|
r = b""
|
||||||
first = True
|
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:
|
for line in f:
|
||||||
comment = line.find('#')
|
comment = line.find('#')
|
||||||
if comment != -1:
|
if comment != -1:
|
||||||
@@ -102,37 +145,39 @@ def process_nodes(g, f, structname, defaultport):
|
|||||||
line = line.strip()
|
line = line.strip()
|
||||||
if not line:
|
if not line:
|
||||||
continue
|
continue
|
||||||
if not first:
|
|
||||||
g.write(',\n')
|
|
||||||
first = False
|
|
||||||
|
|
||||||
(host,port) = parse_spec(line, defaultport)
|
spec = parse_spec(line)
|
||||||
hoststr = ','.join(('0x%02x' % b) for b in host)
|
if spec is None: # ignore this entry (e.g. no longer supported addresses like TORV2)
|
||||||
g.write(' {{%s}, %i}' % (hoststr, port))
|
continue
|
||||||
g.write('\n};\n')
|
blob = bip155_serialize(spec)
|
||||||
|
hoststr = ','.join(('0x%02x' % b) for b in blob)
|
||||||
|
g.write(f' {hoststr}, // {line}\n')
|
||||||
|
g.write('};\n')
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
if len(sys.argv)<2:
|
if len(sys.argv)<2:
|
||||||
print(('Usage: %s <path_to_nodes_txt>' % sys.argv[0]), file=sys.stderr)
|
print(('Usage: %s <path_to_nodes_txt>' % sys.argv[0]), file=sys.stderr)
|
||||||
exit(1)
|
sys.exit(1)
|
||||||
g = sys.stdout
|
g = sys.stdout
|
||||||
indir = sys.argv[1]
|
indir = sys.argv[1]
|
||||||
g.write('#ifndef BITCOIN_CHAINPARAMSSEEDS_H\n')
|
g.write('// Copyright (c) 2016-2022 The Hush developers\n')
|
||||||
g.write('#define BITCOIN_CHAINPARAMSSEEDS_H\n')
|
g.write('// Distributed under the GPLv3 software license, see the accompanying\n')
|
||||||
g.write('/**\n')
|
g.write('// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html\n')
|
||||||
g.write(' * List of fixed seed nodes for the bitcoin network\n')
|
g.write('// THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY\n')
|
||||||
g.write(' * AUTOGENERATED by contrib/seeds/generate-seeds.py\n')
|
g.write('// Instead, update contrib/seeds/nodes_main.txt then run\n')
|
||||||
g.write(' *\n')
|
g.write('// ./contrib/seeds/generate-seeds.py contrib/seeds > src/chainparamsseeds.h\n')
|
||||||
g.write(' * Each line contains a 16-byte IPv6 address and a port.\n')
|
g.write('// OR run: make seeds\n')
|
||||||
g.write(' * IPv4 as well as onion addresses are wrapped inside a IPv6 address accordingly.\n')
|
g.write('#ifndef HUSH_CHAINPARAMSSEEDS_H\n')
|
||||||
g.write(' */\n')
|
g.write('#define HUSH_CHAINPARAMSSEEDS_H\n')
|
||||||
with open(os.path.join(indir,'nodes_main.txt'),'r') as f:
|
g.write('// List of fixed seed nodes for the Hush network\n')
|
||||||
process_nodes(g, f, 'pnSeed6_main', 8233)
|
g.write('// Each line contains a BIP155 serialized address.\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')
|
g.write('\n')
|
||||||
with open(os.path.join(indir,'nodes_test.txt'),'r') as f:
|
with open(os.path.join(indir,'nodes_test.txt'), 'r', encoding="utf8") as f:
|
||||||
process_nodes(g, f, 'pnSeed6_test', 18233)
|
process_nodes(g, f, 'chainparams_seed_test')
|
||||||
g.write('#endif // BITCOIN_CHAINPARAMSSEEDS_H\n')
|
g.write('#endif // HUSH_CHAINPARAMSSEEDS_H\n')
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,18 @@
|
|||||||
185.25.48.236:27485
|
# node1.hush.land
|
||||||
185.25.48.236:27487
|
185.241.61.43
|
||||||
185.64.105.111:27485
|
|
||||||
185.64.105.111:27487
|
# node2.hush.is
|
||||||
185.25.48.72:27485
|
137.74.4.198
|
||||||
185.25.48.72:27487
|
|
||||||
|
# lite.hushpool.is
|
||||||
|
149.28.102.219
|
||||||
|
|
||||||
|
# wtfistheinternet.hush.is
|
||||||
|
107.174.70.251
|
||||||
|
|
||||||
|
# torv3
|
||||||
|
56wqzfj6mhxgsv3h3nh3pdocguogxfxud55libqjhjsdh5alfsko2iqd.onion
|
||||||
|
hushv3h6mbxd2pptj42reko3jcexcgnz5zvp3mqcu6myto3jhhn4yzyd.onion
|
||||||
|
|
||||||
|
# todo: i2p
|
||||||
|
iljqq7nnmw2ij2ezl334cerwwmgzmmbmoc3n4saditd2xhi3xohq.b32.i2p
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
# List of fixed seed nodes for testnet
|
# List of fixed seed nodes for testnet
|
||||||
|
# note: File must be non-empty to compile
|
||||||
|
1.2.3.4
|
||||||
|
|
||||||
# Onion nodes
|
# Onion nodes
|
||||||
thfsmmn2jbitcoin.onion
|
|
||||||
it2pj4f7657g3rhi.onion
|
|
||||||
nkf5e6b7pl4jfd4a.onion
|
|
||||||
4zhkir2ofl7orfom.onion
|
|
||||||
t6xj6wilh4ytvcs7.onion
|
|
||||||
i6y6ivorwakd7nw3.onion
|
|
||||||
ubqj4rsu3nqtxmtp.onion
|
|
||||||
|
|
||||||
|
|||||||
161
doc/i2p.md
Normal file
161
doc/i2p.md
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
# I2P support in Hush
|
||||||
|
|
||||||
|
It is possible to run a Hush or HSC full node as an
|
||||||
|
[I2P (Invisible Internet Project)](https://en.wikipedia.org/wiki/I2P)
|
||||||
|
service and connect to such services.
|
||||||
|
|
||||||
|
This [glossary](https://geti2p.net/en/about/glossary) may be useful to get
|
||||||
|
started with I2P terminology.
|
||||||
|
|
||||||
|
## Run with an I2P router (proxy)
|
||||||
|
|
||||||
|
A running I2P router (proxy) with [SAM](https://geti2p.net/en/docs/api/samv3)
|
||||||
|
enabled is required. Options include:
|
||||||
|
|
||||||
|
- [i2prouter (I2P Router)](https://geti2p.net), the official implementation in
|
||||||
|
Java
|
||||||
|
- [i2pd (I2P Daemon)](https://github.com/PurpleI2P/i2pd)
|
||||||
|
([documentation](https://i2pd.readthedocs.io/en/latest)), a lighter
|
||||||
|
alternative in C++ (successfully tested with version 2.23 and up; version 2.36
|
||||||
|
or later recommended)
|
||||||
|
- [i2p-zero](https://github.com/i2p-zero/i2p-zero)
|
||||||
|
- [other alternatives](https://en.wikipedia.org/wiki/I2P#Routers)
|
||||||
|
|
||||||
|
Note the IP address and port the SAM proxy is listening to; usually, it is
|
||||||
|
`127.0.0.1:7656`.
|
||||||
|
|
||||||
|
Once an I2P router with SAM enabled is up and running, use the following
|
||||||
|
configuration options:
|
||||||
|
|
||||||
|
```
|
||||||
|
-i2psam=<ip:port>
|
||||||
|
I2P SAM proxy to reach I2P peers and accept I2P connections (default:
|
||||||
|
none)
|
||||||
|
|
||||||
|
-i2pacceptincoming
|
||||||
|
If set and -i2psam is also set then incoming I2P connections are
|
||||||
|
accepted via the SAM proxy. If this is not set but -i2psam is set
|
||||||
|
then only outgoing connections will be made to the I2P network.
|
||||||
|
Ignored if -i2psam is not set. Listening for incoming I2P
|
||||||
|
connections is done through the SAM proxy, not by binding to a
|
||||||
|
local address and port (default: 1)
|
||||||
|
```
|
||||||
|
|
||||||
|
In a typical situation, this suffices:
|
||||||
|
|
||||||
|
```
|
||||||
|
hushd -i2psam=127.0.0.1:7656
|
||||||
|
```
|
||||||
|
|
||||||
|
The first time hushd connects to the I2P router, if
|
||||||
|
`-i2pacceptincoming=1`, then it will automatically generate a persistent I2P
|
||||||
|
address and its corresponding private key. The private key will be saved in a
|
||||||
|
file named `i2p_private_key` in the Hush data directory. The persistent
|
||||||
|
I2P address is used for accepting incoming connections and for making outgoing
|
||||||
|
connections if `-i2pacceptincoming=1`. If `-i2pacceptincoming=0` then only
|
||||||
|
outbound I2P connections are made and a different transient I2P address is used
|
||||||
|
for each connection to improve privacy.
|
||||||
|
|
||||||
|
## Persistent vs transient I2P addresses
|
||||||
|
|
||||||
|
In I2P connections, the connection receiver sees the I2P address of the
|
||||||
|
connection initiator. This is unlike the Tor network where the recipient does
|
||||||
|
not know who is connecting to them and can't tell if two connections are from
|
||||||
|
the same peer or not.
|
||||||
|
|
||||||
|
If an I2P node is not accepting incoming connections, then Hush uses
|
||||||
|
random, one-time, transient I2P addresses for itself for outbound connections
|
||||||
|
to make it harder to discriminate, fingerprint or analyze it based on its I2P
|
||||||
|
address.
|
||||||
|
|
||||||
|
## Additional configuration options related to I2P
|
||||||
|
|
||||||
|
```
|
||||||
|
-debug=i2p
|
||||||
|
```
|
||||||
|
|
||||||
|
Set the `debug=i2p` config logging option to see additional information in the
|
||||||
|
debug log about your I2P configuration and connections. Run `hush-cli help
|
||||||
|
logging` for more information.
|
||||||
|
|
||||||
|
```
|
||||||
|
-onlynet=i2p
|
||||||
|
```
|
||||||
|
|
||||||
|
Make automatic outbound connections only to I2P addresses. Inbound and manual
|
||||||
|
connections are not affected by this option. It can be specified multiple times
|
||||||
|
to allow multiple networks, e.g. onlynet=onion, onlynet=i2p.
|
||||||
|
|
||||||
|
I2P support was added to Hush in version 3.9.3 and there may be fewer I2P
|
||||||
|
peers than Tor or IP ones. Therefore, using I2P alone without other networks may
|
||||||
|
make a node more susceptible to [Sybil
|
||||||
|
attacks](https://en.bitcoin.it/wiki/Weaknesses#Sybil_attack). You can use
|
||||||
|
`hush-cli -addrinfo` to see the number of I2P addresses known to your node.
|
||||||
|
|
||||||
|
Another consideration with `onlynet=i2p` is that the initial blocks download
|
||||||
|
phase when syncing up a new node can be very slow. This phase can be sped up by
|
||||||
|
using other networks, for instance `onlynet=onion`, at the same time.
|
||||||
|
|
||||||
|
In general, a node can be run with both onion and I2P hidden services (or
|
||||||
|
any/all of IPv4/IPv6/onion/I2P/CJDNS), which can provide a potential fallback if
|
||||||
|
one of the networks has issues.
|
||||||
|
|
||||||
|
## I2P-related information
|
||||||
|
|
||||||
|
There are several ways to see your I2P address if accepting
|
||||||
|
incoming I2P connections (`-i2pacceptincoming`):
|
||||||
|
- in the "Local addresses" output of CLI `-netinfo`
|
||||||
|
- in the "localaddresses" output of RPC `getnetworkinfo`
|
||||||
|
- in the debug log (grep for `AddLocal`; the I2P address ends in `.b32.i2p`)
|
||||||
|
|
||||||
|
To see which I2P peers your node is connected to, use `hush-cli -netinfo 4`
|
||||||
|
or the `getpeerinfo` RPC (e.g. `hush-cli getpeerinfo`).
|
||||||
|
|
||||||
|
To see which I2P addresses your node knows, use the `getnodeaddresses 0 i2p`
|
||||||
|
RPC.
|
||||||
|
|
||||||
|
## Compatibility
|
||||||
|
|
||||||
|
Hush uses the [SAM v3.1](https://geti2p.net/en/docs/api/samv3) protocol
|
||||||
|
to connect to the I2P network. Any I2P router that supports it can be used.
|
||||||
|
|
||||||
|
## Ports in I2P and Hush
|
||||||
|
|
||||||
|
Hush uses the [SAM v3.1](https://geti2p.net/en/docs/api/samv3)
|
||||||
|
protocol. One particularity of SAM v3.1 is that it does not support ports,
|
||||||
|
unlike newer versions of SAM (v3.2 and up) that do support them and default the
|
||||||
|
port numbers to 0. From the point of view of peers that use newer versions of
|
||||||
|
SAM or other protocols that support ports, a SAM v3.1 peer is connecting to them
|
||||||
|
on port 0, from source port 0.
|
||||||
|
|
||||||
|
To allow future upgrades to newer versions of SAM, Hush sets its
|
||||||
|
listening port to 0 when listening for incoming I2P connections and advertises
|
||||||
|
its own I2P address with port 0. Furthermore, it will not attempt to connect to
|
||||||
|
I2P addresses with a non-zero port number because with SAM v3.1 the destination
|
||||||
|
port (`TO_PORT`) is always set to 0 and is not in the control of Hush.
|
||||||
|
|
||||||
|
## Bandwidth
|
||||||
|
|
||||||
|
I2P routers may route a large amount of general network traffic with their
|
||||||
|
default settings. Check your router's configuration to limit the amount of this
|
||||||
|
traffic relayed, if desired.
|
||||||
|
|
||||||
|
With `i2pd`, the amount of bandwidth being shared with the wider network can be
|
||||||
|
adjusted with the `bandwidth`, `share` and `transittunnels` options in your
|
||||||
|
`i2pd.conf` file. For example, to limit total I2P traffic to 256KB/s and share
|
||||||
|
50% of this limit for a maximum of 20 transit tunnels:
|
||||||
|
|
||||||
|
```
|
||||||
|
bandwidth = 256
|
||||||
|
share = 50
|
||||||
|
|
||||||
|
[limits]
|
||||||
|
transittunnels = 20
|
||||||
|
```
|
||||||
|
|
||||||
|
If you prefer not to relay any public I2P traffic and only permit I2P traffic
|
||||||
|
from programs which are connecting via the SAM proxy, e.g. Hush, you
|
||||||
|
can set the `notransit` option to `true`.
|
||||||
|
|
||||||
|
Similar bandwidth configuration options for the Java I2P router can be found in
|
||||||
|
`http://127.0.0.1:7657/config` under the "Bandwidth" tab.
|
||||||
297
doc/tor.md
297
doc/tor.md
@@ -1,154 +1,225 @@
|
|||||||
# Warning
|
# Tor
|
||||||
|
|
||||||
Do not assume Tor support works perfectly in Hush; better Tor support is currently being worked on.
|
It is possible to run Hush as a Tor onion service, and connect to such services.
|
||||||
|
|
||||||
# Hush + Tor
|
|
||||||
|
|
||||||
It is possible to run Hush as a Tor hidden service, and connect to such services.
|
|
||||||
|
|
||||||
The following directions assume you have a Tor proxy running on port 9050. Many distributions default to having a SOCKS proxy listening on port 9050, but others may not. In particular, the Tor Browser Bundle defaults to listening on port 9150. See [Tor Project FAQ:TBBSocksPort](https://www.torproject.org/docs/faq.html.en#TBBSocksPort) for how to properly
|
The following directions assume you have a Tor proxy running on port 9050. Many distributions default to having a SOCKS proxy listening on port 9050, but others may not. In particular, the Tor Browser Bundle defaults to listening on port 9150. See [Tor Project FAQ:TBBSocksPort](https://www.torproject.org/docs/faq.html.en#TBBSocksPort) for how to properly
|
||||||
configure Tor.
|
configure Tor.
|
||||||
|
|
||||||
|
## Compatibility
|
||||||
|
|
||||||
1. Run Hush behind a Tor proxy
|
- Starting with version 3.9.3, Hush only supports Tor version 3 hidden
|
||||||
-------------------------------
|
services (Tor v3). Tor v2 addresses are ignored by Hush and neither
|
||||||
|
relayed nor stored.
|
||||||
|
|
||||||
The first step is running Hush behind a Tor proxy. This will already make all
|
- Tor removed v2 support beginning with version 0.4.6.
|
||||||
outgoing connections be anonymized, but more is possible.
|
|
||||||
|
|
||||||
-proxy=ip:port Set the proxy server. If SOCKS5 is selected (default), this proxy
|
## How to see information about your Tor configuration via Hush
|
||||||
server will be used to try to reach .onion addresses as well.
|
|
||||||
|
|
||||||
-onion=ip:port Set the proxy server to use for Tor hidden services. You do not
|
There are several ways to see your local onion address in Hush:
|
||||||
need to set this if it's the same as -proxy. You can use -noonion
|
- in the "Local addresses" output of CLI `-netinfo`
|
||||||
to explicitly disable access to hidden service.
|
- in the "localaddresses" output of RPC `getnetworkinfo`
|
||||||
|
- in the debug log (grep for "AddLocal"; the Tor address ends in `.onion`)
|
||||||
|
|
||||||
-listen When using -proxy, listening is disabled by default. If you want
|
You may set the `-debug=tor` config logging option to have additional
|
||||||
to run a hidden service (see next section), you'll need to enable
|
information in the debug log about your Tor configuration.
|
||||||
it explicitly.
|
|
||||||
|
|
||||||
-connect=X When behind a Tor proxy, you can specify .onion addresses instead
|
CLI `-addrinfo` returns the number of addresses known to your node per
|
||||||
-addnode=X of IP addresses or hostnames in these parameters. It requires
|
network. This can be useful to see how many onion peers your node knows,
|
||||||
-seednode=X SOCKS5. In Tor mode, such addresses can also be exchanged with
|
e.g. for `-onlynet=onion`.
|
||||||
other P2P nodes.
|
|
||||||
|
To fetch a number of onion addresses that your node knows, for example seven
|
||||||
|
addresses, use the `getnodeaddresses 7 onion` RPC.
|
||||||
|
|
||||||
|
## 1. Run Hush behind a Tor proxy
|
||||||
|
|
||||||
|
The first step is running Hush behind a Tor proxy. This will already anonymize all
|
||||||
|
outgoing connections, but more is possible.
|
||||||
|
|
||||||
|
-proxy=ip:port Set the proxy server. If SOCKS5 is selected (default), this proxy
|
||||||
|
server will be used to try to reach .onion addresses as well.
|
||||||
|
You need to use -noonion or -onion=0 to explicitly disable
|
||||||
|
outbound access to onion services.
|
||||||
|
|
||||||
|
-onion=ip:port Set the proxy server to use for Tor onion services. You do not
|
||||||
|
need to set this if it's the same as -proxy. You can use -onion=0
|
||||||
|
to explicitly disable access to onion services.
|
||||||
|
------------------------------------------------------------------
|
||||||
|
Note: Only the -proxy option sets the proxy for DNS requests;
|
||||||
|
with -onion they will not route over Tor, so use -proxy if you
|
||||||
|
have privacy concerns.
|
||||||
|
------------------------------------------------------------------
|
||||||
|
|
||||||
|
-listen When using -proxy, listening is disabled by default. If you want
|
||||||
|
to manually configure an onion service (see section 3), you'll
|
||||||
|
need to enable it explicitly.
|
||||||
|
|
||||||
|
-connect=X When behind a Tor proxy, you can specify .onion addresses instead
|
||||||
|
-addnode=X of IP addresses or hostnames in these parameters. It requires
|
||||||
|
-seednode=X SOCKS5. In Tor mode, such addresses can also be exchanged with
|
||||||
|
other P2P nodes.
|
||||||
|
|
||||||
|
-onlynet=onion Make automatic outbound connections only to .onion addresses.
|
||||||
|
Inbound and manual connections are not affected by this option.
|
||||||
|
It can be specified multiple times to allow multiple networks,
|
||||||
|
e.g. onlynet=onion, onlynet=i2p, onlynet=cjdns.
|
||||||
|
|
||||||
In a typical situation, this suffices to run behind a Tor proxy:
|
In a typical situation, this suffices to run behind a Tor proxy:
|
||||||
|
|
||||||
./hushd -proxy=127.0.0.1:9050
|
./hushd -proxy=127.0.0.1:9050
|
||||||
|
|
||||||
If using the Tor Browser Bundle:
|
## 2. Automatically create a Hush onion service
|
||||||
|
|
||||||
./hushd -proxy=127.0.0.1:9150
|
Hush makes use of Tor's control socket API to create and destroy
|
||||||
|
ephemeral onion services programmatically. This means that if Tor is running and
|
||||||
|
proper authentication has been configured, Hush automatically creates an
|
||||||
|
onion service to listen on. The goal is to increase the number of available
|
||||||
|
onion nodes.
|
||||||
|
|
||||||
|
This feature is enabled by default if Hush is listening (`-listen`) and
|
||||||
|
it requires a Tor connection to work. It can be explicitly disabled with
|
||||||
|
`-listenonion=0`. If it is not disabled, it can be configured using the
|
||||||
|
`-torcontrol` and `-torpassword` settings.
|
||||||
|
|
||||||
|
To see verbose Tor information in the hushd debug log, pass `-debug=tor`.
|
||||||
|
|
||||||
|
### Control Port
|
||||||
|
|
||||||
|
You may need to set up the Tor Control Port. On Linux distributions there may be
|
||||||
|
some or all of the following settings in `/etc/tor/torrc`, generally commented
|
||||||
|
out by default (if not, add them):
|
||||||
|
|
||||||
|
```
|
||||||
|
ControlPort 9051
|
||||||
|
CookieAuthentication 1
|
||||||
|
CookieAuthFileGroupReadable 1
|
||||||
|
```
|
||||||
|
|
||||||
|
Add or uncomment those, save, and restart Tor (usually `systemctl restart tor`
|
||||||
|
or `sudo systemctl restart tor` on most systemd-based systems, including recent
|
||||||
|
Debian and Ubuntu, or just restart the computer).
|
||||||
|
|
||||||
|
On some systems (such as Arch Linux), you may also need to add the following
|
||||||
|
line:
|
||||||
|
|
||||||
|
```
|
||||||
|
DataDirectoryGroupReadable 1
|
||||||
|
```
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
|
||||||
|
Connecting to Tor's control socket API requires one of two authentication
|
||||||
|
methods to be configured: cookie authentication or hushd's `-torpassword`
|
||||||
|
configuration option.
|
||||||
|
|
||||||
|
#### Cookie authentication
|
||||||
|
|
||||||
|
For cookie authentication, the user running hushd must have read access to
|
||||||
|
the `CookieAuthFile` specified in the Tor configuration. In some cases this is
|
||||||
|
preconfigured and the creation of an onion service is automatic. Don't forget to
|
||||||
|
use the `-debug=tor` hushd configuration option to enable Tor debug logging.
|
||||||
|
|
||||||
|
If a permissions problem is seen in the debug log, e.g. `tor: Authentication
|
||||||
|
cookie /run/tor/control.authcookie could not be opened (check permissions)`, it
|
||||||
|
can be resolved by adding both the user running Tor and the user running
|
||||||
|
hushd to the same Tor group and setting permissions appropriately.
|
||||||
|
|
||||||
|
On Debian-derived systems, the Tor group will likely be `debian-tor` and one way
|
||||||
|
to verify could be to list the groups and grep for a "tor" group name:
|
||||||
|
|
||||||
|
```
|
||||||
|
getent group | cut -d: -f1 | grep -i tor
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also check the group of the cookie file. On most Linux systems, the Tor
|
||||||
|
auth cookie will usually be `/run/tor/control.authcookie`:
|
||||||
|
|
||||||
|
```
|
||||||
|
TORGROUP=$(stat -c '%G' /run/tor/control.authcookie)
|
||||||
|
```
|
||||||
|
|
||||||
|
Once you have determined the `${TORGROUP}` and selected the `${USER}` that will
|
||||||
|
run hushd, run this as root:
|
||||||
|
|
||||||
|
```
|
||||||
|
usermod -a -G ${TORGROUP} ${USER}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then restart the computer (or log out) and log in as the `${USER}` that will run
|
||||||
|
hushd.
|
||||||
|
|
||||||
|
#### `torpassword` authentication
|
||||||
|
|
||||||
|
For the `-torpassword=password` option, the password is the clear text form that
|
||||||
|
was used when generating the hashed password for the `HashedControlPassword`
|
||||||
|
option in the Tor configuration file.
|
||||||
|
|
||||||
|
The hashed password can be obtained with the command `tor --hash-password
|
||||||
|
password` (refer to the [Tor Dev
|
||||||
|
Manual](https://2019.www.torproject.org/docs/tor-manual.html.en) for more
|
||||||
|
details).
|
||||||
|
|
||||||
|
|
||||||
|
## 3. Manually create a Hush onion service
|
||||||
|
|
||||||
2. Run a Hush hidden server
|
You can also manually configure your node to be reachable from the Tor network.
|
||||||
----------------------------
|
Add these lines to your `/etc/tor/torrc` (or equivalent config file):
|
||||||
|
|
||||||
If you configure your Tor system accordingly, it is possible to make your node also
|
HiddenServiceDir /var/lib/tor/hush-service/
|
||||||
reachable from the Tor network. Add these lines to your /etc/tor/torrc (or equivalent
|
HiddenServicePort 18030 127.0.0.1:18032
|
||||||
config file):
|
|
||||||
|
|
||||||
HiddenServiceDir /var/lib/tor/hush-service/
|
The directory can be different of course, but virtual port numbers should be equal to
|
||||||
HiddenServicePort 18030 127.0.0.1:18030
|
your hushd's P2P listen port (18030 by default), and target addresses and ports
|
||||||
|
should be equal to binding address and port for inbound Tor connections (127.0.0.1:18032 by default).
|
||||||
|
|
||||||
The directory can be different of course, but (both) port numbers should be equal to
|
-externalip=X You can tell hush about its publicly reachable addresses using
|
||||||
your hushd's P2P listen port (18030 by default).
|
this option, and this can be an onion address. Given the above
|
||||||
|
configuration, you can find your onion address in
|
||||||
|
/var/lib/tor/hush-service/hostname. For connections
|
||||||
|
coming from unroutable addresses (such as 127.0.0.1, where the
|
||||||
|
Tor proxy typically runs), onion addresses are given
|
||||||
|
preference for your node to advertise itself with.
|
||||||
|
|
||||||
-externalip=X You can tell Hush about its publicly reachable address using
|
You can set multiple local addresses with -externalip. The
|
||||||
this option, and this can be a .onion address. Given the above
|
one that will be rumoured to a particular peer is the most
|
||||||
configuration, you can find your onion address in
|
compatible one and also using heuristics, e.g. the address
|
||||||
/var/lib/tor/hush-service/hostname. Onion addresses are given
|
with the most incoming connections, etc.
|
||||||
preference for your node to advertize itself with, for connections
|
|
||||||
coming from unroutable addresses (such as 127.0.0.1, where the
|
|
||||||
Tor proxy typically runs).
|
|
||||||
|
|
||||||
-listen You'll need to enable listening for incoming connections, as this
|
-listen You'll need to enable listening for incoming connections, as this
|
||||||
is off by default behind a proxy.
|
is off by default behind a proxy.
|
||||||
|
|
||||||
-discover When -externalip is specified, no attempt is made to discover local
|
-discover When -externalip is specified, no attempt is made to discover local
|
||||||
IPv4 or IPv6 addresses. If you want to run a dual stack, reachable
|
IPv4 or IPv6 addresses. If you want to run a dual stack, reachable
|
||||||
from both Tor and IPv4 (or IPv6), you'll need to either pass your
|
from both Tor and IPv4 (or IPv6), you'll need to either pass your
|
||||||
other addresses using -externalip, or explicitly enable -discover.
|
other addresses using -externalip, or explicitly enable -discover.
|
||||||
Note that both addresses of a dual-stack system may be easily
|
Note that both addresses of a dual-stack system may be easily
|
||||||
linkable using traffic analysis.
|
linkable using traffic analysis.
|
||||||
|
|
||||||
In a typical situation, where you're only reachable via Tor, this should suffice:
|
In a typical situation, where you're only reachable via Tor, this should suffice:
|
||||||
|
|
||||||
./hushd -proxy=127.0.0.1:9050 -externalip=hushc0de123.onion -listen
|
./hushd -proxy=127.0.0.1:9050 -externalip=7zvj7a2imdgkdbg4f2dryd5rgtrn7upivr5eeij4cicjh65pooxeshid.onion -listen
|
||||||
|
|
||||||
(obviously, replace the Onion address with your own). Currently only v2 HS's are supported.
|
(obviously, replace the .onion address with your own). It should be noted that you still
|
||||||
It should be noted that you still listen on all devices and another node could establish a clearnet connection, when knowing
|
listen on all devices and another node could establish a clearnet connection, when knowing
|
||||||
your address. To mitigate this, additionally bind the address of your Tor proxy:
|
your address. To mitigate this, additionally bind the address of your Tor proxy:
|
||||||
|
|
||||||
./hushd ... -bind=127.0.0.1
|
./hushd ... -bind=127.0.0.1
|
||||||
|
|
||||||
If you don't care too much about hiding your node, and want to be reachable on IPv4
|
If you don't care too much about hiding your node, and want to be reachable on IPv4
|
||||||
as well, use `discover` instead:
|
as well, use `discover` instead:
|
||||||
|
|
||||||
./hushd ... -discover
|
./hushd ... -discover
|
||||||
|
|
||||||
and open port 18030 on your firewall.
|
and open port 18030 on your firewall (or use port mapping, i.e., `-upnp` or `-natpmp`).
|
||||||
|
|
||||||
If you only want to use Tor to reach onion addresses, but not use it as a proxy
|
If you only want to use Tor to reach .onion addresses, but not use it as a proxy
|
||||||
for normal IPv4/IPv6 communication, use:
|
for normal IPv4/IPv6 communication, use:
|
||||||
|
|
||||||
./hushd -onion=127.0.0.1:9050 -externalip=hushc0de123.onion -discover
|
./hushd -onion=127.0.0.1:9050 -externalip=7zvj7a2imdgkdbg4f2dryd5rgtrn7upivr5eeij4cicjh65pooxeshid.onion -discover
|
||||||
|
|
||||||
|
## 4. Privacy recommendations
|
||||||
|
|
||||||
3. Automatically listen on Tor
|
- Do not add anything but Hush ports to the onion service created in section 3.
|
||||||
--------------------------------
|
If you run a web service too, create a new onion service for that.
|
||||||
|
Otherwise it is trivial to link them, which may reduce privacy. Onion
|
||||||
Starting with Tor version 0.2.7.1 it is possible, through Tor's control socket
|
services created automatically (as in section 2) always have only one port
|
||||||
API, to create and destroy 'ephemeral' hidden services programmatically.
|
open.
|
||||||
Hush has been updated to make use of this.
|
|
||||||
|
|
||||||
This means that if Tor is running (and proper authentication has been configured),
|
|
||||||
Hush automatically creates a hidden service to listen on. Hush will also use Tor
|
|
||||||
automatically to connect to other .onion nodes if the control socket can be
|
|
||||||
successfully opened. This will positively affect the number of available .onion
|
|
||||||
nodes and their usage.
|
|
||||||
|
|
||||||
This new feature is enabled by default if Hush is listening (`-listen`), and
|
|
||||||
requires a Tor connection to work. It can be explicitly disabled with `-listenonion=0`
|
|
||||||
and, if not disabled, configured using the `-torcontrol` and `-torpassword` settings.
|
|
||||||
To show verbose debugging information, pass `-debug=tor`.
|
|
||||||
|
|
||||||
Connecting to Tor's control socket API requires one of two authentication methods to be
|
|
||||||
configured. For cookie authentication the user running hushd must have write access
|
|
||||||
to the `CookieAuthFile` specified in Tor configuration. In some cases this is
|
|
||||||
preconfigured and the creation of a hidden service is automatic. If permission problems
|
|
||||||
are seen with `-debug=tor` they can be resolved by adding both the user running tor and
|
|
||||||
the user running hushd to the same group and setting permissions appropriately. On
|
|
||||||
Debian-based systems the user running hushd can be added to the debian-tor group,
|
|
||||||
which has the appropriate permissions. An alternative authentication method is the use
|
|
||||||
of the `-torpassword` flag and a `hash-password` which can be enabled and specified in
|
|
||||||
Tor configuration.
|
|
||||||
|
|
||||||
|
|
||||||
4. Connect to a Hush hidden server
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
To test your set-up, you might want to try connecting via Tor on a different computer to just a
|
|
||||||
a single Hush hidden server. Launch hushd as follows:
|
|
||||||
|
|
||||||
./hushd -onion=127.0.0.1:9050 -connect=fuckzookoie6wxgio.onion
|
|
||||||
|
|
||||||
Now use hush-cli to verify there is only a single peer connection.
|
|
||||||
|
|
||||||
hush-cli getpeerinfo
|
|
||||||
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"id" : 1,
|
|
||||||
"addr" : "zcashhoneypot.onion:18030",
|
|
||||||
...
|
|
||||||
"version" : 1987420,
|
|
||||||
"subver" : "/GoldenSandtrout:3.6.0/",
|
|
||||||
...
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
To connect to multiple Tor nodes, use:
|
|
||||||
|
|
||||||
./hushd -onion=127.0.0.1:9050 -addnode=hushbeef123.onion -dnsseed=0 -onlynet=onion
|
|
||||||
|
|||||||
@@ -4,9 +4,7 @@
|
|||||||
# Distributed under the GPLv3 software license, see the accompanying
|
# Distributed under the GPLv3 software license, see the accompanying
|
||||||
# file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
# file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
|
|
||||||
#
|
|
||||||
# Test rpc http basics
|
# Test rpc http basics
|
||||||
#
|
|
||||||
|
|
||||||
from test_framework.test_framework import BitcoinTestFramework
|
from test_framework.test_framework import BitcoinTestFramework
|
||||||
from test_framework.util import assert_equal, start_nodes
|
from test_framework.util import assert_equal, start_nodes
|
||||||
@@ -97,7 +95,7 @@ class HTTPBasicsTest (BitcoinTestFramework):
|
|||||||
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
|
conn.request('POST', '/', '{"method": "getbestblockhash"}', headers)
|
||||||
out1 = conn.getresponse().read()
|
out1 = conn.getresponse().read()
|
||||||
assert_equal('"error":null' in out1, True)
|
assert_equal('"error":null' in out1, True)
|
||||||
assert_equal(conn.sock!=None, True) # connection must be closed because bitcoind should use keep-alive by default
|
assert_equal(conn.sock!=None, True) # connection must be closed because hushd should use keep-alive by default
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
HTTPBasicsTest().main()
|
HTTPBasicsTest().main()
|
||||||
|
|||||||
@@ -116,8 +116,8 @@ class TestNode(NodeConnCB):
|
|||||||
class AcceptBlockTest(BitcoinTestFramework):
|
class AcceptBlockTest(BitcoinTestFramework):
|
||||||
def add_options(self, parser):
|
def add_options(self, parser):
|
||||||
parser.add_option("--testbinary", dest="testbinary",
|
parser.add_option("--testbinary", dest="testbinary",
|
||||||
default=os.getenv("BITCOIND", "bitcoind"),
|
default=os.getenv("BITCOIND", "hushd"),
|
||||||
help="bitcoind binary to test")
|
help="hushd binary to test")
|
||||||
|
|
||||||
def setup_chain(self):
|
def setup_chain(self):
|
||||||
initialize_chain_clean(self.options.tmpdir, 2)
|
initialize_chain_clean(self.options.tmpdir, 2)
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ import os
|
|||||||
|
|
||||||
'''
|
'''
|
||||||
Test plan:
|
Test plan:
|
||||||
- Start bitcoind's with different proxy configurations
|
- Start hushd's with different proxy configurations
|
||||||
- Use addnode to initiate connections
|
- Use addnode to initiate connections
|
||||||
- Verify that proxies are connected to, and the right connection command is given
|
- Verify that proxies are connected to, and the right connection command is given
|
||||||
- Proxy configurations to test on bitcoind side:
|
- Proxy configurations to test on hushd side:
|
||||||
- `-proxy` (proxy everything)
|
- `-proxy` (proxy everything)
|
||||||
- `-onion` (proxy just onions)
|
- `-onion` (proxy just onions)
|
||||||
- `-proxyrandomize` Circuit randomization
|
- `-proxyrandomize` Circuit randomization
|
||||||
@@ -26,8 +26,8 @@ Test plan:
|
|||||||
- proxy on IPv6
|
- proxy on IPv6
|
||||||
|
|
||||||
- Create various proxies (as threads)
|
- Create various proxies (as threads)
|
||||||
- Create bitcoinds that connect to them
|
- Create hushds that connect to them
|
||||||
- Manipulate the bitcoinds using addnode (onetry) an observe effects
|
- Manipulate the hushds using addnode (onetry) an observe effects
|
||||||
|
|
||||||
addnode connect to IPv4
|
addnode connect to IPv4
|
||||||
addnode connect to IPv6
|
addnode connect to IPv6
|
||||||
@@ -78,7 +78,7 @@ class ProxyTest(BitcoinTestFramework):
|
|||||||
node.addnode("15.61.23.23:1234", "onetry")
|
node.addnode("15.61.23.23:1234", "onetry")
|
||||||
cmd = proxies[0].queue.get()
|
cmd = proxies[0].queue.get()
|
||||||
assert(isinstance(cmd, Socks5Command))
|
assert(isinstance(cmd, Socks5Command))
|
||||||
# Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6
|
# Note: hushd's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6
|
||||||
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
|
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
|
||||||
assert_equal(cmd.addr, "15.61.23.23")
|
assert_equal(cmd.addr, "15.61.23.23")
|
||||||
assert_equal(cmd.port, 1234)
|
assert_equal(cmd.port, 1234)
|
||||||
@@ -91,7 +91,7 @@ class ProxyTest(BitcoinTestFramework):
|
|||||||
node.addnode("[1233:3432:2434:2343:3234:2345:6546:4534]:5443", "onetry")
|
node.addnode("[1233:3432:2434:2343:3234:2345:6546:4534]:5443", "onetry")
|
||||||
cmd = proxies[1].queue.get()
|
cmd = proxies[1].queue.get()
|
||||||
assert(isinstance(cmd, Socks5Command))
|
assert(isinstance(cmd, Socks5Command))
|
||||||
# Note: bitcoind's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6
|
# Note: hushd's SOCKS5 implementation only sends atyp DOMAINNAME, even if connecting directly to IPv4/IPv6
|
||||||
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
|
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
|
||||||
assert_equal(cmd.addr, "1233:3432:2434:2343:3234:2345:6546:4534")
|
assert_equal(cmd.addr, "1233:3432:2434:2343:3234:2345:6546:4534")
|
||||||
assert_equal(cmd.port, 5443)
|
assert_equal(cmd.port, 5443)
|
||||||
@@ -102,24 +102,24 @@ class ProxyTest(BitcoinTestFramework):
|
|||||||
|
|
||||||
if test_onion:
|
if test_onion:
|
||||||
# Test: outgoing onion connection through node
|
# Test: outgoing onion connection through node
|
||||||
node.addnode("bitcoinostk4e4re.onion:8333", "onetry")
|
node.addnode("hushv3h6mbxd2pptj42reko3jcexcgnz5zvp3mqcu6myto3jhhn4yzyd.onion:18030", "onetry")
|
||||||
cmd = proxies[2].queue.get()
|
cmd = proxies[2].queue.get()
|
||||||
assert(isinstance(cmd, Socks5Command))
|
assert(isinstance(cmd, Socks5Command))
|
||||||
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
|
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
|
||||||
assert_equal(cmd.addr, "bitcoinostk4e4re.onion")
|
assert_equal(cmd.addr, "hushv3h6mbxd2pptj42reko3jcexcgnz5zvp3mqcu6myto3jhhn4yzyd.onion")
|
||||||
assert_equal(cmd.port, 8333)
|
assert_equal(cmd.port, 18030)
|
||||||
if not auth:
|
if not auth:
|
||||||
assert_equal(cmd.username, None)
|
assert_equal(cmd.username, None)
|
||||||
assert_equal(cmd.password, None)
|
assert_equal(cmd.password, None)
|
||||||
rv.append(cmd)
|
rv.append(cmd)
|
||||||
|
|
||||||
# Test: outgoing DNS name connection through node
|
# Test: outgoing DNS name connection through node
|
||||||
node.addnode("node.noumenon:8333", "onetry")
|
node.addnode("node.noumenon:18030", "onetry")
|
||||||
cmd = proxies[3].queue.get()
|
cmd = proxies[3].queue.get()
|
||||||
assert(isinstance(cmd, Socks5Command))
|
assert(isinstance(cmd, Socks5Command))
|
||||||
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
|
assert_equal(cmd.atyp, AddressType.DOMAINNAME)
|
||||||
assert_equal(cmd.addr, "node.noumenon")
|
assert_equal(cmd.addr, "node.noumenon")
|
||||||
assert_equal(cmd.port, 8333)
|
assert_equal(cmd.port, 18030)
|
||||||
if not auth:
|
if not auth:
|
||||||
assert_equal(cmd.username, None)
|
assert_equal(cmd.username, None)
|
||||||
assert_equal(cmd.password, None)
|
assert_equal(cmd.password, None)
|
||||||
|
|||||||
@@ -984,24 +984,6 @@ class msg_addr(object):
|
|||||||
return "msg_addr(addrs=%s)" % (repr(self.addrs))
|
return "msg_addr(addrs=%s)" % (repr(self.addrs))
|
||||||
|
|
||||||
|
|
||||||
class msg_alert(object):
|
|
||||||
command = "alert"
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.alert = CAlert()
|
|
||||||
|
|
||||||
def deserialize(self, f):
|
|
||||||
self.alert = CAlert()
|
|
||||||
self.alert.deserialize(f)
|
|
||||||
|
|
||||||
def serialize(self):
|
|
||||||
r = ""
|
|
||||||
r += self.alert.serialize()
|
|
||||||
return r
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "msg_alert(alert=%s)" % (repr(self.alert), )
|
|
||||||
|
|
||||||
|
|
||||||
class msg_inv(object):
|
class msg_inv(object):
|
||||||
command = "inv"
|
command = "inv"
|
||||||
@@ -1370,7 +1352,6 @@ class NodeConn(asyncore.dispatcher):
|
|||||||
"version": msg_version,
|
"version": msg_version,
|
||||||
"verack": msg_verack,
|
"verack": msg_verack,
|
||||||
"addr": msg_addr,
|
"addr": msg_addr,
|
||||||
"alert": msg_alert,
|
|
||||||
"inv": msg_inv,
|
"inv": msg_inv,
|
||||||
"getdata": msg_getdata,
|
"getdata": msg_getdata,
|
||||||
"getblocks": msg_getblocks,
|
"getblocks": msg_getblocks,
|
||||||
|
|||||||
@@ -9,6 +9,12 @@ AM_CXXFLAGS = $(SAN_CXXFLAGS) $(HARDENED_CXXFLAGS) $(ERROR_CXXFLAGS)
|
|||||||
AM_CPPFLAGS = $(HARDENED_CPPFLAGS)
|
AM_CPPFLAGS = $(HARDENED_CPPFLAGS)
|
||||||
EXTRA_LIBRARIES =
|
EXTRA_LIBRARIES =
|
||||||
|
|
||||||
|
if ARCH_ARM
|
||||||
|
PLATFORM_VARIANT = armv8.1-a+crypto
|
||||||
|
else
|
||||||
|
PLATFORM_VARIANT = x86-64
|
||||||
|
endif
|
||||||
|
|
||||||
if EMBEDDED_LEVELDB
|
if EMBEDDED_LEVELDB
|
||||||
LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/include
|
LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/include
|
||||||
LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/helpers/memenv
|
LEVELDB_CPPFLAGS += -I$(srcdir)/leveldb/helpers/memenv
|
||||||
@@ -28,6 +34,7 @@ BITCOIN_CONFIG_INCLUDES=-I$(builddir)/config
|
|||||||
BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS)
|
BITCOIN_INCLUDES=-I$(builddir) -I$(builddir)/obj $(BDB_CPPFLAGS) $(BOOST_CPPFLAGS) $(LEVELDB_CPPFLAGS) $(CRYPTO_CFLAGS) $(SSL_CFLAGS)
|
||||||
|
|
||||||
BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include
|
BITCOIN_INCLUDES += -I$(srcdir)/secp256k1/include
|
||||||
|
BITCOIN_INCLUDES += -I$(srcdir)/cc/includes
|
||||||
BITCOIN_INCLUDES += -I$(srcdir)/cryptoconditions/include
|
BITCOIN_INCLUDES += -I$(srcdir)/cryptoconditions/include
|
||||||
BITCOIN_INCLUDES += -I$(srcdir)/cryptoconditions/src
|
BITCOIN_INCLUDES += -I$(srcdir)/cryptoconditions/src
|
||||||
BITCOIN_INCLUDES += -I$(srcdir)/cryptoconditions/src/asn
|
BITCOIN_INCLUDES += -I$(srcdir)/cryptoconditions/src/asn
|
||||||
@@ -63,13 +70,13 @@ LIBBITCOIN_WALLET=libbitcoin_wallet.a
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
$(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*)
|
$(LIBSECP256K1): $(wildcard secp256k1/src/*) $(wildcard secp256k1/include/*)
|
||||||
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -g "
|
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -march=$(PLATFORM_VARIANT) -g "
|
||||||
|
|
||||||
$(LIBUNIVALUE): $(wildcard univalue/lib/*)
|
$(LIBUNIVALUE): $(wildcard univalue/lib/*)
|
||||||
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -g "
|
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -march=$(PLATFORM_VARIANT) -g "
|
||||||
|
|
||||||
$(LIBCRYPTOCONDITIONS): $(wildcard cryptoconditions/src/*) $(wildcard cryptoconditions/include/*)
|
$(LIBCRYPTOCONDITIONS): $(wildcard cryptoconditions/src/*) $(wildcard cryptoconditions/include/*)
|
||||||
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -g "
|
$(AM_V_at)$(MAKE) $(AM_MAKEFLAGS) -C $(@D) $(@F) OPTFLAGS="-O2 -march=$(PLATFORM_VARIANT) -g "
|
||||||
|
|
||||||
# Make is not made aware of per-object dependencies to avoid limiting building parallelization
|
# Make is not made aware of per-object dependencies to avoid limiting building parallelization
|
||||||
# But to build the less dependent modules first, we manually select their order here:
|
# But to build the less dependent modules first, we manually select their order here:
|
||||||
@@ -122,7 +129,8 @@ BITCOIN_CORE_H = \
|
|||||||
addressindex.h \
|
addressindex.h \
|
||||||
spentindex.h \
|
spentindex.h \
|
||||||
addrman.h \
|
addrman.h \
|
||||||
alert.h \
|
attributes.h \
|
||||||
|
addrdb.h \
|
||||||
amount.h \
|
amount.h \
|
||||||
amqp/amqpabstractnotifier.h \
|
amqp/amqpabstractnotifier.h \
|
||||||
amqp/amqpconfig.h \
|
amqp/amqpconfig.h \
|
||||||
@@ -161,6 +169,7 @@ BITCOIN_CORE_H = \
|
|||||||
hash.h \
|
hash.h \
|
||||||
httprpc.h \
|
httprpc.h \
|
||||||
httpserver.h \
|
httpserver.h \
|
||||||
|
i2p.h \
|
||||||
init.h \
|
init.h \
|
||||||
key.h \
|
key.h \
|
||||||
key_io.h \
|
key_io.h \
|
||||||
@@ -175,10 +184,13 @@ BITCOIN_CORE_H = \
|
|||||||
mruset.h \
|
mruset.h \
|
||||||
net.h \
|
net.h \
|
||||||
netbase.h \
|
netbase.h \
|
||||||
|
netaddress.h \
|
||||||
|
netmessagemaker.h \
|
||||||
noui.h \
|
noui.h \
|
||||||
policy/fees.h \
|
policy/fees.h \
|
||||||
pow.h \
|
pow.h \
|
||||||
prevector.h \
|
prevector.h \
|
||||||
|
span.h \
|
||||||
primitives/block.h \
|
primitives/block.h \
|
||||||
primitives/transaction.h \
|
primitives/transaction.h \
|
||||||
protocol.h \
|
protocol.h \
|
||||||
@@ -218,8 +230,13 @@ BITCOIN_CORE_H = \
|
|||||||
uint252.h \
|
uint252.h \
|
||||||
undo.h \
|
undo.h \
|
||||||
util.h \
|
util.h \
|
||||||
|
util/readwritefile.h \
|
||||||
|
util/sock.h \
|
||||||
|
util/string.h \
|
||||||
|
util/spanparsing.h \
|
||||||
|
util/strencodings.h \
|
||||||
utilmoneystr.h \
|
utilmoneystr.h \
|
||||||
utilstrencodings.h \
|
# utilstrencodings.h \
|
||||||
utiltime.h \
|
utiltime.h \
|
||||||
validationinterface.h \
|
validationinterface.h \
|
||||||
version.h \
|
version.h \
|
||||||
@@ -249,10 +266,8 @@ libbitcoin_util_a-clientversion.$(OBJEXT): obj/build.h
|
|||||||
libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS)
|
libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(EVENT_CFLAGS) $(EVENT_PTHREADS_CFLAGS)
|
||||||
libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||||
libbitcoin_server_a_SOURCES = \
|
libbitcoin_server_a_SOURCES = \
|
||||||
sendalert.cpp \
|
|
||||||
addrman.cpp \
|
addrman.cpp \
|
||||||
alert.cpp \
|
addrdb.cpp \
|
||||||
alertkeys.h \
|
|
||||||
asyncrpcoperation.cpp \
|
asyncrpcoperation.cpp \
|
||||||
asyncrpcqueue.cpp \
|
asyncrpcqueue.cpp \
|
||||||
bloom.cpp \
|
bloom.cpp \
|
||||||
@@ -287,6 +302,7 @@ libbitcoin_server_a_SOURCES = \
|
|||||||
deprecation.cpp \
|
deprecation.cpp \
|
||||||
httprpc.cpp \
|
httprpc.cpp \
|
||||||
httpserver.cpp \
|
httpserver.cpp \
|
||||||
|
i2p.cpp \
|
||||||
init.cpp \
|
init.cpp \
|
||||||
dbwrapper.cpp \
|
dbwrapper.cpp \
|
||||||
main.cpp \
|
main.cpp \
|
||||||
@@ -361,6 +377,8 @@ crypto_libbitcoin_crypto_a_SOURCES = \
|
|||||||
crypto/ripemd160.h \
|
crypto/ripemd160.h \
|
||||||
crypto/sha1.cpp \
|
crypto/sha1.cpp \
|
||||||
crypto/sha1.h \
|
crypto/sha1.h \
|
||||||
|
crypto/sha3.cpp \
|
||||||
|
crypto/sha3.h \
|
||||||
crypto/sha256.cpp \
|
crypto/sha256.cpp \
|
||||||
crypto/sha256.h \
|
crypto/sha256.h \
|
||||||
crypto/sha512.cpp \
|
crypto/sha512.cpp \
|
||||||
@@ -401,6 +419,7 @@ libbitcoin_common_a_SOURCES = \
|
|||||||
key.cpp \
|
key.cpp \
|
||||||
key_io.cpp \
|
key_io.cpp \
|
||||||
keystore.cpp \
|
keystore.cpp \
|
||||||
|
netaddress.cpp \
|
||||||
netbase.cpp \
|
netbase.cpp \
|
||||||
metrics.cpp \
|
metrics.cpp \
|
||||||
primitives/block.cpp \
|
primitives/block.cpp \
|
||||||
@@ -439,9 +458,13 @@ libbitcoin_util_a_SOURCES = \
|
|||||||
uint256.cpp \
|
uint256.cpp \
|
||||||
util.cpp \
|
util.cpp \
|
||||||
utilmoneystr.cpp \
|
utilmoneystr.cpp \
|
||||||
utilstrencodings.cpp \
|
|
||||||
utiltime.cpp \
|
utiltime.cpp \
|
||||||
|
util/strencodings.cpp \
|
||||||
util/asmap.cpp \
|
util/asmap.cpp \
|
||||||
|
util/sock.cpp \
|
||||||
|
util/spanparsing.cpp \
|
||||||
|
util/string.cpp \
|
||||||
|
util/readwritefile.cpp \
|
||||||
$(BITCOIN_CORE_H) \
|
$(BITCOIN_CORE_H) \
|
||||||
$(LIBZCASH_H)
|
$(LIBZCASH_H)
|
||||||
|
|
||||||
@@ -671,6 +694,8 @@ clean-local:
|
|||||||
-$(MAKE) -C univalue clean
|
-$(MAKE) -C univalue clean
|
||||||
rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno
|
rm -f leveldb/*/*.gcno leveldb/helpers/memenv/*.gcno
|
||||||
-rm -f config.h
|
-rm -f config.h
|
||||||
|
-rm -f *.a
|
||||||
|
-rm -f *.so
|
||||||
|
|
||||||
.rc.o:
|
.rc.o:
|
||||||
@test -f $(WINDRES)
|
@test -f $(WINDRES)
|
||||||
|
|||||||
122
src/addrdb.cpp
Normal file
122
src/addrdb.cpp
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
|
// Copyright (c) 2009-2016 The Bitcoin Core developers
|
||||||
|
// Copyright (c) 2016-2022 The Hush developers
|
||||||
|
// Distributed under the GPLv3 software license, see the accompanying
|
||||||
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
|
|
||||||
|
#include "addrdb.h"
|
||||||
|
#include "addrman.h"
|
||||||
|
#include "chainparams.h"
|
||||||
|
#include "clientversion.h"
|
||||||
|
#include "fs.h"
|
||||||
|
#include "hash.h"
|
||||||
|
#include "random.h"
|
||||||
|
#include "streams.h"
|
||||||
|
#include "tinyformat.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
template <typename Stream, typename Data>
|
||||||
|
bool SerializeDB(Stream& stream, const Data& data)
|
||||||
|
{
|
||||||
|
// Write and commit header, data
|
||||||
|
try {
|
||||||
|
CHashWriter hasher(stream.GetType(), stream.GetVersion());
|
||||||
|
stream << FLATDATA(Params().MessageStart()) << data;
|
||||||
|
hasher << FLATDATA(Params().MessageStart()) << data;
|
||||||
|
stream << hasher.GetHash();
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
return error("%s: Serialize or I/O error - %s", __func__, e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Data>
|
||||||
|
bool SerializeFileDB(const std::string& prefix, const fs::path& path, const Data& data)
|
||||||
|
{
|
||||||
|
// Generate random temporary filename
|
||||||
|
unsigned short randv = 0;
|
||||||
|
GetRandBytes((unsigned char*)&randv, sizeof(randv));
|
||||||
|
std::string tmpfn = strprintf("%s.%04x", prefix, randv);
|
||||||
|
|
||||||
|
// open temp output file, and associate with CAutoFile
|
||||||
|
fs::path pathTmp = GetDataDir() / tmpfn;
|
||||||
|
FILE *file = fsbridge::fopen(pathTmp, "wb");
|
||||||
|
CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
|
||||||
|
if (fileout.IsNull())
|
||||||
|
return error("%s: Failed to open file %s", __func__, pathTmp.string());
|
||||||
|
|
||||||
|
// Serialize
|
||||||
|
if (!SerializeDB(fileout, data)) return false;
|
||||||
|
FileCommit(fileout.Get());
|
||||||
|
fileout.fclose();
|
||||||
|
|
||||||
|
// replace existing file, if any, with new file
|
||||||
|
if (!RenameOver(pathTmp, path))
|
||||||
|
return error("%s: Rename-into-place failed", __func__);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Stream, typename Data>
|
||||||
|
bool DeserializeDB(Stream& stream, Data& data, bool fCheckSum = true)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
CHashVerifier<Stream> verifier(&stream);
|
||||||
|
// de-serialize file header (network specific magic number) and ..
|
||||||
|
unsigned char pchMsgTmp[4];
|
||||||
|
verifier >> FLATDATA(pchMsgTmp);
|
||||||
|
// ... verify the network matches ours
|
||||||
|
if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
|
||||||
|
return error("%s: Invalid network magic number", __func__);
|
||||||
|
|
||||||
|
// de-serialize data
|
||||||
|
verifier >> data;
|
||||||
|
|
||||||
|
// verify checksum
|
||||||
|
if (fCheckSum) {
|
||||||
|
uint256 hashTmp;
|
||||||
|
stream >> hashTmp;
|
||||||
|
if (hashTmp != verifier.GetHash()) {
|
||||||
|
return error("%s: Checksum mismatch, data corrupted", __func__);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
return error("%s: Deserialize or I/O error - %s", __func__, e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Data>
|
||||||
|
bool DeserializeFileDB(const fs::path& path, Data& data)
|
||||||
|
{
|
||||||
|
// open input file, and associate with CAutoFile
|
||||||
|
FILE *file = fsbridge::fopen(path, "rb");
|
||||||
|
CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
|
||||||
|
if (filein.IsNull())
|
||||||
|
return error("%s: Failed to open file %s", __func__, path.string());
|
||||||
|
|
||||||
|
return DeserializeDB(filein, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CBanDB::CBanDB()
|
||||||
|
{
|
||||||
|
pathBanlist = GetDataDir() / "banlist.dat";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBanDB::Write(const banmap_t& banSet)
|
||||||
|
{
|
||||||
|
return SerializeFileDB("banlist", pathBanlist, banSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CBanDB::Read(banmap_t& banSet)
|
||||||
|
{
|
||||||
|
return DeserializeFileDB(pathBanlist, banSet);
|
||||||
|
}
|
||||||
|
|
||||||
90
src/addrdb.h
Normal file
90
src/addrdb.h
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
|
// Copyright (c) 2009-2016 The Bitcoin Core developers
|
||||||
|
// Distributed under the GPLv3 software license, see the accompanying
|
||||||
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
|
|
||||||
|
#ifndef HUSH_ADDRDB_H
|
||||||
|
#define HUSH_ADDRDB_H
|
||||||
|
|
||||||
|
#include "fs.h"
|
||||||
|
#include "serialize.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
class CSubNet;
|
||||||
|
class CAddrMan;
|
||||||
|
class CDataStream;
|
||||||
|
|
||||||
|
typedef enum BanReason
|
||||||
|
{
|
||||||
|
BanReasonUnknown = 0,
|
||||||
|
BanReasonNodeMisbehaving = 1,
|
||||||
|
BanReasonManuallyAdded = 2
|
||||||
|
} BanReason;
|
||||||
|
|
||||||
|
class CBanEntry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const int CURRENT_VERSION=1;
|
||||||
|
int nVersion;
|
||||||
|
int64_t nCreateTime;
|
||||||
|
int64_t nBanUntil;
|
||||||
|
uint8_t banReason;
|
||||||
|
|
||||||
|
CBanEntry()
|
||||||
|
{
|
||||||
|
SetNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit CBanEntry(int64_t nCreateTimeIn)
|
||||||
|
{
|
||||||
|
SetNull();
|
||||||
|
nCreateTime = nCreateTimeIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
ADD_SERIALIZE_METHODS;
|
||||||
|
|
||||||
|
template <typename Stream, typename Operation>
|
||||||
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||||
|
READWRITE(this->nVersion);
|
||||||
|
READWRITE(nCreateTime);
|
||||||
|
READWRITE(nBanUntil);
|
||||||
|
READWRITE(banReason);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNull()
|
||||||
|
{
|
||||||
|
nVersion = CBanEntry::CURRENT_VERSION;
|
||||||
|
nCreateTime = 0;
|
||||||
|
nBanUntil = 0;
|
||||||
|
banReason = BanReasonUnknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string banReasonToString() const
|
||||||
|
{
|
||||||
|
switch (banReason) {
|
||||||
|
case BanReasonNodeMisbehaving:
|
||||||
|
return "node misbehaving";
|
||||||
|
case BanReasonManuallyAdded:
|
||||||
|
return "manually added";
|
||||||
|
default:
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::map<CSubNet, CBanEntry> banmap_t;
|
||||||
|
|
||||||
|
/** Access to the banlist database (banlist.dat) */
|
||||||
|
class CBanDB
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
fs::path pathBanlist;
|
||||||
|
public:
|
||||||
|
CBanDB();
|
||||||
|
bool Write(const banmap_t& banSet);
|
||||||
|
bool Read(banmap_t& banSet);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HUSH_ADDRDB_H
|
||||||
319
src/addrman.cpp
319
src/addrman.cpp
@@ -23,6 +23,7 @@
|
|||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "serialize.h"
|
#include "serialize.h"
|
||||||
#include "streams.h"
|
#include "streams.h"
|
||||||
|
#include "init.h"
|
||||||
|
|
||||||
int CAddrInfo::GetTriedBucket(const uint256& nKey, const std::vector<bool> &asmap) const
|
int CAddrInfo::GetTriedBucket(const uint256& nKey, const std::vector<bool> &asmap) const
|
||||||
{
|
{
|
||||||
@@ -53,6 +54,9 @@ int CAddrInfo::GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) co
|
|||||||
|
|
||||||
bool CAddrInfo::IsTerrible(int64_t nNow) const
|
bool CAddrInfo::IsTerrible(int64_t nNow) const
|
||||||
{
|
{
|
||||||
|
if (fLocal) //never remove local addresses
|
||||||
|
return false;
|
||||||
|
|
||||||
if (nLastTry && nLastTry >= nNow - 60) // never remove things tried in the last minute
|
if (nLastTry && nLastTry >= nNow - 60) // never remove things tried in the last minute
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -71,6 +75,14 @@ bool CAddrInfo::IsTerrible(int64_t nNow) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CAddrInfo::IsJustTried(int64_t nNow) const
|
||||||
|
{
|
||||||
|
if (nLastTry && nLastTry >= nNow - 60)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
double CAddrInfo::GetChance(int64_t nNow) const
|
double CAddrInfo::GetChance(int64_t nNow) const
|
||||||
{
|
{
|
||||||
double fChance = 1.0;
|
double fChance = 1.0;
|
||||||
@@ -95,24 +107,30 @@ double CAddrInfo::GetChance(int64_t nNow) const
|
|||||||
|
|
||||||
CAddrInfo* CAddrMan::Find(const CNetAddr& addr, int* pnId)
|
CAddrInfo* CAddrMan::Find(const CNetAddr& addr, int* pnId)
|
||||||
{
|
{
|
||||||
std::map<CNetAddr, int>::iterator it = mapAddr.find(addr);
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
|
const auto it = mapAddr.find(addr);
|
||||||
if (it == mapAddr.end())
|
if (it == mapAddr.end())
|
||||||
return NULL;
|
return nullptr;
|
||||||
if (pnId)
|
if (pnId)
|
||||||
*pnId = (*it).second;
|
*pnId = (*it).second;
|
||||||
std::map<int, CAddrInfo>::iterator it2 = mapInfo.find((*it).second);
|
const auto it2 = mapInfo.find((*it).second);
|
||||||
if (it2 != mapInfo.end())
|
if (it2 != mapInfo.end())
|
||||||
return &(*it2).second;
|
return &(*it2).second;
|
||||||
return NULL;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CAddrInfo* CAddrMan::Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId)
|
CAddrInfo* CAddrMan::Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId)
|
||||||
{
|
{
|
||||||
int nId = nIdCount++;
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
|
int nId = nIdCount;
|
||||||
mapInfo[nId] = CAddrInfo(addr, addrSource);
|
mapInfo[nId] = CAddrInfo(addr, addrSource);
|
||||||
mapAddr[addr] = nId;
|
mapAddr[addr] = nId;
|
||||||
mapInfo[nId].nRandomPos = vRandom.size();
|
mapInfo[nId].nRandomPos = vRandom.size();
|
||||||
vRandom.push_back(nId);
|
vRandom.push_back(nId);
|
||||||
|
nNew++;
|
||||||
|
nIdCount++;
|
||||||
if (pnId)
|
if (pnId)
|
||||||
*pnId = nId;
|
*pnId = nId;
|
||||||
return &mapInfo[nId];
|
return &mapInfo[nId];
|
||||||
@@ -120,6 +138,8 @@ CAddrInfo* CAddrMan::Create(const CAddress& addr, const CNetAddr& addrSource, in
|
|||||||
|
|
||||||
void CAddrMan::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2)
|
void CAddrMan::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2)
|
||||||
{
|
{
|
||||||
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
if (nRndPos1 == nRndPos2)
|
if (nRndPos1 == nRndPos2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -128,11 +148,13 @@ void CAddrMan::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2)
|
|||||||
int nId1 = vRandom[nRndPos1];
|
int nId1 = vRandom[nRndPos1];
|
||||||
int nId2 = vRandom[nRndPos2];
|
int nId2 = vRandom[nRndPos2];
|
||||||
|
|
||||||
assert(mapInfo.count(nId1) == 1);
|
const auto it_1{mapInfo.find(nId1)};
|
||||||
assert(mapInfo.count(nId2) == 1);
|
const auto it_2{mapInfo.find(nId2)};
|
||||||
|
assert(it_1 != mapInfo.end());
|
||||||
|
assert(it_2 != mapInfo.end());
|
||||||
|
|
||||||
mapInfo[nId1].nRandomPos = nRndPos2;
|
it_1->second.nRandomPos = nRndPos2;
|
||||||
mapInfo[nId2].nRandomPos = nRndPos1;
|
it_2->second.nRandomPos = nRndPos1;
|
||||||
|
|
||||||
vRandom[nRndPos1] = nId2;
|
vRandom[nRndPos1] = nId2;
|
||||||
vRandom[nRndPos2] = nId1;
|
vRandom[nRndPos2] = nId1;
|
||||||
@@ -140,41 +162,57 @@ void CAddrMan::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2)
|
|||||||
|
|
||||||
void CAddrMan::Delete(int nId)
|
void CAddrMan::Delete(int nId)
|
||||||
{
|
{
|
||||||
assert(mapInfo.count(nId) != 0);
|
AssertLockHeld(cs);
|
||||||
CAddrInfo& info = mapInfo[nId];
|
|
||||||
assert(!info.fInTried);
|
const auto it{mapInfo.find(nId)};
|
||||||
assert(info.nRefCount == 0);
|
if (it != mapInfo.end()) {
|
||||||
|
CAddrInfo& info = (*it).second;
|
||||||
|
assert(!info.fInTried);
|
||||||
|
assert(info.nRefCount == 0);
|
||||||
|
|
||||||
|
SwapRandom(info.nRandomPos, vRandom.size() - 1);
|
||||||
|
vRandom.pop_back();
|
||||||
|
mapAddr.erase(info);
|
||||||
|
mapInfo.erase(nId);
|
||||||
|
nNew--;
|
||||||
|
}
|
||||||
|
|
||||||
SwapRandom(info.nRandomPos, vRandom.size() - 1);
|
|
||||||
vRandom.pop_back();
|
|
||||||
mapAddr.erase(info);
|
|
||||||
mapInfo.erase(nId);
|
|
||||||
nNew--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAddrMan::ClearNew(int nUBucket, int nUBucketPos)
|
void CAddrMan::ClearNew(int nUBucket, int nUBucketPos)
|
||||||
{
|
{
|
||||||
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
// if there is an entry in the specified bucket, delete it.
|
// if there is an entry in the specified bucket, delete it.
|
||||||
if (vvNew[nUBucket][nUBucketPos] != -1) {
|
if (vvNew[nUBucket][nUBucketPos] != -1) {
|
||||||
int nIdDelete = vvNew[nUBucket][nUBucketPos];
|
int nIdDelete = vvNew[nUBucket][nUBucketPos];
|
||||||
CAddrInfo& infoDelete = mapInfo[nIdDelete];
|
const auto it{mapInfo.find(nIdDelete)};
|
||||||
assert(infoDelete.nRefCount > 0);
|
if (it != mapInfo.end()) {
|
||||||
infoDelete.nRefCount--;
|
CAddrInfo& infoDelete = (*it).second;
|
||||||
vvNew[nUBucket][nUBucketPos] = -1;
|
assert(infoDelete.nRefCount > 0);
|
||||||
if (infoDelete.nRefCount == 0) {
|
infoDelete.nRefCount--;
|
||||||
Delete(nIdDelete);
|
vvNew[nUBucket][nUBucketPos] = -1;
|
||||||
|
if (infoDelete.nRefCount == 0) {
|
||||||
|
Delete(nIdDelete);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAddrMan::MakeTried(CAddrInfo& info, int nId)
|
void CAddrMan::MakeTried(CAddrInfo& info, int nId)
|
||||||
{
|
{
|
||||||
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
// remove the entry from all new buckets
|
// remove the entry from all new buckets
|
||||||
for (int bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) {
|
const int start_bucket{info.GetNewBucket(nKey, m_asmap)};
|
||||||
int pos = info.GetBucketPosition(nKey, true, bucket);
|
for (int n = 0; n < ADDRMAN_NEW_BUCKET_COUNT; ++n) {
|
||||||
|
const int bucket{(start_bucket + n) % ADDRMAN_NEW_BUCKET_COUNT};
|
||||||
|
const int pos{info.GetBucketPosition(nKey, true, bucket)};
|
||||||
if (vvNew[bucket][pos] == nId) {
|
if (vvNew[bucket][pos] == nId) {
|
||||||
vvNew[bucket][pos] = -1;
|
vvNew[bucket][pos] = -1;
|
||||||
info.nRefCount--;
|
info.nRefCount--;
|
||||||
|
if (info.nRefCount == 0) break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nNew--;
|
nNew--;
|
||||||
@@ -215,67 +253,6 @@ void CAddrMan::MakeTried(CAddrInfo& info, int nId)
|
|||||||
info.fInTried = true;
|
info.fInTried = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAddrMan::Good_(const CService& addr, bool test_before_evict, int64_t nTime) {
|
|
||||||
int nId;
|
|
||||||
CAddrInfo* pinfo = Find(addr, &nId);
|
|
||||||
|
|
||||||
// if not found, bail out
|
|
||||||
if (!pinfo)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CAddrInfo& info = *pinfo;
|
|
||||||
|
|
||||||
// check whether we are talking about the exact same CService (including same port)
|
|
||||||
if (info != addr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// update info
|
|
||||||
info.nLastSuccess = nTime;
|
|
||||||
info.nLastTry = nTime;
|
|
||||||
info.nAttempts = 0;
|
|
||||||
// nTime is not updated here, to avoid leaking information about
|
|
||||||
// currently-connected peers.
|
|
||||||
|
|
||||||
// if it is already in the tried set, don't do anything else
|
|
||||||
if (info.fInTried)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// find a bucket it is in now
|
|
||||||
int nRnd = RandomInt(ADDRMAN_NEW_BUCKET_COUNT);
|
|
||||||
int nUBucket = -1;
|
|
||||||
for (unsigned int n = 0; n < ADDRMAN_NEW_BUCKET_COUNT; n++) {
|
|
||||||
int nB = (n + nRnd) % ADDRMAN_NEW_BUCKET_COUNT;
|
|
||||||
int nBpos = info.GetBucketPosition(nKey, true, nB);
|
|
||||||
if (vvNew[nB][nBpos] == nId) {
|
|
||||||
nUBucket = nB;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if no bucket is found, something bad happened;
|
|
||||||
// TODO: maybe re-add the node, but for now, just bail out
|
|
||||||
if (nUBucket == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// which tried bucket to move the entry to
|
|
||||||
int tried_bucket = info.GetTriedBucket(nKey,m_asmap);
|
|
||||||
int tried_bucket_pos = info.GetBucketPosition(nKey, false, tried_bucket);
|
|
||||||
|
|
||||||
// Will moving this address into tried evict another entry?
|
|
||||||
if (test_before_evict && (vvTried[tried_bucket][tried_bucket_pos] != -1)) {
|
|
||||||
LogPrint("addrman", "Collision inserting element into tried table, moving %s to m_tried_collisions=%d\n", addr.ToString(), m_tried_collisions.size());
|
|
||||||
if (m_tried_collisions.size() < ADDRMAN_SET_TRIED_COLLISION_SIZE) {
|
|
||||||
m_tried_collisions.insert(nId);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LogPrint("addrman", "Moving %s to tried\n", addr.ToString());
|
|
||||||
printf("%s: Moving %s to tried\n", __func__, addr.ToString().c_str() );
|
|
||||||
|
|
||||||
// move nId to the tried tables
|
|
||||||
MakeTried(info, nId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAddrMan::ResolveCollisions_() {
|
void CAddrMan::ResolveCollisions_() {
|
||||||
for (std::set<int>::iterator it = m_tried_collisions.begin(); it != m_tried_collisions.end();) {
|
for (std::set<int>::iterator it = m_tried_collisions.begin(); it != m_tried_collisions.end();) {
|
||||||
int id_new = *it;
|
int id_new = *it;
|
||||||
@@ -351,13 +328,59 @@ CAddrInfo CAddrMan::SelectTriedCollision_() {
|
|||||||
return mapInfo[id_old];
|
return mapInfo[id_old];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CAddrMan::Good_(const CService& addr, bool test_before_evict, int64_t nTime) {
|
||||||
|
int nId;
|
||||||
|
CAddrInfo* pinfo = Find(addr, &nId);
|
||||||
|
|
||||||
|
// if not found, bail out
|
||||||
|
if (!pinfo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CAddrInfo& info = *pinfo;
|
||||||
|
|
||||||
|
// check whether we are talking about the exact same CService (including same port)
|
||||||
|
if (info != addr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// update info
|
||||||
|
info.nLastSuccess = nTime;
|
||||||
|
info.nLastTry = nTime;
|
||||||
|
info.nAttempts = 0;
|
||||||
|
// nTime is not updated here, to avoid leaking information about
|
||||||
|
// currently-connected peers.
|
||||||
|
|
||||||
|
// if it is already in the tried set, don't do anything else
|
||||||
|
if (info.fInTried)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// find a bucket it is in now
|
||||||
|
int nRnd = RandomInt(ADDRMAN_NEW_BUCKET_COUNT);
|
||||||
|
int nUBucket = -1;
|
||||||
|
for (unsigned int n = 0; n < ADDRMAN_NEW_BUCKET_COUNT; n++) {
|
||||||
|
int nB = (n + nRnd) % ADDRMAN_NEW_BUCKET_COUNT;
|
||||||
|
int nBpos = info.GetBucketPosition(nKey, true, nB);
|
||||||
|
if (vvNew[nB][nBpos] == nId) {
|
||||||
|
nUBucket = nB;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no bucket is found, something bad happened;
|
||||||
|
// TODO: maybe re-add the node, but for now, just bail out
|
||||||
|
if (nUBucket == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LogPrint("addrman", "Moving %s to tried\n", addr.ToString());
|
||||||
|
|
||||||
|
// move nId to the tried tables
|
||||||
|
MakeTried(info, nId);
|
||||||
|
}
|
||||||
|
|
||||||
bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty)
|
bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty)
|
||||||
{
|
{
|
||||||
if (!addr.IsRoutable())
|
if (!addr.IsRoutable())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool fNew = false;
|
|
||||||
int nId;
|
int nId;
|
||||||
CAddrInfo* pinfo = Find(addr, &nId);
|
CAddrInfo* pinfo = Find(addr, &nId);
|
||||||
|
|
||||||
@@ -392,19 +415,20 @@ bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimeP
|
|||||||
} else {
|
} else {
|
||||||
pinfo = Create(addr, source, &nId);
|
pinfo = Create(addr, source, &nId);
|
||||||
pinfo->nTime = std::max((int64_t)0, (int64_t)pinfo->nTime - nTimePenalty);
|
pinfo->nTime = std::max((int64_t)0, (int64_t)pinfo->nTime - nTimePenalty);
|
||||||
nNew++;
|
|
||||||
fNew = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int nUBucket = pinfo->GetNewBucket(nKey, source, m_asmap);
|
int nUBucket = pinfo->GetNewBucket(nKey, source, m_asmap);
|
||||||
int nUBucketPos = pinfo->GetBucketPosition(nKey, true, nUBucket);
|
int nUBucketPos = pinfo->GetBucketPosition(nKey, true, nUBucket);
|
||||||
|
bool fInsert = vvNew[nUBucket][nUBucketPos] == -1;
|
||||||
if (vvNew[nUBucket][nUBucketPos] != nId) {
|
if (vvNew[nUBucket][nUBucketPos] != nId) {
|
||||||
bool fInsert = vvNew[nUBucket][nUBucketPos] == -1;
|
|
||||||
if (!fInsert) {
|
if (!fInsert) {
|
||||||
CAddrInfo& infoExisting = mapInfo[vvNew[nUBucket][nUBucketPos]];
|
const auto it{mapInfo.find(vvNew[nUBucket][nUBucketPos])};
|
||||||
if (infoExisting.IsTerrible() || (infoExisting.nRefCount > 1 && pinfo->nRefCount == 0)) {
|
if (it != mapInfo.end()) {
|
||||||
// Overwrite the existing new table entry.
|
CAddrInfo& infoExisting = (*it).second;
|
||||||
fInsert = true;
|
if (infoExisting.IsTerrible() || (infoExisting.nRefCount > 1 && pinfo->nRefCount == 0)) {
|
||||||
|
// Overwrite the existing new table entry.
|
||||||
|
fInsert = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fInsert) {
|
if (fInsert) {
|
||||||
@@ -417,7 +441,7 @@ bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimeP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fNew;
|
return fInsert;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAddrMan::Attempt_(const CService& addr, int64_t nTime)
|
void CAddrMan::Attempt_(const CService& addr, int64_t nTime)
|
||||||
@@ -457,7 +481,12 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
|
|||||||
(nTried > 0 && (nNew == 0 || RandomInt(2) == 0))) {
|
(nTried > 0 && (nNew == 0 || RandomInt(2) == 0))) {
|
||||||
// use a tried node
|
// use a tried node
|
||||||
double fChanceFactor = 1.0;
|
double fChanceFactor = 1.0;
|
||||||
|
double fReachableFactor = 1.0;
|
||||||
|
double fJustTried = 1.0;
|
||||||
while (1) {
|
while (1) {
|
||||||
|
if (ShutdownRequested()) //break loop on shutdown request
|
||||||
|
return CAddrInfo();
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int nKBucket = RandomInt(ADDRMAN_TRIED_BUCKET_COUNT);
|
int nKBucket = RandomInt(ADDRMAN_TRIED_BUCKET_COUNT);
|
||||||
int nKBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE);
|
int nKBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE);
|
||||||
@@ -472,14 +501,27 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
|
|||||||
int nId = vvTried[nKBucket][nKBucketPos];
|
int nId = vvTried[nKBucket][nKBucketPos];
|
||||||
assert(mapInfo.count(nId) == 1);
|
assert(mapInfo.count(nId) == 1);
|
||||||
CAddrInfo& info = mapInfo[nId];
|
CAddrInfo& info = mapInfo[nId];
|
||||||
if (RandomInt(1 << 30) < fChanceFactor * info.GetChance() * (1 << 30))
|
if (info.IsReachableNetwork()) {
|
||||||
|
//deprioritize unreachable networks
|
||||||
|
fReachableFactor = 0.25;
|
||||||
|
}
|
||||||
|
if (info.IsJustTried()) {
|
||||||
|
//deprioritize entries just tried
|
||||||
|
fJustTried = 0.10;
|
||||||
|
}
|
||||||
|
if (RandomInt(1 << 30) < fChanceFactor * fReachableFactor * fJustTried * info.GetChance() * (1 << 30))
|
||||||
return info;
|
return info;
|
||||||
fChanceFactor *= 1.2;
|
fChanceFactor *= 1.2;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// use a new node
|
// use a new node
|
||||||
double fChanceFactor = 1.0;
|
double fChanceFactor = 1.0;
|
||||||
|
double fReachableFactor = 1.0;
|
||||||
|
double fJustTried = 1.0;
|
||||||
while (1) {
|
while (1) {
|
||||||
|
if (ShutdownRequested()) //break loop on shutdown request
|
||||||
|
return CAddrInfo();
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int nUBucket = RandomInt(ADDRMAN_NEW_BUCKET_COUNT);
|
int nUBucket = RandomInt(ADDRMAN_NEW_BUCKET_COUNT);
|
||||||
int nUBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE);
|
int nUBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE);
|
||||||
@@ -494,7 +536,15 @@ CAddrInfo CAddrMan::Select_(bool newOnly)
|
|||||||
int nId = vvNew[nUBucket][nUBucketPos];
|
int nId = vvNew[nUBucket][nUBucketPos];
|
||||||
assert(mapInfo.count(nId) == 1);
|
assert(mapInfo.count(nId) == 1);
|
||||||
CAddrInfo& info = mapInfo[nId];
|
CAddrInfo& info = mapInfo[nId];
|
||||||
if (RandomInt(1 << 30) < fChanceFactor * info.GetChance() * (1 << 30))
|
if (info.IsReachableNetwork()) {
|
||||||
|
//deprioritize unreachable networks
|
||||||
|
fReachableFactor = 0.25;
|
||||||
|
}
|
||||||
|
if (info.IsJustTried()) {
|
||||||
|
//deprioritize entries just tried
|
||||||
|
fJustTried = 0.10;
|
||||||
|
}
|
||||||
|
if (RandomInt(1 << 30) < fChanceFactor * fReachableFactor * fJustTried * info.GetChance() * (1 << 30))
|
||||||
return info;
|
return info;
|
||||||
fChanceFactor *= 1.2;
|
fChanceFactor *= 1.2;
|
||||||
}
|
}
|
||||||
@@ -581,24 +631,59 @@ int CAddrMan::Check_()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void CAddrMan::GetAddr_(std::vector<CAddress>& vAddr)
|
void CAddrMan::GetAddr_(std::vector<CAddress>& vAddr, bool wants_addrv2)
|
||||||
{
|
{
|
||||||
unsigned int nNodes = ADDRMAN_GETADDR_MAX_PCT * vRandom.size() / 100;
|
unsigned int nNodes = ADDRMAN_GETADDR_MAX_PCT * vRandom.size() / 100;
|
||||||
if (nNodes > ADDRMAN_GETADDR_MAX)
|
if (nNodes > ADDRMAN_GETADDR_MAX)
|
||||||
nNodes = ADDRMAN_GETADDR_MAX;
|
nNodes = ADDRMAN_GETADDR_MAX;
|
||||||
|
|
||||||
|
int addrv2Nodes = nNodes/5;
|
||||||
|
int ipv4Nodes = 0;
|
||||||
|
int ipv6Nodes = 0;
|
||||||
|
int torNodes = 0;
|
||||||
|
int i2pNodes = 0;
|
||||||
|
int cjdnsNodes = 0;
|
||||||
|
|
||||||
|
// Randomize Nodes
|
||||||
|
for (unsigned int n = 0; n < vRandom.size(); n++) {
|
||||||
|
int nRndPos = RandomInt(vRandom.size() - n) + n;
|
||||||
|
SwapRandom(n, nRndPos);
|
||||||
|
}
|
||||||
|
|
||||||
// gather a list of random nodes, skipping those of low quality
|
// gather a list of random nodes, skipping those of low quality
|
||||||
for (unsigned int n = 0; n < vRandom.size(); n++) {
|
for (unsigned int n = 0; n < vRandom.size(); n++) {
|
||||||
if (vAddr.size() >= nNodes)
|
if (vAddr.size() >= nNodes)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
int nRndPos = RandomInt(vRandom.size() - n) + n;
|
|
||||||
SwapRandom(n, nRndPos);
|
|
||||||
assert(mapInfo.count(vRandom[n]) == 1);
|
assert(mapInfo.count(vRandom[n]) == 1);
|
||||||
|
|
||||||
const CAddrInfo& ai = mapInfo[vRandom[n]];
|
const CAddrInfo& ai = mapInfo[vRandom[n]];
|
||||||
if (!ai.IsTerrible())
|
|
||||||
vAddr.push_back(ai);
|
if (!ai.IsTerrible()) {
|
||||||
|
if (!wants_addrv2) {
|
||||||
|
vAddr.push_back(ai);
|
||||||
|
} else {
|
||||||
|
if (ai.IsIPv4() && ipv4Nodes <= addrv2Nodes) {
|
||||||
|
vAddr.push_back(ai);
|
||||||
|
ipv4Nodes++;
|
||||||
|
}
|
||||||
|
if (ai.IsIPv6() && ipv6Nodes <= addrv2Nodes) {
|
||||||
|
vAddr.push_back(ai);
|
||||||
|
ipv6Nodes++;
|
||||||
|
}
|
||||||
|
if (ai.IsCJDNS() && cjdnsNodes <= addrv2Nodes) {
|
||||||
|
vAddr.push_back(ai);
|
||||||
|
cjdnsNodes++;
|
||||||
|
}
|
||||||
|
if (ai.IsTor() && torNodes <= addrv2Nodes) {
|
||||||
|
vAddr.push_back(ai);
|
||||||
|
torNodes++;
|
||||||
|
}
|
||||||
|
if (ai.IsI2P() && i2pNodes <= addrv2Nodes) {
|
||||||
|
vAddr.push_back(ai);
|
||||||
|
i2pNodes++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,10 +707,36 @@ void CAddrMan::Connected_(const CService& addr, int64_t nTime)
|
|||||||
info.nTime = nTime;
|
info.nTime = nTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CAddrMan::SetLocal_(const CService& addr)
|
||||||
|
{
|
||||||
|
CAddrInfo* pinfo = Find(addr);
|
||||||
|
|
||||||
|
// if not found, bail out
|
||||||
|
if (!pinfo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CAddrInfo& info = *pinfo;
|
||||||
|
|
||||||
|
// check whether we are talking about the exact same CService (including same port)
|
||||||
|
if (info != addr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// update info
|
||||||
|
info.fLocal = true;
|
||||||
|
}
|
||||||
|
|
||||||
int CAddrMan::RandomInt(int nMax){
|
int CAddrMan::RandomInt(int nMax){
|
||||||
return GetRandInt(nMax);
|
return GetRandInt(nMax);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CAddrMan::GetAllPeers(std::map<std::string, int64_t> &info) {
|
||||||
|
|
||||||
|
for(std::map<int, CAddrInfo>::iterator it = mapInfo.begin(); it != mapInfo.end(); it++) {
|
||||||
|
info[(*it).second.ToStringIPPort()] = (*it).second.GetLastSuccess();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<bool> CAddrMan::DecodeAsmap(fs::path path)
|
std::vector<bool> CAddrMan::DecodeAsmap(fs::path path)
|
||||||
{
|
{
|
||||||
std::vector<bool> bits;
|
std::vector<bool> bits;
|
||||||
|
|||||||
220
src/addrman.h
220
src/addrman.h
@@ -24,6 +24,7 @@
|
|||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
|
#include "streams.h"
|
||||||
#include "timedata.h"
|
#include "timedata.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
@@ -64,18 +65,17 @@ private:
|
|||||||
//! position in vRandom
|
//! position in vRandom
|
||||||
int nRandomPos;
|
int nRandomPos;
|
||||||
|
|
||||||
|
//! Address is local
|
||||||
|
bool fLocal;
|
||||||
|
|
||||||
friend class CAddrMan;
|
friend class CAddrMan;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
SERIALIZE_METHODS(CAddrInfo, obj)
|
||||||
|
{
|
||||||
template <typename Stream, typename Operation>
|
READWRITEAS(CAddress, obj);
|
||||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
READ_WRITE(obj.source, obj.nLastSuccess, obj.nAttempts);
|
||||||
READWRITE(*(CAddress*)this);
|
|
||||||
READWRITE(source);
|
|
||||||
READWRITE(nLastSuccess);
|
|
||||||
READWRITE(nAttempts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
@@ -86,6 +86,7 @@ public:
|
|||||||
nRefCount = 0;
|
nRefCount = 0;
|
||||||
fInTried = false;
|
fInTried = false;
|
||||||
nRandomPos = -1;
|
nRandomPos = -1;
|
||||||
|
fLocal = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn), source(addrSource)
|
CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn), source(addrSource)
|
||||||
@@ -116,9 +117,15 @@ public:
|
|||||||
//! Determine whether the statistics about this entry are bad enough so that it can just be deleted
|
//! Determine whether the statistics about this entry are bad enough so that it can just be deleted
|
||||||
bool IsTerrible(int64_t nNow = GetTime()) const;
|
bool IsTerrible(int64_t nNow = GetTime()) const;
|
||||||
|
|
||||||
|
//Determine if this entry was just tried
|
||||||
|
bool IsJustTried(int64_t nNow = GetTime()) const;
|
||||||
|
|
||||||
//! Calculate the relative chance this entry should be given when selecting nodes to connect to
|
//! Calculate the relative chance this entry should be given when selecting nodes to connect to
|
||||||
double GetChance(int64_t nNow = GetTime()) const;
|
double GetChance(int64_t nNow = GetTime()) const;
|
||||||
|
|
||||||
|
//Returns the last successful connection
|
||||||
|
int64_t GetLastSuccess() {return nTime;}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Stochastic address manager
|
/** Stochastic address manager
|
||||||
@@ -199,8 +206,30 @@ private:
|
|||||||
//! critical section to protect the inner data structures
|
//! critical section to protect the inner data structures
|
||||||
mutable CCriticalSection cs;
|
mutable CCriticalSection cs;
|
||||||
|
|
||||||
|
//! Serialization versions.
|
||||||
|
enum Format : uint8_t {
|
||||||
|
V0_HISTORICAL = 0, //!< historic format, before commit e6b343d88
|
||||||
|
V1_DETERMINISTIC = 1, //!< for pre-asmap files
|
||||||
|
V2_ASMAP = 2, //!< for files including asmap version
|
||||||
|
V3_BIP155 = 3, //!< same as V2_ASMAP plus addresses are in BIP155 format
|
||||||
|
};
|
||||||
|
|
||||||
|
//! The maximum format this software knows it can unserialize. Also, we always serialize
|
||||||
|
//! in this format.
|
||||||
|
//! The format (first byte in the serialized stream) can be higher than this and
|
||||||
|
//! still this software may be able to unserialize the file - if the second byte
|
||||||
|
//! (see `lowest_compatible` in `Unserialize()`) is less or equal to this.
|
||||||
|
static constexpr Format FILE_FORMAT = Format::V3_BIP155;
|
||||||
|
|
||||||
|
//! The initial value of a field that is incremented every time an incompatible format
|
||||||
|
//! change is made (such that old software versions would not be able to parse and
|
||||||
|
//! understand the new file format). This is 32 because we overtook the "key size"
|
||||||
|
//! field which was 32 historically.
|
||||||
|
//! @note Don't increment this. Increment `lowest_compatible` in `Serialize()` instead.
|
||||||
|
static constexpr uint8_t INCOMPATIBILITY_BASE = 32;
|
||||||
|
|
||||||
//! last used nId
|
//! last used nId
|
||||||
int nIdCount;
|
int nIdCount GUARDED_BY(cs){0};
|
||||||
|
|
||||||
//! table with information about all nIds
|
//! table with information about all nIds
|
||||||
std::map<int, CAddrInfo> mapInfo;
|
std::map<int, CAddrInfo> mapInfo;
|
||||||
@@ -280,12 +309,16 @@ protected:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
//! Select several addresses at once.
|
//! Select several addresses at once.
|
||||||
void GetAddr_(std::vector<CAddress> &vAddr);
|
void GetAddr_(std::vector<CAddress> &vAddr, bool wants_addrv2);
|
||||||
|
|
||||||
//! Mark an entry as currently-connected-to.
|
//! Mark an entry as currently-connected-to.
|
||||||
void Connected_(const CService &addr, int64_t nTime);
|
void Connected_(const CService &addr, int64_t nTime);
|
||||||
|
|
||||||
|
//! Mark an entry as local
|
||||||
|
void SetLocal_(const CService &addr);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
void GetAllPeers(std::map<std::string, int64_t> &info);
|
||||||
// Compressed IP->ASN mapping, loaded from a file when a node starts.
|
// Compressed IP->ASN mapping, loaded from a file when a node starts.
|
||||||
// Should be always empty if no file was provided.
|
// Should be always empty if no file was provided.
|
||||||
// This mapping is then used for bucketing nodes in Addrman.
|
// This mapping is then used for bucketing nodes in Addrman.
|
||||||
@@ -336,13 +369,22 @@ public:
|
|||||||
* very little in common.
|
* very little in common.
|
||||||
*/
|
*/
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
void Serialize(Stream &s) const
|
void Serialize(Stream &s_) const
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(!cs)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
|
|
||||||
unsigned char nVersion = 2;
|
// Always serialize in the latest version (FILE_FORMAT).
|
||||||
s << nVersion;
|
|
||||||
s << ((unsigned char)32);
|
OverrideStream<Stream> s(&s_, s_.GetType(), s_.GetVersion() | ADDRV2_FORMAT);
|
||||||
|
|
||||||
|
s << static_cast<uint8_t>(FILE_FORMAT);
|
||||||
|
|
||||||
|
// Increment `lowest_compatible` iff a newly introduced format is incompatible with
|
||||||
|
// the previous one.
|
||||||
|
static constexpr uint8_t lowest_compatible = Format::V3_BIP155;
|
||||||
|
s << static_cast<uint8_t>(INCOMPATIBILITY_BASE + lowest_compatible);
|
||||||
|
|
||||||
s << nKey;
|
s << nKey;
|
||||||
s << nNew;
|
s << nNew;
|
||||||
s << nTried;
|
s << nTried;
|
||||||
@@ -393,22 +435,40 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
void Unserialize(Stream& s)
|
void Unserialize(Stream& s_) EXCLUSIVE_LOCKS_REQUIRED(!cs)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
|
|
||||||
Clear();
|
std::vector<int>().swap(vRandom);
|
||||||
unsigned char nVersion;
|
|
||||||
s >> nVersion;
|
Format format;
|
||||||
unsigned char nKeySize;
|
s_ >> Using<CustomUintFormatter<1>>(format);
|
||||||
s >> nKeySize;
|
|
||||||
if (nKeySize != 32) throw std::ios_base::failure("Incorrect keysize in addrman deserialization");
|
int stream_version = s_.GetVersion();
|
||||||
|
if (format >= Format::V3_BIP155) {
|
||||||
|
// Add ADDRV2_FORMAT to the version so that the CNetAddr and CAddress
|
||||||
|
// unserialize methods know that an address in addrv2 format is coming.
|
||||||
|
stream_version |= ADDRV2_FORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
OverrideStream<Stream> s(&s_, s_.GetType(), stream_version);
|
||||||
|
|
||||||
|
uint8_t compat;
|
||||||
|
s >> compat;
|
||||||
|
const uint8_t lowest_compatible = compat - INCOMPATIBILITY_BASE;
|
||||||
|
if (lowest_compatible > FILE_FORMAT) {
|
||||||
|
throw std::ios_base::failure(strprintf(
|
||||||
|
"Unsupported format of addrman database: %u. It is compatible with formats >=%u, "
|
||||||
|
"but the maximum supported by this version of %s is %u.",
|
||||||
|
format, lowest_compatible, PACKAGE_NAME, static_cast<uint8_t>(FILE_FORMAT)));
|
||||||
|
}
|
||||||
|
|
||||||
s >> nKey;
|
s >> nKey;
|
||||||
s >> nNew;
|
s >> nNew;
|
||||||
s >> nTried;
|
s >> nTried;
|
||||||
int nUBuckets = 0;
|
int nUBuckets = 0;
|
||||||
s >> nUBuckets;
|
s >> nUBuckets;
|
||||||
if (nVersion != 0) {
|
if (format >= Format::V1_DETERMINISTIC) {
|
||||||
nUBuckets ^= (1 << 30);
|
nUBuckets ^= (1 << 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,7 +482,7 @@ public:
|
|||||||
|
|
||||||
// Deserialize entries from the new table.
|
// Deserialize entries from the new table.
|
||||||
for (int n = 0; n < nNew; n++) {
|
for (int n = 0; n < nNew; n++) {
|
||||||
CAddrInfo &info = mapInfo[n];
|
CAddrInfo& info = mapInfo[n];
|
||||||
s >> info;
|
s >> info;
|
||||||
mapAddr[info] = n;
|
mapAddr[info] = n;
|
||||||
info.nRandomPos = vRandom.size();
|
info.nRandomPos = vRandom.size();
|
||||||
@@ -437,7 +497,7 @@ public:
|
|||||||
s >> info;
|
s >> info;
|
||||||
int nKBucket = info.GetTriedBucket(nKey, m_asmap);
|
int nKBucket = info.GetTriedBucket(nKey, m_asmap);
|
||||||
int nKBucketPos = info.GetBucketPosition(nKey, false, nKBucket);
|
int nKBucketPos = info.GetBucketPosition(nKey, false, nKBucket);
|
||||||
if (vvTried[nKBucket][nKBucketPos] == -1) {
|
if (info.IsValid() && vvTried[nKBucket][nKBucketPos] == -1) {
|
||||||
info.nRandomPos = vRandom.size();
|
info.nRandomPos = vRandom.size();
|
||||||
info.fInTried = true;
|
info.fInTried = true;
|
||||||
vRandom.push_back(nIdCount);
|
vRandom.push_back(nIdCount);
|
||||||
@@ -452,60 +512,84 @@ public:
|
|||||||
nTried -= nLost;
|
nTried -= nLost;
|
||||||
|
|
||||||
// Store positions in the new table buckets to apply later (if possible).
|
// Store positions in the new table buckets to apply later (if possible).
|
||||||
std::map<int, int> entryToBucket; // Represents which entry belonged to which bucket when serializing
|
// An entry may appear in up to ADDRMAN_NEW_BUCKETS_PER_ADDRESS buckets,
|
||||||
|
// so we store all bucket-entry_index pairs to iterate through later.
|
||||||
|
std::vector<std::pair<int, int>> bucket_entries;
|
||||||
|
|
||||||
for (int bucket = 0; bucket < nUBuckets; bucket++) {
|
for (int bucket = 0; bucket < nUBuckets; ++bucket) {
|
||||||
int nSize = 0;
|
int num_entries{0};
|
||||||
s >> nSize;
|
s >> num_entries;
|
||||||
for (int n = 0; n < nSize; n++) {
|
for (int n = 0; n < num_entries; ++n) {
|
||||||
int nIndex = 0;
|
int entry_index{0};
|
||||||
s >> nIndex;
|
s >> entry_index;
|
||||||
if (nIndex >= 0 && nIndex < nNew) {
|
if (entry_index >= 0 && entry_index < nNew) {
|
||||||
entryToBucket[nIndex] = bucket;
|
bucket_entries.emplace_back(bucket, entry_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 supplied_asmap_version;
|
// If the bucket count and asmap checksum haven't changed, then attempt
|
||||||
|
// to restore the entries to the buckets/positions they were in before
|
||||||
|
// serialization.
|
||||||
|
uint256 supplied_asmap_checksum;
|
||||||
if (m_asmap.size() != 0) {
|
if (m_asmap.size() != 0) {
|
||||||
supplied_asmap_version = SerializeHash(m_asmap);
|
supplied_asmap_checksum = SerializeHash(m_asmap);
|
||||||
}
|
}
|
||||||
uint256 serialized_asmap_version;
|
uint256 serialized_asmap_checksum;
|
||||||
if (nVersion > 1) {
|
if (format >= Format::V2_ASMAP) {
|
||||||
s >> serialized_asmap_version;
|
s >> serialized_asmap_checksum;
|
||||||
|
}
|
||||||
|
const bool restore_bucketing{nUBuckets == ADDRMAN_NEW_BUCKET_COUNT &&
|
||||||
|
serialized_asmap_checksum == supplied_asmap_checksum};
|
||||||
|
|
||||||
|
if (!restore_bucketing) {
|
||||||
|
LogPrint("addrman", "Bucketing method was updated, re-bucketing addrman entries from disk\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int n = 0; n < nNew; n++) {
|
for (auto bucket_entry : bucket_entries) {
|
||||||
CAddrInfo &info = mapInfo[n];
|
int bucket{bucket_entry.first};
|
||||||
int bucket = entryToBucket[n];
|
const int entry_index{bucket_entry.second};
|
||||||
int nUBucketPos = info.GetBucketPosition(nKey, true, bucket);
|
// CAddrInfo& info = mapInfo[entry_index];
|
||||||
if (nVersion == 2 && nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && vvNew[bucket][nUBucketPos] == -1 &&
|
|
||||||
info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS && serialized_asmap_version == supplied_asmap_version) {
|
const auto it{mapInfo.find(entry_index)};
|
||||||
// Bucketing has not changed, using existing bucket positions for the new table
|
if (it != mapInfo.end()) {
|
||||||
vvNew[bucket][nUBucketPos] = n;
|
CAddrInfo& info = (*it).second;
|
||||||
info.nRefCount++;
|
|
||||||
} else {
|
// Don't store the entry in the new bucket if it's not a valid address for our addrman
|
||||||
// In case the new table data cannot be used (nVersion unknown, bucket count wrong or new asmap),
|
if (!info.IsValid()) continue;
|
||||||
// try to give them a reference based on their primary source address.
|
|
||||||
LogPrint("addrman", "Bucketing method was updated, re-bucketing addrman entries from disk\n");
|
// The entry shouldn't appear in more than
|
||||||
bucket = info.GetNewBucket(nKey, m_asmap);
|
// ADDRMAN_NEW_BUCKETS_PER_ADDRESS. If it has already, just skip
|
||||||
nUBucketPos = info.GetBucketPosition(nKey, true, bucket);
|
// this bucket_entry.
|
||||||
if (vvNew[bucket][nUBucketPos] == -1) {
|
if (info.nRefCount >= ADDRMAN_NEW_BUCKETS_PER_ADDRESS) continue;
|
||||||
vvNew[bucket][nUBucketPos] = n;
|
|
||||||
info.nRefCount++;
|
int bucket_position = info.GetBucketPosition(nKey, true, bucket);
|
||||||
|
if (restore_bucketing && vvNew[bucket][bucket_position] == -1) {
|
||||||
|
// Bucketing has not changed, using existing bucket positions for the new table
|
||||||
|
vvNew[bucket][bucket_position] = entry_index;
|
||||||
|
++info.nRefCount;
|
||||||
|
} else {
|
||||||
|
// In case the new table data cannot be used (bucket count wrong or new asmap),
|
||||||
|
// try to give them a reference based on their primary source address.
|
||||||
|
bucket = info.GetNewBucket(nKey, m_asmap);
|
||||||
|
bucket_position = info.GetBucketPosition(nKey, true, bucket);
|
||||||
|
if (vvNew[bucket][bucket_position] == -1) {
|
||||||
|
vvNew[bucket][bucket_position] = entry_index;
|
||||||
|
++info.nRefCount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prune new entries with refcount 0 (as a result of collisions).
|
// Prune new entries with refcount 0 (as a result of collisions).
|
||||||
int nLostUnk = 0;
|
int nLostUnk = 0;
|
||||||
for (std::map<int, CAddrInfo>::const_iterator it = mapInfo.begin(); it != mapInfo.end(); ) {
|
for (auto it = mapInfo.cbegin(); it != mapInfo.cend(); ) {
|
||||||
if (it->second.fInTried == false && it->second.nRefCount == 0) {
|
if (it->second.fInTried == false && it->second.nRefCount == 0) {
|
||||||
std::map<int, CAddrInfo>::const_iterator itCopy = it++;
|
const auto itCopy = it++;
|
||||||
Delete(itCopy->first);
|
Delete(itCopy->first);
|
||||||
nLostUnk++;
|
++nLostUnk;
|
||||||
} else {
|
} else {
|
||||||
it++;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (nLost + nLostUnk > 0) {
|
if (nLost + nLostUnk > 0) {
|
||||||
@@ -531,7 +615,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nIdCount = 0;
|
|
||||||
nTried = 0;
|
nTried = 0;
|
||||||
nNew = 0;
|
nNew = 0;
|
||||||
mapInfo.clear();
|
mapInfo.clear();
|
||||||
@@ -657,13 +740,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Return a bunch of addresses, selected at random.
|
//! Return a bunch of addresses, selected at random.
|
||||||
std::vector<CAddress> GetAddr()
|
std::vector<CAddress> GetAddr(bool wants_addrv2 = false)
|
||||||
{
|
{
|
||||||
Check();
|
Check();
|
||||||
std::vector<CAddress> vAddr;
|
std::vector<CAddress> vAddr;
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
GetAddr_(vAddr);
|
GetAddr_(vAddr, wants_addrv2);
|
||||||
}
|
}
|
||||||
Check();
|
Check();
|
||||||
return vAddr;
|
return vAddr;
|
||||||
@@ -680,6 +763,17 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Mark an entry as currently-connected-to.
|
||||||
|
void SetLocal(const CService &addr)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
LOCK(cs);
|
||||||
|
Check();
|
||||||
|
SetLocal_(addr);
|
||||||
|
Check();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // HUSH_ADDRMAN_H
|
#endif // HUSH_ADDRMAN_H
|
||||||
|
|||||||
163
src/alert.cpp
163
src/alert.cpp
@@ -1,163 +0,0 @@
|
|||||||
// Copyright (c) 2010 Satoshi Nakamoto
|
|
||||||
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
|
||||||
// Copyright (c) 2016-2022 The Hush developers
|
|
||||||
// Distributed under the GPLv3 software license, see the accompanying
|
|
||||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
|
||||||
/******************************************************************************
|
|
||||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
|
||||||
* *
|
|
||||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
|
||||||
* the top-level directory of this distribution for the individual copyright *
|
|
||||||
* holder information and the developer policies on copyright and licensing. *
|
|
||||||
* *
|
|
||||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
|
||||||
* SuperNET software, including this file may be copied, modified, propagated *
|
|
||||||
* or distributed except according to the terms contained in the LICENSE file *
|
|
||||||
* *
|
|
||||||
* Removal or modification of this copyright notice is prohibited. *
|
|
||||||
* *
|
|
||||||
******************************************************************************/
|
|
||||||
#include "alert.h"
|
|
||||||
#include "clientversion.h"
|
|
||||||
#include "net.h"
|
|
||||||
#include "pubkey.h"
|
|
||||||
#include "timedata.h"
|
|
||||||
#include "ui_interface.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <map>
|
|
||||||
#include <boost/algorithm/string/classification.hpp>
|
|
||||||
#include <boost/algorithm/string/replace.hpp>
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <boost/thread.hpp>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
map<uint256, CAlert> mapAlerts;
|
|
||||||
CCriticalSection cs_mapAlerts;
|
|
||||||
|
|
||||||
void CUnsignedAlert::SetNull()
|
|
||||||
{
|
|
||||||
nVersion = 1;
|
|
||||||
nRelayUntil = 0;
|
|
||||||
nExpiration = 0;
|
|
||||||
nID = 0;
|
|
||||||
nCancel = 0;
|
|
||||||
setCancel.clear();
|
|
||||||
nMinVer = 0;
|
|
||||||
nMaxVer = 0;
|
|
||||||
setSubVer.clear();
|
|
||||||
nPriority = 0;
|
|
||||||
|
|
||||||
strComment.clear();
|
|
||||||
strStatusBar.clear();
|
|
||||||
strRPCError.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CUnsignedAlert::ToString() const
|
|
||||||
{
|
|
||||||
std::string strSetCancel;
|
|
||||||
BOOST_FOREACH(int n, setCancel)
|
|
||||||
strSetCancel += strprintf("%d ", n);
|
|
||||||
std::string strSetSubVer;
|
|
||||||
BOOST_FOREACH(const std::string& str, setSubVer)
|
|
||||||
strSetSubVer += "\"" + str + "\" ";
|
|
||||||
return strprintf(
|
|
||||||
"CAlert(\n"
|
|
||||||
" nVersion = %d\n"
|
|
||||||
" nRelayUntil = %d\n"
|
|
||||||
" nExpiration = %d\n"
|
|
||||||
" nID = %d\n"
|
|
||||||
" nCancel = %d\n"
|
|
||||||
" setCancel = %s\n"
|
|
||||||
" nMinVer = %d\n"
|
|
||||||
" nMaxVer = %d\n"
|
|
||||||
" setSubVer = %s\n"
|
|
||||||
" nPriority = %d\n"
|
|
||||||
" strComment = \"%s\"\n"
|
|
||||||
" strStatusBar = \"%s\"\n"
|
|
||||||
" strRPCError = \"%s\"\n"
|
|
||||||
")\n",
|
|
||||||
nVersion,
|
|
||||||
nRelayUntil,
|
|
||||||
nExpiration,
|
|
||||||
nID,
|
|
||||||
nCancel,
|
|
||||||
strSetCancel,
|
|
||||||
nMinVer,
|
|
||||||
nMaxVer,
|
|
||||||
strSetSubVer,
|
|
||||||
nPriority,
|
|
||||||
strComment,
|
|
||||||
strStatusBar,
|
|
||||||
strRPCError);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAlert::SetNull()
|
|
||||||
{
|
|
||||||
CUnsignedAlert::SetNull();
|
|
||||||
vchMsg.clear();
|
|
||||||
vchSig.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CAlert::IsNull() const
|
|
||||||
{
|
|
||||||
return (nExpiration == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint256 CAlert::GetHash() const
|
|
||||||
{
|
|
||||||
return Hash(this->vchMsg.begin(), this->vchMsg.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CAlert::IsInEffect() const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CAlert::Cancels(const CAlert& alert) const
|
|
||||||
{
|
|
||||||
if (!IsInEffect())
|
|
||||||
return false; // this was a no-op before 31403
|
|
||||||
return (alert.nID <= nCancel || setCancel.count(alert.nID));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CAlert::AppliesTo(int nVersion, const std::string& strSubVerIn) const
|
|
||||||
{
|
|
||||||
// TODO: rework for client-version-embedded-in-strSubVer ?
|
|
||||||
return (IsInEffect() &&
|
|
||||||
nMinVer <= nVersion && nVersion <= nMaxVer &&
|
|
||||||
(setSubVer.empty() || setSubVer.count(strSubVerIn)));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CAlert::AppliesToMe() const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CAlert::RelayTo(CNode* pnode) const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CAlert::CheckSignature(const std::vector<unsigned char>& alertKey) const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CAlert CAlert::getAlertByHash(const uint256 &hash)
|
|
||||||
{
|
|
||||||
CAlert retval;
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CAlert::ProcessAlert(const std::vector<unsigned char>& alertKey, bool fThread)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAlert::Notify(const std::string& strMessage, bool fThread)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
127
src/alert.h
127
src/alert.h
@@ -1,127 +0,0 @@
|
|||||||
// Copyright (c) 2010 Satoshi Nakamoto
|
|
||||||
// Copyright (c) 2009-2013 The Bitcoin Core developers
|
|
||||||
// Copyright (c) 2016-2022 The Hush developers
|
|
||||||
// Distributed under the GPLv3 software license, see the accompanying
|
|
||||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
|
||||||
* *
|
|
||||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
|
||||||
* the top-level directory of this distribution for the individual copyright *
|
|
||||||
* holder information and the developer policies on copyright and licensing. *
|
|
||||||
* *
|
|
||||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
|
||||||
* SuperNET software, including this file may be copied, modified, propagated *
|
|
||||||
* or distributed except according to the terms contained in the LICENSE file *
|
|
||||||
* *
|
|
||||||
* Removal or modification of this copyright notice is prohibited. *
|
|
||||||
* *
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#ifndef HUSH_ALERT_H
|
|
||||||
#define HUSH_ALERT_H
|
|
||||||
|
|
||||||
#include "serialize.h"
|
|
||||||
#include "sync.h"
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class CAlert;
|
|
||||||
class CNode;
|
|
||||||
class uint256;
|
|
||||||
|
|
||||||
extern std::map<uint256, CAlert> mapAlerts;
|
|
||||||
extern CCriticalSection cs_mapAlerts;
|
|
||||||
|
|
||||||
/** Alerts are for notifying old versions if they become too obsolete and
|
|
||||||
* need to upgrade. The message is displayed in the status bar.
|
|
||||||
* Alert messages are broadcast as a vector of signed data. Unserializing may
|
|
||||||
* not read the entire buffer if the alert is for a newer version, but older
|
|
||||||
* versions can still relay the original data.
|
|
||||||
*/
|
|
||||||
class CUnsignedAlert
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
int nVersion;
|
|
||||||
int64_t nRelayUntil; // when newer nodes stop relaying to newer nodes
|
|
||||||
int64_t nExpiration;
|
|
||||||
int nID;
|
|
||||||
int nCancel;
|
|
||||||
std::set<int> setCancel;
|
|
||||||
int nMinVer; // lowest version inclusive
|
|
||||||
int nMaxVer; // highest version inclusive
|
|
||||||
std::set<std::string> setSubVer; // empty matches all
|
|
||||||
int nPriority;
|
|
||||||
|
|
||||||
// Actions
|
|
||||||
std::string strComment;
|
|
||||||
std::string strStatusBar;
|
|
||||||
std::string strRPCError;
|
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
|
||||||
|
|
||||||
template <typename Stream, typename Operation>
|
|
||||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
||||||
READWRITE(this->nVersion);
|
|
||||||
READWRITE(nRelayUntil);
|
|
||||||
READWRITE(nExpiration);
|
|
||||||
READWRITE(nID);
|
|
||||||
READWRITE(nCancel);
|
|
||||||
READWRITE(setCancel);
|
|
||||||
READWRITE(nMinVer);
|
|
||||||
READWRITE(nMaxVer);
|
|
||||||
READWRITE(setSubVer);
|
|
||||||
READWRITE(nPriority);
|
|
||||||
|
|
||||||
READWRITE(LIMITED_STRING(strComment, 65536));
|
|
||||||
READWRITE(LIMITED_STRING(strStatusBar, 256));
|
|
||||||
READWRITE(LIMITED_STRING(strRPCError, 256));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetNull();
|
|
||||||
|
|
||||||
std::string ToString() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** An alert is a combination of a serialized CUnsignedAlert and a signature. */
|
|
||||||
class CAlert : public CUnsignedAlert
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
std::vector<unsigned char> vchMsg;
|
|
||||||
std::vector<unsigned char> vchSig;
|
|
||||||
|
|
||||||
CAlert()
|
|
||||||
{
|
|
||||||
SetNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
|
||||||
|
|
||||||
template <typename Stream, typename Operation>
|
|
||||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
||||||
READWRITE(vchMsg);
|
|
||||||
READWRITE(vchSig);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetNull();
|
|
||||||
bool IsNull() const;
|
|
||||||
uint256 GetHash() const;
|
|
||||||
bool IsInEffect() const;
|
|
||||||
bool Cancels(const CAlert& alert) const;
|
|
||||||
bool AppliesTo(int nVersion, const std::string& strSubVerIn) const;
|
|
||||||
bool AppliesToMe() const;
|
|
||||||
bool RelayTo(CNode* pnode) const;
|
|
||||||
bool CheckSignature(const std::vector<unsigned char>& alertKey) const;
|
|
||||||
bool ProcessAlert(const std::vector<unsigned char>& alertKey, bool fThread = true); // fThread means run -alertnotify in a free-running thread
|
|
||||||
static void Notify(const std::string& strMessage, bool fThread);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get copy of (active) alert object by hash. Returns a null alert if it is not found.
|
|
||||||
*/
|
|
||||||
static CAlert getAlertByHash(const uint256 &hash);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // HUSH_ALERT_H
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
// Copyright (c) 2016-2022 The Hush developers
|
|
||||||
// Distributed under the GPLv3 software license, see the accompanying
|
|
||||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
|
||||||
/******************************************************************************
|
|
||||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
|
||||||
* *
|
|
||||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
|
||||||
* the top-level directory of this distribution for the individual copyright *
|
|
||||||
* holder information and the developer policies on copyright and licensing. *
|
|
||||||
* *
|
|
||||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
|
||||||
* SuperNET software, including this file may be copied, modified, propagated *
|
|
||||||
* or distributed except according to the terms contained in the LICENSE file *
|
|
||||||
* *
|
|
||||||
* Removal or modification of this copyright notice is prohibited. *
|
|
||||||
* *
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#ifndef HUSH_ALERTKEYS_H
|
|
||||||
#define HUSH_ALERTKEYS_H
|
|
||||||
|
|
||||||
// REMINDER: DO NOT COMMIT YOUR PRIVATE KEYS TO THE GIT REPOSITORY, lulz
|
|
||||||
|
|
||||||
const char* pszPrivKey = "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
|
|
||||||
const char* pszTestNetPrivKey = "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
#include "arith_uint256.h"
|
#include "arith_uint256.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "crypto/common.h"
|
#include "crypto/common.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|||||||
20
src/attributes.h
Normal file
20
src/attributes.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
|
// Copyright (c) 2009-2020 The Bitcoin Core developers
|
||||||
|
// Copyright (c) 2016-2022 The Hush developers
|
||||||
|
// Distributed under the GPLv3 software license, see the accompanying
|
||||||
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
|
|
||||||
|
#ifndef HUSH_ATTRIBUTES_H
|
||||||
|
#define HUSH_ATTRIBUTES_H
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
# if __has_attribute(lifetimebound)
|
||||||
|
# define LIFETIMEBOUND [[clang::lifetimebound]]
|
||||||
|
# else
|
||||||
|
# define LIFETIMEBOUND
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define LIFETIMEBOUND
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // HUSH_ATTRIBUTES_H
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
#include "rpc/client.h"
|
#include "rpc/client.h"
|
||||||
#include "rpc/protocol.h"
|
#include "rpc/protocol.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include <boost/filesystem/operations.hpp>
|
#include <boost/filesystem/operations.hpp>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <event2/buffer.h>
|
#include <event2/buffer.h>
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ SHELL = /bin/sh
|
|||||||
CC = gcc
|
CC = gcc
|
||||||
CC_DARWIN = g++-6
|
CC_DARWIN = g++-6
|
||||||
CC_WIN = x86_64-w64-mingw32-gcc-posix
|
CC_WIN = x86_64-w64-mingw32-gcc-posix
|
||||||
CFLAGS_DARWIN = -std=c++11 -arch x86_64 -I/usr/local/Cellar/gcc\@6/6.4.0_2/include/c++/6.4.0/ -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -c -Wl,-undefined -Wl,dynamic_lookup -dynamiclib
|
CFLAGS = -arch x86_64
|
||||||
CFLAGS = -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c
|
CXXFLAGS_DARWIN = -std=c++11 -arch x86_64 -I/usr/local/Cellar/gcc\@6/6.4.0_2/include/c++/6.4.0/ -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -c -Wl,-undefined -Wl,dynamic_lookup -dynamiclib
|
||||||
CFLAGS_WIN = -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c
|
CXXFLAGS = -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c
|
||||||
|
CXXFLAGS_WIN = -std=c++11 -I../../depends/$(shell echo `../..//depends/config.guess`/include) -I../univalue/include -I../cryptoconditions/include -I../cryptoconditions/src -I../cryptoconditions/src/asn -I.. -I. -fPIC -shared -c
|
||||||
DEBUGFLAGS = -O0 -D _DEBUG
|
DEBUGFLAGS = -O0 -D _DEBUG
|
||||||
RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program
|
RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program
|
||||||
$(info $(OS))
|
$(info $(OS))
|
||||||
@@ -13,21 +14,27 @@ $(info $(OS))
|
|||||||
TARGET = ../libcc.so
|
TARGET = ../libcc.so
|
||||||
TARGET_DARWIN = ../libcc.dylib
|
TARGET_DARWIN = ../libcc.dylib
|
||||||
TARGET_WIN = ../libcc.dll
|
TARGET_WIN = ../libcc.dll
|
||||||
SOURCES = cclib.cpp
|
SOURCES = cclib.cpp ../cJSON.c
|
||||||
#HEADERS = $(shell echo ../cryptoconditions/include/*.h)
|
OBJS = cclib.o ../cJSON.o
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(SOURCES)
|
%.o: %.c
|
||||||
|
$(CC) -o $@ $< $(CFLAGS) $(DEBUGFLAGS)
|
||||||
|
|
||||||
|
%.o: %.cpp
|
||||||
|
$(CC) -o $@ $< $(CXXFLAGS) $(DEBUGFLAGS)
|
||||||
|
|
||||||
|
$(TARGET): $(OBJS)
|
||||||
$(info Building cclib to src/)
|
$(info Building cclib to src/)
|
||||||
ifeq ($(OS),Darwin)
|
ifeq ($(OS),Darwin)
|
||||||
$(CC_DARWIN) $(CFLAGS_DARWIN) $(DEBUGFLAGS) -o $(TARGET_DARWIN) $(SOURCES)
|
$(CC_DARWIN) $(CXXFLAGS_DARWIN) $(DEBUGFLAGS) -o $(TARGET_DARWIN) $(OBJS)
|
||||||
else ifeq ($(OS),Linux)
|
else ifeq ($(OS),Linux)
|
||||||
$(CC) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) $(SOURCES)
|
$(CC) $(CXXFLAGS) $(DEBUGFLAGS) -o $(TARGET) $(OBJS)
|
||||||
#else ifeq ($(WIN_HOST),True) - todo: pass ENV var from build.sh if WIN host
|
#else ifeq ($(WIN_HOST),True) - todo: pass ENV var from build.sh if WIN host
|
||||||
else
|
else
|
||||||
$(info WINDOWS)
|
$(info WINDOWS)
|
||||||
$(CC_WIN) $(CFLAGS_WIN) $(DEBUGFLAGS) -o $(TARGET_WIN) $(SOURCES)
|
$(CC_WIN) $(CXXFLAGS_WIN) $(DEBUGFLAGS) -o $(TARGET_WIN) $(OBJS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "crypto/equihash.h"
|
#include "crypto/equihash.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <boost/assign/list_of.hpp>
|
#include <boost/assign/list_of.hpp>
|
||||||
#include "chainparamsseeds.h"
|
#include "chainparamsseeds.h"
|
||||||
@@ -142,7 +142,6 @@ public:
|
|||||||
pchMessageStart[1] = 0xee;
|
pchMessageStart[1] = 0xee;
|
||||||
pchMessageStart[2] = 0xe4;
|
pchMessageStart[2] = 0xe4;
|
||||||
pchMessageStart[3] = 0x8d;
|
pchMessageStart[3] = 0x8d;
|
||||||
vAlertPubKey = ParseHex("038a1bd41a08f38edda51042988022933c5775dfce81f7bae0b32a9179650352ac");
|
|
||||||
nDefaultPort = 5420;
|
nDefaultPort = 5420;
|
||||||
nMinerThreads = 0;
|
nMinerThreads = 0;
|
||||||
nMaxTipAge = 24 * 60 * 60;
|
nMaxTipAge = 24 * 60 * 60;
|
||||||
@@ -206,7 +205,7 @@ public:
|
|||||||
bech32HRPs[SAPLING_INCOMING_VIEWING_KEY] = "zivks";
|
bech32HRPs[SAPLING_INCOMING_VIEWING_KEY] = "zivks";
|
||||||
bech32HRPs[SAPLING_EXTENDED_SPEND_KEY] = "secret-extended-key-main";
|
bech32HRPs[SAPLING_EXTENDED_SPEND_KEY] = "secret-extended-key-main";
|
||||||
|
|
||||||
vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main));
|
vFixedSeeds = std::vector<uint8_t>(std::begin(chainparams_seed_main), std::end(chainparams_seed_main));
|
||||||
|
|
||||||
fMiningRequiresPeers = true;
|
fMiningRequiresPeers = true;
|
||||||
fDefaultConsistencyChecks = false;
|
fDefaultConsistencyChecks = false;
|
||||||
@@ -280,7 +279,6 @@ public:
|
|||||||
pchMessageStart[1] = 0x1F;
|
pchMessageStart[1] = 0x1F;
|
||||||
pchMessageStart[2] = 0x7E;
|
pchMessageStart[2] = 0x7E;
|
||||||
pchMessageStart[3] = 0x62;
|
pchMessageStart[3] = 0x62;
|
||||||
vAlertPubKey = ParseHex("038a1bd41a08f38edda51042988022933c5775dfce81f7bae0b32a9179650352ac");
|
|
||||||
nMaxTipAge = 24 * 60 * 60;
|
nMaxTipAge = 24 * 60 * 60;
|
||||||
|
|
||||||
nPruneAfterHeight = 1000;
|
nPruneAfterHeight = 1000;
|
||||||
@@ -315,7 +313,7 @@ public:
|
|||||||
bech32HRPs[SAPLING_INCOMING_VIEWING_KEY] = "zivktestsapling";
|
bech32HRPs[SAPLING_INCOMING_VIEWING_KEY] = "zivktestsapling";
|
||||||
bech32HRPs[SAPLING_EXTENDED_SPEND_KEY] = "secret-extended-key-test";
|
bech32HRPs[SAPLING_EXTENDED_SPEND_KEY] = "secret-extended-key-test";
|
||||||
|
|
||||||
vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_test, pnSeed6_test + ARRAYLEN(pnSeed6_test));
|
vFixedSeeds = std::vector<uint8_t>(std::begin(chainparams_seed_test), std::end(chainparams_seed_test));
|
||||||
|
|
||||||
//fRequireRPCPassword = true;
|
//fRequireRPCPassword = true;
|
||||||
fMiningRequiresPeers = false;//true;
|
fMiningRequiresPeers = false;//true;
|
||||||
|
|||||||
@@ -36,11 +36,6 @@ struct CDNSSeedData {
|
|||||||
CDNSSeedData(const std::string &strName, const std::string &strHost) : name(strName), host(strHost) {}
|
CDNSSeedData(const std::string &strName, const std::string &strHost) : name(strName), host(strHost) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SeedSpec6 {
|
|
||||||
uint8_t addr[16];
|
|
||||||
uint16_t port;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::map<int, uint256> MapCheckpoints;
|
typedef std::map<int, uint256> MapCheckpoints;
|
||||||
|
|
||||||
|
|
||||||
@@ -85,7 +80,6 @@ public:
|
|||||||
|
|
||||||
const Consensus::Params& GetConsensus() const { return consensus; }
|
const Consensus::Params& GetConsensus() const { return consensus; }
|
||||||
const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; }
|
const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; }
|
||||||
const std::vector<unsigned char>& AlertKey() const { return vAlertPubKey; }
|
|
||||||
int GetDefaultPort() const { return nDefaultPort; }
|
int GetDefaultPort() const { return nDefaultPort; }
|
||||||
|
|
||||||
const CBlock& GenesisBlock() const { return genesis; }
|
const CBlock& GenesisBlock() const { return genesis; }
|
||||||
@@ -109,7 +103,7 @@ public:
|
|||||||
const std::vector<CDNSSeedData>& DNSSeeds() const { return vSeeds; }
|
const std::vector<CDNSSeedData>& DNSSeeds() const { return vSeeds; }
|
||||||
const std::vector<unsigned char>& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; }
|
const std::vector<unsigned char>& Base58Prefix(Base58Type type) const { return base58Prefixes[type]; }
|
||||||
const std::string& Bech32HRP(Bech32Type type) const { return bech32HRPs[type]; }
|
const std::string& Bech32HRP(Bech32Type type) const { return bech32HRPs[type]; }
|
||||||
const std::vector<SeedSpec6>& FixedSeeds() const { return vFixedSeeds; }
|
const std::vector<uint8_t>& FixedSeeds() const { return vFixedSeeds; }
|
||||||
const CCheckpointData& Checkpoints() const { return checkpointData; }
|
const CCheckpointData& Checkpoints() const { return checkpointData; }
|
||||||
/** Return the founder's reward address and script for a given block height */
|
/** Return the founder's reward address and script for a given block height */
|
||||||
std::string GetFoundersRewardAddressAtHeight(int height) const;
|
std::string GetFoundersRewardAddressAtHeight(int height) const;
|
||||||
@@ -134,8 +128,6 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
CChainParams() {}
|
CChainParams() {}
|
||||||
|
|
||||||
//! Raw pub key bytes for the broadcast alert signing key.
|
|
||||||
std::vector<unsigned char> vAlertPubKey;
|
|
||||||
int nMinerThreads = 0;
|
int nMinerThreads = 0;
|
||||||
long nMaxTipAge = 0;
|
long nMaxTipAge = 0;
|
||||||
int nDefaultPort = 0;
|
int nDefaultPort = 0;
|
||||||
@@ -149,7 +141,7 @@ protected:
|
|||||||
std::string strCurrencyUnits;
|
std::string strCurrencyUnits;
|
||||||
uint32_t bip44CoinType;
|
uint32_t bip44CoinType;
|
||||||
CBlock genesis;
|
CBlock genesis;
|
||||||
std::vector<SeedSpec6> vFixedSeeds;
|
std::vector<uint8_t> vFixedSeeds;
|
||||||
bool fMiningRequiresPeers = false;
|
bool fMiningRequiresPeers = false;
|
||||||
bool fDefaultConsistencyChecks = false;
|
bool fDefaultConsistencyChecks = false;
|
||||||
bool fRequireStandard = false;
|
bool fRequireStandard = false;
|
||||||
|
|||||||
@@ -1,37 +1,26 @@
|
|||||||
// Copyright (c) 2016-2022 The Hush developers
|
// Copyright (c) 2016-2022 The Hush developers
|
||||||
/******************************************************************************
|
// Distributed under the GPLv3 software license, see the accompanying
|
||||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
* *
|
// THIS FILE IS AUTOGENERATED, DO NOT MODIFY DIRECTLY
|
||||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
// Instead, update contrib/seeds/nodes_main.txt then run
|
||||||
* the top-level directory of this distribution for the individual copyright *
|
// ./contrib/seeds/generate-seeds.py contrib/seeds > src/chainparamsseeds.h
|
||||||
* holder information and the developer policies on copyright and licensing. *
|
// OR run: make seeds
|
||||||
* *
|
|
||||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
|
||||||
* SuperNET software, including this file may be copied, modified, propagated *
|
|
||||||
* or distributed except according to the terms contained in the LICENSE file *
|
|
||||||
* *
|
|
||||||
* Removal or modification of this copyright notice is prohibited. *
|
|
||||||
* *
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#ifndef HUSH_CHAINPARAMSSEEDS_H
|
#ifndef HUSH_CHAINPARAMSSEEDS_H
|
||||||
#define HUSH_CHAINPARAMSSEEDS_H
|
#define HUSH_CHAINPARAMSSEEDS_H
|
||||||
/**
|
// List of fixed seed nodes for the Hush network
|
||||||
* List of fixed seed nodes for the bitcoin network
|
// Each line contains a BIP155 serialized address.
|
||||||
* AUTOGENERATED by contrib/seeds/generate-seeds.py
|
//
|
||||||
*
|
static const uint8_t chainparams_seed_main[] = {
|
||||||
* Each line contains a 16-byte IPv6 address and a port.
|
0x01,0x04,0xb9,0xf1,0x3d,0x2b,0x00,0x00, // 185.241.61.43
|
||||||
* IPv4 as well as onion addresses are wrapped inside a IPv6 address accordingly.
|
0x01,0x04,0x89,0x4a,0x04,0xc6,0x00,0x00, // 137.74.4.198
|
||||||
*/
|
0x01,0x04,0x95,0x1c,0x66,0xdb,0x00,0x00, // 149.28.102.219
|
||||||
static SeedSpec6 pnSeed6_main[] = {
|
0x01,0x04,0x6b,0xae,0x46,0xfb,0x00,0x00, // 107.174.70.251
|
||||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xec}, 27485},
|
0x04,0x20,0xef,0xad,0x0c,0x95,0x3e,0x61,0xee,0x69,0x57,0x67,0xdb,0x4f,0xb7,0x8d,0xc2,0x35,0x1c,0x6b,0x96,0xf4,0x1f,0x7a,0xb4,0x06,0x09,0x3a,0x64,0x33,0xf4,0x0b,0x2c,0x94,0x00,0x00, // 56wqzfj6mhxgsv3h3nh3pdocguogxfxud55libqjhjsdh5alfsko2iqd.onion
|
||||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0xec}, 27487},
|
0x04,0x20,0x3d,0x24,0x7a,0xec,0xfe,0x60,0x6e,0x3d,0x3d,0xf3,0x4f,0x35,0x12,0x29,0xdb,0x48,0x89,0x71,0x19,0xb9,0xee,0x6a,0xfd,0xb2,0x02,0xa7,0x99,0x89,0xbb,0x69,0x39,0xdb,0x00,0x00, // hushv3h6mbxd2pptj42reko3jcexcgnz5zvp3mqcu6myto3jhhn4yzyd.onion
|
||||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x69,0x6f}, 27485},
|
0x05,0x20,0x42,0xd3,0x08,0x7d,0xad,0x65,0xb4,0x84,0xe8,0x99,0x5e,0xf7,0xc1,0x12,0x36,0xb3,0x0d,0x96,0x30,0x2c,0x70,0xb6,0xde,0x48,0x03,0x44,0xc7,0xab,0x9d,0x1b,0xbb,0x8f,0x00,0x00, // iljqq7nnmw2ij2ezl334cerwwmgzmmbmoc3n4saditd2xhi3xohq.b32.i2p
|
||||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x40,0x69,0x6f}, 27487},
|
|
||||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x48}, 27485},
|
|
||||||
{{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xb9,0x19,0x30,0x48}, 27487}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static SeedSpec6 pnSeed6_test[] = {
|
static const uint8_t chainparams_seed_test[] = {
|
||||||
|
0x01,0x04,0x01,0x02,0x03,0x04,0x00,0x00, // 1.2.3.4
|
||||||
};
|
};
|
||||||
#endif // HUSH_CHAINPARAMSSEEDS_H
|
#endif // HUSH_CHAINPARAMSSEEDS_H
|
||||||
|
|||||||
@@ -24,6 +24,9 @@
|
|||||||
#include "hush_defs.h"
|
#include "hush_defs.h"
|
||||||
#include "importcoin.h"
|
#include "importcoin.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include "util.h"
|
||||||
|
extern bool fZdebug;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* calculate number of bytes for the bitmask, and its number of non-zero bytes
|
* calculate number of bytes for the bitmask, and its number of non-zero bytes
|
||||||
* each bit in the bitmask represents the availability of one output, but the
|
* each bit in the bitmask represents the availability of one output, but the
|
||||||
|
|||||||
12
src/compat.h
12
src/compat.h
@@ -78,6 +78,8 @@ typedef u_int SOCKET;
|
|||||||
#define SOCKET_ERROR -1
|
#define SOCKET_ERROR -1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define WSAEAGAIN EAGAIN
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#ifndef S_IRUSR
|
#ifndef S_IRUSR
|
||||||
#define S_IRUSR 0400
|
#define S_IRUSR 0400
|
||||||
@@ -109,8 +111,14 @@ typedef u_int SOCKET;
|
|||||||
size_t strnlen( const char *start, size_t max_len);
|
size_t strnlen( const char *start, size_t max_len);
|
||||||
#endif // HAVE_DECL_STRNLEN
|
#endif // HAVE_DECL_STRNLEN
|
||||||
|
|
||||||
bool static inline IsSelectableSocket(SOCKET s) {
|
#ifndef WIN32
|
||||||
#ifdef _WIN32
|
typedef void* sockopt_arg_type;
|
||||||
|
#else
|
||||||
|
typedef char* sockopt_arg_type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool static inline IsSelectableSocket(const SOCKET& s) {
|
||||||
|
#ifdef WIN32
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
return (s < FD_SETSIZE);
|
return (s < FD_SETSIZE);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
#include "streams.h"
|
#include "streams.h"
|
||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#include <boost/algorithm/string/classification.hpp>
|
#include <boost/algorithm/string/classification.hpp>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilmoneystr.h"
|
#include "utilmoneystr.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
|
|
||||||
#include <boost/assign/list_of.hpp>
|
#include <boost/assign/list_of.hpp>
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
|||||||
@@ -62,6 +62,13 @@ void static inline WriteLE64(unsigned char* ptr, uint64_t x)
|
|||||||
memcpy(ptr, (char*)&v, 8);
|
memcpy(ptr, (char*)&v, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t static inline ReadBE16(const unsigned char* ptr)
|
||||||
|
{
|
||||||
|
uint16_t x;
|
||||||
|
memcpy((char*)&x, ptr, 2);
|
||||||
|
return be16toh(x);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t static inline ReadBE32(const unsigned char* ptr)
|
uint32_t static inline ReadBE32(const unsigned char* ptr)
|
||||||
{
|
{
|
||||||
uint32_t x;
|
uint32_t x;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#define HUSH_EQUIHASH_H
|
#define HUSH_EQUIHASH_H
|
||||||
|
|
||||||
#include "crypto/sha256.h"
|
#include "crypto/sha256.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "sodium.h"
|
#include "sodium.h"
|
||||||
#include "hush_nk.h"
|
#include "hush_nk.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|||||||
162
src/crypto/sha3.cpp
Normal file
162
src/crypto/sha3.cpp
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
// Copyright (c) 2020 The Bitcoin Core developers
|
||||||
|
// Copyright (c) 2016-2022 The Hush developers
|
||||||
|
// Distributed under the GPLv3 software license, see the accompanying
|
||||||
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
|
|
||||||
|
// Based on https://github.com/mjosaarinen/tiny_sha3/blob/master/sha3.c
|
||||||
|
// by Markku-Juhani O. Saarinen <mjos@iki.fi>
|
||||||
|
|
||||||
|
#include "crypto/sha3.h"
|
||||||
|
#include "crypto/common.h"
|
||||||
|
#include "span.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array> // For std::begin and std::end.
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// Internal implementation code.
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
uint64_t Rotl(uint64_t x, int n) { return (x << n) | (x >> (64 - n)); }
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void KeccakF(uint64_t (&st)[25])
|
||||||
|
{
|
||||||
|
static constexpr uint64_t RNDC[24] = {
|
||||||
|
0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000,
|
||||||
|
0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009,
|
||||||
|
0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
|
||||||
|
0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003,
|
||||||
|
0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a,
|
||||||
|
0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008
|
||||||
|
};
|
||||||
|
static constexpr int ROUNDS = 24;
|
||||||
|
|
||||||
|
for (int round = 0; round < ROUNDS; ++round) {
|
||||||
|
uint64_t bc0, bc1, bc2, bc3, bc4, t;
|
||||||
|
|
||||||
|
// Theta
|
||||||
|
bc0 = st[0] ^ st[5] ^ st[10] ^ st[15] ^ st[20];
|
||||||
|
bc1 = st[1] ^ st[6] ^ st[11] ^ st[16] ^ st[21];
|
||||||
|
bc2 = st[2] ^ st[7] ^ st[12] ^ st[17] ^ st[22];
|
||||||
|
bc3 = st[3] ^ st[8] ^ st[13] ^ st[18] ^ st[23];
|
||||||
|
bc4 = st[4] ^ st[9] ^ st[14] ^ st[19] ^ st[24];
|
||||||
|
t = bc4 ^ Rotl(bc1, 1); st[0] ^= t; st[5] ^= t; st[10] ^= t; st[15] ^= t; st[20] ^= t;
|
||||||
|
t = bc0 ^ Rotl(bc2, 1); st[1] ^= t; st[6] ^= t; st[11] ^= t; st[16] ^= t; st[21] ^= t;
|
||||||
|
t = bc1 ^ Rotl(bc3, 1); st[2] ^= t; st[7] ^= t; st[12] ^= t; st[17] ^= t; st[22] ^= t;
|
||||||
|
t = bc2 ^ Rotl(bc4, 1); st[3] ^= t; st[8] ^= t; st[13] ^= t; st[18] ^= t; st[23] ^= t;
|
||||||
|
t = bc3 ^ Rotl(bc0, 1); st[4] ^= t; st[9] ^= t; st[14] ^= t; st[19] ^= t; st[24] ^= t;
|
||||||
|
|
||||||
|
// Rho Pi
|
||||||
|
t = st[1];
|
||||||
|
bc0 = st[10]; st[10] = Rotl(t, 1); t = bc0;
|
||||||
|
bc0 = st[7]; st[7] = Rotl(t, 3); t = bc0;
|
||||||
|
bc0 = st[11]; st[11] = Rotl(t, 6); t = bc0;
|
||||||
|
bc0 = st[17]; st[17] = Rotl(t, 10); t = bc0;
|
||||||
|
bc0 = st[18]; st[18] = Rotl(t, 15); t = bc0;
|
||||||
|
bc0 = st[3]; st[3] = Rotl(t, 21); t = bc0;
|
||||||
|
bc0 = st[5]; st[5] = Rotl(t, 28); t = bc0;
|
||||||
|
bc0 = st[16]; st[16] = Rotl(t, 36); t = bc0;
|
||||||
|
bc0 = st[8]; st[8] = Rotl(t, 45); t = bc0;
|
||||||
|
bc0 = st[21]; st[21] = Rotl(t, 55); t = bc0;
|
||||||
|
bc0 = st[24]; st[24] = Rotl(t, 2); t = bc0;
|
||||||
|
bc0 = st[4]; st[4] = Rotl(t, 14); t = bc0;
|
||||||
|
bc0 = st[15]; st[15] = Rotl(t, 27); t = bc0;
|
||||||
|
bc0 = st[23]; st[23] = Rotl(t, 41); t = bc0;
|
||||||
|
bc0 = st[19]; st[19] = Rotl(t, 56); t = bc0;
|
||||||
|
bc0 = st[13]; st[13] = Rotl(t, 8); t = bc0;
|
||||||
|
bc0 = st[12]; st[12] = Rotl(t, 25); t = bc0;
|
||||||
|
bc0 = st[2]; st[2] = Rotl(t, 43); t = bc0;
|
||||||
|
bc0 = st[20]; st[20] = Rotl(t, 62); t = bc0;
|
||||||
|
bc0 = st[14]; st[14] = Rotl(t, 18); t = bc0;
|
||||||
|
bc0 = st[22]; st[22] = Rotl(t, 39); t = bc0;
|
||||||
|
bc0 = st[9]; st[9] = Rotl(t, 61); t = bc0;
|
||||||
|
bc0 = st[6]; st[6] = Rotl(t, 20); t = bc0;
|
||||||
|
st[1] = Rotl(t, 44);
|
||||||
|
|
||||||
|
// Chi Iota
|
||||||
|
bc0 = st[0]; bc1 = st[1]; bc2 = st[2]; bc3 = st[3]; bc4 = st[4];
|
||||||
|
st[0] = bc0 ^ (~bc1 & bc2) ^ RNDC[round];
|
||||||
|
st[1] = bc1 ^ (~bc2 & bc3);
|
||||||
|
st[2] = bc2 ^ (~bc3 & bc4);
|
||||||
|
st[3] = bc3 ^ (~bc4 & bc0);
|
||||||
|
st[4] = bc4 ^ (~bc0 & bc1);
|
||||||
|
bc0 = st[5]; bc1 = st[6]; bc2 = st[7]; bc3 = st[8]; bc4 = st[9];
|
||||||
|
st[5] = bc0 ^ (~bc1 & bc2);
|
||||||
|
st[6] = bc1 ^ (~bc2 & bc3);
|
||||||
|
st[7] = bc2 ^ (~bc3 & bc4);
|
||||||
|
st[8] = bc3 ^ (~bc4 & bc0);
|
||||||
|
st[9] = bc4 ^ (~bc0 & bc1);
|
||||||
|
bc0 = st[10]; bc1 = st[11]; bc2 = st[12]; bc3 = st[13]; bc4 = st[14];
|
||||||
|
st[10] = bc0 ^ (~bc1 & bc2);
|
||||||
|
st[11] = bc1 ^ (~bc2 & bc3);
|
||||||
|
st[12] = bc2 ^ (~bc3 & bc4);
|
||||||
|
st[13] = bc3 ^ (~bc4 & bc0);
|
||||||
|
st[14] = bc4 ^ (~bc0 & bc1);
|
||||||
|
bc0 = st[15]; bc1 = st[16]; bc2 = st[17]; bc3 = st[18]; bc4 = st[19];
|
||||||
|
st[15] = bc0 ^ (~bc1 & bc2);
|
||||||
|
st[16] = bc1 ^ (~bc2 & bc3);
|
||||||
|
st[17] = bc2 ^ (~bc3 & bc4);
|
||||||
|
st[18] = bc3 ^ (~bc4 & bc0);
|
||||||
|
st[19] = bc4 ^ (~bc0 & bc1);
|
||||||
|
bc0 = st[20]; bc1 = st[21]; bc2 = st[22]; bc3 = st[23]; bc4 = st[24];
|
||||||
|
st[20] = bc0 ^ (~bc1 & bc2);
|
||||||
|
st[21] = bc1 ^ (~bc2 & bc3);
|
||||||
|
st[22] = bc2 ^ (~bc3 & bc4);
|
||||||
|
st[23] = bc3 ^ (~bc4 & bc0);
|
||||||
|
st[24] = bc4 ^ (~bc0 & bc1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SHA3_256_& SHA3_256_::Write(Span<const unsigned char> data)
|
||||||
|
{
|
||||||
|
if (m_bufsize && m_bufsize + data.size() >= sizeof(m_buffer)) {
|
||||||
|
// Fill the buffer and process it.
|
||||||
|
std::copy(data.begin(), data.begin() + sizeof(m_buffer) - m_bufsize, m_buffer + m_bufsize);
|
||||||
|
data = data.subspan(sizeof(m_buffer) - m_bufsize);
|
||||||
|
m_state[m_pos++] ^= ReadLE64(m_buffer);
|
||||||
|
m_bufsize = 0;
|
||||||
|
if (m_pos == RATE_BUFFERS) {
|
||||||
|
KeccakF(m_state);
|
||||||
|
m_pos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (data.size() >= sizeof(m_buffer)) {
|
||||||
|
// Process chunks directly from the buffer.
|
||||||
|
m_state[m_pos++] ^= ReadLE64(data.data());
|
||||||
|
data = data.subspan(8);
|
||||||
|
if (m_pos == RATE_BUFFERS) {
|
||||||
|
KeccakF(m_state);
|
||||||
|
m_pos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data.size()) {
|
||||||
|
// Keep the remainder in the buffer.
|
||||||
|
std::copy(data.begin(), data.end(), m_buffer + m_bufsize);
|
||||||
|
m_bufsize += data.size();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHA3_256_& SHA3_256_::Finalize(Span<unsigned char> output)
|
||||||
|
{
|
||||||
|
assert(output.size() == OUTPUT_SIZE);
|
||||||
|
std::fill(m_buffer + m_bufsize, m_buffer + sizeof(m_buffer), 0);
|
||||||
|
m_buffer[m_bufsize] ^= 0x06;
|
||||||
|
m_state[m_pos] ^= ReadLE64(m_buffer);
|
||||||
|
m_state[RATE_BUFFERS - 1] ^= 0x8000000000000000;
|
||||||
|
KeccakF(m_state);
|
||||||
|
for (unsigned i = 0; i < 4; ++i) {
|
||||||
|
WriteLE64(output.data() + 8 * i, m_state[i]);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHA3_256_& SHA3_256_::Reset()
|
||||||
|
{
|
||||||
|
m_bufsize = 0;
|
||||||
|
m_pos = 0;
|
||||||
|
std::fill(std::begin(m_state), std::end(m_state), 0);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
42
src/crypto/sha3.h
Normal file
42
src/crypto/sha3.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// Copyright (c) 2020 The Bitcoin Core developers
|
||||||
|
// Copyright (c) 2016-2022 The Hush developers
|
||||||
|
// Distributed under the GPLv3 software license, see the accompanying
|
||||||
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
|
|
||||||
|
#ifndef HUSH_CRYPTO_SHA3_H
|
||||||
|
#define HUSH_CRYPTO_SHA3_H
|
||||||
|
|
||||||
|
#include "span.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
//! The Keccak-f[1600] transform.
|
||||||
|
void KeccakF(uint64_t (&st)[25]);
|
||||||
|
|
||||||
|
class SHA3_256_
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint64_t m_state[25] = {0};
|
||||||
|
unsigned char m_buffer[8];
|
||||||
|
unsigned m_bufsize = 0;
|
||||||
|
unsigned m_pos = 0;
|
||||||
|
|
||||||
|
//! Sponge rate in bits.
|
||||||
|
static constexpr unsigned RATE_BITS = 1088;
|
||||||
|
|
||||||
|
//! Sponge rate expressed as a multiple of the buffer size.
|
||||||
|
static constexpr unsigned RATE_BUFFERS = RATE_BITS / (8 * sizeof(m_buffer));
|
||||||
|
|
||||||
|
static_assert(RATE_BITS % (8 * sizeof(m_buffer)) == 0, "Rate must be a multiple of 8 bytes");
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr size_t OUTPUT_SIZE = 32;
|
||||||
|
|
||||||
|
SHA3_256_() {}
|
||||||
|
SHA3_256_& Write(Span<const unsigned char> data);
|
||||||
|
SHA3_256_& Finalize(Span<unsigned char> output);
|
||||||
|
SHA3_256_& Reset();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HUSH_CRYPTO_SHA3_H
|
||||||
@@ -19,8 +19,6 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include "deprecation.h"
|
#include "deprecation.h"
|
||||||
|
|
||||||
#include "alert.h"
|
|
||||||
#include "clientversion.h"
|
#include "clientversion.h"
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "ui_interface.h"
|
#include "ui_interface.h"
|
||||||
@@ -51,7 +49,6 @@ void EnforceNodeDeprecation(int nHeight, bool forceLogging, bool fThread) {
|
|||||||
DEPRECATION_HEIGHT) + " " +
|
DEPRECATION_HEIGHT) + " " +
|
||||||
_("You should upgrade to the latest version of Hush.");
|
_("You should upgrade to the latest version of Hush.");
|
||||||
LogPrintf("*** %s\n", msg);
|
LogPrintf("*** %s\n", msg);
|
||||||
CAlert::Notify(msg, fThread);
|
|
||||||
uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_ERROR);
|
uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_ERROR);
|
||||||
}
|
}
|
||||||
StartShutdown();
|
StartShutdown();
|
||||||
@@ -60,7 +57,6 @@ void EnforceNodeDeprecation(int nHeight, bool forceLogging, bool fThread) {
|
|||||||
DEPRECATION_HEIGHT) + " " +
|
DEPRECATION_HEIGHT) + " " +
|
||||||
_("You should upgrade to the latest version of Hush.");
|
_("You should upgrade to the latest version of Hush.");
|
||||||
LogPrintf("*** %s\n", msg);
|
LogPrintf("*** %s\n", msg);
|
||||||
CAlert::Notify(msg, fThread);
|
|
||||||
uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_WARNING);
|
uiInterface.ThreadSafeMessageBox(msg, "", CClientUIInterface::MSG_WARNING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "serialize.h"
|
#include "serialize.h"
|
||||||
#include "streams.h"
|
#include "streams.h"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "ui_interface.h"
|
#include "ui_interface.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
|
|
||||||
#include <boost/filesystem/operations.hpp>
|
#include <boost/filesystem/operations.hpp>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "serialize.h"
|
#include "serialize.h"
|
||||||
#include "streams.h"
|
#include "streams.h"
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#include "primitives/block.h"
|
#include "primitives/block.h"
|
||||||
#include "rpc/server.h"
|
#include "rpc/server.h"
|
||||||
#include "streams.h"
|
#include "streams.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
|
|
||||||
extern UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false);
|
extern UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool txDetails = false);
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include "streams.h"
|
#include "streams.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Test that removing #1144 succeeded by verifying the hash of a transaction is over the entire serialized form.
|
Test that removing #1144 succeeded by verifying the hash of a transaction is over the entire serialized form.
|
||||||
|
|||||||
67
src/hash.h
67
src/hash.h
@@ -28,9 +28,7 @@
|
|||||||
#include "serialize.h"
|
#include "serialize.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#include "sodium.h"
|
#include "sodium.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
typedef uint256 ChainCode;
|
typedef uint256 ChainCode;
|
||||||
@@ -48,6 +46,18 @@ public:
|
|||||||
sha.Reset().Write(buf, sha.OUTPUT_SIZE).Finalize(hash);
|
sha.Reset().Write(buf, sha.OUTPUT_SIZE).Finalize(hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CHash256& Write(Span<const unsigned char> input) {
|
||||||
|
sha.Write(input.data(), input.size());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Finalize(Span<unsigned char> output) {
|
||||||
|
assert(output.size() == OUTPUT_SIZE);
|
||||||
|
unsigned char buf[CSHA256::OUTPUT_SIZE];
|
||||||
|
sha.Finalize(buf);
|
||||||
|
sha.Reset().Write(buf, CSHA256::OUTPUT_SIZE).Finalize(output.data());
|
||||||
|
}
|
||||||
|
|
||||||
CHash256& Write(const unsigned char *data, size_t len) {
|
CHash256& Write(const unsigned char *data, size_t len) {
|
||||||
sha.Write(data, len);
|
sha.Write(data, len);
|
||||||
return *this;
|
return *this;
|
||||||
@@ -120,6 +130,23 @@ inline uint256 Hash(const T1 p1begin, const T1 p1end,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Compute the 256-bit hash of an object. */
|
||||||
|
template<typename T>
|
||||||
|
inline uint256 Hash(const T& in1)
|
||||||
|
{
|
||||||
|
uint256 result;
|
||||||
|
CHash256().Write(MakeUCharSpan(in1)).Finalize(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Compute the 256-bit hash of the concatenation of two objects. */
|
||||||
|
template<typename T1, typename T2>
|
||||||
|
inline uint256 Hash(const T1& in1, const T2& in2) {
|
||||||
|
uint256 result;
|
||||||
|
CHash256().Write(MakeUCharSpan(in1)).Write(MakeUCharSpan(in2)).Finalize(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/** Compute the 160-bit hash an object. */
|
/** Compute the 160-bit hash an object. */
|
||||||
template<typename T1>
|
template<typename T1>
|
||||||
inline uint160 Hash160(const T1 pbegin, const T1 pend)
|
inline uint160 Hash160(const T1 pbegin, const T1 pend)
|
||||||
@@ -178,6 +205,40 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Reads data from an underlying stream, while hashing the read data. */
|
||||||
|
template<typename Source>
|
||||||
|
class CHashVerifier : public CHashWriter
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Source* source;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit CHashVerifier(Source* source_) : CHashWriter(source_->GetType(), source_->GetVersion()), source(source_) {}
|
||||||
|
|
||||||
|
void read(char* pch, size_t nSize)
|
||||||
|
{
|
||||||
|
source->read(pch, nSize);
|
||||||
|
this->write(pch, nSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ignore(size_t nSize)
|
||||||
|
{
|
||||||
|
char data[1024];
|
||||||
|
while (nSize > 0) {
|
||||||
|
size_t now = std::min<size_t>(nSize, 1024);
|
||||||
|
read(data, now);
|
||||||
|
nSize -= now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
CHashVerifier<Source>& operator>>(T&& obj)
|
||||||
|
{
|
||||||
|
// Unserialize from this stream
|
||||||
|
::Unserialize(*this, obj);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/** A writer stream (for serialization) that computes a 256-bit BLAKE2b hash. */
|
/** A writer stream (for serialization) that computes a 256-bit BLAKE2b hash. */
|
||||||
class CBLAKE2bWriter
|
class CBLAKE2bWriter
|
||||||
@@ -221,6 +282,7 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/** Compute the 256-bit hash of an object's serialization. */
|
/** Compute the 256-bit hash of an object's serialization. */
|
||||||
template<typename T>
|
template<typename T>
|
||||||
uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
|
uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
|
||||||
@@ -230,6 +292,7 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL
|
|||||||
return ss.GetHash();
|
return ss.GetHash();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char>& vDataToHash);
|
unsigned int MurmurHash3(unsigned int nHashSeed, const std::vector<unsigned char>& vDataToHash);
|
||||||
|
|
||||||
void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]);
|
void BIP32Hash(const ChainCode &chainCode, unsigned int nChild, unsigned char header, const unsigned char data[32], unsigned char output[64]);
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "ui_interface.h"
|
#include "ui_interface.h"
|
||||||
#include <boost/algorithm/string.hpp> // boost::trim
|
#include <boost/algorithm/string.hpp> // boost::trim
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,13 @@
|
|||||||
#include "chainparamsbase.h"
|
#include "chainparamsbase.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "util/strencodings.h"
|
||||||
#include "netbase.h"
|
#include "netbase.h"
|
||||||
#include "rpc/protocol.h" // For HTTP status codes
|
#include "rpc/protocol.h" // For HTTP status codes
|
||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
#include "ui_interface.h"
|
#include "ui_interface.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -22,6 +24,7 @@
|
|||||||
#include <event2/http.h>
|
#include <event2/http.h>
|
||||||
#include <event2/thread.h>
|
#include <event2/thread.h>
|
||||||
#include <event2/buffer.h>
|
#include <event2/buffer.h>
|
||||||
|
#include <event2/bufferevent.h>
|
||||||
#include <event2/util.h>
|
#include <event2/util.h>
|
||||||
#include <event2/keyvalq_struct.h>
|
#include <event2/keyvalq_struct.h>
|
||||||
|
|
||||||
@@ -157,6 +160,7 @@ public:
|
|||||||
boost::unique_lock<boost::mutex> lock(cs);
|
boost::unique_lock<boost::mutex> lock(cs);
|
||||||
return queue.size();
|
return queue.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t MaxDepth()
|
size_t MaxDepth()
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::mutex> lock(cs);
|
boost::unique_lock<boost::mutex> lock(cs);
|
||||||
@@ -167,6 +171,7 @@ public:
|
|||||||
boost::unique_lock<boost::mutex> lock(cs);
|
boost::unique_lock<boost::mutex> lock(cs);
|
||||||
return numThreads;
|
return numThreads;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HTTPPathHandler
|
struct HTTPPathHandler
|
||||||
@@ -196,7 +201,6 @@ std::vector<HTTPPathHandler> pathHandlers;
|
|||||||
//! Bound listening sockets
|
//! Bound listening sockets
|
||||||
std::vector<evhttp_bound_socket *> boundSockets;
|
std::vector<evhttp_bound_socket *> boundSockets;
|
||||||
|
|
||||||
|
|
||||||
int getWorkQueueDepth()
|
int getWorkQueueDepth()
|
||||||
{
|
{
|
||||||
return workQueue->Depth();
|
return workQueue->Depth();
|
||||||
@@ -227,12 +231,17 @@ static bool ClientAllowed(const CNetAddr& netaddr)
|
|||||||
static bool InitHTTPAllowList()
|
static bool InitHTTPAllowList()
|
||||||
{
|
{
|
||||||
rpc_allow_subnets.clear();
|
rpc_allow_subnets.clear();
|
||||||
rpc_allow_subnets.push_back(CSubNet("127.0.0.0/8")); // always allow IPv4 local subnet
|
CNetAddr localv4;
|
||||||
rpc_allow_subnets.push_back(CSubNet("::1")); // always allow IPv6 localhost
|
CNetAddr localv6;
|
||||||
|
LookupHost("127.0.0.1", localv4, false);
|
||||||
|
LookupHost("::1", localv6, false);
|
||||||
|
rpc_allow_subnets.push_back(CSubNet(localv4, 8)); // always allow IPv4 local subnet
|
||||||
|
rpc_allow_subnets.push_back(CSubNet(localv6)); // always allow IPv6 localhost
|
||||||
if (mapMultiArgs.count("-rpcallowip")) {
|
if (mapMultiArgs.count("-rpcallowip")) {
|
||||||
const std::vector<std::string>& vAllow = mapMultiArgs["-rpcallowip"];
|
const std::vector<std::string>& vAllow = mapMultiArgs["-rpcallowip"];
|
||||||
BOOST_FOREACH (std::string strAllow, vAllow) {
|
BOOST_FOREACH (std::string strAllow, vAllow) {
|
||||||
CSubNet subnet(strAllow);
|
CSubNet subnet;
|
||||||
|
LookupSubNet(strAllow.c_str(), subnet);
|
||||||
if (!subnet.IsValid()) {
|
if (!subnet.IsValid()) {
|
||||||
uiInterface.ThreadSafeMessageBox(
|
uiInterface.ThreadSafeMessageBox(
|
||||||
strprintf("Invalid -rpcallowip subnet specification: %s. Valid are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24).", strAllow),
|
strprintf("Invalid -rpcallowip subnet specification: %s. Valid are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24).", strAllow),
|
||||||
@@ -273,6 +282,16 @@ static std::string RequestMethodString(HTTPRequest::RequestMethod m)
|
|||||||
/** HTTP request callback */
|
/** HTTP request callback */
|
||||||
static void http_request_cb(struct evhttp_request* req, void* arg)
|
static void http_request_cb(struct evhttp_request* req, void* arg)
|
||||||
{
|
{
|
||||||
|
// Disable reading to work around a libevent bug, fixed in 2.2.0.
|
||||||
|
if (event_get_version_number() >= 0x02010600 && event_get_version_number() < 0x02020001) {
|
||||||
|
evhttp_connection* conn = evhttp_request_get_connection(req);
|
||||||
|
if (conn) {
|
||||||
|
bufferevent* bev = evhttp_connection_get_bufferevent(conn);
|
||||||
|
if (bev) {
|
||||||
|
bufferevent_disable(bev, EV_READ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
std::unique_ptr<HTTPRequest> hreq(new HTTPRequest(req));
|
std::unique_ptr<HTTPRequest> hreq(new HTTPRequest(req));
|
||||||
|
|
||||||
// Early address-based allow check
|
// Early address-based allow check
|
||||||
@@ -315,11 +334,10 @@ static void http_request_cb(struct evhttp_request* req, void* arg)
|
|||||||
if (i != iend) {
|
if (i != iend) {
|
||||||
std::unique_ptr<HTTPWorkItem> item(new HTTPWorkItem(hreq.release(), path, i->handler));
|
std::unique_ptr<HTTPWorkItem> item(new HTTPWorkItem(hreq.release(), path, i->handler));
|
||||||
assert(workQueue);
|
assert(workQueue);
|
||||||
if (workQueue->Enqueue(item.get())) {
|
if (workQueue->Enqueue(item.get()))
|
||||||
item.release(); /* if true, queue took ownership */
|
item.release(); /* if true, queue took ownership */
|
||||||
} else {
|
else
|
||||||
item->req->WriteReply(HTTP_INTERNAL, strprintf("Work queue depth %d exceeded", workQueue->Depth() ));
|
item->req->WriteReply(HTTP_INTERNAL, "Work queue depth exceeded");
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
hreq->WriteReply(HTTP_NOTFOUND);
|
hreq->WriteReply(HTTP_NOTFOUND);
|
||||||
}
|
}
|
||||||
@@ -541,7 +559,7 @@ struct event_base* EventBase()
|
|||||||
static void httpevent_callback_fn(evutil_socket_t, short, void* data)
|
static void httpevent_callback_fn(evutil_socket_t, short, void* data)
|
||||||
{
|
{
|
||||||
// Static handler: simply call inner handler
|
// Static handler: simply call inner handler
|
||||||
HTTPEvent *self = ((HTTPEvent*)data);
|
HTTPEvent *self = static_cast<HTTPEvent*>(data);
|
||||||
self->handler();
|
self->handler();
|
||||||
if (self->deleteWhenTriggered)
|
if (self->deleteWhenTriggered)
|
||||||
delete self;
|
delete self;
|
||||||
@@ -628,8 +646,21 @@ void HTTPRequest::WriteReply(int nStatus, const std::string& strReply)
|
|||||||
struct evbuffer* evb = evhttp_request_get_output_buffer(req);
|
struct evbuffer* evb = evhttp_request_get_output_buffer(req);
|
||||||
assert(evb);
|
assert(evb);
|
||||||
evbuffer_add(evb, strReply.data(), strReply.size());
|
evbuffer_add(evb, strReply.data(), strReply.size());
|
||||||
HTTPEvent* ev = new HTTPEvent(eventBase, true,
|
auto req_copy = req;
|
||||||
boost::bind(evhttp_send_reply, req, nStatus, (const char*)NULL, (struct evbuffer *)NULL));
|
HTTPEvent* ev = new HTTPEvent(eventBase, true, [req_copy, nStatus]{
|
||||||
|
evhttp_send_reply(req_copy, nStatus, (const char*)NULL, (struct evbuffer *)NULL);
|
||||||
|
// Re-enable reading from the socket. This is the second part of the libevent
|
||||||
|
// workaround above.
|
||||||
|
if (event_get_version_number() >= 0x02010600 && event_get_version_number() < 0x02020001) {
|
||||||
|
evhttp_connection* conn = evhttp_request_get_connection(req_copy);
|
||||||
|
if (conn) {
|
||||||
|
bufferevent* bev = evhttp_connection_get_bufferevent(conn);
|
||||||
|
if (bev) {
|
||||||
|
bufferevent_enable(bev, EV_READ | EV_WRITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
ev->trigger(0);
|
ev->trigger(0);
|
||||||
replySent = true;
|
replySent = true;
|
||||||
req = 0; // transferred back to main thread
|
req = 0; // transferred back to main thread
|
||||||
@@ -644,7 +675,7 @@ CService HTTPRequest::GetPeer()
|
|||||||
const char* address = "";
|
const char* address = "";
|
||||||
uint16_t port = 0;
|
uint16_t port = 0;
|
||||||
evhttp_connection_get_peer(con, (char**)&address, &port);
|
evhttp_connection_get_peer(con, (char**)&address, &port);
|
||||||
peer = CService(address, port);
|
peer = LookupNumeric(address, port);
|
||||||
}
|
}
|
||||||
return peer;
|
return peer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilmoneystr.h"
|
#include "utilmoneystr.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/assign/list_of.hpp>
|
#include <boost/assign/list_of.hpp>
|
||||||
|
|||||||
441
src/i2p.cpp
Normal file
441
src/i2p.cpp
Normal file
@@ -0,0 +1,441 @@
|
|||||||
|
// Copyright (c) 2020-2020 The Bitcoin Core developers
|
||||||
|
// Copyright (c) 2016-2022 The Hush developers
|
||||||
|
// Distributed under the GPLv3 software license, see the accompanying
|
||||||
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
|
|
||||||
|
#include <init.h>
|
||||||
|
#include <chainparams.h>
|
||||||
|
#include <compat.h>
|
||||||
|
#include <compat/endian.h>
|
||||||
|
#include <crypto/sha256.h>
|
||||||
|
#include <fs.h>
|
||||||
|
#include <i2p.h>
|
||||||
|
#include <netbase.h>
|
||||||
|
#include <random.h>
|
||||||
|
#include <util/strencodings.h>
|
||||||
|
#include <tinyformat.h>
|
||||||
|
#include <util/readwritefile.h>
|
||||||
|
#include <util/sock.h>
|
||||||
|
#include <util/spanparsing.h>
|
||||||
|
#include <util.h>
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <memory>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace i2p {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swap Standard Base64 <-> I2P Base64.
|
||||||
|
* Standard Base64 uses `+` and `/` as last two characters of its alphabet.
|
||||||
|
* I2P Base64 uses `-` and `~` respectively.
|
||||||
|
* So it is easy to detect in which one is the input and convert to the other.
|
||||||
|
* @param[in] from Input to convert.
|
||||||
|
* @return converted `from`
|
||||||
|
*/
|
||||||
|
static std::string SwapBase64(const std::string& from)
|
||||||
|
{
|
||||||
|
std::string to;
|
||||||
|
to.resize(from.size());
|
||||||
|
for (size_t i = 0; i < from.size(); ++i) {
|
||||||
|
switch (from[i]) {
|
||||||
|
case '-':
|
||||||
|
to[i] = '+';
|
||||||
|
break;
|
||||||
|
case '~':
|
||||||
|
to[i] = '/';
|
||||||
|
break;
|
||||||
|
case '+':
|
||||||
|
to[i] = '-';
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
to[i] = '~';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
to[i] = from[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return to;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode an I2P-style Base64 string.
|
||||||
|
* @param[in] i2p_b64 I2P-style Base64 string.
|
||||||
|
* @return decoded `i2p_b64`
|
||||||
|
* @throw std::runtime_error if decoding fails
|
||||||
|
*/
|
||||||
|
static Binary DecodeI2PBase64(const std::string& i2p_b64)
|
||||||
|
{
|
||||||
|
const std::string& std_b64 = SwapBase64(i2p_b64);
|
||||||
|
bool invalid;
|
||||||
|
Binary decoded = DecodeBase64(std_b64.c_str(), &invalid);
|
||||||
|
if (invalid) {
|
||||||
|
throw std::runtime_error(strprintf("Cannot decode Base64: \"%s\"", i2p_b64));
|
||||||
|
}
|
||||||
|
return decoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derive the .b32.i2p address of an I2P destination (binary).
|
||||||
|
* @param[in] dest I2P destination.
|
||||||
|
* @return the address that corresponds to `dest`
|
||||||
|
* @throw std::runtime_error if conversion fails
|
||||||
|
*/
|
||||||
|
static CNetAddr DestBinToAddr(const Binary& dest)
|
||||||
|
{
|
||||||
|
CSHA256 hasher;
|
||||||
|
hasher.Write(dest.data(), dest.size());
|
||||||
|
unsigned char hash[CSHA256::OUTPUT_SIZE];
|
||||||
|
hasher.Finalize(hash);
|
||||||
|
|
||||||
|
CNetAddr addr;
|
||||||
|
const std::string addr_str = EncodeBase32(hash, false) + ".b32.i2p";
|
||||||
|
if (!addr.SetSpecial(addr_str)) {
|
||||||
|
throw std::runtime_error(strprintf("Cannot parse I2P address: \"%s\"", addr_str));
|
||||||
|
}
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derive the .b32.i2p address of an I2P destination (I2P-style Base64).
|
||||||
|
* @param[in] dest I2P destination.
|
||||||
|
* @return the address that corresponds to `dest`
|
||||||
|
* @throw std::runtime_error if conversion fails
|
||||||
|
*/
|
||||||
|
static CNetAddr DestB64ToAddr(const std::string& dest)
|
||||||
|
{
|
||||||
|
const Binary& decoded = DecodeI2PBase64(dest);
|
||||||
|
return DestBinToAddr(decoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace sam {
|
||||||
|
|
||||||
|
Session::Session(const fs::path& private_key_file,
|
||||||
|
const CService& control_host)
|
||||||
|
: m_private_key_file(private_key_file), m_control_host(control_host),
|
||||||
|
m_control_sock(std::unique_ptr<Sock>(new Sock(INVALID_SOCKET)))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Session::~Session()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Session::Check()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
LOCK(cs_i2p);
|
||||||
|
CreateIfNotCreatedAlready();
|
||||||
|
return true;
|
||||||
|
} catch (const std::runtime_error& e) {
|
||||||
|
LogPrint("i2p","I2P: Error Checking Session: %s\n", e.what());
|
||||||
|
CheckControlSock();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Session::Listen(Connection& conn)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
LOCK(cs_i2p);
|
||||||
|
CreateIfNotCreatedAlready();
|
||||||
|
conn.me = m_my_addr;
|
||||||
|
conn.sock = StreamAccept();
|
||||||
|
return true;
|
||||||
|
} catch (const std::runtime_error& e) {
|
||||||
|
LogPrint("i2p","I2P: Error listening: %s\n", e.what());
|
||||||
|
CheckControlSock();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Session::Accept(Connection& conn)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
// boost::this_thread::interruption_point();
|
||||||
|
if (ShutdownRequested()) {
|
||||||
|
Disconnect();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Sock::Event occurred;
|
||||||
|
if (!conn.sock->Wait(std::chrono::milliseconds{MAX_WAIT_FOR_IO}, Sock::RECV, &occurred)) {
|
||||||
|
throw std::runtime_error("wait on socket failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((occurred & Sock::RECV) == 0) {
|
||||||
|
// Timeout, no incoming connections within MAX_WAIT_FOR_IO.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& peer_dest =
|
||||||
|
conn.sock->RecvUntilTerminator('\n', std::chrono::milliseconds{MAX_WAIT_FOR_IO}, MAX_MSG_SIZE);
|
||||||
|
|
||||||
|
if (ShutdownRequested()) {
|
||||||
|
Disconnect();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.peer = CService(DestB64ToAddr(peer_dest), Params().GetDefaultPort());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (const std::runtime_error& e) {
|
||||||
|
LogPrint("i2p","I2P: Error accepting: %s\n", e.what());
|
||||||
|
CheckControlSock();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Session::Connect(const CService& to, Connection& conn, bool& proxy_error)
|
||||||
|
{
|
||||||
|
proxy_error = true;
|
||||||
|
|
||||||
|
std::string session_id;
|
||||||
|
std::unique_ptr<Sock> sock;
|
||||||
|
conn.peer = to;
|
||||||
|
|
||||||
|
try {
|
||||||
|
{
|
||||||
|
LOCK(cs_i2p);
|
||||||
|
CreateIfNotCreatedAlready();
|
||||||
|
session_id = m_session_id;
|
||||||
|
conn.me = m_my_addr;
|
||||||
|
sock = Hello();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Reply& lookup_reply =
|
||||||
|
SendRequestAndGetReply(*sock, strprintf("NAMING LOOKUP NAME=%s", to.ToStringIP()));
|
||||||
|
|
||||||
|
const std::string& dest = lookup_reply.Get("VALUE");
|
||||||
|
|
||||||
|
const Reply& connect_reply = SendRequestAndGetReply(
|
||||||
|
*sock, strprintf("STREAM CONNECT ID=%s DESTINATION=%s SILENT=false", session_id, dest),
|
||||||
|
false);
|
||||||
|
|
||||||
|
const std::string& result = connect_reply.Get("RESULT");
|
||||||
|
|
||||||
|
if (result == "OK") {
|
||||||
|
conn.sock = std::move(sock);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == "INVALID_ID") {
|
||||||
|
LOCK(cs_i2p);
|
||||||
|
Disconnect();
|
||||||
|
throw std::runtime_error("Invalid session id");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == "CANT_REACH_PEER" || result == "TIMEOUT" || "KEY_NOT_FOUND") {
|
||||||
|
proxy_error = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw std::runtime_error(strprintf("\"%s\"", connect_reply.full));
|
||||||
|
} catch (const std::runtime_error& e) {
|
||||||
|
LogPrint("i2p","I2P: Error connecting to %s: %s\n", to.ToString(), e.what());
|
||||||
|
CheckControlSock();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private methods
|
||||||
|
|
||||||
|
std::string Session::Reply::Get(const std::string& key) const
|
||||||
|
{
|
||||||
|
const auto& pos = keys.find(key);
|
||||||
|
if (pos == keys.end() || !pos->second.has_value()) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
strprintf("Missing %s= in the reply to \"%s\": \"%s\"", key, request, full));
|
||||||
|
}
|
||||||
|
return pos->second.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
Session::Reply Session::SendRequestAndGetReply(const Sock& sock,
|
||||||
|
const std::string& request,
|
||||||
|
bool check_result_ok) const
|
||||||
|
{
|
||||||
|
sock.SendComplete(request + "\n", std::chrono::milliseconds{MAX_WAIT_FOR_IO});
|
||||||
|
|
||||||
|
Reply reply;
|
||||||
|
|
||||||
|
// Don't log the full "SESSION CREATE ..." because it contains our private key.
|
||||||
|
reply.request = request.substr(0, 14) == "SESSION CREATE" ? "SESSION CREATE ..." : request;
|
||||||
|
|
||||||
|
// It could take a few minutes for the I2P router to reply as it is querying the I2P network
|
||||||
|
// (when doing name lookup, for example).
|
||||||
|
|
||||||
|
reply.full = sock.RecvUntilTerminator('\n', std::chrono::minutes{3}, MAX_MSG_SIZE);
|
||||||
|
|
||||||
|
for (const auto& kv : spanparsing::Split(reply.full, ' ')) {
|
||||||
|
const auto& pos = std::find(kv.begin(), kv.end(), '=');
|
||||||
|
if (pos != kv.end()) {
|
||||||
|
reply.keys.emplace(std::string{kv.begin(), pos}, std::string{pos + 1, kv.end()});
|
||||||
|
} else {
|
||||||
|
reply.keys.emplace(std::string{kv.begin(), kv.end()}, boost::none);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LogPrint("i2p","I2P: Handshake reply %s\n", reply.full);
|
||||||
|
|
||||||
|
if (check_result_ok && reply.Get("RESULT") != "OK") {
|
||||||
|
if (!ShutdownRequested()) {
|
||||||
|
throw std::runtime_error(strprintf("Unexpected reply to \"%s\": \"%s\"", request, reply.full));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Sock> Session::Hello() const
|
||||||
|
{
|
||||||
|
auto sock = CreateSock(m_control_host);
|
||||||
|
|
||||||
|
if (!sock) {
|
||||||
|
throw std::runtime_error("Cannot create socket");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ConnectSocketDirectly(m_control_host, *sock, nConnectTimeout)) {
|
||||||
|
throw std::runtime_error(strprintf("Cannot connect to %s", m_control_host.ToString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
SendRequestAndGetReply(*sock, "HELLO VERSION MIN=3.1 MAX=3.1");
|
||||||
|
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::CheckControlSock()
|
||||||
|
{
|
||||||
|
LOCK(cs_i2p);
|
||||||
|
|
||||||
|
std::string errmsg;
|
||||||
|
if (!m_control_sock->IsConnected(errmsg)) {
|
||||||
|
LogPrint("i2p","I2P: Control socket error: %s\n", errmsg);
|
||||||
|
Disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::DestGenerate(const Sock& sock)
|
||||||
|
{
|
||||||
|
// https://geti2p.net/spec/common-structures#key-certificates
|
||||||
|
// "7" or "EdDSA_SHA512_Ed25519" - "Recent Router Identities and Destinations".
|
||||||
|
// Use "7" because i2pd <2.24.0 does not recognize the textual form.
|
||||||
|
const Reply& reply = SendRequestAndGetReply(sock, "DEST GENERATE SIGNATURE_TYPE=7", false);
|
||||||
|
|
||||||
|
m_private_key = DecodeI2PBase64(reply.Get("PRIV"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::GenerateAndSavePrivateKey(const Sock& sock)
|
||||||
|
{
|
||||||
|
DestGenerate(sock);
|
||||||
|
|
||||||
|
// umask is set to 077 in init.cpp, which is ok (unless -sysperms is given)
|
||||||
|
if (!WriteBinaryFile(m_private_key_file,
|
||||||
|
std::string(m_private_key.begin(), m_private_key.end()))) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
strprintf("Cannot save I2P private key to %s", m_private_key_file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Binary Session::MyDestination() const
|
||||||
|
{
|
||||||
|
// From https://geti2p.net/spec/common-structures#destination:
|
||||||
|
// "They are 387 bytes plus the certificate length specified at bytes 385-386, which may be
|
||||||
|
// non-zero"
|
||||||
|
static constexpr size_t DEST_LEN_BASE = 387;
|
||||||
|
static constexpr size_t CERT_LEN_POS = 385;
|
||||||
|
|
||||||
|
uint16_t cert_len;
|
||||||
|
memcpy(&cert_len, &m_private_key.at(CERT_LEN_POS), sizeof(cert_len));
|
||||||
|
cert_len = be16toh(cert_len);
|
||||||
|
|
||||||
|
const size_t dest_len = DEST_LEN_BASE + cert_len;
|
||||||
|
|
||||||
|
return Binary{m_private_key.begin(), m_private_key.begin() + dest_len};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::CreateIfNotCreatedAlready()
|
||||||
|
{
|
||||||
|
LOCK(cs_i2p);
|
||||||
|
|
||||||
|
std::string errmsg;
|
||||||
|
if (m_control_sock->IsConnected(errmsg)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogPrint("i2p","I2P: Creating SAM session with %s\n", m_control_host.ToString());
|
||||||
|
|
||||||
|
auto sock = Hello();
|
||||||
|
|
||||||
|
const std::pair<bool,std::string> i2pRead = ReadBinaryFile(m_private_key_file);
|
||||||
|
if (i2pRead.first) {
|
||||||
|
m_private_key.assign(i2pRead.second.begin(), i2pRead.second.end());
|
||||||
|
} else {
|
||||||
|
GenerateAndSavePrivateKey(*sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& session_id = GetRandHash().GetHex().substr(0, 10); // full is an overkill, too verbose in the logs
|
||||||
|
const std::string& private_key_b64 = SwapBase64(EncodeBase64(m_private_key));
|
||||||
|
|
||||||
|
SendRequestAndGetReply(*sock, strprintf("SESSION CREATE STYLE=STREAM ID=%s DESTINATION=%s",
|
||||||
|
session_id, private_key_b64));
|
||||||
|
|
||||||
|
m_my_addr = CService(DestBinToAddr(MyDestination()), Params().GetDefaultPort());
|
||||||
|
m_session_id = session_id;
|
||||||
|
m_control_sock = std::move(sock);
|
||||||
|
|
||||||
|
LogPrint("i2p","I2P: SAM session created: session id=%s, my address=%s\n", m_session_id,
|
||||||
|
m_my_addr.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Sock> Session::StreamAccept()
|
||||||
|
{
|
||||||
|
auto sock = Hello();
|
||||||
|
|
||||||
|
const Reply& reply = SendRequestAndGetReply(
|
||||||
|
*sock, strprintf("STREAM ACCEPT ID=%s SILENT=false", m_session_id), false);
|
||||||
|
|
||||||
|
const std::string& result = reply.Get("RESULT");
|
||||||
|
|
||||||
|
if (result == "OK") {
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result == "INVALID_ID") {
|
||||||
|
// If our session id is invalid, then force session re-creation on next usage.
|
||||||
|
Disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw std::runtime_error(strprintf("\"%s\"", reply.full));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Session::Disconnect()
|
||||||
|
{
|
||||||
|
LOCK(cs_i2p);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (m_control_sock->Get() != INVALID_SOCKET) {
|
||||||
|
if (m_session_id.empty()) {
|
||||||
|
LogPrint("i2p","I2P: Destroying incomplete session\n");
|
||||||
|
} else {
|
||||||
|
LogPrint("i2p","I2P: Destroying session %s\n", m_session_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_control_sock->Reset();
|
||||||
|
m_session_id.clear();
|
||||||
|
}
|
||||||
|
catch(std::bad_alloc&)
|
||||||
|
{
|
||||||
|
// when the node is shutting down, the call above might use invalid memory resulting in a
|
||||||
|
// std::bad_alloc exception when instantiating internal objs for handling log category
|
||||||
|
LogPrintf("(node is probably shutting down) Destroying session=%d\n", m_session_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
} // namespace sam
|
||||||
|
} // namespace i2p
|
||||||
256
src/i2p.h
Normal file
256
src/i2p.h
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
// Copyright (c) 2020-2020 The Bitcoin Core developers
|
||||||
|
// Copyright (c) 2016-2022 The Hush developers
|
||||||
|
// Distributed under the GPLv3 software license, see the accompanying
|
||||||
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
|
|
||||||
|
#ifndef HUSH_I2P_H
|
||||||
|
#define HUSH_I2P_H
|
||||||
|
|
||||||
|
#include <compat.h>
|
||||||
|
#include <fs.h>
|
||||||
|
#include <netaddress.h>
|
||||||
|
#include <sync.h>
|
||||||
|
#include <util/sock.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace i2p {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Binary data.
|
||||||
|
*/
|
||||||
|
using Binary = std::vector<uint8_t>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An established connection with another peer.
|
||||||
|
*/
|
||||||
|
struct Connection {
|
||||||
|
/** Connected socket. */
|
||||||
|
std::unique_ptr<Sock> sock;
|
||||||
|
|
||||||
|
/** Our I2P address. */
|
||||||
|
CService me;
|
||||||
|
|
||||||
|
/** The peer's I2P address. */
|
||||||
|
CService peer;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace sam {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum size of an incoming message from the I2P SAM proxy (in bytes).
|
||||||
|
* Used to avoid a runaway proxy from sending us an "unlimited" amount of data without a terminator.
|
||||||
|
* The longest known message is ~1400 bytes, so this is high enough not to be triggered during
|
||||||
|
* normal operation, yet low enough to avoid a malicious proxy from filling our memory.
|
||||||
|
*/
|
||||||
|
static constexpr size_t MAX_MSG_SIZE{65536};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* I2P SAM session.
|
||||||
|
*/
|
||||||
|
class Session
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Construct a session. This will not initiate any IO, the session will be lazily created
|
||||||
|
* later when first used.
|
||||||
|
* @param[in] private_key_file Path to a private key file. If the file does not exist then the
|
||||||
|
* private key will be generated and saved into the file.
|
||||||
|
* @param[in] control_host Location of the SAM proxy.
|
||||||
|
*/
|
||||||
|
Session(const fs::path& private_key_file,
|
||||||
|
const CService& control_host);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy the session, closing the internally used sockets. The sockets that have been
|
||||||
|
* returned by `Accept()` or `Connect()` will not be closed, but they will be closed by
|
||||||
|
* the SAM proxy because the session is destroyed. So they will return an error next time
|
||||||
|
* we try to read or write to them.
|
||||||
|
*/
|
||||||
|
~Session();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the control sock and restart if needed
|
||||||
|
*/
|
||||||
|
bool Check();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start listening for an incoming connection.
|
||||||
|
* @param[out] conn Upon successful completion the `sock` and `me` members will be set
|
||||||
|
* to the listening socket and address.
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
|
bool Listen(Connection& conn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for and accept a new incoming connection.
|
||||||
|
* @param[in,out] conn The `sock` member is used for waiting and accepting. Upon successful
|
||||||
|
* completion the `peer` member will be set to the address of the incoming peer.
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
|
bool Accept(Connection& conn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect to an I2P peer.
|
||||||
|
* @param[in] to Peer to connect to.
|
||||||
|
* @param[out] conn Established connection. Only set if `true` is returned.
|
||||||
|
* @param[out] proxy_error If an error occurs due to proxy or general network failure, then
|
||||||
|
* this is set to `true`. If an error occurs due to unreachable peer (likely peer is down), then
|
||||||
|
* it is set to `false`. Only set if `false` is returned.
|
||||||
|
* @return true on success
|
||||||
|
*/
|
||||||
|
bool Connect(const CService& to, Connection& conn, bool& proxy_error);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
CCriticalSection cs_i2p;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* A reply from the SAM proxy.
|
||||||
|
*/
|
||||||
|
struct Reply {
|
||||||
|
/**
|
||||||
|
* Full, unparsed reply.
|
||||||
|
*/
|
||||||
|
std::string full;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request, used for detailed error reporting.
|
||||||
|
*/
|
||||||
|
std::string request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A map of keywords from the parsed reply.
|
||||||
|
* For example, if the reply is "A=X B C=YZ", then the map will be
|
||||||
|
* keys["A"] == "X"
|
||||||
|
* keys["B"] == (empty std::optional)
|
||||||
|
* keys["C"] == "YZ"
|
||||||
|
*/
|
||||||
|
std::unordered_map<std::string, boost::optional<std::string>> keys;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of a given key.
|
||||||
|
* For example if the reply is "A=X B" then:
|
||||||
|
* Value("A") -> "X"
|
||||||
|
* Value("B") -> throws
|
||||||
|
* Value("C") -> throws
|
||||||
|
* @param[in] key Key whose value to retrieve
|
||||||
|
* @returns the key's value
|
||||||
|
* @throws std::runtime_error if the key is not present or if it has no value
|
||||||
|
*/
|
||||||
|
std::string Get(const std::string& key) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send request and get a reply from the SAM proxy.
|
||||||
|
* @param[in] sock A socket that is connected to the SAM proxy.
|
||||||
|
* @param[in] request Raw request to send, a newline terminator is appended to it.
|
||||||
|
* @param[in] check_result_ok If true then after receiving the reply a check is made
|
||||||
|
* whether it contains "RESULT=OK" and an exception is thrown if it does not.
|
||||||
|
* @throws std::runtime_error if an error occurs
|
||||||
|
*/
|
||||||
|
Reply SendRequestAndGetReply(const Sock& sock,
|
||||||
|
const std::string& request,
|
||||||
|
bool check_result_ok = true) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a new connection to the SAM proxy.
|
||||||
|
* @return a connected socket
|
||||||
|
* @throws std::runtime_error if an error occurs
|
||||||
|
*/
|
||||||
|
std::unique_ptr<Sock> Hello() const EXCLUSIVE_LOCKS_REQUIRED(cs_i2p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the control socket for errors and possibly disconnect.
|
||||||
|
*/
|
||||||
|
void CheckControlSock();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a new destination with the SAM proxy and set `m_private_key` to it.
|
||||||
|
* @param[in] sock Socket to use for talking to the SAM proxy.
|
||||||
|
* @throws std::runtime_error if an error occurs
|
||||||
|
*/
|
||||||
|
void DestGenerate(const Sock& sock) EXCLUSIVE_LOCKS_REQUIRED(cs_i2p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a new destination with the SAM proxy, set `m_private_key` to it and save
|
||||||
|
* it on disk to `m_private_key_file`.
|
||||||
|
* @param[in] sock Socket to use for talking to the SAM proxy.
|
||||||
|
* @throws std::runtime_error if an error occurs
|
||||||
|
*/
|
||||||
|
void GenerateAndSavePrivateKey(const Sock& sock) EXCLUSIVE_LOCKS_REQUIRED(cs_i2p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derive own destination from `m_private_key`.
|
||||||
|
* @see https://geti2p.net/spec/common-structures#destination
|
||||||
|
* @return an I2P destination
|
||||||
|
*/
|
||||||
|
Binary MyDestination() const EXCLUSIVE_LOCKS_REQUIRED(cs_i2p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the session if not already created. Reads the private key file and connects to the
|
||||||
|
* SAM proxy.
|
||||||
|
* @throws std::runtime_error if an error occurs
|
||||||
|
*/
|
||||||
|
void CreateIfNotCreatedAlready() EXCLUSIVE_LOCKS_REQUIRED(cs_i2p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a new connection to the SAM proxy and issue "STREAM ACCEPT" request using the existing
|
||||||
|
* session id.
|
||||||
|
* @return the idle socket that is waiting for a peer to connect to us
|
||||||
|
* @throws std::runtime_error if an error occurs
|
||||||
|
*/
|
||||||
|
std::unique_ptr<Sock> StreamAccept() EXCLUSIVE_LOCKS_REQUIRED(cs_i2p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy the session, closing the internally used sockets.
|
||||||
|
*/
|
||||||
|
void Disconnect() EXCLUSIVE_LOCKS_REQUIRED(cs_i2p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the file where this peer's private key is stored (in binary).
|
||||||
|
*/
|
||||||
|
const fs::path m_private_key_file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The host and port of the SAM control service.
|
||||||
|
*/
|
||||||
|
const CService m_control_host;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The private key of this peer.
|
||||||
|
* @see The reply to the "DEST GENERATE" command in https://geti2p.net/en/docs/api/samv3
|
||||||
|
*/
|
||||||
|
Binary m_private_key GUARDED_BY(cs_i2p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SAM control socket.
|
||||||
|
* Used to connect to the I2P SAM service and create a session
|
||||||
|
* ("SESSION CREATE"). With the established session id we later open
|
||||||
|
* other connections to the SAM service to accept incoming I2P
|
||||||
|
* connections and make outgoing ones.
|
||||||
|
* See https://geti2p.net/en/docs/api/samv3
|
||||||
|
*/
|
||||||
|
std::unique_ptr<Sock> m_control_sock GUARDED_BY(cs_i2p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Our .b32.i2p address.
|
||||||
|
* Derived from `m_private_key`.
|
||||||
|
*/
|
||||||
|
CService m_my_addr GUARDED_BY(cs_i2p);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SAM session id.
|
||||||
|
*/
|
||||||
|
std::string m_session_id GUARDED_BY(cs_i2p);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace sam
|
||||||
|
} // namespace i2p
|
||||||
|
|
||||||
|
#endif /* HUSH_I2P_H */
|
||||||
90
src/init.cpp
90
src/init.cpp
@@ -87,7 +87,6 @@ using namespace std;
|
|||||||
|
|
||||||
#include "hush_defs.h"
|
#include "hush_defs.h"
|
||||||
static const bool DEFAULT_STRATUM_ENABLE = false;
|
static const bool DEFAULT_STRATUM_ENABLE = false;
|
||||||
extern void ThreadSendAlert();
|
|
||||||
extern bool hush_dailysnapshot(int32_t height);
|
extern bool hush_dailysnapshot(int32_t height);
|
||||||
extern int32_t HUSH_LOADINGBLOCKS;
|
extern int32_t HUSH_LOADINGBLOCKS;
|
||||||
extern char SMART_CHAIN_SYMBOL[];
|
extern char SMART_CHAIN_SYMBOL[];
|
||||||
@@ -247,14 +246,22 @@ void Shutdown()
|
|||||||
if (pcoinsTip != NULL) {
|
if (pcoinsTip != NULL) {
|
||||||
FlushStateToDisk();
|
FlushStateToDisk();
|
||||||
}
|
}
|
||||||
delete pcoinsTip;
|
if (pcoinsTip != NULL) {
|
||||||
pcoinsTip = NULL;
|
delete pcoinsTip;
|
||||||
delete pcoinscatcher;
|
pcoinsTip = NULL;
|
||||||
pcoinscatcher = NULL;
|
}
|
||||||
delete pcoinsdbview;
|
if (pcoinscatcher != NULL) {
|
||||||
pcoinsdbview = NULL;
|
delete pcoinscatcher;
|
||||||
delete pblocktree;
|
pcoinscatcher = NULL;
|
||||||
pblocktree = NULL;
|
}
|
||||||
|
if (pcoinsdbview != NULL) {
|
||||||
|
delete pcoinsdbview;
|
||||||
|
pcoinsdbview = NULL;
|
||||||
|
}
|
||||||
|
if (pblocktree != NULL) {
|
||||||
|
delete pblocktree;
|
||||||
|
pblocktree = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
if (pwalletMain)
|
if (pwalletMain)
|
||||||
@@ -275,7 +282,7 @@ void Shutdown()
|
|||||||
#endif
|
#endif
|
||||||
globalVerifyHandle.reset();
|
globalVerifyHandle.reset();
|
||||||
ECC_Stop();
|
ECC_Stop();
|
||||||
CNode::NetCleanup();
|
// CNode::NetCleanup();
|
||||||
LogPrintf("%s: done\n", __func__);
|
LogPrintf("%s: done\n", __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,7 +333,7 @@ bool static InitWarning(const std::string &str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool static Bind(const CService &addr, unsigned int flags) {
|
bool static Bind(const CService &addr, unsigned int flags) {
|
||||||
if (!(flags & BF_EXPLICIT) && IsLimited(addr))
|
if (!(flags & BF_EXPLICIT) && !IsReachable(addr))
|
||||||
return false;
|
return false;
|
||||||
std::string strError;
|
std::string strError;
|
||||||
if (!BindListenPort(addr, strError, (flags & BF_ALLOWLIST) != 0)) {
|
if (!BindListenPort(addr, strError, (flags & BF_ALLOWLIST) != 0)) {
|
||||||
@@ -361,7 +368,6 @@ std::string HelpMessage(HelpMessageMode mode)
|
|||||||
|
|
||||||
string strUsage = HelpMessageGroup(_("Options:"));
|
string strUsage = HelpMessageGroup(_("Options:"));
|
||||||
strUsage += HelpMessageOpt("-?", _("This help message"));
|
strUsage += HelpMessageOpt("-?", _("This help message"));
|
||||||
strUsage += HelpMessageOpt("-alertnotify=<cmd>", _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)"));
|
|
||||||
strUsage += HelpMessageOpt("-blocknotify=<cmd>", _("Execute command when the best block changes (%s in cmd is replaced by block hash)"));
|
strUsage += HelpMessageOpt("-blocknotify=<cmd>", _("Execute command when the best block changes (%s in cmd is replaced by block hash)"));
|
||||||
strUsage += HelpMessageOpt("-checkblocks=<n>", strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), 288));
|
strUsage += HelpMessageOpt("-checkblocks=<n>", strprintf(_("How many blocks to check at startup (default: %u, 0 = all)"), 288));
|
||||||
strUsage += HelpMessageOpt("-checklevel=<n>", strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"), 3));
|
strUsage += HelpMessageOpt("-checklevel=<n>", strprintf(_("How thorough the block verification of -checkblocks is (0-4, default: %u)"), 3));
|
||||||
@@ -418,7 +424,14 @@ std::string HelpMessage(HelpMessageMode mode)
|
|||||||
strUsage += HelpMessageOpt("-maxreceivebuffer=<n>", strprintf(_("Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)"), 5000));
|
strUsage += HelpMessageOpt("-maxreceivebuffer=<n>", strprintf(_("Maximum per-connection receive buffer, <n>*1000 bytes (default: %u)"), 5000));
|
||||||
strUsage += HelpMessageOpt("-maxsendbuffer=<n>", strprintf(_("Maximum per-connection send buffer, <n>*1000 bytes (default: %u)"), 1000));
|
strUsage += HelpMessageOpt("-maxsendbuffer=<n>", strprintf(_("Maximum per-connection send buffer, <n>*1000 bytes (default: %u)"), 1000));
|
||||||
strUsage += HelpMessageOpt("-onion=<ip:port>", strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy"));
|
strUsage += HelpMessageOpt("-onion=<ip:port>", strprintf(_("Use separate SOCKS5 proxy to reach peers via Tor hidden services (default: %s)"), "-proxy"));
|
||||||
strUsage += HelpMessageOpt("-onlynet=<net>", _("Only connect to nodes in network <net> (ipv4, ipv6 or onion)"));
|
strUsage += HelpMessageOpt("-nspv_msg", strprintf(_("Enable NSPV messages processing (default: true when -ac_private=1, otherwise false)")));
|
||||||
|
|
||||||
|
strUsage += HelpMessageOpt("-i2psam=<ip:port>", strprintf(_("I2P SAM proxy to reach I2P peers and accept I2P connections (default: none)")));
|
||||||
|
strUsage += HelpMessageOpt("-i2pacceptincoming", strprintf(_("If set and -i2psam is also set then incoming I2P connections are accepted via the SAM proxy. If this is not set but -i2psam is set then only outgoing connections will be made to the I2P network. Ignored if -i2psam is not set. Listening for incoming I2P connections is done through the SAM proxy, not by binding to a local address and port (default: 1)")));
|
||||||
|
strUsage += HelpMessageOpt("-onlynet=<net>", _("Only connect to nodes in network <net> (ipv4, ipv6, onion or i2p)"));
|
||||||
|
strUsage += HelpMessageOpt("-disableipv4", _("Disable Ipv4 network connections") + " " + _("(default: 0)"));
|
||||||
|
strUsage += HelpMessageOpt("-disableipv6", _("Disable Ipv6 network connections") + " " + _("(default: 0)"));
|
||||||
|
|
||||||
strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), 1));
|
strUsage += HelpMessageOpt("-permitbaremultisig", strprintf(_("Relay non-P2SH multisig (default: %u)"), 1));
|
||||||
strUsage += HelpMessageOpt("-peerbloomfilters", strprintf(_("Support filtering of blocks and transaction with Bloom filters (default: %u)"), 1));
|
strUsage += HelpMessageOpt("-peerbloomfilters", strprintf(_("Support filtering of blocks and transaction with Bloom filters (default: %u)"), 1));
|
||||||
if (showDebug)
|
if (showDebug)
|
||||||
@@ -501,7 +514,7 @@ std::string HelpMessage(HelpMessageMode mode)
|
|||||||
strUsage += HelpMessageOpt("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", 0));
|
strUsage += HelpMessageOpt("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", 0));
|
||||||
strUsage += HelpMessageOpt("-nuparams=hexBranchId:activationHeight", "Use given activation height for specified network upgrade (regtest-only)");
|
strUsage += HelpMessageOpt("-nuparams=hexBranchId:activationHeight", "Use given activation height for specified network upgrade (regtest-only)");
|
||||||
}
|
}
|
||||||
string debugCategories = "addrman, alert, bench, coindb, db, deletetx, estimatefee, http, libevent, lock, mempool, net, tls, partitioncheck, pow, proxy, prune, rand, randomx, reindex, rpc, selectcoins, stratum, tor, zrpc, zrpcunsafe (implies zrpc)"; // Don't translate these
|
string debugCategories = "addrman, bench, coindb, db, deletetx, estimatefee, http, libevent, lock, mempool, net, tls, partitioncheck, pow, proxy, prune, rand, randomx, reindex, rpc, selectcoins, stratum, tor, zrpc, zrpcunsafe (implies zrpc)"; // Don't translate these
|
||||||
strUsage += HelpMessageOpt("-debug=<category>", strprintf(_("Output debugging information (default: %u, supplying <category> is optional)"), 0) + ". " +
|
strUsage += HelpMessageOpt("-debug=<category>", strprintf(_("Output debugging information (default: %u, supplying <category> is optional)"), 0) + ". " +
|
||||||
_("If <category> is not supplied or if <category> = 1, output all debugging information.") + " " + _("<category> can be:") + " " + debugCategories + ".");
|
_("If <category> is not supplied or if <category> = 1, output all debugging information.") + " " + _("<category> can be:") + " " + debugCategories + ".");
|
||||||
strUsage += HelpMessageOpt("-experimentalfeatures", _("Enable use of experimental features"));
|
strUsage += HelpMessageOpt("-experimentalfeatures", _("Enable use of experimental features"));
|
||||||
@@ -1380,8 +1393,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||||||
fIsBareMultisigStd = GetBoolArg("-permitbaremultisig", true);
|
fIsBareMultisigStd = GetBoolArg("-permitbaremultisig", true);
|
||||||
nMaxDatacarrierBytes = GetArg("-datacarriersize", nMaxDatacarrierBytes);
|
nMaxDatacarrierBytes = GetArg("-datacarriersize", nMaxDatacarrierBytes);
|
||||||
|
|
||||||
fAlerts = GetBoolArg("-alerts", DEFAULT_ALERTS);
|
|
||||||
|
|
||||||
// Option to startup with mocktime set (used for regression testing):
|
// Option to startup with mocktime set (used for regression testing):
|
||||||
SetMockTime(GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op
|
SetMockTime(GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op
|
||||||
|
|
||||||
@@ -1613,14 +1624,15 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||||||
for (int n = 0; n < NET_MAX; n++) {
|
for (int n = 0; n < NET_MAX; n++) {
|
||||||
enum Network net = (enum Network)n;
|
enum Network net = (enum Network)n;
|
||||||
if (!nets.count(net))
|
if (!nets.count(net))
|
||||||
SetLimited(net);
|
SetReachable(net, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//fprintf(stderr,"%s tik19\n", __FUNCTION__);
|
//fprintf(stderr,"%s tik19\n", __FUNCTION__);
|
||||||
if (mapArgs.count("-allowlist")) {
|
if (mapArgs.count("-allowlist")) {
|
||||||
BOOST_FOREACH(const std::string& net, mapMultiArgs["-allowlist"]) {
|
BOOST_FOREACH(const std::string& net, mapMultiArgs["-allowlist"]) {
|
||||||
CSubNet subnet(net);
|
CSubNet subnet;
|
||||||
|
LookupSubNet(net.c_str(), subnet);
|
||||||
if (!subnet.IsValid())
|
if (!subnet.IsValid())
|
||||||
return InitError(strprintf(_("Invalid netmask specified in -allowlist: '%s'"), net));
|
return InitError(strprintf(_("Invalid netmask specified in -allowlist: '%s'"), net));
|
||||||
CNode::AddAllowlistedRange(subnet);
|
CNode::AddAllowlistedRange(subnet);
|
||||||
@@ -1631,9 +1643,10 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||||||
// -proxy sets a proxy for all outgoing network traffic
|
// -proxy sets a proxy for all outgoing network traffic
|
||||||
// -noproxy (or -proxy=0) as well as the empty string can be used to not set a proxy, this is the default
|
// -noproxy (or -proxy=0) as well as the empty string can be used to not set a proxy, this is the default
|
||||||
std::string proxyArg = GetArg("-proxy", "");
|
std::string proxyArg = GetArg("-proxy", "");
|
||||||
SetLimited(NET_ONION);
|
SetReachable(NET_ONION,false);
|
||||||
if (proxyArg != "" && proxyArg != "0") {
|
if (proxyArg != "" && proxyArg != "0") {
|
||||||
proxyType addrProxy = proxyType(CService(proxyArg, 9050), proxyRandomize);
|
CService resolved(LookupNumeric(proxyArg.c_str(), 9050));
|
||||||
|
proxyType addrProxy = proxyType(resolved, proxyRandomize);
|
||||||
if (!addrProxy.IsValid())
|
if (!addrProxy.IsValid())
|
||||||
return InitError(strprintf(_("Invalid -proxy address: '%s'"), proxyArg));
|
return InitError(strprintf(_("Invalid -proxy address: '%s'"), proxyArg));
|
||||||
|
|
||||||
@@ -1641,9 +1654,20 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||||||
SetProxy(NET_IPV6, addrProxy);
|
SetProxy(NET_IPV6, addrProxy);
|
||||||
SetProxy(NET_ONION, addrProxy);
|
SetProxy(NET_ONION, addrProxy);
|
||||||
SetNameProxy(addrProxy);
|
SetNameProxy(addrProxy);
|
||||||
SetLimited(NET_ONION, false); // by default, -proxy sets onion as reachable, unless -noonion later
|
SetReachable(NET_ONION, true); // by default, -proxy sets onion as reachable, unless -noonion later
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& i2psam_arg = GetArg("-i2psam", "");
|
||||||
|
if (!i2psam_arg.empty()) {
|
||||||
|
CService addr;
|
||||||
|
if (!Lookup(i2psam_arg.c_str(), addr, 7656, fNameLookup) || !addr.IsValid()) {
|
||||||
|
return InitError(strprintf(_("Invalid -i2psam address or hostname: '%s'"), i2psam_arg));
|
||||||
|
}
|
||||||
|
SetReachable(NET_I2P, true);
|
||||||
|
SetProxy(NET_I2P, proxyType{addr});
|
||||||
|
} else {
|
||||||
|
SetReachable(NET_I2P, false);
|
||||||
}
|
}
|
||||||
//fprintf(stderr,"%s tik20\n", __FUNCTION__);
|
|
||||||
|
|
||||||
// -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses
|
// -onion can be used to set only a proxy for .onion, or override normal proxy for .onion addresses
|
||||||
// -noonion (or -onion=0) disables connecting to .onion entirely
|
// -noonion (or -onion=0) disables connecting to .onion entirely
|
||||||
@@ -1651,13 +1675,14 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||||||
std::string onionArg = GetArg("-onion", "");
|
std::string onionArg = GetArg("-onion", "");
|
||||||
if (onionArg != "") {
|
if (onionArg != "") {
|
||||||
if (onionArg == "0") { // Handle -noonion/-onion=0
|
if (onionArg == "0") { // Handle -noonion/-onion=0
|
||||||
SetLimited(NET_ONION); // set onions as unreachable
|
SetReachable(NET_ONION,false); // set onions as unreachable
|
||||||
} else {
|
} else {
|
||||||
proxyType addrOnion = proxyType(CService(onionArg, 9050), proxyRandomize);
|
CService resolved(LookupNumeric(onionArg.c_str(), 9050));
|
||||||
|
proxyType addrOnion = proxyType(resolved, proxyRandomize);
|
||||||
if (!addrOnion.IsValid())
|
if (!addrOnion.IsValid())
|
||||||
return InitError(strprintf(_("Invalid -onion address: '%s'"), onionArg));
|
return InitError(strprintf(_("Invalid -onion address: '%s'"), onionArg));
|
||||||
SetProxy(NET_ONION, addrOnion);
|
SetProxy(NET_ONION, addrOnion);
|
||||||
SetLimited(NET_ONION, false);
|
SetReachable(NET_ONION, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1696,10 +1721,12 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||||||
|
|
||||||
if (mapArgs.count("-externalip")) {
|
if (mapArgs.count("-externalip")) {
|
||||||
BOOST_FOREACH(const std::string& strAddr, mapMultiArgs["-externalip"]) {
|
BOOST_FOREACH(const std::string& strAddr, mapMultiArgs["-externalip"]) {
|
||||||
CService addrLocal(strAddr, GetListenPort(), fNameLookup);
|
CService addrLocal;
|
||||||
if (!addrLocal.IsValid())
|
if (Lookup(strAddr.c_str(), addrLocal, GetListenPort(), fNameLookup) && addrLocal.IsValid()) {
|
||||||
|
AddLocal(addrLocal, LOCAL_MANUAL);
|
||||||
|
} else {
|
||||||
return InitError(strprintf(_("Cannot resolve -externalip address: '%s'"), strAddr));
|
return InitError(strprintf(_("Cannot resolve -externalip address: '%s'"), strAddr));
|
||||||
AddLocal(CService(strAddr, GetListenPort(), fNameLookup), LOCAL_MANUAL);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2042,7 +2069,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pwalletMain->consolidationInterval = consolidationInterval;
|
pwalletMain->consolidationInterval = consolidationInterval;
|
||||||
pwalletMain->nextConsolidation = pwalletMain->consolidationInterval + chainActive.Tip()->GetHeight();
|
pwalletMain->nextConsolidation = pwalletMain->consolidationInterval + chainActive.Height();
|
||||||
LogPrintf("%s: set nextConsolidation=%d\n", __func__, pwalletMain->nextConsolidation );
|
LogPrintf("%s: set nextConsolidation=%d\n", __func__, pwalletMain->nextConsolidation );
|
||||||
|
|
||||||
//Validate Sapling Addresses
|
//Validate Sapling Addresses
|
||||||
@@ -2066,7 +2093,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||||||
sweepInterval = 10;
|
sweepInterval = 10;
|
||||||
}
|
}
|
||||||
pwalletMain->sweepInterval = sweepInterval;
|
pwalletMain->sweepInterval = sweepInterval;
|
||||||
pwalletMain->nextSweep = pwalletMain->sweepInterval + chainActive.Tip()->GetHeight();
|
pwalletMain->nextSweep = pwalletMain->sweepInterval + chainActive.Height();
|
||||||
LogPrintf("%s: set nextSweep=%d with sweepInterval=%d\n", __func__, pwalletMain->nextSweep, pwalletMain->sweepInterval );
|
LogPrintf("%s: set nextSweep=%d with sweepInterval=%d\n", __func__, pwalletMain->nextSweep, pwalletMain->sweepInterval );
|
||||||
fSweepTxFee = GetArg("-zsweepfee", DEFAULT_SWEEP_FEE);
|
fSweepTxFee = GetArg("-zsweepfee", DEFAULT_SWEEP_FEE);
|
||||||
fSweepMapUsed = !mapMultiArgs["-zsweepaddress"].empty();
|
fSweepMapUsed = !mapMultiArgs["-zsweepaddress"].empty();
|
||||||
@@ -2398,9 +2425,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// SENDALERT
|
|
||||||
threadGroup.create_thread(boost::bind(ThreadSendAlert));
|
|
||||||
|
|
||||||
if(fDebug)
|
if(fDebug)
|
||||||
fprintf(stderr,"%s end fRequestShutdown=%d\n", __FUNCTION__, !!fRequestShutdown);
|
fprintf(stderr,"%s end fRequestShutdown=%d\n", __FUNCTION__, !!fRequestShutdown);
|
||||||
return !fRequestShutdown;
|
return !fRequestShutdown;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include <base58.h>
|
#include <base58.h>
|
||||||
#include <bech32.h>
|
#include <bech32.h>
|
||||||
#include <script/script.h>
|
#include <script/script.h>
|
||||||
#include <utilstrencodings.h>
|
#include <util/strencodings.h>
|
||||||
|
|
||||||
#include <boost/variant/apply_visitor.hpp>
|
#include <boost/variant/apply_visitor.hpp>
|
||||||
#include <boost/variant/static_visitor.hpp>
|
#include <boost/variant/static_visitor.hpp>
|
||||||
|
|||||||
247
src/main.cpp
247
src/main.cpp
@@ -20,7 +20,6 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "sodium.h"
|
#include "sodium.h"
|
||||||
#include "addrman.h"
|
#include "addrman.h"
|
||||||
#include "alert.h"
|
|
||||||
#include "arith_uint256.h"
|
#include "arith_uint256.h"
|
||||||
#include "importcoin.h"
|
#include "importcoin.h"
|
||||||
#include "chainparams.h"
|
#include "chainparams.h"
|
||||||
@@ -34,6 +33,7 @@
|
|||||||
#include "metrics.h"
|
#include "metrics.h"
|
||||||
#include "notarizationdb.h"
|
#include "notarizationdb.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
#include "netmessagemaker.h"
|
||||||
#include "pow.h"
|
#include "pow.h"
|
||||||
#include "script/interpreter.h"
|
#include "script/interpreter.h"
|
||||||
#include "txdb.h"
|
#include "txdb.h"
|
||||||
@@ -106,7 +106,6 @@ bool fCheckpointsEnabled = true;
|
|||||||
bool fCoinbaseEnforcedProtectionEnabled = true;
|
bool fCoinbaseEnforcedProtectionEnabled = true;
|
||||||
size_t nCoinCacheUsage = 5000 * 300;
|
size_t nCoinCacheUsage = 5000 * 300;
|
||||||
uint64_t nPruneTarget = 0;
|
uint64_t nPruneTarget = 0;
|
||||||
bool fAlerts = DEFAULT_ALERTS;
|
|
||||||
// If the tip is older than this (in seconds), the node is considered to be in initial block download.
|
// If the tip is older than this (in seconds), the node is considered to be in initial block download.
|
||||||
int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE;
|
int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE;
|
||||||
bool ishush3 = strncmp(SMART_CHAIN_SYMBOL, "HUSH3",5) == 0 ? true : false;
|
bool ishush3 = strncmp(SMART_CHAIN_SYMBOL, "HUSH3",5) == 0 ? true : false;
|
||||||
@@ -983,7 +982,7 @@ bool IsStandardTx(const CTransaction& tx, string& reason, const int nHeight)
|
|||||||
if (!::IsStandard(txout.scriptPubKey, whichType))
|
if (!::IsStandard(txout.scriptPubKey, whichType))
|
||||||
{
|
{
|
||||||
reason = "scriptpubkey";
|
reason = "scriptpubkey";
|
||||||
//fprintf(stderr,">>>>>>>>>>>>>>> vout.%d nDataout.%d\n",v,nDataOut);
|
//fprintf(stderr," vout.%d nDataout.%d\n",v,nDataOut);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2470,9 +2469,8 @@ void CheckForkWarningConditions()
|
|||||||
{
|
{
|
||||||
if (!fLargeWorkForkFound && pindexBestForkBase)
|
if (!fLargeWorkForkFound && pindexBestForkBase)
|
||||||
{
|
{
|
||||||
std::string warning = std::string("'Warning: Large-work fork detected, forking after block ") +
|
std::string warning = std::string("'Warning: Large-work fork detected, forking after block ") + pindexBestForkBase->phashBlock->ToString() + std::string("'");
|
||||||
pindexBestForkBase->phashBlock->ToString() + std::string("'");
|
LogPrintf("%s: %s\n", __func__, warning.c_str());
|
||||||
CAlert::Notify(warning, true);
|
|
||||||
}
|
}
|
||||||
if (pindexBestForkTip && pindexBestForkBase)
|
if (pindexBestForkTip && pindexBestForkBase)
|
||||||
{
|
{
|
||||||
@@ -2480,12 +2478,9 @@ void CheckForkWarningConditions()
|
|||||||
pindexBestForkBase->GetHeight(), pindexBestForkBase->phashBlock->ToString(),
|
pindexBestForkBase->GetHeight(), pindexBestForkBase->phashBlock->ToString(),
|
||||||
pindexBestForkTip->GetHeight(), pindexBestForkTip->phashBlock->ToString());
|
pindexBestForkTip->GetHeight(), pindexBestForkTip->phashBlock->ToString());
|
||||||
fLargeWorkForkFound = true;
|
fLargeWorkForkFound = true;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
std::string warning = std::string("Warning: Found invalid chain at least ~6 blocks longer than our best chain.\nChain state database corruption likely.");
|
std::string warning = std::string("Warning: Found invalid chain at least ~6 blocks longer than our best chain.\nChain state database corruption likely.");
|
||||||
LogPrintf("%s: %s\n", warning.c_str(), __func__);
|
LogPrintf("%s: %s\n", __func__, warning.c_str());
|
||||||
CAlert::Notify(warning, true);
|
|
||||||
fLargeWorkInvalidChainFound = true;
|
fLargeWorkInvalidChainFound = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -3776,7 +3771,7 @@ void static UpdateTip(CBlockIndex *pindexNew) {
|
|||||||
mempool.AddTransactionsUpdated(1);
|
mempool.AddTransactionsUpdated(1);
|
||||||
HUSH_NEWBLOCKS++;
|
HUSH_NEWBLOCKS++;
|
||||||
double progress;
|
double progress;
|
||||||
if ( SMART_CHAIN_SYMBOL[0] == 0 ) {
|
if ( ishush3 ) {
|
||||||
progress = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.LastTip());
|
progress = Checkpoints::GuessVerificationProgress(chainParams.Checkpoints(), chainActive.LastTip());
|
||||||
} else {
|
} else {
|
||||||
int32_t longestchain = hush_longestchain();
|
int32_t longestchain = hush_longestchain();
|
||||||
@@ -4336,6 +4331,9 @@ bool ActivateBestChain(bool fSkipdpow, CValidationState &state, CBlock *pblock)
|
|||||||
do {
|
do {
|
||||||
boost::this_thread::interruption_point();
|
boost::this_thread::interruption_point();
|
||||||
|
|
||||||
|
if (ShutdownRequested())
|
||||||
|
break;
|
||||||
|
|
||||||
bool fInitialDownload;
|
bool fInitialDownload;
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
@@ -5960,20 +5958,6 @@ bool static LoadBlockIndexDB()
|
|||||||
pblocktree->ReadFlag("spentindex", fSpentIndex);
|
pblocktree->ReadFlag("spentindex", fSpentIndex);
|
||||||
LogPrintf("%s: spent index %s\n", __func__, fSpentIndex ? "enabled" : "disabled");
|
LogPrintf("%s: spent index %s\n", __func__, fSpentIndex ? "enabled" : "disabled");
|
||||||
|
|
||||||
// Fill in-memory data
|
|
||||||
BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex)
|
|
||||||
{
|
|
||||||
CBlockIndex* pindex = item.second;
|
|
||||||
// - This relationship will always be true even if pprev has multiple
|
|
||||||
// children, because hashSproutAnchor is technically a property of pprev,
|
|
||||||
// not its children.
|
|
||||||
// - This will miss chain tips; we handle the best tip below, and other
|
|
||||||
// tips will be handled by ConnectTip during a re-org.
|
|
||||||
if (pindex->pprev) {
|
|
||||||
pindex->pprev->hashFinalSproutRoot = pindex->hashSproutAnchor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load pointer to end of best chain
|
// Load pointer to end of best chain
|
||||||
BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
|
BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock());
|
||||||
if (it == mapBlockIndex.end())
|
if (it == mapBlockIndex.end())
|
||||||
@@ -6665,11 +6649,7 @@ void static CheckBlockIndex()
|
|||||||
assert(nNodes == forward.size());
|
assert(nNodes == forward.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// CAlert
|
// CAlert
|
||||||
//
|
|
||||||
|
|
||||||
std::string GetWarnings(const std::string& strFor)
|
std::string GetWarnings(const std::string& strFor)
|
||||||
{
|
{
|
||||||
int nPriority = 0;
|
int nPriority = 0;
|
||||||
@@ -6700,23 +6680,6 @@ std::string GetWarnings(const std::string& strFor)
|
|||||||
strStatusBar = strRPC = _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.");
|
strStatusBar = strRPC = _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alerts
|
|
||||||
{
|
|
||||||
LOCK(cs_mapAlerts);
|
|
||||||
BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
|
|
||||||
{
|
|
||||||
const CAlert& alert = item.second;
|
|
||||||
if (alert.AppliesToMe() && alert.nPriority > nPriority)
|
|
||||||
{
|
|
||||||
nPriority = alert.nPriority;
|
|
||||||
strStatusBar = alert.strStatusBar;
|
|
||||||
if (alert.nPriority >= ALERT_PRIORITY_SAFE_MODE) {
|
|
||||||
strRPC = alert.strRPCError;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strFor == "statusbar")
|
if (strFor == "statusbar")
|
||||||
return strStatusBar;
|
return strStatusBar;
|
||||||
else if (strFor == "rpc")
|
else if (strFor == "rpc")
|
||||||
@@ -6725,18 +6688,7 @@ std::string GetWarnings(const std::string& strFor)
|
|||||||
return "error";
|
return "error";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// Messages
|
// Messages
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||||
{
|
{
|
||||||
@@ -6825,7 +6777,7 @@ void static ProcessGetData(CNode* pfrom)
|
|||||||
//for (z=31; z>=0; z--)
|
//for (z=31; z>=0; z--)
|
||||||
// fprintf(stderr,"%02x",((uint8_t *)&hash)[z]);
|
// fprintf(stderr,"%02x",((uint8_t *)&hash)[z]);
|
||||||
//fprintf(stderr," send block %d\n",hush_block2height(&block));
|
//fprintf(stderr," send block %d\n",hush_block2height(&block));
|
||||||
pfrom->PushMessage("block", block);
|
pfrom->PushMessage(NetMsgType::BLOCK, block);
|
||||||
}
|
}
|
||||||
else // MSG_FILTERED_BLOCK)
|
else // MSG_FILTERED_BLOCK)
|
||||||
{
|
{
|
||||||
@@ -6833,7 +6785,7 @@ void static ProcessGetData(CNode* pfrom)
|
|||||||
if (pfrom->pfilter)
|
if (pfrom->pfilter)
|
||||||
{
|
{
|
||||||
CMerkleBlock merkleBlock(block, *pfrom->pfilter);
|
CMerkleBlock merkleBlock(block, *pfrom->pfilter);
|
||||||
pfrom->PushMessage("merkleblock", merkleBlock);
|
pfrom->PushMessage(NetMsgType::MERKLEBLOCK, merkleBlock);
|
||||||
// CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
|
// CMerkleBlock just contains hashes, so also push any transactions in the block the client did not see
|
||||||
// This avoids hurting performance by pointlessly requiring a round-trip
|
// This avoids hurting performance by pointlessly requiring a round-trip
|
||||||
// Note that there is currently no way for a node to request any single transactions we didn't send here -
|
// Note that there is currently no way for a node to request any single transactions we didn't send here -
|
||||||
@@ -6843,7 +6795,7 @@ void static ProcessGetData(CNode* pfrom)
|
|||||||
typedef std::pair<unsigned int, uint256> PairType;
|
typedef std::pair<unsigned int, uint256> PairType;
|
||||||
BOOST_FOREACH(PairType& pair, merkleBlock.vMatchedTxn)
|
BOOST_FOREACH(PairType& pair, merkleBlock.vMatchedTxn)
|
||||||
if (!pfrom->setInventoryKnown.count(CInv(MSG_TX, pair.second)))
|
if (!pfrom->setInventoryKnown.count(CInv(MSG_TX, pair.second)))
|
||||||
pfrom->PushMessage("tx", block.vtx[pair.first]);
|
pfrom->PushMessage(NetMsgType::TX, block.vtx[pair.first]);
|
||||||
}
|
}
|
||||||
// else
|
// else
|
||||||
// no response
|
// no response
|
||||||
@@ -6857,7 +6809,7 @@ void static ProcessGetData(CNode* pfrom)
|
|||||||
// wait for other stuff first.
|
// wait for other stuff first.
|
||||||
vector<CInv> vInv;
|
vector<CInv> vInv;
|
||||||
vInv.push_back(CInv(MSG_BLOCK, chainActive.Tip()->GetBlockHash()));
|
vInv.push_back(CInv(MSG_BLOCK, chainActive.Tip()->GetBlockHash()));
|
||||||
pfrom->PushMessage("inv", vInv);
|
pfrom->PushMessage(NetMsgType::INV, vInv);
|
||||||
pfrom->hashContinue.SetNull();
|
pfrom->hashContinue.SetNull();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6880,7 +6832,7 @@ void static ProcessGetData(CNode* pfrom)
|
|||||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
ss.reserve(1000);
|
ss.reserve(1000);
|
||||||
ss << tx;
|
ss << tx;
|
||||||
pfrom->PushMessage("tx", ss);
|
pfrom->PushMessage(NetMsgType::TX, ss);
|
||||||
pushed = true;
|
pushed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6907,7 +6859,7 @@ void static ProcessGetData(CNode* pfrom)
|
|||||||
// do that because they want to know about (and store and rebroadcast and
|
// do that because they want to know about (and store and rebroadcast and
|
||||||
// risk analyze) the dependencies of transactions relevant to them, without
|
// risk analyze) the dependencies of transactions relevant to them, without
|
||||||
// having to download the entire memory pool.
|
// having to download the entire memory pool.
|
||||||
pfrom->PushMessage("notfound", vNotFound);
|
pfrom->PushMessage(NetMsgType::NOTFOUND, vNotFound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6934,7 +6886,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
if(p2pdebug)
|
if(p2pdebug)
|
||||||
fprintf(stderr,"%s: netmsg: %s from %s\n", __func__, strCommand.c_str(), pfrom->addr.ToString().c_str() );
|
fprintf(stderr,"%s: netmsg: %s from %s\n", __func__, strCommand.c_str(), pfrom->addr.ToString().c_str() );
|
||||||
|
|
||||||
if (strCommand == "version") {
|
if (strCommand == NetMsgType::VERSION) {
|
||||||
// Feeler connections exist only to verify if node is online
|
// Feeler connections exist only to verify if node is online
|
||||||
if (pfrom->fFeeler) {
|
if (pfrom->fFeeler) {
|
||||||
assert(pfrom->fInbound == false);
|
assert(pfrom->fInbound == false);
|
||||||
@@ -6946,7 +6898,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
// Each connection can only send one version message
|
// Each connection can only send one version message
|
||||||
if (pfrom->nVersion != 0)
|
if (pfrom->nVersion != 0)
|
||||||
{
|
{
|
||||||
pfrom->PushMessage("reject", strCommand, REJECT_DUPLICATE, string("Duplicate version message"));
|
pfrom->PushMessage(NetMsgType::REJECT, strCommand, REJECT_DUPLICATE, string("Duplicate version message"));
|
||||||
Misbehaving(pfrom->GetId(), 1);
|
Misbehaving(pfrom->GetId(), 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -6964,7 +6916,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
{
|
{
|
||||||
// disconnect from peers older than this proto version
|
// disconnect from peers older than this proto version
|
||||||
LogPrintf("Disconnecting peer=%d at %s using obsolete version %i < %i\n", pfrom->id, pfrom->addr.ToString().c_str(), nVersion, minVersion);
|
LogPrintf("Disconnecting peer=%d at %s using obsolete version %i < %i\n", pfrom->id, pfrom->addr.ToString().c_str(), nVersion, minVersion);
|
||||||
pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", minVersion));
|
pfrom->PushMessage(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE, strprintf("Version must be %d or greater", minVersion));
|
||||||
pfrom->fDisconnect = true;
|
pfrom->fDisconnect = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -6975,7 +6927,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
if (nVersion < params.vUpgrades[currentEpoch].nProtocolVersion)
|
if (nVersion < params.vUpgrades[currentEpoch].nProtocolVersion)
|
||||||
{
|
{
|
||||||
LogPrintf("Disconnecting peer=%d at %s using obsolete epoch version %i\n", pfrom->id, pfrom->addr.ToString().c_str(), nVersion);
|
LogPrintf("Disconnecting peer=%d at %s using obsolete epoch version %i\n", pfrom->id, pfrom->addr.ToString().c_str(), nVersion);
|
||||||
pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE,
|
pfrom->PushMessage(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE,
|
||||||
strprintf("Version must be %d or greater",
|
strprintf("Version must be %d or greater",
|
||||||
params.vUpgrades[currentEpoch].nProtocolVersion));
|
params.vUpgrades[currentEpoch].nProtocolVersion));
|
||||||
pfrom->fDisconnect = true;
|
pfrom->fDisconnect = true;
|
||||||
@@ -7019,6 +6971,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
// Potentially mark this peer as a preferred download peer.
|
// Potentially mark this peer as a preferred download peer.
|
||||||
UpdatePreferredDownload(pfrom, State(pfrom->GetId()));
|
UpdatePreferredDownload(pfrom, State(pfrom->GetId()));
|
||||||
|
|
||||||
|
//Ask for Address Format Version 2
|
||||||
|
pfrom->PushMessage(NetMsgType::SENDADDRV2);
|
||||||
|
|
||||||
// Change version
|
// Change version
|
||||||
pfrom->PushMessage("verack");
|
pfrom->PushMessage("verack");
|
||||||
pfrom->ssSend.SetVersion(min(pfrom->nVersion, PROTOCOL_VERSION));
|
pfrom->ssSend.SetVersion(min(pfrom->nVersion, PROTOCOL_VERSION));
|
||||||
@@ -7043,7 +6998,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
// Get recent addresses
|
// Get recent addresses
|
||||||
if (pfrom->fOneShot || pfrom->nVersion >= CADDR_TIME_VERSION || addrman.size() < 1000)
|
if (pfrom->fOneShot || pfrom->nVersion >= CADDR_TIME_VERSION || addrman.size() < 1000)
|
||||||
{
|
{
|
||||||
pfrom->PushMessage("getaddr");
|
pfrom->PushMessage(NetMsgType::GETADDR);
|
||||||
pfrom->fGetAddr = true;
|
pfrom->fGetAddr = true;
|
||||||
}
|
}
|
||||||
addrman.Good(pfrom->addr);
|
addrman.Good(pfrom->addr);
|
||||||
@@ -7074,7 +7029,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
// Must have a version message before anything else
|
// Must have a version message before anything else
|
||||||
Misbehaving(pfrom->GetId(), 1);
|
Misbehaving(pfrom->GetId(), 1);
|
||||||
return false;
|
return false;
|
||||||
} else if ( strCommand == "events" ) {
|
} else if ( strCommand == NetMsgType::EVENTS ) {
|
||||||
if ( ASSETCHAINS_CCLIB != "gamescc" )
|
if ( ASSETCHAINS_CCLIB != "gamescc" )
|
||||||
{
|
{
|
||||||
Misbehaving(pfrom->GetId(), 1);
|
Misbehaving(pfrom->GetId(), 1);
|
||||||
@@ -7084,7 +7039,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
vRecv >> payload;
|
vRecv >> payload;
|
||||||
hush_netevent(payload);
|
hush_netevent(payload);
|
||||||
return(true);
|
return(true);
|
||||||
} else if (strCommand == "verack") {
|
} else if (strCommand == NetMsgType::VERACK) {
|
||||||
pfrom->SetRecvVersion(min(pfrom->nVersion, PROTOCOL_VERSION));
|
pfrom->SetRecvVersion(min(pfrom->nVersion, PROTOCOL_VERSION));
|
||||||
|
|
||||||
if ( HUSH_NSPV_SUPERLITE )
|
if ( HUSH_NSPV_SUPERLITE )
|
||||||
@@ -7100,6 +7055,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
if (pfrom->fNetworkNode) {
|
if (pfrom->fNetworkNode) {
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
State(pfrom->GetId())->fCurrentlyConnected = true;
|
State(pfrom->GetId())->fCurrentlyConnected = true;
|
||||||
|
AddressCurrentlyConnected(State(pfrom->GetId())->address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7108,15 +7064,29 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
// 2. Peer version is below the minimum version for the current epoch
|
// 2. Peer version is below the minimum version for the current epoch
|
||||||
else if (pfrom->nVersion < chainparams.GetConsensus().vUpgrades[CurrentEpoch(GetHeight(), chainparams.GetConsensus())].nProtocolVersion) {
|
else if (pfrom->nVersion < chainparams.GetConsensus().vUpgrades[CurrentEpoch(GetHeight(), chainparams.GetConsensus())].nProtocolVersion) {
|
||||||
LogPrintf("Disconnecting peer=%d at %s using obsolete version %i vs %d\n", pfrom->id, pfrom->addr.ToString().c_str(), pfrom->nVersion,(int32_t)chainparams.GetConsensus().vUpgrades[CurrentEpoch(GetHeight(), chainparams.GetConsensus())].nProtocolVersion);
|
LogPrintf("Disconnecting peer=%d at %s using obsolete version %i vs %d\n", pfrom->id, pfrom->addr.ToString().c_str(), pfrom->nVersion,(int32_t)chainparams.GetConsensus().vUpgrades[CurrentEpoch(GetHeight(), chainparams.GetConsensus())].nProtocolVersion);
|
||||||
pfrom->PushMessage("reject", strCommand, REJECT_OBSOLETE,
|
pfrom->PushMessage(NetMsgType::REJECT, strCommand, REJECT_OBSOLETE,
|
||||||
strprintf("Version must be %d or greater",
|
strprintf("Version must be %d or greater",
|
||||||
chainparams.GetConsensus().vUpgrades[
|
chainparams.GetConsensus().vUpgrades[
|
||||||
CurrentEpoch(GetHeight(), chainparams.GetConsensus())].nProtocolVersion));
|
CurrentEpoch(GetHeight(), chainparams.GetConsensus())].nProtocolVersion));
|
||||||
|
|
||||||
pfrom->fDisconnect = true;
|
pfrom->fDisconnect = true;
|
||||||
return false;
|
return false;
|
||||||
} else if (strCommand == "addr") {
|
} else if (strCommand == NetMsgType::SENDADDRV2) {
|
||||||
|
pfrom->m_wants_addrv2 = true;
|
||||||
|
return true;
|
||||||
|
} else if (strCommand == NetMsgType::ADDR || strCommand == NetMsgType::ADDRV2) {
|
||||||
|
int stream_version = vRecv.GetVersion();
|
||||||
|
int tempStream_version = vRecv.GetVersion();
|
||||||
|
tempStream_version |= ADDRV2_FORMAT;
|
||||||
|
|
||||||
|
if (strCommand == NetMsgType::ADDRV2) {
|
||||||
|
// Add ADDRV2_FORMAT to the version so that the CNetAddr and CAddress
|
||||||
|
// unserialize methods know that an address in v2 format is coming.
|
||||||
|
stream_version |= ADDRV2_FORMAT;
|
||||||
|
}
|
||||||
|
OverrideStream<CDataStream> s(&vRecv, vRecv.GetType(), stream_version);
|
||||||
vector<CAddress> vAddr;
|
vector<CAddress> vAddr;
|
||||||
vRecv >> vAddr;
|
s >> vAddr;
|
||||||
if(p2pdebug)
|
if(p2pdebug)
|
||||||
fprintf(stderr,"%s: processing add with vAddr.size=%lu\n", __func__, vAddr.size() );
|
fprintf(stderr,"%s: processing add with vAddr.size=%lu\n", __func__, vAddr.size() );
|
||||||
|
|
||||||
@@ -7126,7 +7096,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
if (vAddr.size() > 1000)
|
if (vAddr.size() > 1000)
|
||||||
{
|
{
|
||||||
Misbehaving(pfrom->GetId(), 20);
|
Misbehaving(pfrom->GetId(), 20);
|
||||||
return error("message addr size() = %u", vAddr.size());
|
return error("%s message size() = %u", strCommand, vAddr.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the new addresses
|
// Store the new addresses
|
||||||
@@ -7185,7 +7155,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
pfrom->fGetAddr = false;
|
pfrom->fGetAddr = false;
|
||||||
if (pfrom->fOneShot)
|
if (pfrom->fOneShot)
|
||||||
pfrom->fDisconnect = true;
|
pfrom->fDisconnect = true;
|
||||||
} else if (strCommand == "ping") {
|
} else if (strCommand == NetMsgType::PING) {
|
||||||
if (pfrom->nVersion > BIP0031_VERSION)
|
if (pfrom->nVersion > BIP0031_VERSION)
|
||||||
{
|
{
|
||||||
uint64_t nonce = 0;
|
uint64_t nonce = 0;
|
||||||
@@ -7201,9 +7171,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
// it, if the remote node sends a ping once per second and this node takes 5
|
// it, if the remote node sends a ping once per second and this node takes 5
|
||||||
// seconds to respond to each, the 5th ping the remote sends would appear to
|
// seconds to respond to each, the 5th ping the remote sends would appear to
|
||||||
// return very quickly.
|
// return very quickly.
|
||||||
pfrom->PushMessage("pong", nonce);
|
pfrom->PushMessage(NetMsgType::PONG, nonce);
|
||||||
}
|
}
|
||||||
} else if (strCommand == "pong") {
|
} else if (strCommand == NetMsgType::PONG) {
|
||||||
int64_t pingUsecEnd = nTimeReceived;
|
int64_t pingUsecEnd = nTimeReceived;
|
||||||
uint64_t nonce = 0;
|
uint64_t nonce = 0;
|
||||||
size_t nAvail = vRecv.in_avail();
|
size_t nAvail = vRecv.in_avail();
|
||||||
@@ -7256,6 +7226,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
}
|
}
|
||||||
if (bPingFinished) {
|
if (bPingFinished) {
|
||||||
pfrom->nPingNonceSent = 0;
|
pfrom->nPingNonceSent = 0;
|
||||||
|
pfrom->nPingRetry = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// This asymmetric behavior for inbound and outbound connections was introduced
|
// This asymmetric behavior for inbound and outbound connections was introduced
|
||||||
@@ -7263,7 +7234,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
// to users' AddrMan and later request them by sending getaddr messages.
|
// to users' AddrMan and later request them by sending getaddr messages.
|
||||||
// Making nodes which are behind NAT and can only make outgoing connections ignore
|
// Making nodes which are behind NAT and can only make outgoing connections ignore
|
||||||
// the getaddr message mitigates the attack.
|
// the getaddr message mitigates the attack.
|
||||||
else if ((strCommand == "getaddr") && (pfrom->fInbound))
|
else if ((strCommand == NetMsgType::GETADDR) && (pfrom->fInbound))
|
||||||
{
|
{
|
||||||
// Only send one GetAddr response per connection to reduce resource waste
|
// Only send one GetAddr response per connection to reduce resource waste
|
||||||
// and discourage addr stamping of INV announcements.
|
// and discourage addr stamping of INV announcements.
|
||||||
@@ -7274,10 +7245,11 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
pfrom->fSentAddr = true;
|
pfrom->fSentAddr = true;
|
||||||
|
|
||||||
pfrom->vAddrToSend.clear();
|
pfrom->vAddrToSend.clear();
|
||||||
vector<CAddress> vAddr = addrman.GetAddr();
|
vector<CAddress> vAddr = addrman.GetAddr(pfrom->m_wants_addrv2);
|
||||||
BOOST_FOREACH(const CAddress &addr, vAddr)
|
BOOST_FOREACH(const CAddress &addr, vAddr)
|
||||||
pfrom->PushAddress(addr);
|
pfrom->PushAddress(addr);
|
||||||
} else if (strCommand == "getnSPV") {
|
} else if (GetBoolArg("-nspv_msg", DEFAULT_NSPV_PROCESSING) &&
|
||||||
|
(strCommand == NetMsgType::GETNSPV)) {
|
||||||
if ( HUSH_NSPV == 0 )//&& HUSH_INSYNC != 0 )
|
if ( HUSH_NSPV == 0 )//&& HUSH_INSYNC != 0 )
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> payload;
|
std::vector<uint8_t> payload;
|
||||||
@@ -7285,7 +7257,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
hush_nSPVreq(pfrom,payload);
|
hush_nSPVreq(pfrom,payload);
|
||||||
}
|
}
|
||||||
return(true);
|
return(true);
|
||||||
} else if (strCommand == "nSPV") {
|
} else if (GetBoolArg("-nspv_msg", DEFAULT_NSPV_PROCESSING) &&
|
||||||
|
(strCommand == NetMsgType::GETNSPV)) {
|
||||||
if ( HUSH_NSPV_SUPERLITE )
|
if ( HUSH_NSPV_SUPERLITE )
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> payload;
|
std::vector<uint8_t> payload;
|
||||||
@@ -7293,10 +7266,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
hush_nSPVresp(pfrom,payload);
|
hush_nSPVresp(pfrom,payload);
|
||||||
}
|
}
|
||||||
return(true);
|
return(true);
|
||||||
}
|
} else if ( HUSH_NSPV_SUPERLITE ) {
|
||||||
else if ( HUSH_NSPV_SUPERLITE )
|
|
||||||
return(true);
|
return(true);
|
||||||
else if (strCommand == "inv") {
|
} else if (strCommand == NetMsgType::INV) {
|
||||||
vector<CInv> vInv;
|
vector<CInv> vInv;
|
||||||
vRecv >> vInv;
|
vRecv >> vInv;
|
||||||
if(p2pdebug)
|
if(p2pdebug)
|
||||||
@@ -7335,7 +7307,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
// time the block arrives, the header chain leading up to it is already validated. Not
|
// time the block arrives, the header chain leading up to it is already validated. Not
|
||||||
// doing this will result in the received block being rejected as an orphan in case it is
|
// doing this will result in the received block being rejected as an orphan in case it is
|
||||||
// not a direct successor.
|
// not a direct successor.
|
||||||
pfrom->PushMessage("getheaders", chainActive.GetLocator(pindexBestHeader), inv.hash);
|
pfrom->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexBestHeader), inv.hash);
|
||||||
CNodeState *nodestate = State(pfrom->GetId());
|
CNodeState *nodestate = State(pfrom->GetId());
|
||||||
if (chainActive.Tip()->GetBlockTime() > GetTime() - chainparams.GetConsensus().nPowTargetSpacing * 20 &&
|
if (chainActive.Tip()->GetBlockTime() > GetTime() - chainparams.GetConsensus().nPowTargetSpacing * 20 &&
|
||||||
nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
|
nodestate->nBlocksInFlight < MAX_BLOCKS_IN_TRANSIT_PER_PEER) {
|
||||||
@@ -7358,8 +7330,8 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!vToFetch.empty())
|
if (!vToFetch.empty())
|
||||||
pfrom->PushMessage("getdata", vToFetch);
|
pfrom->PushMessage(NetMsgType::GETDATA, vToFetch);
|
||||||
} else if (strCommand == "getdata") {
|
} else if (strCommand == NetMsgType::GETDATA) {
|
||||||
vector<CInv> vInv;
|
vector<CInv> vInv;
|
||||||
vRecv >> vInv;
|
vRecv >> vInv;
|
||||||
if(p2pdebug)
|
if(p2pdebug)
|
||||||
@@ -7378,7 +7350,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
|
|
||||||
pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end());
|
pfrom->vRecvGetData.insert(pfrom->vRecvGetData.end(), vInv.begin(), vInv.end());
|
||||||
ProcessGetData(pfrom);
|
ProcessGetData(pfrom);
|
||||||
} else if (strCommand == "getblocks") {
|
} else if (strCommand == NetMsgType::GETBLOCKS) {
|
||||||
CBlockLocator locator;
|
CBlockLocator locator;
|
||||||
uint256 hashStop;
|
uint256 hashStop;
|
||||||
vRecv >> locator >> hashStop;
|
vRecv >> locator >> hashStop;
|
||||||
@@ -7410,7 +7382,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (strCommand == "getheaders") {
|
} else if (strCommand == NetMsgType::GETHEADERS) {
|
||||||
CBlockLocator locator;
|
CBlockLocator locator;
|
||||||
uint256 hashStop;
|
uint256 hashStop;
|
||||||
vRecv >> locator >> hashStop;
|
vRecv >> locator >> hashStop;
|
||||||
@@ -7461,7 +7433,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
|
if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pfrom->PushMessage("headers", vHeaders);
|
pfrom->PushMessage(NetMsgType::HEADERS, vHeaders);
|
||||||
}
|
}
|
||||||
/*else if ( IS_HUSH_NOTARY != 0 )
|
/*else if ( IS_HUSH_NOTARY != 0 )
|
||||||
{
|
{
|
||||||
@@ -7469,7 +7441,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
if ( counter++ < 3 )
|
if ( counter++ < 3 )
|
||||||
fprintf(stderr,"you can ignore redundant getheaders from peer.%d %d prev.%d\n",(int32_t)pfrom->id,(int32_t)(pindex ? pindex->GetHeight() : -1),pfrom->lasthdrsreq);
|
fprintf(stderr,"you can ignore redundant getheaders from peer.%d %d prev.%d\n",(int32_t)pfrom->id,(int32_t)(pindex ? pindex->GetHeight() : -1),pfrom->lasthdrsreq);
|
||||||
}*/
|
}*/
|
||||||
} else if (strCommand == "tx") {
|
} else if (strCommand == NetMsgType::TX) {
|
||||||
if (IsInitialBlockDownload())
|
if (IsInitialBlockDownload())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -7597,12 +7569,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
LogPrint("mempool", "%s from peer=%d %s was not accepted into the memory pool: %s\n", tx.GetHash().ToString(),
|
LogPrint("mempool", "%s from peer=%d %s was not accepted into the memory pool: %s\n", tx.GetHash().ToString(),
|
||||||
pfrom->id, pfrom->cleanSubVer,
|
pfrom->id, pfrom->cleanSubVer,
|
||||||
state.GetRejectReason());
|
state.GetRejectReason());
|
||||||
pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
|
pfrom->PushMessage(NetMsgType::REJECT, strCommand, state.GetRejectCode(),
|
||||||
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
|
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
|
||||||
if (nDoS > 0)
|
if (nDoS > 0)
|
||||||
Misbehaving(pfrom->GetId(), nDoS);
|
Misbehaving(pfrom->GetId(), nDoS);
|
||||||
}
|
}
|
||||||
} else if (strCommand == "headers" && !fImporting && !fReindex) // Ignore headers received while importing
|
} else if (strCommand == NetMsgType::HEADERS && !fImporting && !fReindex) // Ignore headers received while importing
|
||||||
{
|
{
|
||||||
std::vector<CBlockHeader> headers;
|
std::vector<CBlockHeader> headers;
|
||||||
|
|
||||||
@@ -7660,12 +7632,12 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
{
|
{
|
||||||
pfrom->sendhdrsreq = (int32_t)pindexLast->GetHeight();
|
pfrom->sendhdrsreq = (int32_t)pindexLast->GetHeight();
|
||||||
LogPrint("net", "more getheaders (%d) to end to peer=%d (startheight:%d)\n", pindexLast->GetHeight(), pfrom->id, pfrom->nStartingHeight);
|
LogPrint("net", "more getheaders (%d) to end to peer=%d (startheight:%d)\n", pindexLast->GetHeight(), pfrom->id, pfrom->nStartingHeight);
|
||||||
pfrom->PushMessage("getheaders", chainActive.GetLocator(pindexLast), uint256());
|
pfrom->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexLast), uint256());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckBlockIndex();
|
CheckBlockIndex();
|
||||||
} else if (strCommand == "block" && !fImporting && !fReindex) // Ignore blocks received while importing
|
} else if (strCommand == NetMsgType::BLOCK && !fImporting && !fReindex) // Ignore blocks received while importing
|
||||||
{
|
{
|
||||||
CBlock block;
|
CBlock block;
|
||||||
vRecv >> block;
|
vRecv >> block;
|
||||||
@@ -7684,7 +7656,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
ProcessNewBlock(0,0,state, pfrom, &block, forceProcessing, NULL);
|
ProcessNewBlock(0,0,state, pfrom, &block, forceProcessing, NULL);
|
||||||
int nDoS;
|
int nDoS;
|
||||||
if (state.IsInvalid(nDoS)) {
|
if (state.IsInvalid(nDoS)) {
|
||||||
pfrom->PushMessage("reject", strCommand, state.GetRejectCode(),
|
pfrom->PushMessage(NetMsgType::REJECT, strCommand, state.GetRejectCode(),
|
||||||
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
|
state.GetRejectReason().substr(0, MAX_REJECT_MESSAGE_LENGTH), inv.hash);
|
||||||
if (nDoS > 0) {
|
if (nDoS > 0) {
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
@@ -7692,7 +7664,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (strCommand == "mempool") {
|
} else if (strCommand == NetMsgType::MEMPOOL) {
|
||||||
LOCK2(cs_main, pfrom->cs_filter);
|
LOCK2(cs_main, pfrom->cs_filter);
|
||||||
//LogPrintf("%s: mempool request from %s",__func__, pfrom->addr.ToString().c_str());
|
//LogPrintf("%s: mempool request from %s",__func__, pfrom->addr.ToString().c_str());
|
||||||
// TODO: limit mempool requests per time and per peer
|
// TODO: limit mempool requests per time and per peer
|
||||||
@@ -7710,18 +7682,20 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
}
|
}
|
||||||
vInv.push_back(inv);
|
vInv.push_back(inv);
|
||||||
if (vInv.size() == MAX_INV_SZ) {
|
if (vInv.size() == MAX_INV_SZ) {
|
||||||
pfrom->PushMessage("inv", vInv);
|
pfrom->PushMessage(NetMsgType::INV, vInv);
|
||||||
vInv.clear();
|
vInv.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (vInv.size() > 0)
|
if (vInv.size() > 0)
|
||||||
pfrom->PushMessage("inv", vInv);
|
pfrom->PushMessage(NetMsgType::INV, vInv);
|
||||||
} else if (fAlerts && strCommand == "alert") {
|
} else if (strCommand == NetMsgType::ALERT) {
|
||||||
// Do not process alert p2p messages and give DoS penalty
|
// Small DoS penalty so peers that send us lots of
|
||||||
|
// duplicate/expired/invalid-signature/whatever alerts
|
||||||
|
// eventually get banned.
|
||||||
Misbehaving(pfrom->GetId(), 10);
|
Misbehaving(pfrom->GetId(), 10);
|
||||||
} else if (!(nLocalServices & NODE_BLOOM) &&
|
} else if (!(nLocalServices & NODE_BLOOM) &&
|
||||||
(strCommand == "filterload" ||
|
(strCommand == NetMsgType::FILTERLOAD ||
|
||||||
strCommand == "filteradd")) {
|
strCommand == NetMsgType::FILTERADD)) {
|
||||||
if (pfrom->nVersion >= NO_BLOOM_VERSION) {
|
if (pfrom->nVersion >= NO_BLOOM_VERSION) {
|
||||||
Misbehaving(pfrom->GetId(), 100);
|
Misbehaving(pfrom->GetId(), 100);
|
||||||
return false;
|
return false;
|
||||||
@@ -7729,7 +7703,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
pfrom->fDisconnect = true;
|
pfrom->fDisconnect = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (strCommand == "filterload") {
|
} else if (strCommand == NetMsgType::FILTERLOAD) {
|
||||||
CBloomFilter filter;
|
CBloomFilter filter;
|
||||||
vRecv >> filter;
|
vRecv >> filter;
|
||||||
|
|
||||||
@@ -7744,7 +7718,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
pfrom->pfilter->UpdateEmptyFull();
|
pfrom->pfilter->UpdateEmptyFull();
|
||||||
}
|
}
|
||||||
pfrom->fRelayTxes = true;
|
pfrom->fRelayTxes = true;
|
||||||
} else if (strCommand == "filteradd") {
|
} else if (strCommand == NetMsgType::FILTERADD) {
|
||||||
vector<unsigned char> vData;
|
vector<unsigned char> vData;
|
||||||
vRecv >> vData;
|
vRecv >> vData;
|
||||||
|
|
||||||
@@ -7760,14 +7734,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
else
|
else
|
||||||
Misbehaving(pfrom->GetId(), 100);
|
Misbehaving(pfrom->GetId(), 100);
|
||||||
}
|
}
|
||||||
} else if (strCommand == "filterclear") {
|
} else if (strCommand == NetMsgType::FILTERCLEAR) {
|
||||||
LOCK(pfrom->cs_filter);
|
LOCK(pfrom->cs_filter);
|
||||||
if (nLocalServices & NODE_BLOOM) {
|
if (nLocalServices & NODE_BLOOM) {
|
||||||
delete pfrom->pfilter;
|
delete pfrom->pfilter;
|
||||||
pfrom->pfilter = new CBloomFilter();
|
pfrom->pfilter = new CBloomFilter();
|
||||||
}
|
}
|
||||||
pfrom->fRelayTxes = true;
|
pfrom->fRelayTxes = true;
|
||||||
} else if (strCommand == "reject") {
|
} else if (strCommand == NetMsgType::REJECT) {
|
||||||
if (fDebug) {
|
if (fDebug) {
|
||||||
try {
|
try {
|
||||||
string strMsg; unsigned char ccode; string strReason;
|
string strMsg; unsigned char ccode; string strReason;
|
||||||
@@ -7788,7 +7762,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
LogPrint("net", "Unparseable reject message received\n");
|
LogPrint("net", "Unparseable reject message received\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (strCommand == "notfound") {
|
} else if (strCommand == NetMsgType::NOTFOUND) {
|
||||||
// We do not care about the NOTFOUND message, but logging an Unknown Command
|
// We do not care about the NOTFOUND message, but logging an Unknown Command
|
||||||
// message would be undesirable as we transmit it ourselves.
|
// message would be undesirable as we transmit it ourselves.
|
||||||
} else {
|
} else {
|
||||||
@@ -7881,7 +7855,7 @@ bool ProcessMessages(CNode* pfrom)
|
|||||||
}
|
}
|
||||||
catch (const std::ios_base::failure& e)
|
catch (const std::ios_base::failure& e)
|
||||||
{
|
{
|
||||||
pfrom->PushMessage("reject", strCommand, REJECT_MALFORMED, string("error parsing message"));
|
pfrom->PushMessage(NetMsgType::REJECT, strCommand, REJECT_MALFORMED, string("error parsing message"));
|
||||||
if (strstr(e.what(), "end of data"))
|
if (strstr(e.what(), "end of data"))
|
||||||
{
|
{
|
||||||
// Allow exceptions from under-length message on vRecv
|
// Allow exceptions from under-length message on vRecv
|
||||||
@@ -7933,9 +7907,12 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
|||||||
// RPC ping request by user
|
// RPC ping request by user
|
||||||
pingSend = true;
|
pingSend = true;
|
||||||
}
|
}
|
||||||
if (pto->nPingNonceSent == 0 && pto->nPingUsecStart + PING_INTERVAL * 1000000 < GetTimeMicros()) {
|
if (pto->nPingUsecStart + PING_INTERVAL * 1000000 < GetTimeMicros()) {
|
||||||
// Ping automatically sent as a latency probe & keepalive.
|
// Ping automatically sent as a latency probe & keepalive.
|
||||||
pingSend = true;
|
pingSend = true;
|
||||||
|
if (pto->nPingNonceSent != 0) {
|
||||||
|
pto->nPingRetry++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (pingSend) {
|
if (pingSend) {
|
||||||
uint64_t nonce = 0;
|
uint64_t nonce = 0;
|
||||||
@@ -7946,12 +7923,12 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
|||||||
pto->nPingUsecStart = GetTimeMicros();
|
pto->nPingUsecStart = GetTimeMicros();
|
||||||
if (pto->nVersion > BIP0031_VERSION) {
|
if (pto->nVersion > BIP0031_VERSION) {
|
||||||
pto->nPingNonceSent = nonce;
|
pto->nPingNonceSent = nonce;
|
||||||
pto->PushMessage("ping", nonce);
|
pto->PushMessage(NetMsgType::PING, nonce);
|
||||||
} else {
|
} // else {
|
||||||
// Peer is too old to support ping command with nonce, pong will never arrive.
|
// Peer is too old to support ping command with nonce, pong will never arrive.
|
||||||
pto->nPingNonceSent = 0;
|
// pto->nPingNonceSent = 0;
|
||||||
pto->PushMessage("ping");
|
// pto->PushMessage("ping");
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
TRY_LOCK(cs_main, lockMain); // Acquire cs_main for IsInitialBlockDownload() and CNodeState()
|
TRY_LOCK(cs_main, lockMain); // Acquire cs_main for IsInitialBlockDownload() and CNodeState()
|
||||||
@@ -7987,17 +7964,29 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
|||||||
{
|
{
|
||||||
pto->addrKnown.insert(addr.GetKey());
|
pto->addrKnown.insert(addr.GetKey());
|
||||||
vAddr.push_back(addr);
|
vAddr.push_back(addr);
|
||||||
// receiver rejects addr messages larger than 1000
|
|
||||||
if (vAddr.size() >= 1000)
|
if (vAddr.size() >= MAX_ADDR_TO_SEND)
|
||||||
{
|
{
|
||||||
pto->PushMessage("addr", vAddr);
|
// Should be impossible since we always check size before adding to
|
||||||
vAddr.clear();
|
// vAddrToSend. Recover by trimming the vector.
|
||||||
|
vAddr.resize(MAX_ADDR_TO_SEND);
|
||||||
}
|
}
|
||||||
|
const char* msg_type;
|
||||||
|
int make_flags;
|
||||||
|
if (pto->m_wants_addrv2) {
|
||||||
|
msg_type = NetMsgType::ADDRV2;
|
||||||
|
make_flags = ADDRV2_FORMAT;
|
||||||
|
} else {
|
||||||
|
msg_type = NetMsgType::ADDR;
|
||||||
|
make_flags = 0;
|
||||||
|
}
|
||||||
|
pto->PushAddrMessage(CNetMsgMaker(std::min(pto->nVersion, PROTOCOL_VERSION)).Make(make_flags, msg_type, pto->vAddrToSend));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pto->vAddrToSend.clear();
|
pto->vAddrToSend.clear();
|
||||||
if (!vAddr.empty())
|
vAddr.clear();
|
||||||
pto->PushMessage("addr", vAddr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CNodeState &state = *State(pto->GetId());
|
CNodeState &state = *State(pto->GetId());
|
||||||
@@ -8010,7 +7999,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
|||||||
LogPrintf("Warning: not banning local peer %s!\n", pto->addr.ToString());
|
LogPrintf("Warning: not banning local peer %s!\n", pto->addr.ToString());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CNode::Ban(pto->addr);
|
CNode::Ban(pto->addr, BanReasonNodeMisbehaving);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.fShouldBan = false;
|
state.fShouldBan = false;
|
||||||
@@ -8021,7 +8010,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
|||||||
return(true);
|
return(true);
|
||||||
}
|
}
|
||||||
BOOST_FOREACH(const CBlockReject& reject, state.rejects)
|
BOOST_FOREACH(const CBlockReject& reject, state.rejects)
|
||||||
pto->PushMessage("reject", (string)"block", reject.chRejectCode, reject.strRejectReason, reject.hashBlock);
|
pto->PushMessage(NetMsgType::REJECT, (string)"block", reject.chRejectCode, reject.strRejectReason, reject.hashBlock);
|
||||||
state.rejects.clear();
|
state.rejects.clear();
|
||||||
|
|
||||||
// Start block sync
|
// Start block sync
|
||||||
@@ -8035,7 +8024,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
|||||||
nSyncStarted++;
|
nSyncStarted++;
|
||||||
CBlockIndex *pindexStart = pindexBestHeader->pprev ? pindexBestHeader->pprev : pindexBestHeader;
|
CBlockIndex *pindexStart = pindexBestHeader->pprev ? pindexBestHeader->pprev : pindexBestHeader;
|
||||||
LogPrint("net", "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->GetHeight(), pto->id, pto->nStartingHeight);
|
LogPrint("net", "initial getheaders (%d) to peer=%d (startheight:%d)\n", pindexStart->GetHeight(), pto->id, pto->nStartingHeight);
|
||||||
pto->PushMessage("getheaders", chainActive.GetLocator(pindexStart), uint256());
|
pto->PushMessage(NetMsgType::GETHEADERS, chainActive.GetLocator(pindexStart), uint256());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8083,7 +8072,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
|||||||
vInv.push_back(inv);
|
vInv.push_back(inv);
|
||||||
if (vInv.size() >= 1000)
|
if (vInv.size() >= 1000)
|
||||||
{
|
{
|
||||||
pto->PushMessage("inv", vInv);
|
pto->PushMessage(NetMsgType::INV, vInv);
|
||||||
vInv.clear();
|
vInv.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8091,7 +8080,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
|||||||
pto->vInventoryToSend = vInvWait;
|
pto->vInventoryToSend = vInvWait;
|
||||||
}
|
}
|
||||||
if (!vInv.empty())
|
if (!vInv.empty())
|
||||||
pto->PushMessage("inv", vInv);
|
pto->PushMessage(NetMsgType::INV, vInv);
|
||||||
|
|
||||||
// Detect whether we're stalling
|
// Detect whether we're stalling
|
||||||
int64_t nNow = GetTimeMicros();
|
int64_t nNow = GetTimeMicros();
|
||||||
@@ -8156,7 +8145,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
|||||||
vGetData.push_back(inv);
|
vGetData.push_back(inv);
|
||||||
if (vGetData.size() >= 1000)
|
if (vGetData.size() >= 1000)
|
||||||
{
|
{
|
||||||
pto->PushMessage("getdata", vGetData);
|
pto->PushMessage(NetMsgType::GETDATA, vGetData);
|
||||||
vGetData.clear();
|
vGetData.clear();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -8166,7 +8155,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
|||||||
pto->mapAskFor.erase(pto->mapAskFor.begin());
|
pto->mapAskFor.erase(pto->mapAskFor.begin());
|
||||||
}
|
}
|
||||||
if (!vGetData.empty())
|
if (!vGetData.empty())
|
||||||
pto->PushMessage("getdata", vGetData);
|
pto->PushMessage(NetMsgType::GETDATA, vGetData);
|
||||||
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -71,10 +71,6 @@ static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 2000000;//MAX_BLOCK_SIZE;
|
|||||||
static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0;
|
static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0;
|
||||||
/** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/
|
/** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/
|
||||||
static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = DEFAULT_BLOCK_MAX_SIZE / 2;
|
static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = DEFAULT_BLOCK_MAX_SIZE / 2;
|
||||||
/** Default for accepting alerts from the P2P network. */
|
|
||||||
static const bool DEFAULT_ALERTS = true;
|
|
||||||
/** Minimum alert priority for enabling safe mode. */
|
|
||||||
static const int ALERT_PRIORITY_SAFE_MODE = 4000;
|
|
||||||
/** Maximum reorg length we will accept before we shut down and alert the user. */
|
/** Maximum reorg length we will accept before we shut down and alert the user. */
|
||||||
static unsigned int MAX_REORG_LENGTH = _COINBASE_MATURITY - 1;
|
static unsigned int MAX_REORG_LENGTH = _COINBASE_MATURITY - 1;
|
||||||
/** Maximum number of signature check operations in an IsStandard() P2SH script */
|
/** Maximum number of signature check operations in an IsStandard() P2SH script */
|
||||||
@@ -118,6 +114,9 @@ static const unsigned int DATABASE_FLUSH_INTERVAL = 24 * 60 * 60;
|
|||||||
static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111;
|
static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111;
|
||||||
static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60;
|
static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60;
|
||||||
|
|
||||||
|
// NSPV enabled?
|
||||||
|
static const bool DEFAULT_NSPV_PROCESSING = false;
|
||||||
|
|
||||||
//static const bool DEFAULT_ADDRESSINDEX = false;
|
//static const bool DEFAULT_ADDRESSINDEX = false;
|
||||||
//static const bool DEFAULT_SPENTINDEX = false;
|
//static const bool DEFAULT_SPENTINDEX = false;
|
||||||
#define DEFAULT_ADDRESSINDEX (GetArg("-ac_cc",0) != 0 || GetArg("-ac_ccactivate",0) != 0)
|
#define DEFAULT_ADDRESSINDEX (GetArg("-ac_cc",0) != 0 || GetArg("-ac_ccactivate",0) != 0)
|
||||||
@@ -165,7 +164,6 @@ extern bool fCheckpointsEnabled;
|
|||||||
extern bool fCoinbaseEnforcedProtectionEnabled;
|
extern bool fCoinbaseEnforcedProtectionEnabled;
|
||||||
extern size_t nCoinCacheUsage;
|
extern size_t nCoinCacheUsage;
|
||||||
extern CFeeRate minRelayTxFee;
|
extern CFeeRate minRelayTxFee;
|
||||||
extern bool fAlerts;
|
|
||||||
extern int64_t nMaxTipAge;
|
extern int64_t nMaxTipAge;
|
||||||
|
|
||||||
/** Best header we've seen so far (used for getheaders queries' starting points). */
|
/** Best header we've seen so far (used for getheaders queries' starting points). */
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "consensus/consensus.h"
|
#include "consensus/consensus.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "hush_defs.h"
|
#include "hush_defs.h"
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utiltime.h"
|
#include "utiltime.h"
|
||||||
#include "utilmoneystr.h"
|
#include "utilmoneystr.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
#include <boost/thread/synchronized_value.hpp>
|
#include <boost/thread/synchronized_value.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|||||||
141
src/miner.cpp
141
src/miner.cpp
@@ -1067,6 +1067,42 @@ void static RandomXMiner()
|
|||||||
);
|
);
|
||||||
miningTimer.start();
|
miningTimer.start();
|
||||||
|
|
||||||
|
randomx_flags flags = randomx_get_flags();
|
||||||
|
// TODO: attempt to use large pages and fall back to no large pages
|
||||||
|
// flags |= RANDOMX_FLAG_LARGE_PAGES;
|
||||||
|
flags |= RANDOMX_FLAG_FULL_MEM;
|
||||||
|
//flags |= RANDOMX_FLAG_JIT;
|
||||||
|
randomx_cache *randomxCache = randomx_alloc_cache(flags);
|
||||||
|
if (randomxCache == NULL) {
|
||||||
|
LogPrintf("RandomX cache is null, something is wrong, cannot mine!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rxdebug("%s: created randomx flags + cache\n");
|
||||||
|
randomx_dataset *randomxDataset = randomx_alloc_dataset(flags);
|
||||||
|
rxdebug("%s: created dataset\n");
|
||||||
|
|
||||||
|
auto datasetItemCount = randomx_dataset_item_count();
|
||||||
|
rxdebug("%s: dataset items=%lu\n", datasetItemCount);
|
||||||
|
|
||||||
|
if( randomxDataset == nullptr) {
|
||||||
|
LogPrintf("%s: allocating randomx dataset failed!\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char randomxHash[RANDOMX_HASH_SIZE];
|
||||||
|
rxdebug("%s: created randomxHash of size %d\n", RANDOMX_HASH_SIZE);
|
||||||
|
char randomxKey[82]; // randomx spec says keysize of >60 bytes is implementation-specific
|
||||||
|
// initial randomx key is unique to every Hush Smart Chain, and has at least 9 bytes (2^9=128 bits) of entropy
|
||||||
|
// since magic is 4 bytes, rpc port is 4 bytes and smart chain symbol must be at least 1 character long
|
||||||
|
snprintf(randomxKey, 81, "%08x%s%08x", ASSETCHAINS_MAGIC, SMART_CHAIN_SYMBOL, ASSETCHAINS_RPCPORT);
|
||||||
|
|
||||||
|
// With the defaults of 1024 and 64
|
||||||
|
// the key block will change every ~21.3 hours with a 75s block time
|
||||||
|
// and every ~17 hours with the default 60s block time for HSCs
|
||||||
|
int randomxInterval = GetArg("-ac_randomx_interval",1024);
|
||||||
|
// This lag is 80 mins for 75s blocktime and 64 mins for 60s (default) blocktime for HSCs
|
||||||
|
int randomxBlockLag = GetArg("-ac_randomx_lag", 64);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// fprintf(stderr,"RandomXMiner: mining %s with randomx\n",SMART_CHAIN_SYMBOL);
|
// fprintf(stderr,"RandomXMiner: mining %s with randomx\n",SMART_CHAIN_SYMBOL);
|
||||||
|
|
||||||
@@ -1115,6 +1151,38 @@ void static RandomXMiner()
|
|||||||
Mining_height = pindexPrev->GetHeight()+1;
|
Mining_height = pindexPrev->GetHeight()+1;
|
||||||
Mining_start = (uint32_t)time(NULL);
|
Mining_start = (uint32_t)time(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fprintf(stderr,"RandomXMiner: using initial key with interval=%d and lag=%d\n", randomxInterval, randomxBlockLag);
|
||||||
|
rxdebug("%s: using initial key, interval=%d, lag=%d, Mining_height=%u\n", randomxInterval, randomxBlockLag, Mining_height);
|
||||||
|
// Use the initial key at the start of the chain, until the first key block
|
||||||
|
if( (Mining_height) < randomxInterval + randomxBlockLag) {
|
||||||
|
randomx_init_cache(randomxCache, &randomxKey, sizeof randomxKey);
|
||||||
|
rxdebug("%s: initialized cache with initial key\n");
|
||||||
|
} else {
|
||||||
|
rxdebug("%s: calculating keyHeight with randomxInterval=%d\n", randomxInterval);
|
||||||
|
// At heights between intervals, we use the same block key and wait randomxBlockLag blocks until changing
|
||||||
|
int keyHeight = ((Mining_height - randomxBlockLag) / randomxInterval) * randomxInterval;
|
||||||
|
uint256 randomxBlockKey = chainActive[keyHeight]->GetBlockHash();
|
||||||
|
|
||||||
|
randomx_init_cache(randomxCache, &randomxBlockKey, sizeof randomxBlockKey);
|
||||||
|
rxdebug("%s: initialized cache with keyHeight=%d, randomxBlockKey=%s\n", keyHeight, randomxBlockKey.ToString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: this is hardcoded to use 2 threads instead of the number of mining threads
|
||||||
|
rxdebug("%s: initializing dataset with 2 threads\n");
|
||||||
|
std::thread t1(&randomx_init_dataset, randomxDataset, randomxCache, 0, datasetItemCount / 2);
|
||||||
|
std::thread t2(&randomx_init_dataset, randomxDataset, randomxCache, datasetItemCount / 2, datasetItemCount - datasetItemCount / 2);
|
||||||
|
t1.join();
|
||||||
|
t2.join();
|
||||||
|
|
||||||
|
// randomx_init_dataset(randomxDataset, randomxCache, 0, datasetItemCount);
|
||||||
|
rxdebug("%s: dataset initialized\n");
|
||||||
|
|
||||||
|
randomx_vm *myVM = randomx_create_vm(flags, nullptr, randomxDataset);
|
||||||
|
if(myVM == NULL) {
|
||||||
|
LogPrintf("RandomXMiner: Cannot create RandomX VM, aborting!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
//fprintf(stderr,"RandomXMiner: Mining_start=%u\n", Mining_start);
|
//fprintf(stderr,"RandomXMiner: Mining_start=%u\n", Mining_start);
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, pindexPrev->GetHeight()+1, gpucount, 0);
|
CBlockTemplate *ptr = CreateNewBlockWithKey(reservekey, pindexPrev->GetHeight()+1, gpucount, 0);
|
||||||
@@ -1168,6 +1236,7 @@ void static RandomXMiner()
|
|||||||
} else fprintf(stderr,"%s vouts.%d mining.%d vs %d\n",SMART_CHAIN_SYMBOL,(int32_t)pblock->vtx[0].vout.size(),Mining_height,ASSETCHAINS_MINHEIGHT);
|
} else fprintf(stderr,"%s vouts.%d mining.%d vs %d\n",SMART_CHAIN_SYMBOL,(int32_t)pblock->vtx[0].vout.size(),Mining_height,ASSETCHAINS_MINHEIGHT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rxdebug("%s: incrementing extra nonce\n");
|
||||||
IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
|
IncrementExtraNonce(pblock, pindexPrev, nExtraNonce);
|
||||||
// fprintf(stderr,"RandomXMiner: %u transactions in block\n",(int32_t)pblock->vtx.size());
|
// fprintf(stderr,"RandomXMiner: %u transactions in block\n",(int32_t)pblock->vtx.size());
|
||||||
LogPrintf("Running HushRandomXMiner with %u transactions in block (%u bytes)\n",pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION));
|
LogPrintf("Running HushRandomXMiner with %u transactions in block (%u bytes)\n",pblock->vtx.size(),::GetSerializeSize(*pblock,SER_NETWORK,PROTOCOL_VERSION));
|
||||||
@@ -1181,8 +1250,8 @@ void static RandomXMiner()
|
|||||||
HASHTarget = arith_uint256().SetCompact(savebits);
|
HASHTarget = arith_uint256().SetCompact(savebits);
|
||||||
roundrobin_delay = ROUNDROBIN_DELAY;
|
roundrobin_delay = ROUNDROBIN_DELAY;
|
||||||
Mining_start = 0;
|
Mining_start = 0;
|
||||||
|
|
||||||
gotinvalid = 0;
|
gotinvalid = 0;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if ( gotinvalid != 0 ) {
|
if ( gotinvalid != 0 ) {
|
||||||
@@ -1196,13 +1265,6 @@ void static RandomXMiner()
|
|||||||
arith_uint256 hashTarget;
|
arith_uint256 hashTarget;
|
||||||
hashTarget = HASHTarget;
|
hashTarget = HASHTarget;
|
||||||
|
|
||||||
char randomxHash[RANDOMX_HASH_SIZE];
|
|
||||||
//fprintf(stderr,"RandomXMiner: created randomxHash of size %d\n", RANDOMX_HASH_SIZE);
|
|
||||||
char randomxKey[82]; // randomx spec says keysize of >60 bytes is implementation-specific
|
|
||||||
// initial randomx key is unique to every Hush Smart Chain, and has at least 9 bytes (2^128 bits) of entropy
|
|
||||||
// since magic is 4 bytes, rpc port is 4 bytes and smart chain symbol must be at least 1 character long
|
|
||||||
snprintf(randomxKey, 81, "%08x%s%08x", ASSETCHAINS_MAGIC, SMART_CHAIN_SYMBOL, ASSETCHAINS_RPCPORT);
|
|
||||||
|
|
||||||
CDataStream randomxInput(SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream randomxInput(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
// Use the current block as randomx input
|
// Use the current block as randomx input
|
||||||
randomxInput << pblocktemplate->block;
|
randomxInput << pblocktemplate->block;
|
||||||
@@ -1211,49 +1273,9 @@ void static RandomXMiner()
|
|||||||
// fprintf(stderr,"RandomXMiner: created randomxKey=%s , randomxInput.size=%lu\n", randomxKey, randomxInput.size() ); //randomxInput);
|
// fprintf(stderr,"RandomXMiner: created randomxKey=%s , randomxInput.size=%lu\n", randomxKey, randomxInput.size() ); //randomxInput);
|
||||||
rxdebug("%s: randomxKey=%s randomxInput=%s\n", randomxKey, HexStr(randomxInput).c_str());
|
rxdebug("%s: randomxKey=%s randomxInput=%s\n", randomxKey, HexStr(randomxInput).c_str());
|
||||||
|
|
||||||
randomx_flags flags = randomx_get_flags();
|
rxdebug("%s: calculating randomx hash\n");
|
||||||
randomx_cache *randomxCache = randomx_alloc_cache(flags);
|
|
||||||
if (randomxCache == NULL) {
|
|
||||||
LogPrintf("RandomX cache is null, something is wrong, cannot mine!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// fprintf(stderr,"RandomXMiner: created randomx flags + cache\n");
|
|
||||||
|
|
||||||
// With the defaults of 1024 and 64
|
|
||||||
// the key block will change every ~21.3 hours with a 75s block time
|
|
||||||
// and every ~17 hours with the default 60s block time for HSCs
|
|
||||||
int randomxInterval = GetArg("-ac_randomx_interval",1024);
|
|
||||||
// This lag is 80 mins for 75s blocktime and 64 mins for 60s (default) blocktime for HSCs
|
|
||||||
int randomxBlockLag = GetArg("-ac_randomx_lag", 64);
|
|
||||||
|
|
||||||
// fprintf(stderr,"RandomXMiner: using initial key with interval=%d and lag=%d\n", randomxInterval, randomxBlockLag);
|
|
||||||
rxdebug("%s: using initial key, interval=%d, lag=%d, Mining_height=%u\n", randomxInterval, randomxBlockLag, Mining_height);
|
|
||||||
// Use the initial key at the start of the chain, until the first key block
|
|
||||||
if( (Mining_height) < randomxInterval + randomxBlockLag) {
|
|
||||||
randomx_init_cache(randomxCache, &randomxKey, sizeof randomxKey);
|
|
||||||
rxdebug("%s: initialized cache with initial key\n");
|
|
||||||
} else {
|
|
||||||
rxdebug("%s: calculating keyHeight with randomxInterval=%d\n", randomxInterval);
|
|
||||||
// At heights between intervals, we use the same block key and wait randomxBlockLag blocks until changing
|
|
||||||
int keyHeight = ((Mining_height - randomxBlockLag) / randomxInterval) * randomxInterval;
|
|
||||||
uint256 randomxBlockKey = chainActive[keyHeight]->GetBlockHash();
|
|
||||||
|
|
||||||
randomx_init_cache(randomxCache, &randomxBlockKey, sizeof randomxBlockKey);
|
|
||||||
rxdebug("%s: initialized cache with keyHeight=%d, randomxBlockKey=%s\n", keyHeight, randomxBlockKey.ToString().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
randomx_vm *myVM = randomx_create_vm(flags, randomxCache, NULL);
|
|
||||||
if(myVM == NULL) {
|
|
||||||
LogPrintf("RandomXMiner: Cannot create RandomX VM, aborting!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
randomx_calculate_hash(myVM, &randomxInput, sizeof randomxInput, randomxHash);
|
randomx_calculate_hash(myVM, &randomxInput, sizeof randomxInput, randomxHash);
|
||||||
// rxdebug("calculated randomx hash\n");
|
rxdebug("%s: calculated randomx hash\n");
|
||||||
|
|
||||||
randomx_destroy_vm(myVM);
|
|
||||||
// fprintf(stderr,"RandomXMiner: destroyed VM\n");
|
|
||||||
randomx_release_cache(randomxCache);
|
|
||||||
|
|
||||||
rxdebug("%s: randomxHash=");
|
rxdebug("%s: randomxHash=");
|
||||||
if (fRandomXDebug) {
|
if (fRandomXDebug) {
|
||||||
@@ -1263,8 +1285,8 @@ void static RandomXMiner()
|
|||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
// Use randomx hash to build a valid block
|
|
||||||
|
|
||||||
|
// Use randomx hash to build a valid block
|
||||||
std::function<bool(std::vector<unsigned char>)> validBlock =
|
std::function<bool(std::vector<unsigned char>)> validBlock =
|
||||||
#ifdef ENABLE_WALLET
|
#ifdef ENABLE_WALLET
|
||||||
[&pblock, &hashTarget, &pwallet, &reservekey, &m_cs, &cancelSolver, &chainparams]
|
[&pblock, &hashTarget, &pwallet, &reservekey, &m_cs, &cancelSolver, &chainparams]
|
||||||
@@ -1277,7 +1299,7 @@ void static RandomXMiner()
|
|||||||
rxdebug("%s: Checking solution against target\n");
|
rxdebug("%s: Checking solution against target\n");
|
||||||
pblock->nSolution = soln;
|
pblock->nSolution = soln;
|
||||||
solutionTargetChecks.increment();
|
solutionTargetChecks.increment();
|
||||||
fprintf(stderr,"%s: solutionTargetChecks=%lu\n", __func__, solutionTargetChecks.get());
|
// fprintf(stderr,"%s: solutionTargetChecks=%lu\n", __func__, solutionTargetChecks.get());
|
||||||
B = *pblock;
|
B = *pblock;
|
||||||
h = UintToArith256(B.GetHash());
|
h = UintToArith256(B.GetHash());
|
||||||
|
|
||||||
@@ -1371,7 +1393,14 @@ void static RandomXMiner()
|
|||||||
pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1);
|
pblock->nNonce = ArithToUint256(UintToArith256(pblock->nNonce) + 1);
|
||||||
pblock->nBits = savebits;
|
pblock->nBits = savebits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rxdebug("%s: going to destroy rx VM\n");
|
||||||
|
randomx_destroy_vm(myVM);
|
||||||
|
rxdebug("%s: destroyed VM\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} catch (const boost::thread_interrupted&) {
|
} catch (const boost::thread_interrupted&) {
|
||||||
miningTimer.stop();
|
miningTimer.stop();
|
||||||
c.disconnect();
|
c.disconnect();
|
||||||
@@ -1383,6 +1412,11 @@ void static RandomXMiner()
|
|||||||
fprintf(stderr,"RandomXMiner: runtime error: %s\n", e.what());
|
fprintf(stderr,"RandomXMiner: runtime error: %s\n", e.what());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
randomx_release_dataset(randomxDataset);
|
||||||
|
rxdebug("%s: released dataset\n");
|
||||||
|
randomx_release_cache(randomxCache);
|
||||||
|
rxdebug("%s: released cache\n");
|
||||||
miningTimer.stop();
|
miningTimer.stop();
|
||||||
c.disconnect();
|
c.disconnect();
|
||||||
}
|
}
|
||||||
@@ -1646,7 +1680,7 @@ void static BitcoinMiner()
|
|||||||
LogPrint("pow", "- Checking solution against target\n");
|
LogPrint("pow", "- Checking solution against target\n");
|
||||||
pblock->nSolution = soln;
|
pblock->nSolution = soln;
|
||||||
solutionTargetChecks.increment();
|
solutionTargetChecks.increment();
|
||||||
rxdebug("%s: solutionTargetChecks=%lu\n", solutionTargetChecks.get());
|
// fprintf(stderr, "%s: solutionTargetChecks=%lu\n", __func__, solutionTargetChecks.get());
|
||||||
B = *pblock;
|
B = *pblock;
|
||||||
h = UintToArith256(B.GetHash());
|
h = UintToArith256(B.GetHash());
|
||||||
/*for (z=31; z>=16; z--)
|
/*for (z=31; z>=16; z--)
|
||||||
@@ -1859,6 +1893,7 @@ void static BitcoinMiner()
|
|||||||
LogPrintf("HushMiner runtime error: %s\n", e.what());
|
LogPrintf("HushMiner runtime error: %s\n", e.what());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
miningTimer.stop();
|
miningTimer.stop();
|
||||||
c.disconnect();
|
c.disconnect();
|
||||||
}
|
}
|
||||||
|
|||||||
689
src/net.cpp
689
src/net.cpp
File diff suppressed because it is too large
Load Diff
140
src/net.h
140
src/net.h
@@ -20,9 +20,11 @@
|
|||||||
#ifndef HUSH_NET_H
|
#ifndef HUSH_NET_H
|
||||||
#define HUSH_NET_H
|
#define HUSH_NET_H
|
||||||
|
|
||||||
|
#include "addrdb.h"
|
||||||
#include "bloom.h"
|
#include "bloom.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
|
#include "i2p.h"
|
||||||
#include "limitedmap.h"
|
#include "limitedmap.h"
|
||||||
#include "mruset.h"
|
#include "mruset.h"
|
||||||
#include "netbase.h"
|
#include "netbase.h"
|
||||||
@@ -31,7 +33,7 @@
|
|||||||
#include "streams.h"
|
#include "streams.h"
|
||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -62,6 +64,8 @@ namespace boost {
|
|||||||
|
|
||||||
/** Time between pings automatically sent out for latency probing and keepalive (in seconds). */
|
/** Time between pings automatically sent out for latency probing and keepalive (in seconds). */
|
||||||
static const int PING_INTERVAL = 2 * 60;
|
static const int PING_INTERVAL = 2 * 60;
|
||||||
|
/** Retry Time between pings automatically sent out for latency probing and keepalive (in seconds). */
|
||||||
|
static const int MAX_PING_RETRY = 20;
|
||||||
/** Time after which to disconnect, after waiting for a ping response (or inactivity). */
|
/** Time after which to disconnect, after waiting for a ping response (or inactivity). */
|
||||||
static const int TIMEOUT_INTERVAL = 20 * 60;
|
static const int TIMEOUT_INTERVAL = 20 * 60;
|
||||||
/** The maximum number of entries in an 'inv' protocol message */
|
/** The maximum number of entries in an 'inv' protocol message */
|
||||||
@@ -84,6 +88,7 @@ static const unsigned int DEFAULT_MAX_PEER_CONNECTIONS = 384;
|
|||||||
static const int NETWORK_UPGRADE_PEER_PREFERENCE_BLOCK_PERIOD = 24 * 24 * 3;
|
static const int NETWORK_UPGRADE_PEER_PREFERENCE_BLOCK_PERIOD = 24 * 24 * 3;
|
||||||
/** Run the feeler connection loop once every 120 seconds. **/
|
/** Run the feeler connection loop once every 120 seconds. **/
|
||||||
static const int FEELER_INTERVAL = 120;
|
static const int FEELER_INTERVAL = 120;
|
||||||
|
extern std::atomic<bool> fNetworkActive;
|
||||||
|
|
||||||
unsigned int ReceiveFloodSize();
|
unsigned int ReceiveFloodSize();
|
||||||
unsigned int SendBufferSize();
|
unsigned int SendBufferSize();
|
||||||
@@ -99,6 +104,7 @@ CNode* ConnectNode(CAddress addrConnect, const char *pszDest = NULL);
|
|||||||
bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false);
|
bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false);
|
||||||
unsigned short GetListenPort();
|
unsigned short GetListenPort();
|
||||||
bool BindListenPort(const CService &bindAddr, std::string& strError, bool fAllowlisted = false);
|
bool BindListenPort(const CService &bindAddr, std::string& strError, bool fAllowlisted = false);
|
||||||
|
void LoadPeers();
|
||||||
void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler);
|
void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler);
|
||||||
bool StopNode();
|
bool StopNode();
|
||||||
void SocketSendData(CNode *pnode);
|
void SocketSendData(CNode *pnode);
|
||||||
@@ -108,11 +114,56 @@ X509 *generate_x509(EVP_PKEY *pkey);
|
|||||||
bool write_to_disk(EVP_PKEY *pkey, X509 *x509);
|
bool write_to_disk(EVP_PKEY *pkey, X509 *x509);
|
||||||
void configure_context(SSL_CTX *ctx, bool server_side);
|
void configure_context(SSL_CTX *ctx, bool server_side);
|
||||||
|
|
||||||
|
// OpenSSL related variables for metrics.cpp
|
||||||
|
static std::string routingsecrecy;
|
||||||
|
static std::string cipherdescription;
|
||||||
|
static std::string securitylevel;
|
||||||
|
static std::string validationdescription;
|
||||||
|
|
||||||
|
void GetBanned(banmap_t &banmap);
|
||||||
|
void SetBanned(const banmap_t &banmap);
|
||||||
|
|
||||||
|
//!check is the banlist has unwritten changes
|
||||||
|
bool BannedSetIsDirty();
|
||||||
|
//!set the "dirty" flag for the banlist
|
||||||
|
void SetBannedSetDirty(bool dirty=true);
|
||||||
|
//!clean unused entries (if bantime has expired)
|
||||||
|
void SweepBanned();
|
||||||
|
|
||||||
|
void CreateNodeFromAcceptedSocket(SOCKET hSocket,
|
||||||
|
bool whitelisted,
|
||||||
|
const CAddress& addr_bind,
|
||||||
|
const CAddress& addr);
|
||||||
typedef int NodeId;
|
typedef int NodeId;
|
||||||
|
|
||||||
|
enum NumConnections {
|
||||||
|
CONNECTIONS_NONE = 0,
|
||||||
|
CONNECTIONS_IN = (1U << 0),
|
||||||
|
CONNECTIONS_OUT = (1U << 1),
|
||||||
|
CONNECTIONS_ALL = (CONNECTIONS_IN | CONNECTIONS_OUT),
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t GetNodeCount(NumConnections num);
|
||||||
|
|
||||||
|
bool GetNetworkActive();
|
||||||
|
void SetNetworkActive(bool active);
|
||||||
|
|
||||||
class CNodeStats;
|
class CNodeStats;
|
||||||
void CopyNodeStats(std::vector<CNodeStats>& vstats);
|
void CopyNodeStats(std::vector<CNodeStats>& vstats);
|
||||||
|
|
||||||
|
struct CSerializedNetMsg
|
||||||
|
{
|
||||||
|
CSerializedNetMsg() = default;
|
||||||
|
CSerializedNetMsg(CSerializedNetMsg&&) = default;
|
||||||
|
CSerializedNetMsg& operator=(CSerializedNetMsg&&) = default;
|
||||||
|
// No copying, only moves.
|
||||||
|
CSerializedNetMsg(const CSerializedNetMsg& msg) = delete;
|
||||||
|
CSerializedNetMsg& operator=(const CSerializedNetMsg&) = delete;
|
||||||
|
|
||||||
|
std::vector<unsigned char> data;
|
||||||
|
std::string m_type;
|
||||||
|
};
|
||||||
|
|
||||||
struct CombinerAll
|
struct CombinerAll
|
||||||
{
|
{
|
||||||
typedef bool result_type;
|
typedef bool result_type;
|
||||||
@@ -155,17 +206,21 @@ enum
|
|||||||
|
|
||||||
bool IsPeerAddrLocalGood(CNode *pnode);
|
bool IsPeerAddrLocalGood(CNode *pnode);
|
||||||
void AdvertizeLocal(CNode *pnode);
|
void AdvertizeLocal(CNode *pnode);
|
||||||
void SetLimited(enum Network net, bool fLimited = true);
|
|
||||||
bool IsLimited(enum Network net);
|
|
||||||
bool IsLimited(const CNetAddr& addr);
|
|
||||||
bool AddLocal(const CService& addr, int nScore = LOCAL_NONE);
|
bool AddLocal(const CService& addr, int nScore = LOCAL_NONE);
|
||||||
bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE);
|
bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE);
|
||||||
bool RemoveLocal(const CService& addr);
|
bool RemoveLocal(const CService& addr);
|
||||||
bool SeenLocal(const CService& addr);
|
bool SeenLocal(const CService& addr);
|
||||||
bool IsLocal(const CService& addr);
|
bool IsLocal(const CService& addr);
|
||||||
bool GetLocal(CService &addr, const CNetAddr *paddrPeer = NULL);
|
bool GetLocal(CService &addr, const CNetAddr *paddrPeer = NULL);
|
||||||
|
/**
|
||||||
|
* Mark a network as reachable or unreachable (no automatic connects to it)
|
||||||
|
* @note Networks are reachable by default
|
||||||
|
*/
|
||||||
|
void SetReachable(enum Network net, bool reachable);
|
||||||
|
/** @returns true if the network is reachable, false otherwise */
|
||||||
bool IsReachable(enum Network net);
|
bool IsReachable(enum Network net);
|
||||||
bool IsReachable(const CNetAddr &addr);
|
/** @returns true if the address is in a reachable network, false otherwise */
|
||||||
|
bool IsReachable(const CNetAddr& addr);
|
||||||
CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL);
|
CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL);
|
||||||
|
|
||||||
|
|
||||||
@@ -190,12 +245,14 @@ extern CCriticalSection cs_vAddedNodes;
|
|||||||
extern NodeId nLastNodeId;
|
extern NodeId nLastNodeId;
|
||||||
extern CCriticalSection cs_nLastNodeId;
|
extern CCriticalSection cs_nLastNodeId;
|
||||||
|
|
||||||
/** Subversion as sent to the P2P network in `version` messages */
|
|
||||||
extern std::string strSubVersion;
|
|
||||||
|
|
||||||
extern SSL_CTX *tls_ctx_server;
|
extern SSL_CTX *tls_ctx_server;
|
||||||
extern SSL_CTX *tls_ctx_client;
|
extern SSL_CTX *tls_ctx_client;
|
||||||
|
|
||||||
|
extern std::unique_ptr<i2p::sam::Session> m_i2p_sam_session;
|
||||||
|
|
||||||
|
/** Subversion as sent to the P2P network in `version` messages */
|
||||||
|
extern std::string strSubVersion;
|
||||||
|
|
||||||
struct LocalServiceInfo {
|
struct LocalServiceInfo {
|
||||||
int nScore;
|
int nScore;
|
||||||
int nPort;
|
int nPort;
|
||||||
@@ -204,6 +261,8 @@ struct LocalServiceInfo {
|
|||||||
extern CCriticalSection cs_mapLocalHost;
|
extern CCriticalSection cs_mapLocalHost;
|
||||||
extern std::map<CNetAddr, LocalServiceInfo> mapLocalHost;
|
extern std::map<CNetAddr, LocalServiceInfo> mapLocalHost;
|
||||||
|
|
||||||
|
typedef std::map<std::string, uint64_t> mapMsgCmdSize; //command, total bytes
|
||||||
|
|
||||||
class CNodeStats
|
class CNodeStats
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -228,12 +287,19 @@ public:
|
|||||||
bool fFeeler; // If true this node is being used as a short lived feeler.
|
bool fFeeler; // If true this node is being used as a short lived feeler.
|
||||||
double dPingTime;
|
double dPingTime;
|
||||||
double dPingWait;
|
double dPingWait;
|
||||||
|
double dMinPing;
|
||||||
std::string addrLocal;
|
std::string addrLocal;
|
||||||
// Address of this peer
|
// Address of this peer
|
||||||
CAddress addr;
|
CAddress addr;
|
||||||
// Bind address of our side of the connection
|
// Bind address of our side of the connection
|
||||||
// CAddress addrBind; // https://github.com/bitcoin/bitcoin/commit/a7e3c2814c8e49197889a4679461be42254e5c51
|
// CAddress addrBind; // https://github.com/bitcoin/bitcoin/commit/a7e3c2814c8e49197889a4679461be42254e5c51
|
||||||
uint32_t m_mapped_as; // Mapped ASN for this address
|
uint32_t m_mapped_as;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the peer has signaled support for receiving ADDRv2 (BIP155)
|
||||||
|
* messages, implying a preference to receive ADDRv2 instead of ADDR ones.
|
||||||
|
*/
|
||||||
|
bool m_wants_addrv2;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -277,6 +343,22 @@ public:
|
|||||||
int readData(const char *pch, unsigned int nBytes);
|
int readData(const char *pch, unsigned int nBytes);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** The TransportSerializer prepares messages for the network transport
|
||||||
|
*/
|
||||||
|
class TransportSerializer {
|
||||||
|
public:
|
||||||
|
// prepare message for transport (header construction, error-correction computation, payload encryption, etc.)
|
||||||
|
virtual void prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) = 0;
|
||||||
|
virtual ~TransportSerializer() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class V1TransportSerializer : public TransportSerializer {
|
||||||
|
public:
|
||||||
|
void prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/** Information about a peer */
|
/** Information about a peer */
|
||||||
class CNode
|
class CNode
|
||||||
{
|
{
|
||||||
@@ -284,6 +366,8 @@ public:
|
|||||||
// TLS via WolfSSL
|
// TLS via WolfSSL
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
std::string tls_cipher;
|
std::string tls_cipher;
|
||||||
|
//Message Transport Serializer
|
||||||
|
std::unique_ptr<TransportSerializer> m_serializer;
|
||||||
|
|
||||||
// socket
|
// socket
|
||||||
uint64_t nServices;
|
uint64_t nServices;
|
||||||
@@ -342,12 +426,19 @@ public:
|
|||||||
CBloomFilter* pfilter;
|
CBloomFilter* pfilter;
|
||||||
int nRefCount;
|
int nRefCount;
|
||||||
NodeId id;
|
NodeId id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the peer has signaled support for receiving ADDRv2 (BIP155)
|
||||||
|
* messages, implying a preference to receive ADDRv2 instead of ADDR ones.
|
||||||
|
*/
|
||||||
|
bool m_wants_addrv2{false};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Denial-of-service detection/prevention
|
// Denial-of-service detection/prevention
|
||||||
// Key is IP address, value is banned-until-time
|
// Key is IP address, value is banned-until-time
|
||||||
static std::map<CSubNet, int64_t> setBanned;
|
// static std::map<CSubNet, int64_t> setBanned;
|
||||||
static CCriticalSection cs_setBanned;
|
// static CCriticalSection cs_setBanned;
|
||||||
|
|
||||||
// Allowlisted ranges. Any node connecting from these is automatically
|
// Allowlisted ranges. Any node connecting from these is automatically
|
||||||
// allowlisted (as well as those connecting to allowlisted binds).
|
// allowlisted (as well as those connecting to allowlisted binds).
|
||||||
@@ -393,6 +484,8 @@ public:
|
|||||||
int64_t nMinPingUsecTime;
|
int64_t nMinPingUsecTime;
|
||||||
// Whether a ping is requested.
|
// Whether a ping is requested.
|
||||||
bool fPingQueued;
|
bool fPingQueued;
|
||||||
|
// Times has ping been retried
|
||||||
|
int64_t nPingRetry;
|
||||||
|
|
||||||
CNode(SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false, SSL *sslIn = NULL);
|
CNode(SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false, SSL *sslIn = NULL);
|
||||||
~CNode();
|
~CNode();
|
||||||
@@ -407,6 +500,8 @@ private:
|
|||||||
CNode(const CNode&);
|
CNode(const CNode&);
|
||||||
void operator=(const CNode&);
|
void operator=(const CNode&);
|
||||||
|
|
||||||
|
mapMsgCmdSize mapSendBytesPerMsgCmd GUARDED_BY(cs_vSend);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
NodeId GetId() const {
|
NodeId GetId() const {
|
||||||
@@ -452,21 +547,26 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void AddAddressKnown(const CAddress& addr)
|
void AddAddressKnown(const CAddress& _addr)
|
||||||
{
|
{
|
||||||
addrKnown.insert(addr.GetKey());
|
addrKnown.insert(_addr.GetKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PushAddress(const CAddress& addr)
|
void PushAddress(const CAddress& _addr)
|
||||||
{
|
{
|
||||||
|
// Whether the peer supports the address in `_addr`. For example,
|
||||||
|
// nodes that do not implement BIP155 cannot receive Tor v3 addresses
|
||||||
|
// because they require ADDRv2 (BIP155) encoding.
|
||||||
|
const bool addr_format_supported = m_wants_addrv2 || _addr.IsAddrV1Compatible();
|
||||||
|
|
||||||
// Known checking here is only to save space from duplicates.
|
// Known checking here is only to save space from duplicates.
|
||||||
// SendMessages will filter it again for knowns that were added
|
// SendMessages will filter it again for knowns that were added
|
||||||
// after addresses were pushed.
|
// after addresses were pushed.
|
||||||
if (addr.IsValid() && !addrKnown.contains(addr.GetKey())) {
|
if (_addr.IsValid() && !addrKnown.contains(_addr.GetKey()) && addr_format_supported) {
|
||||||
if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) {
|
if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) {
|
||||||
vAddrToSend[insecure_rand() % vAddrToSend.size()] = addr;
|
vAddrToSend[insecure_rand() % vAddrToSend.size()] = _addr;
|
||||||
} else {
|
} else {
|
||||||
vAddrToSend.push_back(addr);
|
vAddrToSend.push_back(_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -500,6 +600,8 @@ public:
|
|||||||
// TODO: Document the precondition of this function. Is cs_vSend locked?
|
// TODO: Document the precondition of this function. Is cs_vSend locked?
|
||||||
void EndMessage() UNLOCK_FUNCTION(cs_vSend);
|
void EndMessage() UNLOCK_FUNCTION(cs_vSend);
|
||||||
|
|
||||||
|
void PushAddrMessage(CSerializedNetMsg&& msg);
|
||||||
|
|
||||||
void PushVersion();
|
void PushVersion();
|
||||||
|
|
||||||
|
|
||||||
@@ -682,8 +784,8 @@ public:
|
|||||||
static void ClearBanned(); // needed for unit testing
|
static void ClearBanned(); // needed for unit testing
|
||||||
static bool IsBanned(CNetAddr ip);
|
static bool IsBanned(CNetAddr ip);
|
||||||
static bool IsBanned(CSubNet subnet);
|
static bool IsBanned(CSubNet subnet);
|
||||||
static void Ban(const CNetAddr &ip, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
|
static void Ban(const CNetAddr &ip, const BanReason& reason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
|
||||||
static void Ban(const CSubNet &subNet, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
|
static void Ban(const CSubNet &subNet, const BanReason& reason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
|
||||||
static bool Unban(const CNetAddr &ip);
|
static bool Unban(const CNetAddr &ip);
|
||||||
static bool Unban(const CSubNet &ip);
|
static bool Unban(const CSubNet &ip);
|
||||||
static void GetBanned(std::map<CSubNet, int64_t> &banmap);
|
static void GetBanned(std::map<CSubNet, int64_t> &banmap);
|
||||||
|
|||||||
1222
src/netaddress.cpp
Normal file
1222
src/netaddress.cpp
Normal file
File diff suppressed because it is too large
Load Diff
534
src/netaddress.h
Normal file
534
src/netaddress.h
Normal file
@@ -0,0 +1,534 @@
|
|||||||
|
// Copyright (c) 2009-2015 The Bitcoin Core developers
|
||||||
|
// Copyright (c) 2016-2022 The Hush developers
|
||||||
|
// Distributed under the GPLv3 software license, see the accompanying
|
||||||
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
|
|
||||||
|
#ifndef HUSH_NETADDRESS_H
|
||||||
|
#define HUSH_NETADDRESS_H
|
||||||
|
|
||||||
|
#if defined(HAVE_CONFIG_H)
|
||||||
|
#include "config/bitcoin-config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "attributes.h"
|
||||||
|
#include "compat.h"
|
||||||
|
#include "prevector.h"
|
||||||
|
#include "serialize.h"
|
||||||
|
#include "tinyformat.h"
|
||||||
|
#include "util/strencodings.h"
|
||||||
|
#include "util/string.h"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <ios>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A flag that is ORed into the protocol version to designate that addresses
|
||||||
|
* should be serialized in (unserialized from) v2 format (BIP155).
|
||||||
|
* Make sure that this does not collide with any of the values in `version.h`
|
||||||
|
* or with `SERIALIZE_TRANSACTION_NO_WITNESS`.
|
||||||
|
*/
|
||||||
|
static const int ADDRV2_FORMAT = 0x20000000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A network type.
|
||||||
|
* @note An address may belong to more than one network, for example `10.0.0.1`
|
||||||
|
* belongs to both `NET_UNROUTABLE` and `NET_IPV4`.
|
||||||
|
* Keep these sequential starting from 0 and `NET_MAX` as the last entry.
|
||||||
|
* We have loops like `for (int i = 0; i < NET_MAX; i++)` that expect to iterate
|
||||||
|
* over all enum values and also `GetExtNetwork()` "extends" this enum by
|
||||||
|
* introducing standalone constants starting from `NET_MAX`.
|
||||||
|
*/
|
||||||
|
enum Network
|
||||||
|
{
|
||||||
|
/// Addresses from these networks are not publicly routable on the global Internet.
|
||||||
|
NET_UNROUTABLE = 0,
|
||||||
|
|
||||||
|
/// IPv4
|
||||||
|
NET_IPV4,
|
||||||
|
|
||||||
|
/// IPv6
|
||||||
|
NET_IPV6,
|
||||||
|
|
||||||
|
/// TOR (v2 or v3)
|
||||||
|
NET_ONION,
|
||||||
|
|
||||||
|
/// I2P
|
||||||
|
NET_I2P,
|
||||||
|
|
||||||
|
/// CJDNS
|
||||||
|
NET_CJDNS,
|
||||||
|
|
||||||
|
/// A set of addresses that represent the hash of a string or FQDN. We use
|
||||||
|
/// them in CAddrMan to keep track of which DNS seeds were used.
|
||||||
|
NET_INTERNAL,
|
||||||
|
|
||||||
|
/// Dummy value to indicate the number of NET_* constants.
|
||||||
|
NET_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Prefix of an IPv6 address when it contains an embedded IPv4 address.
|
||||||
|
/// Used when (un)serializing addresses in ADDRv1 format (pre-BIP155).
|
||||||
|
static const std::array<uint8_t, 12> IPV4_IN_IPV6_PREFIX{
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Prefix of an IPv6 address when it contains an embedded TORv2 address.
|
||||||
|
/// Used when (un)serializing addresses in ADDRv1 format (pre-BIP155).
|
||||||
|
/// Such dummy IPv6 addresses are guaranteed to not be publicly routable as they
|
||||||
|
/// fall under RFC4193's fc00::/7 subnet allocated to unique-local addresses.
|
||||||
|
static const std::array<uint8_t, 6> TORV2_IN_IPV6_PREFIX{
|
||||||
|
0xFD, 0x87, 0xD8, 0x7E, 0xEB, 0x43
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Prefix of an IPv6 address when it contains an embedded "internal" address.
|
||||||
|
/// Used when (un)serializing addresses in ADDRv1 format (pre-BIP155).
|
||||||
|
/// The prefix comes from 0xFD + SHA256("bitcoin")[0:5].
|
||||||
|
/// Such dummy IPv6 addresses are guaranteed to not be publicly routable as they
|
||||||
|
/// fall under RFC4193's fc00::/7 subnet allocated to unique-local addresses.
|
||||||
|
static const std::array<uint8_t, 6> INTERNAL_IN_IPV6_PREFIX{
|
||||||
|
0xFD, 0x6B, 0x88, 0xC0, 0x87, 0x24 // 0xFD + sha256("bitcoin")[0:5].
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Size of IPv4 address (in bytes).
|
||||||
|
static constexpr uint64_t ADDR_IPV4_SIZE = 4;
|
||||||
|
|
||||||
|
/// Size of IPv6 address (in bytes).
|
||||||
|
static constexpr uint64_t ADDR_IPV6_SIZE = 16;
|
||||||
|
|
||||||
|
/// Size of TORv2 address (in bytes).
|
||||||
|
static constexpr uint64_t ADDR_TORV2_SIZE = 10;
|
||||||
|
|
||||||
|
/// Size of TORv3 address (in bytes). This is the length of just the address
|
||||||
|
/// as used in BIP155, without the checksum and the version byte.
|
||||||
|
static constexpr uint64_t ADDR_TORV3_SIZE = 32;
|
||||||
|
|
||||||
|
/// Size of I2P address (in bytes).
|
||||||
|
static constexpr uint64_t ADDR_I2P_SIZE = 32;
|
||||||
|
|
||||||
|
/// Size of CJDNS address (in bytes).
|
||||||
|
static constexpr uint64_t ADDR_CJDNS_SIZE = 16;
|
||||||
|
|
||||||
|
/// Size of "internal" (NET_INTERNAL) address (in bytes).
|
||||||
|
static constexpr uint64_t ADDR_INTERNAL_SIZE = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Network address.
|
||||||
|
*/
|
||||||
|
class CNetAddr
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* Raw representation of the network address.
|
||||||
|
* In network byte order (big endian) for IPv4 and IPv6.
|
||||||
|
*/
|
||||||
|
prevector<ADDR_IPV6_SIZE, uint8_t> m_addr{ADDR_IPV6_SIZE, 0x0};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Network to which this address belongs.
|
||||||
|
*/
|
||||||
|
Network m_net{NET_IPV6};
|
||||||
|
|
||||||
|
uint32_t scopeId{0}; // for scoped/link-local ipv6 addresses
|
||||||
|
|
||||||
|
public:
|
||||||
|
CNetAddr();
|
||||||
|
explicit CNetAddr(const struct in_addr& ipv4Addr);
|
||||||
|
void SetIP(const CNetAddr& ip);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Set from a legacy IPv6 address.
|
||||||
|
* Legacy IPv6 address may be a normal IPv6 address, or another address
|
||||||
|
* (e.g. IPv4) disguised as IPv6. This encoding is used in the legacy
|
||||||
|
* `addr` encoding.
|
||||||
|
*/
|
||||||
|
void SetLegacyIPv6(Span<const uint8_t> ipv6);
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** check whether a given address is in a network we can probably connect to */
|
||||||
|
bool IsReachableNetwork();
|
||||||
|
bool SetInternal(const std::string& name);
|
||||||
|
|
||||||
|
bool SetSpecial(const std::string &strName); // for Tor addresses
|
||||||
|
|
||||||
|
bool IsBindAny() const; // INADDR_ANY equivalent
|
||||||
|
bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0)
|
||||||
|
bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor)
|
||||||
|
bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
|
||||||
|
bool IsRFC2544() const; // IPv4 inter-network communcations (192.18.0.0/15)
|
||||||
|
bool IsRFC6598() const; // IPv4 ISP-level NAT (100.64.0.0/10)
|
||||||
|
bool IsRFC5737() const; // IPv4 documentation addresses (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24)
|
||||||
|
bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32)
|
||||||
|
bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16)
|
||||||
|
bool IsRFC3964() const; // IPv6 6to4 tunnelling (2002::/16)
|
||||||
|
bool IsRFC4193() const; // IPv6 unique local (FC00::/7)
|
||||||
|
bool IsRFC4380() const; // IPv6 Teredo tunnelling (2001::/32)
|
||||||
|
bool IsRFC4843() const; // IPv6 ORCHID (deprecated) (2001:10::/28)
|
||||||
|
bool IsRFC7343() const; // IPv6 ORCHIDv2 (2001:20::/28)
|
||||||
|
bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64)
|
||||||
|
bool IsRFC6052() const; // IPv6 well-known prefix for IPv4-embedded address (64:FF9B::/96)
|
||||||
|
bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96) (actually defined in RFC2765)
|
||||||
|
bool IsHeNet() const; // IPv6 Hurricane Electric - https://he.net (2001:0470::/36)
|
||||||
|
bool IsTor() const;
|
||||||
|
bool IsI2P() const;
|
||||||
|
bool IsCJDNS() const;
|
||||||
|
bool IsLocal() const;
|
||||||
|
bool IsRoutable() const;
|
||||||
|
bool IsInternal() const;
|
||||||
|
bool IsValid() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
|
||||||
|
*/
|
||||||
|
bool IsAddrV1Compatible() const;
|
||||||
|
|
||||||
|
enum Network GetNetwork() const;
|
||||||
|
std::string ToString() const;
|
||||||
|
std::string ToStringIP() const;
|
||||||
|
uint64_t GetHash() const;
|
||||||
|
bool GetInAddr(struct in_addr* pipv4Addr) const;
|
||||||
|
uint32_t GetNetClass() const;
|
||||||
|
|
||||||
|
//! For IPv4, mapped IPv4, SIIT translated IPv4, Teredo, 6to4 tunneled addresses, return the relevant IPv4 address as a uint32.
|
||||||
|
uint32_t GetLinkedIPv4() const;
|
||||||
|
//! Whether this address has a linked IPv4 address (see GetLinkedIPv4()).
|
||||||
|
bool HasLinkedIPv4() const;
|
||||||
|
|
||||||
|
// The AS on the BGP path to the node we use to diversify
|
||||||
|
// peers in AddrMan bucketing based on the AS infrastructure.
|
||||||
|
// The ip->AS mapping depends on how asmap is constructed.
|
||||||
|
uint32_t GetMappedAS(const std::vector<bool> &asmap) const;
|
||||||
|
|
||||||
|
std::vector<unsigned char> GetGroup(const std::vector<bool> &asmap) const;
|
||||||
|
std::vector<unsigned char> GetAddrBytes() const;
|
||||||
|
int GetReachabilityFrom(const CNetAddr *paddrPartner = nullptr) const;
|
||||||
|
|
||||||
|
CNetAddr(const struct in6_addr& pipv6Addr, const uint32_t scope = 0);
|
||||||
|
bool GetIn6Addr(struct in6_addr* pipv6Addr) const;
|
||||||
|
|
||||||
|
friend bool operator==(const CNetAddr& a, const CNetAddr& b);
|
||||||
|
friend bool operator!=(const CNetAddr& a, const CNetAddr& b) { return !(a == b); }
|
||||||
|
friend bool operator<(const CNetAddr& a, const CNetAddr& b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize to a stream.
|
||||||
|
*/
|
||||||
|
template <typename Stream>
|
||||||
|
void Serialize(Stream& s) const
|
||||||
|
{
|
||||||
|
if (s.GetVersion() & ADDRV2_FORMAT) {
|
||||||
|
SerializeV2Stream(s);
|
||||||
|
} else {
|
||||||
|
SerializeV1Stream(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unserialize from a stream.
|
||||||
|
*/
|
||||||
|
template <typename Stream>
|
||||||
|
void Unserialize(Stream& s)
|
||||||
|
{
|
||||||
|
if (s.GetVersion() & ADDRV2_FORMAT) {
|
||||||
|
UnserializeV2Stream(s);
|
||||||
|
} else {
|
||||||
|
UnserializeV1Stream(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
friend class CSubNet;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Parse a Tor address and set this object to it.
|
||||||
|
* @param[in] addr Address to parse, must be a valid C string, for example
|
||||||
|
* pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion.
|
||||||
|
* @returns Whether the operation was successful.
|
||||||
|
* @see CNetAddr::IsTor()
|
||||||
|
*/
|
||||||
|
bool SetTor(const std::string& addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse an I2P address and set this object to it.
|
||||||
|
* @param[in] addr Address to parse, must be a valid C string, for example
|
||||||
|
* ukeu3k5oycgaauneqgtnvselmt4yemvoilkln7jpvamvfx7dnkdq.b32.i2p.
|
||||||
|
* @returns Whether the operation was successful.
|
||||||
|
* @see CNetAddr::IsI2P()
|
||||||
|
*/
|
||||||
|
bool SetI2P(const std::string& addr);
|
||||||
|
/**
|
||||||
|
* BIP155 network ids recognized by this software.
|
||||||
|
*/
|
||||||
|
enum BIP155Network : uint8_t {
|
||||||
|
IPV4 = 1,
|
||||||
|
IPV6 = 2,
|
||||||
|
TORV2 = 3,
|
||||||
|
TORV3 = 4,
|
||||||
|
I2P = 5,
|
||||||
|
CJDNS = 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of CNetAddr when serialized as ADDRv1 (pre-BIP155) (in bytes).
|
||||||
|
*/
|
||||||
|
static constexpr uint64_t V1_SERIALIZATION_SIZE = ADDR_IPV6_SIZE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum size of an address as defined in BIP155 (in bytes).
|
||||||
|
* This is only the size of the address, not the entire CNetAddr object
|
||||||
|
* when serialized.
|
||||||
|
*/
|
||||||
|
static constexpr uint64_t MAX_ADDRV2_SIZE = 512;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the BIP155 network id of this address.
|
||||||
|
* Must not be called for IsInternal() objects.
|
||||||
|
* @returns BIP155 network id
|
||||||
|
*/
|
||||||
|
BIP155Network GetBIP155Network() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set `m_net` from the provided BIP155 network id and size after validation.
|
||||||
|
* @retval true the network was recognized, is valid and `m_net` was set
|
||||||
|
* @retval false not recognised (from future?) and should be silently ignored
|
||||||
|
* @throws std::ios_base::failure if the network is one of the BIP155 founding
|
||||||
|
* networks (id 1..6) with wrong address size.
|
||||||
|
*/
|
||||||
|
bool SetNetFromBIP155Network(uint8_t possible_bip155_net, uint64_t address_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize in pre-ADDRv2/BIP155 format to an array.
|
||||||
|
*/
|
||||||
|
void SerializeV1Array(uint8_t (&arr)[V1_SERIALIZATION_SIZE]) const
|
||||||
|
{
|
||||||
|
uint64_t prefix_size;
|
||||||
|
|
||||||
|
switch (m_net) {
|
||||||
|
case NET_IPV6:
|
||||||
|
assert(m_addr.size() == sizeof(arr));
|
||||||
|
memcpy(arr, m_addr.data(), m_addr.size());
|
||||||
|
return;
|
||||||
|
case NET_IPV4:
|
||||||
|
prefix_size = sizeof(IPV4_IN_IPV6_PREFIX);
|
||||||
|
assert(prefix_size + m_addr.size() == sizeof(arr));
|
||||||
|
memcpy(arr, IPV4_IN_IPV6_PREFIX.data(), prefix_size);
|
||||||
|
memcpy(arr + prefix_size, m_addr.data(), m_addr.size());
|
||||||
|
return;
|
||||||
|
case NET_ONION:
|
||||||
|
if (m_addr.size() == ADDR_TORV3_SIZE) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
prefix_size = sizeof(TORV2_IN_IPV6_PREFIX);
|
||||||
|
assert(prefix_size + m_addr.size() == sizeof(arr));
|
||||||
|
memcpy(arr, TORV2_IN_IPV6_PREFIX.data(), prefix_size);
|
||||||
|
memcpy(arr + prefix_size, m_addr.data(), m_addr.size());
|
||||||
|
return;
|
||||||
|
case NET_INTERNAL:
|
||||||
|
prefix_size = sizeof(INTERNAL_IN_IPV6_PREFIX);
|
||||||
|
assert(prefix_size + m_addr.size() == sizeof(arr));
|
||||||
|
memcpy(arr, INTERNAL_IN_IPV6_PREFIX.data(), prefix_size);
|
||||||
|
memcpy(arr + prefix_size, m_addr.data(), m_addr.size());
|
||||||
|
return;
|
||||||
|
case NET_I2P:
|
||||||
|
break;
|
||||||
|
case NET_CJDNS:
|
||||||
|
break;
|
||||||
|
case NET_UNROUTABLE:
|
||||||
|
case NET_MAX:
|
||||||
|
assert(false);
|
||||||
|
} // no default case, so the compiler can warn about missing cases
|
||||||
|
|
||||||
|
// Serialize TORv3, I2P and CJDNS as all-zeros.
|
||||||
|
memset(arr, 0x0, V1_SERIALIZATION_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize in pre-ADDRv2/BIP155 format to a stream.
|
||||||
|
*/
|
||||||
|
template <typename Stream>
|
||||||
|
void SerializeV1Stream(Stream& s) const
|
||||||
|
{
|
||||||
|
uint8_t serialized[V1_SERIALIZATION_SIZE];
|
||||||
|
|
||||||
|
SerializeV1Array(serialized);
|
||||||
|
|
||||||
|
s << serialized;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serialize as ADDRv2 / BIP155.
|
||||||
|
*/
|
||||||
|
template <typename Stream>
|
||||||
|
void SerializeV2Stream(Stream& s) const
|
||||||
|
{
|
||||||
|
if (IsInternal()) {
|
||||||
|
// Serialize NET_INTERNAL as embedded in IPv6. We need to
|
||||||
|
// serialize such addresses from addrman.
|
||||||
|
s << static_cast<uint8_t>(BIP155Network::IPV6);
|
||||||
|
s << COMPACTSIZE(ADDR_IPV6_SIZE);
|
||||||
|
SerializeV1Stream(s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s << static_cast<uint8_t>(GetBIP155Network());
|
||||||
|
s << m_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unserialize from a pre-ADDRv2/BIP155 format from an array.
|
||||||
|
*/
|
||||||
|
void UnserializeV1Array(uint8_t (&arr)[V1_SERIALIZATION_SIZE])
|
||||||
|
{
|
||||||
|
// Use SetLegacyIPv6() so that m_net is set correctly. For example
|
||||||
|
// ::FFFF:0102:0304 should be set as m_net=NET_IPV4 (1.2.3.4).
|
||||||
|
SetLegacyIPv6(arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unserialize from a pre-ADDRv2/BIP155 format from a stream.
|
||||||
|
*/
|
||||||
|
template <typename Stream>
|
||||||
|
void UnserializeV1Stream(Stream& s)
|
||||||
|
{
|
||||||
|
uint8_t serialized[V1_SERIALIZATION_SIZE];
|
||||||
|
|
||||||
|
s >> serialized;
|
||||||
|
|
||||||
|
UnserializeV1Array(serialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unserialize from a ADDRv2 / BIP155 format.
|
||||||
|
*/
|
||||||
|
template <typename Stream>
|
||||||
|
void UnserializeV2Stream(Stream& s)
|
||||||
|
{
|
||||||
|
uint8_t bip155_net;
|
||||||
|
s >> bip155_net;
|
||||||
|
|
||||||
|
uint64_t address_size;
|
||||||
|
s >> COMPACTSIZE(address_size);
|
||||||
|
|
||||||
|
if (address_size > MAX_ADDRV2_SIZE) {
|
||||||
|
throw std::ios_base::failure(strprintf(
|
||||||
|
"Address too long: %u > %u", address_size, MAX_ADDRV2_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
scopeId = 0;
|
||||||
|
|
||||||
|
if (SetNetFromBIP155Network(bip155_net, address_size)) {
|
||||||
|
m_addr.resize(address_size);
|
||||||
|
s >> MakeSpan(m_addr);
|
||||||
|
|
||||||
|
if (m_net != NET_IPV6) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do some special checks on IPv6 addresses.
|
||||||
|
|
||||||
|
// Recognize NET_INTERNAL embedded in IPv6, such addresses are not
|
||||||
|
// gossiped but could be coming from addrman, when unserializing from
|
||||||
|
// disk.
|
||||||
|
if (HasPrefix(m_addr, INTERNAL_IN_IPV6_PREFIX)) {
|
||||||
|
m_net = NET_INTERNAL;
|
||||||
|
memmove(m_addr.data(), m_addr.data() + INTERNAL_IN_IPV6_PREFIX.size(),
|
||||||
|
ADDR_INTERNAL_SIZE);
|
||||||
|
m_addr.resize(ADDR_INTERNAL_SIZE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!HasPrefix(m_addr, IPV4_IN_IPV6_PREFIX) &&
|
||||||
|
!HasPrefix(m_addr, TORV2_IN_IPV6_PREFIX)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IPv4 and TORv2 are not supposed to be embedded in IPv6 (like in V1
|
||||||
|
// encoding). Unserialize as !IsValid(), thus ignoring them.
|
||||||
|
} else {
|
||||||
|
// If we receive an unknown BIP155 network id (from the future?) then
|
||||||
|
// ignore the address - unserialize as !IsValid().
|
||||||
|
s.ignore(address_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mimic a default-constructed CNetAddr object which is !IsValid() and thus
|
||||||
|
// will not be gossiped, but continue reading next addresses from the stream.
|
||||||
|
m_net = NET_IPV6;
|
||||||
|
m_addr.assign(ADDR_IPV6_SIZE, 0x0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CSubNet
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
/// Network (base) address
|
||||||
|
CNetAddr network;
|
||||||
|
/// Netmask, in network byte order
|
||||||
|
uint8_t netmask[16];
|
||||||
|
/// Is this value valid? (only used to signal parse errors)
|
||||||
|
bool valid;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CSubNet();
|
||||||
|
CSubNet(const CNetAddr& addr, uint8_t mask);
|
||||||
|
CSubNet(const CNetAddr& addr, const CNetAddr& mask);
|
||||||
|
|
||||||
|
//constructor for single ip subnet (<ipv4>/32 or <ipv6>/128)
|
||||||
|
explicit CSubNet(const CNetAddr& addr);
|
||||||
|
|
||||||
|
bool Match(const CNetAddr &addr) const;
|
||||||
|
|
||||||
|
std::string ToString() const;
|
||||||
|
bool IsValid() const;
|
||||||
|
|
||||||
|
friend bool operator==(const CSubNet& a, const CSubNet& b);
|
||||||
|
friend bool operator!=(const CSubNet& a, const CSubNet& b) { return !(a == b); }
|
||||||
|
friend bool operator<(const CSubNet& a, const CSubNet& b);
|
||||||
|
|
||||||
|
ADD_SERIALIZE_METHODS;
|
||||||
|
|
||||||
|
template <typename Stream, typename Operation>
|
||||||
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||||
|
READWRITE(network);
|
||||||
|
READWRITE(FLATDATA(netmask));
|
||||||
|
READWRITE(FLATDATA(valid));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** A combination of a network address (CNetAddr) and a (TCP) port */
|
||||||
|
class CService : public CNetAddr
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
unsigned short port; // host order
|
||||||
|
|
||||||
|
public:
|
||||||
|
CService();
|
||||||
|
CService(const CNetAddr& ip, unsigned short port);
|
||||||
|
CService(const struct in_addr& ipv4Addr, unsigned short port);
|
||||||
|
explicit CService(const struct sockaddr_in& addr);
|
||||||
|
unsigned short GetPort() const;
|
||||||
|
bool GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const;
|
||||||
|
bool SetSockAddr(const struct sockaddr* paddr);
|
||||||
|
friend bool operator==(const CService& a, const CService& b);
|
||||||
|
friend bool operator!=(const CService& a, const CService& b) { return !(a == b); }
|
||||||
|
friend bool operator<(const CService& a, const CService& b);
|
||||||
|
std::vector<unsigned char> GetKey() const;
|
||||||
|
std::string ToString() const;
|
||||||
|
std::string ToStringPort() const;
|
||||||
|
std::string ToStringIPPort() const;
|
||||||
|
|
||||||
|
CService(const struct in6_addr& ipv6Addr, unsigned short port);
|
||||||
|
CService(const struct sockaddr_in6& addr);
|
||||||
|
|
||||||
|
SERIALIZE_METHODS(CService, obj)
|
||||||
|
{
|
||||||
|
READWRITEAS(CNetAddr, obj);
|
||||||
|
READ_WRITE(Using<BigEndianFormatter<2>>(obj.port));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
bool SanityCheckASMap(const std::vector<bool>& asmap);
|
||||||
|
|
||||||
|
#endif // HUSH_NETADDRESS_H
|
||||||
1212
src/netbase.cpp
1212
src/netbase.cpp
File diff suppressed because it is too large
Load Diff
245
src/netbase.h
245
src/netbase.h
@@ -1,23 +1,8 @@
|
|||||||
|
// Copyright (c) 2009-2015 The Bitcoin Core developers
|
||||||
// Copyright (c) 2016-2022 The Hush developers
|
// Copyright (c) 2016-2022 The Hush developers
|
||||||
// Copyright (c) 2009-2013 The Bitcoin Core developers
|
|
||||||
// Distributed under the GPLv3 software license, see the accompanying
|
// Distributed under the GPLv3 software license, see the accompanying
|
||||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
|
||||||
* *
|
|
||||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
|
||||||
* the top-level directory of this distribution for the individual copyright *
|
|
||||||
* holder information and the developer policies on copyright and licensing. *
|
|
||||||
* *
|
|
||||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
|
||||||
* SuperNET software, including this file may be copied, modified, propagated *
|
|
||||||
* or distributed except according to the terms contained in the LICENSE file *
|
|
||||||
* *
|
|
||||||
* Removal or modification of this copyright notice is prohibited. *
|
|
||||||
* *
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#ifndef HUSH_NETBASE_H
|
#ifndef HUSH_NETBASE_H
|
||||||
#define HUSH_NETBASE_H
|
#define HUSH_NETBASE_H
|
||||||
|
|
||||||
@@ -26,8 +11,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
|
#include "netaddress.h"
|
||||||
#include "serialize.h"
|
#include "serialize.h"
|
||||||
#include "util/asmap.h"
|
#include "util/sock.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -36,177 +22,16 @@
|
|||||||
extern int nConnectTimeout;
|
extern int nConnectTimeout;
|
||||||
extern bool fNameLookup;
|
extern bool fNameLookup;
|
||||||
|
|
||||||
/** -timeout default */
|
//! -timeout default
|
||||||
static const int DEFAULT_CONNECT_TIMEOUT = 5000;
|
static const int DEFAULT_CONNECT_TIMEOUT = 60000;
|
||||||
|
//! -dns default
|
||||||
#ifdef _WIN32
|
static const int DEFAULT_NAME_LOOKUP = true;
|
||||||
// In MSVC, this is defined as a macro, undefine it to prevent a compile and link error
|
|
||||||
#undef SetPort
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum Network
|
|
||||||
{
|
|
||||||
NET_UNROUTABLE = 0,
|
|
||||||
NET_IPV4,
|
|
||||||
NET_IPV6,
|
|
||||||
NET_ONION,
|
|
||||||
NET_INTERNAL,
|
|
||||||
|
|
||||||
NET_MAX,
|
|
||||||
};
|
|
||||||
|
|
||||||
/** IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96)) */
|
|
||||||
class CNetAddr
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
unsigned char ip[16]; // in network byte order
|
|
||||||
|
|
||||||
public:
|
|
||||||
CNetAddr();
|
|
||||||
CNetAddr(const struct in_addr& ipv4Addr);
|
|
||||||
explicit CNetAddr(const char *pszIp, bool fAllowLookup = false);
|
|
||||||
explicit CNetAddr(const std::string &strIp, bool fAllowLookup = false);
|
|
||||||
void Init();
|
|
||||||
void SetIP(const CNetAddr& ip);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set raw IPv4 or IPv6 address (in network byte order)
|
|
||||||
* @note Only NET_IPV4 and NET_IPV6 are allowed for network.
|
|
||||||
*/
|
|
||||||
void SetRaw(Network network, const uint8_t *data);
|
|
||||||
|
|
||||||
bool SetSpecial(const std::string &strName); // for Tor addresses
|
|
||||||
bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0)
|
|
||||||
bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor)
|
|
||||||
bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12)
|
|
||||||
bool IsRFC2544() const; // IPv4 inter-network communications (192.18.0.0/15)
|
|
||||||
bool IsRFC6598() const; // IPv4 ISP-level NAT (100.64.0.0/10)
|
|
||||||
bool IsRFC5737() const; // IPv4 documentation addresses (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24)
|
|
||||||
bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32)
|
|
||||||
bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16)
|
|
||||||
bool IsRFC3964() const; // IPv6 6to4 tunnelling (2002::/16)
|
|
||||||
bool IsRFC4193() const; // IPv6 unique local (FC00::/7)
|
|
||||||
bool IsRFC4380() const; // IPv6 Teredo tunnelling (2001::/32)
|
|
||||||
bool IsRFC4843() const; // IPv6 ORCHID (2001:10::/28)
|
|
||||||
bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64)
|
|
||||||
bool IsRFC6052() const; // IPv6 well-known prefix (64:FF9B::/96)
|
|
||||||
bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96)
|
|
||||||
bool IsTor() const;
|
|
||||||
bool IsLocal() const;
|
|
||||||
bool IsRoutable() const;
|
|
||||||
bool IsInternal() const;
|
|
||||||
bool IsValid() const;
|
|
||||||
bool IsMulticast() const;
|
|
||||||
enum Network GetNetwork() const;
|
|
||||||
std::string ToString() const;
|
|
||||||
std::string ToStringIP() const;
|
|
||||||
unsigned int GetByte(int n) const;
|
|
||||||
uint64_t GetHash() const;
|
|
||||||
bool GetInAddr(struct in_addr* pipv4Addr) const;
|
|
||||||
uint32_t GetNetClass() const;
|
|
||||||
|
|
||||||
//! For IPv4, mapped IPv4, SIIT translated IPv4, Teredo, 6to4 tunneled addresses, return the relevant IPv4 address as a uint32.
|
|
||||||
uint32_t GetLinkedIPv4() const;
|
|
||||||
//! Whether this address has a linked IPv4 address (see GetLinkedIPv4()).
|
|
||||||
bool HasLinkedIPv4() const;
|
|
||||||
|
|
||||||
// The AS on the BGP path to the node we use to diversify
|
|
||||||
// peers in AddrMan bucketing based on the AS infrastructure.
|
|
||||||
// The ip->AS mapping depends on how asmap is constructed.
|
|
||||||
uint32_t GetMappedAS(const std::vector<bool> &asmap) const;
|
|
||||||
|
|
||||||
std::vector<unsigned char> GetGroup(const std::vector<bool> &asmap) const;
|
|
||||||
int GetReachabilityFrom(const CNetAddr *paddrPartner = NULL) const;
|
|
||||||
|
|
||||||
CNetAddr(const struct in6_addr& pipv6Addr);
|
|
||||||
bool GetIn6Addr(struct in6_addr* pipv6Addr) const;
|
|
||||||
|
|
||||||
friend bool operator==(const CNetAddr& a, const CNetAddr& b);
|
|
||||||
friend bool operator!=(const CNetAddr& a, const CNetAddr& b);
|
|
||||||
friend bool operator<(const CNetAddr& a, const CNetAddr& b);
|
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
|
||||||
|
|
||||||
template <typename Stream, typename Operation>
|
|
||||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
||||||
READWRITE(FLATDATA(ip));
|
|
||||||
}
|
|
||||||
|
|
||||||
friend class CSubNet;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CSubNet
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
/// Network (base) address
|
|
||||||
CNetAddr network;
|
|
||||||
/// Netmask, in network byte order
|
|
||||||
uint8_t netmask[16];
|
|
||||||
/// Is this value valid? (only used to signal parse errors)
|
|
||||||
bool valid;
|
|
||||||
|
|
||||||
public:
|
|
||||||
CSubNet();
|
|
||||||
explicit CSubNet(const std::string &strSubnet, bool fAllowLookup = false);
|
|
||||||
|
|
||||||
bool Match(const CNetAddr &addr) const;
|
|
||||||
|
|
||||||
std::string ToString() const;
|
|
||||||
bool IsValid() const;
|
|
||||||
|
|
||||||
friend bool operator==(const CSubNet& a, const CSubNet& b);
|
|
||||||
friend bool operator!=(const CSubNet& a, const CSubNet& b);
|
|
||||||
friend bool operator<(const CSubNet& a, const CSubNet& b);
|
|
||||||
};
|
|
||||||
|
|
||||||
/** A combination of a network address (CNetAddr) and a (TCP) port */
|
|
||||||
class CService : public CNetAddr
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
unsigned short port; // host order
|
|
||||||
|
|
||||||
public:
|
|
||||||
CService();
|
|
||||||
CService(const CNetAddr& ip, unsigned short port);
|
|
||||||
CService(const struct in_addr& ipv4Addr, unsigned short port);
|
|
||||||
CService(const struct sockaddr_in& addr);
|
|
||||||
explicit CService(const char *pszIpPort, int portDefault, bool fAllowLookup = false);
|
|
||||||
explicit CService(const char *pszIpPort, bool fAllowLookup = false);
|
|
||||||
explicit CService(const std::string& strIpPort, int portDefault, bool fAllowLookup = false);
|
|
||||||
explicit CService(const std::string& strIpPort, bool fAllowLookup = false);
|
|
||||||
void Init();
|
|
||||||
void SetPort(unsigned short portIn);
|
|
||||||
unsigned short GetPort() const;
|
|
||||||
bool GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const;
|
|
||||||
bool SetSockAddr(const struct sockaddr* paddr);
|
|
||||||
friend bool operator==(const CService& a, const CService& b);
|
|
||||||
friend bool operator!=(const CService& a, const CService& b);
|
|
||||||
friend bool operator<(const CService& a, const CService& b);
|
|
||||||
std::vector<unsigned char> GetKey() const;
|
|
||||||
std::string ToString() const;
|
|
||||||
std::string ToStringPort() const;
|
|
||||||
std::string ToStringIPPort() const;
|
|
||||||
|
|
||||||
CService(const struct in6_addr& ipv6Addr, unsigned short port);
|
|
||||||
CService(const struct sockaddr_in6& addr);
|
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
|
||||||
|
|
||||||
template <typename Stream, typename Operation>
|
|
||||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
||||||
READWRITE(FLATDATA(ip));
|
|
||||||
unsigned short portN = htons(port);
|
|
||||||
READWRITE(FLATDATA(portN));
|
|
||||||
if (ser_action.ForRead())
|
|
||||||
port = ntohs(portN);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class proxyType
|
class proxyType
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
proxyType(): randomize_credentials(false) {}
|
proxyType(): randomize_credentials(false) {}
|
||||||
proxyType(const CService &proxy, bool randomize_credentials=false): proxy(proxy), randomize_credentials(randomize_credentials) {}
|
proxyType(const CService &_proxy, bool _randomize_credentials=false): proxy(_proxy), randomize_credentials(_randomize_credentials) {}
|
||||||
|
|
||||||
bool IsValid() const { return proxy.IsValid(); }
|
bool IsValid() const { return proxy.IsValid(); }
|
||||||
|
|
||||||
@@ -216,29 +41,51 @@ public:
|
|||||||
|
|
||||||
enum Network ParseNetwork(std::string net);
|
enum Network ParseNetwork(std::string net);
|
||||||
std::string GetNetworkName(enum Network net);
|
std::string GetNetworkName(enum Network net);
|
||||||
void SplitHostPort(std::string in, int &portOut, std::string &hostOut);
|
|
||||||
bool SetProxy(enum Network net, const proxyType &addrProxy);
|
bool SetProxy(enum Network net, const proxyType &addrProxy);
|
||||||
bool GetProxy(enum Network net, proxyType &proxyInfoOut);
|
bool GetProxy(enum Network net, proxyType &proxyInfoOut);
|
||||||
bool IsProxy(const CNetAddr &addr);
|
bool IsProxy(const CNetAddr &addr);
|
||||||
bool SetNameProxy(const proxyType &addrProxy);
|
bool SetNameProxy(const proxyType &addrProxy);
|
||||||
bool HaveNameProxy();
|
bool HaveNameProxy();
|
||||||
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions = 0, bool fAllowLookup = true);
|
bool LookupHost(const char *pszName, std::vector<CNetAddr>& vIP, unsigned int nMaxSolutions, bool fAllowLookup);
|
||||||
bool Lookup(const char *pszName, CService& addr, int portDefault = 0, bool fAllowLookup = true);
|
bool LookupHost(const char *pszName, CNetAddr& addr, bool fAllowLookup);
|
||||||
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault = 0, bool fAllowLookup = true, unsigned int nMaxSolutions = 0);
|
bool Lookup(const char *pszName, CService& addr, int portDefault, bool fAllowLookup);
|
||||||
bool LookupNumeric(const char *pszName, CService& addr, int portDefault = 0);
|
bool Lookup(const char *pszName, std::vector<CService>& vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions);
|
||||||
|
CService LookupNumeric(const char *pszName, int portDefault = 0);
|
||||||
|
bool LookupSubNet(const char *pszName, CSubNet& subnet);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a TCP socket in the given address family.
|
||||||
|
* @param[in] address_family The socket is created in the same address family as this address.
|
||||||
|
* @return pointer to the created Sock object or unique_ptr that owns nothing in case of failure
|
||||||
|
*/
|
||||||
|
std::unique_ptr<Sock> CreateSockTCP(const CService& address_family);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Socket factory. Defaults to `CreateSockTCP()`, but can be overridden by unit tests.
|
||||||
|
*/
|
||||||
|
extern std::function<std::unique_ptr<Sock>(const CService&)> CreateSock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to connect to the specified service on the specified socket.
|
||||||
|
*
|
||||||
|
* @param addrConnect The service to which to connect.
|
||||||
|
* @param sock The socket on which to connect.
|
||||||
|
* @param nTimeout Wait this many milliseconds for the connection to be
|
||||||
|
* established.
|
||||||
|
* @param manual_connection Whether or not the connection was manually requested
|
||||||
|
* (e.g. through the addnode RPC)
|
||||||
|
*
|
||||||
|
* @returns Whether or not a connection was successfully made.
|
||||||
|
*/
|
||||||
|
bool ConnectSocketDirectly(const CService &addrConnect, const Sock& sock, int nTimeout);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed = 0);
|
bool ConnectSocket(const CService &addr, SOCKET& hSocketRet, int nTimeout, bool *outProxyConnectionFailed = 0);
|
||||||
bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed = 0);
|
bool ConnectSocketByName(CService &addr, SOCKET& hSocketRet, const char *pszDest, int portDefault, int nTimeout, bool *outProxyConnectionFailed = 0);
|
||||||
/** Return readable error string for a network error code */
|
|
||||||
std::string NetworkErrorString(int err);
|
|
||||||
/** Close socket and set hSocket to INVALID_SOCKET */
|
|
||||||
bool CloseSocket(SOCKET& hSocket);
|
|
||||||
/** Disable or enable blocking-mode for a socket */
|
|
||||||
bool SetSocketNonBlocking(SOCKET& hSocket, bool fNonBlocking);
|
|
||||||
/**
|
|
||||||
* Convert milliseconds to a struct timeval for e.g. select.
|
|
||||||
*/
|
|
||||||
struct timeval MillisToTimeval(int64_t nTimeout);
|
|
||||||
|
|
||||||
bool SanityCheckASMap(const std::vector<bool>& asmap);
|
bool SetSocketNonBlocking(SOCKET& hSocket, bool fNonBlocking);
|
||||||
|
/** Set the TCP_NODELAY flag on a socket */
|
||||||
|
bool SetSocketNoDelay(const SOCKET& hSocket);
|
||||||
|
|
||||||
#endif // HUSH_NETBASE_H
|
#endif // HUSH_NETBASE_H
|
||||||
|
|||||||
37
src/netmessagemaker.h
Normal file
37
src/netmessagemaker.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
|
// Copyright (c) 2009-2020 The Bitcoin Core developers
|
||||||
|
// Copyright (c) 2016-2022 The Hush developers
|
||||||
|
// Distributed under the GPLv3 software license, see the accompanying
|
||||||
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
|
|
||||||
|
#ifndef HUSH_NETMESSAGEMAKER_H
|
||||||
|
#define HUSH_NETMESSAGEMAKER_H
|
||||||
|
|
||||||
|
#include <net.h>
|
||||||
|
#include <serialize.h>
|
||||||
|
|
||||||
|
class CNetMsgMaker
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit CNetMsgMaker(int nVersionIn) : nVersion(nVersionIn){}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
CSerializedNetMsg Make(int nFlags, std::string msg_type, Args&&... args) const
|
||||||
|
{
|
||||||
|
CSerializedNetMsg msg;
|
||||||
|
msg.m_type = std::move(msg_type);
|
||||||
|
CVectorWriter{ SER_NETWORK, nFlags | nVersion, msg.data, 0, std::forward<Args>(args)... };
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
CSerializedNetMsg Make(std::string msg_type, Args&&... args) const
|
||||||
|
{
|
||||||
|
return Make(0, std::move(msg_type), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const int nVersion;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HUSH_NETMESSAGEMAKER_H
|
||||||
11
src/pow.cpp
11
src/pow.cpp
@@ -509,8 +509,9 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Changing this requires changing many other things and
|
// Changing this requires changing many other things and
|
||||||
// changes consensus. Have fun -- Duke
|
// might change consensus. Have fun -- Duke
|
||||||
int64_t AveragingWindowTimespan(int32_t height) {
|
// NOTE: Ony HUSH3 mainnet should use this function, all HSC's should use params.AveragigWindowTimespan()
|
||||||
|
int64_t AveragingWindowTimespan() {
|
||||||
// used in const methods, beware!
|
// used in const methods, beware!
|
||||||
// This is the correct AWT for 75s blocktime, before block 340k
|
// This is the correct AWT for 75s blocktime, before block 340k
|
||||||
// the correct value was 2550 when the blocktime was 150s
|
// the correct value was 2550 when the blocktime was 150s
|
||||||
@@ -526,7 +527,11 @@ unsigned int CalculateNextWorkRequired(arith_uint256 bnAvg,
|
|||||||
// Limit adjustment step and use medians to prevent time-warp attacks
|
// Limit adjustment step and use medians to prevent time-warp attacks
|
||||||
int64_t nActualTimespan = nLastBlockTime - nFirstBlockTime;
|
int64_t nActualTimespan = nLastBlockTime - nFirstBlockTime;
|
||||||
LogPrint("pow", " nActualTimespan = %d before dampening\n", nActualTimespan);
|
LogPrint("pow", " nActualTimespan = %d before dampening\n", nActualTimespan);
|
||||||
int64_t AWT = AveragingWindowTimespan(height) ;
|
|
||||||
|
bool ishush3 = strncmp(SMART_CHAIN_SYMBOL, "HUSH3",5) == 0 ? true : false;
|
||||||
|
// If this is HUSH3, use AWT function defined above, else use the one in params
|
||||||
|
int64_t AWT = ishush3 ? AveragingWindowTimespan() : params.AveragingWindowTimespan();
|
||||||
|
|
||||||
nActualTimespan = AWT + (nActualTimespan - AWT)/4;
|
nActualTimespan = AWT + (nActualTimespan - AWT)/4;
|
||||||
LogPrint("pow", " nActualTimespan = %d before bounds\n", nActualTimespan);
|
LogPrint("pow", " nActualTimespan = %d before bounds\n", nActualTimespan);
|
||||||
|
|
||||||
|
|||||||
245
src/prevector.h
245
src/prevector.h
@@ -1,17 +1,21 @@
|
|||||||
|
// Copyright (c) 2015-2020 The Bitcoin Core developers
|
||||||
// Copyright (c) 2016-2022 The Hush developers
|
// Copyright (c) 2016-2022 The Hush developers
|
||||||
// Distributed under the GPLv3 software license, see the accompanying
|
// Distributed under the GPLv3 software license, see the accompanying
|
||||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
#ifndef _HUSH_PREVECTOR_H_
|
|
||||||
#define _HUSH_PREVECTOR_H_
|
|
||||||
|
|
||||||
#include <util.h>
|
#ifndef HUSH_PREVECTOR_H
|
||||||
|
#define HUSH_PREVECTOR_H
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <iterator>
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#include <algorithm>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
/** Implements a drop-in replacement for std::vector<T> which stores up to N
|
/** Implements a drop-in replacement for std::vector<T> which stores up to N
|
||||||
* elements directly (without heap allocation). The types Size and Diff are
|
* elements directly (without heap allocation). The types Size and Diff are
|
||||||
* used to store element counts, and can be any unsigned + signed type.
|
* used to store element counts, and can be any unsigned + signed type.
|
||||||
@@ -130,7 +134,7 @@ public:
|
|||||||
typedef const T* pointer;
|
typedef const T* pointer;
|
||||||
typedef const T& reference;
|
typedef const T& reference;
|
||||||
typedef std::bidirectional_iterator_tag iterator_category;
|
typedef std::bidirectional_iterator_tag iterator_category;
|
||||||
const_reverse_iterator(T* ptr_) : ptr(ptr_) {}
|
const_reverse_iterator(const T* ptr_) : ptr(ptr_) {}
|
||||||
const_reverse_iterator(reverse_iterator x) : ptr(&(*x)) {}
|
const_reverse_iterator(reverse_iterator x) : ptr(&(*x)) {}
|
||||||
const T& operator*() const { return *ptr; }
|
const T& operator*() const { return *ptr; }
|
||||||
const T* operator->() const { return ptr; }
|
const T* operator->() const { return ptr; }
|
||||||
@@ -143,19 +147,25 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_type _size;
|
#pragma pack(push, 1)
|
||||||
union {
|
union direct_or_indirect {
|
||||||
char direct[sizeof(T) * N];
|
char direct[sizeof(T) * N];
|
||||||
struct {
|
struct {
|
||||||
size_type capacity;
|
|
||||||
char* indirect;
|
char* indirect;
|
||||||
};
|
size_type capacity;
|
||||||
} _union;
|
} indirect_contents;
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
alignas(char*) direct_or_indirect _union = {};
|
||||||
|
size_type _size = 0;
|
||||||
|
|
||||||
|
static_assert(alignof(char*) % alignof(size_type) == 0 && sizeof(char*) % alignof(size_type) == 0, "size_type cannot have more restrictive alignment requirement than pointer");
|
||||||
|
static_assert(alignof(char*) % alignof(T) == 0, "value_type T cannot have more restrictive alignment requirement than pointer");
|
||||||
|
|
||||||
T* direct_ptr(difference_type pos) { return reinterpret_cast<T*>(_union.direct) + pos; }
|
T* direct_ptr(difference_type pos) { return reinterpret_cast<T*>(_union.direct) + pos; }
|
||||||
const T* direct_ptr(difference_type pos) const { return reinterpret_cast<const T*>(_union.direct) + pos; }
|
const T* direct_ptr(difference_type pos) const { return reinterpret_cast<const T*>(_union.direct) + pos; }
|
||||||
T* indirect_ptr(difference_type pos) { return reinterpret_cast<T*>(_union.indirect) + pos; }
|
T* indirect_ptr(difference_type pos) { return reinterpret_cast<T*>(_union.indirect_contents.indirect) + pos; }
|
||||||
const T* indirect_ptr(difference_type pos) const { return reinterpret_cast<const T*>(_union.indirect) + pos; }
|
const T* indirect_ptr(difference_type pos) const { return reinterpret_cast<const T*>(_union.indirect_contents.indirect) + pos; }
|
||||||
bool is_direct() const { return _size <= N; }
|
bool is_direct() const { return _size <= N; }
|
||||||
|
|
||||||
void change_capacity(size_type new_capacity) {
|
void change_capacity(size_type new_capacity) {
|
||||||
@@ -173,17 +183,17 @@ private:
|
|||||||
/* FIXME: Because malloc/realloc here won't call new_handler if allocation fails, assert
|
/* FIXME: Because malloc/realloc here won't call new_handler if allocation fails, assert
|
||||||
success. These should instead use an allocator or new/delete so that handlers
|
success. These should instead use an allocator or new/delete so that handlers
|
||||||
are called as necessary, but performance would be slightly degraded by doing so. */
|
are called as necessary, but performance would be slightly degraded by doing so. */
|
||||||
_union.indirect = static_cast<char*>(realloc(_union.indirect, ((size_t)sizeof(T)) * new_capacity));
|
_union.indirect_contents.indirect = static_cast<char*>(realloc(_union.indirect_contents.indirect, ((size_t)sizeof(T)) * new_capacity));
|
||||||
if (!_union.indirect) { new_handler_terminate(); }
|
assert(_union.indirect_contents.indirect);
|
||||||
_union.capacity = new_capacity;
|
_union.indirect_contents.capacity = new_capacity;
|
||||||
} else {
|
} else {
|
||||||
char* new_indirect = static_cast<char*>(malloc(((size_t)sizeof(T)) * new_capacity));
|
char* new_indirect = static_cast<char*>(malloc(((size_t)sizeof(T)) * new_capacity));
|
||||||
if (!new_indirect) { new_handler_terminate(); }
|
assert(new_indirect);
|
||||||
T* src = direct_ptr(0);
|
T* src = direct_ptr(0);
|
||||||
T* dst = reinterpret_cast<T*>(new_indirect);
|
T* dst = reinterpret_cast<T*>(new_indirect);
|
||||||
memcpy(dst, src, size() * sizeof(T));
|
memcpy(dst, src, size() * sizeof(T));
|
||||||
_union.indirect = new_indirect;
|
_union.indirect_contents.indirect = new_indirect;
|
||||||
_union.capacity = new_capacity;
|
_union.indirect_contents.capacity = new_capacity;
|
||||||
_size += N + 1;
|
_size += N + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -192,16 +202,27 @@ private:
|
|||||||
T* item_ptr(difference_type pos) { return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); }
|
T* item_ptr(difference_type pos) { return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); }
|
||||||
const T* item_ptr(difference_type pos) const { return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); }
|
const T* item_ptr(difference_type pos) const { return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); }
|
||||||
|
|
||||||
|
void fill(T* dst, ptrdiff_t count, const T& value = T{}) {
|
||||||
|
std::fill_n(dst, count, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename InputIterator>
|
||||||
|
void fill(T* dst, InputIterator first, InputIterator last) {
|
||||||
|
while (first != last) {
|
||||||
|
new(static_cast<void*>(dst)) T(*first);
|
||||||
|
++dst;
|
||||||
|
++first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void assign(size_type n, const T& val) {
|
void assign(size_type n, const T& val) {
|
||||||
clear();
|
clear();
|
||||||
if (capacity() < n) {
|
if (capacity() < n) {
|
||||||
change_capacity(n);
|
change_capacity(n);
|
||||||
}
|
}
|
||||||
while (size() < n) {
|
_size += n;
|
||||||
_size++;
|
fill(item_ptr(0), n, val);
|
||||||
new(static_cast<void*>(item_ptr(size() - 1))) T(val);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename InputIterator>
|
template<typename InputIterator>
|
||||||
@@ -211,60 +232,51 @@ public:
|
|||||||
if (capacity() < n) {
|
if (capacity() < n) {
|
||||||
change_capacity(n);
|
change_capacity(n);
|
||||||
}
|
}
|
||||||
while (first != last) {
|
_size += n;
|
||||||
_size++;
|
fill(item_ptr(0), first, last);
|
||||||
new(static_cast<void*>(item_ptr(size() - 1))) T(*first);
|
|
||||||
++first;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prevector() : _size(0) {}
|
prevector() {}
|
||||||
|
|
||||||
explicit prevector(size_type n) : _size(0) {
|
explicit prevector(size_type n) {
|
||||||
resize(n);
|
resize(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit prevector(size_type n, const T& val = T()) : _size(0) {
|
explicit prevector(size_type n, const T& val) {
|
||||||
change_capacity(n);
|
change_capacity(n);
|
||||||
while (size() < n) {
|
_size += n;
|
||||||
_size++;
|
fill(item_ptr(0), n, val);
|
||||||
new(static_cast<void*>(item_ptr(size() - 1))) T(val);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename InputIterator>
|
template<typename InputIterator>
|
||||||
prevector(InputIterator first, InputIterator last) : _size(0) {
|
prevector(InputIterator first, InputIterator last) {
|
||||||
size_type n = last - first;
|
size_type n = last - first;
|
||||||
change_capacity(n);
|
change_capacity(n);
|
||||||
while (first != last) {
|
_size += n;
|
||||||
_size++;
|
fill(item_ptr(0), first, last);
|
||||||
new(static_cast<void*>(item_ptr(size() - 1))) T(*first);
|
|
||||||
++first;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prevector(const prevector<N, T, Size, Diff>& other) : _size(0) {
|
prevector(const prevector<N, T, Size, Diff>& other) {
|
||||||
change_capacity(other.size());
|
size_type n = other.size();
|
||||||
const_iterator it = other.begin();
|
change_capacity(n);
|
||||||
while (it != other.end()) {
|
_size += n;
|
||||||
_size++;
|
fill(item_ptr(0), other.begin(), other.end());
|
||||||
new(static_cast<void*>(item_ptr(size() - 1))) T(*it);
|
}
|
||||||
++it;
|
|
||||||
}
|
prevector(prevector<N, T, Size, Diff>&& other) {
|
||||||
|
swap(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
prevector& operator=(const prevector<N, T, Size, Diff>& other) {
|
prevector& operator=(const prevector<N, T, Size, Diff>& other) {
|
||||||
if (&other == this) {
|
if (&other == this) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
resize(0);
|
assign(other.begin(), other.end());
|
||||||
change_capacity(other.size());
|
return *this;
|
||||||
const_iterator it = other.begin();
|
}
|
||||||
while (it != other.end()) {
|
|
||||||
_size++;
|
prevector& operator=(prevector<N, T, Size, Diff>&& other) {
|
||||||
new(static_cast<void*>(item_ptr(size() - 1))) T(*it);
|
swap(other);
|
||||||
++it;
|
|
||||||
}
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,7 +302,7 @@ public:
|
|||||||
if (is_direct()) {
|
if (is_direct()) {
|
||||||
return N;
|
return N;
|
||||||
} else {
|
} else {
|
||||||
return _union.capacity;
|
return _union.indirect_contents.capacity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,17 +315,20 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void resize(size_type new_size) {
|
void resize(size_type new_size) {
|
||||||
while (size() > new_size) {
|
size_type cur_size = size();
|
||||||
item_ptr(size() - 1)->~T();
|
if (cur_size == new_size) {
|
||||||
_size--;
|
return;
|
||||||
|
}
|
||||||
|
if (cur_size > new_size) {
|
||||||
|
erase(item_ptr(new_size), end());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (new_size > capacity()) {
|
if (new_size > capacity()) {
|
||||||
change_capacity(new_size);
|
change_capacity(new_size);
|
||||||
}
|
}
|
||||||
while (size() < new_size) {
|
ptrdiff_t increase = new_size - cur_size;
|
||||||
_size++;
|
fill(item_ptr(cur_size), increase);
|
||||||
new(static_cast<void*>(item_ptr(size() - 1))) T();
|
_size += increase;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void reserve(size_type new_capacity) {
|
void reserve(size_type new_capacity) {
|
||||||
@@ -336,10 +351,11 @@ public:
|
|||||||
if (capacity() < new_size) {
|
if (capacity() < new_size) {
|
||||||
change_capacity(new_size + (new_size >> 1));
|
change_capacity(new_size + (new_size >> 1));
|
||||||
}
|
}
|
||||||
memmove(item_ptr(p + 1), item_ptr(p), (size() - p) * sizeof(T));
|
T* ptr = item_ptr(p);
|
||||||
|
memmove(ptr + 1, ptr, (size() - p) * sizeof(T));
|
||||||
_size++;
|
_size++;
|
||||||
new(static_cast<void*>(item_ptr(p))) T(value);
|
new(static_cast<void*>(ptr)) T(value);
|
||||||
return iterator(item_ptr(p));
|
return iterator(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void insert(iterator pos, size_type count, const T& value) {
|
void insert(iterator pos, size_type count, const T& value) {
|
||||||
@@ -348,11 +364,10 @@ public:
|
|||||||
if (capacity() < new_size) {
|
if (capacity() < new_size) {
|
||||||
change_capacity(new_size + (new_size >> 1));
|
change_capacity(new_size + (new_size >> 1));
|
||||||
}
|
}
|
||||||
memmove(item_ptr(p + count), item_ptr(p), (size() - p) * sizeof(T));
|
T* ptr = item_ptr(p);
|
||||||
|
memmove(ptr + count, ptr, (size() - p) * sizeof(T));
|
||||||
_size += count;
|
_size += count;
|
||||||
for (size_type i = 0; i < count; i++) {
|
fill(item_ptr(p), count, value);
|
||||||
new(static_cast<void*>(item_ptr(p + i))) T(value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename InputIterator>
|
template<typename InputIterator>
|
||||||
@@ -363,45 +378,69 @@ public:
|
|||||||
if (capacity() < new_size) {
|
if (capacity() < new_size) {
|
||||||
change_capacity(new_size + (new_size >> 1));
|
change_capacity(new_size + (new_size >> 1));
|
||||||
}
|
}
|
||||||
memmove(item_ptr(p + count), item_ptr(p), (size() - p) * sizeof(T));
|
T* ptr = item_ptr(p);
|
||||||
|
memmove(ptr + count, ptr, (size() - p) * sizeof(T));
|
||||||
_size += count;
|
_size += count;
|
||||||
while (first != last) {
|
fill(ptr, first, last);
|
||||||
new(static_cast<void*>(item_ptr(p))) T(*first);
|
}
|
||||||
++p;
|
|
||||||
++first;
|
inline void resize_uninitialized(size_type new_size) {
|
||||||
|
// resize_uninitialized changes the size of the prevector but does not initialize it.
|
||||||
|
// If size < new_size, the added elements must be initialized explicitly.
|
||||||
|
if (capacity() < new_size) {
|
||||||
|
change_capacity(new_size);
|
||||||
|
_size += new_size - size();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (new_size < size()) {
|
||||||
|
erase(item_ptr(new_size), end());
|
||||||
|
} else {
|
||||||
|
_size += new_size - size();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator erase(iterator pos) {
|
iterator erase(iterator pos) {
|
||||||
(*pos).~T();
|
return erase(pos, pos + 1);
|
||||||
memmove(&(*pos), &(*pos) + 1, ((char*)&(*end())) - ((char*)(1 + &(*pos))));
|
|
||||||
_size--;
|
|
||||||
return pos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator erase(iterator first, iterator last) {
|
iterator erase(iterator first, iterator last) {
|
||||||
|
// Erase is not allowed to the change the object's capacity. That means
|
||||||
|
// that when starting with an indirectly allocated prevector with
|
||||||
|
// size and capacity > N, the result may be a still indirectly allocated
|
||||||
|
// prevector with size <= N and capacity > N. A shrink_to_fit() call is
|
||||||
|
// necessary to switch to the (more efficient) directly allocated
|
||||||
|
// representation (with capacity N and size <= N).
|
||||||
iterator p = first;
|
iterator p = first;
|
||||||
char* endp = (char*)&(*end());
|
char* endp = (char*)&(*end());
|
||||||
while (p != last) {
|
if (!std::is_trivially_destructible<T>::value) {
|
||||||
(*p).~T();
|
while (p != last) {
|
||||||
_size--;
|
(*p).~T();
|
||||||
++p;
|
_size--;
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_size -= last - p;
|
||||||
}
|
}
|
||||||
memmove(&(*first), &(*last), endp - ((char*)(&(*last))));
|
memmove(&(*first), &(*last), endp - ((char*)(&(*last))));
|
||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
|
|
||||||
void push_back(const T& value) {
|
template<typename... Args>
|
||||||
|
void emplace_back(Args&&... args) {
|
||||||
size_type new_size = size() + 1;
|
size_type new_size = size() + 1;
|
||||||
if (capacity() < new_size) {
|
if (capacity() < new_size) {
|
||||||
change_capacity(new_size + (new_size >> 1));
|
change_capacity(new_size + (new_size >> 1));
|
||||||
}
|
}
|
||||||
new(item_ptr(size())) T(value);
|
new(item_ptr(size())) T(std::forward<Args>(args)...);
|
||||||
_size++;
|
_size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void push_back(const T& value) {
|
||||||
|
emplace_back(value);
|
||||||
|
}
|
||||||
|
|
||||||
void pop_back() {
|
void pop_back() {
|
||||||
_size--;
|
erase(end() - 1, end());
|
||||||
}
|
}
|
||||||
|
|
||||||
T& front() {
|
T& front() {
|
||||||
@@ -421,20 +460,17 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void swap(prevector<N, T, Size, Diff>& other) {
|
void swap(prevector<N, T, Size, Diff>& other) {
|
||||||
if (_size & other._size & 1) {
|
std::swap(_union, other._union);
|
||||||
std::swap(_union.capacity, other._union.capacity);
|
|
||||||
std::swap(_union.indirect, other._union.indirect);
|
|
||||||
} else {
|
|
||||||
std::swap(_union, other._union);
|
|
||||||
}
|
|
||||||
std::swap(_size, other._size);
|
std::swap(_size, other._size);
|
||||||
}
|
}
|
||||||
|
|
||||||
~prevector() {
|
~prevector() {
|
||||||
clear();
|
if (!std::is_trivially_destructible<T>::value) {
|
||||||
|
clear();
|
||||||
|
}
|
||||||
if (!is_direct()) {
|
if (!is_direct()) {
|
||||||
free(_union.indirect);
|
free(_union.indirect_contents.indirect);
|
||||||
_union.indirect = NULL;
|
_union.indirect_contents.indirect = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,10 +522,17 @@ public:
|
|||||||
if (is_direct()) {
|
if (is_direct()) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return ((size_t)(sizeof(T))) * _union.capacity;
|
return ((size_t)(sizeof(T))) * _union.indirect_contents.capacity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
#endif
|
value_type* data() {
|
||||||
|
return item_ptr(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const value_type* data() const {
|
||||||
|
return item_ptr(0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HUSH_PREVECTOR_H
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
#include "primitives/block.h"
|
#include "primitives/block.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "tinyformat.h"
|
#include "tinyformat.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "crypto/common.h"
|
#include "crypto/common.h"
|
||||||
#include "hush_defs.h"
|
#include "hush_defs.h"
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "tinyformat.h"
|
#include "tinyformat.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
|
|
||||||
#include "librustzcash.h"
|
#include "librustzcash.h"
|
||||||
|
|
||||||
|
|||||||
@@ -18,9 +18,11 @@
|
|||||||
* *
|
* *
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
# include <arpa/inet.h>
|
# include <arpa/inet.h>
|
||||||
@@ -34,6 +36,93 @@ static const char* ppszTypeName[] =
|
|||||||
"filtered block"
|
"filtered block"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace NetMsgType {
|
||||||
|
const char *VERSION="version"; //used
|
||||||
|
const char *VERACK="verack"; //used
|
||||||
|
const char *ADDR="addr"; //used
|
||||||
|
const char *ADDRV2="addrv2"; //used
|
||||||
|
const char *SENDADDRV2="sendaddrv2";
|
||||||
|
const char *INV="inv"; //used
|
||||||
|
const char *GETDATA="getdata"; //used
|
||||||
|
const char *MERKLEBLOCK="merkleblock";
|
||||||
|
const char *GETBLOCKS="getblocks"; //used
|
||||||
|
const char *GETHEADERS="getheaders"; //used
|
||||||
|
const char *TX="tx"; //used
|
||||||
|
const char *HEADERS="headers"; //used
|
||||||
|
const char *BLOCK="block"; //used
|
||||||
|
const char *GETADDR="getaddr"; //used
|
||||||
|
const char *MEMPOOL="mempool"; //used
|
||||||
|
const char *PING="ping"; //used
|
||||||
|
const char *PONG="pong"; //used
|
||||||
|
const char *NOTFOUND="notfound"; //used
|
||||||
|
const char *FILTERLOAD="filterload"; //used
|
||||||
|
const char *FILTERADD="filteradd"; //used
|
||||||
|
const char *FILTERCLEAR="filterclear"; //used
|
||||||
|
const char *SENDHEADERS="sendheaders";
|
||||||
|
const char *FEEFILTER="feefilter";
|
||||||
|
const char *SENDCMPCT="sendcmpct";
|
||||||
|
const char *CMPCTBLOCK="cmpctblock";
|
||||||
|
const char *GETBLOCKTXN="getblocktxn";
|
||||||
|
const char *BLOCKTXN="blocktxn";
|
||||||
|
const char *GETCFILTERS="getcfilters";
|
||||||
|
const char *CFILTER="cfilter";
|
||||||
|
const char *GETCFHEADERS="getcfheaders";
|
||||||
|
const char *CFHEADERS="cfheaders";
|
||||||
|
const char *GETCFCHECKPT="getcfcheckpt";
|
||||||
|
const char *CFCHECKPT="cfcheckpt";
|
||||||
|
const char *WTXIDRELAY="wtxidrelay";
|
||||||
|
const char *EVENTS="events"; //used
|
||||||
|
const char *GETNSPV="getnSPV"; //used
|
||||||
|
const char *NSPV="nSPV"; //used
|
||||||
|
const char *ALERT="alert"; //used
|
||||||
|
const char *REJECT="reject"; //used
|
||||||
|
} // namespace NetMsgType
|
||||||
|
|
||||||
|
/** All known message types. Keep this in the same order as the list of
|
||||||
|
* messages above and in protocol.h.
|
||||||
|
*/
|
||||||
|
const static std::string allNetMessageTypes[] = {
|
||||||
|
NetMsgType::VERSION,
|
||||||
|
NetMsgType::VERACK,
|
||||||
|
NetMsgType::ADDR,
|
||||||
|
NetMsgType::ADDRV2,
|
||||||
|
NetMsgType::SENDADDRV2,
|
||||||
|
NetMsgType::INV,
|
||||||
|
NetMsgType::GETDATA,
|
||||||
|
NetMsgType::MERKLEBLOCK,
|
||||||
|
NetMsgType::GETBLOCKS,
|
||||||
|
NetMsgType::GETHEADERS,
|
||||||
|
NetMsgType::TX,
|
||||||
|
NetMsgType::HEADERS,
|
||||||
|
NetMsgType::BLOCK,
|
||||||
|
NetMsgType::GETADDR,
|
||||||
|
NetMsgType::MEMPOOL,
|
||||||
|
NetMsgType::PING,
|
||||||
|
NetMsgType::PONG,
|
||||||
|
NetMsgType::NOTFOUND,
|
||||||
|
NetMsgType::FILTERLOAD,
|
||||||
|
NetMsgType::FILTERADD,
|
||||||
|
NetMsgType::FILTERCLEAR,
|
||||||
|
NetMsgType::SENDHEADERS,
|
||||||
|
NetMsgType::FEEFILTER,
|
||||||
|
NetMsgType::SENDCMPCT,
|
||||||
|
NetMsgType::CMPCTBLOCK,
|
||||||
|
NetMsgType::GETBLOCKTXN,
|
||||||
|
NetMsgType::BLOCKTXN,
|
||||||
|
NetMsgType::GETCFILTERS,
|
||||||
|
NetMsgType::CFILTER,
|
||||||
|
NetMsgType::GETCFHEADERS,
|
||||||
|
NetMsgType::CFHEADERS,
|
||||||
|
NetMsgType::GETCFCHECKPT,
|
||||||
|
NetMsgType::CFCHECKPT,
|
||||||
|
NetMsgType::WTXIDRELAY,
|
||||||
|
NetMsgType::EVENTS,
|
||||||
|
NetMsgType::GETNSPV,
|
||||||
|
NetMsgType::NSPV,
|
||||||
|
NetMsgType::ALERT,
|
||||||
|
NetMsgType::REJECT,
|
||||||
|
};
|
||||||
|
|
||||||
CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn)
|
CMessageHeader::CMessageHeader(const MessageStartChars& pchMessageStartIn)
|
||||||
{
|
{
|
||||||
memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);
|
memcpy(pchMessageStart, pchMessageStartIn, MESSAGE_START_SIZE);
|
||||||
@@ -101,7 +190,7 @@ CAddress::CAddress(CService ipIn, uint64_t nServicesIn) : CService(ipIn)
|
|||||||
|
|
||||||
void CAddress::Init()
|
void CAddress::Init()
|
||||||
{
|
{
|
||||||
nServices = NODE_NETWORK | NODE_NSPV;
|
nServices = GetBoolArg("-nspv_msg", DEFAULT_NSPV_PROCESSING) ? NODE_NETWORK | NODE_NSPV : NODE_NETWORK;
|
||||||
nTime = 100000000;
|
nTime = 100000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
313
src/protocol.h
313
src/protocol.h
@@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include "netbase.h"
|
#include "netbase.h"
|
||||||
#include "serialize.h"
|
#include "serialize.h"
|
||||||
|
#include "streams.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
@@ -79,8 +80,224 @@ public:
|
|||||||
unsigned int nChecksum;
|
unsigned int nChecksum;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bitcoin protocol message types. When adding new message types, don't forget
|
||||||
|
* to update allNetMessageTypes in protocol.cpp.
|
||||||
|
*/
|
||||||
|
namespace NetMsgType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The version message provides information about the transmitting node to the
|
||||||
|
* receiving node at the beginning of a connection.
|
||||||
|
*/
|
||||||
|
extern const char* VERSION;
|
||||||
|
/**
|
||||||
|
* The verack message acknowledges a previously-received version message,
|
||||||
|
* informing the connecting node that it can begin to send other messages.
|
||||||
|
*/
|
||||||
|
extern const char* VERACK;
|
||||||
|
/**
|
||||||
|
* The addr (IP address) message relays connection information for peers on the
|
||||||
|
* network.
|
||||||
|
*/
|
||||||
|
extern const char* ADDR;
|
||||||
|
/**
|
||||||
|
* The addrv2 message relays connection information for peers on the network just
|
||||||
|
* like the addr message, but is extended to allow gossiping of longer node
|
||||||
|
* addresses (see BIP155).
|
||||||
|
*/
|
||||||
|
extern const char *ADDRV2;
|
||||||
|
/**
|
||||||
|
* The sendaddrv2 message signals support for receiving ADDRV2 messages (BIP155).
|
||||||
|
* It also implies that its sender can encode as ADDRV2 and would send ADDRV2
|
||||||
|
* instead of ADDR to a peer that has signaled ADDRV2 support by sending SENDADDRV2.
|
||||||
|
*/
|
||||||
|
extern const char *SENDADDRV2;
|
||||||
|
/**
|
||||||
|
* The inv message (inventory message) transmits one or more inventories of
|
||||||
|
* objects known to the transmitting peer.
|
||||||
|
*/
|
||||||
|
extern const char* INV;
|
||||||
|
/**
|
||||||
|
* The getdata message requests one or more data objects from another node.
|
||||||
|
*/
|
||||||
|
extern const char* GETDATA;
|
||||||
|
/**
|
||||||
|
* The merkleblock message is a reply to a getdata message which requested a
|
||||||
|
* block using the inventory type MSG_MERKLEBLOCK.
|
||||||
|
* @since protocol version 70001 as described by BIP37.
|
||||||
|
*/
|
||||||
|
extern const char* MERKLEBLOCK;
|
||||||
|
/**
|
||||||
|
* The getblocks message requests an inv message that provides block header
|
||||||
|
* hashes starting from a particular point in the block chain.
|
||||||
|
*/
|
||||||
|
extern const char* GETBLOCKS;
|
||||||
|
/**
|
||||||
|
* The getheaders message requests a headers message that provides block
|
||||||
|
* headers starting from a particular point in the block chain.
|
||||||
|
* @since protocol version 31800.
|
||||||
|
*/
|
||||||
|
extern const char* GETHEADERS;
|
||||||
|
/**
|
||||||
|
* The tx message transmits a single transaction.
|
||||||
|
*/
|
||||||
|
extern const char* TX;
|
||||||
|
/**
|
||||||
|
* The headers message sends one or more block headers to a node which
|
||||||
|
* previously requested certain headers with a getheaders message.
|
||||||
|
* @since protocol version 31800.
|
||||||
|
*/
|
||||||
|
extern const char* HEADERS;
|
||||||
|
/**
|
||||||
|
* The block message transmits a single serialized block.
|
||||||
|
*/
|
||||||
|
extern const char* BLOCK;
|
||||||
|
/**
|
||||||
|
* The getaddr message requests an addr message from the receiving node,
|
||||||
|
* preferably one with lots of IP addresses of other receiving nodes.
|
||||||
|
*/
|
||||||
|
extern const char* GETADDR;
|
||||||
|
/**
|
||||||
|
* The mempool message requests the TXIDs of transactions that the receiving
|
||||||
|
* node has verified as valid but which have not yet appeared in a block.
|
||||||
|
* @since protocol version 60002.
|
||||||
|
*/
|
||||||
|
extern const char* MEMPOOL;
|
||||||
|
/**
|
||||||
|
* The ping message is sent periodically to help confirm that the receiving
|
||||||
|
* peer is still connected.
|
||||||
|
*/
|
||||||
|
extern const char* PING;
|
||||||
|
/**
|
||||||
|
* The pong message replies to a ping message, proving to the pinging node that
|
||||||
|
* the ponging node is still alive.
|
||||||
|
* @since protocol version 60001 as described by BIP31.
|
||||||
|
*/
|
||||||
|
extern const char* PONG;
|
||||||
|
/**
|
||||||
|
* The notfound message is a reply to a getdata message which requested an
|
||||||
|
* object the receiving node does not have available for relay.
|
||||||
|
* @since protocol version 70001.
|
||||||
|
*/
|
||||||
|
extern const char* NOTFOUND;
|
||||||
|
/**
|
||||||
|
* The filterload message tells the receiving peer to filter all relayed
|
||||||
|
* transactions and requested merkle blocks through the provided filter.
|
||||||
|
* @since protocol version 70001 as described by BIP37.
|
||||||
|
* Only available with service bit NODE_BLOOM since protocol version
|
||||||
|
* 70011 as described by BIP111.
|
||||||
|
*/
|
||||||
|
extern const char* FILTERLOAD;
|
||||||
|
/**
|
||||||
|
* The filteradd message tells the receiving peer to add a single element to a
|
||||||
|
* previously-set bloom filter, such as a new public key.
|
||||||
|
* @since protocol version 70001 as described by BIP37.
|
||||||
|
* Only available with service bit NODE_BLOOM since protocol version
|
||||||
|
* 70011 as described by BIP111.
|
||||||
|
*/
|
||||||
|
extern const char* FILTERADD;
|
||||||
|
/**
|
||||||
|
* The filterclear message tells the receiving peer to remove a previously-set
|
||||||
|
* bloom filter.
|
||||||
|
* @since protocol version 70001 as described by BIP37.
|
||||||
|
* Only available with service bit NODE_BLOOM since protocol version
|
||||||
|
* 70011 as described by BIP111.
|
||||||
|
*/
|
||||||
|
extern const char* FILTERCLEAR;
|
||||||
|
/**
|
||||||
|
* Indicates that a node prefers to receive new block announcements via a
|
||||||
|
* "headers" message rather than an "inv".
|
||||||
|
* @since protocol version 70012 as described by BIP130.
|
||||||
|
*/
|
||||||
|
extern const char* SENDHEADERS;
|
||||||
|
/**
|
||||||
|
* The feefilter message tells the receiving peer not to inv us any txs
|
||||||
|
* which do not meet the specified min fee rate.
|
||||||
|
* @since protocol version 70013 as described by BIP133
|
||||||
|
*/
|
||||||
|
extern const char* FEEFILTER;
|
||||||
|
/**
|
||||||
|
* Contains a 1-byte bool and 8-byte LE version number.
|
||||||
|
* Indicates that a node is willing to provide blocks via "cmpctblock" messages.
|
||||||
|
* May indicate that a node prefers to receive new block announcements via a
|
||||||
|
* "cmpctblock" message rather than an "inv", depending on message contents.
|
||||||
|
* @since protocol version 70014 as described by BIP 152
|
||||||
|
*/
|
||||||
|
extern const char* SENDCMPCT;
|
||||||
|
/**
|
||||||
|
* Contains a CBlockHeaderAndShortTxIDs object - providing a header and
|
||||||
|
* list of "short txids".
|
||||||
|
* @since protocol version 70014 as described by BIP 152
|
||||||
|
*/
|
||||||
|
extern const char* CMPCTBLOCK;
|
||||||
|
/**
|
||||||
|
* Contains a BlockTransactionsRequest
|
||||||
|
* Peer should respond with "blocktxn" message.
|
||||||
|
* @since protocol version 70014 as described by BIP 152
|
||||||
|
*/
|
||||||
|
extern const char* GETBLOCKTXN;
|
||||||
|
/**
|
||||||
|
* Contains a BlockTransactions.
|
||||||
|
* Sent in response to a "getblocktxn" message.
|
||||||
|
* @since protocol version 70014 as described by BIP 152
|
||||||
|
*/
|
||||||
|
extern const char* BLOCKTXN;
|
||||||
|
/**
|
||||||
|
* getcfilters requests compact filters for a range of blocks.
|
||||||
|
* Only available with service bit NODE_COMPACT_FILTERS as described by
|
||||||
|
* BIP 157 & 158.
|
||||||
|
*/
|
||||||
|
extern const char* GETCFILTERS;
|
||||||
|
/**
|
||||||
|
* cfilter is a response to a getcfilters request containing a single compact
|
||||||
|
* filter.
|
||||||
|
*/
|
||||||
|
extern const char* CFILTER;
|
||||||
|
/**
|
||||||
|
* getcfheaders requests a compact filter header and the filter hashes for a
|
||||||
|
* range of blocks, which can then be used to reconstruct the filter headers
|
||||||
|
* for those blocks.
|
||||||
|
* Only available with service bit NODE_COMPACT_FILTERS as described by
|
||||||
|
* BIP 157 & 158.
|
||||||
|
*/
|
||||||
|
extern const char* GETCFHEADERS;
|
||||||
|
/**
|
||||||
|
* cfheaders is a response to a getcfheaders request containing a filter header
|
||||||
|
* and a vector of filter hashes for each subsequent block in the requested range.
|
||||||
|
*/
|
||||||
|
extern const char* CFHEADERS;
|
||||||
|
/**
|
||||||
|
* getcfcheckpt requests evenly spaced compact filter headers, enabling
|
||||||
|
* parallelized download and validation of the headers between them.
|
||||||
|
* Only available with service bit NODE_COMPACT_FILTERS as described by
|
||||||
|
* BIP 157 & 158.
|
||||||
|
*/
|
||||||
|
extern const char* GETCFCHECKPT;
|
||||||
|
/**
|
||||||
|
* cfcheckpt is a response to a getcfcheckpt request containing a vector of
|
||||||
|
* evenly spaced filter headers for blocks on the requested chain.
|
||||||
|
*/
|
||||||
|
extern const char* CFCHECKPT;
|
||||||
|
/**
|
||||||
|
* Indicates that a node prefers to relay transactions via wtxid, rather than
|
||||||
|
* txid.
|
||||||
|
* @since protocol version 70016 as described by BIP 339.
|
||||||
|
*/
|
||||||
|
extern const char* WTXIDRELAY;
|
||||||
|
|
||||||
|
extern const char* EVENTS;
|
||||||
|
extern const char* GETNSPV;
|
||||||
|
extern const char* NSPV;
|
||||||
|
extern const char* ALERT;
|
||||||
|
extern const char* REJECT;
|
||||||
|
}; // namespace NetMsgType
|
||||||
|
|
||||||
|
/* Get a vector of all valid message types (see above) */
|
||||||
|
const std::vector<std::string>& getAllNetMessageTypes();
|
||||||
|
|
||||||
/** nServices flags */
|
/** nServices flags */
|
||||||
enum {
|
enum ServiceFlags : uint64_t {
|
||||||
// NODE_NETWORK means that the node is capable of serving the block chain. It is currently
|
// NODE_NETWORK means that the node is capable of serving the block chain. It is currently
|
||||||
// set by all Bitcoin Core nodes, and is unset by SPV clients or other peers that just want
|
// set by all Bitcoin Core nodes, and is unset by SPV clients or other peers that just want
|
||||||
// network services but don't provide them.
|
// network services but don't provide them.
|
||||||
@@ -106,27 +323,93 @@ enum {
|
|||||||
/** A CService with information about it as peer */
|
/** A CService with information about it as peer */
|
||||||
class CAddress : public CService
|
class CAddress : public CService
|
||||||
{
|
{
|
||||||
|
static constexpr uint32_t TIME_INIT{100000000};
|
||||||
|
|
||||||
|
/** Historically, CAddress disk serialization stored the CLIENT_VERSION, optionally OR'ed with
|
||||||
|
* the ADDRV2_FORMAT flag to indicate V2 serialization. The first field has since been
|
||||||
|
* disentangled from client versioning, and now instead:
|
||||||
|
* - The low bits (masked by DISK_VERSION_IGNORE_MASK) store the fixed value DISK_VERSION_INIT,
|
||||||
|
* (in case any code exists that treats it as a client version) but are ignored on
|
||||||
|
* deserialization.
|
||||||
|
* - The high bits (masked by ~DISK_VERSION_IGNORE_MASK) store actual serialization information.
|
||||||
|
* Only 0 or DISK_VERSION_ADDRV2 (equal to the historical ADDRV2_FORMAT) are valid now, and
|
||||||
|
* any other value triggers a deserialization failure. Other values can be added later if
|
||||||
|
* needed.
|
||||||
|
*
|
||||||
|
* For disk deserialization, ADDRV2_FORMAT in the stream version signals that ADDRV2
|
||||||
|
* deserialization is permitted, but the actual format is determined by the high bits in the
|
||||||
|
* stored version field. For network serialization, the stream version having ADDRV2_FORMAT or
|
||||||
|
* not determines the actual format used (as it has no embedded version number).
|
||||||
|
*/
|
||||||
|
static constexpr uint32_t DISK_VERSION_INIT{220000};
|
||||||
|
static constexpr uint32_t DISK_VERSION_IGNORE_MASK{0b00000000000001111111111111111111};
|
||||||
|
/** The version number written in disk serialized addresses to indicate V2 serializations.
|
||||||
|
* It must be exactly 1<<29, as that is the value that historical versions used for this
|
||||||
|
* (they used their internal ADDRV2_FORMAT flag here). */
|
||||||
|
static constexpr uint32_t DISK_VERSION_ADDRV2{1 << 29};
|
||||||
|
static_assert((DISK_VERSION_INIT & ~DISK_VERSION_IGNORE_MASK) == 0, "DISK_VERSION_INIT must be covered by DISK_VERSION_IGNORE_MASK");
|
||||||
|
static_assert((DISK_VERSION_ADDRV2 & DISK_VERSION_IGNORE_MASK) == 0, "DISK_VERSION_ADDRV2 must not be covered by DISK_VERSION_IGNORE_MASK");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CAddress();
|
CAddress();
|
||||||
explicit CAddress(CService ipIn, uint64_t nServicesIn = NODE_NETWORK);
|
explicit CAddress(CService ipIn, uint64_t nServicesIn = NODE_NETWORK);
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
ADD_SERIALIZE_METHODS;
|
SERIALIZE_METHODS(CAddress, obj)
|
||||||
|
|
||||||
template <typename Stream, typename Operation>
|
|
||||||
inline void SerializationOp(Stream& s, Operation ser_action)
|
|
||||||
{
|
{
|
||||||
if (ser_action.ForRead())
|
// CAddress has a distinct network serialization and a disk serialization, but it should never
|
||||||
Init();
|
// be hashed (except through CHashWriter in addrdb.cpp, which sets SER_DISK), and it's
|
||||||
int nVersion = s.GetVersion();
|
// ambiguous what that would mean. Make sure no code relying on that is introduced:
|
||||||
if (s.GetType() & SER_DISK)
|
assert(!(s.GetType() & SER_GETHASH));
|
||||||
READWRITE(nVersion);
|
bool use_v2;
|
||||||
if ((s.GetType() & SER_DISK) ||
|
bool store_time;
|
||||||
(nVersion >= CADDR_TIME_VERSION && !(s.GetType() & SER_GETHASH)))
|
if (s.GetType() & SER_DISK) {
|
||||||
READWRITE(nTime);
|
// In the disk serialization format, the encoding (v1 or v2) is determined by a flag version
|
||||||
READWRITE(nServices);
|
// that's part of the serialization itself. ADDRV2_FORMAT in the stream version only determines
|
||||||
READWRITE(*(CService*)this);
|
// whether V2 is chosen/permitted at all.
|
||||||
|
uint32_t stored_format_version = DISK_VERSION_INIT;
|
||||||
|
if (s.GetVersion() & ADDRV2_FORMAT) stored_format_version |= DISK_VERSION_ADDRV2;
|
||||||
|
READ_WRITE(stored_format_version);
|
||||||
|
stored_format_version &= ~DISK_VERSION_IGNORE_MASK; // ignore low bits
|
||||||
|
if (stored_format_version == 0) {
|
||||||
|
use_v2 = false;
|
||||||
|
} else if (stored_format_version == DISK_VERSION_ADDRV2 && (s.GetVersion() & ADDRV2_FORMAT)) {
|
||||||
|
// Only support v2 deserialization if ADDRV2_FORMAT is set.
|
||||||
|
use_v2 = true;
|
||||||
|
} else {
|
||||||
|
throw std::ios_base::failure("Unsupported CAddress disk format version");
|
||||||
|
}
|
||||||
|
store_time = true;
|
||||||
|
} else {
|
||||||
|
// In the network serialization format, the encoding (v1 or v2) is determined directly by
|
||||||
|
// the value of ADDRV2_FORMAT in the stream version, as no explicitly encoded version
|
||||||
|
// exists in the stream.
|
||||||
|
assert(s.GetType() & SER_NETWORK);
|
||||||
|
use_v2 = s.GetVersion() & ADDRV2_FORMAT;
|
||||||
|
// The only time we serialize a CAddress object without nTime is in
|
||||||
|
// the initial VERSION messages which contain two CAddress records.
|
||||||
|
// At that point, the serialization version is INIT_PROTO_VERSION.
|
||||||
|
// After the version handshake, serialization version is >=
|
||||||
|
// MIN_PEER_PROTO_VERSION and all ADDR messages are serialized with
|
||||||
|
// nTime.
|
||||||
|
store_time = s.GetVersion() != INIT_PROTO_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
SER_READ(obj, obj.nTime = TIME_INIT);
|
||||||
|
if (store_time) READWRITE(obj.nTime);
|
||||||
|
// nServices is serialized as CompactSize in V2; as uint64_t in V1.
|
||||||
|
if (use_v2) {
|
||||||
|
uint64_t services_tmp;
|
||||||
|
SER_WRITE(obj, services_tmp = obj.nServices);
|
||||||
|
READ_WRITE(Using<CompactSizeFormatter<false>>(services_tmp));
|
||||||
|
SER_READ(obj, obj.nServices = static_cast<ServiceFlags>(services_tmp));
|
||||||
|
} else {
|
||||||
|
READ_WRITE(Using<CustomUintFormatter<8>>(obj.nServices));
|
||||||
|
}
|
||||||
|
// Invoke V1/V2 serializer for CService parent object.
|
||||||
|
OverrideStream<Stream> os(&s, s.GetType(), use_v2 ? ADDRV2_FORMAT : 0);
|
||||||
|
SerReadWriteMany(os, ser_action, ReadWriteAsHelper<CService>(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: make private (improves encapsulation)
|
// TODO: make private (improves encapsulation)
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "serialize.h" // for begin_ptr(vec)
|
#include "serialize.h" // for begin_ptr(vec)
|
||||||
#include "util.h" // for LogPrint()
|
#include "util.h" // for LogPrint()
|
||||||
#include "utilstrencodings.h" // for GetTime()
|
#include "util/strencodings.h" // for GetTime()
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
#include "streams.h"
|
#include "streams.h"
|
||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
#include "txmempool.h"
|
#include "txmempool.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/dynamic_bitset.hpp>
|
#include <boost/dynamic_bitset.hpp>
|
||||||
|
|||||||
@@ -1334,7 +1334,7 @@ UniValue getsnapshot(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
|||||||
" \"utxos\": 14, (number) Total number of UTXOs in snapshot\n"
|
" \"utxos\": 14, (number) Total number of UTXOs in snapshot\n"
|
||||||
" \"total_addresses\": 2, (number) Total number of addresses in snapshot,\n"
|
" \"total_addresses\": 2, (number) Total number of addresses in snapshot,\n"
|
||||||
" \"start_height\": 91, (number) Block height snapshot began\n"
|
" \"start_height\": 91, (number) Block height snapshot began\n"
|
||||||
" \"ending_height\": 91 (number) Block height snapsho finished,\n"
|
" \"ending_height\": 91 (number) Block height snapshot finished,\n"
|
||||||
" \"start_time\": 1531982752, (number) Unix epoch time snapshot started\n"
|
" \"start_time\": 1531982752, (number) Unix epoch time snapshot started\n"
|
||||||
" \"end_time\": 1531982752 (number) Unix epoch time snapshot finished\n"
|
" \"end_time\": 1531982752 (number) Unix epoch time snapshot finished\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "clientversion.h"
|
#include "clientversion.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
|
#include "addrman.h"
|
||||||
#include "netbase.h"
|
#include "netbase.h"
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
@@ -75,6 +76,36 @@ UniValue ping(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
|||||||
return NullUniValue;
|
return NullUniValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UniValue getpeerlist(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||||
|
{
|
||||||
|
if (fHelp || params.size() != 0)
|
||||||
|
throw runtime_error(
|
||||||
|
"getpeerlist\n"
|
||||||
|
"\nReturns a list of connected network node addresses that have connected to the\n"
|
||||||
|
"in the last 30 days as a json array of objects.\n"
|
||||||
|
"\nbResult:\n"
|
||||||
|
"[\n"
|
||||||
|
" \"host:port\", (string) The ip address and port of the peer\n"
|
||||||
|
"]\n"
|
||||||
|
"\nExamples:\n"
|
||||||
|
+ HelpExampleCli("getpeerlist", "")
|
||||||
|
+ HelpExampleRpc("getpeerlist", "")
|
||||||
|
);
|
||||||
|
|
||||||
|
LOCK(cs_main);
|
||||||
|
|
||||||
|
UniValue ret(UniValue::VARR);
|
||||||
|
std::map<std::string, int64_t> info;
|
||||||
|
addrman.GetAllPeers(info);
|
||||||
|
int64_t nCutOff = GetTime() - (60 * 60 * 24 * 30); //Connected within last 30 days.
|
||||||
|
for (std::map<std::string, int64_t>::iterator it = info.begin(); it != info.end(); it++) {
|
||||||
|
if ((*it).second >= nCutOff)
|
||||||
|
ret.push_back((*it).first);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
||||||
{
|
{
|
||||||
if (fHelp || params.size() != 0)
|
if (fHelp || params.size() != 0)
|
||||||
@@ -159,6 +190,7 @@ UniValue getpeerinfo(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
|||||||
// corrupting or modifying the JSON output by putting special characters in
|
// corrupting or modifying the JSON output by putting special characters in
|
||||||
// their ver message.
|
// their ver message.
|
||||||
obj.push_back(Pair("subver", stats.cleanSubVer));
|
obj.push_back(Pair("subver", stats.cleanSubVer));
|
||||||
|
obj.push_back(Pair("addrv2", stats.m_wants_addrv2));
|
||||||
obj.push_back(Pair("inbound", stats.fInbound));
|
obj.push_back(Pair("inbound", stats.fInbound));
|
||||||
obj.push_back(Pair("startingheight", stats.nStartingHeight));
|
obj.push_back(Pair("startingheight", stats.nStartingHeight));
|
||||||
if (fStateStats) {
|
if (fStateStats) {
|
||||||
@@ -447,13 +479,12 @@ static UniValue GetNetworksInfo()
|
|||||||
for(int n=0; n<NET_MAX; ++n)
|
for(int n=0; n<NET_MAX; ++n)
|
||||||
{
|
{
|
||||||
enum Network network = static_cast<enum Network>(n);
|
enum Network network = static_cast<enum Network>(n);
|
||||||
if(network == NET_UNROUTABLE)
|
if(network == NET_UNROUTABLE || network == NET_INTERNAL)
|
||||||
continue;
|
continue;
|
||||||
proxyType proxy;
|
proxyType proxy;
|
||||||
UniValue obj(UniValue::VOBJ);
|
UniValue obj(UniValue::VOBJ);
|
||||||
GetProxy(network, proxy);
|
GetProxy(network, proxy);
|
||||||
obj.push_back(Pair("name", GetNetworkName(network)));
|
obj.push_back(Pair("name", GetNetworkName(network)));
|
||||||
obj.push_back(Pair("limited", IsLimited(network)));
|
|
||||||
obj.push_back(Pair("reachable", IsReachable(network)));
|
obj.push_back(Pair("reachable", IsReachable(network)));
|
||||||
obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string()));
|
obj.push_back(Pair("proxy", proxy.IsValid() ? proxy.proxy.ToStringIPPort() : string()));
|
||||||
obj.push_back(Pair("proxy_randomize_credentials", proxy.randomize_credentials));
|
obj.push_back(Pair("proxy_randomize_credentials", proxy.randomize_credentials));
|
||||||
@@ -586,10 +617,13 @@ UniValue setban(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
|||||||
if (params[0].get_str().find("/") != string::npos)
|
if (params[0].get_str().find("/") != string::npos)
|
||||||
isSubnet = true;
|
isSubnet = true;
|
||||||
|
|
||||||
if (!isSubnet)
|
if (!isSubnet) {
|
||||||
netAddr = CNetAddr(params[0].get_str());
|
CNetAddr resolved;
|
||||||
else
|
LookupHost(params[0].get_str().c_str(), resolved, false);
|
||||||
subNet = CSubNet(params[0].get_str());
|
netAddr = resolved;
|
||||||
|
} else {
|
||||||
|
LookupSubNet(params[0].get_str().c_str(), subNet);
|
||||||
|
}
|
||||||
|
|
||||||
if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) )
|
if (! (isSubnet ? subNet.IsValid() : netAddr.IsValid()) )
|
||||||
throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Invalid IP/Subnet");
|
throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: Invalid IP/Subnet");
|
||||||
@@ -599,7 +633,7 @@ UniValue setban(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
|||||||
if (isSubnet ? CNode::IsBanned(subNet) : CNode::IsBanned(netAddr))
|
if (isSubnet ? CNode::IsBanned(subNet) : CNode::IsBanned(netAddr))
|
||||||
throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned");
|
throw JSONRPCError(RPC_CLIENT_NODE_ALREADY_ADDED, "Error: IP/Subnet already banned");
|
||||||
|
|
||||||
int64_t banTime = 0; //use standard bantime if not specified
|
int64_t banTime = 60*60*24; //use standard bantime if not specified
|
||||||
if (params.size() >= 3 && !params[2].isNull())
|
if (params.size() >= 3 && !params[2].isNull())
|
||||||
banTime = params[2].get_int64();
|
banTime = params[2].get_int64();
|
||||||
|
|
||||||
@@ -607,14 +641,14 @@ UniValue setban(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
|||||||
if (params.size() == 4 && params[3].isTrue())
|
if (params.size() == 4 && params[3].isTrue())
|
||||||
absolute = true;
|
absolute = true;
|
||||||
|
|
||||||
isSubnet ? CNode::Ban(subNet, banTime, absolute) : CNode::Ban(netAddr, banTime, absolute);
|
fprintf(stderr,"%s: adding manual ban for %s with banTime=%ld absolute=%d isSubnet=%d\n", __func__, isSubnet ? subNet.ToString().c_str() : netAddr.ToString().c_str(), banTime, absolute, isSubnet);
|
||||||
|
isSubnet ? CNode::Ban(subNet, BanReasonManuallyAdded, banTime, absolute) : CNode::Ban(netAddr, BanReasonManuallyAdded, banTime, absolute);
|
||||||
|
|
||||||
//disconnect possible nodes
|
//disconnect possible nodes
|
||||||
while(CNode *bannedNode = (isSubnet ? FindNode(subNet) : FindNode(netAddr)))
|
while(CNode *bannedNode = (isSubnet ? FindNode(subNet) : FindNode(netAddr))) {
|
||||||
bannedNode->fDisconnect = true;
|
bannedNode->fDisconnect = true;
|
||||||
}
|
}
|
||||||
else if(strCommand == "remove")
|
} else if(strCommand == "remove") {
|
||||||
{
|
|
||||||
if (!( isSubnet ? CNode::Unban(subNet) : CNode::Unban(netAddr) ))
|
if (!( isSubnet ? CNode::Unban(subNet) : CNode::Unban(netAddr) ))
|
||||||
throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed");
|
throw JSONRPCError(RPC_MISC_ERROR, "Error: Unban failed");
|
||||||
}
|
}
|
||||||
@@ -633,17 +667,21 @@ UniValue listbanned(const UniValue& params, bool fHelp, const CPubKey& mypk)
|
|||||||
+ HelpExampleRpc("listbanned", "")
|
+ HelpExampleRpc("listbanned", "")
|
||||||
);
|
);
|
||||||
|
|
||||||
std::map<CSubNet, int64_t> banMap;
|
banmap_t banMap;
|
||||||
CNode::GetBanned(banMap);
|
GetBanned(banMap);
|
||||||
const int64_t current_time{GetTime()};
|
|
||||||
|
|
||||||
UniValue bannedAddresses(UniValue::VARR);
|
UniValue bannedAddresses(UniValue::VARR);
|
||||||
for (std::map<CSubNet, int64_t>::iterator it = banMap.begin(); it != banMap.end(); it++)
|
const int64_t current_time{GetTime()};
|
||||||
|
|
||||||
|
for (banmap_t::iterator it = banMap.begin(); it != banMap.end(); it++)
|
||||||
{
|
{
|
||||||
|
CBanEntry banEntry = (*it).second;
|
||||||
UniValue rec(UniValue::VOBJ);
|
UniValue rec(UniValue::VOBJ);
|
||||||
rec.push_back(Pair("address", (*it).first.ToString()));
|
rec.push_back(Pair("address", (*it).first.ToString()));
|
||||||
rec.push_back(Pair("banned_until", (*it).second));
|
rec.push_back(Pair("banned_until", banEntry.nBanUntil));
|
||||||
rec.push_back(Pair("time_remaining", (*it).second - current_time));
|
rec.push_back(Pair("time_remaining", banEntry.nBanUntil - current_time));
|
||||||
|
rec.push_back(Pair("ban_created", banEntry.nCreateTime));
|
||||||
|
rec.push_back(Pair("ban_reason", banEntry.banReasonToString()));
|
||||||
bannedAddresses.push_back(rec);
|
bannedAddresses.push_back(rec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -672,6 +710,7 @@ static const CRPCCommand commands[] =
|
|||||||
{ "network", "getconnectioncount", &getconnectioncount, true },
|
{ "network", "getconnectioncount", &getconnectioncount, true },
|
||||||
{ "network", "getdeprecationinfo", &getdeprecationinfo, true },
|
{ "network", "getdeprecationinfo", &getdeprecationinfo, true },
|
||||||
{ "network", "ping", &ping, true },
|
{ "network", "ping", &ping, true },
|
||||||
|
{ "network", "getpeerlist", &getpeerlist, true },
|
||||||
{ "network", "getpeerinfo", &getpeerinfo, true },
|
{ "network", "getpeerinfo", &getpeerinfo, true },
|
||||||
{ "network", "addnode", &addnode, true },
|
{ "network", "addnode", &addnode, true },
|
||||||
{ "network", "disconnectnode", &disconnectnode, true },
|
{ "network", "disconnectnode", &disconnectnode, true },
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "tinyformat.h"
|
#include "tinyformat.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "utiltime.h"
|
#include "utiltime.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
#include "ui_interface.h"
|
#include "ui_interface.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "asyncrpcqueue.h"
|
#include "asyncrpcqueue.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
#include "script.h"
|
#include "script.h"
|
||||||
|
|
||||||
#include "tinyformat.h"
|
#include "tinyformat.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "script/cc.h"
|
#include "script/cc.h"
|
||||||
#include "cc/eval.h"
|
#include "cc/eval.h"
|
||||||
#include "cryptoconditions/include/cryptoconditions.h"
|
#include "cryptoconditions/include/cryptoconditions.h"
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
#include "pubkey.h"
|
#include "pubkey.h"
|
||||||
#include "script/script.h"
|
#include "script/script.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "script/cc.h"
|
#include "script/cc.h"
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
// Copyright (c) 2016-2022 The Hush developers
|
|
||||||
// Copyright (c) 2016 The Zcash developers
|
|
||||||
// Original code from: https://gist.github.com/laanwj/0e689cfa37b52bcbbb44
|
|
||||||
// Distributed under the GPLv3 software license, see the accompanying
|
|
||||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Copyright © 2014-2019 The SuperNET Developers. *
|
|
||||||
* *
|
|
||||||
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
|
|
||||||
* the top-level directory of this distribution for the individual copyright *
|
|
||||||
* holder information and the developer policies on copyright and licensing. *
|
|
||||||
* *
|
|
||||||
* Unless otherwise agreed in a custom licensing agreement, no part of the *
|
|
||||||
* SuperNET software, including this file may be copied, modified, propagated *
|
|
||||||
* or distributed except according to the terms contained in the LICENSE file *
|
|
||||||
* *
|
|
||||||
* Removal or modification of this copyright notice is prohibited. *
|
|
||||||
* *
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
To set up a new alert system
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
Create a new alert key pair:
|
|
||||||
openssl ecparam -name secp256k1 -genkey -param_enc explicit -outform PEM -out data.pem
|
|
||||||
|
|
||||||
Get the private key in hex:
|
|
||||||
openssl ec -in data.pem -outform DER | tail -c 279 | xxd -p -c 279
|
|
||||||
|
|
||||||
Get the public key in hex:
|
|
||||||
openssl ec -in data.pem -pubout -outform DER | tail -c 65 | xxd -p -c 65
|
|
||||||
|
|
||||||
Update the public keys found in chainparams.cpp.
|
|
||||||
|
|
||||||
|
|
||||||
To send an alert message
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
Copy the private keys into alertkeys.h.
|
|
||||||
|
|
||||||
Modify the alert parameters, id and message found in this file.
|
|
||||||
|
|
||||||
Build and run with -sendalert or -printalert.
|
|
||||||
|
|
||||||
./hushd -printtoconsole -sendalert
|
|
||||||
|
|
||||||
One minute after starting up, the alert will be broadcast. It is then
|
|
||||||
flooded through the network until the nRelayUntil time, and will be
|
|
||||||
active until nExpiration OR the alert is cancelled.
|
|
||||||
|
|
||||||
If you make a mistake, send another alert with nCancel set to cancel
|
|
||||||
the bad alert.
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Copyright (c) 2016-2022 The Hush developers
|
|
||||||
// Distributed under the GPLv3 software license, see the accompanying
|
|
||||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
|
||||||
#include "main.h"
|
|
||||||
#include "net.h"
|
|
||||||
#include "alert.h"
|
|
||||||
#include "init.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include "utiltime.h"
|
|
||||||
#include "key.h"
|
|
||||||
#include "clientversion.h"
|
|
||||||
#include "chainparams.h"
|
|
||||||
#include "alertkeys.h"
|
|
||||||
|
|
||||||
static const int64_t DAYS = 24 * 60 * 60;
|
|
||||||
|
|
||||||
void ThreadSendAlert()
|
|
||||||
{
|
|
||||||
if (!mapArgs.count("-sendalert") && !mapArgs.count("-printalert"))
|
|
||||||
return;
|
|
||||||
|
|
||||||
fprintf(stderr,"Sending alerts not supported!\n");
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
306
src/serialize.h
306
src/serialize.h
@@ -1,6 +1,6 @@
|
|||||||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
// Copyright (c) 2009-2014 The Bitcoin Core developers
|
||||||
// Copyright (c) 2009-2014 The Hush developers
|
// Copyright (c) 2016-2022 The Hush developers
|
||||||
// Distributed under the GPLv3 software license, see the accompanying
|
// Distributed under the GPLv3 software license, see the accompanying
|
||||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
|
|
||||||
@@ -42,6 +42,7 @@
|
|||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
#include "prevector.h"
|
#include "prevector.h"
|
||||||
|
#include "span.h"
|
||||||
|
|
||||||
static const unsigned int MAX_SIZE = 0x02000000;
|
static const unsigned int MAX_SIZE = 0x02000000;
|
||||||
|
|
||||||
@@ -59,6 +60,12 @@ static const unsigned int MAX_SIZE = 0x02000000;
|
|||||||
struct deserialize_type {};
|
struct deserialize_type {};
|
||||||
constexpr deserialize_type deserialize {};
|
constexpr deserialize_type deserialize {};
|
||||||
|
|
||||||
|
//! Safely convert odd char pointer types to standard ones.
|
||||||
|
inline char* CharCast(char* c) { return c; }
|
||||||
|
inline char* CharCast(unsigned char* c) { return (char*)c; }
|
||||||
|
inline const char* CharCast(const char* c) { return c; }
|
||||||
|
inline const char* CharCast(const unsigned char* c) { return (const char*)c; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to bypass the rule against non-const reference to temporary
|
* Used to bypass the rule against non-const reference to temporary
|
||||||
* where it makes sense with wrappers such as CFlatData or CTxDB
|
* where it makes sense with wrappers such as CFlatData or CTxDB
|
||||||
@@ -121,6 +128,11 @@ template<typename Stream> inline void ser_writedata16(Stream &s, uint16_t obj)
|
|||||||
obj = htole16(obj);
|
obj = htole16(obj);
|
||||||
s.write((char*)&obj, 2);
|
s.write((char*)&obj, 2);
|
||||||
}
|
}
|
||||||
|
template<typename Stream> inline void ser_writedata16be(Stream &s, uint16_t obj)
|
||||||
|
{
|
||||||
|
obj = htobe16(obj);
|
||||||
|
s.write((char*)&obj, 2);
|
||||||
|
}
|
||||||
template<typename Stream> inline void ser_writedata32(Stream &s, uint32_t obj)
|
template<typename Stream> inline void ser_writedata32(Stream &s, uint32_t obj)
|
||||||
{
|
{
|
||||||
obj = htole32(obj);
|
obj = htole32(obj);
|
||||||
@@ -148,6 +160,12 @@ template<typename Stream> inline uint16_t ser_readdata16(Stream &s)
|
|||||||
s.read((char*)&obj, 2);
|
s.read((char*)&obj, 2);
|
||||||
return le16toh(obj);
|
return le16toh(obj);
|
||||||
}
|
}
|
||||||
|
template<typename Stream> inline uint16_t ser_readdata16be(Stream &s)
|
||||||
|
{
|
||||||
|
uint16_t obj;
|
||||||
|
s.read((char*)&obj, 2);
|
||||||
|
return be16toh(obj);
|
||||||
|
}
|
||||||
template<typename Stream> inline uint32_t ser_readdata32(Stream &s)
|
template<typename Stream> inline uint32_t ser_readdata32(Stream &s)
|
||||||
{
|
{
|
||||||
uint32_t obj;
|
uint32_t obj;
|
||||||
@@ -208,9 +226,64 @@ enum
|
|||||||
SER_GETHASH = (1 << 2),
|
SER_GETHASH = (1 << 2),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! Convert the reference base type to X, without changing constness or reference type.
|
||||||
|
template<typename X> X& ReadWriteAsHelper(X& x) { return x; }
|
||||||
|
template<typename X> const X& ReadWriteAsHelper(const X& x) { return x; }
|
||||||
|
|
||||||
#define READWRITE(obj) (::SerReadWrite(s, (obj), ser_action))
|
#define READWRITE(obj) (::SerReadWrite(s, (obj), ser_action))
|
||||||
#define READWRITEMANY(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
|
#define READWRITEMANY(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
|
||||||
|
|
||||||
|
#define READ_WRITE(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
|
||||||
|
#define READWRITEAS(type, obj) (::SerReadWriteMany(s, ser_action, ReadWriteAsHelper<type>(obj)))
|
||||||
|
#define SER_READ(obj, code) ::SerRead(s, ser_action, obj, [&](Stream& s, typename std::remove_const<Type>::type& obj) { code; })
|
||||||
|
#define SER_WRITE(obj, code) ::SerWrite(s, ser_action, obj, [&](Stream& s, const Type& obj) { code; })
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement the Ser and Unser methods needed for implementing a formatter (see Using below).
|
||||||
|
*
|
||||||
|
* Both Ser and Unser are delegated to a single static method SerializationOps, which is polymorphic
|
||||||
|
* in the serialized/deserialized type (allowing it to be const when serializing, and non-const when
|
||||||
|
* deserializing).
|
||||||
|
*
|
||||||
|
* Example use:
|
||||||
|
* struct FooFormatter {
|
||||||
|
* FORMATTER_METHODS(Class, obj) { READWRITE(obj.val1, VARINT(obj.val2)); }
|
||||||
|
* }
|
||||||
|
* would define a class FooFormatter that defines a serialization of Class objects consisting
|
||||||
|
* of serializing its val1 member using the default serialization, and its val2 member using
|
||||||
|
* VARINT serialization. That FooFormatter can then be used in statements like
|
||||||
|
* READWRITE(Using<FooFormatter>(obj.bla)).
|
||||||
|
*/
|
||||||
|
#define FORMATTER_METHODS(cls, obj) \
|
||||||
|
template<typename Stream> \
|
||||||
|
static void Ser(Stream& s, const cls& obj) { SerializationOps(obj, s, CSerActionSerialize()); } \
|
||||||
|
template<typename Stream> \
|
||||||
|
static void Unser(Stream& s, cls& obj) { SerializationOps(obj, s, CSerActionUnserialize()); } \
|
||||||
|
template<typename Stream, typename Type, typename Operation> \
|
||||||
|
static inline void SerializationOps(Type& obj, Stream& s, Operation ser_action) \
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement the Serialize and Unserialize methods by delegating to a single templated
|
||||||
|
* static method that takes the to-be-(de)serialized object as a parameter. This approach
|
||||||
|
* has the advantage that the constness of the object becomes a template parameter, and
|
||||||
|
* thus allows a single implementation that sees the object as const for serializing
|
||||||
|
* and non-const for deserializing, without casts.
|
||||||
|
*/
|
||||||
|
#define SERIALIZE_METHODS(cls, obj) \
|
||||||
|
template<typename Stream> \
|
||||||
|
void Serialize(Stream& s) const \
|
||||||
|
{ \
|
||||||
|
static_assert(std::is_same<const cls&, decltype(*this)>::value, "Serialize type mismatch"); \
|
||||||
|
Ser(s, *this); \
|
||||||
|
} \
|
||||||
|
template<typename Stream> \
|
||||||
|
void Unserialize(Stream& s) \
|
||||||
|
{ \
|
||||||
|
static_assert(std::is_same<cls&, decltype(*this)>::value, "Unserialize type mismatch"); \
|
||||||
|
Unser(s, *this); \
|
||||||
|
} \
|
||||||
|
FORMATTER_METHODS(cls, obj)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implement three methods for serializable objects. These are actually wrappers over
|
* Implement three methods for serializable objects. These are actually wrappers over
|
||||||
* "SerializationOp" template, which implements the body of each class' serialization
|
* "SerializationOp" template, which implements the body of each class' serialization
|
||||||
@@ -227,7 +300,9 @@ enum
|
|||||||
SerializationOp(s, CSerActionUnserialize()); \
|
SerializationOp(s, CSerActionUnserialize()); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CHAR_EQUALS_INT8
|
||||||
template<typename Stream> inline void Serialize(Stream& s, char a ) { ser_writedata8(s, a); } // TODO Get rid of bare char
|
template<typename Stream> inline void Serialize(Stream& s, char a ) { ser_writedata8(s, a); } // TODO Get rid of bare char
|
||||||
|
#endif
|
||||||
template<typename Stream> inline void Serialize(Stream& s, int8_t a ) { ser_writedata8(s, a); }
|
template<typename Stream> inline void Serialize(Stream& s, int8_t a ) { ser_writedata8(s, a); }
|
||||||
template<typename Stream> inline void Serialize(Stream& s, uint8_t a ) { ser_writedata8(s, a); }
|
template<typename Stream> inline void Serialize(Stream& s, uint8_t a ) { ser_writedata8(s, a); }
|
||||||
template<typename Stream> inline void Serialize(Stream& s, int16_t a ) { ser_writedata16(s, a); }
|
template<typename Stream> inline void Serialize(Stream& s, int16_t a ) { ser_writedata16(s, a); }
|
||||||
@@ -236,10 +311,17 @@ template<typename Stream> inline void Serialize(Stream& s, int32_t a ) { ser_wri
|
|||||||
template<typename Stream> inline void Serialize(Stream& s, uint32_t a) { ser_writedata32(s, a); }
|
template<typename Stream> inline void Serialize(Stream& s, uint32_t a) { ser_writedata32(s, a); }
|
||||||
template<typename Stream> inline void Serialize(Stream& s, int64_t a ) { ser_writedata64(s, a); }
|
template<typename Stream> inline void Serialize(Stream& s, int64_t a ) { ser_writedata64(s, a); }
|
||||||
template<typename Stream> inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); }
|
template<typename Stream> inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); }
|
||||||
|
template<typename Stream, int N> inline void Serialize(Stream& s, const char (&a)[N]) { s.write(a, N); }
|
||||||
|
template<typename Stream, int N> inline void Serialize(Stream& s, const unsigned char (&a)[N]) { s.write(CharCast(a), N); }
|
||||||
|
template<typename Stream> inline void Serialize(Stream& s, const Span<const unsigned char>& span) { s.write(CharCast(span.data()), span.size()); }
|
||||||
|
template<typename Stream> inline void Serialize(Stream& s, const Span<unsigned char>& span) { s.write(CharCast(span.data()), span.size()); }
|
||||||
|
|
||||||
template<typename Stream> inline void Serialize(Stream& s, float a ) { ser_writedata32(s, ser_float_to_uint32(a)); }
|
template<typename Stream> inline void Serialize(Stream& s, float a ) { ser_writedata32(s, ser_float_to_uint32(a)); }
|
||||||
template<typename Stream> inline void Serialize(Stream& s, double a ) { ser_writedata64(s, ser_double_to_uint64(a)); }
|
template<typename Stream> inline void Serialize(Stream& s, double a ) { ser_writedata64(s, ser_double_to_uint64(a)); }
|
||||||
|
|
||||||
|
#ifndef CHAR_EQUALS_INT8
|
||||||
template<typename Stream> inline void Unserialize(Stream& s, char& a ) { a = ser_readdata8(s); } // TODO Get rid of bare char
|
template<typename Stream> inline void Unserialize(Stream& s, char& a ) { a = ser_readdata8(s); } // TODO Get rid of bare char
|
||||||
|
#endif
|
||||||
template<typename Stream> inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); }
|
template<typename Stream> inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); }
|
||||||
template<typename Stream> inline void Unserialize(Stream& s, uint8_t& a ) { a = ser_readdata8(s); }
|
template<typename Stream> inline void Unserialize(Stream& s, uint8_t& a ) { a = ser_readdata8(s); }
|
||||||
template<typename Stream> inline void Unserialize(Stream& s, int16_t& a ) { a = ser_readdata16(s); }
|
template<typename Stream> inline void Unserialize(Stream& s, int16_t& a ) { a = ser_readdata16(s); }
|
||||||
@@ -248,6 +330,10 @@ template<typename Stream> inline void Unserialize(Stream& s, int32_t& a ) { a =
|
|||||||
template<typename Stream> inline void Unserialize(Stream& s, uint32_t& a) { a = ser_readdata32(s); }
|
template<typename Stream> inline void Unserialize(Stream& s, uint32_t& a) { a = ser_readdata32(s); }
|
||||||
template<typename Stream> inline void Unserialize(Stream& s, int64_t& a ) { a = ser_readdata64(s); }
|
template<typename Stream> inline void Unserialize(Stream& s, int64_t& a ) { a = ser_readdata64(s); }
|
||||||
template<typename Stream> inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); }
|
template<typename Stream> inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); }
|
||||||
|
template<typename Stream, int N> inline void Unserialize(Stream& s, char (&a)[N]) { s.read(a, N); }
|
||||||
|
template<typename Stream, int N> inline void Unserialize(Stream& s, unsigned char (&a)[N]) { s.read(CharCast(a), N); }
|
||||||
|
template<typename Stream> inline void Unserialize(Stream& s, Span<unsigned char>& span) { s.read(CharCast(span.data()), span.size()); }
|
||||||
|
|
||||||
template<typename Stream> inline void Unserialize(Stream& s, float& a ) { a = ser_uint32_to_float(ser_readdata32(s)); }
|
template<typename Stream> inline void Unserialize(Stream& s, float& a ) { a = ser_uint32_to_float(ser_readdata32(s)); }
|
||||||
template<typename Stream> inline void Unserialize(Stream& s, double& a ) { a = ser_uint64_to_double(ser_readdata64(s)); }
|
template<typename Stream> inline void Unserialize(Stream& s, double& a ) { a = ser_uint64_to_double(ser_readdata64(s)); }
|
||||||
|
|
||||||
@@ -301,7 +387,7 @@ void WriteCompactSize(Stream& os, uint64_t nSize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Stream>
|
template<typename Stream>
|
||||||
uint64_t ReadCompactSize(Stream& is)
|
uint64_t ReadCompactSize(Stream& is, bool range_check = true)
|
||||||
{
|
{
|
||||||
uint8_t chSize = ser_readdata8(is);
|
uint8_t chSize = ser_readdata8(is);
|
||||||
uint64_t nSizeRet = 0;
|
uint64_t nSizeRet = 0;
|
||||||
@@ -327,8 +413,9 @@ uint64_t ReadCompactSize(Stream& is)
|
|||||||
if (nSizeRet < 0x100000000ULL)
|
if (nSizeRet < 0x100000000ULL)
|
||||||
throw std::ios_base::failure("non-canonical ReadCompactSize()");
|
throw std::ios_base::failure("non-canonical ReadCompactSize()");
|
||||||
}
|
}
|
||||||
if (nSizeRet > (uint64_t)MAX_SIZE)
|
if (range_check && nSizeRet > MAX_SIZE) {
|
||||||
throw std::ios_base::failure("ReadCompactSize(): size too large");
|
throw std::ios_base::failure("ReadCompactSize(): size too large");
|
||||||
|
}
|
||||||
return nSizeRet;
|
return nSizeRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,6 +604,191 @@ public:
|
|||||||
template<typename I>
|
template<typename I>
|
||||||
CVarInt<I> WrapVarInt(I& n) { return CVarInt<I>(n); }
|
CVarInt<I> WrapVarInt(I& n) { return CVarInt<I>(n); }
|
||||||
|
|
||||||
|
|
||||||
|
/** Simple wrapper class to serialize objects using a formatter; used by Using(). */
|
||||||
|
template<typename Formatter, typename T>
|
||||||
|
class Wrapper
|
||||||
|
{
|
||||||
|
static_assert(std::is_lvalue_reference<T>::value, "Wrapper needs an lvalue reference type T");
|
||||||
|
protected:
|
||||||
|
T m_object;
|
||||||
|
public:
|
||||||
|
explicit Wrapper(T obj) : m_object(obj) {}
|
||||||
|
template<typename Stream> void Serialize(Stream &s) const { Formatter().Ser(s, m_object); }
|
||||||
|
template<typename Stream> void Unserialize(Stream &s) { Formatter().Unser(s, m_object); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Cause serialization/deserialization of an object to be done using a specified formatter class.
|
||||||
|
*
|
||||||
|
* To use this, you need a class Formatter that has public functions Ser(stream, const object&) for
|
||||||
|
* serialization, and Unser(stream, object&) for deserialization. Serialization routines (inside
|
||||||
|
* READWRITE, or directly with << and >> operators), can then use Using<Formatter>(object).
|
||||||
|
*
|
||||||
|
* This works by constructing a Wrapper<Formatter, T>-wrapped version of object, where T is
|
||||||
|
* const during serialization, and non-const during deserialization, which maintains const
|
||||||
|
* correctness.
|
||||||
|
*/
|
||||||
|
template<typename Formatter, typename T>
|
||||||
|
static inline Wrapper<Formatter, T&> Using(T&& t) { return Wrapper<Formatter, T&>(t); }
|
||||||
|
|
||||||
|
// #define VARINT_MODE(obj, mode) Using<VarIntFormatter<mode>>(obj)
|
||||||
|
// #define VARINT(obj) Using<VarIntFormatter<VarIntMode::DEFAULT>>(obj)
|
||||||
|
// #define COMPACTSIZE(obj) Using<CompactSizeFormatter<true>>(obj)
|
||||||
|
// #define LIMITED_STRING(obj,n) Using<LimitedStringFormatter<n>>(obj)
|
||||||
|
//
|
||||||
|
// /** Serialization wrapper class for integers in VarInt format. */
|
||||||
|
// template<VarIntMode Mode>
|
||||||
|
// struct VarIntFormatter
|
||||||
|
// {
|
||||||
|
// template<typename Stream, typename I> void Ser(Stream &s, I v)
|
||||||
|
// {
|
||||||
|
// WriteVarInt<Stream,Mode,typename std::remove_cv<I>::type>(s, v);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// template<typename Stream, typename I> void Unser(Stream& s, I& v)
|
||||||
|
// {
|
||||||
|
// v = ReadVarInt<Stream,Mode,typename std::remove_cv<I>::type>(s);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
/** Serialization wrapper class for custom integers and enums.
|
||||||
|
*
|
||||||
|
* It permits specifying the serialized size (1 to 8 bytes) and endianness.
|
||||||
|
*
|
||||||
|
* Use the big endian mode for values that are stored in memory in native
|
||||||
|
* byte order, but serialized in big endian notation. This is only intended
|
||||||
|
* to implement serializers that are compatible with existing formats, and
|
||||||
|
* its use is not recommended for new data structures.
|
||||||
|
*/
|
||||||
|
template<int Bytes, bool BigEndian = false>
|
||||||
|
struct CustomUintFormatter
|
||||||
|
{
|
||||||
|
static_assert(Bytes > 0 && Bytes <= 8, "CustomUintFormatter Bytes out of range");
|
||||||
|
static constexpr uint64_t MAX = 0xffffffffffffffff >> (8 * (8 - Bytes));
|
||||||
|
|
||||||
|
template <typename Stream, typename I> void Ser(Stream& s, I v)
|
||||||
|
{
|
||||||
|
if (v < 0 || v > MAX) throw std::ios_base::failure("CustomUintFormatter value out of range");
|
||||||
|
if (BigEndian) {
|
||||||
|
uint64_t raw = htobe64(v);
|
||||||
|
s.write(((const char*)&raw) + 8 - Bytes, Bytes);
|
||||||
|
} else {
|
||||||
|
uint64_t raw = htole64(v);
|
||||||
|
s.write((const char*)&raw, Bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Stream, typename I> void Unser(Stream& s, I& v)
|
||||||
|
{
|
||||||
|
using U = typename std::conditional<std::is_enum<I>::value, std::underlying_type<I>, std::common_type<I>>::type::type;
|
||||||
|
static_assert(std::numeric_limits<U>::max() >= MAX && std::numeric_limits<U>::min() <= 0, "Assigned type too small");
|
||||||
|
uint64_t raw = 0;
|
||||||
|
if (BigEndian) {
|
||||||
|
s.read(((char*)&raw) + 8 - Bytes, Bytes);
|
||||||
|
v = static_cast<I>(be64toh(raw));
|
||||||
|
} else {
|
||||||
|
s.read((char*)&raw, Bytes);
|
||||||
|
v = static_cast<I>(le64toh(raw));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<int Bytes> using BigEndianFormatter = CustomUintFormatter<Bytes, true>;
|
||||||
|
|
||||||
|
/** Formatter for integers in CompactSize format. */
|
||||||
|
template<bool RangeCheck>
|
||||||
|
struct CompactSizeFormatter
|
||||||
|
{
|
||||||
|
template<typename Stream, typename I>
|
||||||
|
void Unser(Stream& s, I& v)
|
||||||
|
{
|
||||||
|
uint64_t n = ReadCompactSize<Stream>(s, RangeCheck);
|
||||||
|
if (n < std::numeric_limits<I>::min() || n > std::numeric_limits<I>::max()) {
|
||||||
|
throw std::ios_base::failure("CompactSize exceeds limit of type");
|
||||||
|
}
|
||||||
|
v = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Stream, typename I>
|
||||||
|
void Ser(Stream& s, I v)
|
||||||
|
{
|
||||||
|
static_assert(std::is_unsigned<I>::value, "CompactSize only supported for unsigned integers");
|
||||||
|
static_assert(std::numeric_limits<I>::max() <= std::numeric_limits<uint64_t>::max(), "CompactSize only supports 64-bit integers and below");
|
||||||
|
|
||||||
|
WriteCompactSize<Stream>(s, v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// template<size_t Limit>
|
||||||
|
// struct LimitedStringFormatter
|
||||||
|
// {
|
||||||
|
// template<typename Stream>
|
||||||
|
// void Unser(Stream& s, std::string& v)
|
||||||
|
// {
|
||||||
|
// size_t size = ReadCompactSize(s);
|
||||||
|
// if (size > Limit) {
|
||||||
|
// throw std::ios_base::failure("String length limit exceeded");
|
||||||
|
// }
|
||||||
|
// v.resize(size);
|
||||||
|
// if (size != 0) s.read((char*)v.data(), size);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// template<typename Stream>
|
||||||
|
// void Ser(Stream& s, const std::string& v)
|
||||||
|
// {
|
||||||
|
// s << v;
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
/** Formatter to serialize/deserialize vector elements using another formatter
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* struct X {
|
||||||
|
* std::vector<uint64_t> v;
|
||||||
|
* SERIALIZE_METHODS(X, obj) { READWRITE(Using<VectorFormatter<VarInt>>(obj.v)); }
|
||||||
|
* };
|
||||||
|
* will define a struct that contains a vector of uint64_t, which is serialized
|
||||||
|
* as a vector of VarInt-encoded integers.
|
||||||
|
*
|
||||||
|
* V is not required to be an std::vector type. It works for any class that
|
||||||
|
* exposes a value_type, size, reserve, emplace_back, back, and const iterators.
|
||||||
|
*/
|
||||||
|
// template<class Formatter>
|
||||||
|
// struct VectorFormatter
|
||||||
|
// {
|
||||||
|
// template<typename Stream, typename V>
|
||||||
|
// void Ser(Stream& s, const V& v)
|
||||||
|
// {
|
||||||
|
// Formatter formatter;
|
||||||
|
// WriteCompactSize(s, v.size());
|
||||||
|
// for (const typename V::value_type& elem : v) {
|
||||||
|
// formatter.Ser(s, elem);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// template<typename Stream, typename V>
|
||||||
|
// void Unser(Stream& s, V& v)
|
||||||
|
// {
|
||||||
|
// Formatter formatter;
|
||||||
|
// v.clear();
|
||||||
|
// size_t size = ReadCompactSize(s);
|
||||||
|
// size_t allocated = 0;
|
||||||
|
// while (allocated < size) {
|
||||||
|
// // For DoS prevention, do not blindly allocate as much as the stream claims to contain.
|
||||||
|
// // Instead, allocate in 5MiB batches, so that an attacker actually needs to provide
|
||||||
|
// // X MiB of data to make us allocate X+5 Mib.
|
||||||
|
// static_assert(sizeof(typename V::value_type) <= MAX_VECTOR_ALLOCATE, "Vector element size too large");
|
||||||
|
// allocated = std::min(size, allocated + MAX_VECTOR_ALLOCATE / sizeof(typename V::value_type));
|
||||||
|
// v.reserve(allocated);
|
||||||
|
// while (v.size() < allocated) {
|
||||||
|
// v.emplace_back();
|
||||||
|
// formatter.Unser(s, v.back());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// };
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forward declarations
|
* Forward declarations
|
||||||
*/
|
*/
|
||||||
@@ -1083,17 +1355,39 @@ inline void UnserializeMany(Stream& s, Arg& arg, Args&... args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Stream, typename... Args>
|
template<typename Stream, typename... Args>
|
||||||
inline void SerReadWriteMany(Stream& s, CSerActionSerialize ser_action, Args&&... args)
|
inline void SerReadWriteMany(Stream& s, CSerActionSerialize ser_action, const Args&... args)
|
||||||
{
|
{
|
||||||
::SerializeMany(s, std::forward<Args>(args)...);
|
::SerializeMany(s, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Stream, typename... Args>
|
template<typename Stream, typename... Args>
|
||||||
inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&... args)
|
inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&&... args)
|
||||||
{
|
{
|
||||||
::UnserializeMany(s, args...);
|
::UnserializeMany(s, args...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Stream, typename Type, typename Fn>
|
||||||
|
inline void SerRead(Stream& s, CSerActionSerialize ser_action, Type&&, Fn&&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Stream, typename Type, typename Fn>
|
||||||
|
inline void SerRead(Stream& s, CSerActionUnserialize ser_action, Type&& obj, Fn&& fn)
|
||||||
|
{
|
||||||
|
fn(s, std::forward<Type>(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Stream, typename Type, typename Fn>
|
||||||
|
inline void SerWrite(Stream& s, CSerActionSerialize ser_action, Type&& obj, Fn&& fn)
|
||||||
|
{
|
||||||
|
fn(s, std::forward<Type>(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Stream, typename Type, typename Fn>
|
||||||
|
inline void SerWrite(Stream& s, CSerActionUnserialize ser_action, Type&&, Fn&&)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template<typename I>
|
template<typename I>
|
||||||
inline void WriteVarInt(CSizeComputer &s, I n)
|
inline void WriteVarInt(CSizeComputer &s, I n)
|
||||||
{
|
{
|
||||||
|
|||||||
252
src/span.h
Normal file
252
src/span.h
Normal file
@@ -0,0 +1,252 @@
|
|||||||
|
// Copyright (c) 2018-2020 The Bitcoin Core developers
|
||||||
|
// Copyright (c) 2016-2022 The Hush developers
|
||||||
|
// Distributed under the GPLv3 software license, see the accompanying
|
||||||
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
|
|
||||||
|
#ifndef BITCOIN_SPAN_H
|
||||||
|
#define BITCOIN_SPAN_H
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define CONSTEXPR_IF_NOT_DEBUG
|
||||||
|
#define ASSERT_IF_DEBUG(x) assert((x))
|
||||||
|
#else
|
||||||
|
#define CONSTEXPR_IF_NOT_DEBUG constexpr
|
||||||
|
#define ASSERT_IF_DEBUG(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#if __has_attribute(lifetimebound)
|
||||||
|
#define SPAN_ATTR_LIFETIMEBOUND [[clang::lifetimebound]]
|
||||||
|
#else
|
||||||
|
#define SPAN_ATTR_LIFETIMEBOUND
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define SPAN_ATTR_LIFETIMEBOUND
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** A Span is an object that can refer to a contiguous sequence of objects.
|
||||||
|
*
|
||||||
|
* It implements a subset of C++20's std::span.
|
||||||
|
*
|
||||||
|
* Things to be aware of when writing code that deals with Spans:
|
||||||
|
*
|
||||||
|
* - Similar to references themselves, Spans are subject to reference lifetime
|
||||||
|
* issues. The user is responsible for making sure the objects pointed to by
|
||||||
|
* a Span live as long as the Span is used. For example:
|
||||||
|
*
|
||||||
|
* std::vector<int> vec{1,2,3,4};
|
||||||
|
* Span<int> sp(vec);
|
||||||
|
* vec.push_back(5);
|
||||||
|
* printf("%i\n", sp.front()); // UB!
|
||||||
|
*
|
||||||
|
* may exhibit undefined behavior, as increasing the size of a vector may
|
||||||
|
* invalidate references.
|
||||||
|
*
|
||||||
|
* - One particular pitfall is that Spans can be constructed from temporaries,
|
||||||
|
* but this is unsafe when the Span is stored in a variable, outliving the
|
||||||
|
* temporary. For example, this will compile, but exhibits undefined behavior:
|
||||||
|
*
|
||||||
|
* Span<const int> sp(std::vector<int>{1, 2, 3});
|
||||||
|
* printf("%i\n", sp.front()); // UB!
|
||||||
|
*
|
||||||
|
* The lifetime of the vector ends when the statement it is created in ends.
|
||||||
|
* Thus the Span is left with a dangling reference, and using it is undefined.
|
||||||
|
*
|
||||||
|
* - Due to Span's automatic creation from range-like objects (arrays, and data
|
||||||
|
* types that expose a data() and size() member function), functions that
|
||||||
|
* accept a Span as input parameter can be called with any compatible
|
||||||
|
* range-like object. For example, this works:
|
||||||
|
*
|
||||||
|
* void Foo(Span<const int> arg);
|
||||||
|
*
|
||||||
|
* Foo(std::vector<int>{1, 2, 3}); // Works
|
||||||
|
*
|
||||||
|
* This is very useful in cases where a function truly does not care about the
|
||||||
|
* container, and only about having exactly a range of elements. However it
|
||||||
|
* may also be surprising to see automatic conversions in this case.
|
||||||
|
*
|
||||||
|
* When a function accepts a Span with a mutable element type, it will not
|
||||||
|
* accept temporaries; only variables or other references. For example:
|
||||||
|
*
|
||||||
|
* void FooMut(Span<int> arg);
|
||||||
|
*
|
||||||
|
* FooMut(std::vector<int>{1, 2, 3}); // Does not compile
|
||||||
|
* std::vector<int> baz{1, 2, 3};
|
||||||
|
* FooMut(baz); // Works
|
||||||
|
*
|
||||||
|
* This is similar to how functions that take (non-const) lvalue references
|
||||||
|
* as input cannot accept temporaries. This does not work either:
|
||||||
|
*
|
||||||
|
* void FooVec(std::vector<int>& arg);
|
||||||
|
* FooVec(std::vector<int>{1, 2, 3}); // Does not compile
|
||||||
|
*
|
||||||
|
* The idea is that if a function accepts a mutable reference, a meaningful
|
||||||
|
* result will be present in that variable after the call. Passing a temporary
|
||||||
|
* is useless in that context.
|
||||||
|
*/
|
||||||
|
template<typename C>
|
||||||
|
class Span
|
||||||
|
{
|
||||||
|
C* m_data;
|
||||||
|
std::size_t m_size;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct is_Span_int : public std::false_type {};
|
||||||
|
template <class T>
|
||||||
|
struct is_Span_int<Span<T>> : public std::true_type {};
|
||||||
|
template <class T>
|
||||||
|
struct is_Span : public is_Span_int<typename std::remove_cv<T>::type>{};
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr Span() noexcept : m_data(nullptr), m_size(0) {}
|
||||||
|
|
||||||
|
/** Construct a span from a begin pointer and a size.
|
||||||
|
*
|
||||||
|
* This implements a subset of the iterator-based std::span constructor in C++20,
|
||||||
|
* which is hard to implement without std::address_of.
|
||||||
|
*/
|
||||||
|
template <typename T, typename std::enable_if<std::is_convertible<T (*)[], C (*)[]>::value, int>::type = 0>
|
||||||
|
constexpr Span(T* begin, std::size_t size) noexcept : m_data(begin), m_size(size) {}
|
||||||
|
|
||||||
|
/** Construct a span from a begin and end pointer.
|
||||||
|
*
|
||||||
|
* This implements a subset of the iterator-based std::span constructor in C++20,
|
||||||
|
* which is hard to implement without std::address_of.
|
||||||
|
*/
|
||||||
|
template <typename T, typename std::enable_if<std::is_convertible<T (*)[], C (*)[]>::value, int>::type = 0>
|
||||||
|
CONSTEXPR_IF_NOT_DEBUG Span(T* begin, T* end) noexcept : m_data(begin), m_size(end - begin)
|
||||||
|
{
|
||||||
|
ASSERT_IF_DEBUG(end >= begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Implicit conversion of spans between compatible types.
|
||||||
|
*
|
||||||
|
* Specifically, if a pointer to an array of type O can be implicitly converted to a pointer to an array of type
|
||||||
|
* C, then permit implicit conversion of Span<O> to Span<C>. This matches the behavior of the corresponding
|
||||||
|
* C++20 std::span constructor.
|
||||||
|
*
|
||||||
|
* For example this means that a Span<T> can be converted into a Span<const T>.
|
||||||
|
*/
|
||||||
|
template <typename O, typename std::enable_if<std::is_convertible<O (*)[], C (*)[]>::value, int>::type = 0>
|
||||||
|
constexpr Span(const Span<O>& other) noexcept : m_data(other.m_data), m_size(other.m_size) {}
|
||||||
|
|
||||||
|
/** Default copy constructor. */
|
||||||
|
constexpr Span(const Span&) noexcept = default;
|
||||||
|
|
||||||
|
/** Default assignment operator. */
|
||||||
|
Span& operator=(const Span& other) noexcept = default;
|
||||||
|
|
||||||
|
/** Construct a Span from an array. This matches the corresponding C++20 std::span constructor. */
|
||||||
|
template <int N>
|
||||||
|
constexpr Span(C (&a)[N]) noexcept : m_data(a), m_size(N) {}
|
||||||
|
|
||||||
|
/** Construct a Span for objects with .data() and .size() (std::string, std::array, std::vector, ...).
|
||||||
|
*
|
||||||
|
* This implements a subset of the functionality provided by the C++20 std::span range-based constructor.
|
||||||
|
*
|
||||||
|
* To prevent surprises, only Spans for constant value types are supported when passing in temporaries.
|
||||||
|
* Note that this restriction does not exist when converting arrays or other Spans (see above).
|
||||||
|
*/
|
||||||
|
template <typename V>
|
||||||
|
constexpr Span(V& other SPAN_ATTR_LIFETIMEBOUND,
|
||||||
|
typename std::enable_if<!is_Span<V>::value &&
|
||||||
|
std::is_convertible<typename std::remove_pointer<decltype(std::declval<V&>().data())>::type (*)[], C (*)[]>::value &&
|
||||||
|
std::is_convertible<decltype(std::declval<V&>().size()), std::size_t>::value, std::nullptr_t>::type = nullptr)
|
||||||
|
: m_data(other.data()), m_size(other.size()){}
|
||||||
|
|
||||||
|
template <typename V>
|
||||||
|
constexpr Span(const V& other SPAN_ATTR_LIFETIMEBOUND,
|
||||||
|
typename std::enable_if<!is_Span<V>::value &&
|
||||||
|
std::is_convertible<typename std::remove_pointer<decltype(std::declval<const V&>().data())>::type (*)[], C (*)[]>::value &&
|
||||||
|
std::is_convertible<decltype(std::declval<const V&>().size()), std::size_t>::value, std::nullptr_t>::type = nullptr)
|
||||||
|
: m_data(other.data()), m_size(other.size()){}
|
||||||
|
|
||||||
|
constexpr C* data() const noexcept { return m_data; }
|
||||||
|
constexpr C* begin() const noexcept { return m_data; }
|
||||||
|
constexpr C* end() const noexcept { return m_data + m_size; }
|
||||||
|
CONSTEXPR_IF_NOT_DEBUG C& front() const noexcept
|
||||||
|
{
|
||||||
|
ASSERT_IF_DEBUG(size() > 0);
|
||||||
|
return m_data[0];
|
||||||
|
}
|
||||||
|
CONSTEXPR_IF_NOT_DEBUG C& back() const noexcept
|
||||||
|
{
|
||||||
|
ASSERT_IF_DEBUG(size() > 0);
|
||||||
|
return m_data[m_size - 1];
|
||||||
|
}
|
||||||
|
constexpr std::size_t size() const noexcept { return m_size; }
|
||||||
|
constexpr bool empty() const noexcept { return size() == 0; }
|
||||||
|
CONSTEXPR_IF_NOT_DEBUG C& operator[](std::size_t pos) const noexcept
|
||||||
|
{
|
||||||
|
ASSERT_IF_DEBUG(size() > pos);
|
||||||
|
return m_data[pos];
|
||||||
|
}
|
||||||
|
CONSTEXPR_IF_NOT_DEBUG Span<C> subspan(std::size_t offset) const noexcept
|
||||||
|
{
|
||||||
|
ASSERT_IF_DEBUG(size() >= offset);
|
||||||
|
return Span<C>(m_data + offset, m_size - offset);
|
||||||
|
}
|
||||||
|
CONSTEXPR_IF_NOT_DEBUG Span<C> subspan(std::size_t offset, std::size_t count) const noexcept
|
||||||
|
{
|
||||||
|
ASSERT_IF_DEBUG(size() >= offset + count);
|
||||||
|
return Span<C>(m_data + offset, count);
|
||||||
|
}
|
||||||
|
CONSTEXPR_IF_NOT_DEBUG Span<C> first(std::size_t count) const noexcept
|
||||||
|
{
|
||||||
|
ASSERT_IF_DEBUG(size() >= count);
|
||||||
|
return Span<C>(m_data, count);
|
||||||
|
}
|
||||||
|
CONSTEXPR_IF_NOT_DEBUG Span<C> last(std::size_t count) const noexcept
|
||||||
|
{
|
||||||
|
ASSERT_IF_DEBUG(size() >= count);
|
||||||
|
return Span<C>(m_data + m_size - count, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend constexpr bool operator==(const Span& a, const Span& b) noexcept { return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin()); }
|
||||||
|
friend constexpr bool operator!=(const Span& a, const Span& b) noexcept { return !(a == b); }
|
||||||
|
friend constexpr bool operator<(const Span& a, const Span& b) noexcept { return std::lexicographical_compare(a.begin(), a.end(), b.begin(), b.end()); }
|
||||||
|
friend constexpr bool operator<=(const Span& a, const Span& b) noexcept { return !(b < a); }
|
||||||
|
friend constexpr bool operator>(const Span& a, const Span& b) noexcept { return (b < a); }
|
||||||
|
friend constexpr bool operator>=(const Span& a, const Span& b) noexcept { return !(a < b); }
|
||||||
|
|
||||||
|
template <typename O> friend class Span;
|
||||||
|
};
|
||||||
|
|
||||||
|
// MakeSpan helps constructing a Span of the right type automatically.
|
||||||
|
/** MakeSpan for arrays: */
|
||||||
|
template <typename A, int N> Span<A> constexpr MakeSpan(A (&a)[N]) { return Span<A>(a, N); }
|
||||||
|
/** MakeSpan for temporaries / rvalue references, only supporting const output. */
|
||||||
|
template <typename V> constexpr auto MakeSpan(V&& v SPAN_ATTR_LIFETIMEBOUND) -> typename std::enable_if<!std::is_lvalue_reference<V>::value, Span<const typename std::remove_pointer<decltype(v.data())>::type>>::type { return std::forward<V>(v); }
|
||||||
|
/** MakeSpan for (lvalue) references, supporting mutable output. */
|
||||||
|
template <typename V> constexpr auto MakeSpan(V& v SPAN_ATTR_LIFETIMEBOUND) -> Span<typename std::remove_pointer<decltype(v.data())>::type> { return v; }
|
||||||
|
|
||||||
|
/** Pop the last element off a span, and return a reference to that element. */
|
||||||
|
template <typename T>
|
||||||
|
T& SpanPopBack(Span<T>& span)
|
||||||
|
{
|
||||||
|
size_t size = span.size();
|
||||||
|
ASSERT_IF_DEBUG(size > 0);
|
||||||
|
T& back = span[size - 1];
|
||||||
|
span = Span<T>(span.data(), size - 1);
|
||||||
|
return back;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper functions to safely cast to unsigned char pointers.
|
||||||
|
inline unsigned char* UCharCast(char* c) { return (unsigned char*)c; }
|
||||||
|
inline unsigned char* UCharCast(unsigned char* c) { return c; }
|
||||||
|
inline const unsigned char* UCharCast(const char* c) { return (unsigned char*)c; }
|
||||||
|
inline const unsigned char* UCharCast(const unsigned char* c) { return c; }
|
||||||
|
|
||||||
|
// Helper function to safely convert a Span to a Span<[const] unsigned char>.
|
||||||
|
template <typename T> constexpr auto UCharSpanCast(Span<T> s) -> Span<typename std::remove_pointer<decltype(UCharCast(s.data()))>::type> { return {UCharCast(s.data()), s.size()}; }
|
||||||
|
|
||||||
|
/** Like MakeSpan, but for (const) unsigned char member types only. Only works for (un)signed char containers. */
|
||||||
|
template <typename V> constexpr auto MakeUCharSpan(V&& v) -> decltype(UCharSpanCast(MakeSpan(std::forward<V>(v)))) { return UCharSpanCast(MakeSpan(std::forward<V>(v))); }
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
#include "txmempool.h"
|
#include "txmempool.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
#include <algorithm> // for std::reverse
|
#include <algorithm> // for std::reverse
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -114,12 +114,19 @@ namespace { // better to use anonymous namespace for helper routines
|
|||||||
static bool InitStratumAllowList(std::vector<CSubNet>& allowed_subnets)
|
static bool InitStratumAllowList(std::vector<CSubNet>& allowed_subnets)
|
||||||
{
|
{
|
||||||
allowed_subnets.clear();
|
allowed_subnets.clear();
|
||||||
allowed_subnets.push_back(CSubNet("127.0.0.0/8")); // always allow IPv4 local subnet
|
CNetAddr localv4, localv6;
|
||||||
allowed_subnets.push_back(CSubNet("::1")); // always allow IPv6 localhost
|
LookupHost("127.0.0.1", localv4, false);
|
||||||
|
LookupHost("::1", localv6, false);
|
||||||
|
|
||||||
|
allowed_subnets.push_back(CSubNet(localv4, 8)); // always allow IPv4 local subnet
|
||||||
|
allowed_subnets.push_back(CSubNet(localv6)); // always allow IPv6 localhost
|
||||||
if (mapMultiArgs.count("-stratumallowip")) {
|
if (mapMultiArgs.count("-stratumallowip")) {
|
||||||
const std::vector<std::string>& vAllow = mapMultiArgs["-stratumallowip"];
|
const std::vector<std::string>& vAllow = mapMultiArgs["-stratumallowip"];
|
||||||
for(const std::string& strAllow : vAllow) {
|
for(const std::string& strAllow : vAllow) {
|
||||||
CSubNet subnet(strAllow);
|
CNetAddr netaddr;
|
||||||
|
// todo: v6
|
||||||
|
LookupHost(strAllow.c_str(), netaddr, false);
|
||||||
|
CSubNet subnet(netaddr);
|
||||||
if (!subnet.IsValid()) {
|
if (!subnet.IsValid()) {
|
||||||
uiInterface.ThreadSafeMessageBox(
|
uiInterface.ThreadSafeMessageBox(
|
||||||
strprintf("Invalid -stratumallowip subnet specification: %s. Valid are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24).", strAllow),
|
strprintf("Invalid -stratumallowip subnet specification: %s. Valid are a single IP (e.g. 1.2.3.4), a network/netmask (e.g. 1.2.3.4/255.255.255.0) or a network/CIDR (e.g. 1.2.3.4/24).", strAllow),
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ public:
|
|||||||
|
|
||||||
int GetVersion() const { return nVersion; }
|
int GetVersion() const { return nVersion; }
|
||||||
int GetType() const { return nType; }
|
int GetType() const { return nType; }
|
||||||
|
size_t size() const { return stream->size(); }
|
||||||
|
void ignore(size_t size) { return stream->ignore(size); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename S>
|
template<typename S>
|
||||||
@@ -85,6 +87,70 @@ OverrideStream<S> WithVersion(S* s, int nVersion)
|
|||||||
return OverrideStream<S>(s, s->GetType(), nVersion);
|
return OverrideStream<S>(s, s->GetType(), nVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Minimal stream for overwriting and/or appending to an existing byte vector
|
||||||
|
*
|
||||||
|
* The referenced vector will grow as necessary
|
||||||
|
*/
|
||||||
|
class CVectorWriter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @param[in] nTypeIn Serialization Type
|
||||||
|
* @param[in] nVersionIn Serialization Version (including any flags)
|
||||||
|
* @param[in] vchDataIn Referenced byte vector to overwrite/append
|
||||||
|
* @param[in] nPosIn Starting position. Vector index where writes should start. The vector will initially
|
||||||
|
* grow as necessary to max(nPosIn, vec.size()). So to append, use vec.size().
|
||||||
|
*/
|
||||||
|
CVectorWriter(int nTypeIn, int nVersionIn, std::vector<unsigned char>& vchDataIn, size_t nPosIn) : nType(nTypeIn), nVersion(nVersionIn), vchData(vchDataIn), nPos(nPosIn)
|
||||||
|
{
|
||||||
|
if(nPos > vchData.size())
|
||||||
|
vchData.resize(nPos);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* (other params same as above)
|
||||||
|
* @param[in] args A list of items to serialize starting at nPosIn.
|
||||||
|
*/
|
||||||
|
template <typename... Args>
|
||||||
|
CVectorWriter(int nTypeIn, int nVersionIn, std::vector<unsigned char>& vchDataIn, size_t nPosIn, Args&&... args) : CVectorWriter(nTypeIn, nVersionIn, vchDataIn, nPosIn)
|
||||||
|
{
|
||||||
|
::SerializeMany(*this, std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
void write(const char* pch, size_t nSize)
|
||||||
|
{
|
||||||
|
assert(nPos <= vchData.size());
|
||||||
|
size_t nOverwrite = std::min(nSize, vchData.size() - nPos);
|
||||||
|
if (nOverwrite) {
|
||||||
|
memcpy(vchData.data() + nPos, reinterpret_cast<const unsigned char*>(pch), nOverwrite);
|
||||||
|
}
|
||||||
|
if (nOverwrite < nSize) {
|
||||||
|
vchData.insert(vchData.end(), reinterpret_cast<const unsigned char*>(pch) + nOverwrite, reinterpret_cast<const unsigned char*>(pch) + nSize);
|
||||||
|
}
|
||||||
|
nPos += nSize;
|
||||||
|
}
|
||||||
|
template<typename T>
|
||||||
|
CVectorWriter& operator<<(const T& obj)
|
||||||
|
{
|
||||||
|
// Serialize to this stream
|
||||||
|
::Serialize(*this, obj);
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
int GetVersion() const
|
||||||
|
{
|
||||||
|
return nVersion;
|
||||||
|
}
|
||||||
|
int GetType() const
|
||||||
|
{
|
||||||
|
return nType;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
const int nType;
|
||||||
|
const int nVersion;
|
||||||
|
std::vector<unsigned char>& vchData;
|
||||||
|
size_t nPos;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/** Double ended buffer combining vector and stream-like interfaces.
|
/** Double ended buffer combining vector and stream-like interfaces.
|
||||||
*
|
*
|
||||||
* >> and << read and write unformatted data using the above serialization templates.
|
* >> and << read and write unformatted data using the above serialization templates.
|
||||||
@@ -355,7 +421,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
CBaseDataStream& operator>>(T& obj)
|
CBaseDataStream& operator>>(T&& obj)
|
||||||
{
|
{
|
||||||
// Unserialize from this stream
|
// Unserialize from this stream
|
||||||
::Unserialize(*this, obj);
|
::Unserialize(*this, obj);
|
||||||
@@ -547,19 +613,20 @@ protected:
|
|||||||
readNow = nAvail;
|
readNow = nAvail;
|
||||||
if (readNow == 0)
|
if (readNow == 0)
|
||||||
return false;
|
return false;
|
||||||
size_t read = fread((void*)&vchBuf[pos], 1, readNow, src);
|
size_t nBytes = fread((void*)&vchBuf[pos], 1, readNow, src);
|
||||||
if (read == 0) {
|
if (nBytes == 0) {
|
||||||
throw std::ios_base::failure(feof(src) ? "CBufferedFile::Fill: end of file" : "CBufferedFile::Fill: fread failed");
|
throw std::ios_base::failure(feof(src) ? "CBufferedFile::Fill: end of file" : "CBufferedFile::Fill: fread failed");
|
||||||
} else {
|
|
||||||
nSrcPos += read;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
nSrcPos += nBytes;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CBufferedFile(FILE *fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn) :
|
CBufferedFile(FILE *fileIn, uint64_t nBufSize, uint64_t nRewindIn, int nTypeIn, int nVersionIn) :
|
||||||
nType(nTypeIn), nVersion(nVersionIn), nSrcPos(0), nReadPos(0), nReadLimit((uint64_t)(-1)), nRewind(nRewindIn), vchBuf(nBufSize, 0)
|
nType(nTypeIn), nVersion(nVersionIn), nSrcPos(0), nReadPos(0), nReadLimit((uint64_t)(-1)), nRewind(nRewindIn), vchBuf(nBufSize, 0)
|
||||||
{
|
{
|
||||||
|
if (nRewindIn >= nBufSize)
|
||||||
|
throw std::ios_base::failure("Rewind limit must be less than buffer size");
|
||||||
src = fileIn;
|
src = fileIn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -594,8 +661,6 @@ public:
|
|||||||
|
|
||||||
if (nSize + nReadPos > nReadLimit)
|
if (nSize + nReadPos > nReadLimit)
|
||||||
throw std::ios_base::failure("Read attempted past buffer limit");
|
throw std::ios_base::failure("Read attempted past buffer limit");
|
||||||
if (nSize + nRewind > vchBuf.size())
|
|
||||||
throw std::ios_base::failure("Read larger than buffer size");
|
|
||||||
while (nSize > 0) {
|
while (nSize > 0) {
|
||||||
if (nReadPos == nSrcPos)
|
if (nReadPos == nSrcPos)
|
||||||
Fill();
|
Fill();
|
||||||
@@ -619,16 +684,19 @@ public:
|
|||||||
|
|
||||||
// rewind to a given reading position
|
// rewind to a given reading position
|
||||||
bool SetPos(uint64_t nPos) {
|
bool SetPos(uint64_t nPos) {
|
||||||
nReadPos = nPos;
|
size_t bufsize = vchBuf.size();
|
||||||
if (nReadPos + nRewind < nSrcPos) {
|
if (nPos + bufsize < nSrcPos) {
|
||||||
nReadPos = nSrcPos - nRewind;
|
// rewinding too far, rewind as far as possible
|
||||||
|
nReadPos = nSrcPos - bufsize;
|
||||||
return false;
|
return false;
|
||||||
} else if (nReadPos > nSrcPos) {
|
}
|
||||||
|
if (nPos > nSrcPos) {
|
||||||
|
// can't go this far forward, go as far as possible
|
||||||
nReadPos = nSrcPos;
|
nReadPos = nSrcPos;
|
||||||
return false;
|
return false;
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
nReadPos = nPos;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Seek(uint64_t nPos) {
|
bool Seek(uint64_t nPos) {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <boost/thread.hpp>
|
#include <boost/thread.hpp>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include "netbase.h"
|
#include "netbase.h"
|
||||||
#include "chainparams.h"
|
#include "chainparams.h"
|
||||||
#include "tinyformat.h"
|
#include "tinyformat.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
|
|
||||||
#define NODE_NONE 0
|
#define NODE_NONE 0
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#include "rpc/protocol.h"
|
#include "rpc/protocol.h"
|
||||||
#include "txdb.h"
|
#include "txdb.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "utiltime.h"
|
#include "utiltime.h"
|
||||||
#include "consensus/validation.h"
|
#include "consensus/validation.h"
|
||||||
#include "primitives/transaction.h"
|
#include "primitives/transaction.h"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// Distributed under the GPLv3 software license, see the accompanying
|
// Distributed under the GPLv3 software license, see the accompanying
|
||||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
|
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "test/test_bitcoin.h"
|
#include "test/test_bitcoin.h"
|
||||||
|
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#include "test/test_bitcoin.h"
|
#include "test/test_bitcoin.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
|
|
||||||
#include <univalue.h>
|
#include <univalue.h>
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// Distributed under the GPLv3 software license, see the accompanying
|
// Distributed under the GPLv3 software license, see the accompanying
|
||||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
|
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "test/test_bitcoin.h"
|
#include "test/test_bitcoin.h"
|
||||||
|
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include "key_io.h"
|
#include "key_io.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "test/test_bitcoin.h"
|
#include "test/test_bitcoin.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#include "streams.h"
|
#include "streams.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "test/test_bitcoin.h"
|
#include "test/test_bitcoin.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "script/standard.h"
|
#include "script/standard.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "test/test_bitcoin.h"
|
#include "test/test_bitcoin.h"
|
||||||
#include "consensus/validation.h"
|
#include "consensus/validation.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
// Distributed under the GPLv3 software license, see the accompanying
|
// Distributed under the GPLv3 software license, see the accompanying
|
||||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
|
|
||||||
#include <utilstrencodings.h>
|
#include <util/strencodings.h>
|
||||||
#include <test/test_bitcoin.h>
|
#include <test/test_bitcoin.h>
|
||||||
#include <zcash/NoteEncryption.hpp>
|
#include <zcash/NoteEncryption.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#include "crypto/hmac_sha256.h"
|
#include "crypto/hmac_sha256.h"
|
||||||
#include "crypto/hmac_sha512.h"
|
#include "crypto/hmac_sha512.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "test/test_bitcoin.h"
|
#include "test/test_bitcoin.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
// file COPYING or https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
|
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "test/test_bitcoin.h"
|
#include "test/test_bitcoin.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include "script/script.h"
|
#include "script/script.h"
|
||||||
#include "uint256.h"
|
#include "uint256.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "test/test_bitcoin.h"
|
#include "test/test_bitcoin.h"
|
||||||
#include "zcash/Address.hpp"
|
#include "zcash/Address.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|||||||
@@ -121,17 +121,6 @@ BOOST_AUTO_TEST_CASE(netbase_lookupnumeric)
|
|||||||
BOOST_CHECK(TestParse(":::", ""));
|
BOOST_CHECK(TestParse(":::", ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(onioncat_test)
|
|
||||||
{
|
|
||||||
// values from https://web.archive.org/web/20121122003543/http://www.cypherpunk.at/onioncat/wiki/OnionCat
|
|
||||||
CNetAddr addr1("5wyqrzbvrdsumnok.onion");
|
|
||||||
CNetAddr addr2("FD87:D87E:EB43:edb1:8e4:3588:e546:35ca");
|
|
||||||
BOOST_CHECK(addr1 == addr2);
|
|
||||||
BOOST_CHECK(addr1.IsTor());
|
|
||||||
BOOST_CHECK(addr1.ToStringIP() == "5wyqrzbvrdsumnok.onion");
|
|
||||||
BOOST_CHECK(addr1.IsRoutable());
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(subnet_test)
|
BOOST_AUTO_TEST_CASE(subnet_test)
|
||||||
{
|
{
|
||||||
BOOST_CHECK(CSubNet("1.2.3.0/24") == CSubNet("1.2.3.0/255.255.255.0"));
|
BOOST_CHECK(CSubNet("1.2.3.0/24") == CSubNet("1.2.3.0/255.255.255.0"));
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#include "rpc/client.h"
|
#include "rpc/client.h"
|
||||||
#include "key_io.h"
|
#include "key_io.h"
|
||||||
#include "netbase.h"
|
#include "netbase.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "test/test_bitcoin.h"
|
#include "test/test_bitcoin.h"
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#include "streams.h"
|
#include "streams.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "test/test_bitcoin.h"
|
#include "test/test_bitcoin.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include "primitives/transaction.h"
|
#include "primitives/transaction.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
#include "utilmoneystr.h"
|
#include "utilmoneystr.h"
|
||||||
#include "test/test_bitcoin.h"
|
#include "test/test_bitcoin.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
#include "ui_interface.h"
|
#include "ui_interface.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "utilstrencodings.h"
|
#include "util/strencodings.h"
|
||||||
|
|
||||||
CTimeWarning timeWarning;
|
CTimeWarning timeWarning;
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user