mirror of
https://github.com/planetmint/planetmint.git
synced 2025-03-30 15:08:31 +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:
|
||||
test:
|
||||
if: ${{ false }
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
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:
|
||||
test:
|
||||
if: ${{ false }
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
@ -27,6 +27,15 @@ For reference, the possible headings are:
|
||||
|
||||
## [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
|
||||
* **Changed** adjusted to zenroom calling convention of PRP #13 (breaking change)
|
||||
* **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
|
||||
@$(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
|
||||
@$(DC) run --rm --no-deps planetmint pytest -f
|
||||
|
@ -17,3 +17,4 @@ RUN pip install --upgrade \
|
||||
planetmint-driver>=0.9.2 \
|
||||
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 planetmint-ipld>=0.0.3
|
||||
|
@ -23,6 +23,7 @@ import os
|
||||
# For this test case we import and use the Python Driver.
|
||||
from planetmint_driver import Planetmint
|
||||
from planetmint_driver.crypto import generate_keypair
|
||||
from ipld import multihash, marshal
|
||||
|
||||
|
||||
def test_get_tests():
|
||||
@ -41,7 +42,7 @@ def test_get_tests():
|
||||
# ## Alice registers her bike in Planetmint
|
||||
# Alice has a nice bike, and here she creates the "digital twin"
|
||||
# of her bike.
|
||||
bike = {"data": {"bicycle": {"serial_number": 420420}}}
|
||||
bike = {"data": multihash(marshal({"bicycle": {"serial_number": 420420}}))}
|
||||
|
||||
# She prepares a `CREATE` transaction...
|
||||
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.
|
||||
from planetmint_driver import Planetmint
|
||||
from planetmint_driver.crypto import generate_keypair
|
||||
from ipld import multihash, marshal
|
||||
|
||||
|
||||
def test_basic():
|
||||
@ -41,7 +42,7 @@ def test_basic():
|
||||
# ## Alice registers her bike in Planetmint
|
||||
# Alice has a nice bike, and here she creates the "digital twin"
|
||||
# of her bike.
|
||||
bike = {"data": {"bicycle": {"serial_number": 420420}}}
|
||||
bike = {"data": multihash(marshal({"bicycle": {"serial_number": 420420}}))}
|
||||
|
||||
# She prepares a `CREATE` transaction...
|
||||
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.
|
||||
from planetmint_driver import Planetmint
|
||||
from planetmint_driver.crypto import generate_keypair
|
||||
from ipld import multihash, marshal
|
||||
|
||||
|
||||
def test_divisible_assets():
|
||||
@ -48,10 +49,14 @@ def test_divisible_assets():
|
||||
# the bike for one hour.
|
||||
|
||||
bike_token = {
|
||||
"data": {
|
||||
"token_for": {"bike": {"serial_number": 420420}},
|
||||
"description": "Time share token. Each token equals one hour of riding.",
|
||||
},
|
||||
"data": multihash(
|
||||
marshal(
|
||||
{
|
||||
"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.
|
||||
|
@ -14,6 +14,7 @@ import queue
|
||||
import planetmint_driver.exceptions
|
||||
from planetmint_driver import Planetmint
|
||||
from planetmint_driver.crypto import generate_keypair
|
||||
from ipld import multihash, marshal
|
||||
|
||||
|
||||
def test_double_create():
|
||||
@ -23,7 +24,9 @@ def test_double_create():
|
||||
results = queue.Queue()
|
||||
|
||||
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,
|
||||
)
|
||||
|
||||
|
@ -25,6 +25,7 @@ import os
|
||||
# For this test case we import and use the Python Driver.
|
||||
from planetmint_driver import Planetmint
|
||||
from planetmint_driver.crypto import generate_keypair
|
||||
from ipld import multihash, marshal
|
||||
|
||||
|
||||
def test_multiple_owners():
|
||||
@ -41,7 +42,7 @@ def test_multiple_owners():
|
||||
# high rents anymore. Bob suggests to get a dish washer for the
|
||||
# kitchen. Alice agrees and here they go, creating the asset for their
|
||||
# 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
|
||||
# Bob and Alice need to be the recipients.
|
||||
|
@ -29,6 +29,7 @@ import pytest
|
||||
from planetmint_driver import Planetmint
|
||||
from planetmint_driver.crypto import generate_keypair
|
||||
from planetmint_driver.exceptions import BadRequest
|
||||
from ipld import multihash, marshal
|
||||
|
||||
naughty_strings = blns.all()
|
||||
skipped_naughty_strings = [
|
||||
@ -118,8 +119,8 @@ def send_naughty_tx(asset, metadata):
|
||||
@pytest.mark.parametrize("naughty_string", naughty_strings, ids=naughty_strings)
|
||||
def test_naughty_keys(naughty_string):
|
||||
|
||||
asset = {"data": {naughty_string: "nice_value"}}
|
||||
metadata = {naughty_string: "nice_value"}
|
||||
asset = {"data": multihash(marshal({naughty_string: "nice_value"}))}
|
||||
metadata = multihash(marshal({naughty_string: "nice_value"}))
|
||||
|
||||
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)
|
||||
def test_naughty_values(naughty_string):
|
||||
|
||||
asset = {"data": {"nice_key": naughty_string}}
|
||||
metadata = {"nice_key": naughty_string}
|
||||
asset = {"data": multihash(marshal({"nice_key": naughty_string}))}
|
||||
metadata = multihash(marshal({"nice_key": naughty_string}))
|
||||
|
||||
send_naughty_tx(asset, metadata)
|
||||
|
@ -21,6 +21,7 @@ import queue
|
||||
import json
|
||||
from threading import Thread, Event
|
||||
from uuid import uuid4
|
||||
from ipld import multihash, marshal
|
||||
|
||||
# For this script, we need to set up a websocket connection, that's the reason
|
||||
# we import the
|
||||
@ -91,7 +92,9 @@ def test_stream():
|
||||
for _ in range(10):
|
||||
tx = bdb.transactions.fulfill(
|
||||
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,
|
||||
)
|
||||
|
@ -7,6 +7,7 @@ from cryptoconditions.types.zenroom import ZenroomSha256
|
||||
from zenroom import zencode_exec
|
||||
from planetmint_driver import Planetmint
|
||||
from planetmint_driver.crypto import generate_keypair
|
||||
from ipld import multihash, marshal
|
||||
|
||||
|
||||
def test_zenroom_signing(
|
||||
@ -66,8 +67,8 @@ def test_zenroom_signing(
|
||||
metadata = {"result": {"output": ["ok"]}}
|
||||
|
||||
script_ = {
|
||||
"code": {"type": "zenroom", "raw": "test_string", "parameters": [{"obj": "1"}, {"obj": "2"}]},
|
||||
"state": "dd8bbd234f9869cab4cc0b84aa660e9b5ef0664559b8375804ee8dce75b10576",
|
||||
"code": {"type": "zenroom", "raw": "test_string", "parameters": [{"obj": "1"}, {"obj": "2"}]}, # obsolete
|
||||
"state": "dd8bbd234f9869cab4cc0b84aa660e9b5ef0664559b8375804ee8dce75b10576", #
|
||||
"input": zenroom_script_input,
|
||||
"output": ["ok"],
|
||||
"policies": {},
|
||||
@ -75,9 +76,9 @@ def test_zenroom_signing(
|
||||
|
||||
token_creation_tx = {
|
||||
"operation": "CREATE",
|
||||
"asset": {"data": {"test": "my asset"}},
|
||||
"asset": {"data": multihash(marshal({"test": "my asset"}))},
|
||||
"metadata": multihash(marshal(metadata)),
|
||||
"script": script_,
|
||||
"metadata": metadata,
|
||||
"outputs": [
|
||||
output,
|
||||
],
|
||||
|
@ -15,6 +15,7 @@ from planetmint import lib
|
||||
from planetmint.transactions.types.assets.create import Create
|
||||
from planetmint.transactions.types.assets.transfer import Transfer
|
||||
from planetmint.web import server
|
||||
from ipld import multihash, marshal
|
||||
|
||||
|
||||
TPLS = {}
|
||||
@ -157,10 +158,12 @@ def main():
|
||||
ctx["api_index"] = pretty_json(json.loads(res.data.decode()))
|
||||
|
||||
# tx create
|
||||
from ipld import marshal, multihash
|
||||
|
||||
privkey = "CfdqtD7sS7FgkMoGPXw55MVGGFwQLAoHYTcBhZDtF99Z"
|
||||
pubkey = "4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD"
|
||||
asset = {"msg": "Hello Planetmint!"}
|
||||
tx = Create.generate([pubkey], [([pubkey], 1)], asset=asset, metadata={"sequence": 0})
|
||||
asset = {"data": multihash(marshal({"msg": "Hello Planetmint!"}))}
|
||||
tx = Create.generate([pubkey], [([pubkey], 1)], asset=asset, metadata=multihash(marshal({"sequence": 0})))
|
||||
tx = tx.sign([privkey])
|
||||
ctx["tx"] = pretty_json(tx.to_dict())
|
||||
ctx["public_keys"] = tx.outputs[0].public_keys[0]
|
||||
@ -176,7 +179,9 @@ def main():
|
||||
fulfills=TransactionLink(txid=tx.id, output=cid),
|
||||
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])
|
||||
ctx["tx_transfer"] = pretty_json(tx_transfer.to_dict())
|
||||
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,
|
||||
)
|
||||
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])
|
||||
ctx["tx_transfer_last"] = pretty_json(tx_transfer_last.to_dict())
|
||||
|
@ -14,7 +14,7 @@ register_query = module_dispatch_registrar(convert)
|
||||
|
||||
@register_query(LocalMongoDBConnection)
|
||||
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
|
||||
return asset
|
||||
|
||||
|
@ -15,7 +15,7 @@ register_query = module_dispatch_registrar(convert)
|
||||
@register_query(TarantoolDBConnection)
|
||||
def prepare_asset(connection, transaction_type, transaction_id, filter_operation, asset):
|
||||
asset_id = transaction_id
|
||||
if transaction_type != filter_operation:
|
||||
if transaction_type not in filter_operation:
|
||||
asset_id = asset["id"]
|
||||
return tuple([asset, transaction_id, asset_id])
|
||||
|
||||
|
@ -133,7 +133,7 @@ class Planetmint(object):
|
||||
self.connection,
|
||||
transaction_type=transaction["operation"],
|
||||
transaction_id=transaction["id"],
|
||||
filter_operation=t.CREATE,
|
||||
filter_operation=[t.CREATE, t.VALIDATOR_ELECTION, t.CHAIN_MIGRATION_ELECTION],
|
||||
asset=asset,
|
||||
)
|
||||
|
||||
|
@ -108,6 +108,8 @@ class ValidationWorker:
|
||||
asset_id = dict_transaction["asset"]["id"]
|
||||
except KeyError:
|
||||
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])
|
||||
|
||||
|
@ -69,16 +69,9 @@ definitions:
|
||||
- CHAIN_MIGRATION_ELECTION
|
||||
- VOTE
|
||||
asset:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
id:
|
||||
"$ref": "#/definitions/sha3_hexdigest"
|
||||
data:
|
||||
anyOf:
|
||||
- type: object
|
||||
additionalProperties: true
|
||||
- type: 'null'
|
||||
anyOf:
|
||||
- type: 'null'
|
||||
- type: object
|
||||
output:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
@ -135,9 +128,7 @@ definitions:
|
||||
- type: 'null'
|
||||
metadata:
|
||||
anyOf:
|
||||
- type: object
|
||||
additionalProperties: true
|
||||
minProperties: 1
|
||||
- type: string
|
||||
- type: 'null'
|
||||
condition_details:
|
||||
anyOf:
|
||||
|
@ -16,8 +16,7 @@ properties:
|
||||
properties:
|
||||
data:
|
||||
anyOf:
|
||||
- type: object
|
||||
additionalProperties: true
|
||||
- type: string
|
||||
- type: 'null'
|
||||
required:
|
||||
- data
|
||||
|
@ -73,16 +73,9 @@ definitions:
|
||||
- COMPOSE
|
||||
- DECOMPOSE
|
||||
asset:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
id:
|
||||
"$ref": "#/definitions/sha3_hexdigest"
|
||||
data:
|
||||
anyOf:
|
||||
- type: object
|
||||
additionalProperties: true
|
||||
- type: 'null'
|
||||
anyOf:
|
||||
- type: 'null'
|
||||
- type: object
|
||||
output:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
@ -139,9 +132,7 @@ definitions:
|
||||
- type: 'null'
|
||||
metadata:
|
||||
anyOf:
|
||||
- type: object
|
||||
additionalProperties: true
|
||||
minProperties: 1
|
||||
- type: string
|
||||
- type: 'null'
|
||||
condition_details:
|
||||
anyOf:
|
||||
|
@ -35,8 +35,7 @@ definitions:
|
||||
properties:
|
||||
data:
|
||||
anyOf:
|
||||
- type: object
|
||||
additionalProperties: true
|
||||
- type: string
|
||||
- type: 'null'
|
||||
required:
|
||||
- data
|
@ -57,6 +57,10 @@ UnspentOutput = namedtuple(
|
||||
),
|
||||
)
|
||||
|
||||
VALIDATOR_ELECTION = "VALIDATOR_ELECTION"
|
||||
CHAIN_MIGRATION_ELECTION = "CHAIN_MIGRATION_ELECTION"
|
||||
VOTE = "VOTE"
|
||||
|
||||
|
||||
class Transaction(object):
|
||||
"""A Transaction is used to create and transfer assets.
|
||||
@ -83,6 +87,9 @@ class Transaction(object):
|
||||
|
||||
CREATE = "CREATE"
|
||||
TRANSFER = "TRANSFER"
|
||||
VALIDATOR_ELECTION = VALIDATOR_ELECTION
|
||||
CHAIN_MIGRATION_ELECTION = CHAIN_MIGRATION_ELECTION
|
||||
VOTE = VOTE
|
||||
ALLOWED_OPERATIONS = (CREATE, TRANSFER)
|
||||
ASSET = "asset"
|
||||
METADATA = "metadata"
|
||||
@ -127,13 +134,25 @@ class Transaction(object):
|
||||
# Asset payloads for 'CREATE' operations must be None or
|
||||
# dicts holding a `data` property. Asset payloads for 'TRANSFER'
|
||||
# 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):
|
||||
raise TypeError(
|
||||
(
|
||||
"`asset` must be None or a dict holding a `data` "
|
||||
" property instance for '{}' Transactions".format(operation)
|
||||
if operation == self.CREATE and asset is not None:
|
||||
if not isinstance(asset, dict):
|
||||
raise TypeError(
|
||||
(
|
||||
"`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):
|
||||
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):
|
||||
raise TypeError("`inputs` must be a list instance or None")
|
||||
|
||||
if metadata is not None and not isinstance(metadata, dict):
|
||||
raise TypeError("`metadata` must be a dict or None")
|
||||
if metadata is not None and not isinstance(metadata, str):
|
||||
# Add CID validation
|
||||
raise TypeError("`metadata` must be a CID string or None")
|
||||
|
||||
if script is not None and not isinstance(script, dict):
|
||||
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])
|
||||
elif self.operation == self.TRANSFER:
|
||||
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:
|
||||
allowed_ops = ", ".join(self.__class__.ALLOWED_OPERATIONS)
|
||||
raise TypeError("`operation` must be one of {}".format(allowed_ops))
|
||||
@ -561,7 +585,7 @@ class Transaction(object):
|
||||
print(f"Exception ASN1EncodeError : {e}")
|
||||
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
|
||||
# output is always valid.
|
||||
output_valid = True
|
||||
@ -680,7 +704,9 @@ class Transaction(object):
|
||||
transactions = [transactions]
|
||||
|
||||
# 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
|
||||
if len(asset_ids) > 1:
|
||||
@ -887,3 +913,22 @@ class Transaction(object):
|
||||
raise InvalidSignature("Transaction signature is invalid.")
|
||||
|
||||
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")
|
||||
if len(recipients) == 0:
|
||||
raise ValueError("`recipients` list cannot be empty")
|
||||
if not (asset is None or isinstance(asset, dict)):
|
||||
raise TypeError("`asset` must be a dict or None")
|
||||
if not (metadata is None or isinstance(metadata, dict)):
|
||||
raise TypeError("`metadata` must be a dict or None")
|
||||
if not asset is None:
|
||||
if not isinstance(asset, dict):
|
||||
raise TypeError("`asset` must be a CID string 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 = []
|
||||
outputs = []
|
||||
cid.make_cid(asset["data"])
|
||||
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
|
||||
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)
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
def generate(cls, tx_signers, recipients, metadata=None, asset=None):
|
||||
@ -74,5 +66,6 @@ class Create(Transaction):
|
||||
:class:`~planetmint.common.transaction.Transaction`
|
||||
"""
|
||||
|
||||
(inputs, outputs) = cls.validate_create(tx_signers, recipients, asset, metadata)
|
||||
return cls(cls.OPERATION, {"data": asset}, inputs, outputs, metadata)
|
||||
Create.validate_create(tx_signers, recipients, asset, 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
|
||||
|
||||
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
|
||||
|
||||
|
||||
class ChainMigrationElection(Election):
|
||||
|
||||
OPERATION = "CHAIN_MIGRATION_ELECTION"
|
||||
CREATE = OPERATION
|
||||
OPERATION = CHAIN_MIGRATION_ELECTION
|
||||
# CREATE = OPERATION
|
||||
ALLOWED_OPERATIONS = (OPERATION,)
|
||||
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.transactions.common.crypto import public_key_from_ed25519_key
|
||||
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):
|
||||
@ -94,6 +94,25 @@ class Election(Transaction):
|
||||
# validators and their voting power in the network
|
||||
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=[]):
|
||||
"""Validate election transaction
|
||||
|
||||
@ -145,7 +164,8 @@ class Election(Transaction):
|
||||
uuid = uuid4()
|
||||
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)
|
||||
cls.validate_schema(election.to_dict())
|
||||
return election
|
||||
@ -156,7 +176,6 @@ class Election(Transaction):
|
||||
`CREATE` transaction should be inherited
|
||||
"""
|
||||
_validate_schema(TX_SCHEMA_COMMON, tx)
|
||||
_validate_schema(TX_SCHEMA_CREATE, tx)
|
||||
if cls.TX_SCHEMA_CUSTOM:
|
||||
_validate_schema(cls.TX_SCHEMA_CUSTOM, tx)
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
from planetmint.transactions.types.assets.create import Create
|
||||
from planetmint.transactions.types.assets.transfer import Transfer
|
||||
from planetmint.transactions.common.transaction import VOTE
|
||||
from planetmint.transactions.common.schema import (
|
||||
_validate_schema,
|
||||
TX_SCHEMA_COMMON,
|
||||
@ -15,7 +16,7 @@ from planetmint.transactions.common.schema import (
|
||||
|
||||
class Vote(Transfer):
|
||||
|
||||
OPERATION = "VOTE"
|
||||
OPERATION = VOTE
|
||||
# NOTE: This class inherits TRANSFER txn type. The `TRANSFER` property is
|
||||
# overriden to re-use methods from parent class
|
||||
TRANSFER = OPERATION
|
||||
|
@ -6,15 +6,16 @@
|
||||
from planetmint.transactions.common.exceptions import InvalidPowerChange
|
||||
from planetmint.transactions.types.elections.election import 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
|
||||
|
||||
|
||||
class ValidatorElection(Election):
|
||||
|
||||
OPERATION = "VALIDATOR_ELECTION"
|
||||
# NOTE: this transaction class extends create so the operation inheritence is achieved
|
||||
# by renaming CREATE to VALIDATOR_ELECTION
|
||||
CREATE = OPERATION
|
||||
OPERATION = VALIDATOR_ELECTION
|
||||
ALLOWED_OPERATIONS = (OPERATION,)
|
||||
TX_SCHEMA_CUSTOM = TX_SCHEMA_VALIDATOR_ELECTION
|
||||
|
||||
|
@ -3,8 +3,8 @@
|
||||
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
|
||||
# Code is Apache-2.0 and docs are CC-BY-4.0
|
||||
|
||||
__version__ = "1.1.1"
|
||||
__short_version__ = "1.1"
|
||||
__version__ = "1.2.0"
|
||||
__short_version__ = "1.2"
|
||||
|
||||
# Supported Tendermint versions
|
||||
__tm_supported_versions__ = ["0.34.15"]
|
||||
|
9
setup.py
9
setup.py
@ -51,7 +51,7 @@ docs_require = [
|
||||
"charset-normalizer==2.0.12",
|
||||
"commonmark==0.9.1",
|
||||
"docutils==0.17.1",
|
||||
"idna",
|
||||
"idna==2.10", # version conflict with requests lib (required version <3)
|
||||
"imagesize==1.3.0",
|
||||
"importlib-metadata==4.11.3",
|
||||
"Jinja2==3.0.0",
|
||||
@ -129,6 +129,13 @@ install_requires = [
|
||||
"werkzeug==2.0.3",
|
||||
"nest-asyncio==1.5.5",
|
||||
"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(
|
||||
|
@ -51,9 +51,13 @@ def test_asset_id_mismatch(alice, user_pk):
|
||||
from planetmint.transactions.common.transaction import Transaction
|
||||
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])
|
||||
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])
|
||||
|
||||
with pytest.raises(AssetIdMismatch):
|
||||
|
@ -19,7 +19,9 @@ from planetmint.transactions.common.exceptions import DoubleSpend
|
||||
# Single owners_after
|
||||
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])
|
||||
|
||||
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
|
||||
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])
|
||||
|
||||
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
|
||||
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])
|
||||
|
||||
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):
|
||||
|
||||
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])
|
||||
|
||||
@ -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):
|
||||
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])
|
||||
assert tx_signed.validate(b) == tx_signed
|
||||
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):
|
||||
|
||||
# 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])
|
||||
|
||||
# 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):
|
||||
|
||||
# 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])
|
||||
|
||||
# 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):
|
||||
|
||||
# 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])
|
||||
|
||||
# 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):
|
||||
|
||||
# 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])
|
||||
|
||||
# TRANSFER
|
||||
@ -240,7 +264,9 @@ def test_single_in_multiple_own_single_out_single_own_transfer(alice, b, user_pk
|
||||
|
||||
# CREATE divisible asset
|
||||
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])
|
||||
|
||||
@ -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):
|
||||
# CREATE divisible asset
|
||||
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])
|
||||
|
||||
@ -304,7 +332,7 @@ def test_multiple_in_multiple_own_single_out_single_own_transfer(alice, b, user_
|
||||
tx_create = Create.generate(
|
||||
[alice.public_key],
|
||||
[([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])
|
||||
|
||||
@ -342,7 +370,9 @@ def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(alice, b, user_pk
|
||||
|
||||
# CREATE divisible asset
|
||||
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])
|
||||
|
||||
@ -379,7 +409,9 @@ def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(alice, b, user_pk, u
|
||||
|
||||
# CREATE divisible asset
|
||||
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])
|
||||
# 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
|
||||
# 50 shares to `user_pk`
|
||||
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])
|
||||
|
||||
@ -462,7 +496,9 @@ def test_amount_error_transfer(alice, b, user_pk, user_sk):
|
||||
from planetmint.transactions.common.exceptions import AmountError
|
||||
|
||||
# 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])
|
||||
|
||||
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.
|
||||
|
||||
# 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])
|
||||
|
||||
# TRANSFER
|
||||
@ -512,7 +552,9 @@ def test_sum_amount(alice, b, user_pk, user_sk):
|
||||
|
||||
# CREATE divisible asset with 3 outputs with amount 1
|
||||
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])
|
||||
|
||||
@ -535,7 +577,9 @@ def test_sum_amount(alice, b, user_pk, user_sk):
|
||||
def test_divide(alice, b, user_pk, user_sk):
|
||||
|
||||
# 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])
|
||||
|
||||
# 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.zenroom import ZenroomSha256
|
||||
from planetmint.transactions.common.crypto import generate_key_pair
|
||||
from ipld import multihash, marshal
|
||||
|
||||
CONDITION_SCRIPT = """Scenario 'ecdh': create the signature of an object
|
||||
Given I have the 'keyring'
|
||||
@ -101,8 +102,8 @@ def test_zenroom_signing():
|
||||
metadata = {"result": {"output": ["ok"]}}
|
||||
token_creation_tx = {
|
||||
"operation": "CREATE",
|
||||
"asset": {"data": {"test": "my asset"}},
|
||||
"metadata": metadata,
|
||||
"asset": {"data": multihash(marshal({"test": "my asset"}))},
|
||||
"metadata": multihash(marshal(metadata)),
|
||||
"script": script_,
|
||||
"outputs": [
|
||||
output,
|
||||
@ -171,9 +172,6 @@ def test_zenroom_signing():
|
||||
except ValidationError as e:
|
||||
print("Invalid transaction ({}): {}".format(type(e).__name__, e))
|
||||
assert ()
|
||||
except e:
|
||||
print(f"Exception : {e}")
|
||||
assert ()
|
||||
|
||||
print(f"VALIDATED : {tx_obj}")
|
||||
assert (tx_obj == False) is False
|
||||
|
@ -89,7 +89,7 @@ def test_bigchain_show_config(capsys):
|
||||
print(f"config : {sorted_output_config}")
|
||||
# Note: This test passed previously because we were always
|
||||
# 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
|
||||
# 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
|
||||
@ -268,10 +268,16 @@ def test_run_recover(b, alice, bob):
|
||||
from planetmint.backend import query
|
||||
|
||||
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])
|
||||
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])
|
||||
print(tx1.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"
|
||||
|
||||
ASSET_DEFINITION = {"data": {"definition": "Asset definition"}}
|
||||
ASSET_DEFINITION = {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}
|
||||
|
||||
DATA = {"msg": "Hello Planetmint!"}
|
||||
DATA = "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@ -189,11 +189,7 @@ def dummy_transaction():
|
||||
@pytest.fixture
|
||||
def unfulfilled_transaction():
|
||||
return {
|
||||
"asset": {
|
||||
"data": {
|
||||
"msg": "Hello Planetmint!",
|
||||
}
|
||||
},
|
||||
"asset": {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||
"id": None,
|
||||
"inputs": [
|
||||
{
|
||||
@ -229,11 +225,7 @@ def unfulfilled_transaction():
|
||||
@pytest.fixture
|
||||
def fulfilled_transaction():
|
||||
return {
|
||||
"asset": {
|
||||
"data": {
|
||||
"msg": "Hello Planetmint!",
|
||||
}
|
||||
},
|
||||
"asset": {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||
"id": None,
|
||||
"inputs": [
|
||||
{
|
||||
@ -292,11 +284,7 @@ def fulfilled_transaction():
|
||||
)
|
||||
def tri_state_transaction(request):
|
||||
tx = {
|
||||
"asset": {
|
||||
"data": {
|
||||
"msg": "Hello Planetmint!",
|
||||
}
|
||||
},
|
||||
"asset": {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||
"id": None,
|
||||
"inputs": [
|
||||
{"fulfillment": None, "fulfills": None, "owners_before": ["JEAkEJqLbbgDRAtMm8YAjGp759Aq2qTn9eaEHUj2XePE"]}
|
||||
|
@ -17,9 +17,7 @@ pytestmark = pytest.mark.bdb
|
||||
|
||||
def test_memoize_to_dict(b):
|
||||
alice = generate_key_pair()
|
||||
asset = {
|
||||
"data": {"id": "test_id"},
|
||||
}
|
||||
asset = {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}
|
||||
|
||||
assert to_dict.cache_info().hits == 0
|
||||
assert to_dict.cache_info().misses == 0
|
||||
@ -44,9 +42,7 @@ def test_memoize_to_dict(b):
|
||||
|
||||
def test_memoize_from_dict(b):
|
||||
alice = generate_key_pair()
|
||||
asset = {
|
||||
"data": {"id": "test_id"},
|
||||
}
|
||||
asset = {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}
|
||||
|
||||
assert from_dict.cache_info().hits == 0
|
||||
assert from_dict.cache_info().misses == 0
|
||||
@ -72,9 +68,7 @@ def test_memoize_from_dict(b):
|
||||
|
||||
def test_memoize_input_valid(b):
|
||||
alice = generate_key_pair()
|
||||
asset = {
|
||||
"data": {"id": "test_id"},
|
||||
}
|
||||
asset = {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}
|
||||
|
||||
assert Transaction._input_valid.cache_info().hits == 0
|
||||
assert Transaction._input_valid.cache_info().misses == 0
|
||||
|
@ -259,7 +259,9 @@ def test_invalid_transaction_initialization(asset_definition):
|
||||
with raises(TypeError):
|
||||
Transaction(operation="CREATE", asset=asset_definition, outputs=[], inputs="invalid inputs")
|
||||
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):
|
||||
@ -576,7 +578,7 @@ def test_create_create_transaction_single_io(user_output, user_pub, data):
|
||||
"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["inputs"][0]["fulfillment"] = None
|
||||
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()
|
||||
expected = {
|
||||
"outputs": [user_output.to_dict(), user2_output.to_dict()],
|
||||
"metadata": {"message": "hello"},
|
||||
"metadata": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4",
|
||||
"inputs": [input],
|
||||
"operation": "CREATE",
|
||||
"version": Transaction.VERSION,
|
||||
}
|
||||
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()
|
||||
tx.pop("id")
|
||||
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):
|
||||
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])
|
||||
assert tx.inputs_valid() is True
|
||||
|
||||
@ -645,7 +653,7 @@ def test_create_create_transaction_threshold(
|
||||
"operation": "CREATE",
|
||||
"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.pop("id")
|
||||
tx_dict["inputs"][0]["fulfillment"] = None
|
||||
@ -677,9 +685,9 @@ def test_create_create_transaction_with_invalid_parameters(user_pub):
|
||||
with raises(ValueError):
|
||||
Create.generate([user_pub], [([user_pub],)])
|
||||
with raises(TypeError):
|
||||
Create.generate([user_pub], [([user_pub], 1)], metadata="not a dict or none")
|
||||
with raises(TypeError):
|
||||
Create.generate([user_pub], [([user_pub], 1)], asset="not a dict or none")
|
||||
Create.generate([user_pub], [([user_pub], 1)], metadata={"data": "not a dict or none"})
|
||||
with raises(ValueError):
|
||||
Create.generate([user_pub], [([user_pub], 1)], asset={"data": "not a dict or none"})
|
||||
|
||||
|
||||
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(
|
||||
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])
|
||||
|
||||
expected = {
|
||||
@ -794,7 +804,7 @@ def test_create_transfer_with_invalid_parameters(tx, user_pub):
|
||||
with raises(ValueError):
|
||||
Transfer.generate(["fulfillment"], [([user_pub],)], tx.id)
|
||||
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):
|
||||
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(
|
||||
[merlin.public_key],
|
||||
[([alice.public_key], 1), ([bob.public_key], 2), ([carol.public_key], 3)],
|
||||
asset={"hash": "06e47bcf9084f7ecfd2a2a2ad275444a"},
|
||||
asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"},
|
||||
).sign([merlin.private_key])
|
||||
unspent_outputs = list(tx.unspent_outputs)
|
||||
assert len(unspent_outputs) == 3
|
||||
|
@ -15,6 +15,7 @@ import copy
|
||||
import random
|
||||
import tempfile
|
||||
import codecs
|
||||
from ipld import marshal, multihash
|
||||
from collections import namedtuple
|
||||
from logging import getLogger
|
||||
from logging.config import dictConfig
|
||||
@ -287,7 +288,8 @@ def create_tx(alice, user_pk):
|
||||
from planetmint.transactions.types.assets.create import Create
|
||||
|
||||
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
|
||||
@ -333,9 +335,7 @@ def inputs(user_pk, b, alice):
|
||||
for height in range(1, 4):
|
||||
transactions = [
|
||||
Create.generate(
|
||||
[alice.public_key],
|
||||
[([user_pk], 1)],
|
||||
metadata={"msg": random.random()},
|
||||
[alice.public_key], [([user_pk], 1)], metadata=multihash(marshal({"data": f"{random.random()}"}))
|
||||
).sign([alice.private_key])
|
||||
for _ in range(10)
|
||||
]
|
||||
|
@ -6,7 +6,7 @@ import warnings
|
||||
from unittest.mock import patch
|
||||
from planetmint.transactions.types.assets.create import Create
|
||||
from planetmint.transactions.types.assets.transfer import Transfer
|
||||
|
||||
from ipld import marshal, multihash
|
||||
import pytest
|
||||
from base58 import b58decode
|
||||
|
||||
@ -65,9 +65,9 @@ class TestBigchainApi(object):
|
||||
return
|
||||
|
||||
# define the assets
|
||||
asset1 = {"msg": "Planetmint 1"}
|
||||
asset2 = {"msg": "Planetmint 2"}
|
||||
asset3 = {"msg": "Planetmint 3"}
|
||||
asset1 = {"data": multihash(marshal({"msg": "Planetmint 1"}))}
|
||||
asset2 = {"data": multihash(marshal({"msg": "Planetmint 2"}))}
|
||||
asset3 = {"data": multihash(marshal({"msg": "Planetmint 3"}))}
|
||||
|
||||
# create the transactions
|
||||
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
|
||||
assets = list(b.text_search("planetmint"))
|
||||
assert len(assets) == 3
|
||||
assert len(assets) == 0
|
||||
|
||||
@pytest.mark.usefixtures("inputs")
|
||||
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):
|
||||
|
||||
asset1 = {"msg": "Planetmint 1"}
|
||||
asset1 = {"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}
|
||||
|
||||
tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset=asset1).sign([alice.private_key])
|
||||
b.store_bulk_transactions([tx])
|
||||
@ -377,7 +377,7 @@ class TestMultipleInputs(object):
|
||||
|
||||
transactions = []
|
||||
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 = tx.sign([alice.private_key])
|
||||
transactions.append(tx)
|
||||
@ -472,12 +472,15 @@ def test_transaction_unicode(b, alice):
|
||||
from planetmint.transactions.common.utils import serialize
|
||||
|
||||
# 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)
|
||||
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()
|
||||
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])
|
||||
|
||||
@ -355,9 +355,9 @@ def test_store_pre_commit_state_in_end_block(b, alice, init_chain_request):
|
||||
from planetmint import App
|
||||
from planetmint.backend import query
|
||||
|
||||
tx = Create.generate([alice.public_key], [([alice.public_key], 1)], asset={"msg": "live long and prosper"}).sign(
|
||||
[alice.private_key]
|
||||
)
|
||||
tx = Create.generate(
|
||||
[alice.public_key], [([alice.public_key], 1)], asset={"data": "QmaozNR7DZHQK1ZcU9p7QdrshMvXqWK6gpu5rmrkPdT3L4"}
|
||||
).sign([alice.private_key])
|
||||
|
||||
app = App(b)
|
||||
app.init_chain(init_chain_request)
|
||||
|
@ -25,6 +25,7 @@ from planetmint.transactions.common.transaction_mode_types import (
|
||||
BROADCAST_TX_SYNC,
|
||||
)
|
||||
from planetmint.lib import Block
|
||||
from ipld import marshal, multihash
|
||||
|
||||
|
||||
@pytest.mark.bdb
|
||||
@ -40,15 +41,21 @@ def test_asset_is_separated_from_transaciton(b):
|
||||
bob = generate_key_pair()
|
||||
|
||||
asset = {
|
||||
"Never gonna": [
|
||||
"give you up",
|
||||
"let you down",
|
||||
"run around" "desert you",
|
||||
"make you cry",
|
||||
"say goodbye",
|
||||
"tell a lie",
|
||||
"hurt you",
|
||||
]
|
||||
"data": multihash(
|
||||
marshal(
|
||||
{
|
||||
"Never gonna": [
|
||||
"give you up",
|
||||
"let you down",
|
||||
"run around" "desert 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(
|
||||
@ -404,7 +411,7 @@ def test_get_spent_transaction_critical_double_spend(b, alice, bob, carol):
|
||||
from planetmint.exceptions import CriticalDoubleSpend
|
||||
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])
|
||||
|
||||
|
@ -20,6 +20,7 @@ from unittest.mock import MagicMock
|
||||
from planetmint.transactions.common.exceptions import AmountError, SchemaValidationError, ThresholdTooDeep
|
||||
from planetmint.transactions.common.transaction import Transaction
|
||||
from planetmint.transactions.common.utils import _fulfillment_to_details, _fulfillment_from_details
|
||||
from ipld import marshal, multihash
|
||||
|
||||
################################################################################
|
||||
# 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):
|
||||
create_tx.metadata = {"a": 1}
|
||||
create_tx.metadata = multihash(marshal({"a": 1}))
|
||||
signed_tx = create_tx.sign([alice.private_key])
|
||||
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):
|
||||
create_tx.asset["data"] = "a"
|
||||
create_tx.asset["data"] = multihash(marshal({"a": ""}))
|
||||
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):
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
import pytest
|
||||
from planetmint.transactions.types.assets.create import Create
|
||||
from ipld import marshal, multihash
|
||||
|
||||
ASSETS_ENDPOINT = "/api/v1/assets/"
|
||||
|
||||
@ -29,24 +30,24 @@ def test_get_assets_tendermint(client, b, alice):
|
||||
assert res.status_code == 200
|
||||
|
||||
# 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])
|
||||
|
||||
b.store_bulk_transactions([tx])
|
||||
|
||||
# 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 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
|
||||
def test_get_assets_limit_tendermint(client, b, alice):
|
||||
|
||||
# create two assets
|
||||
asset1 = {"msg": "abc 1"}
|
||||
asset2 = {"msg": "abc 2"}
|
||||
asset1 = {"data": multihash(marshal({"msg": "abc 1"}))}
|
||||
asset2 = {"data": multihash(marshal({"msg": "abc 2"}))}
|
||||
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])
|
||||
|
||||
@ -54,11 +55,11 @@ def test_get_assets_limit_tendermint(client, b, alice):
|
||||
b.store_bulk_transactions([tx2])
|
||||
|
||||
# test that both assets are returned without limit
|
||||
res = client.get(ASSETS_ENDPOINT + "?search=abc")
|
||||
assert res.status_code == 200
|
||||
assert len(res.json) == 2
|
||||
|
||||
# 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"])
|
||||
assert res.status_code == 200
|
||||
assert len(res.json) == 1
|
||||
|
||||
# test that only one asset is returned when using limit=1
|
||||
res = client.get(ASSETS_ENDPOINT + "?search=" + asset1["data"] + "&limit=1")
|
||||
assert res.status_code == 200
|
||||
assert len(res.json) == 1
|
||||
|
@ -7,6 +7,7 @@ import pytest
|
||||
|
||||
from planetmint.transactions.types.assets.create import Create
|
||||
from planetmint.lib import Block
|
||||
from ipld import marshal, multihash
|
||||
|
||||
BLOCKS_ENDPOINT = "/api/v1/blocks/"
|
||||
|
||||
@ -16,7 +17,9 @@ BLOCKS_ENDPOINT = "/api/v1/blocks/"
|
||||
def test_get_block_endpoint(b, client, alice):
|
||||
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])
|
||||
|
||||
# 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
|
||||
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])
|
||||
b.store_bulk_transactions([tx])
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
import pytest
|
||||
from planetmint.transactions.types.assets.create import Create
|
||||
from ipld import marshal, multihash
|
||||
|
||||
METADATA_ENDPOINT = "/api/v1/metadata/"
|
||||
|
||||
@ -22,15 +23,15 @@ def test_get_metadata_with_missing_text_search(client):
|
||||
|
||||
@pytest.mark.bdb
|
||||
def test_get_metadata_tendermint(client, b, alice):
|
||||
|
||||
asset = {"data": multihash(marshal({"msg": "abc"}))}
|
||||
# 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.status_code == 200
|
||||
|
||||
# create asset
|
||||
asset = {"msg": "abc"}
|
||||
metadata = {"key": "my_meta"}
|
||||
# asset #= {"msg": "abc"}
|
||||
metadata = multihash(marshal({"key": "my_meta"}))
|
||||
tx = Create.generate([alice.public_key], [([alice.public_key], 1)], metadata=metadata, asset=asset).sign(
|
||||
[alice.private_key]
|
||||
)
|
||||
@ -38,36 +39,36 @@ def test_get_metadata_tendermint(client, b, alice):
|
||||
b.store_bulk_transactions([tx])
|
||||
|
||||
# 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 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
|
||||
def test_get_metadata_limit_tendermint(client, b, alice):
|
||||
|
||||
# create two assets
|
||||
asset1 = {"msg": "abc 1"}
|
||||
meta1 = {"key": "meta 1"}
|
||||
asset1 = {"data": multihash(marshal({"msg": "abc 1"}))}
|
||||
meta1 = multihash(marshal({"key": "meta 1"}))
|
||||
tx1 = Create.generate([alice.public_key], [([alice.public_key], 1)], metadata=meta1, asset=asset1).sign(
|
||||
[alice.private_key]
|
||||
)
|
||||
b.store_bulk_transactions([tx1])
|
||||
|
||||
asset2 = {"msg": "abc 2"}
|
||||
meta2 = {"key": "meta 2"}
|
||||
asset2 = {"data": multihash(marshal({"msg": "abc 2"}))}
|
||||
meta2 = multihash(marshal({"key": "meta 2"}))
|
||||
tx2 = Create.generate([alice.public_key], [([alice.public_key], 1)], metadata=meta2, asset=asset2).sign(
|
||||
[alice.private_key]
|
||||
)
|
||||
b.store_bulk_transactions([tx2])
|
||||
|
||||
# test that both assets are returned without limit
|
||||
res = client.get(METADATA_ENDPOINT + "?search=meta")
|
||||
assert res.status_code == 200
|
||||
assert len(res.json) == 2
|
||||
|
||||
# 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=" + meta1)
|
||||
assert res.status_code == 200
|
||||
assert len(res.json) == 1
|
||||
|
||||
# test that only one asset is returned when using limit=1
|
||||
res = client.get(METADATA_ENDPOINT + "?search=" + meta2 + "&limit=1")
|
||||
assert res.status_code == 200
|
||||
assert len(res.json) == 1
|
||||
|
@ -9,6 +9,7 @@ from unittest.mock import Mock, patch
|
||||
import base58
|
||||
import pytest
|
||||
from cryptoconditions import Ed25519Sha256
|
||||
from ipld import multihash, marshal
|
||||
|
||||
try:
|
||||
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}
|
||||
else:
|
||||
asset = lang_obj
|
||||
|
||||
asset = {"data": multihash(marshal(asset))}
|
||||
tx = Create.generate([user_pub], [([user_pub], 1)], asset=asset)
|
||||
tx = tx.sign([user_priv])
|
||||
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()
|
||||
|
||||
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()))
|
||||
assert res.status_code == 202
|
||||
|
||||
|
@ -11,6 +11,7 @@ import threading
|
||||
# from unittest.mock import patch
|
||||
from planetmint.transactions.types.assets.create import Create
|
||||
from planetmint.transactions.types.assets.transfer import Transfer
|
||||
from ipld import multihash, marshal
|
||||
|
||||
import pytest
|
||||
|
||||
@ -263,7 +264,7 @@ def test_integration_from_webapi_to_websocket(monkeypatch, client, loop):
|
||||
|
||||
# Create a keypair and generate a new asset
|
||||
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 = tx.sign([user_priv])
|
||||
# Post the transaction to the Planetmint Web API
|
||||
|
Loading…
x
Reference in New Issue
Block a user