mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
Merge remote-tracking branch 'origin' into bug/1132/vote-pipeline-validates-transactions-twice
This commit is contained in:
commit
153b3dd8d4
@ -143,6 +143,10 @@ def get_asset_by_id(conn, asset_id):
|
||||
@register_query(MongoDBConnection)
|
||||
def get_spent(conn, transaction_id, output):
|
||||
cursor = conn.db['bigchain'].aggregate([
|
||||
{'$match': {
|
||||
'block.transactions.inputs.fulfills.txid': transaction_id,
|
||||
'block.transactions.inputs.fulfills.output': output
|
||||
}},
|
||||
{'$unwind': '$block.transactions'},
|
||||
{'$match': {
|
||||
'block.transactions.inputs.fulfills.txid': transaction_id,
|
||||
@ -157,12 +161,9 @@ def get_spent(conn, transaction_id, output):
|
||||
@register_query(MongoDBConnection)
|
||||
def get_owned_ids(conn, owner):
|
||||
cursor = conn.db['bigchain'].aggregate([
|
||||
{'$match': {'block.transactions.outputs.public_keys': owner}},
|
||||
{'$unwind': '$block.transactions'},
|
||||
{'$match': {
|
||||
'block.transactions.outputs.public_keys': {
|
||||
'$elemMatch': {'$eq': owner}
|
||||
}
|
||||
}}
|
||||
{'$match': {'block.transactions.outputs.public_keys': owner}}
|
||||
])
|
||||
# we need to access some nested fields before returning so lets use a
|
||||
# generator to avoid having to read all records on the cursor at this point
|
||||
|
@ -63,6 +63,18 @@ def create_bigchain_secondary_index(conn, dbname):
|
||||
.create_index('block.transactions.transaction.asset.id',
|
||||
name='asset_id')
|
||||
|
||||
# secondary index on the public keys of outputs
|
||||
conn.conn[dbname]['bigchain']\
|
||||
.create_index('block.transactions.outputs.public_keys',
|
||||
name='outputs')
|
||||
|
||||
# secondary index on inputs/transaction links (txid, output)
|
||||
conn.conn[dbname]['bigchain']\
|
||||
.create_index([
|
||||
('block.transactions.inputs.fulfills.txid', ASCENDING),
|
||||
('block.transactions.inputs.fulfills.output', ASCENDING),
|
||||
], name='inputs')
|
||||
|
||||
|
||||
def create_backlog_secondary_index(conn, dbname):
|
||||
logger.info('Create `backlog` secondary index.')
|
||||
|
@ -111,21 +111,22 @@ def _get_asset_create_tx_query(asset_id):
|
||||
|
||||
@register_query(RethinkDBConnection)
|
||||
def get_spent(connection, transaction_id, output):
|
||||
# TODO: use index!
|
||||
return connection.run(
|
||||
r.table('bigchain', read_mode=READ_MODE)
|
||||
.concat_map(lambda doc: doc['block']['transactions'])
|
||||
.filter(lambda transaction: transaction['inputs'].contains(
|
||||
lambda input: input['fulfills'] == {'txid': transaction_id, 'output': output})))
|
||||
.get_all([transaction_id, output], index='inputs')
|
||||
.concat_map(lambda doc: doc['block']['transactions'])
|
||||
.filter(lambda transaction: transaction['inputs'].contains(
|
||||
lambda input_: input_['fulfills'] == {'txid': transaction_id, 'output': output})))
|
||||
|
||||
|
||||
@register_query(RethinkDBConnection)
|
||||
def get_owned_ids(connection, owner):
|
||||
# TODO: use index!
|
||||
return connection.run(
|
||||
r.table('bigchain', read_mode=READ_MODE)
|
||||
.concat_map(lambda doc: doc['block']['transactions'])
|
||||
.filter(lambda tx: tx['outputs'].contains(
|
||||
.get_all(owner, index='outputs')
|
||||
.distinct()
|
||||
.concat_map(lambda doc: doc['block']['transactions'])
|
||||
.filter(lambda tx: tx['outputs'].contains(
|
||||
lambda c: c['public_keys'].contains(owner))))
|
||||
|
||||
|
||||
|
@ -66,6 +66,31 @@ def create_bigchain_secondary_index(connection, dbname):
|
||||
.table('bigchain')
|
||||
.index_create('asset_id', r.row['block']['transactions']['asset']['id'], multi=True))
|
||||
|
||||
# secondary index on the public keys of outputs
|
||||
# the last reduce operation is to return a flatten list of public_keys
|
||||
# without it we would need to match exactly the public_keys list.
|
||||
# For instance querying for `pk1` would not match documents with
|
||||
# `public_keys: [pk1, pk2, pk3]`
|
||||
connection.run(
|
||||
r.db(dbname)
|
||||
.table('bigchain')
|
||||
.index_create('outputs',
|
||||
r.row['block']['transactions']
|
||||
.concat_map(lambda tx: tx['outputs']['public_keys'])
|
||||
.reduce(lambda l, r: l + r), multi=True))
|
||||
|
||||
# secondary index on inputs/transaction links (txid, output)
|
||||
connection.run(
|
||||
r.db(dbname)
|
||||
.table('bigchain')
|
||||
.index_create('inputs',
|
||||
r.row['block']['transactions']
|
||||
.concat_map(lambda tx: tx['inputs']['fulfills'])
|
||||
.with_fields('txid', 'output')
|
||||
.map(lambda fulfills: [fulfills['txid'],
|
||||
fulfills['output']]),
|
||||
multi=True))
|
||||
|
||||
# wait for rethinkdb to finish creating secondary indexes
|
||||
connection.run(
|
||||
r.db(dbname)
|
||||
|
@ -209,10 +209,6 @@ class Block(object):
|
||||
return self
|
||||
|
||||
def _validate_block(self, bigchain):
|
||||
# First, make sure this node hasn't already voted on this block
|
||||
if bigchain.has_previous_vote(self.id, self.voters):
|
||||
return self
|
||||
|
||||
# Check if the block was created by a federation node
|
||||
possible_voters = (bigchain.nodes_except_me + [bigchain.me])
|
||||
if self.node_pubkey not in possible_voters:
|
||||
|
@ -21,8 +21,8 @@ def test_init_creates_db_tables_and_indexes():
|
||||
assert sorted(collection_names) == ['backlog', 'bigchain', 'votes']
|
||||
|
||||
indexes = conn.conn[dbname]['bigchain'].index_information().keys()
|
||||
assert sorted(indexes) == ['_id_', 'asset_id', 'block_timestamp',
|
||||
'transaction_id']
|
||||
assert sorted(indexes) == ['_id_', 'asset_id', 'block_timestamp', 'inputs',
|
||||
'outputs', 'transaction_id']
|
||||
|
||||
indexes = conn.conn[dbname]['backlog'].index_information().keys()
|
||||
assert sorted(indexes) == ['_id_', 'assignee__transaction_timestamp',
|
||||
@ -81,8 +81,8 @@ def test_create_secondary_indexes():
|
||||
|
||||
# Bigchain table
|
||||
indexes = conn.conn[dbname]['bigchain'].index_information().keys()
|
||||
assert sorted(indexes) == ['_id_', 'asset_id', 'block_timestamp',
|
||||
'transaction_id']
|
||||
assert sorted(indexes) == ['_id_', 'asset_id', 'block_timestamp', 'inputs',
|
||||
'outputs', 'transaction_id']
|
||||
|
||||
# Backlog table
|
||||
indexes = conn.conn[dbname]['backlog'].index_information().keys()
|
||||
|
@ -85,6 +85,10 @@ def test_create_secondary_indexes():
|
||||
'transaction_id')) is True
|
||||
assert conn.run(r.db(dbname).table('bigchain').index_list().contains(
|
||||
'asset_id')) is True
|
||||
assert conn.run(r.db(dbname).table('bigchain').index_list().contains(
|
||||
'inputs')) is True
|
||||
assert conn.run(r.db(dbname).table('bigchain').index_list().contains(
|
||||
'outputs')) is True
|
||||
|
||||
# Backlog table
|
||||
assert conn.run(r.db(dbname).table('backlog').index_list().contains(
|
||||
|
@ -163,16 +163,3 @@ class TestBlockModel(object):
|
||||
|
||||
public_key = PublicKey(b.me)
|
||||
assert public_key.verify(expected_block_serialized, block.signature)
|
||||
|
||||
def test_validate_already_voted_on_block(self, b, monkeypatch):
|
||||
from unittest.mock import Mock
|
||||
from bigchaindb.models import Transaction
|
||||
|
||||
tx = Transaction.create([b.me], [([b.me], 1)])
|
||||
block = b.create_block([tx])
|
||||
|
||||
has_previous_vote = Mock()
|
||||
has_previous_vote.return_value = True
|
||||
monkeypatch.setattr(b, 'has_previous_vote', has_previous_vote)
|
||||
assert block == block.validate(b)
|
||||
assert has_previous_vote.called is True
|
||||
|
Loading…
x
Reference in New Issue
Block a user