mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-23 17:47:31 +00:00
ecc: small API clean-up
This commit is contained in:
parent
288d793893
commit
0a5ad9fda4
8 changed files with 28 additions and 57 deletions
|
@ -26,49 +26,36 @@
|
||||||
import base64
|
import base64
|
||||||
import hashlib
|
import hashlib
|
||||||
import functools
|
import functools
|
||||||
import copy
|
|
||||||
from typing import Union, Tuple, Optional
|
from typing import Union, Tuple, Optional
|
||||||
|
from ctypes import (
|
||||||
|
byref, c_byte, c_int, c_uint, c_char_p, c_size_t, c_void_p, create_string_buffer,
|
||||||
|
CFUNCTYPE, POINTER, cast
|
||||||
|
)
|
||||||
|
|
||||||
from .util import bfh, bh2u, assert_bytes, to_bytes, InvalidPassword, profiler, randrange
|
from .util import bfh, bh2u, assert_bytes, to_bytes, InvalidPassword, profiler, randrange
|
||||||
from .crypto import (sha256d, aes_encrypt_with_iv, aes_decrypt_with_iv, hmac_oneshot)
|
from .crypto import (sha256d, aes_encrypt_with_iv, aes_decrypt_with_iv, hmac_oneshot)
|
||||||
from . import constants
|
from . import constants
|
||||||
from .logging import get_logger
|
from .logging import get_logger
|
||||||
|
|
||||||
# TODO -->>>
|
|
||||||
import ctypes
|
|
||||||
from ctypes import (
|
|
||||||
byref, c_byte, c_int, c_uint, c_char_p, c_size_t, c_void_p, create_string_buffer,
|
|
||||||
CFUNCTYPE, POINTER, cast
|
|
||||||
)
|
|
||||||
from .ecc_fast import _libsecp256k1, SECP256K1_EC_UNCOMPRESSED
|
from .ecc_fast import _libsecp256k1, SECP256K1_EC_UNCOMPRESSED
|
||||||
# TODO <<<--
|
|
||||||
|
|
||||||
_logger = get_logger(__name__)
|
_logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def generator():
|
|
||||||
return GENERATOR
|
|
||||||
|
|
||||||
|
|
||||||
def point_at_infinity():
|
|
||||||
return ECPubkey(None)
|
|
||||||
|
|
||||||
|
|
||||||
def string_to_number(b: bytes) -> int:
|
def string_to_number(b: bytes) -> int:
|
||||||
return int.from_bytes(b, byteorder='big', signed=False)
|
return int.from_bytes(b, byteorder='big', signed=False)
|
||||||
|
|
||||||
|
|
||||||
def sig_string_from_der_sig(der_sig: bytes, order=None) -> bytes:
|
def sig_string_from_der_sig(der_sig: bytes) -> bytes:
|
||||||
r, s = get_r_and_s_from_der_sig(der_sig)
|
r, s = get_r_and_s_from_der_sig(der_sig)
|
||||||
return sig_string_from_r_and_s(r, s)
|
return sig_string_from_r_and_s(r, s)
|
||||||
|
|
||||||
|
|
||||||
def der_sig_from_sig_string(sig_string: bytes, order=None) -> bytes:
|
def der_sig_from_sig_string(sig_string: bytes) -> bytes:
|
||||||
r, s = get_r_and_s_from_sig_string(sig_string)
|
r, s = get_r_and_s_from_sig_string(sig_string)
|
||||||
return der_sig_from_r_and_s(r, s)
|
return der_sig_from_r_and_s(r, s)
|
||||||
|
|
||||||
|
|
||||||
def der_sig_from_r_and_s(r: int, s: int, order=None) -> bytes:
|
def der_sig_from_r_and_s(r: int, s: int) -> bytes:
|
||||||
sig_string = (int.to_bytes(r, length=32, byteorder="big") +
|
sig_string = (int.to_bytes(r, length=32, byteorder="big") +
|
||||||
int.to_bytes(s, length=32, byteorder="big"))
|
int.to_bytes(s, length=32, byteorder="big"))
|
||||||
sig = create_string_buffer(64)
|
sig = create_string_buffer(64)
|
||||||
|
@ -85,7 +72,7 @@ def der_sig_from_r_and_s(r: int, s: int, order=None) -> bytes:
|
||||||
return bytes(der_sig)[:der_sig_size]
|
return bytes(der_sig)[:der_sig_size]
|
||||||
|
|
||||||
|
|
||||||
def get_r_and_s_from_der_sig(der_sig: bytes, order=None) -> Tuple[int, int]:
|
def get_r_and_s_from_der_sig(der_sig: bytes) -> Tuple[int, int]:
|
||||||
assert isinstance(der_sig, bytes)
|
assert isinstance(der_sig, bytes)
|
||||||
sig = create_string_buffer(64)
|
sig = create_string_buffer(64)
|
||||||
ret = _libsecp256k1.secp256k1_ecdsa_signature_parse_der(_libsecp256k1.ctx, sig, der_sig, len(der_sig))
|
ret = _libsecp256k1.secp256k1_ecdsa_signature_parse_der(_libsecp256k1.ctx, sig, der_sig, len(der_sig))
|
||||||
|
@ -99,7 +86,7 @@ def get_r_and_s_from_der_sig(der_sig: bytes, order=None) -> Tuple[int, int]:
|
||||||
return r, s
|
return r, s
|
||||||
|
|
||||||
|
|
||||||
def get_r_and_s_from_sig_string(sig_string: bytes, order=None) -> Tuple[int, int]:
|
def get_r_and_s_from_sig_string(sig_string: bytes) -> Tuple[int, int]:
|
||||||
if not (isinstance(sig_string, bytes) and len(sig_string) == 64):
|
if not (isinstance(sig_string, bytes) and len(sig_string) == 64):
|
||||||
raise Exception("sig_string must be bytes, and 64 bytes exactly")
|
raise Exception("sig_string must be bytes, and 64 bytes exactly")
|
||||||
sig = create_string_buffer(64)
|
sig = create_string_buffer(64)
|
||||||
|
@ -114,7 +101,7 @@ def get_r_and_s_from_sig_string(sig_string: bytes, order=None) -> Tuple[int, int
|
||||||
return r, s
|
return r, s
|
||||||
|
|
||||||
|
|
||||||
def sig_string_from_r_and_s(r: int, s: int, order=None) -> bytes:
|
def sig_string_from_r_and_s(r: int, s: int) -> bytes:
|
||||||
sig_string = (int.to_bytes(r, length=32, byteorder="big") +
|
sig_string = (int.to_bytes(r, length=32, byteorder="big") +
|
||||||
int.to_bytes(s, length=32, byteorder="big"))
|
int.to_bytes(s, length=32, byteorder="big"))
|
||||||
sig = create_string_buffer(64)
|
sig = create_string_buffer(64)
|
||||||
|
@ -250,12 +237,12 @@ class ECPubkey(object):
|
||||||
|
|
||||||
other %= CURVE_ORDER
|
other %= CURVE_ORDER
|
||||||
if self.is_at_infinity() or other == 0:
|
if self.is_at_infinity() or other == 0:
|
||||||
return point_at_infinity()
|
return POINT_AT_INFINITY
|
||||||
pubkey = self._to_libsecp256k1_pubkey_ptr()
|
pubkey = self._to_libsecp256k1_pubkey_ptr()
|
||||||
|
|
||||||
ret = _libsecp256k1.secp256k1_ec_pubkey_tweak_mul(_libsecp256k1.ctx, pubkey, other.to_bytes(32, byteorder="big"))
|
ret = _libsecp256k1.secp256k1_ec_pubkey_tweak_mul(_libsecp256k1.ctx, pubkey, other.to_bytes(32, byteorder="big"))
|
||||||
if not ret:
|
if not ret:
|
||||||
return point_at_infinity()
|
return POINT_AT_INFINITY
|
||||||
return ECPubkey._from_libsecp256k1_pubkey_ptr(pubkey)
|
return ECPubkey._from_libsecp256k1_pubkey_ptr(pubkey)
|
||||||
|
|
||||||
def __rmul__(self, other: int):
|
def __rmul__(self, other: int):
|
||||||
|
@ -276,7 +263,7 @@ class ECPubkey(object):
|
||||||
array_of_pubkey_ptrs = (c_char_p * 2)(pubkey1, pubkey2)
|
array_of_pubkey_ptrs = (c_char_p * 2)(pubkey1, pubkey2)
|
||||||
ret = _libsecp256k1.secp256k1_ec_pubkey_combine(_libsecp256k1.ctx, pubkey_sum, array_of_pubkey_ptrs, 2)
|
ret = _libsecp256k1.secp256k1_ec_pubkey_combine(_libsecp256k1.ctx, pubkey_sum, array_of_pubkey_ptrs, 2)
|
||||||
if not ret:
|
if not ret:
|
||||||
return point_at_infinity()
|
return POINT_AT_INFINITY
|
||||||
return ECPubkey._from_libsecp256k1_pubkey_ptr(pubkey_sum)
|
return ECPubkey._from_libsecp256k1_pubkey_ptr(pubkey_sum)
|
||||||
|
|
||||||
def __eq__(self, other) -> bool:
|
def __eq__(self, other) -> bool:
|
||||||
|
@ -345,7 +332,7 @@ class ECPubkey(object):
|
||||||
return CURVE_ORDER
|
return CURVE_ORDER
|
||||||
|
|
||||||
def is_at_infinity(self):
|
def is_at_infinity(self):
|
||||||
return self == point_at_infinity()
|
return self == POINT_AT_INFINITY
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def is_pubkey_bytes(cls, b: bytes):
|
def is_pubkey_bytes(cls, b: bytes):
|
||||||
|
@ -359,6 +346,7 @@ class ECPubkey(object):
|
||||||
GENERATOR = ECPubkey(bytes.fromhex('0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'
|
GENERATOR = ECPubkey(bytes.fromhex('0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'
|
||||||
'483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'))
|
'483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8'))
|
||||||
CURVE_ORDER = 0xFFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFE_BAAEDCE6_AF48A03B_BFD25E8C_D0364141
|
CURVE_ORDER = 0xFFFFFFFF_FFFFFFFF_FFFFFFFF_FFFFFFFE_BAAEDCE6_AF48A03B_BFD25E8C_D0364141
|
||||||
|
POINT_AT_INFINITY = ECPubkey(None)
|
||||||
|
|
||||||
|
|
||||||
def msg_magic(message: bytes) -> bytes:
|
def msg_magic(message: bytes) -> bytes:
|
||||||
|
@ -414,7 +402,7 @@ class ECPrivkey(ECPubkey):
|
||||||
raise InvalidECPointException('Invalid secret scalar (not within curve order)')
|
raise InvalidECPointException('Invalid secret scalar (not within curve order)')
|
||||||
self.secret_scalar = secret
|
self.secret_scalar = secret
|
||||||
|
|
||||||
pubkey = generator() * secret
|
pubkey = GENERATOR * secret
|
||||||
super().__init__(pubkey.get_public_key_bytes(compressed=False))
|
super().__init__(pubkey.get_public_key_bytes(compressed=False))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -450,7 +438,7 @@ class ECPrivkey(ECPubkey):
|
||||||
def get_secret_bytes(self) -> bytes:
|
def get_secret_bytes(self) -> bytes:
|
||||||
return int.to_bytes(self.secret_scalar, length=32, byteorder='big', signed=False)
|
return int.to_bytes(self.secret_scalar, length=32, byteorder='big', signed=False)
|
||||||
|
|
||||||
def sign(self, msg_hash: bytes, sigencode=None, sigdecode=None) -> bytes:
|
def sign(self, msg_hash: bytes, sigencode=None) -> bytes:
|
||||||
if not (isinstance(msg_hash, bytes) and len(msg_hash) == 32):
|
if not (isinstance(msg_hash, bytes) and len(msg_hash) == 32):
|
||||||
raise Exception("msg_hash to be signed must be bytes, and 32 bytes exactly")
|
raise Exception("msg_hash to be signed must be bytes, and 32 bytes exactly")
|
||||||
if sigencode is None:
|
if sigencode is None:
|
||||||
|
@ -481,13 +469,11 @@ class ECPrivkey(ECPubkey):
|
||||||
sig_string = sig_string_from_r_and_s(r, s)
|
sig_string = sig_string_from_r_and_s(r, s)
|
||||||
self.verify_message_hash(sig_string, msg_hash)
|
self.verify_message_hash(sig_string, msg_hash)
|
||||||
|
|
||||||
sig = sigencode(r, s, CURVE_ORDER)
|
sig = sigencode(r, s)
|
||||||
return sig
|
return sig
|
||||||
|
|
||||||
def sign_transaction(self, hashed_preimage: bytes) -> bytes:
|
def sign_transaction(self, hashed_preimage: bytes) -> bytes:
|
||||||
return self.sign(hashed_preimage,
|
return self.sign(hashed_preimage, sigencode=der_sig_from_r_and_s)
|
||||||
sigencode=der_sig_from_r_and_s,
|
|
||||||
sigdecode=get_r_and_s_from_der_sig)
|
|
||||||
|
|
||||||
def sign_message(self, message: bytes, is_compressed: bool, algo=lambda x: sha256d(msg_magic(x))) -> bytes:
|
def sign_message(self, message: bytes, is_compressed: bool, algo=lambda x: sha256d(msg_magic(x))) -> bytes:
|
||||||
def bruteforce_recid(sig_string):
|
def bruteforce_recid(sig_string):
|
||||||
|
@ -503,9 +489,7 @@ class ECPrivkey(ECPubkey):
|
||||||
|
|
||||||
message = to_bytes(message, 'utf8')
|
message = to_bytes(message, 'utf8')
|
||||||
msg_hash = algo(message)
|
msg_hash = algo(message)
|
||||||
sig_string = self.sign(msg_hash,
|
sig_string = self.sign(msg_hash, sigencode=sig_string_from_r_and_s)
|
||||||
sigencode=sig_string_from_r_and_s,
|
|
||||||
sigdecode=get_r_and_s_from_sig_string)
|
|
||||||
sig65, recid = bruteforce_recid(sig_string)
|
sig65, recid = bruteforce_recid(sig_string)
|
||||||
return sig65
|
return sig65
|
||||||
|
|
||||||
|
|
|
@ -109,10 +109,6 @@ def load_library():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def is_using_fast_ecc():
|
|
||||||
return True # TODO rm
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
_libsecp256k1 = load_library()
|
_libsecp256k1 = load_library()
|
||||||
except BaseException as e:
|
except BaseException as e:
|
||||||
|
|
|
@ -615,7 +615,7 @@ class Old_KeyStore(MasterPublicKeyMixin, Deterministic_KeyStore):
|
||||||
def get_pubkey_from_mpk(cls, mpk, for_change, n) -> bytes:
|
def get_pubkey_from_mpk(cls, mpk, for_change, n) -> bytes:
|
||||||
z = cls.get_sequence(mpk, for_change, n)
|
z = cls.get_sequence(mpk, for_change, n)
|
||||||
master_public_key = ecc.ECPubkey(bfh('04'+mpk))
|
master_public_key = ecc.ECPubkey(bfh('04'+mpk))
|
||||||
public_key = master_public_key + z*ecc.generator()
|
public_key = master_public_key + z*ecc.GENERATOR
|
||||||
return public_key.get_public_key_bytes(compressed=False)
|
return public_key.get_public_key_bytes(compressed=False)
|
||||||
|
|
||||||
@lru_cache(maxsize=None)
|
@lru_cache(maxsize=None)
|
||||||
|
|
|
@ -1039,7 +1039,7 @@ class Peer(Logger):
|
||||||
timestamp=now.to_bytes(4, byteorder="big"),
|
timestamp=now.to_bytes(4, byteorder="big"),
|
||||||
)
|
)
|
||||||
sighash = sha256d(chan_upd[2 + 64:])
|
sighash = sha256d(chan_upd[2 + 64:])
|
||||||
sig = ecc.ECPrivkey(self.privkey).sign(sighash, sig_string_from_r_and_s, get_r_and_s_from_sig_string)
|
sig = ecc.ECPrivkey(self.privkey).sign(sighash, sig_string_from_r_and_s)
|
||||||
message_type, payload = decode_msg(chan_upd)
|
message_type, payload = decode_msg(chan_upd)
|
||||||
payload['signature'] = sig
|
payload['signature'] = sig
|
||||||
chan_upd = encode_msg(message_type, **payload)
|
chan_upd = encode_msg(message_type, **payload)
|
||||||
|
@ -1071,8 +1071,8 @@ class Peer(Logger):
|
||||||
)
|
)
|
||||||
to_hash = chan_ann[256+2:]
|
to_hash = chan_ann[256+2:]
|
||||||
h = sha256d(to_hash)
|
h = sha256d(to_hash)
|
||||||
bitcoin_signature = ecc.ECPrivkey(chan.config[LOCAL].multisig_key.privkey).sign(h, sig_string_from_r_and_s, get_r_and_s_from_sig_string)
|
bitcoin_signature = ecc.ECPrivkey(chan.config[LOCAL].multisig_key.privkey).sign(h, sig_string_from_r_and_s)
|
||||||
node_signature = ecc.ECPrivkey(self.privkey).sign(h, sig_string_from_r_and_s, get_r_and_s_from_sig_string)
|
node_signature = ecc.ECPrivkey(self.privkey).sign(h, sig_string_from_r_and_s)
|
||||||
self.send_message("announcement_signatures",
|
self.send_message("announcement_signatures",
|
||||||
channel_id=chan.channel_id,
|
channel_id=chan.channel_id,
|
||||||
short_channel_id=chan.short_channel_id,
|
short_channel_id=chan.short_channel_id,
|
||||||
|
|
|
@ -254,7 +254,7 @@ def privkey_to_pubkey(priv: bytes) -> bytes:
|
||||||
return ecc.ECPrivkey(priv[:32]).get_public_key_bytes()
|
return ecc.ECPrivkey(priv[:32]).get_public_key_bytes()
|
||||||
|
|
||||||
def derive_pubkey(basepoint: bytes, per_commitment_point: bytes) -> bytes:
|
def derive_pubkey(basepoint: bytes, per_commitment_point: bytes) -> bytes:
|
||||||
p = ecc.ECPubkey(basepoint) + ecc.generator() * ecc.string_to_number(sha256(per_commitment_point + basepoint))
|
p = ecc.ECPubkey(basepoint) + ecc.GENERATOR * ecc.string_to_number(sha256(per_commitment_point + basepoint))
|
||||||
return p.get_public_key_bytes()
|
return p.get_public_key_bytes()
|
||||||
|
|
||||||
def derive_privkey(secret: int, per_commitment_point: bytes) -> int:
|
def derive_privkey(secret: int, per_commitment_point: bytes) -> int:
|
||||||
|
|
|
@ -40,7 +40,6 @@ from .lntransport import LNTransport, LNResponderTransport
|
||||||
from .lnpeer import Peer, LN_P2P_NETWORK_TIMEOUT
|
from .lnpeer import Peer, LN_P2P_NETWORK_TIMEOUT
|
||||||
from .lnaddr import lnencode, LnAddr, lndecode
|
from .lnaddr import lnencode, LnAddr, lndecode
|
||||||
from .ecc import der_sig_from_sig_string
|
from .ecc import der_sig_from_sig_string
|
||||||
from .ecc_fast import is_using_fast_ecc
|
|
||||||
from .lnchannel import Channel
|
from .lnchannel import Channel
|
||||||
from .lnchannel import channel_states, peer_states
|
from .lnchannel import channel_states, peer_states
|
||||||
from . import lnutil
|
from . import lnutil
|
||||||
|
@ -303,7 +302,6 @@ class LNGossip(LNWorker):
|
||||||
self.localfeatures |= LnLocalFeatures.GOSSIP_QUERIES_OPT
|
self.localfeatures |= LnLocalFeatures.GOSSIP_QUERIES_OPT
|
||||||
self.localfeatures |= LnLocalFeatures.GOSSIP_QUERIES_REQ
|
self.localfeatures |= LnLocalFeatures.GOSSIP_QUERIES_REQ
|
||||||
self.unknown_ids = set()
|
self.unknown_ids = set()
|
||||||
assert is_using_fast_ecc(), "verifying LN gossip msgs without libsecp256k1 is hopeless"
|
|
||||||
|
|
||||||
def start_network(self, network: 'Network'):
|
def start_network(self, network: 'Network'):
|
||||||
assert network
|
assert network
|
||||||
|
|
|
@ -100,7 +100,7 @@ class Test_bitcoin(ElectrumTestCase):
|
||||||
self._do_test_crypto(message)
|
self._do_test_crypto(message)
|
||||||
|
|
||||||
def _do_test_crypto(self, message):
|
def _do_test_crypto(self, message):
|
||||||
G = ecc.generator()
|
G = ecc.GENERATOR
|
||||||
_r = G.order()
|
_r = G.order()
|
||||||
pvk = randrange(_r)
|
pvk = randrange(_r)
|
||||||
|
|
||||||
|
@ -128,11 +128,11 @@ class Test_bitcoin(ElectrumTestCase):
|
||||||
|
|
||||||
@needs_test_with_all_ecc_implementations
|
@needs_test_with_all_ecc_implementations
|
||||||
def test_ecc_sanity(self):
|
def test_ecc_sanity(self):
|
||||||
G = ecc.generator()
|
G = ecc.GENERATOR
|
||||||
n = G.order()
|
n = G.order()
|
||||||
self.assertEqual(ecc.CURVE_ORDER, n)
|
self.assertEqual(ecc.CURVE_ORDER, n)
|
||||||
inf = n * G
|
inf = n * G
|
||||||
self.assertEqual(ecc.point_at_infinity(), inf)
|
self.assertEqual(ecc.POINT_AT_INFINITY, inf)
|
||||||
self.assertTrue(inf.is_at_infinity())
|
self.assertTrue(inf.is_at_infinity())
|
||||||
self.assertFalse(G.is_at_infinity())
|
self.assertFalse(G.is_at_infinity())
|
||||||
self.assertEqual(11 * G, 7 * G + 4 * G)
|
self.assertEqual(11 * G, 7 * G + 4 * G)
|
||||||
|
|
|
@ -70,7 +70,6 @@ from .address_synchronizer import (AddressSynchronizer, TX_HEIGHT_LOCAL,
|
||||||
from .util import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED, PR_INFLIGHT
|
from .util import PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED, PR_INFLIGHT
|
||||||
from .contacts import Contacts
|
from .contacts import Contacts
|
||||||
from .interface import NetworkException
|
from .interface import NetworkException
|
||||||
from .ecc_fast import is_using_fast_ecc
|
|
||||||
from .mnemonic import Mnemonic
|
from .mnemonic import Mnemonic
|
||||||
from .logging import get_logger
|
from .logging import get_logger
|
||||||
from .lnworker import LNWallet
|
from .lnworker import LNWallet
|
||||||
|
@ -270,9 +269,6 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
|
||||||
def init_lightning(self):
|
def init_lightning(self):
|
||||||
if self.db.get('lightning_privkey2'):
|
if self.db.get('lightning_privkey2'):
|
||||||
return
|
return
|
||||||
if not is_using_fast_ecc():
|
|
||||||
raise Exception('libsecp256k1 library not available. '
|
|
||||||
'Verifying Lightning channels is too computationally expensive without libsecp256k1, aborting.')
|
|
||||||
# TODO derive this deterministically from wallet.keystore at keystore generation time
|
# TODO derive this deterministically from wallet.keystore at keystore generation time
|
||||||
# probably along a hardened path ( lnd-equivalent would be m/1017'/coinType'/ )
|
# probably along a hardened path ( lnd-equivalent would be m/1017'/coinType'/ )
|
||||||
seed = os.urandom(32)
|
seed = os.urandom(32)
|
||||||
|
@ -2085,9 +2081,6 @@ class Deterministic_Wallet(Abstract_Wallet):
|
||||||
|
|
||||||
@profiler
|
@profiler
|
||||||
def try_detecting_internal_addresses_corruption(self):
|
def try_detecting_internal_addresses_corruption(self):
|
||||||
if not is_using_fast_ecc():
|
|
||||||
self.logger.info("internal address corruption test skipped due to missing libsecp256k1")
|
|
||||||
return
|
|
||||||
addresses_all = self.get_addresses()
|
addresses_all = self.get_addresses()
|
||||||
# sample 1: first few
|
# sample 1: first few
|
||||||
addresses_sample1 = addresses_all[:10]
|
addresses_sample1 = addresses_all[:10]
|
||||||
|
|
Loading…
Add table
Reference in a new issue