mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
initial implementation of multi input support
This commit is contained in:
parent
4dcd25e8ac
commit
194bf8c6bd
@ -119,7 +119,7 @@ class BaseConsensusRules(AbstractConsensusRules):
|
||||
# If the operation is CREATE the transaction should have no inputs and
|
||||
# should be signed by a federation node
|
||||
if transaction['transaction']['operation'] == 'CREATE':
|
||||
if transaction['transaction']['input']:
|
||||
if transaction['transaction']['inputs']:
|
||||
raise ValueError('A CREATE operation has no inputs')
|
||||
if transaction['transaction']['current_owner'] not in (
|
||||
bigchain.federation_nodes + [bigchain.me]):
|
||||
@ -128,32 +128,32 @@ class BaseConsensusRules(AbstractConsensusRules):
|
||||
|
||||
else:
|
||||
# check if the input exists, is owned by the current_owner
|
||||
if not transaction['transaction']['input']:
|
||||
if not transaction['transaction']['inputs']:
|
||||
raise ValueError(
|
||||
'Only `CREATE` transactions can have null inputs')
|
||||
|
||||
tx_input = bigchain.get_transaction(
|
||||
transaction['transaction']['input'])
|
||||
# check inputs
|
||||
for inp in transaction['transaction']['inputs']:
|
||||
tx_input = bigchain.get_transaction(inp)
|
||||
|
||||
if not tx_input:
|
||||
raise exceptions.TransactionDoesNotExist(
|
||||
'input `{}` does not exist in the bigchain'.format(
|
||||
transaction['transaction']['input']))
|
||||
if not tx_input:
|
||||
raise exceptions.TransactionDoesNotExist(
|
||||
'input `{}` does not exist in the bigchain'.format(
|
||||
transaction['transaction']['input']))
|
||||
|
||||
if (tx_input['transaction']['new_owner'] !=
|
||||
transaction['transaction']['current_owner']):
|
||||
raise exceptions.TransactionOwnerError(
|
||||
'current_owner `{}` does not own the input `{}`'.format(
|
||||
transaction['transaction']['current_owner'],
|
||||
transaction['transaction']['input']))
|
||||
if (tx_input['transaction']['new_owner'] !=
|
||||
transaction['transaction']['current_owner']):
|
||||
raise exceptions.TransactionOwnerError(
|
||||
'current_owner `{}` does not own the input `{}`'.format(
|
||||
transaction['transaction']['current_owner'],
|
||||
transaction['transaction']['input']))
|
||||
|
||||
# check if the input was already spent by a transaction other than
|
||||
# this one.
|
||||
spent = bigchain.get_spent(tx_input['id'])
|
||||
if spent and spent['id'] != transaction['id']:
|
||||
raise exceptions.DoubleSpend(
|
||||
'input `{}` was already spent'.format(
|
||||
transaction['transaction']['input']))
|
||||
# check if the input was already spent by a transaction other than
|
||||
# this one.
|
||||
spent = bigchain.get_spent(tx_input['id'])
|
||||
if spent and spent['id'] != transaction['id']:
|
||||
raise exceptions.DoubleSpend(
|
||||
'input `{}` was already spent'.format(inp))
|
||||
|
||||
# Check hash of the transaction
|
||||
calculated_hash = hash_data(util.serialize(
|
||||
|
@ -203,7 +203,7 @@ class Bigchain(object):
|
||||
# checks if an input was already spent
|
||||
# checks if the bigchain has any transaction with input `transaction_id`
|
||||
response = r.table('bigchain').concat_map(lambda doc: doc['block']['transactions'])\
|
||||
.filter(lambda transaction: transaction['transaction']['input'] == txid).run(self.conn)
|
||||
.filter(lambda transaction: transaction['transaction']['inputs'].contains(txid)).run(self.conn)
|
||||
|
||||
# a transaction_id should have been spent at most one time
|
||||
transactions = list(response)
|
||||
|
@ -76,7 +76,7 @@ def timestamp():
|
||||
return "{0:.6f}".format(time.mktime(dt.timetuple()) + dt.microsecond / 1e6)
|
||||
|
||||
|
||||
def create_tx(current_owner, new_owner, tx_input, operation, payload=None):
|
||||
def create_tx(current_owner, new_owner, inputs, operation, payload=None):
|
||||
"""Create a new transaction
|
||||
|
||||
A transaction in the bigchain is a transfer of a digital asset between two entities represented
|
||||
@ -94,7 +94,7 @@ def create_tx(current_owner, new_owner, tx_input, operation, payload=None):
|
||||
Args:
|
||||
current_owner (str): base58 encoded public key of the current owner of the asset.
|
||||
new_owner (str): base58 encoded public key of the new owner of the digital asset.
|
||||
tx_input (str): id of the transaction to use as input.
|
||||
inputs (list): id of the transaction to use as input.
|
||||
operation (str): Either `CREATE` or `TRANSFER` operation.
|
||||
payload (Optional[dict]): dictionary with information about asset.
|
||||
|
||||
@ -106,6 +106,7 @@ def create_tx(current_owner, new_owner, tx_input, operation, payload=None):
|
||||
TypeError: if the optional ``payload`` argument is not a ``dict``.
|
||||
"""
|
||||
|
||||
# handle payload
|
||||
data = None
|
||||
if payload is not None:
|
||||
if isinstance(payload, dict):
|
||||
@ -123,10 +124,13 @@ def create_tx(current_owner, new_owner, tx_input, operation, payload=None):
|
||||
'payload': payload
|
||||
}
|
||||
|
||||
if inputs == []:
|
||||
inputs = None
|
||||
|
||||
tx = {
|
||||
'current_owner': current_owner,
|
||||
'new_owner': new_owner,
|
||||
'input': tx_input,
|
||||
'inputs': inputs,
|
||||
'operation': operation,
|
||||
'timestamp': timestamp(),
|
||||
'data': data
|
||||
|
@ -756,3 +756,16 @@ class TestBigchainBlock(object):
|
||||
|
||||
def test_duplicated_transactions(self):
|
||||
pytest.skip('We may have duplicates in the initial_results and changefeed')
|
||||
|
||||
|
||||
class TestMultipleInputs(object):
|
||||
|
||||
def test_transfer_transaction_multiple(self, b):
|
||||
pass
|
||||
|
||||
def test_transfer_single_input_from_multi_input(self, b):
|
||||
pass
|
||||
|
||||
def test_get_spent(self, b):
|
||||
pass
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user