mirror of
https://github.com/planetmint/planetmint.git
synced 2025-06-08 23:26:37 +00:00
moved get_merkget_utxoset_merkle_root to dataaccessor and fixed test cases
Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>
This commit is contained in:
parent
a06a7f986f
commit
e627eb899d
@ -364,8 +364,8 @@ def delete_unspent_outputs(connection, unspent_outputs: list):
|
|||||||
@register_query(TarantoolDBConnection)
|
@register_query(TarantoolDBConnection)
|
||||||
@catch_db_exception
|
@catch_db_exception
|
||||||
def get_unspent_outputs(connection, query=None): # for now we don't have implementation for 'query'.
|
def get_unspent_outputs(connection, query=None): # for now we don't have implementation for 'query'.
|
||||||
_utxos = connection.connect().select(TARANT_TABLE_UTXOS, []).data
|
utxos = connection.connect().select(TARANT_TABLE_UTXOS, []).data
|
||||||
return [utx[3] for utx in _utxos]
|
return [{"transaction_id": utxo[5], "output_index": utxo[4]} for utxo in utxos]
|
||||||
|
|
||||||
|
|
||||||
@register_query(TarantoolDBConnection)
|
@register_query(TarantoolDBConnection)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import rapidjson
|
import rapidjson
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
from hashlib import sha3_256
|
||||||
|
|
||||||
from transactions import Transaction
|
from transactions import Transaction
|
||||||
from transactions.common.exceptions import DoubleSpend
|
from transactions.common.exceptions import DoubleSpend
|
||||||
@ -9,7 +10,7 @@ from transactions.common.exceptions import InputDoesNotExist
|
|||||||
from planetmint import config_utils, backend
|
from planetmint import config_utils, backend
|
||||||
from planetmint.const import GOVERNANCE_TRANSACTION_TYPES
|
from planetmint.const import GOVERNANCE_TRANSACTION_TYPES
|
||||||
from planetmint.model.fastquery import FastQuery
|
from planetmint.model.fastquery import FastQuery
|
||||||
from planetmint.abci.utils import key_from_base64
|
from planetmint.abci.utils import key_from_base64, merkleroot
|
||||||
from planetmint.backend.connection import Connection
|
from planetmint.backend.connection import Connection
|
||||||
from planetmint.backend.tarantool.const import TARANT_TABLE_TRANSACTION, TARANT_TABLE_GOVERNANCE, TARANT_TABLE_UTXOS, TARANT_TABLE_OUTPUT
|
from planetmint.backend.tarantool.const import TARANT_TABLE_TRANSACTION, TARANT_TABLE_GOVERNANCE, TARANT_TABLE_UTXOS, TARANT_TABLE_OUTPUT
|
||||||
from planetmint.backend.models.block import Block
|
from planetmint.backend.models.block import Block
|
||||||
@ -74,6 +75,7 @@ class DataAccessor:
|
|||||||
:obj:`list` of TransactionLink: list of ``txid`` s and ``output`` s
|
:obj:`list` of TransactionLink: list of ``txid`` s and ``output`` s
|
||||||
pointing to another transaction's condition
|
pointing to another transaction's condition
|
||||||
"""
|
"""
|
||||||
|
# TODO: adjust for new utxo handling, query and return outputs based on spent
|
||||||
outputs = self.fastquery.get_outputs_by_public_key(owner)
|
outputs = self.fastquery.get_outputs_by_public_key(owner)
|
||||||
if spent is None:
|
if spent is None:
|
||||||
return outputs
|
return outputs
|
||||||
@ -290,6 +292,44 @@ class DataAccessor:
|
|||||||
for index, output in enumerate(transaction["outputs"])
|
for index, output in enumerate(transaction["outputs"])
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def get_utxoset_merkle_root(self):
|
||||||
|
"""Returns the merkle root of the utxoset. This implies that
|
||||||
|
the utxoset is first put into a merkle tree.
|
||||||
|
|
||||||
|
For now, the merkle tree and its root will be computed each
|
||||||
|
time. This obviously is not efficient and a better approach
|
||||||
|
that limits the repetition of the same computation when
|
||||||
|
unnecesary should be sought. For instance, future optimizations
|
||||||
|
could simply re-compute the branches of the tree that were
|
||||||
|
affected by a change.
|
||||||
|
|
||||||
|
The transaction hash (id) and output index should be sufficient
|
||||||
|
to uniquely identify a utxo, and consequently only that
|
||||||
|
information from a utxo record is needed to compute the merkle
|
||||||
|
root. Hence, each node of the merkle tree should contain the
|
||||||
|
tuple (txid, output_index).
|
||||||
|
|
||||||
|
.. important:: The leaves of the tree will need to be sorted in
|
||||||
|
some kind of lexicographical order.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: Merkle root in hexadecimal form.
|
||||||
|
"""
|
||||||
|
utxoset = backend.query.get_unspent_outputs(self.connection)
|
||||||
|
# TODO Once ready, use the already pre-computed utxo_hash field.
|
||||||
|
# See common/transactions.py for details.
|
||||||
|
|
||||||
|
print(utxoset)
|
||||||
|
|
||||||
|
hashes = [
|
||||||
|
sha3_256("{}{}".format(utxo["transaction_id"], utxo["output_index"]).encode()).digest() for utxo in utxoset
|
||||||
|
]
|
||||||
|
|
||||||
|
print(sorted(hashes))
|
||||||
|
|
||||||
|
# TODO Notice the sorted call!
|
||||||
|
return merkleroot(sorted(hashes))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def fastquery(self):
|
def fastquery(self):
|
||||||
return FastQuery(self.connection)
|
return FastQuery(self.connection)
|
||||||
|
@ -22,7 +22,6 @@ from ipld import marshal, multihash
|
|||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
from planetmint.abci.rpc import MODE_COMMIT, MODE_LIST
|
from planetmint.abci.rpc import MODE_COMMIT, MODE_LIST
|
||||||
from tests.utils import get_utxoset_merkle_root
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.bdb
|
@pytest.mark.bdb
|
||||||
@ -239,19 +238,21 @@ def test_delete_many_unspent_outputs(b, alice):
|
|||||||
|
|
||||||
|
|
||||||
def test_get_utxoset_merkle_root_when_no_utxo(b):
|
def test_get_utxoset_merkle_root_when_no_utxo(b):
|
||||||
assert get_utxoset_merkle_root(b.models.connection) == sha3_256(b"").hexdigest()
|
assert b.models.get_utxoset_merkle_root() == sha3_256(b"").hexdigest()
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.bdb
|
@pytest.mark.bdb
|
||||||
def test_get_utxoset_merkle_root(b, dummy_unspent_outputs):
|
def test_get_utxoset_merkle_root(b, user_sk, user_pk):
|
||||||
utxo_space = b.models.connection.get_space("utxos")
|
tx = Create.generate(
|
||||||
for utxo in dummy_unspent_outputs:
|
[user_pk],
|
||||||
res = utxo_space.insert((uuid4().hex, utxo["transaction_id"], utxo["output_index"], utxo))
|
[([user_pk], 8), ([user_pk], 1), ([user_pk], 4)]
|
||||||
assert res
|
).sign([user_sk])
|
||||||
|
|
||||||
expected_merkle_root = "86d311c03115bf4d287f8449ca5828505432d69b82762d47077b1c00fe426eac"
|
b.models.store_bulk_transactions([tx])
|
||||||
merkle_root = get_utxoset_merkle_root(b.models.connection)
|
|
||||||
assert merkle_root == expected_merkle_root
|
expected_merkle_root = "e5fce6fed606b72744330b28b2f6d68f2eca570c4cf8e3c418b0c3150c75bfe2"
|
||||||
|
merkle_root = b.models.get_utxoset_merkle_root()
|
||||||
|
assert merkle_root in expected_merkle_root
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.bdb
|
@pytest.mark.bdb
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
# 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
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
from hashlib import sha3_256
|
|
||||||
|
|
||||||
import base58
|
import base58
|
||||||
import base64
|
import base64
|
||||||
@ -20,7 +19,7 @@ from transactions.common.transaction_mode_types import BROADCAST_TX_COMMIT
|
|||||||
from transactions.types.assets.create import Create
|
from transactions.types.assets.create import Create
|
||||||
from transactions.types.elections.vote import Vote
|
from transactions.types.elections.vote import Vote
|
||||||
from transactions.types.elections.validator_utils import election_id_to_public_key
|
from transactions.types.elections.validator_utils import election_id_to_public_key
|
||||||
from planetmint.abci.utils import merkleroot, key_to_base64
|
from planetmint.abci.utils import key_to_base64
|
||||||
from planetmint.abci.rpc import MODE_COMMIT, MODE_LIST
|
from planetmint.abci.rpc import MODE_COMMIT, MODE_LIST
|
||||||
|
|
||||||
|
|
||||||
@ -127,37 +126,7 @@ def generate_election(b, cls, public_key, private_key, asset_data, voter_keys):
|
|||||||
return election, votes
|
return election, votes
|
||||||
|
|
||||||
|
|
||||||
def get_utxoset_merkle_root(connection):
|
|
||||||
"""Returns the merkle root of the utxoset. This implies that
|
|
||||||
the utxoset is first put into a merkle tree.
|
|
||||||
|
|
||||||
For now, the merkle tree and its root will be computed each
|
|
||||||
time. This obviously is not efficient and a better approach
|
|
||||||
that limits the repetition of the same computation when
|
|
||||||
unnecesary should be sought. For instance, future optimizations
|
|
||||||
could simply re-compute the branches of the tree that were
|
|
||||||
affected by a change.
|
|
||||||
|
|
||||||
The transaction hash (id) and output index should be sufficient
|
|
||||||
to uniquely identify a utxo, and consequently only that
|
|
||||||
information from a utxo record is needed to compute the merkle
|
|
||||||
root. Hence, each node of the merkle tree should contain the
|
|
||||||
tuple (txid, output_index).
|
|
||||||
|
|
||||||
.. important:: The leaves of the tree will need to be sorted in
|
|
||||||
some kind of lexicographical order.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str: Merkle root in hexadecimal form.
|
|
||||||
"""
|
|
||||||
utxoset = backend.query.get_unspent_outputs(connection)
|
|
||||||
# TODO Once ready, use the already pre-computed utxo_hash field.
|
|
||||||
# See common/transactions.py for details.
|
|
||||||
hashes = [
|
|
||||||
sha3_256("{}{}".format(utxo["transaction_id"], utxo["output_index"]).encode()).digest() for utxo in utxoset
|
|
||||||
]
|
|
||||||
# TODO Notice the sorted call!
|
|
||||||
return merkleroot(sorted(hashes))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user