from chia_rs import Coin
from hashlib import sha256
import copy
import pytest
from chia_rs.sized_ints import uint64
parent_coin = b"---foo--- "
puzzle_hash = b"---bar--- "
puzzle_hash2 = b"---bar--- 2 "
def test_coin_name() -> None:
c = Coin(parent_coin, puzzle_hash, uint64(0))
assert c.name() == sha256(parent_coin + puzzle_hash).digest()
c = Coin(parent_coin, puzzle_hash, uint64(1))
assert c.name() == sha256(parent_coin + puzzle_hash + bytes([1])).digest()
c = Coin(parent_coin, puzzle_hash, uint64(0xFF))
assert c.name() == sha256(parent_coin + puzzle_hash + bytes([0, 0xFF])).digest()
c = Coin(parent_coin, puzzle_hash, uint64(0xFFFF))
assert (
c.name() == sha256(parent_coin + puzzle_hash + bytes([0, 0xFF, 0xFF])).digest()
)
c = Coin(parent_coin, puzzle_hash, uint64(0xFFFFFF))
assert (
c.name()
== sha256(parent_coin + puzzle_hash + bytes([0, 0xFF, 0xFF, 0xFF])).digest()
)
c = Coin(parent_coin, puzzle_hash, uint64(0xFFFFFFFF))
assert (
c.name()
== sha256(
parent_coin + puzzle_hash + bytes([0, 0xFF, 0xFF, 0xFF, 0xFF])
).digest()
)
c = Coin(parent_coin, puzzle_hash, uint64(0xFFFFFFFFFF))
assert (
c.name()
== sha256(
parent_coin + puzzle_hash + bytes([0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
).digest()
)
c = Coin(parent_coin, puzzle_hash, uint64(0xFFFFFFFFFFFF))
assert (
c.name()
== sha256(
parent_coin + puzzle_hash + bytes([0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
).digest()
)
c = Coin(parent_coin, puzzle_hash, uint64(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, uint64(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, uint64(0x7F))
assert c.name() == sha256(parent_coin + puzzle_hash + bytes([0x7F])).digest()
c = Coin(parent_coin, puzzle_hash, uint64(0x7FFF))
assert c.name() == sha256(parent_coin + puzzle_hash + bytes([0x7F, 0xFF])).digest()
c = Coin(parent_coin, puzzle_hash, uint64(0x7FFFFF))
assert (
c.name()
== sha256(parent_coin + puzzle_hash + bytes([0x7F, 0xFF, 0xFF])).digest()
)
c = Coin(parent_coin, puzzle_hash, uint64(0x7FFFFFFF))
assert (
c.name()
== sha256(parent_coin + puzzle_hash + bytes([0x7F, 0xFF, 0xFF, 0xFF])).digest()
)
c = Coin(parent_coin, puzzle_hash, uint64(0x7FFFFFFFFF))
assert (
c.name()
== sha256(
parent_coin + puzzle_hash + bytes([0x7F, 0xFF, 0xFF, 0xFF, 0xFF])
).digest()
)
c = Coin(parent_coin, puzzle_hash, uint64(0x7FFFFFFFFFFF))
assert (
c.name()
== sha256(
parent_coin + puzzle_hash + bytes([0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
).digest()
)
c = Coin(parent_coin, puzzle_hash, uint64(0x7FFFFFFFFFFFFF))
assert (
c.name()
== sha256(
parent_coin
+ puzzle_hash
+ bytes([0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
).digest()
)
c = Coin(parent_coin, puzzle_hash, uint64(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, uint64(0x80))
assert c.name() == sha256(parent_coin + puzzle_hash + bytes([0, 0x80])).digest()
c = Coin(parent_coin, puzzle_hash, uint64(0x8000))
assert c.name() == sha256(parent_coin + puzzle_hash + bytes([0, 0x80, 0])).digest()
c = Coin(parent_coin, puzzle_hash, uint64(0x800000))
assert (
c.name() == sha256(parent_coin + puzzle_hash + bytes([0, 0x80, 0, 0])).digest()
)
c = Coin(parent_coin, puzzle_hash, uint64(0x80000000))
assert (
c.name()
== sha256(parent_coin + puzzle_hash + bytes([0, 0x80, 0, 0, 0])).digest()
)
c = Coin(parent_coin, puzzle_hash, uint64(0x8000000000))
assert (
c.name()
== sha256(parent_coin + puzzle_hash + bytes([0, 0x80, 0, 0, 0, 0])).digest()
)
c = Coin(parent_coin, puzzle_hash, uint64(0x800000000000))
assert (
c.name()
== sha256(parent_coin + puzzle_hash + bytes([0, 0x80, 0, 0, 0, 0, 0])).digest()
)
c = Coin(parent_coin, puzzle_hash, uint64(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, uint64(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, uint64(1000000))
c2 = copy.copy(c1)
assert c1 == c2
assert c1 is not c2
def test_coin_deepcopy() -> None:
c1 = Coin(parent_coin, puzzle_hash, uint64(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, uint64(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, uint64(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, uint64(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, uint64(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, uint64(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, uint64(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,
uint64(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, uint64(1000000))
c2 = Coin(parent_coin, puzzle_hash2, uint64(1000000))
c3 = Coin(parent_coin, puzzle_hash, uint64(2000000))
c4 = Coin(parent_coin, puzzle_hash, uint64(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
def test_coin_fields() -> None:
c1 = Coin(parent_coin, puzzle_hash, uint64(1000000))
assert c1.parent_coin_info == parent_coin
assert c1.puzzle_hash == puzzle_hash
assert c1.amount == 1000000