def __init__(self, previous=None, transaction=None): super(TriblerTestBlock, self).__init__() crypto = ECCrypto() other = crypto.generate_key(u"curve25519").pub().key_to_bin() transaction = transaction or { 'up': randint(201, 220), 'down': randint(221, 240) } if 'total_up' not in self.transaction: transaction['total_up'] = randint(241, 260) if 'total_down' not in self.transaction: transaction['total_down'] = randint(261, 280) 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: self.key = crypto.generate_key(u"curve25519") TriblerChainBlock.__init__( self, (encode(transaction), self.key.pub().key_to_bin(), randint(50, 100), other, 0, sha256(str(randint(0, 100000))).digest(), 0, 0)) self.sign(self.key)
def run(): crypto = ECCrypto() dispersy = Dispersy( StandaloneEndpoint(options["port"], options["ip"]), options["statedir"], u'dispersy.db', crypto) if not dispersy.start(): raise RuntimeError("Unable to start Dispersy") master_member = TriblerChainCommunityCrawler.get_master_members( dispersy)[0] my_member = dispersy.get_member(private_key=crypto.key_to_bin( crypto.generate_key(u"curve25519"))) TriblerChainCommunityCrawler.init_community( dispersy, master_member, my_member) self._stopping = False def signal_handler(sig, frame): msg("Received signal '%s' in %s (shutting down)" % (sig, frame)) if not self._stopping: self._stopping = True dispersy.stop().addCallback(lambda _: reactor.stop()) signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler)
def sign(self, key): """ Signs this block with the given key :param key: the key to sign this block with """ crypto = ECCrypto() self.signature = crypto.create_signature(key, self.pack(signature=False))
def setUp(self, autoload_discovery=True): """ Setup various variables. """ os.environ[BOOTSTRAP_FILE_ENVNAME] = os.path.join( TESTS_DATA_DIR, 'bootstrap_empty.txt') yield TestAsServer.setUp(self, autoload_discovery=autoload_discovery) self.sessions = [] self.eccrypto = ECCrypto() ec = self.eccrypto.generate_key(u"curve25519") MarketCommunityTests.master_key = self.eccrypto.key_to_bin( ec.pub()).encode('hex') ec = self.eccrypto.generate_key(u"curve25519") TriblerChainCommunityTests.master_key = self.eccrypto.key_to_bin( ec.pub()).encode('hex') market_member = self.generate_member(self.session) self.market_communities = {} mc_community = self.load_triblerchain_community_in_session( self.session) self.load_market_community_in_session(self.session, market_member, mc_community)
def test_create_genesis(self): key = ECCrypto().generate_key(u"curve25519") db = self.MockDatabase() block = MultiChainBlock.create(db, key.pub().key_to_bin(), link=None) self.assertEqual(block.previous_hash, GENESIS_HASH) self.assertEqual(block.sequence_number, GENESIS_SEQ) self.assertEqual(block.public_key, key.pub().key_to_bin()) self.assertEqual(block.signature, EMPTY_SIG)
def sign(self, member): """ Sign this tick using a private key. :param member: The member that signs this tick """ crypto = ECCrypto() self._public_key = member.public_key self._signature = crypto.create_signature(member.private_key, self.get_sign_data())
def get_master_members(cls, dispersy): eccrypto = ECCrypto() ec = eccrypto.generate_key(u"curve25519") DummyTunnelCommunity.master_key = eccrypto.key_to_bin( ec.pub()).encode('hex') master_key_hex = DummyTunnelCommunity.master_key.decode("HEX") master = dispersy.get_member(public_key=master_key_hex) return [master]
def test_create_link_genesis(self): key = ECCrypto().generate_key(u"curve25519") db = self.MockDatabase() link = TestBlock() db.add_block(link) block = MultiChainBlock.create(db, key.pub().key_to_bin(), link=link) self.assertEqual(block.previous_hash, GENESIS_HASH) self.assertEqual(block.sequence_number, GENESIS_SEQ) self.assertEqual(block.public_key, key.pub().key_to_bin()) self.assertEqual(block.link_public_key, link.public_key) self.assertEqual(block.link_sequence_number, link.sequence_number)
def setUp(self, annotate=True): yield super(CommunityTestSuite, self).setUp(annotate=annotate) dummy1_wallet = DummyWallet1() dummy2_wallet = DummyWallet2() self.market_community = MarketCommunity(self.dispersy, self.master_member, self.member) self.market_community.initialize(wallets={ dummy1_wallet.get_identifier(): dummy1_wallet, dummy2_wallet.get_identifier(): dummy2_wallet }, use_database=False) self.market_community.use_local_address = True self.dispersy._lan_address = ("127.0.0.1", 1234) self.dispersy._endpoint.open(self.dispersy) self.dispersy.attach_community(self.market_community) eccrypto = ECCrypto() ec = eccrypto.generate_key(u"curve25519") member = Member(self.dispersy, ec, 1) trader_id = hashlib.sha1(member.public_key).digest().encode('hex') self.ask = Ask( MessageId(TraderId('0'), MessageNumber('message_number')), OrderId(TraderId(trader_id), OrderNumber(1234)), Price(63400, 'DUM1'), Quantity(30, 'DUM2'), Timeout(3600), Timestamp.now()) self.ask.sign(member) self.bid = Bid( MessageId(TraderId('1'), MessageNumber('message_number')), OrderId(TraderId(trader_id), OrderNumber(1235)), Price(343, 'DUM1'), Quantity(22, 'DUM2'), Timeout(3600), Timestamp.now()) self.bid.sign(member) self.order = Order( OrderId(TraderId(self.market_community.mid), OrderNumber(24)), Price(20, 'DUM1'), Quantity(30, 'DUM2'), Timeout(3600.0), Timestamp.now(), False) self.proposed_trade = Trade.propose( MessageId(TraderId('0'), MessageNumber('message_number')), OrderId(TraderId('0'), OrderNumber(23)), OrderId(TraderId(self.market_community.mid), OrderNumber(24)), Price(20, 'DUM1'), Quantity(30, 'DUM2'), Timestamp.now())
def assertEqual_block(self, expected_block, actual_block): """ Function to assertEqual two blocks """ crypto = ECCrypto() self.assertTrue(expected_block is not None) self.assertTrue(actual_block is not None) self.assertTrue(crypto.is_valid_public_bin(expected_block.public_key)) self.assertTrue(crypto.is_valid_public_bin(actual_block.public_key)) self.assertDictEqual(expected_block.transaction, actual_block.transaction) self.assertEqual(expected_block.public_key, actual_block.public_key) self.assertEqual(expected_block.sequence_number, actual_block.sequence_number) self.assertEqual(expected_block.link_public_key, actual_block.link_public_key) self.assertEqual(expected_block.link_sequence_number, actual_block.link_sequence_number) self.assertEqual(expected_block.previous_hash, actual_block.previous_hash) self.assertEqual(expected_block.signature, actual_block.signature)
def __init__(self, transaction=None, previous=None): crypto = ECCrypto() other = crypto.generate_key(u"curve25519").pub().key_to_bin() transaction = transaction or {'id': 42} if previous: self.key = previous.key TrustChainBlock.__init__(self, (encode(transaction), previous.public_key, previous.sequence_number + 1, other, 0, previous.hash, 0, 0)) else: self.key = crypto.generate_key(u"curve25519") TrustChainBlock.__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)
class TestCommunity(Community): crypto = ECCrypto() def __init__(self): self.key = self.crypto.generate_key(u"medium") self.pk = self.crypto.key_to_bin(self.key.pub()) self.meta_message_cache = {} self._cid = sha1(self.pk).digest() self._meta_messages = {} self._initialize_meta_messages() self._global_time = 0 self._do_pruning = False self._logger = logging.getLogger(self.__class__.__name__) self._conversions = self.initiate_conversions() def initiate_meta_messages(self): return super(TestCommunity, self).initiate_meta_messages() + [ Message(self, SIGNATURE, NoAuthentication(), PublicResolution(), DirectDistribution(), CandidateDestination(), SignaturePayload(), lambda: None, lambda: None), Message(self, CRAWL_REQUEST, NoAuthentication(), PublicResolution(), DirectDistribution(), CandidateDestination(), CrawlRequestPayload(), lambda: None, lambda: None), Message(self, CRAWL_RESPONSE, NoAuthentication(), PublicResolution(), DirectDistribution(), CandidateDestination(), CrawlResponsePayload(), lambda: None, lambda: None), Message(self, CRAWL_RESUME, NoAuthentication(), PublicResolution(), DirectDistribution(), CandidateDestination(), CrawlResumePayload(), lambda: None, lambda: None)] def initiate_conversions(self): return [DefaultConversion(self), MultiChainConversion(self)]
def setUp(self, autoload_discovery=True): """ Setup various variables and load the tunnel community in the main downloader session. """ yield TestAsServer.setUp(self, autoload_discovery=autoload_discovery) self.seed_tdef = None self.sessions = [] self.session2 = None self.crypto_enabled = True self.bypass_dht = False self.seed_config = None self.tunnel_community_seeder = None self.eccrypto = ECCrypto() ec = self.eccrypto.generate_key(u"curve25519") HiddenTunnelCommunityTests.master_key = self.eccrypto.key_to_bin(ec.pub()).encode('hex') self.tunnel_community = self.load_tunnel_community_in_session(self.session, exitnode=True) self.tunnel_communities = []
def __init__(self, previous=None): crypto = ECCrypto() up = random.randint(201, 220) down = random.randint(221, 240) other = crypto.generate_key(u"curve25519").pub().key_to_bin() if previous: self.key = previous.key MultiChainBlock.__init__(self, ( up, down, previous.total_up + up, previous.total_down + down, previous.public_key, previous.sequence_number + 1, other, 0, previous.hash, 0, 0)) else: self.key = crypto.generate_key(u"curve25519") MultiChainBlock.__init__(self, ( up, down, random.randint(241, 260), random.randint(261, 280), 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_get_num_interactors(self): """ Test whether the right number of interactors is returned """ crypto = ECCrypto() my_key = crypto.key_to_bin(crypto.generate_key(u"curve25519").pub()) block1 = TestBlock() block1.public_key_requester = my_key block1.up = 100 block1.down = 100 self.db.add_block(block1) block2 = TestBlock() block2.public_key_responder = my_key block2.up = 100 block2.down = 100 self.db.add_block(block2) self.assertEqual((2, 2), self.db.get_num_unique_interactors(my_key))
def initializeCrypto(self): try: from Tribler.dispersy.crypto import ECCrypto, NoCrypto except: from dispersy.crypto import ECCrypto, NoCrypto if environ.get('TRACKER_CRYPTO', 'ECCrypto') == 'ECCrypto': self._logger.debug('Turning on ECCrypto') return ECCrypto() self._logger.debug('Turning off Crypto') return NoCrypto()
def test_signature(self): """ Test signing a tick """ eccrypto = ECCrypto() keypair = eccrypto.generate_key(u"curve25519") sign_member = MockObject() sign_member.public_key = eccrypto.key_to_bin(keypair.pub()) sign_member.private_key = keypair self.tick.sign(sign_member) self.assertFalse(self.tick.has_valid_signature() ) # Trader ID does not match public key self.tick._order_id = OrderId( TraderId( hashlib.sha1(sign_member.public_key).digest().encode('hex')), OrderNumber(1)) self.assertTrue(self.tick.has_valid_signature()) self.tick._signature = 'a' * 64 self.assertFalse(self.tick.has_valid_signature())
def __init__(self): crypto = ECCrypto() key_requester = crypto.generate_key(u"curve25519") key_responder = crypto.generate_key(u"curve25519") # Random payload but unique numbers. sequence_number_requester = random.randint(50, 100) sequence_number_responder = random.randint(101, 200) up = random.randint(201, 220) down = random.randint(221, 240) total_up_requester = random.randint(241, 260) total_down_requester = random.randint(261, 280) total_up_responder = random.randint(281, 300) total_down_responder = random.randint(301, 320) # A random hash is generated for the previous hash. It is only used to test if a hash can be persisted. previous_hash_requester = sha256(str(random.randint(0, 100000))).digest() public_key_requester = crypto.key_to_bin(key_requester.pub()) signature_requester = crypto.create_signature( key_requester, encode_signing_format([ up, down, total_up_requester, total_down_requester, sequence_number_requester, previous_hash_requester ])) # A random hash is generated for the hash. # TODO: Use the actual hash hash_requester = sha256(str(random.randint(0, 100000))).digest() # A random hash is generated for the previous hash. It is only used to test if a hash can be persisted. previous_hash_responder = sha256(str(random.randint(100001, 200000))).digest() public_key_responder = crypto.key_to_bin(key_responder.pub()) signature_responder = crypto.create_signature( key_responder, encode_signing_format([ up, down, total_up_requester, total_down_requester, sequence_number_requester, previous_hash_requester, total_up_responder, total_down_responder, sequence_number_responder, previous_hash_responder ])) # A random hash is generated for the hash. # TODO: Use the actual hash hash_responder = sha256(str(random.randint(0, 100000))).digest() DatabaseBlock.__init__( self, (public_key_requester, public_key_responder, up, down, total_up_requester, total_down_requester, sequence_number_requester, previous_hash_requester, signature_requester, hash_requester, total_up_responder, total_down_responder, sequence_number_responder, previous_hash_responder, signature_responder, hash_responder, None))
class TestCommunity(Community): crypto = ECCrypto() def __init__(self): self.key = self.crypto.generate_key(u"medium") self.pk = self.crypto.key_to_bin(self.key.pub()) self.meta_message_cache = {} self._cid = sha1(self.pk).digest() self._meta_messages = {} self._initialize_meta_messages() self._global_time = 0 self._do_pruning = False self._logger = logging.getLogger(self.__class__.__name__) self._conversions = self.initiate_conversions() def initiate_meta_messages(self): return super(TestCommunity, self).initiate_meta_messages() + [ Message(self, HALF_BLOCK_BROADCAST, NoAuthentication(), PublicResolution(), DirectDistribution(), NHopCommunityDestination(10, depth=2), HalfBlockPayload(), lambda: None, lambda: None), Message(self, HALF_BLOCK, NoAuthentication(), PublicResolution(), DirectDistribution(), CandidateDestination(), HalfBlockPayload(), lambda: None, lambda: None), Message(self, BLOCK_PAIR, NoAuthentication(), PublicResolution(), DirectDistribution(), CandidateDestination(), BlockPairPayload(), lambda: None, lambda: None), Message(self, BLOCK_PAIR_BROADCAST, NoAuthentication(), PublicResolution(), DirectDistribution(), NHopCommunityDestination(10, depth=2), BlockPairPayload(), lambda: None, lambda: None), Message(self, CRAWL, NoAuthentication(), PublicResolution(), DirectDistribution(), CandidateDestination(), CrawlRequestPayload(), lambda: None, lambda: None) ] def initiate_conversions(self): return [DefaultConversion(self), TrustChainConversion(self)]
def validate(self, database): """ Validates this block against what is known in the database :param database: the database to check against :return: A tuple consisting of a ValidationResult and a list of user string errors """ # we start off thinking everything is hunky dory result = [ValidationResult.valid] errors = [] crypto = ECCrypto() # short cut for invalidating so we don't have repeating similar code for every error. # this is also the reason result is a list, we need a mutable container. Assignments in err are limited to its # scope. So setting result directly is not possible. def err(reason): result[0] = ValidationResult.invalid errors.append(reason) # Step 1: get all related blocks from the database. # The validity of blocks is immutable. Once they are accepted they cannot change validation result. In such # cases subsequent blocks can get validation errors and will not get inserted into the database. Thus we can # assume that all retrieved blocks are not invalid themselves. Blocks can get inserted into the database in any # order, so we need to find successors, predecessors as well as the block itself and its linked block. blk = database.get(self.public_key, self.sequence_number) link = database.get_linked(self) prev_blk = database.get_block_before(self) next_blk = database.get_block_after(self) # Step 2: determine the maximum validation level # Depending on the blocks we get from the database, we can decide to reduce the validation level. We must do # this prior to flagging any errors. This way we are only ever reducing the validation level without having to # resort to min()/max() every time we set it. We first determine some booleans to make everything readable. is_genesis = self.sequence_number == GENESIS_SEQ or self.previous_hash == GENESIS_HASH is_prev_gap = prev_blk.sequence_number != self.sequence_number - 1 if prev_blk else True is_next_gap = next_blk.sequence_number != self.sequence_number + 1 if next_blk else True if not prev_blk and not next_blk: # Is this block a non genesis block? If so, we know nothing about this public key, else pretend the # prev_blk exists if not is_genesis: result[0] = ValidationResult.no_info else: # We pretend prev_blk exists. This leaves us with next missing, which means partial-next at best. result[0] = ValidationResult.partial_next elif not prev_blk and next_blk: # Is this block a non genesis block? if not is_genesis: # We are really missing prev_blk. So now partial-prev at best. result[0] = ValidationResult.partial_previous if is_next_gap: # Both sides are unknown or non-contiguous return a full partial result. result[0] = ValidationResult.partial elif is_next_gap: # This is a genesis block, so the missing previous is expected. If there is a gap to the next block # this reduces the validation result to partial-next result[0] = ValidationResult.partial_next elif prev_blk and not next_blk: # We are missing next_blk, so now partial-next at best. result[0] = ValidationResult.partial_next if is_prev_gap: # Both sides are unknown or non-contiguous return a full partial result. result[0] = ValidationResult.partial else: # both sides have known blocks, see if there are gaps if is_prev_gap and is_next_gap: result[0] = ValidationResult.partial elif is_prev_gap: result[0] = ValidationResult.partial_previous elif is_next_gap: result[0] = ValidationResult.partial_next # Step 3: validate that the block is sane # Some basic self tests. It is possible to violate these when constructing a block in code or getting a block # from the database. The wire format is such that it impossible to hit many of these for blocks that went over # the network. if self.up < 0: err("Up field is negative") if self.down < 0: err("Down field is negative") if self.down == 0 and self.up == 0: # In this case the block doesn't modify any counters, these block are without purpose and are thus invalid. err("Up and down are zero") if self.total_up < 0: err("Total up field is negative") if self.total_down < 0: err("Total down field is negative") if self.sequence_number < GENESIS_SEQ: err("Sequence number is prior to genesis") if self.link_sequence_number < GENESIS_SEQ and self.link_sequence_number != UNKNOWN_SEQ: err("Link sequence number not empty and is prior to genesis") if not crypto.is_valid_public_bin(self.public_key): err("Public key is not valid") else: # If the public key is valid, we can use it to check the signature. We want just a yes/no answer here, and # we want to keep checking for more errors, so just catch all packing exceptions and err() if any happen. try: pck = self.pack(signature=False) except: pck = None if pck is None or not crypto.is_valid_signature( crypto.key_from_public_bin(self.public_key), pck, self.signature): err("Invalid signature") if not crypto.is_valid_public_bin(self.link_public_key): err("Linked public key is not valid") if self.public_key == self.link_public_key: # Blocks to self serve no purpose and are thus invalid. err("Self signed block") if is_genesis: if self.sequence_number == GENESIS_SEQ and self.previous_hash != GENESIS_HASH: err("Sequence number implies previous hash should be Genesis ID" ) if self.sequence_number != GENESIS_SEQ and self.previous_hash == GENESIS_HASH: err("Sequence number implies previous hash should not be Genesis ID" ) if self.total_up != self.up: err("Genesis block invalid total_up and/or up") if self.total_down != self.down: err("Genesis block invalid total_down and/or down") # Step 4: does the database already know about this block? If so it should be equal or else we caught a # branch in someones multichain. if blk: # Sanity check to see if the database returned the expected block, we want to cover all our bases before # crying wolf and making a fraud claim. assert blk.public_key == self.public_key and blk.sequence_number == self.sequence_number, \ "Database returned unexpected block" if blk.up != self.up: err("Up does not match known block") if blk.down != self.down: err("Down does not match known block") if blk.total_up != self.total_up: err("Total up does not match known block") if blk.total_down != self.total_down: err("Total down does not match known block") if blk.link_public_key != self.link_public_key: err("Link public key does not match known block") if blk.link_sequence_number != self.link_sequence_number: err("Link sequence number does not match known block") if blk.previous_hash != self.previous_hash: err("Previous hash does not match known block") if blk.signature != self.signature: err("Signature does not match known block") # if the known block is not equal, and the signatures are valid, we have a double signed PK/seq. Fraud! if self.hash != blk.hash and "Invalid signature" not in errors and "Public key is not valid" not in errors: err("Double sign fraud") # Step 5: does the database have the linked block? If so do the values match up? If the values do not match up # someone comitted fraud, but it is impossible to decide who. So we just invalidate the block that is the latter # to get validated. We can also detect double counter sign fraud at this point. if link: # Sanity check to see if the database returned the expected block, we want to cover all our bases before # crying wolf and making a fraud claim. assert link.public_key == self.link_public_key and \ (link.link_sequence_number == self.sequence_number or link.sequence_number == self.link_sequence_number), \ "Database returned unexpected block" if self.public_key != link.link_public_key: err("Public key mismatch on linked block") elif self.link_sequence_number != UNKNOWN_SEQ: # self counter signs another block (link). If link has a linked block that is not equal to self, # then self is fraudulent, since it tries to countersign a block that is already countersigned linklinked = database.get_linked(link) if linklinked is not None and linklinked.hash != self.hash: err("Double countersign fraud") if self.up != link.down: err("Up/down mismatch on linked block") if self.down != link.up: err("Down/up mismatch on linked block") # Step 6: Did we get blocks from the database before or after self? They should be checked for violations too. if prev_blk: # Sanity check of the block the database gave us. assert prev_blk.public_key == self.public_key and prev_blk.sequence_number < self.sequence_number,\ "Database returned unexpected block" if prev_blk.total_up + self.up > self.total_up: err("Total up is lower than expected compared to the preceding block" ) if prev_blk.total_down + self.down > self.total_down: err("Total down is lower than expected compared to the preceding block" ) if not is_prev_gap and prev_blk.hash != self.previous_hash: err("Previous hash is not equal to the hash id of the previous block" ) # Is this fraud? It is certainly an error, but fixing it would require a different signature on the same # sequence number which is fraud. if next_blk: # Sanity check of the block the database gave us. assert next_blk.public_key == self.public_key and next_blk.sequence_number > self.sequence_number,\ "Database returned unexpected block" if self.total_up + next_blk.up > next_blk.total_up: err("Total up is higher than expected compared to the next block" ) # In this case we could say there is fraud too, since the counters are too high. Also anyone that # counter signed any such counters should be suspected since they apparently failed to validate or put # their signature on it regardless of validation status. But it is not immediately clear where this # error occurred, it might be lower on the chain than self. So it is hard to create a fraud proof here if self.total_down + next_blk.down > next_blk.total_down: err("Total down is higher than expected compared to the next block" ) # See previous comment if not is_next_gap and next_blk.previous_hash != self.hash: err("Next hash is not equal to the hash id of the block") # Again, this might not be fraud, but fixing it can only result in fraud. return result[0], errors
class TestTunnelBase(TestAsServer): @blocking_call_on_reactor_thread @inlineCallbacks def setUp(self, autoload_discovery=True): """ Setup various variables and load the tunnel community in the main downloader session. """ yield TestAsServer.setUp(self, autoload_discovery=autoload_discovery) self.seed_tdef = None self.sessions = [] self.session2 = None self.crypto_enabled = True self.bypass_dht = False self.seed_config = None self.tunnel_community_seeder = None self.eccrypto = ECCrypto() ec = self.eccrypto.generate_key(u"curve25519") HiddenTunnelCommunityTests.master_key = self.eccrypto.key_to_bin( ec.pub()).encode('hex') self.tunnel_community = self.load_tunnel_community_in_session( self.session, exitnode=True) self.tunnel_communities = [] def setUpPreSession(self): TestAsServer.setUpPreSession(self) self.config.set_dispersy_enabled(True) self.config.set_libtorrent_enabled(True) self.config.set_tunnel_community_socks5_listen_ports( self.get_socks5_ports()) @blocking_call_on_reactor_thread @inlineCallbacks def tearDown(self): if self.session2: yield self.session2.shutdown() for session in self.sessions: yield session.shutdown() yield TestAsServer.tearDown(self) @inlineCallbacks def setup_nodes(self, num_relays=1, num_exitnodes=1, seed_hops=0): """ Setup all required nodes, including the relays, exit nodes and seeder. """ assert isInIOThread() baseindex = 3 for i in xrange(baseindex, baseindex + num_relays): # Normal relays proxy = yield self.create_proxy(i) self.tunnel_communities.append(proxy) baseindex += num_relays + 1 for i in xrange(baseindex, baseindex + num_exitnodes): # Exit nodes proxy = yield self.create_proxy(i, exitnode=True) self.tunnel_communities.append(proxy) # Setup the seeder session self.setup_tunnel_seeder(seed_hops) # Add the tunnel community of the downloader session self.tunnel_communities.append(self.tunnel_community) # Connect the candidates with each other in all available tunnel communities candidates = [] for session in self.sessions: self._logger.debug( "Appending candidate from this session to the list") candidates.append( Candidate(session.get_dispersy_instance().lan_address, tunnel=False)) communities_to_inject = self.tunnel_communities if self.tunnel_community_seeder is not None: communities_to_inject.append(self.tunnel_community_seeder) for community in communities_to_inject: for candidate in candidates: self._logger.debug( "Add appended candidate as discovered candidate to this community" ) # We are letting dispersy deal with adding the community's candidate to itself. community.add_discovered_candidate(candidate) @blocking_call_on_reactor_thread def load_tunnel_community_in_session(self, session, exitnode=False): """ Load the tunnel community in a given session. We are using our own tunnel community here instead of the one used in Tribler. """ dispersy = session.get_dispersy_instance() keypair = dispersy.crypto.generate_key(u"curve25519") dispersy_member = dispersy.get_member( private_key=dispersy.crypto.key_to_bin(keypair)) settings = TunnelSettings(tribler_session=session) if not self.crypto_enabled: settings.crypto = NoCrypto() settings.become_exitnode = exitnode return dispersy.define_auto_load(HiddenTunnelCommunityTests, dispersy_member, (session, settings), load=True)[0] @inlineCallbacks def create_proxy(self, index, exitnode=False): """ Create a single proxy and load the tunnel community in the session of that proxy. """ from Tribler.Core.Session import Session self.setUpPreSession() config = self.config.copy() config.set_libtorrent_enabled(True) config.set_dispersy_enabled(True) config.set_state_dir(self.getStateDir(index)) config.set_tunnel_community_socks5_listen_ports( self.get_socks5_ports()) session = Session(config, autoload_discovery=False) yield session.start() self.sessions.append(session) returnValue( self.load_tunnel_community_in_session(session, exitnode=exitnode)) @blocking_call_on_reactor_thread @inlineCallbacks def setup_tunnel_seeder(self, hops): """ Setup the seeder. """ from Tribler.Core.Session import Session self.seed_config = self.config.copy() self.seed_config.set_state_dir(self.getStateDir(2)) self.seed_config.set_megacache_enabled(True) self.seed_config.set_tunnel_community_socks5_listen_ports( self.get_socks5_ports()) if self.session2 is None: self.session2 = Session(self.seed_config, autoload_discovery=False) self.session2.start() tdef = TorrentDef() tdef.add_content(os.path.join(TESTS_DATA_DIR, "video.avi")) tdef.set_tracker("http://localhost/announce") tdef.finalize() torrentfn = os.path.join(self.session2.config.get_state_dir(), "gen.torrent") tdef.save(torrentfn) self.seed_tdef = tdef if hops > 0: # Safe seeding enabled self.tunnel_community_seeder = self.load_tunnel_community_in_session( self.session2) self.tunnel_community_seeder.build_tunnels(hops) from twisted.internet import reactor, task while not list( self.tunnel_community_seeder.active_data_circuits()): yield task.deferLater(reactor, .05, lambda: None) dscfg = DownloadStartupConfig() dscfg.set_dest_dir( TESTS_DATA_DIR) # basedir of the file we are seeding dscfg.set_hops(hops) d = self.session2.start_download_from_tdef(tdef, dscfg) d.set_state_callback(self.seeder_state_callback) def seeder_state_callback(self, ds): """ The callback of the seeder download. For now, this only logs the state of the download that's seeder and is useful for debugging purposes. """ if self.tunnel_community_seeder: self.tunnel_community_seeder.monitor_downloads([ds]) d = ds.get_download() self._logger.debug("seeder: %s %s %s", repr(d.get_def().get_name()), dlstatus_strings[ds.get_status()], ds.get_progress()) return 5.0, False def start_anon_download(self, hops=1): """ Start an anonymous download in the main Tribler session. """ dscfg = DownloadStartupConfig() dscfg.set_dest_dir(self.getDestDir()) dscfg.set_hops(hops) download = self.session.start_download_from_tdef(self.seed_tdef, dscfg) download.add_peer( ("127.0.0.1", self.session2.config.get_libtorrent_port())) return download
def test_sign(self): crypto = ECCrypto() block = TestBlock() self.assertTrue( crypto.is_valid_signature(block.key, block.pack(signature=False), block.signature))
def has_valid_signature(self): crypto = ECCrypto() mid_match = hashlib.sha1(self._public_key).digest().encode('hex') == str(self.order_id.trader_id) return crypto.is_valid_signature( crypto.key_from_public_bin(self._public_key), self.get_sign_data(), self._signature) and mid_match
class TestMarketBase(TestAsServer): def async_sleep(self, secs): d = Deferred() reactor.callLater(secs, d.callback, None) return d @blocking_call_on_reactor_thread @inlineCallbacks def setUp(self, autoload_discovery=True): """ Setup various variables. """ os.environ[BOOTSTRAP_FILE_ENVNAME] = os.path.join( TESTS_DATA_DIR, 'bootstrap_empty.txt') yield TestAsServer.setUp(self, autoload_discovery=autoload_discovery) self.sessions = [] self.eccrypto = ECCrypto() ec = self.eccrypto.generate_key(u"curve25519") MarketCommunityTests.master_key = self.eccrypto.key_to_bin( ec.pub()).encode('hex') ec = self.eccrypto.generate_key(u"curve25519") TriblerChainCommunityTests.master_key = self.eccrypto.key_to_bin( ec.pub()).encode('hex') market_member = self.generate_member(self.session) self.market_communities = {} mc_community = self.load_triblerchain_community_in_session( self.session) self.load_market_community_in_session(self.session, market_member, mc_community) @blocking_call_on_reactor_thread @inlineCallbacks def tearDown(self, annotate=True): for session in self.sessions: yield session.shutdown() yield TestAsServer.tearDown(self) def setUpPreSession(self): TestAsServer.setUpPreSession(self) self.config.set_dispersy_enabled(True) self.config.set_libtorrent_enabled(False) self.config.set_video_server_enabled(False) self.config.set_trustchain_enabled(False) self.config.set_tunnel_community_enabled(False) self.config.set_market_community_enabled(False) def generate_member(self, session): dispersy = session.get_dispersy_instance() keypair = dispersy.crypto.generate_key(u"curve25519") return dispersy.get_member( private_key=dispersy.crypto.key_to_bin(keypair)) @blocking_call_on_reactor_thread def load_market_community_in_session(self, session, market_member, mc_community): """ Load the market community and tradechain community in a given session. """ wallets = { 'BTC': BitcoinWallet( os.path.join(session.config.get_state_dir(), 'wallet')), 'MC': TrustchainWallet(mc_community), 'DUM1': DummyWallet1(), 'DUM2': DummyWallet2() } wallets['MC'].check_negative_balance = False dispersy = session.get_dispersy_instance() # Load MarketCommunity market_kargs = {'tribler_session': session, 'wallets': wallets} self.market_communities[session] = dispersy.define_auto_load( MarketCommunityTests, market_member, kargs=market_kargs, load=True)[0] return self.market_communities[session] @blocking_call_on_reactor_thread def load_triblerchain_community_in_session(self, session): """ Load a custom instance of the TriblerChain community in a given session. """ dispersy = session.get_dispersy_instance() keypair = dispersy.crypto.generate_key(u"curve25519") dispersy_member = dispersy.get_member( private_key=dispersy.crypto.key_to_bin(keypair)) triblerchain_kwargs = {'tribler_session': session} return dispersy.define_auto_load(TriblerChainCommunityTests, dispersy_member, load=True, kargs=triblerchain_kwargs)[0] @inlineCallbacks def create_session(self, index): """ Create a single session and load the tunnel community in the session of that proxy. """ from Tribler.Core.Session import Session config = self.config.copy() config.set_state_dir(self.getStateDir(index)) session = Session(config, autoload_discovery=False) yield session.start() self.sessions.append(session) market_member = self.generate_member(session) mc_community = self.load_triblerchain_community_in_session(session) self.load_market_community_in_session(session, market_member, mc_community) returnValue(session)