mirror of
https://github.com/planetmint/planetmint.git
synced 2025-11-25 06:55:45 +00:00
store and get utxo fixed
This commit is contained in:
parent
c84acc689a
commit
f65cb049e8
@ -64,7 +64,7 @@ keys:create_index('txid_search', {type = 'tree', unique=false, parts={'transacti
|
|||||||
keys:create_index('output_search', {type = 'tree', unique=false, parts={'output_id'}})
|
keys:create_index('output_search', {type = 'tree', unique=false, parts={'output_id'}})
|
||||||
|
|
||||||
utxos = box.schema.space.create('utxos', {engine = 'memtx' , is_sync = false})
|
utxos = box.schema.space.create('utxos', {engine = 'memtx' , is_sync = false})
|
||||||
utxos:format({{name='transaction_id' , type='string'}, {name='output_index' , type='integer'}})
|
utxos:format({{name='transaction_id' , type='string'}, {name='output_index' , type='integer'}, {name='utxo_dict', type='string'}})
|
||||||
utxos:create_index('id_search', {type='hash' , parts={'transaction_id', 'output_index'}})
|
utxos:create_index('id_search', {type='hash' , parts={'transaction_id', 'output_index'}})
|
||||||
utxos:create_index('transaction_search', {type='tree', unique=false, parts={'transaction_id'}})
|
utxos:create_index('transaction_search', {type='tree', unique=false, parts={'transaction_id'}})
|
||||||
utxos:create_index('index_search', {type='tree', unique=false, parts={'output_index'}})
|
utxos:create_index('index_search', {type='tree', unique=false, parts={'output_index'}})
|
||||||
@ -9,11 +9,10 @@ from secrets import token_hex
|
|||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
|
|
||||||
from planetmint.backend import query
|
from planetmint.backend import query
|
||||||
from planetmint.backend.exceptions import DuplicateKeyError
|
|
||||||
from planetmint.backend.exceptions import OperationError
|
|
||||||
from planetmint.backend.utils import module_dispatch_registrar
|
from planetmint.backend.utils import module_dispatch_registrar
|
||||||
from planetmint.backend.tarantool.connection import TarantoolDB
|
from planetmint.backend.tarantool.connection import TarantoolDB
|
||||||
from planetmint.backend.tarantool.transaction.tools import TransactionCompose, TransactionDecompose
|
from planetmint.backend.tarantool.transaction.tools import TransactionCompose, TransactionDecompose
|
||||||
|
from json import dumps, loads
|
||||||
|
|
||||||
register_query = module_dispatch_registrar(query)
|
register_query = module_dispatch_registrar(query)
|
||||||
|
|
||||||
@ -337,7 +336,7 @@ def store_unspent_outputs(connection, *unspent_outputs: list):
|
|||||||
space = connection.space('utxos')
|
space = connection.space('utxos')
|
||||||
if unspent_outputs:
|
if unspent_outputs:
|
||||||
for utxo in unspent_outputs:
|
for utxo in unspent_outputs:
|
||||||
space.insert((utxo['transaction_id'], utxo['output_index']))
|
space.insert((utxo['transaction_id'], utxo['output_index'], dumps(utxo)))
|
||||||
|
|
||||||
|
|
||||||
@register_query(TarantoolDB)
|
@register_query(TarantoolDB)
|
||||||
@ -349,9 +348,10 @@ def delete_unspent_outputs(connection, *unspent_outputs: list):
|
|||||||
|
|
||||||
|
|
||||||
@register_query(TarantoolDB)
|
@register_query(TarantoolDB)
|
||||||
def get_unspent_outputs(connection):
|
def get_unspent_outputs(connection, query=None): # for now we don't have implementation for 'query'.
|
||||||
space = connection.space('utxos')
|
space = connection.space('utxos')
|
||||||
return space.select()
|
_utxos = space.select([]).data
|
||||||
|
return [loads(utx[2]) for utx in _utxos]
|
||||||
|
|
||||||
|
|
||||||
@register_query(TarantoolDB)
|
@register_query(TarantoolDB)
|
||||||
|
|||||||
@ -540,8 +540,9 @@ def dummy_unspent_outputs():
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def utxoset(dummy_unspent_outputs, utxo_collection):
|
def utxoset(dummy_unspent_outputs, utxo_collection):
|
||||||
|
from json import dumps
|
||||||
for utxo in dummy_unspent_outputs:
|
for utxo in dummy_unspent_outputs:
|
||||||
res = utxo_collection.insert((utxo["transaction_id"], utxo["output_index"]))
|
res = utxo_collection.insert((utxo["transaction_id"], utxo["output_index"], dumps(utxo)))
|
||||||
assert res
|
assert res
|
||||||
assert len(utxo_collection.select()) == 3
|
assert len(utxo_collection.select()) == 3
|
||||||
return dummy_unspent_outputs, utxo_collection
|
return dummy_unspent_outputs, utxo_collection
|
||||||
|
|||||||
@ -7,7 +7,6 @@ from operator import index
|
|||||||
import os
|
import os
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from hashlib import sha3_256
|
from hashlib import sha3_256
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@ -45,8 +44,8 @@ def test_asset_is_separated_from_transaciton(b):
|
|||||||
tx = Transaction.create([alice.public_key],
|
tx = Transaction.create([alice.public_key],
|
||||||
[([bob.public_key], 1)],
|
[([bob.public_key], 1)],
|
||||||
metadata=None,
|
metadata=None,
|
||||||
asset=asset)\
|
asset=asset) \
|
||||||
.sign([alice.private_key])
|
.sign([alice.private_key])
|
||||||
|
|
||||||
# with store_bulk_transactions we use `insert_many` where PyMongo
|
# with store_bulk_transactions we use `insert_many` where PyMongo
|
||||||
# automatically adds an `_id` field to the tx, therefore we need the
|
# automatically adds an `_id` field to the tx, therefore we need the
|
||||||
@ -89,8 +88,8 @@ def test_validation_error(b):
|
|||||||
alice = generate_key_pair()
|
alice = generate_key_pair()
|
||||||
tx = Transaction.create([alice.public_key],
|
tx = Transaction.create([alice.public_key],
|
||||||
[([alice.public_key], 1)],
|
[([alice.public_key], 1)],
|
||||||
asset=None)\
|
asset=None) \
|
||||||
.sign([alice.private_key]).to_dict()
|
.sign([alice.private_key]).to_dict()
|
||||||
|
|
||||||
tx['metadata'] = ''
|
tx['metadata'] = ''
|
||||||
assert not b.validate_transaction(tx)
|
assert not b.validate_transaction(tx)
|
||||||
@ -105,8 +104,8 @@ def test_write_and_post_transaction(mock_post, b):
|
|||||||
alice = generate_key_pair()
|
alice = generate_key_pair()
|
||||||
tx = Transaction.create([alice.public_key],
|
tx = Transaction.create([alice.public_key],
|
||||||
[([alice.public_key], 1)],
|
[([alice.public_key], 1)],
|
||||||
asset=None)\
|
asset=None) \
|
||||||
.sign([alice.private_key]).to_dict()
|
.sign([alice.private_key]).to_dict()
|
||||||
|
|
||||||
tx = b.validate_transaction(tx)
|
tx = b.validate_transaction(tx)
|
||||||
b.write_transaction(tx, BROADCAST_TX_ASYNC)
|
b.write_transaction(tx, BROADCAST_TX_ASYNC)
|
||||||
@ -195,7 +194,7 @@ def test_store_transaction(mocker, b, signed_create_tx,
|
|||||||
mocked_store_transaction.assert_called_once_with(
|
mocked_store_transaction.assert_called_once_with(
|
||||||
b.connection,
|
b.connection,
|
||||||
[{k: v for k, v in signed_create_tx.to_dict().items()
|
[{k: v for k, v in signed_create_tx.to_dict().items()
|
||||||
if k not in ('asset', 'metadata')}],
|
if k not in ('asset', 'metadata')}],
|
||||||
)
|
)
|
||||||
mocked_store_asset.reset_mock()
|
mocked_store_asset.reset_mock()
|
||||||
mocked_store_metadata.reset_mock()
|
mocked_store_metadata.reset_mock()
|
||||||
@ -213,13 +212,14 @@ def test_store_transaction(mocker, b, signed_create_tx,
|
|||||||
mocked_store_transaction.assert_called_once_with(
|
mocked_store_transaction.assert_called_once_with(
|
||||||
b.connection,
|
b.connection,
|
||||||
[{k: v for k, v in signed_transfer_tx.to_dict().items()
|
[{k: v for k, v in signed_transfer_tx.to_dict().items()
|
||||||
if k != 'metadata'}],
|
if k != 'metadata'}],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.bdb
|
@pytest.mark.bdb
|
||||||
def test_store_bulk_transaction(mocker, b, signed_create_tx,
|
def test_store_bulk_transaction(mocker, b, signed_create_tx,
|
||||||
signed_transfer_tx, db_context):
|
signed_transfer_tx, db_context):
|
||||||
|
from planetmint.backend.tarantool.connection import TarantoolDB
|
||||||
mocked_store_assets = mocker.patch(
|
mocked_store_assets = mocker.patch(
|
||||||
'planetmint.backend.query.store_assets')
|
'planetmint.backend.query.store_assets')
|
||||||
mocked_store_metadata = mocker.patch(
|
mocked_store_metadata = mocker.patch(
|
||||||
@ -233,10 +233,16 @@ def test_store_bulk_transaction(mocker, b, signed_create_tx,
|
|||||||
# utxo = utxoset.find_one()
|
# utxo = utxoset.find_one()
|
||||||
# assert utxo['transaction_id'] == signed_create_tx.id
|
# assert utxo['transaction_id'] == signed_create_tx.id
|
||||||
# assert utxo['output_index'] == 0
|
# assert utxo['output_index'] == 0
|
||||||
mocked_store_assets.assert_called_once_with(
|
if isinstance(b.connection, TarantoolDB):
|
||||||
b.connection,
|
mocked_store_assets.assert_called_once_with(
|
||||||
[ ( signed_create_tx.asset['data'], signed_create_tx.id, signed_create_tx.id )],
|
b.connection, # signed_create_tx.asset['data'] this was before
|
||||||
)
|
[(signed_create_tx.asset, signed_create_tx.id, signed_create_tx.id)],
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
mocked_store_assets.assert_called_once_with(
|
||||||
|
b.connection, # signed_create_tx.asset['data'] this was before
|
||||||
|
[(signed_create_tx.asset["data"], signed_create_tx.id, signed_create_tx.id)],
|
||||||
|
)
|
||||||
mocked_store_metadata.assert_called_once_with(
|
mocked_store_metadata.assert_called_once_with(
|
||||||
b.connection,
|
b.connection,
|
||||||
[{'id': signed_create_tx.id, 'metadata': signed_create_tx.metadata}],
|
[{'id': signed_create_tx.id, 'metadata': signed_create_tx.metadata}],
|
||||||
@ -244,7 +250,7 @@ def test_store_bulk_transaction(mocker, b, signed_create_tx,
|
|||||||
mocked_store_transactions.assert_called_once_with(
|
mocked_store_transactions.assert_called_once_with(
|
||||||
b.connection,
|
b.connection,
|
||||||
[{k: v for k, v in signed_create_tx.to_dict().items()
|
[{k: v for k, v in signed_create_tx.to_dict().items()
|
||||||
if k not in ('asset', 'metadata')}],
|
if k not in ('asset', 'metadata')}],
|
||||||
)
|
)
|
||||||
mocked_store_assets.reset_mock()
|
mocked_store_assets.reset_mock()
|
||||||
mocked_store_metadata.reset_mock()
|
mocked_store_metadata.reset_mock()
|
||||||
@ -254,7 +260,8 @@ def test_store_bulk_transaction(mocker, b, signed_create_tx,
|
|||||||
# utxo = utxoset.find_one()
|
# utxo = utxoset.find_one()
|
||||||
# assert utxo['transaction_id'] == signed_transfer_tx.id
|
# assert utxo['transaction_id'] == signed_transfer_tx.id
|
||||||
# assert utxo['output_index'] == 0
|
# assert utxo['output_index'] == 0
|
||||||
assert not mocked_store_assets.called
|
if not isinstance(b.connection, TarantoolDB):
|
||||||
|
assert not mocked_store_assets.called
|
||||||
mocked_store_metadata.asser_called_once_with(
|
mocked_store_metadata.asser_called_once_with(
|
||||||
b.connection,
|
b.connection,
|
||||||
[{'id': signed_transfer_tx.id,
|
[{'id': signed_transfer_tx.id,
|
||||||
@ -369,23 +376,23 @@ def test_get_spent_transaction_critical_double_spend(b, alice, bob, carol):
|
|||||||
|
|
||||||
tx = Transaction.create([alice.public_key],
|
tx = Transaction.create([alice.public_key],
|
||||||
[([alice.public_key], 1)],
|
[([alice.public_key], 1)],
|
||||||
asset=asset)\
|
asset=asset) \
|
||||||
.sign([alice.private_key])
|
.sign([alice.private_key])
|
||||||
|
|
||||||
tx_transfer = Transaction.transfer(tx.to_inputs(),
|
tx_transfer = Transaction.transfer(tx.to_inputs(),
|
||||||
[([bob.public_key], 1)],
|
[([bob.public_key], 1)],
|
||||||
asset_id=tx.id)\
|
asset_id=tx.id) \
|
||||||
.sign([alice.private_key])
|
.sign([alice.private_key])
|
||||||
|
|
||||||
double_spend = Transaction.transfer(tx.to_inputs(),
|
double_spend = Transaction.transfer(tx.to_inputs(),
|
||||||
[([carol.public_key], 1)],
|
[([carol.public_key], 1)],
|
||||||
asset_id=tx.id)\
|
asset_id=tx.id) \
|
||||||
.sign([alice.private_key])
|
.sign([alice.private_key])
|
||||||
|
|
||||||
same_input_double_spend = Transaction.transfer(tx.to_inputs() + tx.to_inputs(),
|
same_input_double_spend = Transaction.transfer(tx.to_inputs() + tx.to_inputs(),
|
||||||
[([bob.public_key], 1)],
|
[([bob.public_key], 1)],
|
||||||
asset_id=tx.id)\
|
asset_id=tx.id) \
|
||||||
.sign([alice.private_key])
|
.sign([alice.private_key])
|
||||||
|
|
||||||
b.store_bulk_transactions([tx])
|
b.store_bulk_transactions([tx])
|
||||||
|
|
||||||
@ -441,16 +448,16 @@ def test_migrate_abci_chain_yields_on_genesis(b):
|
|||||||
@pytest.mark.bdb
|
@pytest.mark.bdb
|
||||||
@pytest.mark.parametrize('chain,block_height,expected', [
|
@pytest.mark.parametrize('chain,block_height,expected', [
|
||||||
(
|
(
|
||||||
(1, 'chain-XYZ', True),
|
(1, 'chain-XYZ', True),
|
||||||
4,
|
4,
|
||||||
{'height': 5, 'chain_id': 'chain-XYZ-migrated-at-height-4',
|
{'height': 5, 'chain_id': 'chain-XYZ-migrated-at-height-4',
|
||||||
'is_synced': False},
|
'is_synced': False},
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
(5, 'chain-XYZ-migrated-at-height-4', True),
|
(5, 'chain-XYZ-migrated-at-height-4', True),
|
||||||
13,
|
13,
|
||||||
{'height': 14, 'chain_id': 'chain-XYZ-migrated-at-height-13',
|
{'height': 14, 'chain_id': 'chain-XYZ-migrated-at-height-13',
|
||||||
'is_synced': False},
|
'is_synced': False},
|
||||||
),
|
),
|
||||||
])
|
])
|
||||||
def test_migrate_abci_chain_generates_new_chains(b, chain, block_height,
|
def test_migrate_abci_chain_generates_new_chains(b, chain, block_height,
|
||||||
@ -475,8 +482,8 @@ def test_get_spent_key_order(b, user_pk, user_sk, user2_pk, user2_sk):
|
|||||||
|
|
||||||
tx1 = Transaction.create([user_pk],
|
tx1 = Transaction.create([user_pk],
|
||||||
[([alice.public_key], 3), ([user_pk], 2)],
|
[([alice.public_key], 3), ([user_pk], 2)],
|
||||||
asset=None)\
|
asset=None) \
|
||||||
.sign([user_sk])
|
.sign([user_sk])
|
||||||
b.store_bulk_transactions([tx1])
|
b.store_bulk_transactions([tx1])
|
||||||
assert tx1.validate(b)
|
assert tx1.validate(b)
|
||||||
inputs = tx1.to_inputs()
|
inputs = tx1.to_inputs()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user