Exemplo n.º 1
0
    def vote(self, block_id, previous_block_id, decision, invalid_reason=None):
        """Create a signed vote for a block given the
        :attr:`previous_block_id` and the :attr:`decision` (valid/invalid).

        Args:
            block_id (str): The id of the block to vote on.
            previous_block_id (str): The id of the previous block.
            decision (bool): Whether the block is valid or invalid.
            invalid_reason (Optional[str]): Reason the block is invalid
        """

        if block_id == previous_block_id:
            raise exceptions.CyclicBlockchainError()

        vote = {
            'voting_for_block': block_id,
            'previous_block': previous_block_id,
            'is_block_valid': decision,
            'invalid_reason': invalid_reason,
            'timestamp': gen_timestamp()
        }

        vote_data = serialize(vote)
        signature = crypto.PrivateKey(self.me_private).sign(vote_data.encode())

        vote_signed = {
            'node_pubkey': self.me,
            'signature': signature.decode(),
            'vote': vote
        }

        return vote_signed
Exemplo n.º 2
0
    def vote(self, block_id, previous_block_id, decision, invalid_reason=None):
        """Create a signed vote for a block given the
        :attr:`previous_block_id` and the :attr:`decision` (valid/invalid).

        Args:
            block_id (str): The id of the block to vote on.
            previous_block_id (str): The id of the previous block.
            decision (bool): Whether the block is valid or invalid.
            invalid_reason (Optional[str]): Reason the block is invalid
        """

        if block_id == previous_block_id:
            raise exceptions.CyclicBlockchainError()

        vote = {
            'voting_for_block': block_id,
            'previous_block': previous_block_id,
            'is_block_valid': decision,
            'invalid_reason': invalid_reason,
            'timestamp': gen_timestamp()
        }

        vote_data = serialize(vote)
        signature = crypto.PrivateKey(self.me_private).sign(vote_data.encode())

        vote_signed = {
            'node_pubkey': self.me,
            'signature': signature.decode(),
            'vote': vote
        }

        return vote_signed
Exemplo n.º 3
0
    def test_block_deserialization(self, b):
        from bigchaindb.common.crypto import hash_data
        from bigchaindb.common.utils import gen_timestamp, serialize
        from bigchaindb.models import Block, Transaction

        transaction = Transaction.create([b.me], [([b.me], 1)])
        transaction.sign([b.me_private])
        timestamp = gen_timestamp()
        voters = ['Qaaa', 'Qbbb']
        expected = Block([transaction], b.me, timestamp, voters)

        block = {
            'timestamp': timestamp,
            'transactions': [transaction.to_dict()],
            'node_pubkey': b.me,
            'voters': voters,
        }

        block_body = {
            'id': hash_data(serialize(block)),
            'block': block,
            'signature': None,
        }

        assert expected == Block.from_dict(block_body)
Exemplo n.º 4
0
    def __init__(self, transactions=None, node_pubkey=None, timestamp=None,
                 voters=None, signature=None):
        """The Block model is mainly used for (de)serialization and integrity
        checking.

        Args:
            transaction (:obj:`list` of :class:`~.Transaction`):
                Transactions to be included in the Block.
            node_pubkey (str): The public key of the node creating the
                Block.
            timestamp (str): The Unix time a Block was created.
            voters (:obj:`list` of :obj:`str`): A list of a federation
                nodes' public keys supposed to vote on the Block.
            signature (str): A cryptographic signature ensuring the
                integrity and validity of the creator of a Block.
        """
        if transactions is not None and not isinstance(transactions, list):
            raise TypeError('`transactions` must be a list instance or None')
        else:
            self.transactions = transactions or []

        if voters is not None and not isinstance(voters, list):
            raise TypeError('`voters` must be a list instance or None')
        else:
            self.voters = voters or []

        if timestamp is not None:
            self.timestamp = timestamp
        else:
            self.timestamp = gen_timestamp()

        self.node_pubkey = node_pubkey
        self.signature = signature
Exemplo n.º 5
0
    def __init__(self,
                 transactions=None,
                 node_pubkey=None,
                 timestamp=None,
                 signature=None):
        """The Block model is mainly used for (de)serialization and integrity
        checking.

        Args:
            transaction (:obj:`list` of :class:`~.Transaction`):
                Transactions to be included in the Block.
            node_pubkey (str): The public key of the node creating the
                Block.
            timestamp (str): The Unix time a Block was created.
            signature (str): A cryptographic signature ensuring the
                integrity and validity of the creator of a Block.
        """
        if transactions is not None and not isinstance(transactions, list):
            raise TypeError('`transactions` must be a list instance or None')
        else:
            self.transactions = transactions or []

        if timestamp is not None:
            self.timestamp = timestamp
        else:
            self.timestamp = gen_timestamp()

        self.node_pubkey = node_pubkey
        self.signature = signature
Exemplo n.º 6
0
    def test_block_invalid_signature(self, b, alice):
        from bigchaindb.common.crypto import hash_data
        from bigchaindb.common.exceptions import InvalidSignature
        from bigchaindb.common.utils import gen_timestamp, serialize
        from bigchaindb.models import Block, Transaction

        transaction = Transaction.create([alice.public_key],
                                         [([alice.public_key], 1)])
        transaction.sign([alice.private_key])
        timestamp = gen_timestamp()

        block = {
            'timestamp': timestamp,
            'transactions': [transaction.to_dict()],
            'node_pubkey': alice.public_key,
        }

        block_body = {
            'id': hash_data(serialize(block)),
            'block': block,
            'signature': 'an invalid signature',
        }

        with raises(InvalidSignature):
            Block.from_dict(block_body).validate(b)
Exemplo n.º 7
0
    def test_block_serialization(self, b, alice):
        from bigchaindb.common.crypto import hash_data
        from bigchaindb.common.utils import gen_timestamp, serialize
        from bigchaindb.models import Block, Transaction

        transactions = [
            Transaction.create([alice.public_key], [([alice.public_key], 1)])
        ]
        timestamp = gen_timestamp()
        voters = ['Qaaa', 'Qbbb']
        expected_block = {
            'timestamp': timestamp,
            'transactions': [tx.to_dict() for tx in transactions],
            'node_pubkey': alice.public_key,
            'voters': voters,
        }
        expected = {
            'id': hash_data(serialize(expected_block)),
            'block': expected_block,
            'signature': None,
        }

        block = Block(transactions, alice.public_key, timestamp, voters)

        assert block.to_dict() == expected
Exemplo n.º 8
0
    def test_sign_block(self, b, alice):
        from bigchaindb.common.crypto import PrivateKey, PublicKey
        from bigchaindb.common.utils import gen_timestamp, serialize
        from bigchaindb.models import Block, Transaction

        transactions = [
            Transaction.create([alice.public_key], [([alice.public_key], 1)])
        ]
        timestamp = gen_timestamp()
        voters = ['Qaaa', 'Qbbb']
        expected_block = {
            'timestamp': timestamp,
            'transactions': [tx.to_dict() for tx in transactions],
            'node_pubkey': alice.public_key,
            'voters': voters,
        }
        expected_block_serialized = serialize(expected_block).encode()
        expected = PrivateKey(
            alice.private_key).sign(expected_block_serialized)
        block = Block(transactions, alice.public_key, timestamp, voters)
        block = block.sign(alice.private_key)
        assert block.signature == expected.decode()

        public_key = PublicKey(alice.public_key)
        assert public_key.verify(expected_block_serialized, block.signature)
Exemplo n.º 9
0
def connect_and_recv(event_queue):
    session = aiohttp.ClientSession()
    ws = yield from session.ws_connect(URL)

    logger.info('Connected to tendermint ws server')

    stream_id = 'bigchaindb_stream_{}'.format(gen_timestamp())
    yield from subscribe_events(ws, stream_id)

    while True:
        msg = yield from ws.receive()
        process_event(event_queue, msg.data, stream_id)

        if msg.type in (aiohttp.WSMsgType.CLOSED, aiohttp.WSMsgType.ERROR):
            session.close()
            raise aiohttp.ClientConnectionError()
Exemplo n.º 10
0
 def create_stream(self):
     tx_create = self.bdb.transactions.prepare(
         operation='CREATE',
         signers=self.sharge.public_key,
         asset={
             'data':
                 {
                     'mobile': self.mobile.public_key,
                     'timestamp': gen_timestamp()
                 }
         },
     )
     tx_create_signed = self.bdb.transactions.fulfill(tx_create, private_keys=self.sharge.private_key)
     self.bdb.transactions.send(tx_create_signed)
     poll_status_and_fetch_transaction(tx_create_signed['id'], driver=self.bdb)
     self.data_stream.append(tx_create_signed['id'])
Exemplo n.º 11
0
def connect_and_recv(event_queue):
    session = aiohttp.ClientSession()
    ws = yield from session.ws_connect(URL)

    logger.info('Connected to tendermint ws server')

    stream_id = 'bigchaindb_stream_{}'.format(gen_timestamp())
    yield from subscribe_events(ws, stream_id)

    while True:
        msg = yield from ws.receive()
        process_event(event_queue, msg.data, stream_id)

        if msg.type in (aiohttp.WSMsgType.CLOSED,
                        aiohttp.WSMsgType.ERROR):
            session.close()
            raise aiohttp.ClientConnectionError()
Exemplo n.º 12
0
    def _input_valid(input_,
                     operation,
                     tx_serialized,
                     output_condition_uri=None):
        """Validates a single Input against a single Output.

            Note:
                In case of a `CREATE` or `GENESIS` Transaction, this method
                does not validate against `output_condition_uri`.

            Args:
                input_ (:class:`~bigchaindb.common.transaction.
                    Input`) The Input to be signed.
                operation (str): The type of Transaction.
                tx_serialized (str): The Transaction used as a message when
                    initially signing it.
                output_condition_uri (str, optional): An Output to check the
                    Input against.

            Returns:
                bool: If the Input is valid.
        """
        ccffill = input_.fulfillment
        try:
            parsed_ffill = Fulfillment.from_uri(ccffill.serialize_uri())
        except (TypeError, ValueError, ParsingError):
            return False

        if operation in (Transaction.CREATE, Transaction.GENESIS):
            # NOTE: In the case of a `CREATE` or `GENESIS` transaction, the
            #       output is always valid.
            output_valid = True
        else:
            output_valid = output_condition_uri == ccffill.condition_uri

        # NOTE: We pass a timestamp to `.validate`, as in case of a timeout
        #       condition we'll have to validate against it

        # cryptoconditions makes no assumptions of the encoding of the
        # message to sign or verify. It only accepts bytestrings
        ffill_valid = parsed_ffill.validate(message=tx_serialized.encode(),
                                            now=gen_timestamp())
        return output_valid and ffill_valid
Exemplo n.º 13
0
    def _input_valid(input_, operation, tx_serialized, output_condition_uri=None):
        """Validates a single Input against a single Output.

            Note:
                In case of a `CREATE` or `GENESIS` Transaction, this method
                does not validate against `output_condition_uri`.

            Args:
                input_ (:class:`~bigchaindb.common.transaction.
                    Input`) The Input to be signed.
                operation (str): The type of Transaction.
                tx_serialized (str): The Transaction used as a message when
                    initially signing it.
                output_condition_uri (str, optional): An Output to check the
                    Input against.

            Returns:
                bool: If the Input is valid.
        """
        ccffill = input_.fulfillment
        try:
            parsed_ffill = Fulfillment.from_uri(ccffill.serialize_uri())
        except (TypeError, ValueError, ParsingError):
            return False

        if operation in (Transaction.CREATE, Transaction.GENESIS):
            # NOTE: In the case of a `CREATE` or `GENESIS` transaction, the
            #       output is always valid.
            output_valid = True
        else:
            output_valid = output_condition_uri == ccffill.condition_uri

        # NOTE: We pass a timestamp to `.validate`, as in case of a timeout
        #       condition we'll have to validate against it

        # cryptoconditions makes no assumptions of the encoding of the
        # message to sign or verify. It only accepts bytestrings
        ffill_valid = parsed_ffill.validate(message=tx_serialized.encode(),
                                            now=gen_timestamp())
        return output_valid and ffill_valid
Exemplo n.º 14
0
    def create_block(self, validated_transactions):
        """Creates a block given a list of `validated_transactions`.

        Note that this method does not validate the transactions. Transactions
        should be validated before calling create_block.

        Args:
            validated_transactions (list(Transaction)): list of validated
                                                        transactions.

        Returns:
            Block: created block.
        """
        # Prevent the creation of empty blocks
        if not validated_transactions:
            raise exceptions.OperationError('Empty block creation is not '
                                            'allowed')

        voters = list(self.federation)
        block = Block(validated_transactions, self.me, gen_timestamp(), voters)
        block = block.sign(self.me_private)

        return block
Exemplo n.º 15
0
    def create_block(self, validated_transactions):
        """Creates a block given a list of `validated_transactions`.

        Note that this method does not validate the transactions. Transactions
        should be validated before calling create_block.

        Args:
            validated_transactions (list(Transaction)): list of validated
                                                        transactions.

        Returns:
            Block: created block.
        """
        # Prevent the creation of empty blocks
        if len(validated_transactions) == 0:
            raise exceptions.OperationError('Empty block creation is not '
                                            'allowed')

        voters = self.nodes_except_me + [self.me]
        block = Block(validated_transactions, self.me, gen_timestamp(), voters)
        block = block.sign(self.me_private)

        return block
Exemplo n.º 16
0
    def test_block_deserialization(self, b, alice):
        from bigchaindb.common.crypto import hash_data
        from bigchaindb.common.utils import gen_timestamp, serialize
        from bigchaindb.models import Block, Transaction

        transaction = Transaction.create([alice.public_key],
                                         [([alice.public_key], 1)])
        transaction.sign([alice.private_key])
        timestamp = gen_timestamp()
        expected = Block([transaction], alice.public_key, timestamp)

        block = {
            'timestamp': timestamp,
            'transactions': [transaction.to_dict()],
            'node_pubkey': alice.public_key,
        }

        block_body = {
            'id': hash_data(serialize(block)),
            'block': block,
            'signature': None,
        }

        assert expected == Block.from_dict(block_body)
Exemplo n.º 17
0
def generate_mock_data():
    mobile = generate_keypair()
    plug = generate_keypair()

    now = int(gen_timestamp())
    data = []

    num_samples = 6
    for i in range(num_samples + 1):
        door_control = 1 if i in [0, num_samples] else 0
        plugged = 0 if i in [0, num_samples] else 1
        charge_control = random.randint(2, 10)

        data.append({
            'id_plug': plug.public_key,
            'id_mobile': mobile.public_key,
            'time': str(now + i * 60),
            'door_control': str(door_control),
            'plugged': str(plugged),
            'charge_control_kw': str(charge_control)
        })
    pprint.pprint(data)

    return data, plug, mobile
Exemplo n.º 18
0
    def test_block_invalid_signature(self, b):
        from bigchaindb.common.crypto import hash_data
        from bigchaindb.common.exceptions import InvalidSignature
        from bigchaindb.common.utils import gen_timestamp, serialize
        from bigchaindb.models import Block, Transaction

        transactions = [Transaction.create([b.me], [([b.me], 1)])]
        timestamp = gen_timestamp()

        block = {
            'timestamp': timestamp,
            'transactions': [tx.to_dict() for tx in transactions],
            'node_pubkey': b.me,
            'voters': list(b.federation),
        }

        block_body = {
            'id': hash_data(serialize(block)),
            'block': block,
            'signature': 'an invalid signature',
        }

        with raises(InvalidSignature):
            Block.from_dict(block_body).validate(b)
Exemplo n.º 19
0
def escrow_asset(bigchain,
                 source,
                 to,
                 asset_id,
                 sk,
                 expires_at=None,
                 ilp_header=None,
                 execution_condition=None):
    asset = bigchain.get_transaction(asset_id['txid'])
    payload = asset['transaction']['data']['payload'].copy()
    if ilp_header:
        payload.update({'ilp_header': ilp_header})

    # Create escrow template with the execute and abort address
    asset_escrow = bigchain.create_transaction(source, [source, to],
                                               asset_id,
                                               'TRANSFER',
                                               payload=payload)
    if not expires_at:
        # Set expiry time (100 secs from now)
        time_sleep = 100
        expires_at = float(gen_timestamp()) + time_sleep

    # Create escrow and timeout condition
    condition_escrow = cc.ThresholdSha256Fulfillment(threshold=1)  # OR Gate
    condition_timeout = cc.TimeoutFulfillment(
        expire_time=str(expires_at))  # only valid if now() <= time_expire
    condition_timeout_inverted = cc.InvertedThresholdSha256Fulfillment(
        threshold=1)
    condition_timeout_inverted.add_subfulfillment(condition_timeout)

    # Create execute branch
    execution_threshold = 3 if execution_condition else 2
    condition_execute = cc.ThresholdSha256Fulfillment(
        threshold=execution_threshold)  # AND gate
    condition_execute.add_subfulfillment(
        cc.Ed25519Fulfillment(public_key=to))  # execute address
    condition_execute.add_subfulfillment(
        condition_timeout)  # federation checks on expiry
    if execution_condition:
        condition_execute.add_subcondition_uri(execution_condition)
    condition_escrow.add_subfulfillment(condition_execute)

    # Create abort branch
    condition_abort = cc.ThresholdSha256Fulfillment(threshold=2)  # AND gate
    condition_abort.add_subfulfillment(
        cc.Ed25519Fulfillment(public_key=source))  # abort address
    condition_abort.add_subfulfillment(condition_timeout_inverted)
    condition_escrow.add_subfulfillment(condition_abort)

    # Update the condition in the newly created transaction
    asset_escrow['transaction']['conditions'][0]['condition'] = {
        'details': condition_escrow.to_dict(),
        'uri': condition_escrow.condition.serialize_uri()
    }

    # conditions have been updated, so hash needs updating
    asset_escrow['id'] = crypto.hash_data(asset_escrow)

    # sign transaction
    asset_escrow_signed = bigchaindb.util.sign_tx(asset_escrow,
                                                  sk,
                                                  bigchain=bigchain)
    bigchain.write_transaction(asset_escrow_signed)
    return asset_escrow_signed