warnet 0.9.9__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. test_framework/__init__.py +0 -0
  2. test_framework/address.py +227 -0
  3. test_framework/authproxy.py +189 -0
  4. test_framework/bdb.py +151 -0
  5. test_framework/bip340_test_vectors.csv +16 -0
  6. test_framework/blockfilter.py +49 -0
  7. test_framework/blocktools.py +236 -0
  8. test_framework/coverage.py +113 -0
  9. test_framework/descriptors.py +64 -0
  10. test_framework/ellswift.py +163 -0
  11. test_framework/ellswift_decode_test_vectors.csv +77 -0
  12. test_framework/key.py +351 -0
  13. test_framework/messages.py +1906 -0
  14. test_framework/muhash.py +110 -0
  15. test_framework/netutil.py +160 -0
  16. test_framework/p2p.py +807 -0
  17. test_framework/psbt.py +140 -0
  18. test_framework/ripemd160.py +130 -0
  19. test_framework/script.py +928 -0
  20. test_framework/script_util.py +127 -0
  21. test_framework/secp256k1.py +346 -0
  22. test_framework/segwit_addr.py +141 -0
  23. test_framework/siphash.py +65 -0
  24. test_framework/socks5.py +162 -0
  25. test_framework/test_framework.py +1010 -0
  26. test_framework/test_node.py +892 -0
  27. test_framework/test_shell.py +78 -0
  28. test_framework/util.py +551 -0
  29. test_framework/wallet.py +426 -0
  30. test_framework/wallet_util.py +143 -0
  31. test_framework/xswiftec_inv_test_vectors.csv +33 -0
  32. warnet/__init__.py +0 -0
  33. warnet/backend/__init__.py +0 -0
  34. warnet/backend/kubernetes_backend.py +881 -0
  35. warnet/cli/__init__.py +0 -0
  36. warnet/cli/bitcoin.py +55 -0
  37. warnet/cli/cluster.py +193 -0
  38. warnet/cli/graph.py +127 -0
  39. warnet/cli/image.py +28 -0
  40. warnet/cli/image_build.py +97 -0
  41. warnet/cli/ln.py +39 -0
  42. warnet/cli/main.py +98 -0
  43. warnet/cli/network.py +159 -0
  44. warnet/cli/rpc.py +35 -0
  45. warnet/cli/scenarios.py +110 -0
  46. warnet/cln.py +196 -0
  47. warnet/graphs/__init__.py +3 -0
  48. warnet/graphs/default.graphml +81 -0
  49. warnet/lnchannel.py +148 -0
  50. warnet/lnd.py +191 -0
  51. warnet/lnnode.py +99 -0
  52. warnet/logging_config/config.json +64 -0
  53. warnet/scenarios/__init__.py +0 -0
  54. warnet/scenarios/ln_init.py +186 -0
  55. warnet/scenarios/miner_std.py +78 -0
  56. warnet/scenarios/sens_relay.py +43 -0
  57. warnet/scenarios/tx_flood.py +71 -0
  58. warnet/scenarios/utils.py +5 -0
  59. warnet/schema/__init__.py +3 -0
  60. warnet/schema/graph_schema.json +80 -0
  61. warnet/scripts/quick_start.sh +179 -0
  62. warnet/server.py +606 -0
  63. warnet/services.py +36 -0
  64. warnet/status.py +9 -0
  65. warnet/tank.py +194 -0
  66. warnet/templates/Dockerfile +88 -0
  67. warnet/templates/Dockerfile_sidecar +12 -0
  68. warnet/templates/__init__.py +3 -0
  69. warnet/templates/addrman.patch +51 -0
  70. warnet/templates/addrman_observer_config.toml +8 -0
  71. warnet/templates/archive/fluent.conf +28 -0
  72. warnet/templates/docker_entrypoint.sh +47 -0
  73. warnet/templates/entrypoint.sh +43 -0
  74. warnet/templates/fork_observer_config.toml +31 -0
  75. warnet/templates/grafana-provisioning/dashboards/10619_rev1.json +1782 -0
  76. warnet/templates/grafana-provisioning/dashboards/10619_rev2.json +1260 -0
  77. warnet/templates/grafana-provisioning/dashboards/bitcoin_rpc_scraper.json +340 -0
  78. warnet/templates/grafana-provisioning/dashboards/dashboards.yml +11 -0
  79. warnet/templates/grafana-provisioning/datasources/loki.yml +11 -0
  80. warnet/templates/grafana-provisioning/datasources/prometheus.yml +10 -0
  81. warnet/templates/isroutable.patch +14 -0
  82. warnet/templates/k8s/connect_logging.sh +8 -0
  83. warnet/templates/k8s/grafana/values.yaml +13 -0
  84. warnet/templates/k8s/install_logging.sh +13 -0
  85. warnet/templates/k8s/loki/values.yaml +15 -0
  86. warnet/templates/rpc/Dockerfile_rpc +29 -0
  87. warnet/templates/rpc/Dockerfile_rpc.dockerignore +16 -0
  88. warnet/templates/rpc/Dockerfile_rpc_dev +32 -0
  89. warnet/templates/rpc/entrypoint.sh +38 -0
  90. warnet/templates/rpc/livenessProbe.sh +7 -0
  91. warnet/templates/rpc/namespace.yaml +13 -0
  92. warnet/templates/rpc/rbac-config.yaml +60 -0
  93. warnet/templates/rpc/warnet-rpc-service.yaml +21 -0
  94. warnet/templates/rpc/warnet-rpc-statefulset-dev.yaml +49 -0
  95. warnet/templates/rpc/warnet-rpc-statefulset.yaml +23 -0
  96. warnet/templates/tor/Dockerfile_tor_da +18 -0
  97. warnet/templates/tor/Dockerfile_tor_relay +17 -0
  98. warnet/templates/tor/tor-entrypoint.sh +7 -0
  99. warnet/templates/tor/tor-keys/authority_certificate +45 -0
  100. warnet/templates/tor/tor-keys/authority_identity_key +41 -0
  101. warnet/templates/tor/tor-keys/authority_signing_key +27 -0
  102. warnet/templates/tor/tor-keys/ed25519_master_id_public_key +0 -0
  103. warnet/templates/tor/tor-keys/ed25519_master_id_secret_key +0 -0
  104. warnet/templates/tor/tor-keys/ed25519_signing_cert +0 -0
  105. warnet/templates/tor/tor-keys/ed25519_signing_secret_key +0 -0
  106. warnet/templates/tor/tor-keys/secret_id_key +15 -0
  107. warnet/templates/tor/tor-keys/secret_onion_key +15 -0
  108. warnet/templates/tor/tor-keys/secret_onion_key_ntor +0 -0
  109. warnet/templates/tor/torrc +34 -0
  110. warnet/templates/tor/torrc.da +41 -0
  111. warnet/templates/tor/torrc.relay +37 -0
  112. warnet/test_framework_bridge.py +406 -0
  113. warnet/utils.py +481 -0
  114. warnet/warnet.py +286 -0
  115. warnet-0.9.9.dist-info/LICENSE +21 -0
  116. warnet-0.9.9.dist-info/METADATA +88 -0
  117. warnet-0.9.9.dist-info/RECORD +120 -0
  118. warnet-0.9.9.dist-info/WHEEL +5 -0
  119. warnet-0.9.9.dist-info/entry_points.txt +3 -0
  120. warnet-0.9.9.dist-info/top_level.txt +2 -0
File without changes
@@ -0,0 +1,227 @@
1
+ #!/usr/bin/env python3
2
+ # Copyright (c) 2016-2022 The Bitcoin Core developers
3
+ # Distributed under the MIT software license, see the accompanying
4
+ # file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
+ """Encode and decode Bitcoin addresses.
6
+
7
+ - base58 P2PKH and P2SH addresses.
8
+ - bech32 segwit v0 P2WPKH and P2WSH addresses.
9
+ - bech32m segwit v1 P2TR addresses."""
10
+
11
+ import enum
12
+ import unittest
13
+
14
+ from .script import (
15
+ CScript,
16
+ OP_0,
17
+ OP_TRUE,
18
+ hash160,
19
+ hash256,
20
+ sha256,
21
+ taproot_construct,
22
+ )
23
+ from .util import assert_equal
24
+ from test_framework.script_util import (
25
+ keyhash_to_p2pkh_script,
26
+ program_to_witness_script,
27
+ scripthash_to_p2sh_script,
28
+ )
29
+ from test_framework.segwit_addr import (
30
+ decode_segwit_address,
31
+ encode_segwit_address,
32
+ )
33
+
34
+
35
+ ADDRESS_BCRT1_UNSPENDABLE = 'bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj'
36
+ ADDRESS_BCRT1_UNSPENDABLE_DESCRIPTOR = 'addr(bcrt1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3xueyj)#juyq9d97'
37
+ # Coins sent to this address can be spent with a witness stack of just OP_TRUE
38
+ ADDRESS_BCRT1_P2WSH_OP_TRUE = 'bcrt1qft5p2uhsdcdc3l2ua4ap5qqfg4pjaqlp250x7us7a8qqhrxrxfsqseac85'
39
+
40
+
41
+ class AddressType(enum.Enum):
42
+ bech32 = 'bech32'
43
+ p2sh_segwit = 'p2sh-segwit'
44
+ legacy = 'legacy' # P2PKH
45
+
46
+
47
+ b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
48
+
49
+
50
+ def create_deterministic_address_bcrt1_p2tr_op_true():
51
+ """
52
+ Generates a deterministic bech32m address (segwit v1 output) that
53
+ can be spent with a witness stack of OP_TRUE and the control block
54
+ with internal public key (script-path spending).
55
+
56
+ Returns a tuple with the generated address and the internal key.
57
+ """
58
+ internal_key = (1).to_bytes(32, 'big')
59
+ address = output_key_to_p2tr(taproot_construct(internal_key, [(None, CScript([OP_TRUE]))]).output_pubkey)
60
+ assert_equal(address, 'bcrt1p9yfmy5h72durp7zrhlw9lf7jpwjgvwdg0jr0lqmmjtgg83266lqsekaqka')
61
+ return (address, internal_key)
62
+
63
+
64
+ def byte_to_base58(b, version):
65
+ result = ''
66
+ b = bytes([version]) + b # prepend version
67
+ b += hash256(b)[:4] # append checksum
68
+ value = int.from_bytes(b, 'big')
69
+ while value > 0:
70
+ result = b58chars[value % 58] + result
71
+ value //= 58
72
+ while b[0] == 0:
73
+ result = b58chars[0] + result
74
+ b = b[1:]
75
+ return result
76
+
77
+
78
+ def base58_to_byte(s):
79
+ """Converts a base58-encoded string to its data and version.
80
+
81
+ Throws if the base58 checksum is invalid."""
82
+ if not s:
83
+ return b''
84
+ n = 0
85
+ for c in s:
86
+ n *= 58
87
+ assert c in b58chars
88
+ digit = b58chars.index(c)
89
+ n += digit
90
+ h = '%x' % n
91
+ if len(h) % 2:
92
+ h = '0' + h
93
+ res = n.to_bytes((n.bit_length() + 7) // 8, 'big')
94
+ pad = 0
95
+ for c in s:
96
+ if c == b58chars[0]:
97
+ pad += 1
98
+ else:
99
+ break
100
+ res = b'\x00' * pad + res
101
+
102
+ if hash256(res[:-4])[:4] != res[-4:]:
103
+ raise ValueError('Invalid Base58Check checksum')
104
+
105
+ return res[1:-4], int(res[0])
106
+
107
+
108
+ def keyhash_to_p2pkh(hash, main=False):
109
+ assert len(hash) == 20
110
+ version = 0 if main else 111
111
+ return byte_to_base58(hash, version)
112
+
113
+ def scripthash_to_p2sh(hash, main=False):
114
+ assert len(hash) == 20
115
+ version = 5 if main else 196
116
+ return byte_to_base58(hash, version)
117
+
118
+ def key_to_p2pkh(key, main=False):
119
+ key = check_key(key)
120
+ return keyhash_to_p2pkh(hash160(key), main)
121
+
122
+ def script_to_p2sh(script, main=False):
123
+ script = check_script(script)
124
+ return scripthash_to_p2sh(hash160(script), main)
125
+
126
+ def key_to_p2sh_p2wpkh(key, main=False):
127
+ key = check_key(key)
128
+ p2shscript = CScript([OP_0, hash160(key)])
129
+ return script_to_p2sh(p2shscript, main)
130
+
131
+ def program_to_witness(version, program, main=False):
132
+ if (type(program) is str):
133
+ program = bytes.fromhex(program)
134
+ assert 0 <= version <= 16
135
+ assert 2 <= len(program) <= 40
136
+ assert version > 0 or len(program) in [20, 32]
137
+ return encode_segwit_address("bc" if main else "bcrt", version, program)
138
+
139
+ def script_to_p2wsh(script, main=False):
140
+ script = check_script(script)
141
+ return program_to_witness(0, sha256(script), main)
142
+
143
+ def key_to_p2wpkh(key, main=False):
144
+ key = check_key(key)
145
+ return program_to_witness(0, hash160(key), main)
146
+
147
+ def script_to_p2sh_p2wsh(script, main=False):
148
+ script = check_script(script)
149
+ p2shscript = CScript([OP_0, sha256(script)])
150
+ return script_to_p2sh(p2shscript, main)
151
+
152
+ def output_key_to_p2tr(key, main=False):
153
+ assert len(key) == 32
154
+ return program_to_witness(1, key, main)
155
+
156
+ def check_key(key):
157
+ if (type(key) is str):
158
+ key = bytes.fromhex(key) # Assuming this is hex string
159
+ if (type(key) is bytes and (len(key) == 33 or len(key) == 65)):
160
+ return key
161
+ assert False
162
+
163
+ def check_script(script):
164
+ if (type(script) is str):
165
+ script = bytes.fromhex(script) # Assuming this is hex string
166
+ if (type(script) is bytes or type(script) is CScript):
167
+ return script
168
+ assert False
169
+
170
+
171
+ def bech32_to_bytes(address):
172
+ hrp = address.split('1')[0]
173
+ if hrp not in ['bc', 'tb', 'bcrt']:
174
+ return (None, None)
175
+ version, payload = decode_segwit_address(hrp, address)
176
+ if version is None:
177
+ return (None, None)
178
+ return version, bytearray(payload)
179
+
180
+
181
+ def address_to_scriptpubkey(address):
182
+ """Converts a given address to the corresponding output script (scriptPubKey)."""
183
+ version, payload = bech32_to_bytes(address)
184
+ if version is not None:
185
+ return program_to_witness_script(version, payload) # testnet segwit scriptpubkey
186
+ payload, version = base58_to_byte(address)
187
+ if version == 111: # testnet pubkey hash
188
+ return keyhash_to_p2pkh_script(payload)
189
+ elif version == 196: # testnet script hash
190
+ return scripthash_to_p2sh_script(payload)
191
+ # TODO: also support other address formats
192
+ else:
193
+ assert False
194
+
195
+
196
+ class TestFrameworkScript(unittest.TestCase):
197
+ def test_base58encodedecode(self):
198
+ def check_base58(data, version):
199
+ self.assertEqual(base58_to_byte(byte_to_base58(data, version)), (data, version))
200
+
201
+ check_base58(bytes.fromhex('1f8ea1702a7bd4941bca0941b852c4bbfedb2e05'), 111)
202
+ check_base58(bytes.fromhex('3a0b05f4d7f66c3ba7009f453530296c845cc9cf'), 111)
203
+ check_base58(bytes.fromhex('41c1eaf111802559bad61b60d62b1f897c63928a'), 111)
204
+ check_base58(bytes.fromhex('0041c1eaf111802559bad61b60d62b1f897c63928a'), 111)
205
+ check_base58(bytes.fromhex('000041c1eaf111802559bad61b60d62b1f897c63928a'), 111)
206
+ check_base58(bytes.fromhex('00000041c1eaf111802559bad61b60d62b1f897c63928a'), 111)
207
+ check_base58(bytes.fromhex('1f8ea1702a7bd4941bca0941b852c4bbfedb2e05'), 0)
208
+ check_base58(bytes.fromhex('3a0b05f4d7f66c3ba7009f453530296c845cc9cf'), 0)
209
+ check_base58(bytes.fromhex('41c1eaf111802559bad61b60d62b1f897c63928a'), 0)
210
+ check_base58(bytes.fromhex('0041c1eaf111802559bad61b60d62b1f897c63928a'), 0)
211
+ check_base58(bytes.fromhex('000041c1eaf111802559bad61b60d62b1f897c63928a'), 0)
212
+ check_base58(bytes.fromhex('00000041c1eaf111802559bad61b60d62b1f897c63928a'), 0)
213
+
214
+
215
+ def test_bech32_decode(self):
216
+ def check_bech32_decode(payload, version):
217
+ hrp = "tb"
218
+ self.assertEqual(bech32_to_bytes(encode_segwit_address(hrp, version, payload)), (version, payload))
219
+
220
+ check_bech32_decode(bytes.fromhex('36e3e2a33f328de12e4b43c515a75fba2632ecc3'), 0)
221
+ check_bech32_decode(bytes.fromhex('823e9790fc1d1782321140d4f4aa61aabd5e045b'), 0)
222
+ check_bech32_decode(bytes.fromhex('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 1)
223
+ check_bech32_decode(bytes.fromhex('39cf8ebd95134f431c39db0220770bd127f5dd3cc103c988b7dcd577ae34e354'), 1)
224
+ check_bech32_decode(bytes.fromhex('708244006d27c757f6f1fc6f853b6ec26268b727866f7ce632886e34eb5839a3'), 1)
225
+ check_bech32_decode(bytes.fromhex('616211ab00dffe0adcb6ce258d6d3fd8cbd901e2'), 0)
226
+ check_bech32_decode(bytes.fromhex('b6a7c98b482d7fb21c9fa8e65692a0890410ff22'), 0)
227
+ check_bech32_decode(bytes.fromhex('f0c2109cb1008cfa7b5a09cc56f7267cd8e50929'), 0)
@@ -0,0 +1,189 @@
1
+ # Copyright (c) 2011 Jeff Garzik
2
+ #
3
+ # Previous copyright, from python-jsonrpc/jsonrpc/proxy.py:
4
+ #
5
+ # Copyright (c) 2007 Jan-Klaas Kollhof
6
+ #
7
+ # This file is part of jsonrpc.
8
+ #
9
+ # jsonrpc is free software; you can redistribute it and/or modify
10
+ # it under the terms of the GNU Lesser General Public License as published by
11
+ # the Free Software Foundation; either version 2.1 of the License, or
12
+ # (at your option) any later version.
13
+ #
14
+ # This software is distributed in the hope that it will be useful,
15
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ # GNU Lesser General Public License for more details.
18
+ #
19
+ # You should have received a copy of the GNU Lesser General Public License
20
+ # along with this software; if not, write to the Free Software
21
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
+ """HTTP proxy for opening RPC connection to bitcoind.
23
+
24
+ AuthServiceProxy has the following improvements over python-jsonrpc's
25
+ ServiceProxy class:
26
+
27
+ - HTTP connections persist for the life of the AuthServiceProxy object
28
+ (if server supports HTTP/1.1)
29
+ - sends protocol 'version', per JSON-RPC 1.1
30
+ - sends proper, incrementing 'id'
31
+ - sends Basic HTTP authentication headers
32
+ - parses all JSON numbers that look like floats as Decimal
33
+ - uses standard Python json lib
34
+ """
35
+
36
+ import base64
37
+ import decimal
38
+ from http import HTTPStatus
39
+ import http.client
40
+ import json
41
+ import logging
42
+ import pathlib
43
+ import socket
44
+ import time
45
+ import urllib.parse
46
+
47
+ HTTP_TIMEOUT = 30
48
+ USER_AGENT = "AuthServiceProxy/0.1"
49
+
50
+ log = logging.getLogger("BitcoinRPC")
51
+
52
+ class JSONRPCException(Exception):
53
+ def __init__(self, rpc_error, http_status=None):
54
+ try:
55
+ errmsg = '%(message)s (%(code)i)' % rpc_error
56
+ except (KeyError, TypeError):
57
+ errmsg = ''
58
+ super().__init__(errmsg)
59
+ self.error = rpc_error
60
+ self.http_status = http_status
61
+
62
+
63
+ def serialization_fallback(o):
64
+ if isinstance(o, decimal.Decimal):
65
+ return str(o)
66
+ if isinstance(o, pathlib.Path):
67
+ return str(o)
68
+ raise TypeError(repr(o) + " is not JSON serializable")
69
+
70
+ class AuthServiceProxy():
71
+ __id_count = 0
72
+
73
+ # ensure_ascii: escape unicode as \uXXXX, passed to json.dumps
74
+ def __init__(self, service_url, service_name=None, timeout=HTTP_TIMEOUT, connection=None, ensure_ascii=True):
75
+ self.__service_url = service_url
76
+ self._service_name = service_name
77
+ self.ensure_ascii = ensure_ascii # can be toggled on the fly by tests
78
+ self.__url = urllib.parse.urlparse(service_url)
79
+ user = None if self.__url.username is None else self.__url.username.encode('utf8')
80
+ passwd = None if self.__url.password is None else self.__url.password.encode('utf8')
81
+ authpair = user + b':' + passwd
82
+ self.__auth_header = b'Basic ' + base64.b64encode(authpair)
83
+ # clamp the socket timeout, since larger values can cause an
84
+ # "Invalid argument" exception in Python's HTTP(S) client
85
+ # library on some operating systems (e.g. OpenBSD, FreeBSD)
86
+ self.timeout = min(timeout, 2147483)
87
+ self._set_conn(connection)
88
+
89
+ def __getattr__(self, name):
90
+ if name.startswith('__') and name.endswith('__'):
91
+ # Python internal stuff
92
+ raise AttributeError
93
+ if self._service_name is not None:
94
+ name = "%s.%s" % (self._service_name, name)
95
+ return AuthServiceProxy(self.__service_url, name, connection=self.__conn)
96
+
97
+ def _request(self, method, path, postdata):
98
+ '''
99
+ Do a HTTP request.
100
+ '''
101
+ headers = {'Host': self.__url.hostname,
102
+ 'User-Agent': USER_AGENT,
103
+ 'Authorization': self.__auth_header,
104
+ 'Content-type': 'application/json'}
105
+ self.__conn.request(method, path, postdata, headers)
106
+ return self._get_response()
107
+
108
+ def get_request(self, *args, **argsn):
109
+ AuthServiceProxy.__id_count += 1
110
+
111
+ log.debug("-{}-> {} {}".format(
112
+ AuthServiceProxy.__id_count,
113
+ self._service_name,
114
+ json.dumps(args or argsn, default=serialization_fallback, ensure_ascii=self.ensure_ascii),
115
+ ))
116
+ if args and argsn:
117
+ params = dict(args=args, **argsn)
118
+ else:
119
+ params = args or argsn
120
+ return {'version': '1.1',
121
+ 'method': self._service_name,
122
+ 'params': params,
123
+ 'id': AuthServiceProxy.__id_count}
124
+
125
+ def __call__(self, *args, **argsn):
126
+ postdata = json.dumps(self.get_request(*args, **argsn), default=serialization_fallback, ensure_ascii=self.ensure_ascii)
127
+ response, status = self._request('POST', self.__url.path, postdata.encode('utf-8'))
128
+ if response['error'] is not None:
129
+ raise JSONRPCException(response['error'], status)
130
+ elif 'result' not in response:
131
+ raise JSONRPCException({
132
+ 'code': -343, 'message': 'missing JSON-RPC result'}, status)
133
+ elif status != HTTPStatus.OK:
134
+ raise JSONRPCException({
135
+ 'code': -342, 'message': 'non-200 HTTP status code but no JSON-RPC error'}, status)
136
+ else:
137
+ return response['result']
138
+
139
+ def batch(self, rpc_call_list):
140
+ postdata = json.dumps(list(rpc_call_list), default=serialization_fallback, ensure_ascii=self.ensure_ascii)
141
+ log.debug("--> " + postdata)
142
+ response, status = self._request('POST', self.__url.path, postdata.encode('utf-8'))
143
+ if status != HTTPStatus.OK:
144
+ raise JSONRPCException({
145
+ 'code': -342, 'message': 'non-200 HTTP status code but no JSON-RPC error'}, status)
146
+ return response
147
+
148
+ def _get_response(self):
149
+ req_start_time = time.time()
150
+ try:
151
+ http_response = self.__conn.getresponse()
152
+ except socket.timeout:
153
+ raise JSONRPCException({
154
+ 'code': -344,
155
+ 'message': '%r RPC took longer than %f seconds. Consider '
156
+ 'using larger timeout for calls that take '
157
+ 'longer to return.' % (self._service_name,
158
+ self.__conn.timeout)})
159
+ if http_response is None:
160
+ raise JSONRPCException({
161
+ 'code': -342, 'message': 'missing HTTP response from server'})
162
+
163
+ content_type = http_response.getheader('Content-Type')
164
+ if content_type != 'application/json':
165
+ raise JSONRPCException(
166
+ {'code': -342, 'message': 'non-JSON HTTP response with \'%i %s\' from server' % (http_response.status, http_response.reason)},
167
+ http_response.status)
168
+
169
+ responsedata = http_response.read().decode('utf8')
170
+ response = json.loads(responsedata, parse_float=decimal.Decimal)
171
+ elapsed = time.time() - req_start_time
172
+ if "error" in response and response["error"] is None:
173
+ log.debug("<-%s- [%.6f] %s" % (response["id"], elapsed, json.dumps(response["result"], default=serialization_fallback, ensure_ascii=self.ensure_ascii)))
174
+ else:
175
+ log.debug("<-- [%.6f] %s" % (elapsed, responsedata))
176
+ return response, http_response.status
177
+
178
+ def __truediv__(self, relative_uri):
179
+ return AuthServiceProxy("{}/{}".format(self.__service_url, relative_uri), self._service_name, connection=self.__conn)
180
+
181
+ def _set_conn(self, connection=None):
182
+ port = 80 if self.__url.port is None else self.__url.port
183
+ if connection:
184
+ self.__conn = connection
185
+ self.timeout = connection.timeout
186
+ elif self.__url.scheme == 'https':
187
+ self.__conn = http.client.HTTPSConnection(self.__url.hostname, port, timeout=self.timeout)
188
+ else:
189
+ self.__conn = http.client.HTTPConnection(self.__url.hostname, port, timeout=self.timeout)
test_framework/bdb.py ADDED
@@ -0,0 +1,151 @@
1
+ #!/usr/bin/env python3
2
+ # Copyright (c) 2020-2021 The Bitcoin Core developers
3
+ # Distributed under the MIT software license, see the accompanying
4
+ # file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
+ """
6
+ Utilities for working directly with the wallet's BDB database file
7
+
8
+ This is specific to the configuration of BDB used in this project:
9
+ - pagesize: 4096 bytes
10
+ - Outer database contains single subdatabase named 'main'
11
+ - btree
12
+ - btree leaf pages
13
+
14
+ Each key-value pair is two entries in a btree leaf. The first is the key, the one that follows
15
+ is the value. And so on. Note that the entry data is itself not in the correct order. Instead
16
+ entry offsets are stored in the correct order and those offsets are needed to then retrieve
17
+ the data itself.
18
+
19
+ Page format can be found in BDB source code dbinc/db_page.h
20
+ This only implements the deserialization of btree metadata pages and normal btree pages. Overflow
21
+ pages are not implemented but may be needed in the future if dealing with wallets with large
22
+ transactions.
23
+
24
+ `db_dump -da wallet.dat` is useful to see the data in a wallet.dat BDB file
25
+ """
26
+
27
+ import struct
28
+
29
+ # Important constants
30
+ PAGESIZE = 4096
31
+ OUTER_META_PAGE = 0
32
+ INNER_META_PAGE = 2
33
+
34
+ # Page type values
35
+ BTREE_INTERNAL = 3
36
+ BTREE_LEAF = 5
37
+ BTREE_META = 9
38
+
39
+ # Some magic numbers for sanity checking
40
+ BTREE_MAGIC = 0x053162
41
+ DB_VERSION = 9
42
+
43
+ # Deserializes a leaf page into a dict.
44
+ # Btree internal pages have the same header, for those, return None.
45
+ # For the btree leaf pages, deserialize them and put all the data into a dict
46
+ def dump_leaf_page(data):
47
+ page_info = {}
48
+ page_header = data[0:26]
49
+ _, pgno, prev_pgno, next_pgno, entries, hf_offset, level, pg_type = struct.unpack('QIIIHHBB', page_header)
50
+ page_info['pgno'] = pgno
51
+ page_info['prev_pgno'] = prev_pgno
52
+ page_info['next_pgno'] = next_pgno
53
+ page_info['hf_offset'] = hf_offset
54
+ page_info['level'] = level
55
+ page_info['pg_type'] = pg_type
56
+ page_info['entry_offsets'] = struct.unpack('{}H'.format(entries), data[26:26 + entries * 2])
57
+ page_info['entries'] = []
58
+
59
+ if pg_type == BTREE_INTERNAL:
60
+ # Skip internal pages. These are the internal nodes of the btree and don't contain anything relevant to us
61
+ return None
62
+
63
+ assert pg_type == BTREE_LEAF, 'A non-btree leaf page has been encountered while dumping leaves'
64
+
65
+ for i in range(0, entries):
66
+ offset = page_info['entry_offsets'][i]
67
+ entry = {'offset': offset}
68
+ page_data_header = data[offset:offset + 3]
69
+ e_len, pg_type = struct.unpack('HB', page_data_header)
70
+ entry['len'] = e_len
71
+ entry['pg_type'] = pg_type
72
+ entry['data'] = data[offset + 3:offset + 3 + e_len]
73
+ page_info['entries'].append(entry)
74
+
75
+ return page_info
76
+
77
+ # Deserializes a btree metadata page into a dict.
78
+ # Does a simple sanity check on the magic value, type, and version
79
+ def dump_meta_page(page):
80
+ # metadata page
81
+ # general metadata
82
+ metadata = {}
83
+ meta_page = page[0:72]
84
+ _, pgno, magic, version, pagesize, encrypt_alg, pg_type, metaflags, _, free, last_pgno, nparts, key_count, record_count, flags, uid = struct.unpack('QIIIIBBBBIIIIII20s', meta_page)
85
+ metadata['pgno'] = pgno
86
+ metadata['magic'] = magic
87
+ metadata['version'] = version
88
+ metadata['pagesize'] = pagesize
89
+ metadata['encrypt_alg'] = encrypt_alg
90
+ metadata['pg_type'] = pg_type
91
+ metadata['metaflags'] = metaflags
92
+ metadata['free'] = free
93
+ metadata['last_pgno'] = last_pgno
94
+ metadata['nparts'] = nparts
95
+ metadata['key_count'] = key_count
96
+ metadata['record_count'] = record_count
97
+ metadata['flags'] = flags
98
+ metadata['uid'] = uid.hex().encode()
99
+
100
+ assert magic == BTREE_MAGIC, 'bdb magic does not match bdb btree magic'
101
+ assert pg_type == BTREE_META, 'Metadata page is not a btree metadata page'
102
+ assert version == DB_VERSION, 'Database too new'
103
+
104
+ # btree metadata
105
+ btree_meta_page = page[72:512]
106
+ _, minkey, re_len, re_pad, root, _, crypto_magic, _, iv, chksum = struct.unpack('IIIII368sI12s16s20s', btree_meta_page)
107
+ metadata['minkey'] = minkey
108
+ metadata['re_len'] = re_len
109
+ metadata['re_pad'] = re_pad
110
+ metadata['root'] = root
111
+ metadata['crypto_magic'] = crypto_magic
112
+ metadata['iv'] = iv.hex().encode()
113
+ metadata['chksum'] = chksum.hex().encode()
114
+
115
+ return metadata
116
+
117
+ # Given the dict from dump_leaf_page, get the key-value pairs and put them into a dict
118
+ def extract_kv_pairs(page_data):
119
+ out = {}
120
+ last_key = None
121
+ for i, entry in enumerate(page_data['entries']):
122
+ # By virtue of these all being pairs, even number entries are keys, and odd are values
123
+ if i % 2 == 0:
124
+ out[entry['data']] = b''
125
+ last_key = entry['data']
126
+ else:
127
+ out[last_key] = entry['data']
128
+ return out
129
+
130
+ # Extract the key-value pairs of the BDB file given in filename
131
+ def dump_bdb_kv(filename):
132
+ # Read in the BDB file and start deserializing it
133
+ pages = []
134
+ with open(filename, 'rb') as f:
135
+ data = f.read(PAGESIZE)
136
+ while len(data) > 0:
137
+ pages.append(data)
138
+ data = f.read(PAGESIZE)
139
+
140
+ # Sanity check the meta pages
141
+ dump_meta_page(pages[OUTER_META_PAGE])
142
+ dump_meta_page(pages[INNER_META_PAGE])
143
+
144
+ # Fetch the kv pairs from the leaf pages
145
+ kv = {}
146
+ for i in range(3, len(pages)):
147
+ info = dump_leaf_page(pages[i])
148
+ if info is not None:
149
+ info_kv = extract_kv_pairs(info)
150
+ kv = {**kv, **info_kv}
151
+ return kv
@@ -0,0 +1,16 @@
1
+ index,secret key,public key,aux_rand,message,signature,verification result,comment
2
+ 0,0000000000000000000000000000000000000000000000000000000000000003,F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9,0000000000000000000000000000000000000000000000000000000000000000,0000000000000000000000000000000000000000000000000000000000000000,E907831F80848D1069A5371B402410364BDF1C5F8307B0084C55F1CE2DCA821525F66A4A85EA8B71E482A74F382D2CE5EBEEE8FDB2172F477DF4900D310536C0,TRUE,
3
+ 1,B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,0000000000000000000000000000000000000000000000000000000000000001,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,6896BD60EEAE296DB48A229FF71DFE071BDE413E6D43F917DC8DCF8C78DE33418906D11AC976ABCCB20B091292BFF4EA897EFCB639EA871CFA95F6DE339E4B0A,TRUE,
4
+ 2,C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9,DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8,C87AA53824B4D7AE2EB035A2B5BBBCCC080E76CDC6D1692C4B0B62D798E6D906,7E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C,5831AAEED7B44BB74E5EAB94BA9D4294C49BCF2A60728D8B4C200F50DD313C1BAB745879A5AD954A72C45A91C3A51D3C7ADEA98D82F8481E0E1E03674A6F3FB7,TRUE,
5
+ 3,0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710,25D1DFF95105F5253C4022F628A996AD3A0D95FBF21D468A1B33F8C160D8F517,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,7EB0509757E246F19449885651611CB965ECC1A187DD51B64FDA1EDC9637D5EC97582B9CB13DB3933705B32BA982AF5AF25FD78881EBB32771FC5922EFC66EA3,TRUE,test fails if msg is reduced modulo p or n
6
+ 4,,D69C3509BB99E412E68B0FE8544E72837DFA30746D8BE2AA65975F29D22DC7B9,,4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703,00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6376AFB1548AF603B3EB45C9F8207DEE1060CB71C04E80F593060B07D28308D7F4,TRUE,
7
+ 5,,EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E17776969E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B,FALSE,public key not on the curve
8
+ 6,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFF97BD5755EEEA420453A14355235D382F6472F8568A18B2F057A14602975563CC27944640AC607CD107AE10923D9EF7A73C643E166BE5EBEAFA34B1AC553E2,FALSE,has_even_y(R) is false
9
+ 7,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,1FA62E331EDBC21C394792D2AB1100A7B432B013DF3F6FF4F99FCB33E0E1515F28890B3EDB6E7189B630448B515CE4F8622A954CFE545735AAEA5134FCCDB2BD,FALSE,negated message
10
+ 8,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E177769961764B3AA9B2FFCB6EF947B6887A226E8D7C93E00C5ED0C1834FF0D0C2E6DA6,FALSE,negated s value
11
+ 9,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,0000000000000000000000000000000000000000000000000000000000000000123DDA8328AF9C23A94C1FEECFD123BA4FB73476F0D594DCB65C6425BD186051,FALSE,sG - eP is infinite. Test fails in single verification if has_even_y(inf) is defined as true and x(inf) as 0
12
+ 10,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,00000000000000000000000000000000000000000000000000000000000000017615FBAF5AE28864013C099742DEADB4DBA87F11AC6754F93780D5A1837CF197,FALSE,sG - eP is infinite. Test fails in single verification if has_even_y(inf) is defined as true and x(inf) as 1
13
+ 11,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D69E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B,FALSE,sig[0:32] is not an X coordinate on the curve
14
+ 12,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F69E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B,FALSE,sig[0:32] is equal to field size
15
+ 13,,DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E177769FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141,FALSE,sig[32:64] is equal to curve order
16
+ 14,,FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30,,243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89,6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E17776969E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B,FALSE,public key is not a valid X coordinate because it exceeds the field size
@@ -0,0 +1,49 @@
1
+ #!/usr/bin/env python3
2
+ # Copyright (c) 2022 The Bitcoin Core developers
3
+ # Distributed under the MIT software license, see the accompanying
4
+ # file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
+ """Helper routines relevant for compact block filters (BIP158).
6
+ """
7
+ from .siphash import siphash
8
+
9
+
10
+ def bip158_basic_element_hash(script_pub_key, N, block_hash):
11
+ """ Calculates the ranged hash of a filter element as defined in BIP158:
12
+
13
+ 'The first step in the filter construction is hashing the variable-sized
14
+ raw items in the set to the range [0, F), where F = N * M.'
15
+
16
+ 'The items are first passed through the pseudorandom function SipHash, which takes a
17
+ 128-bit key k and a variable-sized byte vector and produces a uniformly random 64-bit
18
+ output. Implementations of this BIP MUST use the SipHash parameters c = 2 and d = 4.'
19
+
20
+ 'The parameter k MUST be set to the first 16 bytes of the hash (in standard
21
+ little-endian representation) of the block for which the filter is constructed. This
22
+ ensures the key is deterministic while still varying from block to block.'
23
+ """
24
+ M = 784931
25
+ block_hash_bytes = bytes.fromhex(block_hash)[::-1]
26
+ k0 = int.from_bytes(block_hash_bytes[0:8], 'little')
27
+ k1 = int.from_bytes(block_hash_bytes[8:16], 'little')
28
+ return (siphash(k0, k1, script_pub_key) * (N * M)) >> 64
29
+
30
+
31
+ def bip158_relevant_scriptpubkeys(node, block_hash):
32
+ """ Determines the basic filter relvant scriptPubKeys as defined in BIP158:
33
+
34
+ 'A basic filter MUST contain exactly the following items for each transaction in a block:
35
+ - The previous output script (the script being spent) for each input, except for
36
+ the coinbase transaction.
37
+ - The scriptPubKey of each output, aside from all OP_RETURN output scripts.'
38
+ """
39
+ spks = set()
40
+ for tx in node.getblock(blockhash=block_hash, verbosity=3)['tx']:
41
+ # gather prevout scripts
42
+ for i in tx['vin']:
43
+ if 'prevout' in i:
44
+ spks.add(bytes.fromhex(i['prevout']['scriptPubKey']['hex']))
45
+ # gather output scripts
46
+ for o in tx['vout']:
47
+ if o['scriptPubKey']['type'] != 'nulldata':
48
+ spks.add(bytes.fromhex(o['scriptPubKey']['hex']))
49
+ return spks