def test_point_rejects_larger_than_curve_p(a, b): '''Point raises ValueError if x or y coordinate is larger than curve's prime.''' with pytest.raises(ValueError): Point(a, b) with pytest.raises(ValueError): Point(b, a)
def test_point_rejects_negative_coordinates(a, b): '''Point raises ValueError if any coordinate is smaller than 0.''' with pytest.raises(ValueError): Point(a, b) with pytest.raises(ValueError): Point(b, a)
def test_point_from_x(coords): '''Constructing a point from the x coordinate should respect the given parity and return a point with the valid y''' assume(coords != (0, 0)) x, y = coords assert Point.from_x(x, Parity(y & 1)).y == y assert Point.from_x(x, Parity(1 - y & 1)).y == secp256k1.p - y
def test_public_key_to_address(coords, compressed, testnet): address = PublicKey(Point(*coords), testnet=testnet).to_address(compressed=compressed) expected_prefixes = ['1'] if not testnet else ['m', 'n'] assert address[0] in expected_prefixes
def derive_public_child(self, index: int) -> ExtendedPublicKey: if index >= HARDENED_CHILD_INDEX: raise ValueError('Cannot derive hardened public keys!') data = self.key.encode() + index.to_bytes(4, byteorder=BIG) out = hmac_sha512(key=self.chain_code, msg=data) out_l = int.from_bytes(out[:32], byteorder=BIG) out_r = out[32:] if out_l >= secp256k1.n: raise UseNextIndex child_key_point = PrivateKey(k=out_l).generate_public_key().point + self.key.point if child_key_point == Point.inf(): raise UseNextIndex child_key = PublicKey(point=child_key_point, testnet=self.key.testnet) return ExtendedPublicKey( key=child_key, chain_code=out_r, depth=self.depth + 1, parent_fingerprint=self.key.get_identifier()[:4], index=index, )
def test_neg(coords): assume(coords != (0, 0)) p = Point(*coords) p_ = -p assert p.x == p_.x and p.y + p_.y == secp256k1.p
def test_mul_other_not_int(coords): p = Point(*coords) with pytest.raises(ValueError): p * p with pytest.raises(ValueError): p * 1.2
def test_public_key_get_identifier(coords, compressed): pubk = PublicKey(point=Point(*coords)) with patch("pybitcoin.keys.sha256") as mock_sha256, patch( "pybitcoin.keys.ripemd160") as mock_ripemd160: pubk.get_identifier(compressed=compressed) assert mock_ripemd160.call_count == 1 assert mock_ripemd160.call_args == call(mock_sha256.return_value)
def test_public_key_encode(coords, compressed): data = PublicKey(point=Point(*coords)).encode(compressed=compressed) if compressed: expected_length = 33 if coords[1] % 2 == 0: expected_prefix = b"\x02" else: expected_prefix = b"\x03" else: expected_length = 65 expected_prefix = b"\x04" assert len(data) == expected_length assert data[0:1] == expected_prefix
def test_inf(): '''Return the point at infinity.''' inf = Point.inf() assert inf.x == inf.y == 0
def test_mul(data): coords_1, x, coords_2 = data p1 = Point(*coords_1) p2 = Point(*coords_2) assert p1 * x == x * p1 == p2
def test_public_key_x_y_properties(coords): pubk = PublicKey(point=Point(*coords)) assert (pubk.x, pubk.y) == coords
def test_add(data): coords_1, coords_2, coords_res = data p1 = Point(*coords_1) p2 = Point(*coords_2) assert p1 + p2 == Point(*coords_res)
def generate_public_key(self): return PublicKey(point=self.k * Point.gen(), testnet=self.testnet)
def test_add_infinity(coords): p = Point(*coords) inf = Point.inf() assert p + inf == inf + p == p
def test_point_eq(coords_1, coords_2): assume(coords_1 != coords_2) assert Point(*coords_1) == Point(*coords_1) assert Point(*coords_2) == Point(*coords_2) assert Point(*coords_1) != Point(*coords_2)
def test_neg_infinity(): p = Point.inf() p_ = -p assert p == p_
def test_point_rejects_coordinates_not_on_curve(x, y): '''Point raises ValueError if coordinates are not on SECP256K1 curve.''' assume((pow(y, 2, secp256k1.p) - pow(x, 3, secp256k1.p) - 7 % secp256k1.p) != 0) with pytest.raises(ValueError): Point(x, y)
def test_point_accepts_coordinates_on_curve(coords): '''Point constructor doesn't raise for valid coordinates on SECP256K1 curve.''' Point(*coords)
def test_private_key_generate_public_key(k, compressed): prv = PrivateKey(k=k, compressed=compressed) pub = prv.generate_public_key() assert k * Point.gen() == Point(pub.x, pub.y)
def test_gen(): '''Return the generator point of current curve.''' gen = Point.gen() assert gen.x == Point.curve.g_x and gen.y == Point.curve.g_y