def validate_transaction_model(tx): from bigchaindb.common.transaction import Transaction from bigchaindb.common.schema import validate_transaction_schema tx_dict = tx.to_dict() # Check that a transaction is valid by re-serializing it # And calling validate_transaction_schema validate_transaction_schema(tx_dict) Transaction.from_dict(tx_dict)
def test_create_create_transaction_threshold(user_pub, user2_pub, user3_pub, user_user2_threshold_output, user_user2_threshold_input, data): from bigchaindb.common.transaction import Transaction expected = { 'outputs': [user_user2_threshold_output.to_dict()], 'metadata': data, 'asset': { 'data': data, }, 'inputs': [ { 'owners_before': [ user_pub, ], 'fulfillment': None, 'fulfills': None, }, ], 'operation': 'CREATE', 'version': Transaction.VERSION } tx = Transaction.create([user_pub], [([user_pub, user2_pub], 1)], metadata=data, asset=data) tx_dict = tx.to_dict() tx_dict.pop('id') tx_dict['inputs'][0]['fulfillment'] = None assert tx_dict == expected
def test_create_create_transaction_multiple_io(user_output, user2_output, user_pub, user2_pub, asset_definition): from bigchaindb.common.transaction import Transaction, Input # a fulfillment for a create transaction with multiple `owners_before` # is a fulfillment for an implicit threshold condition with # weight = len(owners_before) input = Input.generate([user_pub, user2_pub]).to_dict() expected = { 'outputs': [user_output.to_dict(), user2_output.to_dict()], 'metadata': { 'message': 'hello' }, 'inputs': [input], 'operation': 'CREATE', 'version': Transaction.VERSION } tx = Transaction.create([user_pub, user2_pub], [([user_pub], 1), ([user2_pub], 1)], metadata={ 'message': 'hello' }).to_dict() tx.pop('id') tx.pop('asset') assert tx == expected
def test_validate_single_io_create_transaction(user_pub, user_priv, data, asset_definition): from bigchaindb.common.transaction import Transaction tx = Transaction.create([user_pub], [([user_pub], 1)], metadata=data) tx = tx.sign([user_priv]) assert tx.inputs_valid() is True
def test_create_create_transaction_single_io(user_output, user_pub, data): from bigchaindb.common.transaction import Transaction from .utils import validate_transaction_model expected = { 'outputs': [user_output.to_dict()], 'metadata': data, 'asset': { 'data': data, }, 'inputs': [{ 'owners_before': [user_pub], 'fulfillment': None, 'fulfills': None }], 'operation': 'CREATE', 'version': Transaction.VERSION, } tx = Transaction.create([user_pub], [([user_pub], 1)], metadata=data, asset=data) tx_dict = tx.to_dict() tx_dict['inputs'][0]['fulfillment'] = None tx_dict.pop('id') assert tx_dict == expected validate_transaction_model(tx)
def test_unspent_outputs_property(merlin, alice, bob, carol): from bigchaindb.common.transaction import Transaction tx = Transaction.create( [merlin.public_key], [([alice.public_key], 1), ([bob.public_key], 2), ([carol.public_key], 3)], asset={ 'hash': '06e47bcf9084f7ecfd2a2a2ad275444a' }, ).sign([merlin.private_key]) unspent_outputs = list(tx.unspent_outputs) assert len(unspent_outputs) == 3 assert all(utxo.transaction_id == tx.id for utxo in unspent_outputs) assert all(utxo.asset_id == tx.id for utxo in unspent_outputs) assert all(utxo.output_index == i for i, utxo in enumerate(unspent_outputs)) unspent_output_0 = unspent_outputs[0] assert unspent_output_0.amount == 1 assert unspent_output_0.condition_uri == Ed25519Sha256( public_key=b58decode(alice.public_key)).condition_uri unspent_output_1 = unspent_outputs[1] assert unspent_output_1.amount == 2 assert unspent_output_1.condition_uri == Ed25519Sha256( public_key=b58decode(bob.public_key)).condition_uri unspent_output_2 = unspent_outputs[2] assert unspent_output_2.amount == 3 assert unspent_output_2.condition_uri == Ed25519Sha256( public_key=b58decode(carol.public_key)).condition_uri
def alice_transaction_obj(alice_pubkey): serial_number = b64encode(urandom(10), altchars=b'-_').decode() return Transaction.create( tx_signers=[alice_pubkey], recipients=[([alice_pubkey], 1)], asset={'serial_number': serial_number}, )
def get(): # Cryptographic Identities Generation alice, bob = generate_keypair(), generate_keypair() print(" ") # Digital Asset Definition (e.g. bicycle) asset = Asset(data={ "bicycle": { "manufacturer": "bkfab", "serial_number": "abcd1234" } }) # Metadata Definition metadata = {'planet': 'earth'} # create trnsaction TODO : owners_before might be node_pubkey in v0.8.0 tx = Transaction.create([alice.public_key], [alice.public_key], metadata=metadata, asset=asset) # sign with private key tx = tx.sign([alice.private_key]) # get tx by id b = Bigchain() block = b.create_block([tx]) block_voters = block.to_dict()['block']['voters'] print(block_voters) tx_id = '2cb004cad29c0b79872646558f8c867a4c0aecbc4997f0917' tx = b.get_transaction(tx_id) print( "block status : ", b.block_election_status( '2257384a0cee8cf98bd82c3142dd38eee5c268c124b5b357b773b8c6c1fa1221', block_voters))
def transactions(): priv, pub = generate_key_pair() tx = Transaction.create([pub], [([pub], 1)]) while True: i = yield tx.to_dict() tx.asset = {'data': {'n': i}} tx.sign([priv])
def from_dict(cls, block_body): """Transform a Python dictionary to a Block object. Args: block_body (dict): A block dictionary to be transformed. Returns: :class:`~Block` Raises: InvalidHash: If the block's id is not corresponding to its data. """ # Validate block id block = block_body['block'] block_serialized = serialize(block) block_id = hash_data(block_serialized) if block_id != block_body['id']: raise InvalidHash() transactions = [Transaction.from_dict(tx) for tx in block['transactions']] signature = block_body.get('signature') return cls(transactions, block['node_pubkey'], block['timestamp'], block['voters'], signature)
def test_sign_tx(): tx = create_tx() signed = api.signTx({ 'tx': tx, 'keys': [sec], }) assert signed == Transaction.from_dict(tx).sign([sec]).to_dict()
def input_single_create(b): from bigchaindb.common.transaction import Transaction metadata = {'r': random.random()} tx = Transaction.create([b.me], [([b.me], 1)], metadata).sign([b.me_private]) b.write_transaction(tx) return tx
def fulfill_transaction(transaction, *, private_keys): """ Fulfills the given transaction. Args: transaction (dict): The transaction to be fulfilled. private_keys (:obj:`str` | :obj:`list` | :obj:`tuple`): One or more private keys to be used for fulfilling the transaction. Returns: dict: The fulfilled transaction payload, ready to be sent to a BigchainDB federation. Raises: :exc:`~.exceptions.MissingPrivateKeyError`: If a private key is missing. """ if not isinstance(private_keys, (list, tuple)): private_keys = [private_keys] # NOTE: Needed for the time being. See # https://github.com/bigchaindb/bigchaindb/issues/797 if isinstance(private_keys, tuple): private_keys = list(private_keys) transaction_obj = Transaction.from_dict(transaction) try: signed_transaction = transaction_obj.sign(private_keys) except KeypairMismatchException as exc: raise MissingPrivateKeyError('A private key is missing!') from exc return signed_transaction.to_dict()
def prepare_create_transaction(*, owners_before, owners_after=None, asset=None, metadata=None): """ Prepares a ``"CREATE"`` transaction payload, ready to be fulfilled. Args: owners_before (:obj:`list` | :obj:`tuple` | :obj:`str`): One or more public keys representing the issuer(s) of the asset being created. owners_after (:obj:`list` | :obj:`tuple` | :obj:`str`, optional): One or more public keys representing the new owner(s) of the asset being created. Defaults to ``None``. asset (:obj:`dict`, optional): The asset being created. Defaults to ``None``. metadata (:obj:`dict`, optional): Metadata associated with the transaction. Defaults to ``None``. Returns: dict: The prepared ``"CREATE"`` transaction. .. important:: If ``owners_after`` is not given, or evaluates to ``False``, it will be set equal to ``owners_before``:: if not owners_after: owners_after = owners_before """ if not isinstance(owners_before, (list, tuple)): owners_before = [owners_before] # NOTE: Needed for the time being. See # https://github.com/bigchaindb/bigchaindb/issues/797 elif isinstance(owners_before, tuple): owners_before = list(owners_before) # TODO: This will only work for non-divisible. If its a divisible asset # Transaction.create will raise an exception saying that divisible assets # need to have amount > 1. if not owners_after: owners_after = [(owners_before, 1)] elif not isinstance(owners_after, (list, tuple)): owners_after = [([owners_after], 1)] # NOTE: Needed for the time being. See # https://github.com/bigchaindb/bigchaindb/issues/797 elif isinstance(owners_after, tuple): owners_after = [(list(owners_after), 1)] asset = _normalize_asset(asset) transaction = Transaction.create( owners_before, owners_after, metadata=metadata, asset=asset, ) return transaction.to_dict()
def test_create_default_asset_on_tx_initialization(asset_definition): from bigchaindb.common.transaction import Transaction expected = {'data': None} tx = Transaction(Transaction.CREATE, asset=expected) asset = tx.asset assert asset == expected
def test_validate_input_with_invalid_parameters(utx): from bigchaindb.common.transaction import Transaction input_conditions = [out.fulfillment.condition_uri for out in utx.outputs] tx_dict = utx.to_dict() tx_serialized = Transaction._to_str(tx_dict) valid = utx._input_valid(utx.inputs[0], tx_serialized, input_conditions[0]) assert not valid
def test_validate_tx_simple_create_signature(user_input, user_output, user_priv, asset_definition): from bigchaindb.common.transaction import Transaction from .utils import validate_transaction_model tx = Transaction(Transaction.CREATE, asset_definition, [user_input], [user_output]) expected = deepcopy(user_output) message = str(tx).encode() expected.fulfillment.sign(message, b58decode(user_priv)) tx.sign([user_priv]) assert tx.inputs[0].to_dict()['fulfillment'] == \ expected.fulfillment.serialize_uri() assert tx.inputs_valid() is True validate_transaction_model(tx)
def test_fulfilled_transaction_serialized(fulfilled_transaction): from bigchaindb.common.transaction import Transaction tx_obj = Transaction.from_dict(fulfilled_transaction) expected = json.dumps(fulfilled_transaction, sort_keys=True, separators=(',', ':'), ensure_ascii=True) assert tx_obj.serialized == expected
def transfer_utx(user_output, user2_output, utx): from bigchaindb.common.transaction import (Input, TransactionLink, Transaction) user_output = user_output.to_dict() input = Input(utx.outputs[0].fulfillment, user_output['public_keys'], TransactionLink(utx.id, 0)) return Transaction('TRANSFER', {'id': utx.id}, [input], [user2_output])
def merge_utxo(alicepub, alicepriv, include_spent): asset = Asset(data={ "bicycle": { "manufacturer": "bkfab", "serial_number": "abcd1234" } }, data_id="334cd061-846b-4213-bd25-588e951def5f") metadata = {'planet': 'earth'} b = Bigchain() utxo = b.get_outputs_filtered_not_include_freeze(alicepub, include_spent) for u in utxo: # print(u) u.pop('details') print('userA unspent asset:') print(json.dumps(utxo, indent=4)) inputs = [] balance = 0 utxo = b.get_outputs_filtered_not_include_freeze(alicepub, include_spent) for i in utxo: f = Fulfillment.from_dict({ 'fulfillment': i['details'], 'input': { 'cid': i['cid'], 'txid': i['txid'], }, 'owners_before': [alicepub], }) inputs.append(f) balance += i['amount'] length = len(utxo) if balance <= 0: print('No need to merge, because of lack of balance') elif length <= 1: print('No need to merge, because utxo len = 1') else: tx = Transaction.transfer(inputs, [([alicepub], balance)], metadata=metadata, asset=asset) tx = tx.sign([alicepriv]) tx_id = tx.to_dict()['id'] # write to backlog b.write_transaction(tx) # wait 2 sec print("========userA merge multi-asset========") print("========wait for block and vote...========") sleep(5) # get tx by id tx = b.get_transaction(tx_id) print("merge txid:" + tx.to_dict()['id']) utxo = b.get_outputs_filtered_not_include_freeze(alicepub, include_spent) for u in utxo: # print(u) u.pop('details') print('userA unspent asset:') print(json.dumps(utxo, indent=4))
def bft(): # Cryptographic Identities Generation alice, bob = generate_keypair(), generate_keypair() print(" ") # Digital Asset Definition (e.g. bicycle) asset = Asset(data={ "bicycle": { "manufacturer": "bkfab", "serial_number": "abcd1234" } }) # Metadata Definition metadata = {'planet': 'earth'} # create trnsaction TODO : owners_before might be node_pubkey in v0.8.0 tx = Transaction.create([alice.public_key], [([alice.public_key], 1)], metadata=metadata, asset=asset) # sign with private key tx = tx.sign([alice.private_key]) tx_id = tx.to_dict()['id'] print("tx_id : ", tx_id) # create block b = Bigchain() block = b.create_block([tx]) print("valid block timestamp : ", block.to_dict()['block']['timestamp']) # tamper block block.timestamp = '1' print("tamper block.timestamp to 1 : ") block_id = block.to_dict()['id'] block_voters = block.to_dict()['block']['voters'] print("invalid block timestamp : ", block.to_dict()['block']['timestamp']) print("tamper_block_id : ", block_id) print("db response of block : ", b.write_block(block)) sleep(0) last_voted_id = b.get_last_voted_block().id vote = b.vote(block_id, last_voted_id, True) print("crate vote 'True' : ", vote) print("db response of vote : ", b.write_vote(vote)) print("tamper_block status : ", b.block_election_status(block_id, block_voters)) print("blocks_status_containing_tx : ", b.get_blocks_status_containing_tx(tx_id)) print("wait for 20 sec : ") sleep(20) print("blocks_status_containing_tx : ", b.get_blocks_status_containing_tx(tx_id)) print(" ")
def test_create_transfer_transaction_single_io(tx, user_pub, user2_pub, user2_output, user_priv): from bigchaindb.common.transaction import Transaction from bigchaindb.common.utils import serialize from .utils import validate_transaction_model expected = { 'outputs': [user2_output.to_dict()], 'metadata': None, 'asset': { 'id': tx.id, }, 'inputs': [{ 'owners_before': [user_pub], 'fulfillment': None, 'fulfills': { 'transaction_id': tx.id, 'output_index': 0 } }], 'operation': 'TRANSFER', 'version': Transaction.VERSION } inputs = tx.to_inputs([0]) transfer_tx = Transaction.transfer(inputs, [([user2_pub], 1)], asset_id=tx.id) transfer_tx = transfer_tx.sign([user_priv]) transfer_tx = transfer_tx.to_dict() expected_input = deepcopy(inputs[0]) expected['id'] = transfer_tx['id'] expected_input.fulfillment.sign( serialize(expected).encode(), b58decode(user_priv)) expected_ffill = expected_input.fulfillment.serialize_uri() transfer_ffill = transfer_tx['inputs'][0]['fulfillment'] assert transfer_ffill == expected_ffill transfer_tx = Transaction.from_dict(transfer_tx) assert transfer_tx.inputs_valid([tx.outputs[0]]) is True validate_transaction_model(transfer_tx)
def transactions(): priv, pub = generate_key_pair() tx = Transaction.create([pub], [([pub], 1)]) while True: i = yield tx.to_dict() tx.asset = Asset(data={'n': i}, data_id='20170628150000', divisible=True) tx.sign([priv])
def alice_transaction_obj(alice_pubkey): serial_number = b64encode(urandom(10), altchars=b'-_').decode() return Transaction.create( owners_before=[alice_pubkey], owners_after=[alice_pubkey], asset=Asset(data={'data': { 'serial_number': serial_number }}), )
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, Transaction, TransactionLink) 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 None, amount=output['amount'] if "amount" in output else 1)) return Transaction( operation='TRANSFER', asset=asset, inputs=_inputs, outputs=_outputs, metadata=metadata, )
def test_transaction_hash(fulfilled_transaction): from bigchaindb.common.transaction import Transaction tx_obj = Transaction.from_dict(fulfilled_transaction) assert tx_obj._id is None assert tx_obj.id is None thing_to_hash = json.dumps(fulfilled_transaction, sort_keys=True, separators=(',', ':'), ensure_ascii=True) expected_hash_id = sha3_256(thing_to_hash.encode()).hexdigest() tx_obj._hash() assert tx_obj._id == expected_hash_id assert tx_obj.id == expected_hash_id
def test_validate_threshold_create_transaction(user_pub, user_priv, user2_pub, data, asset_definition): from bigchaindb.common.transaction import Transaction from .utils import validate_transaction_model tx = Transaction.create([user_pub], [([user_pub, user2_pub], 1)], metadata=data) tx = tx.sign([user_priv]) assert tx.inputs_valid() is True validate_transaction_model(tx)
def spend(transaction, output_id): """ Convert a transaction's outputs to inputs. Convert outputs in TRANSACTION (json) to signable/spendable inputs. Outputs can individually be selected by passing one or more CONDITION_ID, as a JSON list. Otherwise, all outputs are converted. """ transaction = Transaction.from_dict(transaction) inputs = transaction.to_inputs(output_id) click.echo(json.dumps([i.to_dict() for i in inputs]))
def test_invalid_transaction_initialization(asset_definition): from bigchaindb.common.transaction import Transaction with raises(ValueError): Transaction(operation='invalid operation', asset=asset_definition) with raises(TypeError): Transaction(operation='CREATE', asset='invalid asset') with raises(TypeError): Transaction(operation='TRANSFER', asset={}) with raises(TypeError): Transaction( operation='CREATE', asset=asset_definition, outputs='invalid outputs' ) with raises(TypeError): Transaction( operation='CREATE', asset=asset_definition, outputs=[], inputs='invalid inputs' ) with raises(TypeError): Transaction( operation='CREATE', asset=asset_definition, outputs=[], inputs=[], metadata='invalid metadata' )
def test_validate_tx_threshold_create_signature(user_user2_threshold_input, user_user2_threshold_output, user_pub, user2_pub, user_priv, user2_priv, asset_definition): from bigchaindb.common.transaction import Transaction from .utils import validate_transaction_model tx = Transaction(Transaction.CREATE, asset_definition, [user_user2_threshold_input], [user_user2_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(user_user2_threshold_output) expected.fulfillment.subconditions[0]['body'].sign(message, b58decode(user_priv)) expected.fulfillment.subconditions[1]['body'].sign(message, b58decode(user2_priv)) tx.sign([user_priv, user2_priv]) assert tx.inputs[0].to_dict()['fulfillment'] == \ expected.fulfillment.serialize_uri() assert tx.inputs_valid() is True validate_transaction_model(tx)
def test_validate_multiple_io_create_transaction(user_pub, user_priv, user2_pub, user2_priv, asset_definition): from bigchaindb.common.transaction import Transaction from .utils import validate_transaction_model tx = Transaction.create([user_pub, user2_pub], [([user_pub], 1), ([user2_pub], 1)], metadata={'message': 'hello'}) tx = tx.sign([user_priv, user2_priv]) assert tx.inputs_valid() is True validate_transaction_model(tx)
def test_transaction_serialization(user_input, user_output, data): from bigchaindb.common.transaction import Transaction expected = { 'id': None, 'version': Transaction.VERSION, # NOTE: This test assumes that Inputs and Outputs can # successfully be serialized 'inputs': [user_input.to_dict()], 'outputs': [user_output.to_dict()], 'operation': Transaction.CREATE, 'metadata': None, 'asset': { 'data': data, } } tx = Transaction(Transaction.CREATE, {'data': data}, [user_input], [user_output]) tx_dict = tx.to_dict() assert tx_dict == expected
def from_dict(cls, block_body): """Transform a Python dictionary to a Block object. Args: block_body (dict): A block dictionary to be transformed. Returns: :class:`~Block` Raises: InvalidHash: If the block's id is not corresponding to its data. InvalidSignature: If the block's signature is not corresponding to it's data or `node_pubkey`. """ # TODO: Reuse `is_signature_valid` method here. block = block_body['block'] block_serialized = serialize(block) block_id = hash_data(block_serialized) public_key = PublicKey(block['node_pubkey']) try: signature = block_body['signature'] except KeyError: signature = None if block_id != block_body['id']: raise InvalidHash() if signature is not None: # NOTE: CC throws a `ValueError` on some wrong signatures # https://github.com/bigchaindb/cryptoconditions/issues/27 try: signature_valid = public_key\ .verify(block_serialized.encode(), signature) except ValueError: signature_valid = False if signature_valid is False: raise InvalidSignature('Invalid block signature') transactions = [Transaction.from_dict(tx) for tx in block['transactions']] return cls(transactions, block['node_pubkey'], block['timestamp'], block['voters'], signature)
'database': _database_map['localmongodb'], 'log': { 'file': log_config['handlers']['file']['filename'], 'error_file': log_config['handlers']['errors']['filename'], 'level_console': logging.getLevelName( log_config['handlers']['console']['level']).lower(), 'level_logfile': logging.getLevelName( log_config['handlers']['file']['level']).lower(), 'datefmt_console': log_config['formatters']['console']['datefmt'], 'datefmt_logfile': log_config['formatters']['file']['datefmt'], 'fmt_console': log_config['formatters']['console']['format'], 'fmt_logfile': log_config['formatters']['file']['format'], 'granular_levels': {}, }, } # We need to maintain a backup copy of the original config dict in case # the user wants to reconfigure the node. Check ``bigchaindb.config_utils`` # for more info. _config = copy.deepcopy(config) from bigchaindb.common.transaction import Transaction # noqa from bigchaindb import models # noqa from bigchaindb.upsert_validator import ValidatorElection # noqa from bigchaindb.elections.vote import Vote # noqa Transaction.register_type(Transaction.CREATE, models.Transaction) Transaction.register_type(Transaction.TRANSFER, models.Transaction) Transaction.register_type(ValidatorElection.OPERATION, ValidatorElection) Transaction.register_type(ChainMigrationElection.OPERATION, ChainMigrationElection) Transaction.register_type(Vote.OPERATION, Vote)
def validate(self, bigchain): """Validate transaction spend Args: bigchain (Bigchain): an instantiated bigchaindb.Bigchain object. Returns: The transaction (Transaction) if the transaction is valid else it raises an exception describing the reason why the transaction is invalid. Raises: ValidationError: If the transaction is invalid """ input_conditions = [] if self.operation == Transaction.TRANSFER: # store the inputs so that we can check if the asset ids match input_txs = [] for input_ in self.inputs: input_txid = input_.fulfills.txid input_tx, status = bigchain.\ get_transaction(input_txid, include_status=True) if input_tx is None: raise InputDoesNotExist("input `{}` doesn't exist" .format(input_txid)) if status != bigchain.TX_VALID: raise TransactionNotInValidBlock( 'input `{}` does not exist in a valid block'.format( input_txid)) 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)) output = input_tx.outputs[input_.fulfills.output] input_conditions.append(output) input_txs.append(input_tx) # Validate that all inputs are distinct links = [i.fulfills.to_uri() for i in self.inputs] if len(links) != len(set(links)): raise DoubleSpend('tx "{}" spends inputs twice'.format(self.id)) # validate asset id asset_id = Transaction.get_asset_id(input_txs) if asset_id != self.asset['id']: raise AssetIdMismatch(('The asset id of the input does not' ' match the asset id of the' ' transaction')) input_amount = sum([input_condition.amount for input_condition in input_conditions]) output_amount = sum([output_condition.amount for output_condition in self.outputs]) if output_amount != input_amount: raise AmountError(('The amount used in the inputs `{}`' ' needs to be same as the amount used' ' in the outputs `{}`') .format(input_amount, output_amount)) if not self.inputs_valid(input_conditions): raise InvalidSignature('Transaction signature is invalid.') return self
def main(): """ Main function """ ctx = {} def pretty_json(data): return json.dumps(data, indent=2, sort_keys=True) client = server.create_app().test_client() host = 'example.com:9984' # HTTP Index res = client.get('/', environ_overrides={'HTTP_HOST': host}) res_data = json.loads(res.data.decode()) ctx['index'] = pretty_json(res_data) # API index res = client.get('/api/v1/', environ_overrides={'HTTP_HOST': host}) ctx['api_index'] = pretty_json(json.loads(res.data.decode())) # tx create privkey = 'CfdqtD7sS7FgkMoGPXw55MVGGFwQLAoHYTcBhZDtF99Z' pubkey = '4K9sWUMFwTgaDGPfdynrbxWqWS6sWmKbZoTjxLtVUibD' asset = {'msg': 'Hello BigchainDB!'} tx = Transaction.create([pubkey], [([pubkey], 1)], asset=asset, metadata={'sequence': 0}) tx = tx.sign([privkey]) ctx['tx'] = pretty_json(tx.to_dict()) ctx['public_keys'] = tx.outputs[0].public_keys[0] ctx['txid'] = tx.id # tx transfer privkey_transfer = '3AeWpPdhEZzWLYfkfYHBfMFC2r1f8HEaGS9NtbbKssya' pubkey_transfer = '3yfQPHeWAa1MxTX9Zf9176QqcpcnWcanVZZbaHb8B3h9' cid = 0 input_ = Input(fulfillment=tx.outputs[cid].fulfillment, fulfills=TransactionLink(txid=tx.id, output=cid), owners_before=tx.outputs[cid].public_keys) tx_transfer = Transaction.transfer([input_], [([pubkey_transfer], 1)], asset_id=tx.id, metadata={'sequence': 1}) tx_transfer = tx_transfer.sign([privkey]) ctx['tx_transfer'] = pretty_json(tx_transfer.to_dict()) ctx['public_keys_transfer'] = tx_transfer.outputs[0].public_keys[0] ctx['tx_transfer_id'] = tx_transfer.id # privkey_transfer_last = 'sG3jWDtdTXUidBJK53ucSTrosktG616U3tQHBk81eQe' pubkey_transfer_last = '3Af3fhhjU6d9WecEM9Uw5hfom9kNEwE7YuDWdqAUssqm' cid = 0 input_ = Input(fulfillment=tx_transfer.outputs[cid].fulfillment, fulfills=TransactionLink(txid=tx_transfer.id, output=cid), owners_before=tx_transfer.outputs[cid].public_keys) tx_transfer_last = Transaction.transfer([input_], [([pubkey_transfer_last], 1)], asset_id=tx.id, metadata={'sequence': 2}) tx_transfer_last = tx_transfer_last.sign([privkey_transfer]) ctx['tx_transfer_last'] = pretty_json(tx_transfer_last.to_dict()) ctx['tx_transfer_last_id'] = tx_transfer_last.id ctx['public_keys_transfer_last'] = tx_transfer_last.outputs[0].public_keys[0] # block node_private = "5G2kE1zJAgTajkVSbPAQWo4c2izvtwqaNHYsaNpbbvxX" node_public = "DngBurxfeNVKZWCEcDnLj1eMPAS7focUZTE5FndFGuHT" signature = "53wxrEQDYk1dXzmvNSytbCfmNVnPqPkDQaTnAe8Jf43s6ssejPxezkCvUnGTnduNUmaLjhaan1iRLi3peu6s5DzA" app_hash = 'f6e0c49c6d94d6924351f25bb334cf2a99af4206339bf784e741d1a5ab599056' block = lib.Block(height=1, transactions=[tx.to_dict()], app_hash=app_hash) block_dict = block._asdict() block_dict.pop('app_hash') ctx['block'] = pretty_json(block_dict) ctx['blockid'] = block.height # block status block_list = [ block.height ] ctx['block_list'] = pretty_json(block_list) base_path = os.path.join(os.path.dirname(__file__), 'source/http-samples') if not os.path.exists(base_path): os.makedirs(base_path) for name, tpl in TPLS.items(): path = os.path.join(base_path, name + '.http') code = tpl % ctx with open(path, 'w') as handle: handle.write(code)