示例#1
0
    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)
示例#2
0
        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)
示例#3
0
 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)
示例#5
0
 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)
示例#6
0
 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())
示例#7
0
    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]
示例#8
0
 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)
示例#9
0
    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)]
示例#13
0
    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)
示例#15
0
    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))
示例#16
0
    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()
示例#17
0
    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())
示例#18
0
    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))
示例#19
0
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)]
示例#20
0
文件: block.py 项目: Solertis/tribler
    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
示例#22
0
 def test_sign(self):
     crypto = ECCrypto()
     block = TestBlock()
     self.assertTrue(
         crypto.is_valid_signature(block.key, block.pack(signature=False),
                                   block.signature))
示例#23
0
    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)