From 407b771185276c0a462308cd5f516a719ad36ea7 Mon Sep 17 00:00:00 2001 From: vrde Date: Wed, 29 Aug 2018 14:13:22 +0200 Subject: [PATCH 1/2] Problem: validating create+transfer might crash the system (#2487) Solution: if a TRANSFER transaction is validated after a CREATE transaction, the system crashes with `AttributeError: 'NoneType' object has no attribute 'txid'`. This happens because querying `get_spent` checks the attributes `txid` and `output` of `input.fulfills` for every transaction in the current buffer (`current_transactions`). For a CREATE, `input.fulfills` is None, so the check would fail. The solution is to check if `input.fulfills` is defined. If not, then the current transaction cannot spend any output, so we can safely skip it. --- bigchaindb/lib.py | 3 ++- tests/tendermint/test_lib.py | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/bigchaindb/lib.py b/bigchaindb/lib.py index cbabf06a..e75153d5 100644 --- a/bigchaindb/lib.py +++ b/bigchaindb/lib.py @@ -285,7 +285,8 @@ class BigchainDB(object): current_spent_transactions = [] for ctxn in current_transactions: for ctxn_input in ctxn.inputs: - if ctxn_input.fulfills.txid == txid and\ + if ctxn_input.fulfills and\ + ctxn_input.fulfills.txid == txid and\ ctxn_input.fulfills.output == output: current_spent_transactions.append(ctxn) diff --git a/tests/tendermint/test_lib.py b/tests/tendermint/test_lib.py index d8223a25..4e8ff6b3 100644 --- a/tests/tendermint/test_lib.py +++ b/tests/tendermint/test_lib.py @@ -419,3 +419,25 @@ def test_get_spent_transaction_critical_double_spend(b, alice, bob, carol): with pytest.raises(CriticalDoubleSpend): b.get_spent(tx.id, tx_transfer.inputs[0].fulfills.output) + + +def test_validation_with_transaction_buffer(b): + from bigchaindb.common.crypto import generate_key_pair + from bigchaindb.models import Transaction + + priv_key, pub_key = generate_key_pair() + + create_tx = Transaction.create([pub_key], [([pub_key], 10)]).sign([priv_key]) + transfer_tx = Transaction.transfer(create_tx.to_inputs(), + [([pub_key], 10)], + asset_id=create_tx.id).sign([priv_key]) + double_spend = Transaction.transfer(create_tx.to_inputs(), + [([pub_key], 10)], + asset_id=create_tx.id).sign([priv_key]) + + assert b.is_valid_transaction(create_tx) + assert b.is_valid_transaction(transfer_tx, [create_tx]) + + assert not b.is_valid_transaction(create_tx, [create_tx]) + assert not b.is_valid_transaction(transfer_tx, [create_tx, transfer_tx]) + assert not b.is_valid_transaction(double_spend, [create_tx, transfer_tx]) From 3f7b521809682a74265ec38830b692b1bf05530e Mon Sep 17 00:00:00 2001 From: vrde Date: Wed, 29 Aug 2018 14:14:47 +0200 Subject: [PATCH 2/2] Problem: make unit-test-watch loops forever (#2486) Solution: BigchainDB by default writes logs in the same directory it is run. The `looponfail` feature provided by pytest waits for changes in the current directory, so it is continuously triggered. This patch tells pytest to only watch the `bigchaindb` and `tests` directories. --- pytest.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/pytest.ini b/pytest.ini index e604b0b9..006bc2bc 100644 --- a/pytest.ini +++ b/pytest.ini @@ -2,3 +2,4 @@ testpaths = tests/ norecursedirs = .* *.egg *.egg-info env* devenv* docs addopts = -m tendermint +looponfailroots = bigchaindb tests