TokenV4 CBOR serialization (#502)

* WIP: cashuB with CBOR

* working

* tokenv4 works

* fix mypy
This commit is contained in:
callebtc
2024-06-30 14:36:44 +02:00
committed by GitHub
parent 1d8b5cd5ca
commit 2739c3127a
12 changed files with 579 additions and 416 deletions

View File

@@ -1,6 +1,6 @@
import pytest
from cashu.core.base import TokenV3
from cashu.core.base import TokenV3, TokenV4, Unit
from cashu.core.helpers import calculate_number_of_blank_outputs
from cashu.core.split import amount_split
@@ -21,6 +21,20 @@ def test_tokenv3_deserialize_get_attributes():
assert len(token.get_proofs()) == 2
def test_tokenv3_deserialize_serialize():
token_str = (
"cashuAeyJ0b2tlbiI6IFt7InByb29mcyI6IFt7ImlkIjogIkplaFpMVTZuQ3BSZCIsICJh"
"bW91bnQiOiAyLCAic2VjcmV0IjogIjBFN2lDazRkVmxSZjVQRjFnNFpWMnci"
"LCAiQyI6ICIwM2FiNTgwYWQ5NTc3OGVkNTI5NmY4YmVlNjU1ZGJkN2Q2NDJmNWQzMmRlOG"
"UyNDg0NzdlMGI0ZDZhYTg2M2ZjZDUifSwgeyJpZCI6ICJKZWhaTFU2bkNwUmQiLCAiYW"
"1vdW50IjogOCwgInNlY3JldCI6ICJzNklwZXh3SGNxcXVLZDZYbW9qTDJnIiwgIkMiOiAiM"
"DIyZDAwNGY5ZWMxNmE1OGFkOTAxNGMyNTliNmQ2MTRlZDM2ODgyOWYwMmMzODc3M2M0"
"NzIyMWY0OTYxY2UzZjIzIn1dLCAibWludCI6ICJodHRwOi8vbG9jYWxob3N0OjMzMzgifV19"
)
token = TokenV3.deserialize(token_str)
assert token.serialize() == token_str
def test_tokenv3_deserialize_serialize_with_dleq():
token_str = (
"cashuAeyJ0b2tlbiI6IFt7InByb29mcyI6IFt7ImlkIjogIjFjQ05JQVoyWC93M"
@@ -45,20 +59,6 @@ def test_tokenv3_deserialize_serialize_with_dleq():
assert token.serialize(include_dleq=True) == token_str
def test_tokenv3_deserialize_serialize():
token_str = (
"cashuAeyJ0b2tlbiI6IFt7InByb29mcyI6IFt7ImlkIjogIkplaFpMVTZuQ3BSZCIsICJh"
"bW91bnQiOiAyLCAic2VjcmV0IjogIjBFN2lDazRkVmxSZjVQRjFnNFpWMnci"
"LCAiQyI6ICIwM2FiNTgwYWQ5NTc3OGVkNTI5NmY4YmVlNjU1ZGJkN2Q2NDJmNWQzMmRlOG"
"UyNDg0NzdlMGI0ZDZhYTg2M2ZjZDUifSwgeyJpZCI6ICJKZWhaTFU2bkNwUmQiLCAiYW"
"1vdW50IjogOCwgInNlY3JldCI6ICJzNklwZXh3SGNxcXVLZDZYbW9qTDJnIiwgIkMiOiAiM"
"DIyZDAwNGY5ZWMxNmE1OGFkOTAxNGMyNTliNmQ2MTRlZDM2ODgyOWYwMmMzODc3M2M0"
"NzIyMWY0OTYxY2UzZjIzIn1dLCAibWludCI6ICJodHRwOi8vbG9jYWxob3N0OjMzMzgifV19"
)
token = TokenV3.deserialize(token_str)
assert token.serialize() == token_str
def test_tokenv3_deserialize_serialize_no_dleq():
token_str = (
"cashuAeyJ0b2tlbiI6IFt7InByb29mcyI6IFt7ImlkIjogIjFjQ05JQVoyWC93MSIsICJhb"
@@ -107,7 +107,7 @@ def test_tokenv3_deserialize_with_memo():
assert token.memo == "Test memo"
def test_serialize_example_token_nut00():
def test_tokenv3_serialize_example_token_nut00():
token_dict = {
"token": [
{
@@ -144,6 +144,107 @@ def test_serialize_example_token_nut00():
)
def test_tokenv4_deserialize_get_attributes():
token_str = "cashuBo2F0gaJhaUgArSaMTR9YJmFwgqNhYQJhc3hAMDZlM2UzZjY4NDRiOGZkOGQ3NDMwODY1MjY3MjQ5YWU3NjdhMzg5MDBjODdkNGE0ZDMxOGY4MTJmNzkzN2ZiMmFjWCEDXDG_wzG35Lu4vcAtiycLSQlNqH65afih9N2SrFJn3GCjYWEIYXN4QDBmNTE5YjgwOWZlNmQ5MzZkMjVhYmU1YjhjYTZhMDRlNDc3OTJjOTI0YTkwZWRmYjU1MmM1ZjkzODJkNzFjMDJhY1ghA4CNH8dD8NNt715E37Ar65X6p6uBUoDbe8JipQp81TIgYW11aHR0cDovL2xvY2FsaG9zdDozMzM4YXVjc2F0"
token = TokenV4.deserialize(token_str)
assert token.mint == "http://localhost:3338"
assert token.amounts == [2, 8]
assert token.amount == 10
assert token.unit == Unit.sat.name
assert token.memo is None
assert len(token.proofs) == 2
def test_tokenv4_deserialize_serialize():
token_str = "cashuBo2F0gaJhaUgArSaMTR9YJmFwgqNhYQJhc3hAMDZlM2UzZjY4NDRiOGZkOGQ3NDMwODY1MjY3MjQ5YWU3NjdhMzg5MDBjODdkNGE0ZDMxOGY4MTJmNzkzN2ZiMmFjWCEDXDG_wzG35Lu4vcAtiycLSQlNqH65afih9N2SrFJn3GCjYWEIYXN4QDBmNTE5YjgwOWZlNmQ5MzZkMjVhYmU1YjhjYTZhMDRlNDc3OTJjOTI0YTkwZWRmYjU1MmM1ZjkzODJkNzFjMDJhY1ghA4CNH8dD8NNt715E37Ar65X6p6uBUoDbe8JipQp81TIgYW11aHR0cDovL2xvY2FsaG9zdDozMzM4YXVjc2F0"
token = TokenV4.deserialize(token_str)
assert token.serialize() == token_str
def test_tokenv4_deserialize_with_dleq():
token_str = "cashuBo2F0gaJhaUgArSaMTR9YJmFwgqRhYQhhc3hAY2I4ZWViZWE3OGRjMTZmMWU4MmY5YTZlOWI4YTU3YTM5ZDM2M2M5MzZkMzBmZTI5YmVlZDI2M2MwOGFkOTY2M2FjWCECRmlA6zYOcRSgigEUDv0BBtC2Ag8x8ZOaZUKo8J2_VWdhZKNhZVggscHmr2oHB_x9Bzhgeg2p9Vbq5Ai23olDz2JbmCRx6dlhc1ggrPmtYrRAgEHnYLIQ83cgyFjAjWNqMeNhUadHMxEm0edhclggQ5c_5bES_NhtzunlDls70fhMDWDgo9DY0kk1GuJGM2ikYWECYXN4QDQxN2E2MjZmNWMyNmVhNjliODM0YTZkZTcxYmZiMGY3ZTQ0NDhlZGFkY2FlNGRmNWVhMzM3NDdmOTVhYjRhYjRhY1ghAwyZ1QstFpNe0sppbduQxiePmGVUUk0mWDj5JAFs74-LYWSjYWVYIPyAzLub_bwc60qFkNfETjig-ESZSR8xdpANy1rHwvHKYXNYIOCInwuipARTL8IFT6NoSJqeeSMjlcbPzL-YSmXjDLIuYXJYIOLk-C0Fhba02B0Ut1BjMQqzxVGaO1NJM9Wi_aDQ37jqYW11aHR0cDovL2xvY2FsaG9zdDozMzM4YXVjc2F0"
token = TokenV4.deserialize(token_str)
assert token.proofs[0].dleq is not None
assert token.proofs[0].dleq.e
assert token.proofs[0].dleq.s
assert token.proofs[0].dleq.r
assert token.serialize(include_dleq=True) == token_str
def test_tokenv4_serialize_example_single_keyset_nut00():
token_dict = {
"t": [
{
"i": bytes.fromhex("00ad268c4d1f5826"),
"p": [
{
"a": 1,
"s": "9a6dbb847bd232ba76db0df197216b29d3b8cc14553cd27827fc1cc942fedb4e",
"c": bytes.fromhex(
"038618543ffb6b8695df4ad4babcde92a34a96bdcd97dcee0d7ccf98d472126792"
),
},
],
},
],
"d": "Thank you",
"m": "http://localhost:3338",
"u": "sat",
}
tokenObj = TokenV4.parse_obj(token_dict)
assert (
tokenObj.serialize()
== "cashuBpGF0gaJhaUgArSaMTR9YJmFwgaNhYQFhc3hAOWE2ZGJiODQ3YmQyMzJiYTc2ZGIwZGYxOTcyMTZiMjlkM2I4Y2MxNDU1M2NkMjc4MjdmYzFjYzk0MmZlZGI0ZWFjWCEDhhhUP_trhpXfStS6vN6So0qWvc2X3O4NfM-Y1HISZ5JhZGlUaGFuayB5b3VhbXVodHRwOi8vbG9jYWxob3N0OjMzMzhhdWNzYXQ="
)
def test_tokenv4_serialize_example_token_nut00():
token_dict = {
"t": [
{
"i": bytes.fromhex("00ffd48b8f5ecf80"),
"p": [
{
"a": 1,
"s": "acc12435e7b8484c3cf1850149218af90f716a52bf4a5ed347e48ecc13f77388",
"c": bytes.fromhex(
"0244538319de485d55bed3b29a642bee5879375ab9e7a620e11e48ba482421f3cf"
),
},
],
},
{
"i": bytes.fromhex("00ad268c4d1f5826"),
"p": [
{
"a": 2,
"s": "1323d3d4707a58ad2e23ada4e9f1f49f5a5b4ac7b708eb0d61f738f48307e8ee",
"c": bytes.fromhex(
"023456aa110d84b4ac747aebd82c3b005aca50bf457ebd5737a4414fac3ae7d94d"
),
},
{
"a": 1,
"s": "56bcbcbb7cc6406b3fa5d57d2174f4eff8b4402b176926d3a57d3c3dcbb59d57",
"c": bytes.fromhex(
"0273129c5719e599379a974a626363c333c56cafc0e6d01abe46d5808280789c63"
),
},
],
},
],
"m": "http://localhost:3338",
"u": "sat",
}
tokenObj = TokenV4.parse_obj(token_dict)
assert (
tokenObj.serialize()
== "cashuBo2F0gqJhaUgA_9SLj17PgGFwgaNhYQFhc3hAYWNjMTI0MzVlN2I4NDg0YzNjZjE4NTAxNDkyMThhZjkwZjcxNmE1MmJmNGE1ZWQzNDdlNDhlY2MxM2Y3NzM4OGFjWCECRFODGd5IXVW-07KaZCvuWHk3WrnnpiDhHki6SCQh88-iYWlIAK0mjE0fWCZhcIKjYWECYXN4QDEzMjNkM2Q0NzA3YTU4YWQyZTIzYWRhNGU5ZjFmNDlmNWE1YjRhYzdiNzA4ZWIwZDYxZjczOGY0ODMwN2U4ZWVhY1ghAjRWqhENhLSsdHrr2Cw7AFrKUL9Ffr1XN6RBT6w659lNo2FhAWFzeEA1NmJjYmNiYjdjYzY0MDZiM2ZhNWQ1N2QyMTc0ZjRlZmY4YjQ0MDJiMTc2OTI2ZDNhNTdkM2MzZGNiYjU5ZDU3YWNYIQJzEpxXGeWZN5qXSmJjY8MzxWyvwObQGr5G1YCCgHicY2FtdWh0dHA6Ly9sb2NhbGhvc3Q6MzMzOGF1Y3NhdA=="
)
def test_calculate_number_of_blank_outputs():
# Example from NUT-08 specification.
fee_reserve_sat = 1000