mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
Problem: Stateful validation doesn't raise double spend exception (#2422)
* Problem: Stateful validation doesn't raise double spend exception Solution: Transaction.validate should raise exception DoubleSpend if the given transaction is already a part of the database * Problem: Double spend exception message not accurate Solution: The exception message should state that the double spend is because of spending the same input more than once in the transaction
This commit is contained in:
parent
4795a78d49
commit
f13c9a9d57
@ -59,7 +59,7 @@ class Transaction(Transaction):
|
||||
|
||||
spent = bigchain.get_spent(input_txid, input_.fulfills.output,
|
||||
current_transactions)
|
||||
if spent and spent.id != self.id:
|
||||
if spent:
|
||||
raise DoubleSpend('input `{}` was already spent'
|
||||
.format(input_txid))
|
||||
|
||||
@ -70,7 +70,7 @@ class Transaction(Transaction):
|
||||
# Validate that all inputs are distinct
|
||||
links = [i.fulfills.to_uri() for i in self.inputs]
|
||||
if len(links) != len(set(links)):
|
||||
raise DoubleSpend('tx "{}" spends inputs twice'.format(self.id))
|
||||
raise DoubleSpend('tx "{}" spends the same output more than once'.format(self.id))
|
||||
|
||||
# validate asset id
|
||||
asset_id = Transaction.get_asset_id(input_txs)
|
||||
|
@ -12,7 +12,7 @@ def test_asset_transfer(b, signed_create_tx, user_pk, user_sk):
|
||||
signed_create_tx.id)
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
|
||||
b.store_bulk_transactions([signed_create_tx, tx_transfer])
|
||||
b.store_bulk_transactions([signed_create_tx])
|
||||
|
||||
assert tx_transfer_signed.validate(b) == tx_transfer_signed
|
||||
assert tx_transfer_signed.asset['id'] == signed_create_tx.id
|
||||
@ -27,7 +27,7 @@ def test_validate_transfer_asset_id_mismatch(b, signed_create_tx, user_pk, user_
|
||||
tx_transfer.asset['id'] = 'a' * 64
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
|
||||
b.store_bulk_transactions([signed_create_tx, tx_transfer_signed])
|
||||
b.store_bulk_transactions([signed_create_tx])
|
||||
|
||||
with pytest.raises(AssetIdMismatch):
|
||||
tx_transfer_signed.validate(b)
|
||||
|
@ -1,6 +1,8 @@
|
||||
import pytest
|
||||
import random
|
||||
|
||||
from bigchaindb.common.exceptions import DoubleSpend
|
||||
|
||||
|
||||
pytestmark = pytest.mark.tendermint
|
||||
|
||||
@ -127,7 +129,7 @@ def test_single_in_single_own_single_out_single_own_transfer(alice, b, user_pk,
|
||||
asset_id=tx_create.id)
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
|
||||
b.store_bulk_transactions([tx_create_signed, tx_transfer_signed])
|
||||
b.store_bulk_transactions([tx_create_signed])
|
||||
|
||||
assert tx_transfer_signed.validate(b)
|
||||
assert len(tx_transfer_signed.outputs) == 1
|
||||
@ -154,7 +156,7 @@ def test_single_in_single_own_multiple_out_single_own_transfer(alice, b, user_pk
|
||||
asset_id=tx_create.id)
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
|
||||
b.store_bulk_transactions([tx_create_signed, tx_transfer_signed])
|
||||
b.store_bulk_transactions([tx_create_signed])
|
||||
|
||||
assert tx_transfer_signed.validate(b) == tx_transfer_signed
|
||||
assert len(tx_transfer_signed.outputs) == 2
|
||||
@ -182,7 +184,7 @@ def test_single_in_single_own_single_out_multiple_own_transfer(alice, b, user_pk
|
||||
asset_id=tx_create.id)
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
|
||||
b.store_bulk_transactions([tx_create_signed, tx_transfer_signed])
|
||||
b.store_bulk_transactions([tx_create_signed])
|
||||
|
||||
assert tx_transfer_signed.validate(b) == tx_transfer_signed
|
||||
assert len(tx_transfer_signed.outputs) == 1
|
||||
@ -194,6 +196,10 @@ def test_single_in_single_own_single_out_multiple_own_transfer(alice, b, user_pk
|
||||
|
||||
assert len(tx_transfer_signed.inputs) == 1
|
||||
|
||||
b.store_bulk_transactions([tx_transfer_signed])
|
||||
with pytest.raises(DoubleSpend):
|
||||
tx_transfer_signed.validate(b)
|
||||
|
||||
|
||||
# TRANSFER divisible asset
|
||||
# Single input
|
||||
@ -215,7 +221,7 @@ def test_single_in_single_own_multiple_out_mix_own_transfer(alice, b, user_pk,
|
||||
asset_id=tx_create.id)
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
|
||||
b.store_bulk_transactions([tx_create_signed, tx_transfer_signed])
|
||||
b.store_bulk_transactions([tx_create_signed])
|
||||
|
||||
assert tx_transfer_signed.validate(b) == tx_transfer_signed
|
||||
assert len(tx_transfer_signed.outputs) == 2
|
||||
@ -228,6 +234,10 @@ def test_single_in_single_own_multiple_out_mix_own_transfer(alice, b, user_pk,
|
||||
|
||||
assert len(tx_transfer_signed.inputs) == 1
|
||||
|
||||
b.store_bulk_transactions([tx_transfer_signed])
|
||||
with pytest.raises(DoubleSpend):
|
||||
tx_transfer_signed.validate(b)
|
||||
|
||||
|
||||
# TRANSFER divisible asset
|
||||
# Single input
|
||||
@ -249,7 +259,7 @@ def test_single_in_multiple_own_single_out_single_own_transfer(alice, b, user_pk
|
||||
asset_id=tx_create.id)
|
||||
tx_transfer_signed = tx_transfer.sign([alice.private_key, user_sk])
|
||||
|
||||
b.store_bulk_transactions([tx_create_signed, tx_transfer_signed])
|
||||
b.store_bulk_transactions([tx_create_signed])
|
||||
|
||||
assert tx_transfer_signed.validate(b) == tx_transfer_signed
|
||||
assert len(tx_transfer_signed.outputs) == 1
|
||||
@ -260,6 +270,10 @@ def test_single_in_multiple_own_single_out_single_own_transfer(alice, b, user_pk
|
||||
assert 'subconditions' in ffill
|
||||
assert len(ffill['subconditions']) == 2
|
||||
|
||||
b.store_bulk_transactions([tx_transfer_signed])
|
||||
with pytest.raises(DoubleSpend):
|
||||
tx_transfer_signed.validate(b)
|
||||
|
||||
|
||||
# TRANSFER divisible asset
|
||||
# Multiple inputs
|
||||
@ -280,13 +294,17 @@ def test_multiple_in_single_own_single_out_single_own_transfer(alice, b, user_pk
|
||||
asset_id=tx_create.id)
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
|
||||
b.store_bulk_transactions([tx_create_signed, tx_transfer_signed])
|
||||
b.store_bulk_transactions([tx_create_signed])
|
||||
|
||||
assert tx_transfer_signed.validate(b)
|
||||
assert len(tx_transfer_signed.outputs) == 1
|
||||
assert tx_transfer_signed.outputs[0].amount == 100
|
||||
assert len(tx_transfer_signed.inputs) == 2
|
||||
|
||||
b.store_bulk_transactions([tx_transfer_signed])
|
||||
with pytest.raises(DoubleSpend):
|
||||
tx_transfer_signed.validate(b)
|
||||
|
||||
|
||||
# TRANSFER divisible asset
|
||||
# Multiple inputs
|
||||
@ -309,9 +327,9 @@ def test_multiple_in_multiple_own_single_out_single_own_transfer(alice, b, user_
|
||||
asset_id=tx_create.id)
|
||||
tx_transfer_signed = tx_transfer.sign([alice.private_key, user_sk])
|
||||
|
||||
b.store_bulk_transactions([tx_create_signed, tx_transfer_signed])
|
||||
b.store_bulk_transactions([tx_create_signed])
|
||||
|
||||
assert tx_transfer_signed.validate(b)
|
||||
assert tx_transfer_signed.validate(b) == tx_transfer_signed
|
||||
assert len(tx_transfer_signed.outputs) == 1
|
||||
assert tx_transfer_signed.outputs[0].amount == 100
|
||||
assert len(tx_transfer_signed.inputs) == 2
|
||||
@ -323,6 +341,10 @@ def test_multiple_in_multiple_own_single_out_single_own_transfer(alice, b, user_
|
||||
assert len(ffill_fid0['subconditions']) == 2
|
||||
assert len(ffill_fid1['subconditions']) == 2
|
||||
|
||||
b.store_bulk_transactions([tx_transfer_signed])
|
||||
with pytest.raises(DoubleSpend):
|
||||
tx_transfer_signed.validate(b)
|
||||
|
||||
|
||||
# TRANSFER divisible asset
|
||||
# Multiple inputs
|
||||
@ -345,7 +367,7 @@ def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(alice, b, user_pk
|
||||
asset_id=tx_create.id)
|
||||
tx_transfer_signed = tx_transfer.sign([alice.private_key, user_sk])
|
||||
|
||||
b.store_bulk_transactions([tx_create_signed, tx_transfer_signed])
|
||||
b.store_bulk_transactions([tx_create_signed])
|
||||
|
||||
assert tx_transfer_signed.validate(b) == tx_transfer_signed
|
||||
assert len(tx_transfer_signed.outputs) == 1
|
||||
@ -358,6 +380,10 @@ def test_muiltiple_in_mix_own_multiple_out_single_own_transfer(alice, b, user_pk
|
||||
assert 'subconditions' in ffill_fid1
|
||||
assert len(ffill_fid1['subconditions']) == 2
|
||||
|
||||
b.store_bulk_transactions([tx_transfer_signed])
|
||||
with pytest.raises(DoubleSpend):
|
||||
tx_transfer_signed.validate(b)
|
||||
|
||||
|
||||
# TRANSFER divisible asset
|
||||
# Multiple inputs
|
||||
@ -382,7 +408,7 @@ def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(alice, b, user_pk,
|
||||
asset_id=tx_create.id)
|
||||
tx_transfer_signed = tx_transfer.sign([alice.private_key, user_sk])
|
||||
|
||||
b.store_bulk_transactions([tx_create_signed, tx_transfer_signed])
|
||||
b.store_bulk_transactions([tx_create_signed])
|
||||
|
||||
assert tx_transfer_signed.validate(b) == tx_transfer_signed
|
||||
assert len(tx_transfer_signed.outputs) == 2
|
||||
@ -402,6 +428,10 @@ def test_muiltiple_in_mix_own_multiple_out_mix_own_transfer(alice, b, user_pk,
|
||||
assert 'subconditions' in ffill_fid1
|
||||
assert len(ffill_fid1['subconditions']) == 2
|
||||
|
||||
b.store_bulk_transactions([tx_transfer_signed])
|
||||
with pytest.raises(DoubleSpend):
|
||||
tx_transfer_signed.validate(b)
|
||||
|
||||
|
||||
# TRANSFER divisible asset
|
||||
# Multiple inputs from different transactions
|
||||
@ -436,7 +466,7 @@ def test_multiple_in_different_transactions(alice, b, user_pk, user_sk):
|
||||
asset_id=tx_create.id)
|
||||
tx_transfer2_signed = tx_transfer2.sign([user_sk])
|
||||
|
||||
b.store_bulk_transactions([tx_create_signed, tx_transfer1_signed, tx_transfer2_signed])
|
||||
b.store_bulk_transactions([tx_create_signed, tx_transfer1_signed])
|
||||
|
||||
assert tx_transfer2_signed.validate(b) == tx_transfer2_signed
|
||||
assert len(tx_transfer2_signed.outputs) == 1
|
||||
@ -501,10 +531,14 @@ def test_threshold_same_public_key(alice, b, user_pk, user_sk):
|
||||
asset_id=tx_create.id)
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk, user_sk])
|
||||
|
||||
b.store_bulk_transactions([tx_create_signed, tx_transfer_signed])
|
||||
b.store_bulk_transactions([tx_create_signed])
|
||||
|
||||
assert tx_transfer_signed.validate(b) == tx_transfer_signed
|
||||
|
||||
b.store_bulk_transactions([tx_transfer_signed])
|
||||
with pytest.raises(DoubleSpend):
|
||||
tx_transfer_signed.validate(b)
|
||||
|
||||
|
||||
def test_sum_amount(alice, b, user_pk, user_sk):
|
||||
from bigchaindb.models import Transaction
|
||||
@ -520,12 +554,16 @@ def test_sum_amount(alice, b, user_pk, user_sk):
|
||||
asset_id=tx_create.id)
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
|
||||
b.store_bulk_transactions([tx_create_signed, tx_transfer_signed])
|
||||
b.store_bulk_transactions([tx_create_signed])
|
||||
|
||||
assert tx_transfer_signed.validate(b) == tx_transfer_signed
|
||||
assert len(tx_transfer_signed.outputs) == 1
|
||||
assert tx_transfer_signed.outputs[0].amount == 3
|
||||
|
||||
b.store_bulk_transactions([tx_transfer_signed])
|
||||
with pytest.raises(DoubleSpend):
|
||||
tx_transfer_signed.validate(b)
|
||||
|
||||
|
||||
def test_divide(alice, b, user_pk, user_sk):
|
||||
from bigchaindb.models import Transaction
|
||||
@ -541,9 +579,13 @@ def test_divide(alice, b, user_pk, user_sk):
|
||||
asset_id=tx_create.id)
|
||||
tx_transfer_signed = tx_transfer.sign([user_sk])
|
||||
|
||||
b.store_bulk_transactions([tx_create_signed, tx_transfer_signed])
|
||||
b.store_bulk_transactions([tx_create_signed])
|
||||
|
||||
assert tx_transfer_signed.validate(b) == tx_transfer_signed
|
||||
assert len(tx_transfer_signed.outputs) == 3
|
||||
for output in tx_transfer_signed.outputs:
|
||||
assert output.amount == 1
|
||||
|
||||
b.store_bulk_transactions([tx_transfer_signed])
|
||||
with pytest.raises(DoubleSpend):
|
||||
tx_transfer_signed.validate(b)
|
||||
|
Loading…
x
Reference in New Issue
Block a user