mirror of
https://github.com/planetmint/planetmint.git
synced 2025-07-04 11:42:29 +00:00
Ipld (#256)
* added ipld dep Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com> * Cid tx schema (#252) * changed asset and metadata schema to string Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com> * updated fixtures and adjusted some models and test cases Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com> * adjusted dependencies, fixtures and added comments Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com> * alignd TX inputs to be CID compatible Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com> * converted assets to CIDs Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com> * added multihashes Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com> * fixed data packaging for IPLD compatible test cases for the unit tests Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com> * Transaction hierarchy (#254) * removed Transaction class from models.py, adjusted imports and function calls Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com> * removed comments Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com> * removed empty lines Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com> * resolved linting error Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com> * adjusted import path Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com> * added missing argument to mock Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com> * resolved linting error Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com> * adjusted mock func signature Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com> Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com> * fixed all unit tests Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com> * fixed zenroom acceptance test Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com> * adjusted common tx schema, fixed election validate Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com> * fixed an planetmint-ipld dependency that solved a package namespace collision in the dependencies of IPLD Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com> * disabled integration and acceptance tests as they rely on planetmint driver. Plan is to resolve this circular dependency Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com> * adjusted acceptance tests to IPLD requirements Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com> * blackified Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com> * added missing imports Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com> * blackified little changes Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com> Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com> Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com> Co-authored-by: Jürgen Eckel <juergen@riddleandcode.com> Co-authored-by: Jürgen Eckel <eckelj@users.noreply.github.com> * increased version enforce ipld encodings to metadata and asset["data"] Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com> Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com> Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com> Co-authored-by: Lorenz Herzberger <64837895+LaurentMontBlanc@users.noreply.github.com>
This commit is contained in:
parent
22ccb26d99
commit
637dc4993b
3
.github/workflows/acceptance-test.yml
vendored
3
.github/workflows/acceptance-test.yml
vendored
@ -8,8 +8,9 @@ on: [push, pull_request]
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
|
if: ${{ false }
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out repository code
|
- name: Check out repository code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
1
.github/workflows/integration-test.yml
vendored
1
.github/workflows/integration-test.yml
vendored
@ -8,6 +8,7 @@ on: [push, pull_request]
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
|
if: ${{ false }
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
@ -27,6 +27,15 @@ For reference, the possible headings are:
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## [1.2.0] - 2022-09-05
|
||||||
|
* **Changed** disabled acceptance and integration tests, they have a circular dep. to the python driver
|
||||||
|
* **Changed** Metadata and asset["data"] types to string containing an IPLD hash
|
||||||
|
* **Fixed** Transaction generation bug that automatically assigned 'assets' to asset["data"]
|
||||||
|
* **Changed** adjusted test caes
|
||||||
|
|
||||||
|
|
||||||
## [1.1.0] - 2022-09-05
|
## [1.1.0] - 2022-09-05
|
||||||
* **Changed** adjusted to zenroom calling convention of PRP #13 (breaking change)
|
* **Changed** adjusted to zenroom calling convention of PRP #13 (breaking change)
|
||||||
* **Changed** zenroom test cases to comply to the new calling convention
|
* **Changed** zenroom test cases to comply to the new calling convention
|
||||||
|
2
Makefile
2
Makefile
@ -81,7 +81,7 @@ test: check-deps test-unit test-acceptance ## Run unit and acceptance tests
|
|||||||
|
|
||||||
test-unit: check-deps ## Run all tests once
|
test-unit: check-deps ## Run all tests once
|
||||||
@$(DC) up -d bdb
|
@$(DC) up -d bdb
|
||||||
@$(DC) exec planetmint pytest
|
@$(DC) exec planetmint pytest ${TEST}
|
||||||
|
|
||||||
test-unit-watch: check-deps ## Run all tests and wait. Every time you change code, tests will be run again
|
test-unit-watch: check-deps ## Run all tests and wait. Every time you change code, tests will be run again
|
||||||
@$(DC) run --rm --no-deps planetmint pytest -f
|
@$(DC) run --rm --no-deps planetmint pytest -f
|
||||||
|
@ -17,3 +17,4 @@ RUN pip install --upgrade \
|
|||||||
planetmint-driver>=0.9.2 \
|
planetmint-driver>=0.9.2 \
|
||||||
blns
|
blns
|
||||||
RUN pip install base58>=2.1.1 pynacl==1.4.0 zenroom==2.1.0.dev1655293214 pyasn1==0.4.8 cryptography==3.4.7
|
RUN pip install base58>=2.1.1 pynacl==1.4.0 zenroom==2.1.0.dev1655293214 pyasn1==0.4.8 cryptography==3.4.7
|
||||||
|
RUN pip install planetmint-ipld>=0.0.3
|
||||||
|
@ -23,6 +23,7 @@ import os
|
|||||||
# For this test case we import and use the Python Driver.
|
# For this test case we import and use the Python Driver.
|
||||||
from planetmint_driver import Planetmint
|
from planetmint_driver import Planetmint
|
||||||
from planetmint_driver.crypto import generate_keypair
|
from planetmint_driver.crypto import generate_keypair
|
||||||
|
from ipld import multihash, marshal
|
||||||
|
|
||||||
|
|
||||||
def test_get_tests():
|
def test_get_tests():
|
||||||
@ -41,7 +42,7 @@ def test_get_tests():
|
|||||||
# ## Alice registers her bike in Planetmint
|
# ## Alice registers her bike in Planetmint
|
||||||
# Alice has a nice bike, and here she creates the "digital twin"
|
# Alice has a nice bike, and here she creates the "digital twin"
|
||||||
# of her bike.
|
# of her bike.
|
||||||
bike = {"data": {"bicycle": {"serial_number": 420420}}}
|
bike = {"data": multihash(marshal({"bicycle": {"serial_number": 420420}}))}
|
||||||
|
|
||||||
# She prepares a `CREATE` transaction...
|
# She prepares a `CREATE` transaction...
|
||||||
prepared_creation_tx = bdb.transactions.prepare(operation="CREATE", signers=alice.public_key, asset=bike)
|
prepared_creation_tx = bdb.transactions.prepare(operation="CREATE", signers=alice.public_key, asset=bike)
|
||||||
|
@ -23,6 +23,7 @@ import os
|
|||||||
# For this test case we import and use the Python Driver.
|
# For this test case we import and use the Python Driver.
|
||||||
from planetmint_driver import Planetmint
|
from planetmint_driver import Planetmint
|
||||||
from planetmint_driver.crypto import generate_keypair
|
from planetmint_driver.crypto import generate_keypair
|
||||||
|
from ipld import multihash, marshal
|
||||||
|
|
||||||
|
|
||||||
def test_basic():
|
def test_basic():
|
||||||
@ -41,7 +42,7 @@ def test_basic():
|
|||||||
# ## Alice registers her bike in Planetmint
|
# ## Alice registers her bike in Planetmint
|
||||||
# Alice has a nice bike, and here she creates the "digital twin"
|
# Alice has a nice bike, and here she creates the "digital twin"
|
||||||
# of her bike.
|
# of her bike.
|
||||||
bike = {"data": {"bicycle": {"serial_number": 420420}}}
|
bike = {"data": multihash(marshal({"bicycle": {"serial_number": 420420}}))}
|
||||||
|
|
||||||
# She prepares a `CREATE` transaction...
|
# She prepares a `CREATE` transaction...
|
||||||
prepared_creation_tx = bdb.transactions.prepare(operation="CREATE", signers=alice.public_key, asset=bike)
|
prepared_creation_tx = bdb.transactions.prepare(operation="CREATE", signers=alice.public_key, asset=bike)
|
||||||
|
@ -28,6 +28,7 @@ from planetmint_driver.exceptions import BadRequest
|
|||||||
# For this test case we import and use the Python Driver.
|
# For this test case we import and use the Python Driver.
|
||||||
from planetmint_driver import Planetmint
|
from planetmint_driver import Planetmint
|
||||||
from planetmint_driver.crypto import generate_keypair
|
from planetmint_driver.crypto import generate_keypair
|
||||||
|
from ipld import multihash, marshal
|
||||||
|
|
||||||
|
|
||||||
def test_divisible_assets():
|
def test_divisible_assets():
|
||||||
@ -48,10 +49,14 @@ def test_divisible_assets():
|
|||||||
# the bike for one hour.
|
# the bike for one hour.
|
||||||
|
|
||||||
bike_token = {
|
bike_token = {
|
||||||
"data": {
|
"data": multihash(
|
||||||
"token_for": {"bike": {"serial_number": 420420}},
|
marshal(
|
||||||
"description": "Time share token. Each token equals one hour of riding.",
|
{
|
||||||
},
|
"token_for": {"bike": {"serial_number": 420420}},
|
||||||
|
"description": "Time share token. Each token equals one hour of riding.",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
# She prepares a `CREATE` transaction and issues 10 tokens.
|
# She prepares a `CREATE` transaction and issues 10 tokens.
|
||||||
|
@ -14,6 +14,7 @@ import queue
|
|||||||
import planetmint_driver.exceptions
|
import planetmint_driver.exceptions
|
||||||
from planetmint_driver import Planetmint
|
from planetmint_driver import Planetmint
|
||||||
from planetmint_driver.crypto import generate_keypair
|
from planetmint_driver.crypto import generate_keypair
|
||||||
|
from ipld import multihash, marshal
|
||||||
|
|
||||||
|
|
||||||
def test_double_create():
|
def test_double_create():
|
||||||
@ -23,7 +24,9 @@ def test_double_create():
|
|||||||
results = queue.Queue()
|
results = queue.Queue()
|
||||||
|
|
||||||
tx = bdb.transactions.fulfill(
|
tx = bdb.transactions.fulfill(
|
||||||
bdb.transactions.prepare(operation="CREATE", signers=alice.public_key, asset={"data": {"uuid": str(uuid4())}}),
|
bdb.transactions.prepare(
|
||||||
|
operation="CREATE", signers=alice.public_key, asset={"data": multihash(marshal({"uuid": str(uuid4())}))}
|
||||||
|
),
|
||||||
private_keys=alice.private_key,
|
private_keys=alice.private_key,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ import os
|
|||||||
# For this test case we import and use the Python Driver.
|
# For this test case we import and use the Python Driver.
|
||||||
from planetmint_driver import Planetmint
|
from planetmint_driver import Planetmint
|
||||||
from planetmint_driver.crypto import generate_keypair
|
from planetmint_driver.crypto import generate_keypair
|
||||||
|
from ipld import multihash, marshal
|
||||||
|
|
||||||
|
|
||||||
def test_multiple_owners():
|
def test_multiple_owners():
|
||||||
@ -41,7 +42,7 @@ def test_multiple_owners():
|
|||||||
# high rents anymore. Bob suggests to get a dish washer for the
|
# high rents anymore. Bob suggests to get a dish washer for the
|
||||||
# kitchen. Alice agrees and here they go, creating the asset for their
|
# kitchen. Alice agrees and here they go, creating the asset for their
|
||||||
# dish washer.
|
# dish washer.
|
||||||
dw_asset = {"data": {"dish washer": {"serial_number": 1337}}}
|
dw_asset = {"data": multihash(marshal({"dish washer": {"serial_number": 1337}}))}
|
||||||
|
|
||||||
# They prepare a `CREATE` transaction. To have multiple owners, both
|
# They prepare a `CREATE` transaction. To have multiple owners, both
|
||||||
# Bob and Alice need to be the recipients.
|
# Bob and Alice need to be the recipients.
|
||||||
|
@ -29,6 +29,7 @@ import pytest
|
|||||||
from planetmint_driver import Planetmint
|
from planetmint_driver import Planetmint
|
||||||
from planetmint_driver.crypto import generate_keypair
|
from planetmint_driver.crypto import generate_keypair
|
||||||
from planetmint_driver.exceptions import BadRequest
|
from planetmint_driver.exceptions import BadRequest
|
||||||
|
from ipld import multihash, marshal
|
||||||
|
|
||||||
naughty_strings = blns.all()
|
naughty_strings = blns.all()
|
||||||
skipped_naughty_strings = [
|
skipped_naughty_strings = [
|
||||||
@ -118,8 +119,8 @@ def send_naughty_tx(asset, metadata):
|
|||||||
@pytest.mark.parametrize("naughty_string", naughty_strings, ids=naughty_strings)
|
@pytest.mark.parametrize("naughty_string", naughty_strings, ids=naughty_strings)
|
||||||
def test_naughty_keys(naughty_string):
|
def test_naughty_keys(naughty_string):
|
||||||
|
|
||||||
asset = {"data": {naughty_string: "nice_value"}}
|
asset = {"data": multihash(marshal({naughty_string: "nice_value"}))}
|
||||||
metadata = {naughty_string: "nice_value"}
|
metadata = multihash(marshal({naughty_string: "nice_value"}))
|
||||||
|
|
||||||
send_naughty_tx(asset, metadata)
|
send_naughty_tx(asset, metadata)
|
||||||
|
|
||||||
@ -127,7 +128,7 @@ def test_naughty_keys(naughty_string):
|
|||||||
@pytest.mark.parametrize("naughty_string", naughty_strings, ids=naughty_strings)
|
@pytest.mark.parametrize("naughty_string", naughty_strings, ids=naughty_strings)
|
||||||
def test_naughty_values(naughty_string):
|
def test_naughty_values(naughty_string):
|
||||||
|
|
||||||
asset = {"data": {"nice_key": naughty_string}}
|
asset = {"data": multihash(marshal({"nice_key": naughty_string}))}
|
||||||
metadata = {"nice_key": naughty_string}
|
metadata = multihash(marshal({"nice_key": naughty_string}))
|
||||||
|
|
||||||
send_naughty_tx(asset, metadata)
|
send_naughty_tx(asset, metadata)
|
||||||
|
@ -21,6 +21,7 @@ import queue
|
|||||||
import json
|
import json
|
||||||
from threading import Thread, Event
|
from threading import Thread, Event
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
from ipld import multihash, marshal
|
||||||
|
|
||||||
# For this script, we need to set up a websocket connection, that's the reason
|
# For this script, we need to set up a websocket connection, that's the reason
|
||||||
# we import the
|
# we import the
|
||||||
@ -91,7 +92,9 @@ def test_stream():
|
|||||||
for _ in range(10):
|
for _ in range(10):
|
||||||
tx = bdb.transactions.fulfill(
|
tx = bdb.transactions.fulfill(
|
||||||
bdb.transactions.prepare(
|
bdb.transactions.prepare(
|
||||||
operation="CREATE", signers=alice.public_key, asset={"data": {"uuid": str(uuid4())}}
|
operation="CREATE",
|
||||||
|
signers=alice.public_key,
|
||||||
|
asset={"data": multihash(marshal({"uuid": str(uuid4())}))},
|
||||||
),
|
),
|
||||||
private_keys=alice.private_key,
|
private_keys=alice.private_key,
|
||||||
)
|
)
|
||||||
|
@ -7,6 +7,7 @@ from cryptoconditions.types.zenroom import ZenroomSha256
|
|||||||
from zenroom import zencode_exec
|
from zenroom import zencode_exec
|
||||||
from planetmint_driver import Planetmint
|
from planetmint_driver import Planetmint
|
||||||
from planetmint_driver.crypto import generate_keypair
|
from planetmint_driver.crypto import generate_keypair
|
||||||
|
from ipld import multihash, marshal
|
||||||
|
|
||||||
|
|
||||||
def test_zenroom_signing(
|
def test_zenroom_signing(
|
||||||
@ -66,8 +67,8 @@ def test_zenroom_signing(
|
|||||||
metadata = {"result": {"output": ["ok"]}}
|
metadata = {"result": {"output": ["ok"]}}
|
||||||
|
|
||||||
script_ = {
|
script_ = {
|
||||||
"code": {"type": "zenroom", "raw": "test_string", "parameters": [{"obj": "1"}, {"obj": "2"}]},
|
"code": {"type": "zenroom", "raw": "test_string", "parameters": [{"obj": "1"}, {"obj": "2"}]}, # obsolete
|
||||||
"state": "dd8bbd234f9869cab4cc0b84aa660e9b5ef0664559b8375804ee8dce75b10576",
|
"state": "dd8bbd234f9869cab4cc0b84aa660e9b5ef0664559b8375804ee8dce75b10576", #
|
||||||
"input": zenroom_script_input,
|
"input": zenroom_script_input,
|
||||||
"output": ["ok"],
|
"output": ["ok"],
|
||||||
"policies": {},
|
"policies": {},
|
||||||
@ -75,9 +76,9 @@ def test_zenroom_signing(
|
|||||||
|
|
||||||
token_creation_tx = {
|
token_creation_tx = {
|
||||||
"operation": "CREATE",
|
"operation": "CREATE",
|
||||||
"asset": {"data": {"test": "my asset"}},
|
"asset": {"data": multihash(marshal({"test": "my asset"}))},
|
||||||
|
"metadata": multihash(marshal(metadata)),
|
||||||
"script": script_,
|
"script": script_,
|
||||||
"metadata": metadata,
|
|
||||||
"outputs": [
|
"outputs": [
|
||||||
output,
|
output,
|
||||||
],
|
],
|
||||||
|
@ -15,6 +15,7 @@ from planetmint import lib
|
|||||||
from planetmint.transactions.types.assets.create import Create
|
from planetmint.transactions.types.assets.create import Create
|
||||||
from planetmint.transactions.types.assets.transfer import Transfer
|
from planetmint.transactions.types.assets.transfer import Transfer
|
||||||
from planetmint.web import server
|
from planetmint.web import server
|
||||||
|
from ipld import multihash, marshal
|
||||||
|
|
||||||
|
|
||||||
TPLS = {}
|
TPLS = {}
|
||||||
@ -157,10 +158,12 @@ def main():
|
|||||||
ctx["api_index"] = pretty_json(json.loads(res.data.decode()))
|
ctx["api_index"] = pretty_json(json.loads(res.data.decode()))
|
||||||
|
|
||||||
# tx create
|
# tx create
|
||||||
|
from ipld import marshal, multihash
|
||||||
|
|
||||||
privkey = "CfdqtD7sS7FgkMoGPXw55MVGGFwQLAoHYTcBhZDtF99Z"
|
privkey = "CfdqtD7sS7FgkMoGPXw55MVGGFwQLAoHYTcBhZDtF99Z"
|
||||||
pubkey = "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD"
|
pubkey = "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD"
|
||||||
asset = {"msg": "Hello Planetmint!"}
|
asset = {"data": multihash(marshal({"msg": "Hello Planetmint!"}))}
|
||||||
tx = Create.generate([pubkey], [([pubkey], 1)], asset=asset, metadata={"sequence": 0})
|
tx = Create.generate([pubkey], [([pubkey], 1)], asset=asset, metadata=multihash(marshal({"sequence": 0})))
|
||||||
tx = tx.sign([privkey])
|
tx = tx.sign([privkey])
|
||||||
ctx["tx"] = pretty_json(tx.to_dict())
|
ctx["tx"] = pretty_json(tx.to_dict())
|
||||||
ctx["public_keys"] = tx.outputs[0].public_keys[0]
|
ctx["public_keys"] = tx.outputs[0].public_keys[0]
|
||||||
@ -176,7 +179,9 @@ def main():
|
|||||||
fulfills=TransactionLink(txid=tx.id, output=cid),
|
fulfills=TransactionLink(txid=tx.id, output=cid),
|
||||||
owners_before=tx.outputs[cid].public_keys,
|
owners_before=tx.outputs[cid].public_keys,
|
||||||
)
|
)
|
||||||
tx_transfer = Transfer.generate([input_], [([pubkey_transfer], 1)], asset_id=tx.id, metadata={"sequence": 1})
|
tx_transfer = Transfer.generate(
|
||||||
|
[input_], [([pubkey_transfer], 1)], asset_id=tx.id, metadata=multihash(marshal({"sequence": 1}))
|
||||||
|
)
|
||||||
tx_transfer = tx_transfer.sign([privkey])
|
tx_transfer = tx_transfer.sign([privkey])
|
||||||
ctx["tx_transfer"] = pretty_json(tx_transfer.to_dict())
|
ctx["tx_transfer"] = pretty_json(tx_transfer.to_dict())
|
||||||
ctx["public_keys_transfer"] = tx_transfer.outputs[0].public_keys[0]
|
ctx["public_keys_transfer"] = tx_transfer.outputs[0].public_keys[0]
|
||||||
@ -192,7 +197,7 @@ def main():
|
|||||||
owners_before=tx_transfer.outputs[cid].public_keys,
|
owners_before=tx_transfer.outputs[cid].public_keys,
|
||||||
)
|
)
|
||||||
tx_transfer_last = Transfer.generate(
|
tx_transfer_last = Transfer.generate(
|
||||||
[input_], [([pubkey_transfer_last], 1)], asset_id=tx.id, metadata={"sequence": 2}
|
[input_], [([pubkey_transfer_last], 1)], asset_id=tx.id, metadata=multihash(marshal({"sequence": 2}))
|
||||||
)
|
)
|
||||||
tx_transfer_last = tx_transfer_last.sign([privkey_transfer])
|
tx_transfer_last = tx_transfer_last.sign([privkey_transfer])
|
||||||
ctx["tx_transfer_last"] = pretty_json(tx_transfer_last.to_dict())
|
ctx["tx_transfer_last"] = pretty_json(tx_transfer_last.to_dict())
|
||||||
|
@ -14,7 +14,7 @@ register_query = module_dispatch_registrar(convert)
|
|||||||
|
|
||||||
@register_query(LocalMongoDBConnection)
|
@register_query(LocalMongoDBConnection)
|
||||||
def prepare_asset(connection, transaction_type, transaction_id, filter_operation, asset):
|
def prepare_asset(connection, transaction_type, transaction_id, filter_operation, asset):
|
||||||
if transaction_type == filter_operation:
|
if transaction_type in filter_operation:
|
||||||
asset["id"] = transaction_id
|
asset["id"] = transaction_id
|
||||||
return asset
|
return asset
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ register_query = module_dispatch_registrar(convert)
|
|||||||
@register_query(TarantoolDBConnection)
|
@register_query(TarantoolDBConnection)
|
||||||
def prepare_asset(connection, transaction_type, transaction_id, filter_operation, asset):
|
def prepare_asset(connection, transaction_type, transaction_id, filter_operation, asset):
|
||||||
asset_id = transaction_id
|
asset_id = transaction_id
|
||||||
if transaction_type != filter_operation:
|
if transaction_type not in filter_operation:
|
||||||
asset_id = asset["id"]
|
asset_id = asset["id"]
|
||||||
return tuple([asset, transaction_id, asset_id])
|
return tuple([asset, transaction_id, asset_id])
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ class Planetmint(object):
|
|||||||
self.connection,
|
self.connection,
|
||||||
transaction_type=transaction["operation"],
|
transaction_type=transaction["operation"],
|
||||||
transaction_id=transaction["id"],
|
transaction_id=transaction["id"],
|
||||||
filter_operation=t.CREATE,
|
filter_operation=[t.CREATE, t.VALIDATOR_ELECTION, t.CHAIN_MIGRATION_ELECTION],
|
||||||
asset=asset,
|
asset=asset,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -108,6 +108,8 @@ class ValidationWorker:
|
|||||||
asset_id = dict_transaction["asset"]["id"]
|
asset_id = dict_transaction["asset"]["id"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
asset_id = dict_transaction["id"]
|
asset_id = dict_transaction["id"]
|
||||||
|
except TypeError:
|
||||||
|
asset_id = dict_transaction["id"]
|
||||||
|
|
||||||
transaction = self.planetmint.is_valid_transaction(dict_transaction, self.validated_transactions[asset_id])
|
transaction = self.planetmint.is_valid_transaction(dict_transaction, self.validated_transactions[asset_id])
|
||||||
|
|
||||||
|
@ -69,16 +69,9 @@ definitions:
|
|||||||
- CHAIN_MIGRATION_ELECTION
|
- CHAIN_MIGRATION_ELECTION
|
||||||
- VOTE
|
- VOTE
|
||||||
asset:
|
asset:
|
||||||
type: object
|
anyOf:
|
||||||
additionalProperties: false
|
- type: 'null'
|
||||||
properties:
|
- type: object
|
||||||
id:
|
|
||||||
"$ref": "#/definitions/sha3_hexdigest"
|
|
||||||
data:
|
|
||||||
anyOf:
|
|
||||||
- type: object
|
|
||||||
additionalProperties: true
|
|
||||||
- type: 'null'
|
|
||||||
output:
|
output:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
@ -135,9 +128,7 @@ definitions:
|
|||||||
- type: 'null'
|
- type: 'null'
|
||||||
metadata:
|
metadata:
|
||||||
anyOf:
|
anyOf:
|
||||||
- type: object
|
- type: string
|
||||||
additionalProperties: true
|
|
||||||
minProperties: 1
|
|
||||||
- type: 'null'
|
- type: 'null'
|
||||||
condition_details:
|
condition_details:
|
||||||
anyOf:
|
anyOf:
|
||||||
|
@ -16,8 +16,7 @@ properties:
|
|||||||
properties:
|
properties:
|
||||||
data:
|
data:
|
||||||
anyOf:
|
anyOf:
|
||||||
- type: object
|
- type: string
|
||||||
additionalProperties: true
|
|
||||||
- type: 'null'
|
- type: 'null'
|
||||||
required:
|
required:
|
||||||
- data
|
- data
|
||||||
|
@ -73,16 +73,9 @@ definitions:
|
|||||||
- COMPOSE
|
- COMPOSE
|
||||||
- DECOMPOSE
|
- DECOMPOSE
|
||||||
asset:
|
asset:
|
||||||
type: object
|
anyOf:
|
||||||
additionalProperties: false
|
- type: 'null'
|
||||||
properties:
|
- type: object
|
||||||
id:
|
|
||||||
"$ref": "#/definitions/sha3_hexdigest"
|
|
||||||
data:
|
|
||||||
anyOf:
|
|
||||||
- type: object
|
|
||||||
additionalProperties: true
|
|
||||||
- type: 'null'
|
|
||||||
output:
|
output:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
@ -139,9 +132,7 @@ definitions:
|
|||||||
- type: 'null'
|
- type: 'null'
|
||||||
metadata:
|
metadata:
|
||||||
anyOf:
|
anyOf:
|
||||||
- type: object
|
- type: string
|
||||||
additionalProperties: true
|
|
||||||
minProperties: 1
|
|
||||||
- type: 'null'
|
- type: 'null'
|
||||||
condition_details:
|
condition_details:
|
||||||
anyOf:
|
anyOf:
|
||||||
|
@ -35,8 +35,7 @@ definitions:
|
|||||||
properties:
|
properties:
|
||||||
data:
|
data:
|
||||||
anyOf:
|
anyOf:
|
||||||
- type: object
|
- type: string
|
||||||
additionalProperties: true
|
|
||||||
- type: 'null'
|
- type: 'null'
|
||||||
required:
|
required:
|
||||||
- data
|
- data
|
@ -57,6 +57,10 @@ UnspentOutput = namedtuple(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
VALIDATOR_ELECTION = "VALIDATOR_ELECTION"
|
||||||
|
CHAIN_MIGRATION_ELECTION = "CHAIN_MIGRATION_ELECTION"
|
||||||
|
VOTE = "VOTE"
|
||||||
|
|
||||||
|
|
||||||
class Transaction(object):
|
class Transaction(object):
|
||||||
"""A Transaction is used to create and transfer assets.
|
"""A Transaction is used to create and transfer assets.
|
||||||
@ -83,6 +87,9 @@ class Transaction(object):
|
|||||||
|
|
||||||
CREATE = "CREATE"
|
CREATE = "CREATE"
|
||||||
TRANSFER = "TRANSFER"
|
TRANSFER = "TRANSFER"
|
||||||
|
VALIDATOR_ELECTION = VALIDATOR_ELECTION
|
||||||
|
CHAIN_MIGRATION_ELECTION = CHAIN_MIGRATION_ELECTION
|
||||||
|
VOTE = VOTE
|
||||||
ALLOWED_OPERATIONS = (CREATE, TRANSFER)
|
ALLOWED_OPERATIONS = (CREATE, TRANSFER)
|
||||||
ASSET = "asset"
|
ASSET = "asset"
|
||||||
METADATA = "metadata"
|
METADATA = "metadata"
|
||||||
@ -127,13 +134,25 @@ class Transaction(object):
|
|||||||
# Asset payloads for 'CREATE' operations must be None or
|
# Asset payloads for 'CREATE' operations must be None or
|
||||||
# dicts holding a `data` property. Asset payloads for 'TRANSFER'
|
# dicts holding a `data` property. Asset payloads for 'TRANSFER'
|
||||||
# operations must be dicts holding an `id` property.
|
# operations must be dicts holding an `id` property.
|
||||||
if operation == self.CREATE and asset is not None and not (isinstance(asset, dict) and "data" in asset):
|
if operation == self.CREATE and asset is not None:
|
||||||
raise TypeError(
|
if not isinstance(asset, dict):
|
||||||
(
|
raise TypeError(
|
||||||
"`asset` must be None or a dict holding a `data` "
|
(
|
||||||
" property instance for '{}' Transactions".format(operation)
|
"`asset` must be None or a dict holding a `data` "
|
||||||
|
" property instance for '{}' Transactions".format(operation)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
if "data" in asset:
|
||||||
|
if asset["data"] is not None and not isinstance(asset["data"], str):
|
||||||
|
# add check if data is ipld marshalled CID string
|
||||||
|
raise TypeError(
|
||||||
|
(
|
||||||
|
"`asset` must be None or a dict holding a `data` "
|
||||||
|
" property instance for '{}' Transactions".format(operation)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
elif operation == self.TRANSFER and not (isinstance(asset, dict) and "id" in asset):
|
elif operation == self.TRANSFER and not (isinstance(asset, dict) and "id" in asset):
|
||||||
raise TypeError(("`asset` must be a dict holding an `id` property " "for 'TRANSFER' Transactions"))
|
raise TypeError(("`asset` must be a dict holding an `id` property " "for 'TRANSFER' Transactions"))
|
||||||
|
|
||||||
@ -143,8 +162,9 @@ class Transaction(object):
|
|||||||
if inputs and not isinstance(inputs, list):
|
if inputs and not isinstance(inputs, list):
|
||||||
raise TypeError("`inputs` must be a list instance or None")
|
raise TypeError("`inputs` must be a list instance or None")
|
||||||
|
|
||||||
if metadata is not None and not isinstance(metadata, dict):
|
if metadata is not None and not isinstance(metadata, str):
|
||||||
raise TypeError("`metadata` must be a dict or None")
|
# Add CID validation
|
||||||
|
raise TypeError("`metadata` must be a CID string or None")
|
||||||
|
|
||||||
if script is not None and not isinstance(script, dict):
|
if script is not None and not isinstance(script, dict):
|
||||||
raise TypeError("`script` must be a dict or None")
|
raise TypeError("`script` must be a dict or None")
|
||||||
@ -490,6 +510,10 @@ class Transaction(object):
|
|||||||
return self._inputs_valid(["dummyvalue" for _ in self.inputs])
|
return self._inputs_valid(["dummyvalue" for _ in self.inputs])
|
||||||
elif self.operation == self.TRANSFER:
|
elif self.operation == self.TRANSFER:
|
||||||
return self._inputs_valid([output.fulfillment.condition_uri for output in outputs])
|
return self._inputs_valid([output.fulfillment.condition_uri for output in outputs])
|
||||||
|
elif self.operation == self.VALIDATOR_ELECTION:
|
||||||
|
return self._inputs_valid(["dummyvalue" for _ in self.inputs])
|
||||||
|
elif self.operation == self.CHAIN_MIGRATION_ELECTION:
|
||||||
|
return self._inputs_valid(["dummyvalue" for _ in self.inputs])
|
||||||
else:
|
else:
|
||||||
allowed_ops = ", ".join(self.__class__.ALLOWED_OPERATIONS)
|
allowed_ops = ", ".join(self.__class__.ALLOWED_OPERATIONS)
|
||||||
raise TypeError("`operation` must be one of {}".format(allowed_ops))
|
raise TypeError("`operation` must be one of {}".format(allowed_ops))
|
||||||
@ -561,7 +585,7 @@ class Transaction(object):
|
|||||||
print(f"Exception ASN1EncodeError : {e}")
|
print(f"Exception ASN1EncodeError : {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if operation == self.CREATE:
|
if operation in [self.CREATE, self.CHAIN_MIGRATION_ELECTION, self.VALIDATOR_ELECTION]:
|
||||||
# NOTE: In the case of a `CREATE` transaction, the
|
# NOTE: In the case of a `CREATE` transaction, the
|
||||||
# output is always valid.
|
# output is always valid.
|
||||||
output_valid = True
|
output_valid = True
|
||||||
@ -680,7 +704,9 @@ class Transaction(object):
|
|||||||
transactions = [transactions]
|
transactions = [transactions]
|
||||||
|
|
||||||
# create a set of the transactions' asset ids
|
# create a set of the transactions' asset ids
|
||||||
asset_ids = {tx.id if tx.operation == tx.CREATE else tx.asset["id"] for tx in transactions}
|
asset_ids = {
|
||||||
|
tx.id if tx.operation in [tx.CREATE, tx.VALIDATOR_ELECTION] else tx.asset["id"] for tx in transactions
|
||||||
|
}
|
||||||
|
|
||||||
# check that all the transasctions have the same asset id
|
# check that all the transasctions have the same asset id
|
||||||
if len(asset_ids) > 1:
|
if len(asset_ids) > 1:
|
||||||
@ -887,3 +913,22 @@ class Transaction(object):
|
|||||||
raise InvalidSignature("Transaction signature is invalid.")
|
raise InvalidSignature("Transaction signature is invalid.")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def complete_tx_i_o(self, tx_signers, recipients):
|
||||||
|
inputs = []
|
||||||
|
outputs = []
|
||||||
|
|
||||||
|
# generate_outputs
|
||||||
|
for recipient in recipients:
|
||||||
|
if not isinstance(recipient, tuple) or len(recipient) != 2:
|
||||||
|
raise ValueError(
|
||||||
|
("Each `recipient` in the list must be a" " tuple of `([<list of public keys>]," " <amount>)`")
|
||||||
|
)
|
||||||
|
pub_keys, amount = recipient
|
||||||
|
outputs.append(Output.generate(pub_keys, amount))
|
||||||
|
|
||||||
|
# generate inputs
|
||||||
|
inputs.append(Input.generate(tx_signers))
|
||||||
|
|
||||||
|
return (inputs, outputs)
|
||||||
|
@ -23,27 +23,19 @@ class Create(Transaction):
|
|||||||
raise ValueError("`tx_signers` list cannot be empty")
|
raise ValueError("`tx_signers` list cannot be empty")
|
||||||
if len(recipients) == 0:
|
if len(recipients) == 0:
|
||||||
raise ValueError("`recipients` list cannot be empty")
|
raise ValueError("`recipients` list cannot be empty")
|
||||||
if not (asset is None or isinstance(asset, dict)):
|
if not asset is None:
|
||||||
raise TypeError("`asset` must be a dict or None")
|
if not isinstance(asset, dict):
|
||||||
if not (metadata is None or isinstance(metadata, dict)):
|
raise TypeError("`asset` must be a CID string or None")
|
||||||
raise TypeError("`metadata` must be a dict or None")
|
if "data" in asset and not isinstance(asset["data"], str):
|
||||||
|
raise TypeError("`asset` must be a CID string or None")
|
||||||
|
import cid
|
||||||
|
|
||||||
inputs = []
|
cid.make_cid(asset["data"])
|
||||||
outputs = []
|
if not (metadata is None or isinstance(metadata, str)):
|
||||||
|
# add check if metadata is ipld marshalled CID string
|
||||||
|
raise TypeError("`metadata` must be a CID string or None")
|
||||||
|
|
||||||
# generate_outputs
|
return True
|
||||||
for recipient in recipients:
|
|
||||||
if not isinstance(recipient, tuple) or len(recipient) != 2:
|
|
||||||
raise ValueError(
|
|
||||||
("Each `recipient` in the list must be a" " tuple of `([<list of public keys>]," " <amount>)`")
|
|
||||||
)
|
|
||||||
pub_keys, amount = recipient
|
|
||||||
outputs.append(Output.generate(pub_keys, amount))
|
|
||||||
|
|
||||||
# generate inputs
|
|
||||||
inputs.append(Input.generate(tx_signers))
|
|
||||||
|
|
||||||
return (inputs, outputs)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def generate(cls, tx_signers, recipients, metadata=None, asset=None):
|
def generate(cls, tx_signers, recipients, metadata=None, asset=None):
|
||||||
@ -74,5 +66,6 @@ class Create(Transaction):
|
|||||||
:class:`~planetmint.common.transaction.Transaction`
|
:class:`~planetmint.common.transaction.Transaction`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
(inputs, outputs) = cls.validate_create(tx_signers, recipients, asset, metadata)
|
Create.validate_create(tx_signers, recipients, asset, metadata)
|
||||||
return cls(cls.OPERATION, {"data": asset}, inputs, outputs, metadata)
|
(inputs, outputs) = Transaction.complete_tx_i_o(tx_signers, recipients)
|
||||||
|
return cls(cls.OPERATION, asset, inputs, outputs, metadata)
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
from planetmint.transactions.common.schema import TX_SCHEMA_CHAIN_MIGRATION_ELECTION
|
from planetmint.transactions.common.schema import TX_SCHEMA_CHAIN_MIGRATION_ELECTION
|
||||||
|
from planetmint.transactions.common.transaction import CHAIN_MIGRATION_ELECTION
|
||||||
from planetmint.transactions.types.elections.election import Election
|
from planetmint.transactions.types.elections.election import Election
|
||||||
|
|
||||||
|
|
||||||
class ChainMigrationElection(Election):
|
class ChainMigrationElection(Election):
|
||||||
|
|
||||||
OPERATION = "CHAIN_MIGRATION_ELECTION"
|
OPERATION = CHAIN_MIGRATION_ELECTION
|
||||||
CREATE = OPERATION
|
# CREATE = OPERATION
|
||||||
ALLOWED_OPERATIONS = (OPERATION,)
|
ALLOWED_OPERATIONS = (OPERATION,)
|
||||||
TX_SCHEMA_CUSTOM = TX_SCHEMA_CHAIN_MIGRATION_ELECTION
|
TX_SCHEMA_CUSTOM = TX_SCHEMA_CHAIN_MIGRATION_ELECTION
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ from planetmint.transactions.common.exceptions import (
|
|||||||
from planetmint.tendermint_utils import key_from_base64, public_key_to_base64
|
from planetmint.tendermint_utils import key_from_base64, public_key_to_base64
|
||||||
from planetmint.transactions.common.crypto import public_key_from_ed25519_key
|
from planetmint.transactions.common.crypto import public_key_from_ed25519_key
|
||||||
from planetmint.transactions.common.transaction import Transaction
|
from planetmint.transactions.common.transaction import Transaction
|
||||||
from planetmint.transactions.common.schema import _validate_schema, TX_SCHEMA_COMMON, TX_SCHEMA_CREATE
|
from planetmint.transactions.common.schema import _validate_schema, TX_SCHEMA_COMMON
|
||||||
|
|
||||||
|
|
||||||
class Election(Transaction):
|
class Election(Transaction):
|
||||||
@ -94,6 +94,25 @@ class Election(Transaction):
|
|||||||
# validators and their voting power in the network
|
# validators and their voting power in the network
|
||||||
return current_topology == voters
|
return current_topology == voters
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def validate_election(self, tx_signers, recipients, asset, metadata):
|
||||||
|
if not isinstance(tx_signers, list):
|
||||||
|
raise TypeError("`tx_signers` must be a list instance")
|
||||||
|
if not isinstance(recipients, list):
|
||||||
|
raise TypeError("`recipients` must be a list instance")
|
||||||
|
if len(tx_signers) == 0:
|
||||||
|
raise ValueError("`tx_signers` list cannot be empty")
|
||||||
|
if len(recipients) == 0:
|
||||||
|
raise ValueError("`recipients` list cannot be empty")
|
||||||
|
if not asset is None:
|
||||||
|
if not isinstance(asset, dict):
|
||||||
|
raise TypeError("`asset` must be a CID string or None")
|
||||||
|
if not (metadata is None or isinstance(metadata, str)):
|
||||||
|
# add check if metadata is ipld marshalled CID string
|
||||||
|
raise TypeError("`metadata` must be a CID string or None")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
def validate(self, planet, current_transactions=[]):
|
def validate(self, planet, current_transactions=[]):
|
||||||
"""Validate election transaction
|
"""Validate election transaction
|
||||||
|
|
||||||
@ -145,7 +164,8 @@ class Election(Transaction):
|
|||||||
uuid = uuid4()
|
uuid = uuid4()
|
||||||
election_data["seed"] = str(uuid)
|
election_data["seed"] = str(uuid)
|
||||||
|
|
||||||
(inputs, outputs) = Create.validate_create(initiator, voters, election_data, metadata)
|
Election.validate_election(initiator, voters, election_data, metadata)
|
||||||
|
(inputs, outputs) = Transaction.complete_tx_i_o(initiator, voters)
|
||||||
election = cls(cls.OPERATION, {"data": election_data}, inputs, outputs, metadata)
|
election = cls(cls.OPERATION, {"data": election_data}, inputs, outputs, metadata)
|
||||||
cls.validate_schema(election.to_dict())
|
cls.validate_schema(election.to_dict())
|
||||||
return election
|
return election
|
||||||
@ -156,7 +176,6 @@ class Election(Transaction):
|
|||||||
`CREATE` transaction should be inherited
|
`CREATE` transaction should be inherited
|
||||||
"""
|
"""
|
||||||
_validate_schema(TX_SCHEMA_COMMON, tx)
|
_validate_schema(TX_SCHEMA_COMMON, tx)
|
||||||
_validate_schema(TX_SCHEMA_CREATE, tx)
|
|
||||||
if cls.TX_SCHEMA_CUSTOM:
|
if cls.TX_SCHEMA_CUSTOM:
|
||||||
_validate_schema(cls.TX_SCHEMA_CUSTOM, tx)
|
_validate_schema(cls.TX_SCHEMA_CUSTOM, tx)
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
from planetmint.transactions.types.assets.create import Create
|
from planetmint.transactions.types.assets.create import Create
|
||||||
from planetmint.transactions.types.assets.transfer import Transfer
|
from planetmint.transactions.types.assets.transfer import Transfer
|
||||||
|
from planetmint.transactions.common.transaction import VOTE
|
||||||
from planetmint.transactions.common.schema import (
|
from planetmint.transactions.common.schema import (
|
||||||
_validate_schema,
|
_validate_schema,
|
||||||
TX_SCHEMA_COMMON,
|
TX_SCHEMA_COMMON,
|
||||||
@ -15,7 +16,7 @@ from planetmint.transactions.common.schema import (
|
|||||||
|
|
||||||
class Vote(Transfer):
|
class Vote(Transfer):
|
||||||
|
|
||||||
OPERATION = "VOTE"
|
OPERATION = VOTE
|
||||||
# NOTE: This class inherits TRANSFER txn type. The `TRANSFER` property is
|
# NOTE: This class inherits TRANSFER txn type. The `TRANSFER` property is
|
||||||
# overriden to re-use methods from parent class
|
# overriden to re-use methods from parent class
|
||||||
TRANSFER = OPERATION
|
TRANSFER = OPERATION
|
||||||
|
@ -6,15 +6,16 @@
|
|||||||
from planetmint.transactions.common.exceptions import InvalidPowerChange
|
from planetmint.transactions.common.exceptions import InvalidPowerChange
|
||||||
from planetmint.transactions.types.elections.election import Election
|
from planetmint.transactions.types.elections.election import Election
|
||||||
from planetmint.transactions.common.schema import TX_SCHEMA_VALIDATOR_ELECTION
|
from planetmint.transactions.common.schema import TX_SCHEMA_VALIDATOR_ELECTION
|
||||||
|
from planetmint.transactions.common.transaction import VALIDATOR_ELECTION
|
||||||
|
|
||||||
|
# from planetmint.transactions.common.transaction import Transaction
|
||||||
|
|
||||||
from .validator_utils import new_validator_set, encode_validator, validate_asset_public_key
|
from .validator_utils import new_validator_set, encode_validator, validate_asset_public_key
|
||||||
|
|
||||||
|
|
||||||
class ValidatorElection(Election):
|
class ValidatorElection(Election):
|
||||||
|
|
||||||
OPERATION = "VALIDATOR_ELECTION"
|
OPERATION = VALIDATOR_ELECTION
|
||||||
# NOTE: this transaction class extends create so the operation inheritence is achieved
|
|
||||||
# by renaming CREATE to VALIDATOR_ELECTION
|
|
||||||
CREATE = OPERATION
|
|
||||||
ALLOWED_OPERATIONS = (OPERATION,)
|
ALLOWED_OPERATIONS = (OPERATION,)
|
||||||
TX_SCHEMA_CUSTOM = TX_SCHEMA_VALIDATOR_ELECTION
|
TX_SCHEMA_CUSTOM = TX_SCHEMA_VALIDATOR_ELECTION
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
|
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
|
||||||
# Code is Apache-2.0 and docs are CC-BY-4.0
|
# Code is Apache-2.0 and docs are CC-BY-4.0
|
||||||
|
|
||||||
__version__ = "1.1.1"
|
__version__ = "1.2.0"
|
||||||
__short_version__ = "1.1"
|
__short_version__ = "1.2"
|
||||||
|
|
||||||
# Supported Tendermint versions
|
# Supported Tendermint versions
|
||||||
__tm_supported_versions__ = ["0.34.15"]
|
__tm_supported_versions__ = ["0.34.15"]
|
||||||
|
9
setup.py
9
setup.py
@ -51,7 +51,7 @@ docs_require = [
|
|||||||
"charset-normalizer==2.0.12",
|
"charset-normalizer==2.0.12",
|
||||||
"commonmark==0.9.1",
|
"commonmark==0.9.1",
|
||||||
"docutils==0.17.1",
|
"docutils==0.17.1",
|
||||||
"idna",
|
"idna==2.10", # version conflict with requests lib (required version <3)
|
||||||
"imagesize==1.3.0",
|
"imagesize==1.3.0",
|
||||||
"importlib-metadata==4.11.3",
|
"importlib-metadata==4.11.3",
|
||||||
"Jinja2==3.0.0",
|
"Jinja2==3.0.0",
|
||||||
@ -129,6 +129,13 @@ install_requires = [
|
|||||||
"werkzeug==2.0.3",
|
"werkzeug==2.0.3",
|
||||||
"nest-asyncio==1.5.5",
|
"nest-asyncio==1.5.5",
|
||||||
"protobuf==3.20.1",
|
"protobuf==3.20.1",
|
||||||
|
"planetmint-ipld>=0.0.3",
|
||||||
|
"pyasn1",
|
||||||
|
"zenroom==2.1.0.dev1655293214",
|
||||||
|
"base58>=2.1.0",
|
||||||
|
"PyNaCl==1.4.0",
|
||||||
|
"pyasn1>=0.4.8",
|
||||||
|
"cryptography==3.4.7",
|
||||||
]
|
]
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
|
@ -51,9 +51,13 @@ def test_asset_id_mismatch(alice, user_pk):
|
|||||||
from planetmint.transactions.common.transaction import Transaction
|
from planetmint.transactions.common.transaction import Transaction
|
||||||
from planetmint.transactions.common.exceptions import AssetIdMismatch
|
from planetmint.transactions.common.exceptions import AssetIdMismatch
|
||||||
|
|
||||||
tx1 = Create.generate([alice.public_key], [([user_pk], 1)], metadata={"msg": random.random()})
|
tx1 = Create.generate(
|
||||||
|
[alice.public_key], [([user_pk], 1)], metadata="QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"
|
||||||
|
)
|
||||||
tx1.sign([alice.private_key])
|
tx1.sign([alice.private_key])
|
||||||
tx2 = Create.generate([alice.public_key], [([user_pk], 1)], metadata={"msg": random.random()})
|
tx2 = Create.generate(
|
||||||
|
[alice.public_key], [([user_pk], 1)], metadata="zb2rhe5P4gXftAwvA4eXQ5HJwsER2owDyS9sKaQRRVQPn93bA"
|
||||||
|
)
|
||||||
tx2.sign([alice.private_key])
|
tx2.sign([alice.private_key])
|
||||||
|
|
||||||
with pytest.raises(AssetIdMismatch):
|
with pytest.raises(AssetIdMismatch):
|
||||||
|
@ -19,7 +19,9 @@ from planetmint.transactions.common.exceptions import DoubleSpend
|
|||||||
# Single owners_after
|
# Single owners_after
|
||||||
def test_single_in_single_own_single_out_single_own_create(alice, user_pk, b):
|
def test_single_in_single_own_single_out_single_own_create(alice, user_pk, b):
|
||||||
|
|
||||||
tx = Create.generate([alice.public_key], [([user_pk], 100)], asset={"name": random.random()})
|
tx = Create.generate(
|
||||||
|
[alice.public_key], [([user_pk], 100)], asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}
|
||||||
|
)
|
||||||
tx_signed = tx.sign([alice.private_key])
|
tx_signed = tx.sign([alice.private_key])
|
||||||
|
|
||||||
assert tx_signed.validate(b) == tx_signed
|
assert tx_signed.validate(b) == tx_signed
|
||||||
@ -35,7 +37,11 @@ def test_single_in_single_own_single_out_single_own_create(alice, user_pk, b):
|
|||||||
# Single owners_after per output
|
# Single owners_after per output
|
||||||
def test_single_in_single_own_multiple_out_single_own_create(alice, user_pk, b):
|
def test_single_in_single_own_multiple_out_single_own_create(alice, user_pk, b):
|
||||||
|
|
||||||
tx = Create.generate([alice.public_key], [([user_pk], 50), ([user_pk], 50)], asset={"name": random.random()})
|
tx = Create.generate(
|
||||||
|
[alice.public_key],
|
||||||
|
[([user_pk], 50), ([user_pk], 50)],
|
||||||
|
asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||||
|
)
|
||||||
tx_signed = tx.sign([alice.private_key])
|
tx_signed = tx.sign([alice.private_key])
|
||||||
|
|
||||||
assert tx_signed.validate(b) == tx_signed
|
assert tx_signed.validate(b) == tx_signed
|
||||||
@ -52,7 +58,11 @@ def test_single_in_single_own_multiple_out_single_own_create(alice, user_pk, b):
|
|||||||
# Multiple owners_after
|
# Multiple owners_after
|
||||||
def test_single_in_single_own_single_out_multiple_own_create(alice, user_pk, b):
|
def test_single_in_single_own_single_out_multiple_own_create(alice, user_pk, b):
|
||||||
|
|
||||||
tx = Create.generate([alice.public_key], [([user_pk, user_pk], 100)], asset={"name": random.random()})
|
tx = Create.generate(
|
||||||
|
[alice.public_key],
|
||||||
|
[([user_pk, user_pk], 100)],
|
||||||
|
asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||||
|
)
|
||||||
tx_signed = tx.sign([alice.private_key])
|
tx_signed = tx.sign([alice.private_key])
|
||||||
|
|
||||||
assert tx_signed.validate(b) == tx_signed
|
assert tx_signed.validate(b) == tx_signed
|
||||||
@ -75,7 +85,9 @@ def test_single_in_single_own_single_out_multiple_own_create(alice, user_pk, b):
|
|||||||
def test_single_in_single_own_multiple_out_mix_own_create(alice, user_pk, b):
|
def test_single_in_single_own_multiple_out_mix_own_create(alice, user_pk, b):
|
||||||
|
|
||||||
tx = Create.generate(
|
tx = Create.generate(
|
||||||
[alice.public_key], [([user_pk], 50), ([user_pk, user_pk], 50)], asset={"name": random.random()}
|
[alice.public_key],
|
||||||
|
[([user_pk], 50), ([user_pk, user_pk], 50)],
|
||||||
|
asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||||
)
|
)
|
||||||
tx_signed = tx.sign([alice.private_key])
|
tx_signed = tx.sign([alice.private_key])
|
||||||
|
|
||||||
@ -98,7 +110,11 @@ def test_single_in_single_own_multiple_out_mix_own_create(alice, user_pk, b):
|
|||||||
def test_single_in_multiple_own_single_out_single_own_create(alice, b, user_pk, user_sk):
|
def test_single_in_multiple_own_single_out_single_own_create(alice, b, user_pk, user_sk):
|
||||||
from planetmint.transactions.common.utils import _fulfillment_to_details
|
from planetmint.transactions.common.utils import _fulfillment_to_details
|
||||||
|
|
||||||
tx = Create.generate([alice.public_key, user_pk], [([user_pk], 100)], asset={"name": random.random()})
|
tx = Create.generate(
|
||||||
|
[alice.public_key, user_pk],
|
||||||
|
[([user_pk], 100)],
|
||||||
|
asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||||
|
)
|
||||||
tx_signed = tx.sign([alice.private_key, user_sk])
|
tx_signed = tx.sign([alice.private_key, user_sk])
|
||||||
assert tx_signed.validate(b) == tx_signed
|
assert tx_signed.validate(b) == tx_signed
|
||||||
assert len(tx_signed.outputs) == 1
|
assert len(tx_signed.outputs) == 1
|
||||||
@ -118,7 +134,9 @@ def test_single_in_multiple_own_single_out_single_own_create(alice, b, user_pk,
|
|||||||
def test_single_in_single_own_single_out_single_own_transfer(alice, b, user_pk, user_sk):
|
def test_single_in_single_own_single_out_single_own_transfer(alice, b, user_pk, user_sk):
|
||||||
|
|
||||||
# CREATE divisible asset
|
# CREATE divisible asset
|
||||||
tx_create = Create.generate([alice.public_key], [([user_pk], 100)], asset={"name": random.random()})
|
tx_create = Create.generate(
|
||||||
|
[alice.public_key], [([user_pk], 100)], asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}
|
||||||
|
)
|
||||||
tx_create_signed = tx_create.sign([alice.private_key])
|
tx_create_signed = tx_create.sign([alice.private_key])
|
||||||
|
|
||||||
# TRANSFER
|
# TRANSFER
|
||||||
@ -141,7 +159,9 @@ def test_single_in_single_own_single_out_single_own_transfer(alice, b, user_pk,
|
|||||||
def test_single_in_single_own_multiple_out_single_own_transfer(alice, b, user_pk, user_sk):
|
def test_single_in_single_own_multiple_out_single_own_transfer(alice, b, user_pk, user_sk):
|
||||||
|
|
||||||
# CREATE divisible asset
|
# CREATE divisible asset
|
||||||
tx_create = Create.generate([alice.public_key], [([user_pk], 100)], asset={"name": random.random()})
|
tx_create = Create.generate(
|
||||||
|
[alice.public_key], [([user_pk], 100)], asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}
|
||||||
|
)
|
||||||
tx_create_signed = tx_create.sign([alice.private_key])
|
tx_create_signed = tx_create.sign([alice.private_key])
|
||||||
|
|
||||||
# TRANSFER
|
# TRANSFER
|
||||||
@ -167,7 +187,9 @@ def test_single_in_single_own_multiple_out_single_own_transfer(alice, b, user_pk
|
|||||||
def test_single_in_single_own_single_out_multiple_own_transfer(alice, b, user_pk, user_sk):
|
def test_single_in_single_own_single_out_multiple_own_transfer(alice, b, user_pk, user_sk):
|
||||||
|
|
||||||
# CREATE divisible asset
|
# CREATE divisible asset
|
||||||
tx_create = Create.generate([alice.public_key], [([user_pk], 100)], asset={"name": random.random()})
|
tx_create = Create.generate(
|
||||||
|
[alice.public_key], [([user_pk], 100)], asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}
|
||||||
|
)
|
||||||
tx_create_signed = tx_create.sign([alice.private_key])
|
tx_create_signed = tx_create.sign([alice.private_key])
|
||||||
|
|
||||||
# TRANSFER
|
# TRANSFER
|
||||||
@ -201,7 +223,9 @@ def test_single_in_single_own_single_out_multiple_own_transfer(alice, b, user_pk
|
|||||||
def test_single_in_single_own_multiple_out_mix_own_transfer(alice, b, user_pk, user_sk):
|
def test_single_in_single_own_multiple_out_mix_own_transfer(alice, b, user_pk, user_sk):
|
||||||
|
|
||||||
# CREATE divisible asset
|
# CREATE divisible asset
|
||||||
tx_create = Create.generate([alice.public_key], [([user_pk], 100)], asset={"name": random.random()})
|
tx_create = Create.generate(
|
||||||
|
[alice.public_key], [([user_pk], 100)], asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}
|
||||||
|
)
|
||||||
tx_create_signed = tx_create.sign([alice.private_key])
|
tx_create_signed = tx_create.sign([alice.private_key])
|
||||||
|
|
||||||
# TRANSFER
|
# TRANSFER
|
||||||
@ -240,7 +264,9 @@ def test_single_in_multiple_own_single_out_single_own_transfer(alice, b, user_pk
|
|||||||
|
|
||||||
# CREATE divisible asset
|
# CREATE divisible asset
|
||||||
tx_create = Create.generate(
|
tx_create = Create.generate(
|
||||||
[alice.public_key], [([alice.public_key, user_pk], 100)], asset={"name": random.random()}
|
[alice.public_key],
|
||||||
|
[([alice.public_key, user_pk], 100)],
|
||||||
|
asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||||
)
|
)
|
||||||
tx_create_signed = tx_create.sign([alice.private_key])
|
tx_create_signed = tx_create.sign([alice.private_key])
|
||||||
|
|
||||||
@ -272,7 +298,9 @@ def test_single_in_multiple_own_single_out_single_own_transfer(alice, b, user_pk
|
|||||||
def test_multiple_in_single_own_single_out_single_own_transfer(alice, b, user_pk, user_sk):
|
def test_multiple_in_single_own_single_out_single_own_transfer(alice, b, user_pk, user_sk):
|
||||||
# CREATE divisible asset
|
# CREATE divisible asset
|
||||||
tx_create = Create.generate(
|
tx_create = Create.generate(
|
||||||
[alice.public_key], [([user_pk], 50), ([user_pk], 50)], asset={"name": random.random()}
|
[alice.public_key],
|
||||||
|
[([user_pk], 50), ([user_pk], 50)],
|
||||||
|
asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||||
)
|
)
|
||||||
tx_create_signed = tx_create.sign([alice.private_key])
|
tx_create_signed = tx_create.sign([alice.private_key])
|
||||||
|
|
||||||
@ -304,7 +332,7 @@ def test_multiple_in_multiple_own_single_out_single_own_transfer(alice, b, user_
|
|||||||
tx_create = Create.generate(
|
tx_create = Create.generate(
|
||||||
[alice.public_key],
|
[alice.public_key],
|
||||||
[([user_pk, alice.public_key], 50), ([user_pk, alice.public_key], 50)],
|
[([user_pk, alice.public_key], 50), ([user_pk, alice.public_key], 50)],
|
||||||
asset={"name": random.random()},
|
asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||||
)
|
)
|
||||||
tx_create_signed = tx_create.sign([alice.private_key])
|
tx_create_signed = tx_create.sign([alice.private_key])
|
||||||
|
|
||||||
@ -342,7 +370,9 @@ def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(alice, b, user_pk
|
|||||||
|
|
||||||
# CREATE divisible asset
|
# CREATE divisible asset
|
||||||
tx_create = Create.generate(
|
tx_create = Create.generate(
|
||||||
[alice.public_key], [([user_pk], 50), ([user_pk, alice.public_key], 50)], asset={"name": random.random()}
|
[alice.public_key],
|
||||||
|
[([user_pk], 50), ([user_pk, alice.public_key], 50)],
|
||||||
|
asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||||
)
|
)
|
||||||
tx_create_signed = tx_create.sign([alice.private_key])
|
tx_create_signed = tx_create.sign([alice.private_key])
|
||||||
|
|
||||||
@ -379,7 +409,9 @@ def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(alice, b, user_pk, u
|
|||||||
|
|
||||||
# CREATE divisible asset
|
# CREATE divisible asset
|
||||||
tx_create = Create.generate(
|
tx_create = Create.generate(
|
||||||
[alice.public_key], [([user_pk], 50), ([user_pk, alice.public_key], 50)], asset={"name": random.random()}
|
[alice.public_key],
|
||||||
|
[([user_pk], 50), ([user_pk, alice.public_key], 50)],
|
||||||
|
asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||||
)
|
)
|
||||||
tx_create_signed = tx_create.sign([alice.private_key])
|
tx_create_signed = tx_create.sign([alice.private_key])
|
||||||
# TRANSFER
|
# TRANSFER
|
||||||
@ -423,7 +455,9 @@ def test_multiple_in_different_transactions(alice, b, user_pk, user_sk):
|
|||||||
# `b` creates a divisible asset and assigns 50 shares to `b` and
|
# `b` creates a divisible asset and assigns 50 shares to `b` and
|
||||||
# 50 shares to `user_pk`
|
# 50 shares to `user_pk`
|
||||||
tx_create = Create.generate(
|
tx_create = Create.generate(
|
||||||
[alice.public_key], [([user_pk], 50), ([alice.public_key], 50)], asset={"name": random.random()}
|
[alice.public_key],
|
||||||
|
[([user_pk], 50), ([alice.public_key], 50)],
|
||||||
|
asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||||
)
|
)
|
||||||
tx_create_signed = tx_create.sign([alice.private_key])
|
tx_create_signed = tx_create.sign([alice.private_key])
|
||||||
|
|
||||||
@ -462,7 +496,9 @@ def test_amount_error_transfer(alice, b, user_pk, user_sk):
|
|||||||
from planetmint.transactions.common.exceptions import AmountError
|
from planetmint.transactions.common.exceptions import AmountError
|
||||||
|
|
||||||
# CREATE divisible asset
|
# CREATE divisible asset
|
||||||
tx_create = Create.generate([alice.public_key], [([user_pk], 100)], asset={"name": random.random()})
|
tx_create = Create.generate(
|
||||||
|
[alice.public_key], [([user_pk], 100)], asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}
|
||||||
|
)
|
||||||
tx_create_signed = tx_create.sign([alice.private_key])
|
tx_create_signed = tx_create.sign([alice.private_key])
|
||||||
|
|
||||||
b.store_bulk_transactions([tx_create_signed])
|
b.store_bulk_transactions([tx_create_signed])
|
||||||
@ -493,7 +529,11 @@ def test_threshold_same_public_key(alice, b, user_pk, user_sk):
|
|||||||
# that does not mean that the code shouldn't work.
|
# that does not mean that the code shouldn't work.
|
||||||
|
|
||||||
# CREATE divisible asset
|
# CREATE divisible asset
|
||||||
tx_create = Create.generate([alice.public_key], [([user_pk, user_pk], 100)], asset={"name": random.random()})
|
tx_create = Create.generate(
|
||||||
|
[alice.public_key],
|
||||||
|
[([user_pk, user_pk], 100)],
|
||||||
|
asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||||
|
)
|
||||||
tx_create_signed = tx_create.sign([alice.private_key])
|
tx_create_signed = tx_create.sign([alice.private_key])
|
||||||
|
|
||||||
# TRANSFER
|
# TRANSFER
|
||||||
@ -512,7 +552,9 @@ def test_sum_amount(alice, b, user_pk, user_sk):
|
|||||||
|
|
||||||
# CREATE divisible asset with 3 outputs with amount 1
|
# CREATE divisible asset with 3 outputs with amount 1
|
||||||
tx_create = Create.generate(
|
tx_create = Create.generate(
|
||||||
[alice.public_key], [([user_pk], 1), ([user_pk], 1), ([user_pk], 1)], asset={"name": random.random()}
|
[alice.public_key],
|
||||||
|
[([user_pk], 1), ([user_pk], 1), ([user_pk], 1)],
|
||||||
|
asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||||
)
|
)
|
||||||
tx_create_signed = tx_create.sign([alice.private_key])
|
tx_create_signed = tx_create.sign([alice.private_key])
|
||||||
|
|
||||||
@ -535,7 +577,9 @@ def test_sum_amount(alice, b, user_pk, user_sk):
|
|||||||
def test_divide(alice, b, user_pk, user_sk):
|
def test_divide(alice, b, user_pk, user_sk):
|
||||||
|
|
||||||
# CREATE divisible asset with 1 output with amount 3
|
# CREATE divisible asset with 1 output with amount 3
|
||||||
tx_create = Create.generate([alice.public_key], [([user_pk], 3)], asset={"name": random.random()})
|
tx_create = Create.generate(
|
||||||
|
[alice.public_key], [([user_pk], 3)], asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}
|
||||||
|
)
|
||||||
tx_create_signed = tx_create.sign([alice.private_key])
|
tx_create_signed = tx_create.sign([alice.private_key])
|
||||||
|
|
||||||
# create a transfer transaction with 3 outputs and check if the amount
|
# create a transfer transaction with 3 outputs and check if the amount
|
||||||
|
@ -6,6 +6,7 @@ from zenroom import zencode_exec
|
|||||||
from cryptoconditions.types.ed25519 import Ed25519Sha256
|
from cryptoconditions.types.ed25519 import Ed25519Sha256
|
||||||
from cryptoconditions.types.zenroom import ZenroomSha256
|
from cryptoconditions.types.zenroom import ZenroomSha256
|
||||||
from planetmint.transactions.common.crypto import generate_key_pair
|
from planetmint.transactions.common.crypto import generate_key_pair
|
||||||
|
from ipld import multihash, marshal
|
||||||
|
|
||||||
CONDITION_SCRIPT = """Scenario 'ecdh': create the signature of an object
|
CONDITION_SCRIPT = """Scenario 'ecdh': create the signature of an object
|
||||||
Given I have the 'keyring'
|
Given I have the 'keyring'
|
||||||
@ -101,8 +102,8 @@ def test_zenroom_signing():
|
|||||||
metadata = {"result": {"output": ["ok"]}}
|
metadata = {"result": {"output": ["ok"]}}
|
||||||
token_creation_tx = {
|
token_creation_tx = {
|
||||||
"operation": "CREATE",
|
"operation": "CREATE",
|
||||||
"asset": {"data": {"test": "my asset"}},
|
"asset": {"data": multihash(marshal({"test": "my asset"}))},
|
||||||
"metadata": metadata,
|
"metadata": multihash(marshal(metadata)),
|
||||||
"script": script_,
|
"script": script_,
|
||||||
"outputs": [
|
"outputs": [
|
||||||
output,
|
output,
|
||||||
@ -171,9 +172,6 @@ def test_zenroom_signing():
|
|||||||
except ValidationError as e:
|
except ValidationError as e:
|
||||||
print("Invalid transaction ({}): {}".format(type(e).__name__, e))
|
print("Invalid transaction ({}): {}".format(type(e).__name__, e))
|
||||||
assert ()
|
assert ()
|
||||||
except e:
|
|
||||||
print(f"Exception : {e}")
|
|
||||||
assert ()
|
|
||||||
|
|
||||||
print(f"VALIDATED : {tx_obj}")
|
print(f"VALIDATED : {tx_obj}")
|
||||||
assert (tx_obj == False) is False
|
assert (tx_obj == False) is False
|
||||||
|
@ -89,7 +89,7 @@ def test_bigchain_show_config(capsys):
|
|||||||
print(f"config : {sorted_output_config}")
|
print(f"config : {sorted_output_config}")
|
||||||
# Note: This test passed previously because we were always
|
# Note: This test passed previously because we were always
|
||||||
# using the default configuration parameters, but since we
|
# using the default configuration parameters, but since we
|
||||||
# are running with docker-compose now and expose parameters like
|
# are running with docker compose now and expose parameters like
|
||||||
# PLANETMINT_SERVER_BIND, PLANETMINT_WSSERVER_HOST, PLANETMINT_WSSERVER_ADVERTISED_HOST
|
# PLANETMINT_SERVER_BIND, PLANETMINT_WSSERVER_HOST, PLANETMINT_WSSERVER_ADVERTISED_HOST
|
||||||
# the default comparison fails i.e. when config is imported at the beginning the
|
# the default comparison fails i.e. when config is imported at the beginning the
|
||||||
# dict returned is different that what is expected after run_show_config
|
# dict returned is different that what is expected after run_show_config
|
||||||
@ -268,10 +268,16 @@ def test_run_recover(b, alice, bob):
|
|||||||
from planetmint.backend import query
|
from planetmint.backend import query
|
||||||
|
|
||||||
tx1 = Create.generate(
|
tx1 = Create.generate(
|
||||||
[alice.public_key], [([alice.public_key], 1)], asset={"cycle": "hero"}, metadata={"name": "hohenheim"}
|
[alice.public_key],
|
||||||
|
[([alice.public_key], 1)],
|
||||||
|
asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||||
|
metadata="QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4",
|
||||||
).sign([alice.private_key])
|
).sign([alice.private_key])
|
||||||
tx2 = Create.generate(
|
tx2 = Create.generate(
|
||||||
[bob.public_key], [([bob.public_key], 1)], asset={"cycle": "hero"}, metadata={"name": "hohenheim"}
|
[bob.public_key],
|
||||||
|
[([bob.public_key], 1)],
|
||||||
|
asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||||
|
metadata="QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4",
|
||||||
).sign([bob.private_key])
|
).sign([bob.private_key])
|
||||||
print(tx1.id)
|
print(tx1.id)
|
||||||
print(tx2.id)
|
print(tx2.id)
|
||||||
|
@ -23,9 +23,9 @@ CC_FULFILLMENT_URI = (
|
|||||||
)
|
)
|
||||||
CC_CONDITION_URI = "ni:///sha-256;" "eZI5q6j8T_fqv7xMROaei9_tmTMk4S7WR5Kr4onPHV8" "?fpt=ed25519-sha-256&cost=131072"
|
CC_CONDITION_URI = "ni:///sha-256;" "eZI5q6j8T_fqv7xMROaei9_tmTMk4S7WR5Kr4onPHV8" "?fpt=ed25519-sha-256&cost=131072"
|
||||||
|
|
||||||
ASSET_DEFINITION = {"data": {"definition": "Asset definition"}}
|
ASSET_DEFINITION = {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}
|
||||||
|
|
||||||
DATA = {"msg": "Hello Planetmint!"}
|
DATA = "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@ -189,11 +189,7 @@ def dummy_transaction():
|
|||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def unfulfilled_transaction():
|
def unfulfilled_transaction():
|
||||||
return {
|
return {
|
||||||
"asset": {
|
"asset": {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||||
"data": {
|
|
||||||
"msg": "Hello Planetmint!",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"id": None,
|
"id": None,
|
||||||
"inputs": [
|
"inputs": [
|
||||||
{
|
{
|
||||||
@ -229,11 +225,7 @@ def unfulfilled_transaction():
|
|||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def fulfilled_transaction():
|
def fulfilled_transaction():
|
||||||
return {
|
return {
|
||||||
"asset": {
|
"asset": {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||||
"data": {
|
|
||||||
"msg": "Hello Planetmint!",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"id": None,
|
"id": None,
|
||||||
"inputs": [
|
"inputs": [
|
||||||
{
|
{
|
||||||
@ -292,11 +284,7 @@ def fulfilled_transaction():
|
|||||||
)
|
)
|
||||||
def tri_state_transaction(request):
|
def tri_state_transaction(request):
|
||||||
tx = {
|
tx = {
|
||||||
"asset": {
|
"asset": {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||||
"data": {
|
|
||||||
"msg": "Hello Planetmint!",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"id": None,
|
"id": None,
|
||||||
"inputs": [
|
"inputs": [
|
||||||
{"fulfillment": None, "fulfills": None, "owners_before": ["JEAkEJqLbbgDRAtMm8YAjGp759Aq2qTn9eaEHUj2XePE"]}
|
{"fulfillment": None, "fulfills": None, "owners_before": ["JEAkEJqLbbgDRAtMm8YAjGp759Aq2qTn9eaEHUj2XePE"]}
|
||||||
|
@ -17,9 +17,7 @@ pytestmark = pytest.mark.bdb
|
|||||||
|
|
||||||
def test_memoize_to_dict(b):
|
def test_memoize_to_dict(b):
|
||||||
alice = generate_key_pair()
|
alice = generate_key_pair()
|
||||||
asset = {
|
asset = {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}
|
||||||
"data": {"id": "test_id"},
|
|
||||||
}
|
|
||||||
|
|
||||||
assert to_dict.cache_info().hits == 0
|
assert to_dict.cache_info().hits == 0
|
||||||
assert to_dict.cache_info().misses == 0
|
assert to_dict.cache_info().misses == 0
|
||||||
@ -44,9 +42,7 @@ def test_memoize_to_dict(b):
|
|||||||
|
|
||||||
def test_memoize_from_dict(b):
|
def test_memoize_from_dict(b):
|
||||||
alice = generate_key_pair()
|
alice = generate_key_pair()
|
||||||
asset = {
|
asset = {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}
|
||||||
"data": {"id": "test_id"},
|
|
||||||
}
|
|
||||||
|
|
||||||
assert from_dict.cache_info().hits == 0
|
assert from_dict.cache_info().hits == 0
|
||||||
assert from_dict.cache_info().misses == 0
|
assert from_dict.cache_info().misses == 0
|
||||||
@ -72,9 +68,7 @@ def test_memoize_from_dict(b):
|
|||||||
|
|
||||||
def test_memoize_input_valid(b):
|
def test_memoize_input_valid(b):
|
||||||
alice = generate_key_pair()
|
alice = generate_key_pair()
|
||||||
asset = {
|
asset = {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}
|
||||||
"data": {"id": "test_id"},
|
|
||||||
}
|
|
||||||
|
|
||||||
assert Transaction._input_valid.cache_info().hits == 0
|
assert Transaction._input_valid.cache_info().hits == 0
|
||||||
assert Transaction._input_valid.cache_info().misses == 0
|
assert Transaction._input_valid.cache_info().misses == 0
|
||||||
|
@ -259,7 +259,9 @@ def test_invalid_transaction_initialization(asset_definition):
|
|||||||
with raises(TypeError):
|
with raises(TypeError):
|
||||||
Transaction(operation="CREATE", asset=asset_definition, outputs=[], inputs="invalid inputs")
|
Transaction(operation="CREATE", asset=asset_definition, outputs=[], inputs="invalid inputs")
|
||||||
with raises(TypeError):
|
with raises(TypeError):
|
||||||
Transaction(operation="CREATE", asset=asset_definition, outputs=[], inputs=[], metadata="invalid metadata")
|
Transaction(
|
||||||
|
operation="CREATE", asset=asset_definition, outputs=[], inputs=[], metadata={"data": "invalid metadata"}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def test_create_default_asset_on_tx_initialization(asset_definition):
|
def test_create_default_asset_on_tx_initialization(asset_definition):
|
||||||
@ -576,7 +578,7 @@ def test_create_create_transaction_single_io(user_output, user_pub, data):
|
|||||||
"version": Transaction.VERSION,
|
"version": Transaction.VERSION,
|
||||||
}
|
}
|
||||||
|
|
||||||
tx = Create.generate([user_pub], [([user_pub], 1)], metadata=data, asset=data)
|
tx = Create.generate([user_pub], [([user_pub], 1)], metadata=data, asset={"data": data})
|
||||||
tx_dict = tx.to_dict()
|
tx_dict = tx.to_dict()
|
||||||
tx_dict["inputs"][0]["fulfillment"] = None
|
tx_dict["inputs"][0]["fulfillment"] = None
|
||||||
tx_dict.pop("id")
|
tx_dict.pop("id")
|
||||||
@ -600,13 +602,15 @@ def test_create_create_transaction_multiple_io(user_output, user2_output, user_p
|
|||||||
input = Input.generate([user_pub, user2_pub]).to_dict()
|
input = Input.generate([user_pub, user2_pub]).to_dict()
|
||||||
expected = {
|
expected = {
|
||||||
"outputs": [user_output.to_dict(), user2_output.to_dict()],
|
"outputs": [user_output.to_dict(), user2_output.to_dict()],
|
||||||
"metadata": {"message": "hello"},
|
"metadata": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4",
|
||||||
"inputs": [input],
|
"inputs": [input],
|
||||||
"operation": "CREATE",
|
"operation": "CREATE",
|
||||||
"version": Transaction.VERSION,
|
"version": Transaction.VERSION,
|
||||||
}
|
}
|
||||||
tx = Create.generate(
|
tx = Create.generate(
|
||||||
[user_pub, user2_pub], [([user_pub], 1), ([user2_pub], 1)], metadata={"message": "hello"}
|
[user_pub, user2_pub],
|
||||||
|
[([user_pub], 1), ([user2_pub], 1)],
|
||||||
|
metadata="QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4",
|
||||||
).to_dict()
|
).to_dict()
|
||||||
tx.pop("id")
|
tx.pop("id")
|
||||||
tx.pop("asset")
|
tx.pop("asset")
|
||||||
@ -617,7 +621,11 @@ def test_create_create_transaction_multiple_io(user_output, user2_output, user_p
|
|||||||
def test_validate_multiple_io_create_transaction(user_pub, user_priv, user2_pub, user2_priv, asset_definition):
|
def test_validate_multiple_io_create_transaction(user_pub, user_priv, user2_pub, user2_priv, asset_definition):
|
||||||
from .utils import validate_transaction_model
|
from .utils import validate_transaction_model
|
||||||
|
|
||||||
tx = Create.generate([user_pub, user2_pub], [([user_pub], 1), ([user2_pub], 1)], metadata={"message": "hello"})
|
tx = Create.generate(
|
||||||
|
[user_pub, user2_pub],
|
||||||
|
[([user_pub], 1), ([user2_pub], 1)],
|
||||||
|
metadata="QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4",
|
||||||
|
)
|
||||||
tx = tx.sign([user_priv, user2_priv])
|
tx = tx.sign([user_priv, user2_priv])
|
||||||
assert tx.inputs_valid() is True
|
assert tx.inputs_valid() is True
|
||||||
|
|
||||||
@ -645,7 +653,7 @@ def test_create_create_transaction_threshold(
|
|||||||
"operation": "CREATE",
|
"operation": "CREATE",
|
||||||
"version": Transaction.VERSION,
|
"version": Transaction.VERSION,
|
||||||
}
|
}
|
||||||
tx = Create.generate([user_pub], [([user_pub, user2_pub], 1)], metadata=data, asset=data)
|
tx = Create.generate([user_pub], [([user_pub, user2_pub], 1)], metadata=data, asset={"data": data})
|
||||||
tx_dict = tx.to_dict()
|
tx_dict = tx.to_dict()
|
||||||
tx_dict.pop("id")
|
tx_dict.pop("id")
|
||||||
tx_dict["inputs"][0]["fulfillment"] = None
|
tx_dict["inputs"][0]["fulfillment"] = None
|
||||||
@ -677,9 +685,9 @@ def test_create_create_transaction_with_invalid_parameters(user_pub):
|
|||||||
with raises(ValueError):
|
with raises(ValueError):
|
||||||
Create.generate([user_pub], [([user_pub],)])
|
Create.generate([user_pub], [([user_pub],)])
|
||||||
with raises(TypeError):
|
with raises(TypeError):
|
||||||
Create.generate([user_pub], [([user_pub], 1)], metadata="not a dict or none")
|
Create.generate([user_pub], [([user_pub], 1)], metadata={"data": "not a dict or none"})
|
||||||
with raises(TypeError):
|
with raises(ValueError):
|
||||||
Create.generate([user_pub], [([user_pub], 1)], asset="not a dict or none")
|
Create.generate([user_pub], [([user_pub], 1)], asset={"data": "not a dict or none"})
|
||||||
|
|
||||||
|
|
||||||
def test_outputs_to_inputs(tx):
|
def test_outputs_to_inputs(tx):
|
||||||
@ -741,7 +749,9 @@ def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub, user2_ou
|
|||||||
def test_create_transfer_transaction_multiple_io(
|
def test_create_transfer_transaction_multiple_io(
|
||||||
user_pub, user_priv, user2_pub, user2_priv, user3_pub, user2_output, asset_definition
|
user_pub, user_priv, user2_pub, user2_priv, user3_pub, user2_output, asset_definition
|
||||||
):
|
):
|
||||||
tx = Create.generate([user_pub], [([user_pub], 1), ([user2_pub], 1)], metadata={"message": "hello"})
|
tx = Create.generate(
|
||||||
|
[user_pub], [([user_pub], 1), ([user2_pub], 1)], metadata="QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"
|
||||||
|
)
|
||||||
tx = tx.sign([user_priv])
|
tx = tx.sign([user_priv])
|
||||||
|
|
||||||
expected = {
|
expected = {
|
||||||
@ -794,7 +804,7 @@ def test_create_transfer_with_invalid_parameters(tx, user_pub):
|
|||||||
with raises(ValueError):
|
with raises(ValueError):
|
||||||
Transfer.generate(["fulfillment"], [([user_pub],)], tx.id)
|
Transfer.generate(["fulfillment"], [([user_pub],)], tx.id)
|
||||||
with raises(TypeError):
|
with raises(TypeError):
|
||||||
Transfer.generate(["fulfillment"], [([user_pub], 1)], tx.id, metadata="not a dict or none")
|
Transfer.generate(["fulfillment"], [([user_pub], 1)], tx.id, metadata={"data": "not a cid string or none"})
|
||||||
with raises(TypeError):
|
with raises(TypeError):
|
||||||
Transfer.generate(["fulfillment"], [([user_pub], 1)], ["not a string"])
|
Transfer.generate(["fulfillment"], [([user_pub], 1)], ["not a string"])
|
||||||
|
|
||||||
@ -851,7 +861,7 @@ def test_unspent_outputs_property(merlin, alice, bob, carol):
|
|||||||
tx = Create.generate(
|
tx = Create.generate(
|
||||||
[merlin.public_key],
|
[merlin.public_key],
|
||||||
[([alice.public_key], 1), ([bob.public_key], 2), ([carol.public_key], 3)],
|
[([alice.public_key], 1), ([bob.public_key], 2), ([carol.public_key], 3)],
|
||||||
asset={"hash": "06e47bcf9084f7ecfd2a2a2ad275444a"},
|
asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||||
).sign([merlin.private_key])
|
).sign([merlin.private_key])
|
||||||
unspent_outputs = list(tx.unspent_outputs)
|
unspent_outputs = list(tx.unspent_outputs)
|
||||||
assert len(unspent_outputs) == 3
|
assert len(unspent_outputs) == 3
|
||||||
|
@ -15,6 +15,7 @@ import copy
|
|||||||
import random
|
import random
|
||||||
import tempfile
|
import tempfile
|
||||||
import codecs
|
import codecs
|
||||||
|
from ipld import marshal, multihash
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from logging.config import dictConfig
|
from logging.config import dictConfig
|
||||||
@ -287,7 +288,8 @@ def create_tx(alice, user_pk):
|
|||||||
from planetmint.transactions.types.assets.create import Create
|
from planetmint.transactions.types.assets.create import Create
|
||||||
|
|
||||||
name = f"I am created by the create_tx fixture. My random identifier is {random.random()}."
|
name = f"I am created by the create_tx fixture. My random identifier is {random.random()}."
|
||||||
return Create.generate([alice.public_key], [([user_pk], 1)], asset={"name": name})
|
asset = {"data": multihash(marshal({"name": name}))}
|
||||||
|
return Create.generate([alice.public_key], [([user_pk], 1)], asset=asset)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
@ -333,9 +335,7 @@ def inputs(user_pk, b, alice):
|
|||||||
for height in range(1, 4):
|
for height in range(1, 4):
|
||||||
transactions = [
|
transactions = [
|
||||||
Create.generate(
|
Create.generate(
|
||||||
[alice.public_key],
|
[alice.public_key], [([user_pk], 1)], metadata=multihash(marshal({"data": f"{random.random()}"}))
|
||||||
[([user_pk], 1)],
|
|
||||||
metadata={"msg": random.random()},
|
|
||||||
).sign([alice.private_key])
|
).sign([alice.private_key])
|
||||||
for _ in range(10)
|
for _ in range(10)
|
||||||
]
|
]
|
||||||
|
@ -6,7 +6,7 @@ import warnings
|
|||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
from planetmint.transactions.types.assets.create import Create
|
from planetmint.transactions.types.assets.create import Create
|
||||||
from planetmint.transactions.types.assets.transfer import Transfer
|
from planetmint.transactions.types.assets.transfer import Transfer
|
||||||
|
from ipld import marshal, multihash
|
||||||
import pytest
|
import pytest
|
||||||
from base58 import b58decode
|
from base58 import b58decode
|
||||||
|
|
||||||
@ -65,9 +65,9 @@ class TestBigchainApi(object):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# define the assets
|
# define the assets
|
||||||
asset1 = {"msg": "Planetmint 1"}
|
asset1 = {"data": multihash(marshal({"msg": "Planetmint 1"}))}
|
||||||
asset2 = {"msg": "Planetmint 2"}
|
asset2 = {"data": multihash(marshal({"msg": "Planetmint 2"}))}
|
||||||
asset3 = {"msg": "Planetmint 3"}
|
asset3 = {"data": multihash(marshal({"msg": "Planetmint 3"}))}
|
||||||
|
|
||||||
# create the transactions
|
# create the transactions
|
||||||
tx1 = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset1).sign([alice.private_key])
|
tx1 = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset1).sign([alice.private_key])
|
||||||
@ -79,7 +79,7 @@ class TestBigchainApi(object):
|
|||||||
|
|
||||||
# get the assets through text search
|
# get the assets through text search
|
||||||
assets = list(b.text_search("planetmint"))
|
assets = list(b.text_search("planetmint"))
|
||||||
assert len(assets) == 3
|
assert len(assets) == 0
|
||||||
|
|
||||||
@pytest.mark.usefixtures("inputs")
|
@pytest.mark.usefixtures("inputs")
|
||||||
def test_non_create_input_not_found(self, b, user_pk):
|
def test_non_create_input_not_found(self, b, user_pk):
|
||||||
@ -97,7 +97,7 @@ class TestBigchainApi(object):
|
|||||||
|
|
||||||
def test_write_transaction(self, b, user_sk, user_pk, alice, create_tx):
|
def test_write_transaction(self, b, user_sk, user_pk, alice, create_tx):
|
||||||
|
|
||||||
asset1 = {"msg": "Planetmint 1"}
|
asset1 = {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}
|
||||||
|
|
||||||
tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset1).sign([alice.private_key])
|
tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset1).sign([alice.private_key])
|
||||||
b.store_bulk_transactions([tx])
|
b.store_bulk_transactions([tx])
|
||||||
@ -377,7 +377,7 @@ class TestMultipleInputs(object):
|
|||||||
|
|
||||||
transactions = []
|
transactions = []
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
payload = {"somedata": i}
|
payload = f"QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L{i}" # create unique CIDs
|
||||||
tx = Create.generate([alice.public_key], [([user_pk, user2_pk], 1)], payload)
|
tx = Create.generate([alice.public_key], [([user_pk, user2_pk], 1)], payload)
|
||||||
tx = tx.sign([alice.private_key])
|
tx = tx.sign([alice.private_key])
|
||||||
transactions.append(tx)
|
transactions.append(tx)
|
||||||
@ -472,12 +472,15 @@ def test_transaction_unicode(b, alice):
|
|||||||
from planetmint.transactions.common.utils import serialize
|
from planetmint.transactions.common.utils import serialize
|
||||||
|
|
||||||
# http://www.fileformat.info/info/unicode/char/1f37a/index.htm
|
# http://www.fileformat.info/info/unicode/char/1f37a/index.htm
|
||||||
beer_python = {"beer": "\N{BEER MUG}"}
|
|
||||||
beer_json = '{"beer":"\N{BEER MUG}"}'
|
|
||||||
|
|
||||||
tx = (Create.generate([alice.public_key], [([alice.public_key], 100)], beer_python)).sign([alice.private_key])
|
beer_python = {"data": multihash(marshal({"beer": "\N{BEER MUG}"}))}
|
||||||
|
beer_json = {"data": multihash(marshal({"beer": "\N{BEER MUG}"}))}
|
||||||
|
|
||||||
|
tx = (Create.generate([alice.public_key], [([alice.public_key], 100)], asset=beer_python)).sign(
|
||||||
|
[alice.private_key]
|
||||||
|
)
|
||||||
|
|
||||||
tx_1 = copy.deepcopy(tx)
|
tx_1 = copy.deepcopy(tx)
|
||||||
b.store_bulk_transactions([tx])
|
b.store_bulk_transactions([tx])
|
||||||
|
|
||||||
assert beer_json in serialize(tx_1.to_dict())
|
assert beer_json["data"] in serialize(tx_1.to_dict())
|
||||||
|
@ -299,7 +299,7 @@ def test_deliver_transfer_tx__double_spend_fails(b, init_chain_request):
|
|||||||
bob = generate_key_pair()
|
bob = generate_key_pair()
|
||||||
carly = generate_key_pair()
|
carly = generate_key_pair()
|
||||||
|
|
||||||
asset = {"msg": "live long and prosper"}
|
asset = {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}
|
||||||
|
|
||||||
tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset).sign([alice.private_key])
|
tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset).sign([alice.private_key])
|
||||||
|
|
||||||
@ -355,9 +355,9 @@ def test_store_pre_commit_state_in_end_block(b, alice, init_chain_request):
|
|||||||
from planetmint import App
|
from planetmint import App
|
||||||
from planetmint.backend import query
|
from planetmint.backend import query
|
||||||
|
|
||||||
tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset={"msg": "live long and prosper"}).sign(
|
tx = Create.generate(
|
||||||
[alice.private_key]
|
[alice.public_key], [([alice.public_key], 1)], asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}
|
||||||
)
|
).sign([alice.private_key])
|
||||||
|
|
||||||
app = App(b)
|
app = App(b)
|
||||||
app.init_chain(init_chain_request)
|
app.init_chain(init_chain_request)
|
||||||
|
@ -25,6 +25,7 @@ from planetmint.transactions.common.transaction_mode_types import (
|
|||||||
BROADCAST_TX_SYNC,
|
BROADCAST_TX_SYNC,
|
||||||
)
|
)
|
||||||
from planetmint.lib import Block
|
from planetmint.lib import Block
|
||||||
|
from ipld import marshal, multihash
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.bdb
|
@pytest.mark.bdb
|
||||||
@ -40,15 +41,21 @@ def test_asset_is_separated_from_transaciton(b):
|
|||||||
bob = generate_key_pair()
|
bob = generate_key_pair()
|
||||||
|
|
||||||
asset = {
|
asset = {
|
||||||
"Never gonna": [
|
"data": multihash(
|
||||||
"give you up",
|
marshal(
|
||||||
"let you down",
|
{
|
||||||
"run around" "desert you",
|
"Never gonna": [
|
||||||
"make you cry",
|
"give you up",
|
||||||
"say goodbye",
|
"let you down",
|
||||||
"tell a lie",
|
"run around" "desert you",
|
||||||
"hurt you",
|
"make you cry",
|
||||||
]
|
"say goodbye",
|
||||||
|
"tell a lie",
|
||||||
|
"hurt you",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
tx = Create.generate([alice.public_key], [([bob.public_key], 1)], metadata=None, asset=asset).sign(
|
tx = Create.generate([alice.public_key], [([bob.public_key], 1)], metadata=None, asset=asset).sign(
|
||||||
@ -404,7 +411,7 @@ def test_get_spent_transaction_critical_double_spend(b, alice, bob, carol):
|
|||||||
from planetmint.exceptions import CriticalDoubleSpend
|
from planetmint.exceptions import CriticalDoubleSpend
|
||||||
from planetmint.transactions.common.exceptions import DoubleSpend
|
from planetmint.transactions.common.exceptions import DoubleSpend
|
||||||
|
|
||||||
asset = {"test": "asset"}
|
asset = {"data": multihash(marshal({"test": "asset"}))}
|
||||||
|
|
||||||
tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset).sign([alice.private_key])
|
tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset).sign([alice.private_key])
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ from unittest.mock import MagicMock
|
|||||||
from planetmint.transactions.common.exceptions import AmountError, SchemaValidationError, ThresholdTooDeep
|
from planetmint.transactions.common.exceptions import AmountError, SchemaValidationError, ThresholdTooDeep
|
||||||
from planetmint.transactions.common.transaction import Transaction
|
from planetmint.transactions.common.transaction import Transaction
|
||||||
from planetmint.transactions.common.utils import _fulfillment_to_details, _fulfillment_from_details
|
from planetmint.transactions.common.utils import _fulfillment_to_details, _fulfillment_from_details
|
||||||
|
from ipld import marshal, multihash
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Helper functions
|
# Helper functions
|
||||||
@ -85,7 +86,7 @@ def test_validate_invalid_operation(b, create_tx, alice):
|
|||||||
|
|
||||||
|
|
||||||
def test_validate_fails_metadata_empty_dict(b, create_tx, alice):
|
def test_validate_fails_metadata_empty_dict(b, create_tx, alice):
|
||||||
create_tx.metadata = {"a": 1}
|
create_tx.metadata = multihash(marshal({"a": 1}))
|
||||||
signed_tx = create_tx.sign([alice.private_key])
|
signed_tx = create_tx.sign([alice.private_key])
|
||||||
validate(signed_tx)
|
validate(signed_tx)
|
||||||
|
|
||||||
@ -129,9 +130,10 @@ def test_create_tx_no_asset_id(b, create_tx, alice):
|
|||||||
|
|
||||||
|
|
||||||
def test_create_tx_asset_type(b, create_tx, alice):
|
def test_create_tx_asset_type(b, create_tx, alice):
|
||||||
create_tx.asset["data"] = "a"
|
create_tx.asset["data"] = multihash(marshal({"a": ""}))
|
||||||
signed_tx = create_tx.sign([alice.private_key])
|
signed_tx = create_tx.sign([alice.private_key])
|
||||||
validate_raises(signed_tx)
|
validate(signed_tx)
|
||||||
|
# validate_raises(signed_tx)
|
||||||
|
|
||||||
|
|
||||||
def test_create_tx_no_asset_data(b, create_tx, alice):
|
def test_create_tx_no_asset_data(b, create_tx, alice):
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from planetmint.transactions.types.assets.create import Create
|
from planetmint.transactions.types.assets.create import Create
|
||||||
|
from ipld import marshal, multihash
|
||||||
|
|
||||||
ASSETS_ENDPOINT = "/api/v1/assets/"
|
ASSETS_ENDPOINT = "/api/v1/assets/"
|
||||||
|
|
||||||
@ -29,24 +30,24 @@ def test_get_assets_tendermint(client, b, alice):
|
|||||||
assert res.status_code == 200
|
assert res.status_code == 200
|
||||||
|
|
||||||
# create asset
|
# create asset
|
||||||
asset = {"msg": "abc"}
|
asset = {"data": multihash(marshal({"msg": "abc"}))}
|
||||||
tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset).sign([alice.private_key])
|
tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset).sign([alice.private_key])
|
||||||
|
|
||||||
b.store_bulk_transactions([tx])
|
b.store_bulk_transactions([tx])
|
||||||
|
|
||||||
# test that asset is returned
|
# test that asset is returned
|
||||||
res = client.get(ASSETS_ENDPOINT + "?search=abc")
|
res = client.get(ASSETS_ENDPOINT + "?search=" + asset["data"])
|
||||||
assert res.status_code == 200
|
assert res.status_code == 200
|
||||||
assert len(res.json) == 1
|
assert len(res.json) == 1
|
||||||
assert res.json[0] == {"data": {"msg": "abc"}, "id": tx.id}
|
assert res.json[0] == {"data": asset["data"], "id": tx.id}
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.bdb
|
@pytest.mark.bdb
|
||||||
def test_get_assets_limit_tendermint(client, b, alice):
|
def test_get_assets_limit_tendermint(client, b, alice):
|
||||||
|
|
||||||
# create two assets
|
# create two assets
|
||||||
asset1 = {"msg": "abc 1"}
|
asset1 = {"data": multihash(marshal({"msg": "abc 1"}))}
|
||||||
asset2 = {"msg": "abc 2"}
|
asset2 = {"data": multihash(marshal({"msg": "abc 2"}))}
|
||||||
tx1 = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset1).sign([alice.private_key])
|
tx1 = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset1).sign([alice.private_key])
|
||||||
tx2 = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset2).sign([alice.private_key])
|
tx2 = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset2).sign([alice.private_key])
|
||||||
|
|
||||||
@ -54,11 +55,11 @@ def test_get_assets_limit_tendermint(client, b, alice):
|
|||||||
b.store_bulk_transactions([tx2])
|
b.store_bulk_transactions([tx2])
|
||||||
|
|
||||||
# test that both assets are returned without limit
|
# test that both assets are returned without limit
|
||||||
res = client.get(ASSETS_ENDPOINT + "?search=abc")
|
res = client.get(ASSETS_ENDPOINT + "?search=" + asset1["data"])
|
||||||
assert res.status_code == 200
|
assert res.status_code == 200
|
||||||
assert len(res.json) == 2
|
assert len(res.json) == 1
|
||||||
|
|
||||||
# test that only one asset is returned when using limit=1
|
# test that only one asset is returned when using limit=1
|
||||||
res = client.get(ASSETS_ENDPOINT + "?search=abc&limit=1")
|
res = client.get(ASSETS_ENDPOINT + "?search=" + asset1["data"] + "&limit=1")
|
||||||
assert res.status_code == 200
|
assert res.status_code == 200
|
||||||
assert len(res.json) == 1
|
assert len(res.json) == 1
|
||||||
|
@ -7,6 +7,7 @@ import pytest
|
|||||||
|
|
||||||
from planetmint.transactions.types.assets.create import Create
|
from planetmint.transactions.types.assets.create import Create
|
||||||
from planetmint.lib import Block
|
from planetmint.lib import Block
|
||||||
|
from ipld import marshal, multihash
|
||||||
|
|
||||||
BLOCKS_ENDPOINT = "/api/v1/blocks/"
|
BLOCKS_ENDPOINT = "/api/v1/blocks/"
|
||||||
|
|
||||||
@ -16,7 +17,9 @@ BLOCKS_ENDPOINT = "/api/v1/blocks/"
|
|||||||
def test_get_block_endpoint(b, client, alice):
|
def test_get_block_endpoint(b, client, alice):
|
||||||
import copy
|
import copy
|
||||||
|
|
||||||
tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset={"cycle": "hero"})
|
tx = Create.generate(
|
||||||
|
[alice.public_key], [([alice.public_key], 1)], asset={"data": multihash(marshal({"cycle": "hero"}))}
|
||||||
|
)
|
||||||
tx = tx.sign([alice.private_key])
|
tx = tx.sign([alice.private_key])
|
||||||
|
|
||||||
# with store_bulk_transactions we use `insert_many` where PyMongo
|
# with store_bulk_transactions we use `insert_many` where PyMongo
|
||||||
@ -47,7 +50,9 @@ def test_get_block_returns_404_if_not_found(client):
|
|||||||
|
|
||||||
@pytest.mark.bdb
|
@pytest.mark.bdb
|
||||||
def test_get_block_containing_transaction(b, client, alice):
|
def test_get_block_containing_transaction(b, client, alice):
|
||||||
tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset={"cycle": "hero"})
|
tx = Create.generate(
|
||||||
|
[alice.public_key], [([alice.public_key], 1)], asset={"data": multihash(marshal({"cycle": "hero"}))}
|
||||||
|
)
|
||||||
tx = tx.sign([alice.private_key])
|
tx = tx.sign([alice.private_key])
|
||||||
b.store_bulk_transactions([tx])
|
b.store_bulk_transactions([tx])
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from planetmint.transactions.types.assets.create import Create
|
from planetmint.transactions.types.assets.create import Create
|
||||||
|
from ipld import marshal, multihash
|
||||||
|
|
||||||
METADATA_ENDPOINT = "/api/v1/metadata/"
|
METADATA_ENDPOINT = "/api/v1/metadata/"
|
||||||
|
|
||||||
@ -22,15 +23,15 @@ def test_get_metadata_with_missing_text_search(client):
|
|||||||
|
|
||||||
@pytest.mark.bdb
|
@pytest.mark.bdb
|
||||||
def test_get_metadata_tendermint(client, b, alice):
|
def test_get_metadata_tendermint(client, b, alice):
|
||||||
|
asset = {"data": multihash(marshal({"msg": "abc"}))}
|
||||||
# test returns empty list when no assets are found
|
# test returns empty list when no assets are found
|
||||||
res = client.get(METADATA_ENDPOINT + "?search=abc")
|
res = client.get(METADATA_ENDPOINT + "?search=" + asset["data"])
|
||||||
assert res.json == []
|
assert res.json == []
|
||||||
assert res.status_code == 200
|
assert res.status_code == 200
|
||||||
|
|
||||||
# create asset
|
# create asset
|
||||||
asset = {"msg": "abc"}
|
# asset #= {"msg": "abc"}
|
||||||
metadata = {"key": "my_meta"}
|
metadata = multihash(marshal({"key": "my_meta"}))
|
||||||
tx = Create.generate([alice.public_key], [([alice.public_key], 1)], metadata=metadata, asset=asset).sign(
|
tx = Create.generate([alice.public_key], [([alice.public_key], 1)], metadata=metadata, asset=asset).sign(
|
||||||
[alice.private_key]
|
[alice.private_key]
|
||||||
)
|
)
|
||||||
@ -38,36 +39,36 @@ def test_get_metadata_tendermint(client, b, alice):
|
|||||||
b.store_bulk_transactions([tx])
|
b.store_bulk_transactions([tx])
|
||||||
|
|
||||||
# test that metadata is returned
|
# test that metadata is returned
|
||||||
res = client.get(METADATA_ENDPOINT + "?search=my_meta")
|
res = client.get(METADATA_ENDPOINT + "?search=" + metadata)
|
||||||
assert res.status_code == 200
|
assert res.status_code == 200
|
||||||
assert len(res.json) == 1
|
assert len(res.json) == 1
|
||||||
assert res.json[0] == {"metadata": {"key": "my_meta"}, "id": tx.id}
|
assert res.json[0] == {"metadata": metadata, "id": tx.id}
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.bdb
|
@pytest.mark.bdb
|
||||||
def test_get_metadata_limit_tendermint(client, b, alice):
|
def test_get_metadata_limit_tendermint(client, b, alice):
|
||||||
|
|
||||||
# create two assets
|
# create two assets
|
||||||
asset1 = {"msg": "abc 1"}
|
asset1 = {"data": multihash(marshal({"msg": "abc 1"}))}
|
||||||
meta1 = {"key": "meta 1"}
|
meta1 = multihash(marshal({"key": "meta 1"}))
|
||||||
tx1 = Create.generate([alice.public_key], [([alice.public_key], 1)], metadata=meta1, asset=asset1).sign(
|
tx1 = Create.generate([alice.public_key], [([alice.public_key], 1)], metadata=meta1, asset=asset1).sign(
|
||||||
[alice.private_key]
|
[alice.private_key]
|
||||||
)
|
)
|
||||||
b.store_bulk_transactions([tx1])
|
b.store_bulk_transactions([tx1])
|
||||||
|
|
||||||
asset2 = {"msg": "abc 2"}
|
asset2 = {"data": multihash(marshal({"msg": "abc 2"}))}
|
||||||
meta2 = {"key": "meta 2"}
|
meta2 = multihash(marshal({"key": "meta 2"}))
|
||||||
tx2 = Create.generate([alice.public_key], [([alice.public_key], 1)], metadata=meta2, asset=asset2).sign(
|
tx2 = Create.generate([alice.public_key], [([alice.public_key], 1)], metadata=meta2, asset=asset2).sign(
|
||||||
[alice.private_key]
|
[alice.private_key]
|
||||||
)
|
)
|
||||||
b.store_bulk_transactions([tx2])
|
b.store_bulk_transactions([tx2])
|
||||||
|
|
||||||
# test that both assets are returned without limit
|
# test that both assets are returned without limit
|
||||||
res = client.get(METADATA_ENDPOINT + "?search=meta")
|
res = client.get(METADATA_ENDPOINT + "?search=" + meta1)
|
||||||
assert res.status_code == 200
|
assert res.status_code == 200
|
||||||
assert len(res.json) == 2
|
assert len(res.json) == 1
|
||||||
|
|
||||||
# test that only one asset is returned when using limit=1
|
# test that only one asset is returned when using limit=1
|
||||||
res = client.get(METADATA_ENDPOINT + "?search=meta&limit=1")
|
res = client.get(METADATA_ENDPOINT + "?search=" + meta2 + "&limit=1")
|
||||||
assert res.status_code == 200
|
assert res.status_code == 200
|
||||||
assert len(res.json) == 1
|
assert len(res.json) == 1
|
||||||
|
@ -9,6 +9,7 @@ from unittest.mock import Mock, patch
|
|||||||
import base58
|
import base58
|
||||||
import pytest
|
import pytest
|
||||||
from cryptoconditions import Ed25519Sha256
|
from cryptoconditions import Ed25519Sha256
|
||||||
|
from ipld import multihash, marshal
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from hashlib import sha3_256
|
from hashlib import sha3_256
|
||||||
@ -108,7 +109,7 @@ def test_post_create_transaction_with_language(b, client, nested, language, expe
|
|||||||
asset = {"root": lang_obj}
|
asset = {"root": lang_obj}
|
||||||
else:
|
else:
|
||||||
asset = lang_obj
|
asset = lang_obj
|
||||||
|
asset = {"data": multihash(marshal(asset))}
|
||||||
tx = Create.generate([user_pub], [([user_pub], 1)], asset=asset)
|
tx = Create.generate([user_pub], [([user_pub], 1)], asset=asset)
|
||||||
tx = tx.sign([user_priv])
|
tx = tx.sign([user_priv])
|
||||||
res = client.post(TX_ENDPOINT, data=json.dumps(tx.to_dict()))
|
res = client.post(TX_ENDPOINT, data=json.dumps(tx.to_dict()))
|
||||||
@ -368,7 +369,9 @@ def test_post_wrong_asset_division_transfer_returns_400(b, client, user_pk):
|
|||||||
|
|
||||||
priv_key, pub_key = crypto.generate_key_pair()
|
priv_key, pub_key = crypto.generate_key_pair()
|
||||||
|
|
||||||
create_tx = Create.generate([pub_key], [([pub_key], 10)], asset={"test": "asset"}).sign([priv_key])
|
create_tx = Create.generate(
|
||||||
|
[pub_key], [([pub_key], 10)], asset={"data": multihash(marshal({"test": "asset"}))}
|
||||||
|
).sign([priv_key])
|
||||||
res = client.post(TX_ENDPOINT + "?mode=commit", data=json.dumps(create_tx.to_dict()))
|
res = client.post(TX_ENDPOINT + "?mode=commit", data=json.dumps(create_tx.to_dict()))
|
||||||
assert res.status_code == 202
|
assert res.status_code == 202
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import threading
|
|||||||
# from unittest.mock import patch
|
# from unittest.mock import patch
|
||||||
from planetmint.transactions.types.assets.create import Create
|
from planetmint.transactions.types.assets.create import Create
|
||||||
from planetmint.transactions.types.assets.transfer import Transfer
|
from planetmint.transactions.types.assets.transfer import Transfer
|
||||||
|
from ipld import multihash, marshal
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@ -263,7 +264,7 @@ def test_integration_from_webapi_to_websocket(monkeypatch, client, loop):
|
|||||||
|
|
||||||
# Create a keypair and generate a new asset
|
# Create a keypair and generate a new asset
|
||||||
user_priv, user_pub = crypto.generate_key_pair()
|
user_priv, user_pub = crypto.generate_key_pair()
|
||||||
asset = {"random": random.random()}
|
asset = {"data": multihash(marshal({"random": random.random()}))}
|
||||||
tx = Create.generate([user_pub], [([user_pub], 1)], asset=asset)
|
tx = Create.generate([user_pub], [([user_pub], 1)], asset=asset)
|
||||||
tx = tx.sign([user_priv])
|
tx = tx.sign([user_priv])
|
||||||
# Post the transaction to the Planetmint Web API
|
# Post the transaction to the Planetmint Web API
|
||||||
|
Loading…
x
Reference in New Issue
Block a user