change fulfills.idx to fulfills.output

This commit is contained in:
Scott Sadler 2016-12-15 12:05:02 +01:00
parent d479a186a4
commit 4e17fe5c3d
7 changed files with 35 additions and 35 deletions

View File

@ -95,13 +95,13 @@ def get_asset_by_id(connection, asset_id):
@register_query(RethinkDBConnection)
def get_spent(connection, transaction_id, output_id):
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, 'idx': output_id})))
lambda input: input['fulfills'] == {'txid': transaction_id, 'output': output})))
@register_query(RethinkDBConnection)

View File

@ -214,10 +214,10 @@ definitions:
Reference to the output that is being spent.
additionalProperties: false
required:
- idx
- output
- txid
properties:
idx:
output:
"$ref": "#/definitions/offset"
description: |
Index of the output containing the condition being fulfilled

View File

@ -132,11 +132,11 @@ class TransactionLink(object):
Attributes:
txid (str, optional): A Transaction to link to.
idx (int, optional): An output's index in a Transaction with id
output (int, optional): An output's index in a Transaction with id
`txid`.
"""
def __init__(self, txid=None, idx=None):
def __init__(self, txid=None, output=None):
"""Create an instance of a :class:`~.TransactionLink`.
Note:
@ -144,18 +144,18 @@ class TransactionLink(object):
as an IPLD link can simply point to an object, as well as an
objects properties. So instead of having a (de)serializable
class, we can have a simple IPLD link of the form:
`/<tx_id>/transaction/outputs/<idx>/`.
`/<tx_id>/transaction/outputs/<output>/`.
Args:
txid (str, optional): A Transaction to link to.
idx (int, optional): An Outputs's index in a Transaction with
output (int, optional): An Outputs's index in a Transaction with
id `txid`.
"""
self.txid = txid
self.idx = idx
self.output = output
def __bool__(self):
return self.txid is not None and self.idx is not None
return self.txid is not None and self.output is not None
def __eq__(self, other):
# TODO: If `other !== TransactionLink` return `False`
@ -172,7 +172,7 @@ class TransactionLink(object):
:class:`~bigchaindb.common.transaction.TransactionLink`
"""
try:
return cls(link['txid'], link['idx'])
return cls(link['txid'], link['output'])
except TypeError:
return cls()
@ -182,12 +182,12 @@ class TransactionLink(object):
Returns:
(dict|None): The link as an alternative serialization format.
"""
if self.txid is None and self.idx is None:
if self.txid is None and self.output is None:
return None
else:
return {
'txid': self.txid,
'idx': self.idx,
'output': self.output,
}
def to_uri(self, path=''):

View File

@ -356,7 +356,7 @@ class Bigchain(object):
if cursor:
return Asset.from_dict(cursor[0]['asset'])
def get_spent(self, txid, idx):
def get_spent(self, txid, output):
"""Check if a `txid` was already used as an input.
A transaction can be used as an input for another transaction. Bigchain needs to make sure that a
@ -364,7 +364,7 @@ class Bigchain(object):
Args:
txid (str): The id of the transaction
idx (num): the index of the output in the respective transaction
output (num): the index of the output in the respective transaction
Returns:
The transaction (Transaction) that used the `txid` as an input else
@ -372,8 +372,8 @@ class Bigchain(object):
"""
# checks if an input was already spent
# checks if the bigchain has any transaction with input {'txid': ...,
# 'idx': ...}
transactions = list(backend.query.get_spent(self.connection, txid, idx))
# 'output': ...}
transactions = list(backend.query.get_spent(self.connection, txid, output))
# a transaction_id should have been spent at most one time
if transactions:
@ -405,7 +405,7 @@ class Bigchain(object):
owner (str): base58 encoded public key.
Returns:
:obj:`list` of TransactionLink: list of ``txid`` s and ``idx`` s
:obj:`list` of TransactionLink: list of ``txid`` s and ``output`` s
pointing to another transaction's condition
"""
@ -437,7 +437,7 @@ class Bigchain(object):
if util.condition_details_has_owner(output['condition']['details'], owner):
tx_link = TransactionLink(tx['id'], index)
# check if input was already spent
if not self.get_spent(tx_link.txid, tx_link.idx):
if not self.get_spent(tx_link.txid, tx_link.output):
owned.append(tx_link)
return owned

View File

@ -56,7 +56,6 @@ class Transaction(Transaction):
input_amount = 0
for input in self.inputs:
input_txid = input.fulfills.txid
input_idx = input.fulfills.idx
input_tx, status = bigchain.\
get_transaction(input_txid, include_status=True)
@ -69,16 +68,17 @@ class Transaction(Transaction):
'input `{}` does not exist in a valid block'.format(
input_txid))
spent = bigchain.get_spent(input_txid, input_idx)
spent = bigchain.get_spent(input_txid, input.fulfills.output)
if spent and spent.id != self.id:
raise DoubleSpend('input `{}` was already spent'
.format(input_txid))
input_conditions.append(input_tx.outputs[input_idx])
output = input_tx.outputs[input.fulfills.output]
input_conditions.append(output)
input_txs.append(input_tx)
if input_tx.outputs[input_idx].amount < 1:
if output.amount < 1:
raise AmountError('`amount` needs to be greater than zero')
input_amount += input_tx.outputs[input_idx].amount
input_amount += output.amount
# validate asset id
asset_id = Asset.get_asset_id(input_txs)

View File

@ -387,7 +387,7 @@ def test_transaction_link_serialization():
tx_id = 'a transaction id'
expected = {
'txid': tx_id,
'idx': 0,
'output': 0,
}
tx_link = TransactionLink(tx_id, 0)
@ -410,7 +410,7 @@ def test_transaction_link_deserialization():
expected = TransactionLink(tx_id, 0)
tx_link = {
'txid': tx_id,
'idx': 0,
'output': 0,
}
tx_link = TransactionLink.from_dict(tx_link)
@ -896,7 +896,7 @@ def test_outputs_to_inputs(tx):
assert input.owners_before == tx.outputs[0].public_keys
assert input.fulfillment == tx.outputs[0].fulfillment
assert input.fulfills.txid == tx.id
assert input.fulfills.idx == 0
assert input.fulfills.output == 0
def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub,
@ -921,7 +921,7 @@ def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub,
'fulfillment': None,
'fulfills': {
'txid': tx.id,
'idx': 0
'output': 0
}
}
],
@ -970,7 +970,7 @@ def test_create_transfer_transaction_multiple_io(user_pub, user_priv,
'fulfillment': None,
'fulfills': {
'txid': tx.id,
'idx': 0
'output': 0
}
}, {
'owners_before': [
@ -979,7 +979,7 @@ def test_create_transfer_transaction_multiple_io(user_pub, user_priv,
'fulfillment': None,
'fulfills': {
'txid': tx.id,
'idx': 1
'output': 1
}
}
],

View File

@ -1025,7 +1025,7 @@ class TestMultipleInputs(object):
# check spents
input_txid = owned_inputs_user1.txid
input_idx = owned_inputs_user1.idx
input_idx = owned_inputs_user1.output
spent_inputs_user1 = b.get_spent(input_txid, input_idx)
assert spent_inputs_user1 is None
@ -1061,7 +1061,7 @@ class TestMultipleInputs(object):
# check spents
input_txid = owned_inputs_user1.txid
input_idx = owned_inputs_user1.idx
input_idx = owned_inputs_user1.output
spent_inputs_user1 = b.get_spent(input_txid, input_idx)
assert spent_inputs_user1 is None
@ -1105,7 +1105,7 @@ class TestMultipleInputs(object):
# check spents
for input_tx in owned_inputs_user1:
assert b.get_spent(input_tx.txid, input_tx.idx) is None
assert b.get_spent(input_tx.txid, input_tx.output) is None
# transfer the first 2 inputs
tx_transfer = Transaction.transfer(tx_create.to_inputs()[:2],
@ -1117,7 +1117,7 @@ class TestMultipleInputs(object):
# check that used inputs are marked as spent
for ffill in tx_create.to_inputs()[:2]:
spent_tx = b.get_spent(ffill.fulfills.txid, ffill.fulfills.idx)
spent_tx = b.get_spent(ffill.fulfills.txid, ffill.fulfills.output)
assert spent_tx == tx_transfer_signed
# check if remaining transaction that was unspent is also perceived
@ -1147,7 +1147,7 @@ class TestMultipleInputs(object):
# check spents
for input_tx in owned_inputs_user1:
assert b.get_spent(input_tx.txid, input_tx.idx) is None
assert b.get_spent(input_tx.txid, input_tx.output) is None
# create a transaction
tx = Transaction.transfer(transactions[0].to_inputs(),