diff --git a/.travis.yml b/.travis.yml index 9d59136..c5977f5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,9 +24,9 @@ script: - pycodestyle neocore tests # now test the upstream neo-python dev branch with the current neocore code -- git clone https://github.com/CityOfZion/neo-python.git +- git clone https://github.com/jseagrave21/neo-python.git - cd neo-python -- git checkout origin/development -b development +- git checkout origin/support-#888 -b support-#888 - pip install -e . - yes | pip uninstall neocore neo-boa - pip install git+https://github.com/CityOfZion/neo-boa@development diff --git a/neocore/Cryptography/Crypto.py b/neocore/Cryptography/Crypto.py index 131f146..476bb59 100644 --- a/neocore/Cryptography/Crypto.py +++ b/neocore/Cryptography/Crypto.py @@ -1,6 +1,5 @@ import bitcoin from ecdsa import NIST256p, VerifyingKey -from logzero import logger from .Helper import * from neocore.UInt160 import UInt160 from .ECCurve import EllipticCurve @@ -108,7 +107,7 @@ def Sign(message, private_key): Sign the message with the given private key. Args: - message (str): message to be signed + message (hexstr): message to be signed private_key (str): 32 byte key as a double digit hex string (e.g. having a length of 64) Returns: bytearray: the signature of the message. @@ -131,7 +130,7 @@ def VerifySignature(message, signature, public_key, unhex=True): Verify the integrity of the message. Args: - message (str): the message to verify. + message (hexstr or str): the message to verify. signature (bytearray): the signature belonging to the message. public_key (ECPoint|bytes): the public key to use for verifying the signature. If `public_key` is of type bytes then it should be raw bytes (i.e. b'\xAA\xBB'). unhex (bool): whether the message should be unhexlified before verifying @@ -149,8 +148,8 @@ def VerifySignature(message, signature, public_key, unhex=True): if unhex: try: message = binascii.unhexlify(message) - except Exception as e: - logger.error("could not get m: %s" % e) + except binascii.Error: + pass elif isinstance(message, str): message = message.encode('utf-8') @@ -162,7 +161,7 @@ def VerifySignature(message, signature, public_key, unhex=True): vk = VerifyingKey.from_string(public_key, curve=NIST256p, hashfunc=hashlib.sha256) res = vk.verify(signature, message, hashfunc=hashlib.sha256) return res - except Exception as e: + except Exception: pass return False diff --git a/neocore/Cryptography/ECCurve.py b/neocore/Cryptography/ECCurve.py index 238050d..5c83874 100644 --- a/neocore/Cryptography/ECCurve.py +++ b/neocore/Cryptography/ECCurve.py @@ -8,7 +8,6 @@ import random import binascii from mpmath.libmp import bitcount as _bitlength -from logzero import logger modpow = pow @@ -49,8 +48,18 @@ def randbytes(n): def next_random_integer(size_in_bits): + """ + Args: + size_in_bits (int): used to specify the size in bits of the random integer + + Returns: + int: random integer + + Raises: + ValueError: if the specified size in bits is < 0 + """ if size_in_bits < 0: - raise Exception('size in bits must be greater than zero') + raise ValueError(f'size in bits ({size_in_bits}) must be greater than zero') if size_in_bits == 0: return 0 @@ -65,9 +74,17 @@ def next_random_integer(size_in_bits): def _lucas_sequence(n, P, Q, k): - """Return the modular Lucas sequence (U_k, V_k, Q_k). - Given a Lucas sequence defined by P, Q, returns the kth values for - U and V, along with Q^k, all modulo n. + """ + Returns: + The modular Lucas sequence (U_k, V_k, Q_k). + Given a Lucas sequence defined by P, Q, returns the kth values for + U and V, along with Q^k, all modulo n. + + Raises: + ValueError: + if n is < 2 + if k < 0 + if D == 0 """ D = P * P - 4 * Q if n < 2: @@ -145,10 +162,14 @@ def _lucas_sequence(n, P, Q, k): def sqrtCQ(val, CQ): + """ + Raises: + LegendaireExponentError: if modpow(val, legendreExponent, CQ) != 1 + """ if test_bit(CQ, 1): z = modpow(val, (CQ >> 2) + 1, CQ) zsquare = (z * z) % CQ - if (z * z) % CQ == val: + if zsquare == val: return z else: return None @@ -156,8 +177,7 @@ def sqrtCQ(val, CQ): qMinusOne = CQ - 1 legendreExponent = qMinusOne >> 1 if modpow(val, legendreExponent, CQ) != 1: - logger.error("legendaire exponent error") - return None + raise LegendaireExponentError() u = qMinusOne >> 2 k = (u << 1) + 1 @@ -185,6 +205,11 @@ def sqrtCQ(val, CQ): return None +class LegendaireExponentError(Exception): + """Provide user friendly feedback in case of a legendaire exponent error.""" + pass + + class FiniteField: """ FiniteField implements a value modulus a number. @@ -248,7 +273,11 @@ def sqrt(self, flag): return self.field.sqrt(self, flag) def sqrtCQ(self, CQ): - return self.field.sqrtCQ(self, CQ) + try: + res = self.field.sqrtCQ(self, CQ) + except LegendaireExponentError: + res = None + return res def inverse(self): return self.field.inverse(self) @@ -287,6 +316,9 @@ def neg(self, val): def sqrt(self, val, flag): """ calculate the square root modulus p + + Raises: + ValueError: if self.p % 8 == 1 """ if val.iszero(): return val @@ -300,7 +332,7 @@ def sqrt(self, val, flag): else: res = (4 * val) ** ((self.p - 5) / 8) * 2 * val else: - raise Exception("modsqrt non supported for (p%8)==1") + raise ValueError("modsqrt non supported for (p%8)==1") if res.value % 2 == flag: return res @@ -570,9 +602,17 @@ def decompress(self, x, flag): return self.point(x, ysquare.sqrt(flag)) def decode_from_reader(self, reader): + """ + Raises: + NotImplementedError: if an unsupported point encoding is used + TypeError: if unexpected encoding is read + """ + try: + f = reader.ReadByte() + except ValueError: + return self.Infinity - f = reader.ReadByte() - + f = int.from_bytes(f, "little") if f == 0: return self.Infinity @@ -589,10 +629,15 @@ def decode_from_reader(self, reader): elif f == 4 or f == 6 or f == 7: raise NotImplementedError() - raise Exception("Invalid point incoding: %s " % f) + raise TypeError(f"Invalid point encoding: {f}") def decode_from_hex(self, hex_str, unhex=True): - + """ + Raises: + ValueError: if the hex_str is an incorrect length for encoding or compressed encoding + NotImplementedError: if an unsupported point encoding is used + TypeError: if unexpected encoding is read + """ ba = None if unhex: ba = bytearray(binascii.unhexlify(hex_str)) @@ -611,7 +656,7 @@ def decode_from_hex(self, hex_str, unhex=True): # these are compressed if f == 2 or f == 3: if len(ba) != expected_byte_len + 1: - raise Exception("Incorrrect length for encoding") + raise ValueError("Incorrect length for encoding") yTilde = f & 1 data = bytearray(ba[1:]) data.reverse() @@ -623,7 +668,7 @@ def decode_from_hex(self, hex_str, unhex=True): elif f == 4: if len(ba) != (2 * expected_byte_len) + 1: - raise Exception("Incorrect length for compressed encoding") + raise ValueError("Incorrect length for compressed encoding") x_data = bytearray(ba[1:1 + expected_byte_len]) x_data.reverse() @@ -643,7 +688,7 @@ def decode_from_hex(self, hex_str, unhex=True): raise NotImplementedError() else: - raise Exception("Invalid point incoding: %s " % f) + raise TypeError(f"Invalid point encoding: {f}") def decompress_from_curve(self, x, flag): """ @@ -656,7 +701,10 @@ def decompress_from_curve(self, x, flag): ysquare = x ** 3 + self.a * x + self.b - ysquare_root = sqrtCQ(ysquare.value, cq) + try: + ysquare_root = sqrtCQ(ysquare.value, cq) + except LegendaireExponentError: + ysquare_root = None bit0 = 0 if ysquare_root % 2 is not 0: @@ -785,8 +833,8 @@ def crack2(self, r, s1, s2, m1, m2): x2 = self.crack1(r, s2, m2, secret) if x1 != x2: - logger.info("x1= %s" % x1) - logger.info("x2= %s" % x2) + print("x1= %s" % x1) + print("x2= %s" % x2) return (secret, x1) @@ -817,6 +865,9 @@ def secp256r1(): def decode_secp256r1(str, unhex=True, check_on_curve=True): """ decode a public key on the secp256r1 curve + + Raises: + ValueError: if input `str` could not be decoded """ GFp = FiniteField(int("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", 16)) @@ -829,7 +880,7 @@ def decode_secp256r1(str, unhex=True, check_on_curve=True): if point.isoncurve(): return ECDSA(GFp, point, int("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", 16)) else: - raise Exception("Could not decode string") + raise ValueError(f"Could not decode string: {str}") return ECDSA(GFp, point, int("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", 16)) diff --git a/neocore/Cryptography/Helper.py b/neocore/Cryptography/Helper.py index 95e26cc..108dc39 100644 --- a/neocore/Cryptography/Helper.py +++ b/neocore/Cryptography/Helper.py @@ -146,11 +146,11 @@ def base256_encode(n, minwidth=0): # int/long to byte array n (int): input value. minwidth: minimum return value length. - Raises: - ValueError: if a negative number is provided. - Returns: bytearray: + + Raises: + ValueError: if a negative number is provided for `n`. """ if n > 0: arr = [] diff --git a/neocore/Cryptography/MerkleTree.py b/neocore/Cryptography/MerkleTree.py index e18fa1a..427cd6b 100644 --- a/neocore/Cryptography/MerkleTree.py +++ b/neocore/Cryptography/MerkleTree.py @@ -76,9 +76,12 @@ def __Build(leaves): Returns: MerkleTreeNode: the root node. + + Raises: + ValueError: if the length of `leaves` is < 1 """ if len(leaves) < 1: - raise Exception('Leaves must have length') + raise ValueError('Leaves must have length') if len(leaves) == 1: return leaves[0] @@ -115,9 +118,12 @@ def ComputeRoot(hashes): Returns: bytes: the root hash. + + Raises: + ValueError: if the `hashes` array is empty """ if not len(hashes): - raise Exception('Hashes must have length') + raise ValueError('Hashes must have length') if len(hashes) == 1: return hashes[0] @@ -157,7 +163,6 @@ def Trim(self, flags): Args: flags: "0000" for trimming, any other value for keeping the nodes. """ - logger.info("Trimming!") flags = bytearray(flags) length = 1 << self.Depth - 1 while len(flags) < length: diff --git a/neocore/Fixed8.py b/neocore/Fixed8.py index cab8d25..e764773 100644 --- a/neocore/Fixed8.py +++ b/neocore/Fixed8.py @@ -53,12 +53,12 @@ def TryParse(value, require_positive=False): val = None try: val = float(value) - except Exception as e: + except Exception: pass if not val: try: val = int(value) - except Exception as e: + except Exception: pass if val is not None: diff --git a/neocore/IO/BinaryReader.py b/neocore/IO/BinaryReader.py index 2749825..1dee107 100644 --- a/neocore/IO/BinaryReader.py +++ b/neocore/IO/BinaryReader.py @@ -10,7 +10,6 @@ import binascii import importlib -from logzero import logger from neocore.Fixed8 import Fixed8 from neocore.UInt160 import UInt160 from neocore.UInt256 import UInt256 @@ -43,23 +42,17 @@ def unpack(self, fmt, length=1): """ return struct.unpack(fmt, self.stream.read(length))[0] - def ReadByte(self, do_ord=True): + def ReadByte(self): """ Read a single byte. - Args: - do_ord (bool): (default True) convert the byte to an ordinal first. - Returns: - bytes: a single byte if successful. 0 (int) if an exception occurred. + bytes: a single byte if successful. + + Raises: + ValueError: if there is insufficient data """ - try: - if do_ord: - return ord(self.stream.read(1)) - return self.stream.read(1) - except Exception as e: - logger.error("ord expected character but got none") - return 0 + return self.SafeReadBytes(1) def ReadBytes(self, length): """ @@ -78,11 +71,11 @@ def SafeReadBytes(self, length): """ Read exactly `length` number of bytes from the stream. - Raises: - ValueError is not enough data - Returns: bytes: `length` number of bytes + + Raises: + ValueError: if there is insufficient data """ data = self.ReadBytes(length) if len(data) < length: @@ -238,22 +231,26 @@ def ReadVarInt(self, max=sys.maxsize): Returns: int: + + Raises: + ValueError: if the specified `max` number of bytes is exceeded """ - fb = self.ReadByte() - if fb is 0: - return fb + try: + fb = self.ReadByte() + except ValueError: + return 0 value = 0 - if hex(fb) == '0xfd': + if fb == b'\xfd': value = self.ReadUInt16() - elif hex(fb) == '0xfe': + elif fb == b'\xfe': value = self.ReadUInt32() - elif hex(fb) == '0xff': + elif fb == b'\xff': value = self.ReadUInt64() else: - value = fb + value = int.from_bytes(fb, "little") if value > max: - raise Exception("Invalid format") + raise ValueError(f"Maximum number of bytes ({max}) exceeded.") return int(value) @@ -321,15 +318,13 @@ def ReadSerializableArray(self, class_name, max=sys.maxsize): klass = getattr(importlib.import_module(module), klassname) length = self.ReadVarInt(max=max) items = [] - # logger.info("READING ITEM %s %s " % (length, class_name)) - try: - for i in range(0, length): + for i in range(0, length): + try: item = klass() item.Deserialize(self) - # logger.info("deserialized item %s %s " % ( i, item)) items.append(item) - except Exception as e: - logger.error("Couldn't deserialize %s " % e) + except Exception: + continue return items diff --git a/neocore/IO/BinaryWriter.py b/neocore/IO/BinaryWriter.py index 1904eec..d84333a 100644 --- a/neocore/IO/BinaryWriter.py +++ b/neocore/IO/BinaryWriter.py @@ -12,8 +12,6 @@ import struct import binascii -from logzero import logger - from neocore.UInt160 import UInt160 from neocore.UInt256 import UInt256 @@ -279,12 +277,12 @@ def WriteUInt160(self, value): value (UInt160): Raises: - Exception: when `value` is not of neocore.UInt160 type. + TypeError: when `value` is not of neocore.UInt160 type. """ if type(value) is UInt160: value.Serialize(self) else: - raise Exception("value must be UInt160 instance ") + raise TypeError("Value must be UInt160 instance.") def WriteUInt256(self, value): """ @@ -294,12 +292,12 @@ def WriteUInt256(self, value): value (UInt256): Raises: - Exception: when `value` is not of neocore.UInt256 type. + TypeError: when `value` is not of neocore.UInt256 type. """ if type(value) is UInt256: value.Serialize(self) else: - raise Exception("Cannot write value that is not UInt256") + raise TypeError("Value must be UInt256 instance.") def WriteVarInt(self, value, endian="<"): """ @@ -310,18 +308,18 @@ def WriteVarInt(self, value, endian="<"): value (int): endian (str): specify the endianness. (Default) Little endian ('<'). Use '>' for big endian. - Raises: - TypeError: if `value` is not of type int. - Exception: if `value` is < 0. - Returns: int: the number of bytes written. + + Raises: + TypeError: if `value` is not of type int. + ValueError: if `value` is < 0. """ if not isinstance(value, int): - raise TypeError('%s not int type.' % value) + raise TypeError(f'{value} not int type.') if value < 0: - raise Exception('%d too small.' % value) + raise ValueError(f'{value} too small.') elif value < 0xfd: return self.WriteByte(value) @@ -381,11 +379,14 @@ def WriteFixedString(self, value, length): Args: value (str): value to write to the stream. length (int): length of the string to write. + + Raises: + ValueError: if the input `value` length is longer than the fixed `length` """ towrite = value.encode('utf-8') slen = len(towrite) if slen > length: - raise Exception("string longer than fixed length: %s " % length) + raise ValueError(f"String '{value}' length is longer than fixed length: {length}") self.WriteBytes(towrite) diff = length - slen @@ -431,7 +432,6 @@ def WriteHashes(self, arr): for item in arr: ba = bytearray(binascii.unhexlify(item)) ba.reverse() - # logger.info("WRITING HASH %s " % ba) self.WriteBytes(ba) def WriteFixed8(self, value, unsigned=False): diff --git a/neocore/KeyPair.py b/neocore/KeyPair.py index 62a99ef..db40a3f 100644 --- a/neocore/KeyPair.py +++ b/neocore/KeyPair.py @@ -45,6 +45,11 @@ def __init__(self, priv_key): Args: priv_key (bytes): a private key. + + Raises: + ValueError: + if the input `priv_key` length is not 32, 96, or 104 + if the input `priv_key` length is 32 but the public key still could not be determined """ self.setup_curve() @@ -60,8 +65,8 @@ def __init__(self, priv_key): if length == 32: try: pubkey_encoded_not_compressed = bitcoin.privkey_to_pubkey(priv_key) - except Exception as e: - raise Exception("Could not determine public key") + except Exception: + raise ValueError("Could not determine public key") elif length == 96 or length == 104: skip = length - 96 @@ -87,6 +92,12 @@ def PrivateKeyFromWIF(wif): Returns: bytes: The private key + + Raises: + ValueError: + if the input `wif` length != 52 + if the input `wif` has an invalid format + if the input `wif` has an invalid checksum """ if wif is None or len(wif) is not 52: raise ValueError('Please provide a wif with a length of 52 bytes (LEN: {0:d})'.format(len(wif))) @@ -116,6 +127,12 @@ def PrivateKeyFromNEP2(nep2_key, passphrase): Returns: bytes: The private key + + Raises: + ValueError: + if the input `nep2_key` length != 58 + if the input `nep2_key` is invalid + if the input `passphrase` is wrong """ if not nep2_key or len(nep2_key) != 58: raise ValueError('Please provide a nep2_key with a length of 58 bytes (LEN: {0:d})'.format(len(nep2_key))) @@ -125,7 +142,7 @@ def PrivateKeyFromNEP2(nep2_key, passphrase): try: decoded_key = base58.b58decode_check(nep2_key) - except Exception as e: + except Exception: raise ValueError("Invalid nep2_key") address_hash = decoded_key[ADDRESS_HASH_OFFSET:ADDRESS_HASH_OFFSET + ADDRESS_HASH_SIZE] @@ -195,6 +212,9 @@ def ExportNEP2(self, passphrase): Returns: str: The NEP-2 encrypted private key + + Raises: + ValueError: if the input `passphrase` length is < 2 """ if len(passphrase) < 2: raise ValueError("Passphrase must have a minimum of 2 characters") diff --git a/neocore/UInt160.py b/neocore/UInt160.py index 352fc84..d4f85f1 100644 --- a/neocore/UInt160.py +++ b/neocore/UInt160.py @@ -7,10 +7,16 @@ def __init__(self, data=None): @staticmethod def ParseString(value): + """ + Parse the input str `value` into UInt160 + + Raises: + ValueError: if the input `value` length (after '0x' if present) != 40 + """ if value[0:2] == '0x': value = value[2:] if not len(value) == 40: - raise Exception("Invalid UInt160 Format: %s chars != 40 chars" % len(value)) + raise ValueError(f"Invalid UInt160 input: {len(value)} chars != 40 chars") reversed_data = bytearray.fromhex(value) reversed_data.reverse() return UInt160(data=reversed_data) diff --git a/neocore/UInt256.py b/neocore/UInt256.py index 5ba634d..436edc8 100644 --- a/neocore/UInt256.py +++ b/neocore/UInt256.py @@ -7,10 +7,16 @@ def __init__(self, data=None): @staticmethod def ParseString(value): + """ + Parse the input str `value` into UInt256 + + Raises: + ValueError: if the input `value` length (after '0x' if present) != 64 + """ if value[0:2] == '0x': value = value[2:] if not len(value) == 64: - raise Exception("Invalid UInt256 Format: %s chars != 64 chars" % len(value)) + raise ValueError(f"Invalid UInt256 input: {len(value)} chars != 64 chars") reversed_data = bytearray.fromhex(value) reversed_data.reverse() return UInt256(data=reversed_data) diff --git a/neocore/UIntBase.py b/neocore/UIntBase.py index 42d60b0..fd1bad1 100644 --- a/neocore/UIntBase.py +++ b/neocore/UIntBase.py @@ -8,6 +8,17 @@ class UIntBase(SerializableMixin): __hash = None def __init__(self, num_bytes, data=None): + """ + Create an instance. + + Args: + num_bytes: (int) the length of data in bytes + data: (bytes, bytearray; optional) the raw data + + Raises: + ValueError: if the input `num_bytes` != the length of the input `data` + TypeError: if the input `data` is not bytes or bytearray + """ super(UIntBase, self).__init__() if data is None: @@ -15,14 +26,14 @@ def __init__(self, num_bytes, data=None): else: if len(data) != num_bytes: - raise Exception("Invalid UInt: data length {} != specified num_bytes {}".format(len(data), num_bytes)) + raise ValueError("Invalid UInt: data length {} != specified num_bytes {}".format(len(data), num_bytes)) if type(data) is bytes: self.Data = bytearray(data) elif type(data) is bytearray: self.Data = data else: - raise Exception("Invalid format") + raise TypeError(f"{type(data)} is invalid") self.__hash = self.GetHashCode() @@ -81,14 +92,21 @@ def __str__(self): return self.ToString() def CompareTo(self, other): + """ + Compare with another UIntBase + + Raises: + TypeError: if the input `other` is not UIntBase + ValueError: if the length of `self` != length of the input `other` + """ if not isinstance(other, UIntBase): - raise Exception('Cannot compare %s to type %s' % (type(self).__name__, type(other).__name__)) + raise TypeError('Cannot compare %s to type %s' % (type(self).__name__, type(other).__name__)) x = self.ToArray() y = other.ToArray() if len(x) != len(y): - raise Exception('Cannot compare %s with length %s to %s with length %s' % (type(self).__name__, len(x), type(other).__name__, len(y))) + raise ValueError('Cannot compare %s with length %s to %s with length %s' % (type(self).__name__, len(x), type(other).__name__, len(y))) length = len(x) diff --git a/requirements.txt b/requirements.txt index bb56053..de83888 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,6 @@ base58==1.0.3 bitcoin==1.1.42 ecdsa==0.13 -logzero==1.5.0 mpmath==1.1.0 pycryptodome==3.7.3 scrypt==0.8.13 diff --git a/tests/test_cryptography.py b/tests/test_cryptography.py index 127550a..7e8c6bf 100644 --- a/tests/test_cryptography.py +++ b/tests/test_cryptography.py @@ -109,12 +109,12 @@ def test_compute_root_multiple_hashes(self): self.assertEqual(expected_hash, root.ToArray()) def test_computer_root_no_input(self): - with self.assertRaises(Exception) as context: + with self.assertRaises(ValueError) as context: MerkleTree.ComputeRoot([]) self.assertTrue("Hashes must have length" in str(context.exception)) def test_build_no_leaves(self): - with self.assertRaises(Exception) as context: + with self.assertRaises(ValueError) as context: MerkleTree([]).__Build([]) self.assertTrue("Leaves must have length" in str(context.exception)) @@ -235,6 +235,21 @@ def test_sign_and_verify(self): verification_result = Crypto.VerifySignature(b'aabb', keypair_signature, keypair.PublicKey) self.assertFalse(verification_result) + def test_sign_and_verify_str(self): + privkey = KeyPair.PrivateKeyFromWIF("L44B5gGEpqEDRS9vVPz7QT35jcBG2r3CZwSwQ4fCewXAhAhqGVpP") + keypair = KeyPair(privkey) + hashdata = "74657374" + + keypair_signature = Crypto.Sign(hashdata, bytes(keypair.PrivateKey)) + keypair_signature2 = Crypto.Default().Sign(hashdata, bytes(keypair.PrivateKey)) + self.assertEqual(keypair_signature, keypair_signature2) + + # verify without unhexing + verification_result = Crypto.VerifySignature("test", keypair_signature, keypair.PublicKey, unhex=False) + verification_result2 = Crypto.Default().VerifySignature("test", keypair_signature, keypair.PublicKey, unhex=False) + self.assertEqual(verification_result, verification_result2) + self.assertTrue(verification_result) + def test_script_hash(self): # Expected output taken from running: getHash(Buffer.from('abc', 'utf8')).toString('hex') # using https://github.com/CityOfZion/neon-wallet-react-native/blob/master/app/api/crypto/index.js @@ -243,12 +258,10 @@ def test_script_hash(self): result = Crypto.Default().Hash160(b'abc') self.assertEqual(expected_result, binascii.hexlify(result)) - @patch('neocore.Cryptography.Crypto.logger') - def test_faulty_message_param_to_verify_signature(self, mocked_logger): + def test_faulty_message_param_to_verify_signature(self): faulty_message = bytes.fromhex('aa') # faulty because the message should be non-raw bytes. i.e. b'aa' fake_signature = bytes.fromhex('aabb') # irrelevant for the test fake_pubkey = bytes.fromhex('aabb') # irrelevant for the test result = Crypto.VerifySignature(faulty_message, fake_signature, fake_pubkey) - self.assertTrue(mocked_logger.error.called) self.assertFalse(result) diff --git a/tests/test_io.py b/tests/test_io.py index f95752a..32128ab 100644 --- a/tests/test_io.py +++ b/tests/test_io.py @@ -50,16 +50,15 @@ def test_various(self): self.assertEqual(self.br.unpack("c"), b"A") b = self.br.ReadByte() - self.assertEqual(b, 1) + self.assertEqual(b, b'\x01') - b = self.br.ReadByte(do_ord=False) + b = self.br.ReadByte() self.assertEqual(b, b"\x02") bio0 = BytesIO(b"") br0 = BinaryReader(bio0) - b = br0.ReadByte() - self.assertEqual(b, 0) - # print("===", b) + with self.assertRaises(ValueError): + br0.ReadByte() b = self.br.ReadBool() self.assertEqual(b, True) @@ -99,8 +98,9 @@ def test_varint(self): self.assertEqual(get_br(b"\xfe1234").ReadVarInt(), 875770417) self.assertEqual(get_br(b"\xff12345678").ReadVarInt(), 4050765991979987505) - with self.assertRaises(Exception): + with self.assertRaises(ValueError) as context: self.assertEqual(get_br(b"\xfd1234").ReadVarInt(max=12848), 12849) + self.assertIn("Maximum number of bytes (12848) exceeded.", context) def test_Read2000256List(self): val = b"1" * 64 @@ -240,7 +240,7 @@ def bw_setup(): stream.seek(0) self.assertEqual(stream.readline(), b'\x124Vx\x90\x124Vx\x90') - with self.assertRaises(Exception): + with self.assertRaises(TypeError): bw.WriteUInt160(123) stream, bw = bw_setup() @@ -248,13 +248,13 @@ def bw_setup(): stream.seek(0) self.assertEqual(stream.readline(), b'\x124Vx\x90\x124Vx\x90\x124Vx\x90\x12') - with self.assertRaises(Exception): + with self.assertRaises(TypeError): bw.WriteUInt256(123) with self.assertRaises(TypeError): bw.WriteVarInt("x") - with self.assertRaises(Exception): + with self.assertRaises(ValueError): bw.WriteVarInt(-1) stream, bw = bw_setup() @@ -347,6 +347,6 @@ def test_writefixedstring_exception(self): stream = BytesIO() bw = BinaryWriter.BinaryWriter(stream) - with self.assertRaises(Exception) as context: + with self.assertRaises(ValueError) as context: bw.WriteFixedString("abc", 2) - self.assertTrue("string longer than fixed length" in str(context.exception)) + self.assertIn("String 'abc' length is longer than fixed length: 2", str(context.exception)) diff --git a/tests/test_numbers.py b/tests/test_numbers.py index ad0704c..59bffa3 100644 --- a/tests/test_numbers.py +++ b/tests/test_numbers.py @@ -114,7 +114,6 @@ def test_various_methods(self): zero = Fixed8.TryParse(0) self.assertEqual(zero, Fixed8(0)) - # with self.assertRaises(Exception): self.assertEqual(Fixed8.TryParse("foo"), None) self.assertEqual(Fixed8.TryParse(-1, require_positive=True), None) @@ -339,11 +338,11 @@ def test_initialization_with_bytearray(self): self.assertEqual(hash(u1), 6513249) def test_initialization_with_invalid_datalen(self): - with self.assertRaises(Exception): + with self.assertRaises(ValueError): UIntBase(3, bytearray(b'abcd')) def test_initialization_with_invalid_datatype(self): - with self.assertRaises(Exception): + with self.assertRaises(TypeError): UIntBase(3, 'abc') def test_size(self): @@ -438,17 +437,17 @@ def test_compareto_valid(self): def test_compareto_invalid_datatype(self): u1 = UIntBase(20, b'12345678901234567890') - with self.assertRaises(Exception): + with self.assertRaises(TypeError): self.assertEqual(u1.CompareTo('asd'), 0) - with self.assertRaises(Exception): + with self.assertRaises(TypeError): self.assertEqual(u1.CompareTo(b'asd'), 0) - with self.assertRaises(Exception): + with self.assertRaises(TypeError): self.assertEqual(u1.CompareTo(123), 0) # Cannot compare uints with different lengths - with self.assertRaises(Exception): + with self.assertRaises(ValueError): a = UInt256(b'12345678901234567890123456789012') b = UIntBase(20, b'12345678901234567890') a.CompareTo(b) @@ -485,8 +484,8 @@ def test_initialization(self): self.assertEqual(hash(u1), 875770417) def test_initialization_invalid_length(self): - with self.assertRaises(Exception): - u1 = UInt160(b'12345') + with self.assertRaises(ValueError): + UInt160(b'12345') def test_parse(self): string = '0xd7678dd97c000be3f33e9362e673101bac4ca654' @@ -500,8 +499,9 @@ def test_parse(self): self.assertEqual(uint160.ToString(), string) string = '5b7074e873973a6ed3708862f219a6fbf4d1c41' - with self.assertRaises(Exception) as context: + with self.assertRaises(ValueError) as context: uint160 = UInt160.ParseString(string) + self.assertIn(f"Invalid UInt160 input: {len(string)} chars != 40 chars", context) class UInt256TestCase(TestCase): @@ -513,11 +513,11 @@ def test_initialization(self): self.assertEqual(hash(u1), 875770417) def test_initialization_invalid(self): - with self.assertRaises(Exception): - u1 = UInt256(b'12345') + with self.assertRaises(ValueError): + UInt256(b'12345') - with self.assertRaises(Exception): - u1 = UInt256('12345678901234567890123456789012') + with self.assertRaises(TypeError): + UInt256('12345678901234567890123456789012') def test_parse(self): string = '0xcedb5c4e24b1f6fc5b239f2d1049c3229ad5ed05293c696b3740dc236c3f41b4' @@ -531,5 +531,6 @@ def test_parse(self): self.assertEqual(uint256.ToString(), string) string = '9410bd44beb7d6febc9278b028158af2781fcfb40cf2c6067b3525d24eff19f' - with self.assertRaises(Exception) as context: + with self.assertRaises(ValueError) as context: uint256 = UInt256.ParseString(string) + self.assertIn(f"Invalid UInt256 input: {len(string)} chars != 64 chars", context)