def test_multiple_input_validation_of_transfer_tx(user_input, user_output, user_priv, user2_pub, user2_priv, user3_pub, user3_priv, asset_definition): from bigchaindb.common.transaction import (Transaction, TransactionLink, Input, Output) from cryptoconditions import Ed25519Sha256 from .utils import validate_transaction_model tx = Transaction(Transaction.CREATE, asset_definition, [user_input], [user_output, deepcopy(user_output)]) tx.sign([user_priv]) inputs = [ Input(cond.fulfillment, cond.public_keys, TransactionLink(tx.id, index)) for index, cond in enumerate(tx.outputs) ] outputs = [ Output(Ed25519Sha256(public_key=b58decode(user3_pub)), [user3_pub]), Output(Ed25519Sha256(public_key=b58decode(user3_pub)), [user3_pub]) ] transfer_tx = Transaction('TRANSFER', {'id': tx.id}, inputs, outputs) transfer_tx = transfer_tx.sign([user_priv]) assert transfer_tx.inputs_valid(tx.outputs) is True validate_transaction_model(tx)
def test_output_from_dict_invalid_amount(user_output): from bigchaindb.common.transaction import Output from bigchaindb.common.exceptions import AmountError out = user_output.to_dict() out['amount'] = 'a' with raises(AmountError): Output.from_dict(out)
def test_invalid_output_initialization(cond_uri, user_pub): from bigchaindb.common.transaction import Output from bigchaindb.common.exceptions import AmountError with raises(TypeError): Output(cond_uri, user_pub) with raises(TypeError): Output(cond_uri, [user_pub], 'amount') with raises(AmountError): Output(cond_uri, [user_pub], 0)
def test_generate_output_invalid_parameters(user_pub, user2_pub, user3_pub): from bigchaindb.common.transaction import Output from bigchaindb.common.exceptions import AmountError with raises(ValueError): Output.generate([], 1) with raises(TypeError): Output.generate('not a list', 1) with raises(ValueError): Output.generate([[user_pub, [user2_pub, [user3_pub]]]], 1) with raises(ValueError): Output.generate([[user_pub]], 1) with raises(AmountError): Output.generate([[user_pub]], -1)
def create_asset(vw_sk, vw_pk, vehicle_id, data, metadata): # Create asset VW -> [VW, TEL] # Custom crypto condition multisig 1-2 threshold_fulfillment = ThresholdSha256Fulfillment(threshold=1) vw_fulfillment = Ed25519Fulfillment(public_key=vw_pk) tel_fulfillment = Ed25519Fulfillment(public_key=vehicle_id) threshold_fulfillment.add_subfulfillment(vw_fulfillment) threshold_fulfillment.add_subfulfillment(tel_fulfillment) output = { 'amount': 1, 'condition': { 'details': threshold_fulfillment.to_dict(), 'uri': threshold_fulfillment.condition.serialize_uri() }, 'public_keys': [vw_pk, vehicle_id] } # Create the transaction tx_create = Transaction.create([vw_pk], [([vw_pk, vehicle_id], 1)], asset=data, metadata=metadata) # Override the condition we our custom build one tx_create.outputs[0] = Output.from_dict(output) # Sign the transaction tx_create_signed = tx_create.sign([vw_sk]) return tx_create_signed
def test_validate_tx_threshold_duplicated_pk(user_pub, user_priv, asset_definition): from cryptoconditions import Ed25519Sha256, ThresholdSha256 from bigchaindb.common.transaction import Input, Output, Transaction threshold = ThresholdSha256(threshold=2) threshold.add_subfulfillment(Ed25519Sha256(public_key=b58decode(user_pub))) threshold.add_subfulfillment(Ed25519Sha256(public_key=b58decode(user_pub))) threshold_input = Input(threshold, [user_pub, user_pub]) threshold_output = Output(threshold, [user_pub, user_pub]) tx = Transaction(Transaction.CREATE, asset_definition, [threshold_input], [threshold_output]) expected = deepcopy(threshold_input) expected.fulfillment.subconditions[0]['body'].sign( str(tx).encode(), b58decode(user_priv)) expected.fulfillment.subconditions[1]['body'].sign( str(tx).encode(), b58decode(user_priv)) tx.sign([user_priv, user_priv]) subconditions = tx.inputs[0].fulfillment.subconditions expected_subconditions = expected.fulfillment.subconditions assert subconditions[0]['body'].to_dict()['signature'] == \ expected_subconditions[0]['body'].to_dict()['signature'] assert subconditions[1]['body'].to_dict()['signature'] == \ expected_subconditions[1]['body'].to_dict()['signature'] assert tx.inputs[0].to_dict()['fulfillment'] == \ expected.fulfillment.serialize_uri() assert tx.inputs_valid() is True
def test_generate_output_single_owner_with_output(user_pub): from bigchaindb.common.transaction import Output from cryptoconditions import Ed25519Sha256 expected = Ed25519Sha256(public_key=b58decode(user_pub)) cond = Output.generate([expected], 1) assert cond.fulfillment.to_dict() == expected.to_dict()
def test_output_hashlock_serialization(): from bigchaindb.common.transaction import Output from cryptoconditions import PreimageSha256 secret = b'wow much secret' hashlock = PreimageSha256(preimage=secret).condition_uri expected = { 'condition': { 'uri': hashlock, }, 'public_keys': None, 'amount': '1', } cond = Output(hashlock, amount=1) assert cond.to_dict() == expected
def prepare_transfer(inputs, outputs, metadata=None): """Create an instance of a :class:`~.Output`. Args: inputs (list of (dict): { 'tx': <(bigchaindb.common.transactionTransaction): input transaction, can differ but must have same asset id>, 'output': <(int): output index of tx> } ) outputs (list of (dict): { 'condition': <(cryptoconditions.Condition): output condition>, 'public_keys': <(optional list of base58): for indexing defaults to `None`>, 'amount': <(int): defaults to `1`> } ) metadata (dict) Raises: TypeError: if `public_keys` is not instance of `list`. """ from bigchaindb.common.transaction import (Input, Output, TransactionLink) from bigchaindb.models import Transaction from cryptoconditions import (Fulfillment, Condition) asset = inputs[0]['tx']['asset'] asset = {'id': asset['id'] if 'id' in asset else inputs[0]['tx']['id']} _inputs, _outputs = [], [] for _input in inputs: _output = _input['tx']['outputs'][_input['output']] _inputs.append( Input(fulfillment=Condition.from_uri(_output['condition']['uri']), owners_before=_output['public_keys'], fulfills=TransactionLink(txid=_input['tx']['id'], output=_input['output']))) for output in outputs: _outputs.append( Output(fulfillment=output['condition'], public_keys=output['public_keys'] if "public_keys" in output else [], amount=output['amount'] if "amount" in output else 1)) return Transaction( operation='TRANSFER', asset=asset, inputs=_inputs, outputs=_outputs, metadata=metadata, )
def test_output_serialization(user_Ed25519, user_pub): from bigchaindb.common.transaction import Output expected = { 'condition': { 'uri': user_Ed25519.condition_uri, 'details': { 'type': 'ed25519-sha-256', 'public_key': b58encode(user_Ed25519.public_key).decode(), }, }, 'public_keys': [user_pub], 'amount': '1', } cond = Output(user_Ed25519, [user_pub], 1) assert cond.to_dict() == expected
def generate_output(amount, owner_after): """ Generate cryptooutputs from keys. Generates a Ed25119 output from a OWNER_AFTER or a ThresholdSha256 Output from more than one OWNER_AFTER. """ output = Output.generate(list(owner_after), amount=amount) click.echo(json.dumps(output.to_dict()))
def test_validate_inputs_of_transfer_tx_with_invalid_params( transfer_tx, cond_uri, utx, user2_pub, user_priv, ffill_uri): from bigchaindb.common.transaction import Output from cryptoconditions import Ed25519Sha256 invalid_out = Output(Ed25519Sha256.from_uri(ffill_uri), ['invalid']) assert transfer_tx.inputs_valid([invalid_out]) is False invalid_out = utx.outputs[0] invalid_out.public_key = 'invalid' assert transfer_tx.inputs_valid([invalid_out]) is True with raises(TypeError): assert transfer_tx.inputs_valid(None) is False with raises(AttributeError): transfer_tx.inputs_valid('not a list') with raises(ValueError): transfer_tx.inputs_valid([]) with raises(TypeError): transfer_tx.operation = "Operation that doesn't exist" transfer_tx.inputs_valid([utx.outputs[0]])
def create(owner_before, outputs, metadata, asset_data): """ Generate a CREATE transaction. The CREATE transaction creates a new asset. """ input_ = Input.generate([owner_before]) outputs = [Output.from_dict(c) for c in listify(outputs)] tx = Transaction(Transaction.CREATE, {'data': asset_data}, [input_], outputs, metadata) tx = Transaction._to_str(tx.to_dict()) click.echo(tx)
def transfer(inputs, outputs, asset, metadata): """ Generate a TRANSFER transaction. The TRANSFER transaction transfers ownership of a given asset. """ inputs = [Input.from_dict(i) for i in listify(inputs)] outputs = [Output.from_dict(i) for i in listify(outputs)] tx = Transaction(Transaction.TRANSFER, asset=asset, inputs=inputs, outputs=outputs, metadata=metadata) click.echo(Transaction._to_str(tx.to_dict()))
def test_generate_outputs_flat_ownage(user_pub, user2_pub, user3_pub): from bigchaindb.common.transaction import Output from cryptoconditions import Ed25519Sha256, ThresholdSha256 expected_simple1 = Ed25519Sha256(public_key=b58decode(user_pub)) expected_simple2 = Ed25519Sha256(public_key=b58decode(user2_pub)) expected_simple3 = Ed25519Sha256(public_key=b58decode(user3_pub)) expected = ThresholdSha256(threshold=3) expected.add_subfulfillment(expected_simple1) expected.add_subfulfillment(expected_simple2) expected.add_subfulfillment(expected_simple3) cond = Output.generate([user_pub, user2_pub, expected_simple3], 1) assert cond.fulfillment.to_dict() == expected.to_dict()
def test_validate_tx_threshold_duplicated_pk(user_pub, user_priv, asset_definition): from cryptoconditions import Ed25519Sha256, ThresholdSha256 from bigchaindb.common.transaction import Input, Output, Transaction threshold = ThresholdSha256(threshold=2) threshold.add_subfulfillment(Ed25519Sha256(public_key=b58decode(user_pub))) threshold.add_subfulfillment(Ed25519Sha256(public_key=b58decode(user_pub))) threshold_input = Input(threshold, [user_pub, user_pub]) threshold_output = Output(threshold, [user_pub, user_pub]) tx = Transaction(Transaction.CREATE, asset_definition, [threshold_input], [threshold_output]) tx_dict = tx.to_dict() tx_dict['inputs'][0]['fulfillment'] = None serialized_tx = json.dumps(tx_dict, sort_keys=True, separators=(',', ':'), ensure_ascii=True) message = sha3_256(serialized_tx.encode()).digest() expected = deepcopy(threshold_input) expected.fulfillment.subconditions[0]['body'].sign(message, b58decode(user_priv)) expected.fulfillment.subconditions[1]['body'].sign(message, b58decode(user_priv)) tx.sign([user_priv, user_priv]) subconditions = tx.inputs[0].fulfillment.subconditions expected_subconditions = expected.fulfillment.subconditions assert subconditions[0]['body'].to_dict()['signature'] == \ expected_subconditions[0]['body'].to_dict()['signature'] assert subconditions[1]['body'].to_dict()['signature'] == \ expected_subconditions[1]['body'].to_dict()['signature'] assert tx.inputs[0].to_dict()['fulfillment'] == \ expected.fulfillment.serialize_uri() assert tx.inputs_valid() is True
def user2_output(user2_Ed25519, user2_pub): from bigchaindb.common.transaction import Output return Output(user2_Ed25519, [user2_pub])
def user_user2_threshold_output(user_user2_threshold, user_pub, user2_pub): from bigchaindb.common.transaction import Output return Output(user_user2_threshold, [user_pub, user2_pub])