Esempio n. 1
0
    def on_balance_request(self, payload):
        """
        We received a balance request from a relay or exit node. Respond with the latest block in our chain.
        """
        if not self.bandwidth_wallet:
            self.logger.warn(
                "Bandwidth wallet is not available, not sending balance response!"
            )
            return

        # Get the latest block
        latest_block = self.bandwidth_wallet.trustchain.persistence.get_latest(
            self.my_peer.public_key.key_to_bin(),
            block_type='tribler_bandwidth')
        if not latest_block:
            latest_block = TriblerBandwidthBlock()
        latest_block.public_key = EMPTY_PK  # We hide the public key

        # We either send the response directly or relay the response to the last verified hop
        circuit = self.circuits[payload.circuit_id]
        if not circuit.hops:
            self.increase_bytes_sent(
                circuit,
                self.send_cell([circuit.peer.address], u"balance-response",
                               BalanceResponsePayload.from_half_block(
                                   latest_block, circuit.circuit_id)))
        else:
            self.increase_bytes_sent(
                circuit,
                self.send_cell([circuit.peer.address],
                               u"relay-balance-response",
                               BalanceResponsePayload.from_half_block(
                                   latest_block, circuit.circuit_id)))
Esempio n. 2
0
    def on_balance_request(self, payload):
        """
        We received a balance request from a relay or exit node. Respond with the latest block in our chain.
        """
        if not self.bandwidth_wallet:
            self.logger.warn("Bandwidth wallet is not available, not sending balance response!")
            return

        # Get the latest block
        latest_block = self.bandwidth_wallet.trustchain.persistence.get_latest(self.my_peer.public_key.key_to_bin(),
                                                                               block_type='tribler_bandwidth')
        if not latest_block:
            latest_block = TriblerBandwidthBlock()
        latest_block.public_key = EMPTY_PK  # We hide the public key

        # We either send the response directly or relay the response to the last verified hop
        circuit = self.circuits[payload.circuit_id]
        if not circuit.hops:
            self.increase_bytes_sent(circuit, self.send_cell([circuit.peer.address],
                                                             u"balance-response",
                                                             BalanceResponsePayload.from_half_block(
                                                                 latest_block, circuit.circuit_id)))
        else:
            self.increase_bytes_sent(circuit, self.send_cell([circuit.peer.address],
                                                             u"relay-balance-response",
                                                             BalanceResponsePayload.from_half_block(
                                                                 latest_block, circuit.circuit_id)))
Esempio n. 3
0
    def __init__(self, previous=None):
        super(TriblerBandwidthTestBlock, self).__init__()
        crypto = ECCrypto()
        other = crypto.generate_key(u"curve25519").pub().key_to_bin()

        transaction = {
            'up': random.randint(201, 220),
            'down': random.randint(221, 240),
            'total_up': 0,
            'total_down': 0,
            'type': 'tribler_bandwidth'
        }

        if previous:
            self.key = previous.key
            transaction['total_up'] = previous.transaction[
                'total_up'] + transaction['up']
            transaction['total_down'] = previous.transaction[
                'total_down'] + transaction['down']
            TriblerBandwidthBlock.__init__(
                self, ('tribler_bandwidth', encode(transaction),
                       previous.public_key, previous.sequence_number + 1,
                       other, 0, previous.hash, 0, 0, 0))
        else:
            transaction['total_up'] = random.randint(241, 260)
            transaction['total_down'] = random.randint(261, 280)
            self.key = crypto.generate_key(u"curve25519")
            TriblerBandwidthBlock.__init__(
                self,
                ('tribler_bandwidth', encode(transaction),
                 self.key.pub().key_to_bin(), random.randint(50, 100), other,
                 0, sha256(str(random.randint(0, 100000))).digest(), 0, 0, 0))
        self.sign(self.key)
Esempio n. 4
0
 def test_validate_not_sane_zeroes(self):
     db = MockDatabase()
     block1 = TriblerBandwidthBlock()
     # Act
     block1.transaction = {'up': 0, 'down': 0, 'total_up': 30, 'total_down': 40}
     result = block1.validate(db)
     self.assertEqual(result[0], ValidationResult.invalid)
     self.assertIn("Up and down are zero", result[1])
Esempio n. 5
0
 def test_validate_not_sane_zeroes(self):
     db = MockDatabase()
     block1 = TriblerBandwidthBlock()
     # Act
     block1.transaction = {'up': 0, 'down': 0, 'total_up': 30, 'total_down': 40}
     result = block1.validate(db)
     self.assertEqual(result[0], ValidationResult.invalid)
     self.assertIn("Up and down are zero", result[1])
Esempio n. 6
0
 def test_validate_not_sane_negatives(self):
     db = MockDatabase()
     block1 = TriblerBandwidthBlock()
     # Act
     block1.transaction = {'up': -10, 'down': -10, 'total_up': -20, 'total_down': -10}
     result = block1.validate(db)
     self.assertEqual(result[0], ValidationResult.invalid)
     self.assertIn("Up field is negative", result[1])
     self.assertIn("Down field is negative", result[1])
     self.assertIn("Total up field is negative", result[1])
     self.assertIn("Total down field is negative", result[1])
Esempio n. 7
0
 def test_validate_not_sane_negatives(self):
     db = MockDatabase()
     block1 = TriblerBandwidthBlock()
     # Act
     block1.transaction = {'up': -10, 'down': -10, 'total_up': -20, 'total_down': -10}
     result = block1.validate(db)
     self.assertEqual(result[0], ValidationResult.invalid)
     self.assertIn("Up field is negative", result[1])
     self.assertIn("Down field is negative", result[1])
     self.assertIn("Total up field is negative", result[1])
     self.assertIn("Total down field is negative", result[1])
Esempio n. 8
0
    def bootstrap_new_identity(self, amount):
        """
        One-way payment channel.
        Create a new temporary identity, and transfer funds to the new identity.
        A different party can then take the result and do a transfer from the temporary identity to itself
        """

        # Create new identity for the temporary identity
        crypto = ECCrypto()
        tmp_peer = Peer(crypto.generate_key(u"curve25519"))

        # Create the transaction specification
        transaction = {'up': 0, 'down': amount, 'type': 'tribler_bandwidth'}

        # Create the two half blocks that form the transaction
        local_half_block = TriblerBandwidthBlock.create(
            'tribler_bandwidth',
            transaction,
            self.trustchain.persistence,
            self.trustchain.my_peer.public_key.key_to_bin(),
            link_pk=tmp_peer.public_key.key_to_bin())
        local_half_block.sign(self.trustchain.my_peer.key)
        tmp_half_block = TriblerBandwidthBlock.create(
            'tribler_bandwidth',
            transaction,
            self.trustchain.persistence,
            tmp_peer.public_key.key_to_bin(),
            link=local_half_block,
            link_pk=self.trustchain.my_peer.public_key.key_to_bin())
        tmp_half_block.sign(tmp_peer.key)

        self.trustchain.persistence.add_block(local_half_block)
        self.trustchain.persistence.add_block(tmp_half_block)

        # Create the bootstrapped identity format
        block = {
            'block_hash': tmp_half_block.hash.encode('base64'),
            'sequence_number': tmp_half_block.sequence_number
        }

        result = {
            'private_key': tmp_peer.key.key_to_bin().encode('base64'),
            'transaction': {
                'up': amount,
                'down': 0
            },
            'block': block
        }
        return result
Esempio n. 9
0
 def test_validate_existing_total_down(self):
     # Arrange
     db = MockDatabase()
     (block1, block2, block3, _) = TestBlocks.setup_validate()
     db.add_block(block1)
     db.add_block(block2)
     db.add_block(block3)
     # Act
     block2 = TriblerBandwidthBlock(block2.pack_db_insert())
     block2.transaction["total_down"] += 10
     block2.sign(db.get(block2.public_key, block2.sequence_number).key)
     result = block2.validate(db)
     # Assert
     self.assertEqual(result[0], ValidationResult.invalid)
     self.assertIn('Total down is higher than expected compared to the next block', result[1])
Esempio n. 10
0
    def do_payout(self, peer, circuit_id, amount, base_amount):
        """
        Perform a payout to a specific peer.
        :param peer: The peer to perform the payout to, usually the next node in the circuit.
        :param circuit_id: The circuit id of the payout, used by the subsequent node.
        :param amount: The amount to put in the transaction, multiplier of base_amount.
        :param base_amount: The base amount for the payouts.
        """
        self.logger.info("Sending payout of %d (base: %d) to %s (cid: %s)",
                         amount, base_amount, peer, circuit_id)

        block = TriblerBandwidthBlock.create(
            'tribler_bandwidth', {
                'up': 0,
                'down': amount
            },
            self.bandwidth_wallet.trustchain.persistence,
            self.my_peer.public_key.key_to_bin(),
            link_pk=peer.public_key.key_to_bin())
        block.sign(self.my_peer.key)
        self.bandwidth_wallet.trustchain.persistence.add_block(block)

        payload = PayoutPayload.from_half_block(block, circuit_id,
                                                base_amount).to_pack_list()
        packet = self._ez_pack(self._prefix, 23, [payload], False)
        self.send_packet([peer], u"payout", packet)
Esempio n. 11
0
    def on_payout_block(self, source_address, data):
        if not self.bandwidth_wallet:
            self.logger.warning(
                "Got payout while not having a TrustChain community running!")
            return

        payload = self._ez_unpack_noauth(PayoutPayload,
                                         data,
                                         global_time=False)
        peer = Peer(payload.public_key, source_address)

        def on_transaction_completed(blocks):
            # Send the next payout
            if blocks and payload.circuit_id in self.relay_from_to and block.transaction[
                    'down'] > payload.base_amount:
                relay = self.relay_from_to[payload.circuit_id]
                self._logger.info("Sending next payout to peer %s", relay.peer)
                self.do_payout(
                    relay.peer, relay.circuit_id,
                    block.transaction['down'] - payload.base_amount * 2,
                    payload.base_amount)

        block = TriblerBandwidthBlock.from_payload(payload, self.serializer)
        self.bandwidth_wallet.trustchain.process_half_block(block, peer)\
            .addCallbacks(on_transaction_completed, lambda _: None)

        # Check whether the block has been added to the database and has been verified
        if not self.bandwidth_wallet.trustchain.persistence.contains(block):
            self.logger.warning(
                "Not proceeding with payout - received payout block is not valid"
            )
            return
Esempio n. 12
0
    def on_payout_block(self, source_address, data):
        if not self.bandwidth_wallet:
            self.logger.warning(
                "Got payout while not having a TrustChain community running!")
            return

        payload = self._ez_unpack_noauth(PayoutPayload,
                                         data,
                                         global_time=False)
        peer = Peer(payload.public_key, source_address)
        block = TriblerBandwidthBlock.from_payload(payload, self.serializer)
        self.bandwidth_wallet.trustchain.process_half_block(block, peer)

        # Send the next payout
        if payload.circuit_id in self.relay_from_to and block.transaction[
                'down'] > payload.base_amount:
            relay = self.relay_from_to[payload.circuit_id]
            circuit_peer = self.get_peer_from_address(relay.peer.address)
            if not circuit_peer:
                self.logger.warning(
                    "%s Unable to find next peer %s for payout!", self.my_peer,
                    relay.peer)
                return

            self.do_payout(circuit_peer, relay.circuit_id,
                           block.transaction['down'] - payload.base_amount * 2,
                           payload.base_amount)
Esempio n. 13
0
 def on_balance_response_cell(self, source_address, data, _):
     payload = self._ez_unpack_noauth(BalanceResponsePayload, data, global_time=False)
     block = TriblerBandwidthBlock.from_payload(payload, self.serializer)
     if not block.transaction:
         self.on_token_balance(payload.circuit_id, 0)
     else:
         self.on_token_balance(payload.circuit_id,
                               block.transaction["total_up"] - block.transaction["total_down"])
Esempio n. 14
0
 def on_balance_response_cell(self, source_address, data, _):
     payload = self._ez_unpack_noauth(BalanceResponsePayload, data, global_time=False)
     block = TriblerBandwidthBlock.from_payload(payload, self.serializer)
     if not block.transaction:
         self.on_token_balance(payload.circuit_id, 0)
     else:
         self.on_token_balance(payload.circuit_id,
                               block.transaction["total_up"] - block.transaction["total_down"])
Esempio n. 15
0
    def on_relay_balance_response_cell(self, source_address, data, _):
        payload = self._ez_unpack_noauth(BalanceResponsePayload, data, global_time=False)
        block = TriblerBandwidthBlock.from_payload(payload, self.serializer)

        # At this point, we don't have the circuit ID of the follow-up hop. We have to iterate over the items in the
        # request cache and find the link to the next hop.
        for cache in self.request_cache._identifiers.values():
            if isinstance(cache, CreateRequestCache) and cache.from_circuit_id == payload.circuit_id:
                self.send_cell([cache.to_peer.address],
                               u"balance-response",
                               BalanceResponsePayload.from_half_block(block, cache.to_circuit_id))
Esempio n. 16
0
    def on_relay_balance_response_cell(self, source_address, data, _):
        payload = self._ez_unpack_noauth(BalanceResponsePayload, data, global_time=False)
        block = TriblerBandwidthBlock.from_payload(payload, self.serializer)

        # At this point, we don't have the circuit ID of the follow-up hop. We have to iterate over the items in the
        # request cache and find the link to the next hop.
        for cache in self.request_cache._identifiers.values():
            if isinstance(cache, ExtendRequestCache) and cache.from_circuit_id == payload.circuit_id:
                self.send_cell([cache.to_peer.address],
                               u"balance-response",
                               BalanceResponsePayload.from_half_block(block, cache.to_circuit_id))
Esempio n. 17
0
 def test_validate_linked_down(self):
     db = MockDatabase()
     (block1, block2, _, _) = TestBlocks.setup_validate()
     db.add_block(block2)
     # Act
     db.add_block(TriblerBandwidthBlock.create('tribler_bandwidth', block1.transaction, db,
                                               block1.link_public_key, block1))
     block1.transaction["down"] -= 5
     result = block1.validate(db)
     self.assertEqual(result[0], ValidationResult.invalid)
     self.assertIn("Down/up mismatch on linked block", result[1])
Esempio n. 18
0
 def test_validate_linked_down(self):
     db = MockDatabase()
     (block1, block2, _, _) = TestBlocks.setup_validate()
     db.add_block(block2)
     # Act
     db.add_block(TriblerBandwidthBlock.create('tribler_bandwidth', block1.transaction, db,
                                               block1.link_public_key, block1))
     block1.transaction["down"] -= 5
     result = block1.validate(db)
     self.assertEqual(result[0], ValidationResult.invalid)
     self.assertIn("Down/up mismatch on linked block", result[1])
Esempio n. 19
0
    def bootstrap_new_identity(self, amount):
        """
        One-way payment channel.
        Create a new temporary identity, and transfer funds to the new identity.
        A different party can then take the result and do a transfer from the temporary identity to itself
        """

        # Create new identity for the temporary identity
        crypto = ECCrypto()
        tmp_peer = Peer(crypto.generate_key(u"curve25519"))

        # Create the transaction specification
        transaction = {
            'up': 0,
            'down': amount,
            'type': 'tribler_bandwidth'
        }

        # Create the two half blocks that form the transaction
        local_half_block = TriblerBandwidthBlock.create('tribler_bandwidth', transaction, self.trustchain.persistence,
                                                        self.trustchain.my_peer.public_key.key_to_bin(),
                                                        link_pk=tmp_peer.public_key.key_to_bin())
        local_half_block.sign(self.trustchain.my_peer.key)
        tmp_half_block = TriblerBandwidthBlock.create('tribler_bandwidth', transaction, self.trustchain.persistence,
                                                      tmp_peer.public_key.key_to_bin(),
                                                      link=local_half_block,
                                                      link_pk=self.trustchain.my_peer.public_key.key_to_bin())
        tmp_half_block.sign(tmp_peer.key)

        self.trustchain.persistence.add_block(local_half_block)
        self.trustchain.persistence.add_block(tmp_half_block)

        # Create the bootstrapped identity format
        block = {'block_hash': tmp_half_block.hash.encode('base64'),
                 'sequence_number': tmp_half_block.sequence_number}

        result = {'private_key': tmp_peer.key.key_to_bin().encode('base64'),
                  'transaction': {'up': amount, 'down': 0}, 'block': block}
        return result
Esempio n. 20
0
    def __init__(self, previous=None):
        super(TriblerBandwidthTestBlock, self).__init__()
        crypto = ECCrypto()
        other = crypto.generate_key(u"curve25519").pub().key_to_bin()

        transaction = {'up': random.randint(201, 220), 'down': random.randint(221, 240), 'total_up': 0,
                       'total_down': 0, 'type': 'tribler_bandwidth'}

        if previous:
            self.key = previous.key
            transaction['total_up'] = previous.transaction['total_up'] + transaction['up']
            transaction['total_down'] = previous.transaction['total_down'] + transaction['down']
            TriblerBandwidthBlock.__init__(self, ('tribler_bandwidth', encode(transaction), previous.public_key,
                                                  previous.sequence_number + 1, other, 0, previous.hash, 0, 0, 0))
        else:
            transaction['total_up'] = random.randint(241, 260)
            transaction['total_down'] = random.randint(261, 280)
            self.key = crypto.generate_key(u"curve25519")
            TriblerBandwidthBlock.__init__(self, (
                'tribler_bandwidth', encode(transaction), self.key.pub().key_to_bin(), random.randint(50, 100), other,
                0, sha256(str(random.randint(0, 100000))).digest(), 0, 0, 0))
        self.sign(self.key)
Esempio n. 21
0
 def test_validate_existing_total_down(self):
     # Arrange
     db = MockDatabase()
     (block1, block2, block3, _) = TestBlocks.setup_validate()
     db.add_block(block1)
     db.add_block(block2)
     db.add_block(block3)
     # Act
     block2 = TriblerBandwidthBlock(block2.pack_db_insert())
     block2.transaction["total_down"] += 10
     block2.sign(db.get(block2.public_key, block2.sequence_number).key)
     result = block2.validate(db)
     # Assert
     self.assertEqual(result[0], ValidationResult.invalid)
     self.assertIn('Total down is higher than expected compared to the next block', result[1])
Esempio n. 22
0
    def do_payout(self, peer, circuit_id, amount, base_amount):
        """
        Perform a payout to a specific peer.
        :param peer: The peer to perform the payout to, usually the next node in the circuit.
        :param circuit_id: The circuit id of the payout, used by the subsequent node.
        :param amount: The amount to put in the transaction, multiplier of base_amount.
        :param base_amount: The base amount for the payouts.
        """
        self.logger.info("Sending payout of %d (base: %d) to %s (cid: %s)", amount, base_amount, peer, circuit_id)

        block = TriblerBandwidthBlock.create(
            'tribler_bandwidth',
            {'up': 0, 'down': amount},
            self.bandwidth_wallet.trustchain.persistence,
            self.my_peer.public_key.key_to_bin(),
            link_pk=peer.public_key.key_to_bin())
        block.sign(self.my_peer.key)
        self.bandwidth_wallet.trustchain.persistence.add_block(block)

        payload = PayoutPayload.from_half_block(block, circuit_id, base_amount).to_pack_list()
        packet = self._ez_pack(self._prefix, 23, [payload], False)
        self.send_packet([peer], packet)
Esempio n. 23
0
    def on_payout_block(self, source_address, data):
        if not self.bandwidth_wallet:
            self.logger.warning("Got payout while not having a TrustChain community running!")
            return

        payload = self._ez_unpack_noauth(PayoutPayload, data, global_time=False)
        peer = Peer(payload.public_key, source_address)

        def on_transaction_completed(blocks):
            # Send the next payout
            if blocks and payload.circuit_id in self.relay_from_to and block.transaction['down'] > payload.base_amount:
                relay = self.relay_from_to[payload.circuit_id]
                self._logger.info("Sending next payout to peer %s", relay.peer)
                self.do_payout(relay.peer, relay.circuit_id, block.transaction['down'] - payload.base_amount * 2,
                               payload.base_amount)

        block = TriblerBandwidthBlock.from_payload(payload, self.serializer)
        self.bandwidth_wallet.trustchain.process_half_block(block, peer)\
            .addCallbacks(on_transaction_completed, lambda _: None)

        # Check whether the block has been added to the database and has been verified
        if not self.bandwidth_wallet.trustchain.persistence.contains(block):
            self.logger.warning("Not proceeding with payout - received payout block is not valid")
            return