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 tmp_member = self.dispersy.get_new_member(u"curve25519") # Create the transaction specification transaction = { 'up': 0, 'down': amount } # Create the two half blocks that form the transaction local_half_block = TriblerChainBlock.create(transaction, self.persistence, self.my_member.public_key, link_pk=tmp_member.public_key) local_half_block.sign(self.my_member.private_key) tmp_half_block = TriblerChainBlock.create(transaction, self.persistence, tmp_member.public_key, link=local_half_block, link_pk=self.my_member.public_key) tmp_half_block.sign(tmp_member.private_key) self.persistence.add_block(local_half_block) self.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_member.private_key.key_to_bin().encode('base64'), 'transaction': {'up': amount, 'down': 0}, 'block': block} return result
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.triblerchain_community: return # Get the latest block latest_block = self.triblerchain_community.persistence.get_latest( self.my_peer.public_key.key_to_bin()) if not latest_block: latest_block = TriblerChainBlock() 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.sock_addr], u"balance-response", BalanceResponsePayload.from_half_block( latest_block, circuit.circuit_id))) else: self.increase_bytes_sent( circuit, self.send_cell([circuit.sock_addr], u"relay-balance-response", BalanceResponsePayload.from_half_block( latest_block, circuit.circuit_id)))
def __init__(self, previous=None): super(TriblerTestBlock, 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 } if previous: self.key = previous.key transaction['total_up'] = previous.transaction[ 'total_up'] + transaction['up'] transaction['total_down'] = previous.transaction[ 'total_down'] + transaction['down'] TriblerChainBlock.__init__( self, (encode(transaction), previous.public_key, previous.sequence_number + 1, other, 0, previous.hash, 0, 0)) else: transaction['total_up'] = random.randint(241, 260) transaction['total_down'] = random.randint(261, 280) self.key = crypto.generate_key(u"curve25519") TriblerChainBlock.__init__( self, (encode(transaction), self.key.pub().key_to_bin(), random.randint(50, 100), other, 0, sha256(str(random.randint(0, 100000))).digest(), 0, 0)) self.sign(self.key)
def test_validate_not_sane_zeroes(self): db = MockDatabase() block1 = TriblerChainBlock() # 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])
def test_validate_not_sane_negatives(self): db = MockDatabase() block1 = TriblerChainBlock() # 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])
def on_balance_response_cell(self, source_address, data, _): _, payload = self._ez_unpack_noauth(BalanceResponsePayload, data) block = TriblerChainBlock.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"])
def test_validate_linked_down(self): db = MockDatabase() (block1, block2, _, _) = TestBlocks.setup_validate() db.add_block(block2) # Act db.add_block(TriblerChainBlock.create(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])
def on_relay_balance_response_cell(self, source_address, data, _): _, payload = self._ez_unpack_noauth(BalanceResponsePayload, data) block = TriblerChainBlock.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_candidate_sock_addr], u"balance-response", BalanceResponsePayload.from_half_block(block, cache.to_circuit_id))
def test_validate_existing_total_up(self): # Arrange db = MockDatabase() (block1, block2, block3, _) = TestBlocks.setup_validate() db.add_block(block1) db.add_block(block2) db.add_block(block3) # Act block2 = TriblerChainBlock(block2.pack_db_insert()) block2.transaction["total_up"] += 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 up is higher than expected compared to the next block', result[1])
def test_crawl_request(self): """ Test whether a crawl request is sent when receiving an introduction response """ his_pk = self.nodes[1].overlay.my_peer.public_key.key_to_bin() block = TriblerChainBlock.create( { 'up': 20, 'down': 40 }, self.nodes[0].overlay.persistence, self.nodes[0].overlay.my_peer.public_key.key_to_bin(), link=None, link_pk=his_pk) block.sign(self.nodes[0].overlay.my_peer.key) self.nodes[0].overlay.persistence.add_block(block) yield self.introduce_nodes() # The block should be available in the databases of both involved parties. for node_nr in [0, 1]: self.assertIsNotNone(self.nodes[node_nr].overlay.persistence.get( self.nodes[0].overlay.my_peer.public_key.key_to_bin(), 1))