from chia_rs import Coin
from hashlib import sha256
import copy
import pytest
parent_coin = b"---foo--- "
puzzle_hash = b"---bar--- "
puzzle_hash2 = b"---bar--- 2 "
def test_coin_name() -> None:
c = Coin(parent_coin, puzzle_hash, 0)
assert c.name() == sha256(parent_coin + puzzle_hash).digest()
c = Coin(parent_coin, puzzle_hash, 1)
assert c.name() == sha256(parent_coin + puzzle_hash + bytes([1])).digest()
c = Coin(parent_coin, puzzle_hash, 0xFF)
assert c.name() == sha256(parent_coin + puzzle_hash + bytes([0, 0xFF])).digest()
c = Coin(parent_coin, puzzle_hash, 0xFFFF)
assert (
c.name() == sha256(parent_coin + puzzle_hash + bytes([0, 0xFF, 0xFF])).digest()
)
c = Coin(parent_coin, puzzle_hash, 0xFFFFFF)
assert (
c.name()
== sha256(parent_coin + puzzle_hash + bytes([0, 0xFF, 0xFF, 0xFF])).digest()
)
c = Coin(parent_coin, puzzle_hash, 0xFFFFFFFF)
assert (
c.name()
== sha256(
parent_coin + puzzle_hash + bytes([0, 0xFF, 0xFF, 0xFF, 0xFF])
).digest()
)
c = Coin(parent_coin, puzzle_hash, 0xFFFFFFFFFF)
assert (
c.name()
== sha256(
parent_coin + puzzle_hash + bytes([0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
).digest()
)
c = Coin(parent_coin, puzzle_hash, 0xFFFFFFFFFFFF)
assert (
c.name()
== sha256(
parent_coin + puzzle_hash + bytes([0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
).digest()
)
c = Coin(parent_coin, puzzle_hash, 0xFFFFFFFFFFFFFF)
assert (
c.name()
== sha256(
parent_coin
+ puzzle_hash
+ bytes([0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
).digest()
)
c = Coin(parent_coin, puzzle_hash, 0xFFFFFFFFFFFFFFFF)
assert (
c.name()
== sha256(
parent_coin
+ puzzle_hash
+ bytes([0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
).digest()
)
c = Coin(parent_coin, puzzle_hash, 0x7F)
assert c.name() == sha256(parent_coin + puzzle_hash + bytes([0x7F])).digest()
c = Coin(parent_coin, puzzle_hash, 0x7FFF)
assert c.name() == sha256(parent_coin + puzzle_hash + bytes([0x7F, 0xFF])).digest()
c = Coin(parent_coin, puzzle_hash, 0x7FFFFF)
assert (
c.name()
== sha256(parent_coin + puzzle_hash + bytes([0x7F, 0xFF, 0xFF])).digest()
)
c = Coin(parent_coin, puzzle_hash, 0x7FFFFFFF)
assert (
c.name()
== sha256(parent_coin + puzzle_hash + bytes([0x7F, 0xFF, 0xFF, 0xFF])).digest()
)
c = Coin(parent_coin, puzzle_hash, 0x7FFFFFFFFF)
assert (
c.name()
== sha256(
parent_coin + puzzle_hash + bytes([0x7F, 0xFF, 0xFF, 0xFF, 0xFF])
).digest()
)
c = Coin(parent_coin, puzzle_hash, 0x7FFFFFFFFFFF)
assert (
c.name()
== sha256(
parent_coin + puzzle_hash + bytes([0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
).digest()
)
c = Coin(parent_coin, puzzle_hash, 0x7FFFFFFFFFFFFF)
assert (
c.name()
== sha256(
parent_coin
+ puzzle_hash
+ bytes([0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
).digest()
)
c = Coin(parent_coin, puzzle_hash, 0x7FFFFFFFFFFFFFFF)
assert (
c.name()
== sha256(
parent_coin
+ puzzle_hash
+ bytes([0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
).digest()
)
c = Coin(parent_coin, puzzle_hash, 0x80)
assert c.name() == sha256(parent_coin + puzzle_hash + bytes([0, 0x80])).digest()
c = Coin(parent_coin, puzzle_hash, 0x8000)
assert (
c.name() == sha256(parent_coin + puzzle_hash + bytes([0, 0x80, 0])).digest()
)
c = Coin(parent_coin, puzzle_hash, 0x800000)
assert (
c.name()
== sha256(parent_coin + puzzle_hash + bytes([0, 0x80, 0, 0])).digest()
)
c = Coin(parent_coin, puzzle_hash, 0x80000000)
assert (
c.name()
== sha256(
parent_coin + puzzle_hash + bytes([0, 0x80, 0, 0, 0])
).digest()
)
c = Coin(parent_coin, puzzle_hash, 0x8000000000)
assert (
c.name()
== sha256(
parent_coin + puzzle_hash + bytes([0, 0x80, 0, 0, 0, 0])
).digest()
)
c = Coin(parent_coin, puzzle_hash, 0x800000000000)
assert (
c.name()
== sha256(
parent_coin + puzzle_hash + bytes([0, 0x80, 0, 0, 0, 0, 0])
).digest()
)
c = Coin(parent_coin, puzzle_hash, 0x80000000000000)
assert (
c.name()
== sha256(
parent_coin
+ puzzle_hash
+ bytes([0, 0x80, 0, 0, 0, 0, 0, 0])
).digest()
)
c = Coin(parent_coin, puzzle_hash, 0x8000000000000000)
assert (
c.name()
== sha256(
parent_coin
+ puzzle_hash
+ bytes([0, 0x80, 0, 0, 0, 0, 0, 0, 0])
).digest()
)
def test_coin_copy() -> None:
c1 = Coin(parent_coin, puzzle_hash, 1000000)
c2 = copy.copy(c1)
assert c1 == c2
assert c1 is not c2
def test_coin_deepcopy() -> None:
c1 = Coin(parent_coin, puzzle_hash, 1000000)
c2 = copy.deepcopy(c1)
assert c1 == c2
assert c1 is not c2
def coin_json_roundtrip(c: Coin) -> bool:
d = c.to_json_dict()
c2 = Coin.from_json_dict(d)
return c == c2 and c.name() == c2.name()
def test_coin_to_json() -> None:
c1 = Coin(parent_coin, puzzle_hash, 1000000)
assert c1.to_json_dict() == {
"parent_coin_info": "0x" + parent_coin.hex(),
"puzzle_hash": "0x" + puzzle_hash.hex(),
"amount": 1000000,
}
assert coin_json_roundtrip(c1)
c2 = Coin(parent_coin, puzzle_hash2, 0)
assert c2.to_json_dict() == {
"parent_coin_info": "0x" + parent_coin.hex(),
"puzzle_hash": "0x" + puzzle_hash2.hex(),
"amount": 0,
}
assert coin_json_roundtrip(c2)
c3 = Coin(parent_coin, puzzle_hash2, 0xFFFFFFFFFFFFFFFF)
assert c3.to_json_dict() == {
"parent_coin_info": "0x" + parent_coin.hex(),
"puzzle_hash": "0x" + puzzle_hash2.hex(),
"amount": 0xFFFFFFFFFFFFFFFF,
}
assert coin_json_roundtrip(c3)
def test_coin_from_json() -> None:
c = {
"parent_coin_info": "0x" + parent_coin.hex(),
"puzzle_hash": "0x" + puzzle_hash2.hex(),
"amount": 12345678,
}
assert Coin.from_json_dict(c) == Coin(parent_coin, puzzle_hash2, 12345678)
def test_coin_from_json_upper_hex() -> None:
c = {
"parent_coin_info": "0x" + parent_coin.hex().upper(),
"puzzle_hash": "0x" + puzzle_hash2.hex().upper(),
"amount": 12345678,
}
assert Coin.from_json_dict(c) == Coin(parent_coin, puzzle_hash2, 12345678)
def test_coin_from_json_lower_hex() -> None:
c = {
"parent_coin_info": "0x" + parent_coin.hex().lower(),
"puzzle_hash": "0x" + puzzle_hash2.hex().lower(),
"amount": 12345678,
}
assert Coin.from_json_dict(c) == Coin(parent_coin, puzzle_hash2, 12345678)
def test_coin_from_json_invalid_hex_prefix() -> None:
c = {
"parent_coin_info": parent_coin.hex(),
"puzzle_hash": "0x" + puzzle_hash2.hex(),
"amount": 12345678,
}
with pytest.raises(ValueError, match="bytes object is expected to start with 0x"):
Coin.from_json_dict(c)
def test_coin_from_json_invalid_hex_prefix2() -> None:
c = {
"parent_coin_info": "0x" + parent_coin.hex(),
"puzzle_hash": puzzle_hash2.hex(),
"amount": 12345678,
}
with pytest.raises(ValueError, match="bytes object is expected to start with 0x"):
Coin.from_json_dict(c)
def test_coin_from_json_hex_digit() -> None:
c = {
"parent_coin_info": "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"puzzle_hash": "0x" + puzzle_hash2.hex(),
"amount": 12345678,
}
assert Coin.from_json_dict(c) == Coin(
bytes.fromhex(
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
),
puzzle_hash2,
12345678,
)
def test_coin_from_json_invalid_hex_digit() -> None:
c = {
"parent_coin_info": "0x0123456789abcdef0123456789abcdef0123456789abcdefg123456789abcdef",
"puzzle_hash": "0x" + puzzle_hash2.hex(),
"amount": 12345678,
}
with pytest.raises(ValueError, match="invalid hex"):
Coin.from_json_dict(c)
def test_coin_from_json_invalid_hex_len() -> None:
c = {
"parent_coin_info": "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde",
"puzzle_hash": "0x" + puzzle_hash2.hex(),
"amount": 12345678,
}
with pytest.raises(ValueError, match="invalid hex"):
Coin.from_json_dict(c)
def test_coin_from_json_invalid_hex_len2() -> None:
c = {
"parent_coin_info": "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcd",
"puzzle_hash": "0x" + puzzle_hash2.hex(),
"amount": 12345678,
}
with pytest.raises(ValueError, match="invalid length 31 expected 32"):
Coin.from_json_dict(c)
def test_coin_from_json_missing_field1() -> None:
c = {
"puzzle_hash": "0x" + puzzle_hash2.hex(),
"amount": 12345678,
}
with pytest.raises(KeyError, match="parent_coin_info"):
Coin.from_json_dict(c)
def test_coin_from_json_missing_field2() -> None:
c = {
"parent_coin_info": "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"amount": 12345678,
}
with pytest.raises(KeyError, match="puzzle_hash"):
Coin.from_json_dict(c)
def test_coin_from_json_missing_field3() -> None:
c = {
"parent_coin_info": "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"puzzle_hash": "0x" + puzzle_hash2.hex(),
}
with pytest.raises(KeyError, match="amount"):
Coin.from_json_dict(c)
def test_coin_hash() -> None:
c1 = Coin(parent_coin, puzzle_hash, 1000000)
c2 = Coin(parent_coin, puzzle_hash2, 1000000)
c3 = Coin(parent_coin, puzzle_hash, 2000000)
c4 = Coin(parent_coin, puzzle_hash, 1000000)
assert hash(c1) != hash(c2)
assert hash(c1) != hash(c3)
assert hash(c2) != hash(c3)
assert hash(c1) == hash(c4)
assert type(hash(c1)) is int