Merge remote-tracking branch 'remotes/origin/feat/128/multiple-input-output' into feat/127/crypto-conditions-ilp-bigchain-integration

Conflicts:
	bigchaindb/consensus.py
	bigchaindb/util.py
This commit is contained in:
diminator 2016-04-06 16:27:56 +02:00
commit ce945e3409
No known key found for this signature in database
GPG Key ID: C3D8590E6D0D439A
3 changed files with 43 additions and 12 deletions

View File

@ -1,3 +1,4 @@
import copy
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
import bigchaindb.exceptions as exceptions import bigchaindb.exceptions as exceptions
@ -119,9 +120,11 @@ class BaseConsensusRules(AbstractConsensusRules):
# If the operation is CREATE the transaction should have no inputs and # If the operation is CREATE the transaction should have no inputs and
# should be signed by a federation node # should be signed by a federation node
if transaction['transaction']['operation'] == 'CREATE': if transaction['transaction']['operation'] == 'CREATE':
if transaction['transaction']['inputs']: # TODO: for now lets assume a CREATE transaction only has one fulfillment
if transaction['transaction']['fulfillments'][0]['input']:
raise ValueError('A CREATE operation has no inputs') raise ValueError('A CREATE operation has no inputs')
if transaction['transaction']['current_owner'] not in ( # TODO: fow now lets assume a CREATE transaction only has one current_owner
if transaction['transaction']['fulfillments'][0]['current_owners'][0] not in (
bigchain.federation_nodes + [bigchain.me]): bigchain.federation_nodes + [bigchain.me]):
raise exceptions.OperationError( raise exceptions.OperationError(
'Only federation nodes can use the operation `CREATE`') 'Only federation nodes can use the operation `CREATE`')
@ -156,6 +159,11 @@ class BaseConsensusRules(AbstractConsensusRules):
'input `{}` was already spent'.format(inp)) 'input `{}` was already spent'.format(inp))
# Check hash of the transaction # Check hash of the transaction
# remove the fulfillment messages (signatures)
transaction_data = copy.deepcopy(transaction)
for fulfillment in transaction_data['transaction']['fulfillments']:
fulfillment['fulfillment'] = None
calculated_hash = crypto.hash_data(util.serialize( calculated_hash = crypto.hash_data(util.serialize(
transaction['transaction'])) transaction['transaction']))
if calculated_hash != transaction['id']: if calculated_hash != transaction['id']:

View File

@ -388,7 +388,7 @@ class Bigchain(object):
raise GenesisBlockAlreadyExistsError('Cannot create the Genesis block') raise GenesisBlockAlreadyExistsError('Cannot create the Genesis block')
payload = {'message': 'Hello World from the BigchainDB'} payload = {'message': 'Hello World from the BigchainDB'}
transaction = self.create_transaction(self.me, self.me, None, 'GENESIS', payload=payload) transaction = self.create_transaction([self.me], [self.me], None, 'GENESIS', payload=payload)
transaction_signed = self.sign_transaction(transaction, self.me_private) transaction_signed = self.sign_transaction(transaction, self.me_private)
# create the block # create the block

View File

@ -239,7 +239,7 @@ def sign_tx(transaction, private_key):
for fulfillment in transaction['transaction']['fulfillments']: for fulfillment in transaction['transaction']['fulfillments']:
fulfillment_message = common_data.copy() fulfillment_message = common_data.copy()
if transaction['transaction']['operation'] == 'CREATE': if transaction['transaction']['operation'] in ['CREATE', 'GENESIS']:
fulfillment_message.update({ fulfillment_message.update({
'input': None, 'input': None,
'condition': None 'condition': None
@ -279,6 +279,7 @@ def check_hash_and_signature(transaction):
def verify_signature(signed_transaction): def verify_signature(signed_transaction):
# TODO: The name should change. This will be the validation of the fulfillments
"""Verify the signature of a transaction """Verify the signature of a transaction
A valid transaction should have been signed `current_owner` corresponding private key. A valid transaction should have been signed `current_owner` corresponding private key.
@ -290,16 +291,38 @@ def verify_signature(signed_transaction):
bool: True if the signature is correct, False otherwise. bool: True if the signature is correct, False otherwise.
""" """
data = signed_transaction.copy() b = bigchaindb.Bigchain()
# if assignee field in the transaction, remove it common_data = {
if 'assignee' in data: 'operation': signed_transaction['transaction']['operation'],
data.pop('assignee') 'timestamp': signed_transaction['transaction']['timestamp'],
'data': signed_transaction['transaction']['data'],
'version': signed_transaction['version'],
'id': signed_transaction['id']
}
signature = data.pop('signature') for fulfillment in signed_transaction['transaction']['fulfillments']:
public_key_base58 = signed_transaction['transaction']['current_owner'] fulfillment_message = common_data.copy()
public_key = crypto.VerifyingKey(public_key_base58) fulfillment_message.update({
return public_key.verify(serialize(data), signature) 'input': fulfillment['input'],
'condition': None,
})
# if not a `CREATE` transaction
if fulfillment['input']:
# get previous condition
previous_tx = b.get_transaction(fulfillment['input']['txid'])
conditions = sorted(previous_tx['transaction']['conditions'], key=lambda d: d['cid'])
fulfillment_message['condition'] = conditions[fulfillment['cid']]
# verify the signature (for now lets assume there is only one owner)
vk = crypto.VerifyingKey(fulfillment['current_owners'][0])
is_valid = vk.verify(serialize(fulfillment_message), fulfillment['fulfillment'])
if not is_valid:
return False
return True
def transform_create(tx): def transform_create(tx):