This commit is contained in:
Scott Sadler 2017-01-26 14:24:20 +01:00
parent c4cf0a5231
commit 27dbf6157d
2 changed files with 36 additions and 0 deletions

View File

@ -79,6 +79,11 @@ class Transaction(Transaction):
raise AmountError('`amount` needs to be greater than zero')
input_amount += input_tx.conditions[input_cid].amount
# Validate that all inputs are distinct
links = [(f.tx_input.txid, f.tx_input.cid) for f in self.fulfillments]
if len(links) != len(set(links)):
raise DoubleSpend('tx "{}" spends inputs twice'.format(self.id))
# validate asset id
asset_id = Asset.get_asset_id(input_txs)
if asset_id != self.asset.data_id:

View File

@ -1178,3 +1178,34 @@ class TestMultipleInputs(object):
# check that the other remain marked as unspent
for unspent in transactions[1:]:
assert b.get_spent(unspent.id, 0) is None
def test_cant_spend_same_input_twice_in_tx(b):
"""
Recreate duplicated fulfillments bug
https://github.com/bigchaindb/bigchaindb/issues/1099
"""
from bigchaindb.models import Asset, Transaction
from bigchaindb.common.exceptions import DoubleSpend
# create a divisible asset
tx_create = Transaction.create([b.me], [([b.me], 100)],
asset=Asset(divisible=True))
tx_create_signed = tx_create.sign([b.me_private])
assert b.validate_transaction(tx_create_signed) == tx_create_signed
## create a block and valid vote
b.create_genesis_block()
block = b.create_block([tx_create_signed])
b.write_block(block, durability='hard')
vote = b.vote(block.id, b.get_last_voted_block().id, True)
b.write_vote(vote)
# Create a transfer transaction with duplicated fulfillments
dup_inputs = tx_create.to_inputs() + tx_create.to_inputs()
tx_transfer = Transaction.transfer(dup_inputs, [([b.me], 200)],
asset=tx_create_signed.asset)
tx_transfer_signed = tx_transfer.sign([b.me_private])
assert b.is_valid_transaction(tx_transfer_signed) is False
with pytest.raises(DoubleSpend):
tx_transfer_signed.validate(b)