sign/verify with fulfillments for CREATE/GENESIS

This commit is contained in:
diminator 2016-04-08 10:56:45 +02:00
parent 66e3c9e8a9
commit cc0c56c150
No known key found for this signature in database
GPG Key ID: C3D8590E6D0D439A
2 changed files with 29 additions and 20 deletions

View File

@ -1,4 +1,4 @@
import copy
import json import json
import time import time
import multiprocessing as mp import multiprocessing as mp
@ -238,24 +238,24 @@ def sign_tx(transaction, sk):
""" """
b = bigchaindb.Bigchain() b = bigchaindb.Bigchain()
sk = crypto.SigningKey(sk) sk = crypto.SigningKey(sk)
tx = copy.deepcopy(transaction)
common_data = { common_data = {
'operation': transaction['transaction']['operation'], 'operation': tx['transaction']['operation'],
'timestamp': transaction['transaction']['timestamp'], 'timestamp': tx['transaction']['timestamp'],
'data': transaction['transaction']['data'], 'data': tx['transaction']['data'],
'version': transaction['version'], 'version': tx['version'],
'id': transaction['id'] 'id': tx['id']
} }
for fulfillment in transaction['transaction']['fulfillments']: for fulfillment in tx['transaction']['fulfillments']:
fulfillment_message = common_data.copy() fulfillment_message = common_data.copy()
if transaction['transaction']['operation'] in ['CREATE', 'GENESIS']: if tx['transaction']['operation'] in ['CREATE', 'GENESIS']:
fulfillment_message.update({ fulfillment_message.update({
'input': None, 'input': None,
'condition': None 'condition': None
}) })
# sign the fulfillment message # sign the fulfillment message
signed_fulfillment = sk.sign(serialize(fulfillment_message)) parsed_fulfillment = Ed25519Fulfillment(public_key=sk.get_verifying_key())
else: else:
# get previous condition # get previous condition
previous_tx = b.get_transaction(fulfillment['input']['txid']) previous_tx = b.get_transaction(fulfillment['input']['txid'])
@ -267,11 +267,11 @@ def sign_tx(transaction, sk):
'condition': conditions[fulfillment['fid']] 'condition': conditions[fulfillment['fid']]
}) })
parsed_fulfillment = Fulfillment.from_json(fulfillment_message['condition']['condition']['details']) parsed_fulfillment = Fulfillment.from_json(fulfillment_message['condition']['condition']['details'])
parsed_fulfillment.sign(serialize(fulfillment_message), sk) parsed_fulfillment.sign(serialize(fulfillment_message), sk)
signed_fulfillment = parsed_fulfillment.serialize_uri() signed_fulfillment = parsed_fulfillment.serialize_uri()
fulfillment.update({'fulfillment': signed_fulfillment}) fulfillment.update({'fulfillment': signed_fulfillment})
return transaction return tx
def create_and_sign_tx(private_key, current_owner, new_owner, tx_input, operation='TRANSFER', payload=None): def create_and_sign_tx(private_key, current_owner, new_owner, tx_input, operation='TRANSFER', payload=None):
@ -326,12 +326,18 @@ def verify_signature(signed_transaction):
previous_tx = b.get_transaction(fulfillment['input']['txid']) previous_tx = b.get_transaction(fulfillment['input']['txid'])
conditions = sorted(previous_tx['transaction']['conditions'], key=lambda d: d['cid']) conditions = sorted(previous_tx['transaction']['conditions'], key=lambda d: d['cid'])
fulfillment_message['condition'] = conditions[fulfillment['fid']] fulfillment_message['condition'] = conditions[fulfillment['fid']]
# verify the fulfillment (for now lets assume there is only one owner)
is_valid = Fulfillment.from_uri(fulfillment['fulfillment']).validate(serialize(fulfillment_message)) # verify the fulfillment (for now lets assume there is only one owner)
else: try:
# verify the signature (for now lets assume there is only one owner) parsed_fulfillment = Fulfillment.from_uri(fulfillment['fulfillment'])
vk = crypto.VerifyingKey(fulfillment['current_owners'][0]) except Exception:
is_valid = vk.verify(serialize(fulfillment_message), fulfillment['fulfillment']) return False
is_valid = parsed_fulfillment.validate(serialize(fulfillment_message))
# if not a `CREATE` transaction
if fulfillment['input']:
is_valid &= parsed_fulfillment.condition.serialize_uri() == \
fulfillment_message['condition']['condition']['uri']
if not is_valid: if not is_valid:
return False return False

View File

@ -36,6 +36,8 @@ class TestBigchainApi(object):
@pytest.mark.usefixtures('inputs') @pytest.mark.usefixtures('inputs')
def test_create_transaction_transfer(self, b, user_vk, user_sk): def test_create_transaction_transfer(self, b, user_vk, user_sk):
input_tx = b.get_owned_ids(user_vk).pop() input_tx = b.get_owned_ids(user_vk).pop()
assert b.verify_signature(b.get_transaction(input_tx)) == True
tx = b.create_transaction(b.me, user_sk, {'txid': input_tx, 'cid': 0}, 'TRANSFER') tx = b.create_transaction(b.me, user_sk, {'txid': input_tx, 'cid': 0}, 'TRANSFER')
assert sorted(tx) == sorted(['id', 'transaction', 'version']) assert sorted(tx) == sorted(['id', 'transaction', 'version'])
@ -43,7 +45,8 @@ class TestBigchainApi(object):
tx_signed = b.sign_transaction(tx, user_sk) tx_signed = b.sign_transaction(tx, user_sk)
b.verify_signature(tx) assert b.verify_signature(tx) == False
assert b.verify_signature(tx_signed) == True
def test_transaction_hash(self, b): def test_transaction_hash(self, b):
payload = {'cats': 'are awesome'} payload = {'cats': 'are awesome'}