Skip to content

Commit 86d9f28

Browse files
committed
ergo-lib-python: add unit tests
1 parent 17a5bd7 commit 86d9f28

File tree

5 files changed

+105
-39
lines changed

5 files changed

+105
-39
lines changed

bindings/ergo-lib-python/src/chain/address.rs

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -17,48 +17,12 @@ impl From<NetworkPrefix> for address::NetworkPrefix {
1717
}
1818
}
1919

20-
/**
21-
* An address is a short string corresponding to some script used to protect a box. Unlike (string-encoded) binary
22-
* representation of a script, an address has some useful characteristics:
23-
*
24-
* - Integrity of an address could be checked., as it is incorporating a checksum.
25-
* - A prefix of address is showing network and an address type.
26-
* - An address is using an encoding (namely, Base58) which is avoiding similarly l0Oking characters, friendly to
27-
* double-clicking and line-breaking in emails.
28-
*
29-
*
30-
*
31-
* An address is encoding network type, address type, checksum, and enough information to watch for a particular scripts.
32-
*
33-
* Possible network types are:
34-
* Mainnet - 0x00
35-
* Testnet - 0x10
36-
*
37-
* For an address type, we form content bytes as follows:
38-
*
39-
* P2PK - serialized (compressed) public key
40-
* P2SH - first 192 bits of the Blake2b256 hash of serialized script bytes
41-
* P2S - serialized script
42-
*
43-
* Address examples for testnet:
44-
*
45-
* 3 - P2PK (3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN)
46-
* ? - P2SH (rbcrmKEYduUvADj9Ts3dSVSG27h54pgrq5fPuwB)
47-
* ? - P2S (Ms7smJwLGbUAjuWQ)
48-
*
49-
* for mainnet:
50-
*
51-
* 9 - P2PK (9fRAWhdxEsTcdb8PhGNrZfwqa65zfkuYHAMmkQLcic1gdLSV5vA)
52-
* ? - P2SH (8UApt8czfFVuTgQmMwtsRBZ4nfWquNiSwCWUjMg)
53-
* ? - P2S (4MQyML64GnzMxZgm, BxKBaHkvrTvLZrDcZjcsxsF7aSsrN73ijeFZXtbj4CXZHHcvBtqSxQ)
54-
*/
5520
#[pyclass(eq, frozen)]
5621
#[derive(From, Into, Clone, PartialEq, Eq)]
5722
pub(crate) struct Address(pub(crate) address::Address);
5823

5924
#[pymethods]
6025
impl Address {
61-
/// Build a new address from a str, ErgoTree or bytes
6226
#[new]
6327
#[pyo3(signature = (arg, network_prefix=None))]
6428
fn new(arg: &Bound<'_, PyAny>, network_prefix: Option<NetworkPrefix>) -> PyResult<Self> {
@@ -90,15 +54,12 @@ impl Address {
9054
fn p2pk(_: &Bound<'_, PyType>, prove_dlog: ProveDlog) -> Address {
9155
address::Address::P2Pk(prove_dlog.into()).into()
9256
}
93-
/// Re-create the address from ErgoTree that was built from the address
94-
/// This is the inverse of Address.ergo_tree()
9557
#[classmethod]
9658
fn recreate_from_ergo_tree(_: &Bound<'_, PyType>, tree: &ErgoTree) -> PyResult<Self> {
9759
address::Address::recreate_from_ergo_tree(&tree.0)
9860
.map(Self)
9961
.map_err(to_value_error)
10062
}
101-
/// Create an ErgoTree script from the address
10263
pub(crate) fn ergo_tree(&self) -> PyResult<ErgoTree> {
10364
self.0.script().map(Into::into).map_err(to_value_error)
10465
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import unittest
2+
from ergo_lib_python.chain import Address, NetworkPrefix
3+
4+
class AddressTests(unittest.TestCase):
5+
def test_from_str(self):
6+
testnet_address_str = "3WvsT2Gm4EpsM9Pg18PdY6XyhNNMqXDsvJTbbf6ihLvAmSb7u5RN"
7+
testnet_address = Address(testnet_address_str)
8+
self.assertEqual(testnet_address.to_str(NetworkPrefix.Testnet), testnet_address_str)
9+
with self.assertRaises(ValueError):
10+
Address(testnet_address_str, network_prefix=NetworkPrefix.Mainnet)
11+
tree = testnet_address.ergo_tree()
12+
self.assertEqual(Address.recreate_from_ergo_tree(tree), testnet_address)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import unittest
2+
from ergo_lib_python.chain import Constant, SType, ErgoBox
3+
4+
class TestConstant(unittest.TestCase):
5+
def test_i32(self):
6+
c = Constant.from_i32(999)
7+
self.assertEqual(c.tpe, SType.SInt())
8+
encoded = bytes(c)
9+
decoded = Constant.from_bytes(encoded)
10+
self.assertEqual(c, decoded)
11+
with self.assertRaises(OverflowError):
12+
Constant.from_i32(2 ** 31)
13+
with self.assertRaises(OverflowError):
14+
Constant.from_i32(-(2 ** 31) - 1)
15+
16+
def test_i64(self):
17+
c = Constant.from_i64(999)
18+
self.assertEqual(c.tpe, SType.SLong())
19+
encoded: bytes = bytes(c)
20+
decoded = Constant.from_bytes(encoded)
21+
self.assertEqual(c, decoded)
22+
with self.assertRaises(OverflowError):
23+
Constant.from_i64(2 ** 63)
24+
with self.assertRaises(OverflowError):
25+
Constant.from_i32(-(2 ** 63) - 1)
26+
def test_bytes(self):
27+
b = bytes([1, 1, 2, 255])
28+
c = Constant(b)
29+
self.assertEqual(c.tpe, SType.SColl(SType.SByte()))
30+
encoded = bytes(c)
31+
decoded = Constant.from_bytes(encoded)
32+
self.assertEqual(c, decoded)
33+
def test_tuple(self):
34+
box = ErgoBox.from_json("""
35+
{
36+
"boxId": "e56847ed19b3dc6b72828fcfb992fdf7310828cf291221269b7ffc72fd66706e",
37+
"value": 67500000000,
38+
"ergoTree": "100204a00b08cd021dde34603426402615658f1d970cfa7c7bd92ac81a8b16eeebff264d59ce4604ea02d192a39a8cc7a70173007301",
39+
"assets": [],
40+
"creationHeight": 284761,
41+
"additionalRegisters": {},
42+
"transactionId": "9148408c04c2e38a6402a7950d6157730fa7d49e9ab3b9cadec481d7769918e9",
43+
"index": 1
44+
}
45+
""")
46+
c = Constant((Constant.from_i32(1), Constant(box), Constant(bytes([1, 2]))))
47+
self.assertEqual(c.value, (Constant.from_i32(1), Constant(box), Constant(bytes([1, 2]))))
48+
self.assertEqual(c.tpe, SType.STuple((SType.SInt(), SType.SBox(), SType.SColl(SType.SByte()))))
49+
#test that pattern matching works
50+
match c.tpe:
51+
case SType.STuple((SType.SInt(), SType.SBox(), SType.SColl(SType.SByte()))):
52+
...
53+
case _:
54+
assert False
55+
encoded = bytes(c)
56+
decoded = Constant.from_bytes(encoded)
57+
self.assertEqual(c, decoded)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import unittest
2+
from ergo_lib_python.chain import BoxId, ErgoBox
3+
import json
4+
5+
class ErgoBoxTests(unittest.TestCase):
6+
def test_json(self):
7+
box_json = """
8+
{
9+
"boxId": "e56847ed19b3dc6b72828fcfb992fdf7310828cf291221269b7ffc72fd66706e",
10+
"value": 67500000000,
11+
"ergoTree": "100204a00b08cd021dde34603426402615658f1d970cfa7c7bd92ac81a8b16eeebff264d59ce4604ea02d192a39a8cc7a70173007301",
12+
"assets": [],
13+
"creationHeight": 284761,
14+
"additionalRegisters": {},
15+
"transactionId": "9148408c04c2e38a6402a7950d6157730fa7d49e9ab3b9cadec481d7769918e9",
16+
"index": 1
17+
}
18+
"""
19+
box = ErgoBox.from_json(box_json)
20+
# test equivalence between from_json(str) and from_json(dict)
21+
self.assertEqual(box, ErgoBox.from_json(json.loads(box_json)))
22+
self.assertEqual(box.box_id, BoxId("e56847ed19b3dc6b72828fcfb992fdf7310828cf291221269b7ffc72fd66706e"))
23+
self.assertEqual(box.creation_height, 284761)
24+
self.assertEqual(box.value, 67500000000)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import unittest
2+
import base64
3+
from ergo_lib_python.chain import TokenId, BoxId
4+
5+
class TokenTests(unittest.TestCase):
6+
id_str = "19475d9a78377ff0f36e9826cec439727bea522f6ffa3bda32e20d2f8b3103ac"
7+
def test_from_str(self):
8+
id = TokenId(self.id_str)
9+
self.assertEqual(bytes(id), base64.b16decode(self.id_str, casefold=True))
10+
def test_from_box_id(self):
11+
box_id = BoxId(self.id_str)
12+
self.assertEqual(bytes(box_id), bytes(TokenId.from_box_id(box_id)))

0 commit comments

Comments
 (0)