Beispiel #1
0
def send_bundle(trytes):
    gtta = api.get_transactions_to_approve(depth=3)
    trunk = str(gtta['trunkTransaction'])  # set a non-tail to fail rule 1
    branch = str(gtta['branchTransaction'])  #set a non-tail to fail rule 1

    attached_trytes = api.attach_to_tangle(trunk, branch, trytes,
                                           9).get('trytes')
    api.broadcast_and_store(attached_trytes)
    bundle = Bundle.from_tryte_strings(attached_trytes)
    pprint('Bundle is:')
    pprint(bundle.as_json_compatible())
    return attached_trytes
Beispiel #2
0
    async def test_validator_error(self):
        """
        TraverseBundleCommand returns bundle but it is invalid.
        """
        # Make the returned bundle invalid
        bundle = Bundle.from_tryte_strings(self.bundle_trytes)
        bundle.transactions[0].value = 999  # Unbalanced bundle

        for txn in bundle.transactions:
            self.adapter.seed_response('getTrytes', {
                'trytes': [txn.as_tryte_string()],
        })

        self.adapter.seed_response('getTrytes', {
            'trytes': [self.spam_trytes],
        })

        with self.assertRaises(BadApiResponse):
            response = await self.command(transactions = [self.tx_hash])
Beispiel #3
0
    async def test_correct_transfer(self):
        """
        Tests the good weather case for transfers
        """
        bundle = Bundle([self.tx2])
        self.wallet.create_wallet()

        # Set up mocks.
        self.wallet.get_balance = lambda: \
            succeed({'available': 42, 'pending': 0, 'currency': self.identifier, 'precision': 0})
        self.wallet.provider.submit_transaction = lambda transaction: succeed(
            bundle)
        self.wallet.provider.get_all_bundles = lambda: succeed([bundle])
        self.wallet.provider.get_seed_transactions = lambda: succeed(
            [self.tx2])
        # Send a correct transfer
        result = await self.wallet.transfer(1, self.tx2.address.__str__())
        # Update the database
        await self.wallet.update_transactions_database()
        await self.wallet.update_bundles_database()
        # Check correct bundle storage
        all_bundles = self.wallet.database.query(DatabaseBundle) \
            .all()
        # Get the bundle sent in the transaction
        bundle_query = self.wallet.database.query(DatabaseBundle) \
            .filter(DatabaseBundle.hash.__eq__(bundle.hash.__str__())) \
            .all()
        self.assertEqual(len(all_bundles), 1)
        self.assertEqual(bundle_query, all_bundles)

        # Check correct transaction storage
        all_txs = self.wallet.database.query(DatabaseTransaction) \
            .all()
        # Get the transaction that's part of the bundle
        tx_query = self.wallet.database.query(DatabaseTransaction) \
            .filter(DatabaseTransaction.hash.__eq__(self.tx2.hash.__str__())) \
            .all()
        self.assertEqual(len(all_txs), 1)
        self.assertEqual(all_txs, tx_query)

        # Assert correct return value
        self.assertEqual(bundle.hash.__str__(), result)
        self.wallet.cancel_all_pending_tasks()
Beispiel #4
0
    async def test_happy_path(self):
        """
        Get a bundle with multiple transactions.
        """
        for txn_trytes in self.bundle_trytes:
            self.adapter.seed_response('getTrytes', {
                'trytes': [txn_trytes],
            })

        self.adapter.seed_response('getTrytes', {
            'trytes': [self.spam_trytes],
        })

        response = await self.command(transactions = [self.tx_hash])

        self.maxDiff = None
        original_bundle = Bundle.from_tryte_strings(self.bundle_trytes)
        self.assertListEqual(
            response['bundles'][0].as_json_compatible(),
            original_bundle.as_json_compatible(),
        )
Beispiel #5
0
    def _execute(self, request):
        transaction_hash = request['transaction']  # type: TransactionHash

        bundle = Bundle(self._traverse_bundle(transaction_hash))
        validator = BundleValidator(bundle)

        if not validator.is_valid():
            raise with_context(
                exc=BadApiResponse(
                    'Bundle failed validation (``exc.context`` has more info).',
                ),
                context={
                    'bundle': bundle,
                    'errors': validator.errors,
                },
            )

        return {
            # Always return a list, so that we have the necessary structure
            # to return multiple bundles in a future iteration.
            'bundles': [bundle],
        }
Beispiel #6
0
  def _execute(self, request):
    change_address        = request['changeAddress'] # type: Optional[Address]
    depth                 = request['depth'] # type: int
    inputs                = request['inputs'] # type: Optional[List[Address]]
    min_weight_magnitude  = request['minWeightMagnitude'] # type: int
    seed                  = request['seed'] # type: Seed
    transfers             = request['transfers'] # type: List[ProposedTransaction]

    pt_response = PrepareTransferCommand(self.adapter)(
      changeAddress   = change_address,
      inputs          = inputs,
      seed            = seed,
      transfers       = transfers,
    )

    st_response = SendTrytesCommand(self.adapter)(
      depth               = depth,
      minWeightMagnitude  = min_weight_magnitude,
      trytes              = pt_response['trytes'],
    )

    return {
      'bundle': Bundle.from_tryte_strings(st_response['trytes']),
    }
Beispiel #7
0
    def test_wrongly_ordered_bundle(self):
        """
        Supply bundle trytes in wrong order.
        `attach_to_tangle` constructs a bundle object from the trytes,
        that should reorder transactions in correct order based on index.
        """
        wrong_bundle_trytes = []
        for txn in reversed(self.bundle.as_tryte_strings()):
            wrong_bundle_trytes.append(txn)

        test_trytes = ccurl_interface.attach_to_tangle(wrong_bundle_trytes,
                                                       self.branch,
                                                       self.trunk,
                                                       mwm=14)

        test_bundle = Bundle.from_tryte_strings(test_trytes)

        validator = BundleValidator(test_bundle)
        if not validator.is_valid():
            raise ValueError(
                'Bundle failed validation:\n{errors}'.format(errors='\n'.join(
                    ('  - ' + e) for e in validator.errors), ), )

        self.assertTrue(validator.is_valid())
Beispiel #8
0
    def _execute(self, request):
        change_address = request['changeAddress']  # type: Optional[Address]
        depth = request['depth']  # type: int
        inputs = request['inputs']  # type: Optional[List[Address]]
        min_weight_magnitude = request['minWeightMagnitude']  # type: int
        seed = request['seed']  # type: Seed
        transfers = request['transfers']  # type: List[ProposedTransaction]

        pt_response = PrepareTransferCommand(self.adapter)(
            changeAddress=change_address,
            inputs=inputs,
            seed=seed,
            transfers=transfers,
        )

        st_response = SendTrytesCommand(self.adapter)(
            depth=depth,
            minWeightMagnitude=min_weight_magnitude,
            trytes=pt_response['trytes'],
        )

        return {
            'bundle': Bundle.from_tryte_strings(st_response['trytes']),
        }
Beispiel #9
0
    def test_full_scan(self):
        """
    Scanning the Tangle for all transfers.
    """

        # To speed up the test, we will mock the address generator.
        # :py:class:`iota.crypto.addresses.AddressGenerator` already has
        # its own test case, so this does not impact the stability of the
        # codebase.
        # noinspection PyUnusedLocal
        def create_generator(ag, start, step=1):
            for addy in [self.addy1, self.addy2][start::step]:
                yield addy

        # The first address received IOTA.
        self.adapter.seed_response(
            'findTransactions',
            {
                'duration':
                42,
                'hashes': [
                    'TESTVALUEFIVE9DONTUSEINPRODUCTION99999VH'
                    'YHRHJETGYCAFZGABTEUBWCWAS9WF99UHBHRHLIOFJ',
                ],
            },
        )

        # The second address is unused.
        self.adapter.seed_response(
            'findTransactions',
            {
                'duration': 1,
                'hashes': [],
            },
        )

        self.adapter.seed_response(
            'getTrytes',
            {
                'duration': 99,

                # Thankfully, we do not have to seed a realistic response for
                # ``getTrytes``, as we will be mocking the ``getBundles``
                # command that uses on it.
                'trytes': [''],
            },
        )

        bundle = Bundle([
            Transaction(
                address=self.addy1,
                timestamp=1483033814,

                # These values are not relevant to the test.
                hash_=None,
                signature_message_fragment=None,
                value=42,
                tag=Tag(b''),
                current_index=0,
                last_index=0,
                bundle_hash=None,
                trunk_transaction_hash=None,
                branch_transaction_hash=None,
                attachment_timestamp=1483033814,
                attachment_timestamp_lower_bound=12,
                attachment_timestamp_upper_bound=0,
                nonce=None,
            )
        ])

        mock_get_bundles = \
            mock.Mock(return_value={
                'bundles': [bundle],
            })

        with mock.patch(
                'iota.crypto.addresses.AddressGenerator.create_iterator',
                create_generator,
        ):
            with mock.patch(
                    'iota.commands.extended.get_bundles.GetBundlesCommand._execute',
                    mock_get_bundles,
            ):
                response = self.command(seed=Seed.random())

        self.assertDictEqual(
            response,
            {
                'bundles': [bundle],
            },
        )
Beispiel #10
0
    def execute(self, api, **arguments):
        # type: (Iota, ...) -> int
        channel_key_index = arguments['channel_key_index']  # type: int
        count = arguments['count']  # type: int
        depth = arguments['depth']  # type: int
        dry_run = arguments['dry_run']  # type: bool
        mam_encrypt_path = arguments['mam_encrypt_path']  # type: Text
        min_weight_magnitude = arguments['min_weight_magnitude']  # type: int
        message_encoding = arguments['message_encoding']  # type: Text
        message_file = arguments['message_file']  # type: Optional[Text]
        security_level = arguments['security_level']  # type: int
        start = arguments['start']  # type: int

        if message_file:
            with codecs.open(
                    message_file, 'r',
                    message_encoding) as f_:  # type: codecs.StreamReaderWriter
                message = f_.read()

        else:
            self.stdout.write(
                'Enter message to send.  Press Ctrl-D on a blank line when done.\n\n',
            )

            message = self.stdin.read().strip()
            self.stdout.write('\n')

        # Generating the encrypted message may take a little while, so we
        # should provide some feedback to the user so that they know that
        # their input is being processed (this is especially important if
        # the user typed in their message, so that they don't press ^D
        # again, thinking that the program didn't register the first one).
        self.stdout.write('Encrypting message...\n')

        proc =\
          run(
            args = [
              # mam_encrypt.js
              mam_encrypt_path,

              # Required arguments
              binary_type(api.seed),
              message,

              # Options
              '--channel-key-index', text_type(channel_key_index),
              '--start', text_type(start),
              '--count', text_type(count),
              '--security-level', text_type(security_level),
            ],

            check   = True,
            stdout  = PIPE,
            stderr  = self.stderr,
          )

        # The output of the JS script is a collection of transaction
        # trytes, encoded as JSON.
        filter_ =\
          f.FilterRunner(
            starting_filter =
                f.Required
              | f.Unicode
              | f.JsonDecode
              | f.Array
              | f.FilterRepeater(
                    f.ByteString(encoding='ascii')
                  | Trytes(result_type=TransactionTrytes)
                ),

            incoming_data = proc.stdout,
          )

        if not filter_.is_valid():
            self.stderr.write(
                'Invalid output from {mam_encrypt_path}:\n'
                '\n'
                'Output:\n'
                '{output}\n'
                '\n'
                'Errors:\n'
                '{errors}\n'.format(
                    errors=pformat(filter_.get_errors(with_context=True)),
                    mam_encrypt_path=mam_encrypt_path,
                    output=proc.stdout,
                ), )

            return 2

        transaction_trytes = filter_.cleaned_data  # type: List[TransactionTrytes]

        bundle = Bundle.from_tryte_strings(transaction_trytes)

        if dry_run:
            self.stdout.write('Transactions:\n\n')
            self.stdout.write(json.dumps(bundle, cls=JsonEncoder, indent=2))
        else:
            api.send_trytes(
                depth=depth,
                trytes=transaction_trytes,
                min_weight_magnitude=min_weight_magnitude,
            )

            self.stdout.write('Message broadcast successfully!\n')
            self.stdout.write(
                'Bundle ID: {bundle_hash}\n'.format(
                    bundle_hash=bundle.hash, ), )

        return 0
Beispiel #11
0
    def test_happy_path(self):
        """
    Successfully replaying a bundle.
    """
        # noinspection SpellCheckingInspection
        bundle = Bundle([
            # "Spend" transaction, Part 1 of 1
            Transaction(
                hash_=TransactionHash(
                    b'LUQJUUDAZIHSTPBLCZYXWXYKXTFCOCQJ9EHXKLEB'
                    b'IJBPSRFSBYRBYODDAZ9NPKPYSMPVNEFXYZQ999999'),
                address=Address(b'FZXUHBBLASPIMBDIHYTDFCDFIRII9LRJPXFTQTPO'
                                b'VLEIFE9NWTFPPQZHDCXYUOUCXHHNRPKCIROYYTWSA'),
                branch_transaction_hash=TransactionHash(
                    b'UKGIAYNLALFGJOVUZYJGNIOZSXBBZDXVQLUMHGQE'
                    b'PZJWYDMGTPJIQXS9GOKXR9WIGWFRWRSKGCJ999999'),
                bundle_hash=BundleHash(
                    b'ZSATLX9HDENCIARERVLWYHXPQETFL9QKTNC9LUOL'
                    b'CDXKKW9MYTLZJDXBNOHURUXSYWMGGD9UDGLHCSZO9'),
                nonce=Nonce(b'LIJVXBVTYMEEPCKJRIQTGAKWJRA'),
                trunk_transaction_hash=TransactionHash(
                    b'KFCQSGDYENCECCPNNZDVDTBINCBRBERPTQIHFH9G'
                    b'YLTCSGUFMVWWSAHVZFXDVEZO9UHAUIU9LNX999999'),
                signature_message_fragment=Fragment(b''),
                current_index=0,
                last_index=3,
                tag=Tag(b''),
                timestamp=1483033814,
                value=1,
                attachment_timestamp=0,
                attachment_timestamp_lower_bound=0,
                attachment_timestamp_upper_bound=0,
            ),

            # Input #1, Part 1 of 2
            Transaction(
                hash_=TransactionHash(
                    b'KFCQSGDYENCECCPNNZDVDTBINCBRBERPTQIHFH9G'
                    b'YLTCSGUFMVWWSAHVZFXDVEZO9UHAUIU9LNX999999'),
                address=Address(b'GMHOSRRGXJLDPVWRWVSRWI9BCIVLUXWKTJYZATIA'
                                b'RAZRUCRGTWXWP9SZPFOVAMLISUPQUKHNDMITUJKIB'),
                branch_transaction_hash=TransactionHash(
                    b'UKGIAYNLALFGJOVUZYJGNIOZSXBBZDXVQLUMHGQE'
                    b'PZJWYDMGTPJIQXS9GOKXR9WIGWFRWRSKGCJ999999'),
                bundle_hash=BundleHash(
                    b'ZSATLX9HDENCIARERVLWYHXPQETFL9QKTNC9LUOL'
                    b'CDXKKW9MYTLZJDXBNOHURUXSYWMGGD9UDGLHCSZO9'),
                nonce=Nonce(b'VRYLDCKEWZJXPQVSWOJVYVBJSCW'),
                trunk_transaction_hash=TransactionHash(
                    b'QSTUKDIBYAZIQVEOMFGKQPHAIPBHUPSDQFFKKHRA'
                    b'ABYMYMQDHMTEWCM9IMZHQMGXOTWNSJYHRNA999999'),
                signature_message_fragment=Fragment(
                    b'XS9OVIXHIGGR9IYQBHGMFAHPZBWLIBNAQPFMPVYUZDOLLFDJIPZEMIOGVANQJSCU'
                    b'IPDNNUNAMWEL9OFXXK9NV9UTCRBYTARBJHPQYJYKNAQGMATG9EXQMHGXY9QOHPBA'
                    b'FEVABDYMCXORXHBMPLEWJYGYFFBWVXAUXHGLTABBKOQMZLFAYWDAKEOMJPJX9TMT'
                    b'GXIJXZTKRRIPAMYY9UNSPPEGFPJE9NFSJFWKYOFZRMPBXZDNQUEKLRUVPXMCTQRE'
                    b'ZWICSCVXN9VBLN9DRINRPAZTYJYXPGGRZJLMYXGCLUQNZ9NJGH9GFQPKKVK9N9WR'
                    b'IJXDNKUMLLJUVIQRGPHEVWTXQHRLRCWQJCHTPASCVLRGPNWSIUKWIBMDJJ9EUTQ9'
                    b'NXZZEJFWY9LCJJSOEPXWETUBKKVZNUKTLUPEPDBLUWCQGYTOXZ9NZUXHBDOUYQBP'
                    b'MNECVJ9HGWA9AWU9VHGETWKBU9YZEZGEQKMVTAKPLCZVWKQFXDEFBPKNUCQDSPWA'
                    b'LMPFTUFGRFDZH9PQHJ9WXZPCDWGMNASVVEUXEGWATM9ZIMCEEXTHCXFLYG9LQAKV'
                    b'UOGORP9UUWYFTWGZ9OFOGSP9KDNPDSQKEMMISEMWQDVFKCSQXSP9RUMNUQJOBACU'
                    b'MPIXCGBJLQQGB9GDSMUUUSYWIY9ZNIAIZBJYTAJKJKZIBFPMGDWUEPXSO9HUJRNV'
                    b'QE9OTVUPKBVNVUBSILVZEDPC9AMEYAIATE9JEIQQWIMGCZXMHOPXPFUTEPJEATJN'
                    b'QWDFZQ9OGPNBFUHLJDJZQJLXCFEUDPZKVCPEBTNBRYNIIKJHUV9EUFVMB9AHTARQ'
                    b'DN9TZ9JPAPCEXSYHZPAQLBJMNQ9R9KPWVZLDLFNHYCCQBFVEPMEZSXAB9GOKGOGC'
                    b'SOVL9XJSAQYSECY9UUNSVQSJB9BZVYRUURNUDMZVBJTMIDQUKQLMVW99XFDWTOPR'
                    b'UBRPKS9BGEAQPIODAMJAILNCH9UVYVWSDCZXZWLO9XJJZ9FQOL9F9ZJDNGMUGFKJ'
                    b'PCYURGYBGYRVKPEBKMJPZZGDKZKT9UBFSJEELREWOYDQZVUPVSGPZYIDVOJGNTXC'
                    b'OFGCHBGVZPQDNRKAQNVJEYKYTKHTFBJRDMKVSHEWADNYIQOAUFXYMZKNJPLXGYFX'
                    b'DTCVDDBUHBDPG9WLNMWPSCCCGVTIOOLEECXKNVAYNNTDLJMDGDGSKOGWO9UYXTTF'
                    b'FCRZEDDQNN9ZODTETGMGGUXOYECGNMHGMGXHZSPODIBMBATJJHSPQHDUCZOMWQNI'
                    b'CUZG9LAMBOQRQQDIPIBMIDCIAJBBBNDUAIEMFCEASHPUJPFPPXNDUVGDNNYBRRTW'
                    b'SPXGXMCSUXYJSTFIRUIDNEUSVKNIDKIBRQNMEDCYQOMJYTMGRZLYHBUYXCRGSAXR'
                    b'ZVHTZEAKNAUKJPFGPOGQLTDMSOXR9NVOIAIMCBVWOF9FXAZUKKZKHJEGHFNLUB9B'
                    b'TGAICGQGAYZRRHSFIDTNIJPHIHCXTHQUSKJRSVAWFUXLBYA99QKMGLHDNUHOPEW9'
                    b'OFNWPDXXRVZREUIQKSVSDCFIJ99TSGSZ9KU9JGE9VXDVVOLMGNMUGSHUZAOFCIMK'
                    b'CPEWMG9IHUZAILQCANIUUG9JNEZMT9EONSN9CWWQOTFBEPZRTTJTQFSTQTBERKGE'
                    b'NGFFIYMZMCFBYNIOBPOFOIYPUMYYPRXEHUJEVVELOPNXAPCYFXQ9ORMSFICDOZTS'
                    b'GQOMDI9FKEKRIMZTWSIWMYAUSBIN9TPFSMQZCYGVPVWKSFZXPE9BP9ALNWQOVJGM'
                    b'SCSJSTNUTMUAJUIQTITPPOHG9NKIFRNXSCMDAEW9LSUCTCXITSTZSBYMPOMSMTXP'
                    b'CEBEOAUJK9STIZRXUORRQBCYJPCNHFKEVY9YBJL9QGLVUCSZKOLHD9BDNKIVJX9T'
                    b'PPXQVGAXUSQQYGFDWQRZPKZKKWB9ZBFXTUGUGOAQLDTJPQXPUPHNATSGILEQCSQX'
                    b'X9IAGIVKUW9MVNGKTSCYDMPSVWXCGLXEHWKRPVARKJFWGRYFCATYNZDTRZDGNZAI'
                    b'OULYHRIPACAZLN9YHOFDSZYIRZJEGDUZBHFFWWQRNOLLWKZZENKOWQQYHGLMBMPF'
                    b'HE9VHDDTBZYHMKQGZNCSLACYRCGYSFFTZQJUSZGJTZKKLWAEBGCRLXQRADCSFQYZ'
                    b'G9CM9VLMQZA'),
                current_index=1,
                last_index=3,
                tag=Tag(b''),
                timestamp=1483033814,
                value=-99,
                attachment_timestamp=0,
                attachment_timestamp_lower_bound=0,
                attachment_timestamp_upper_bound=0,
            ),

            # Input #1, Part 2 of 2
            Transaction(
                hash_=TransactionHash(
                    b'QSTUKDIBYAZIQVEOMFGKQPHAIPBHUPSDQFFKKHRA'
                    b'ABYMYMQDHMTEWCM9IMZHQMGXOTWNSJYHRNA999999'),
                address=Address(b'GMHOSRRGXJLDPVWRWVSRWI9BCIVLUXWKTJYZATIA'
                                b'RAZRUCRGTWXWP9SZPFOVAMLISUPQUKHNDMITUJKIB'),
                branch_transaction_hash=TransactionHash(
                    b'UKGIAYNLALFGJOVUZYJGNIOZSXBBZDXVQLUMHGQE'
                    b'PZJWYDMGTPJIQXS9GOKXR9WIGWFRWRSKGCJ999999'),
                bundle_hash=BundleHash(
                    b'ZSATLX9HDENCIARERVLWYHXPQETFL9QKTNC9LUOL'
                    b'CDXKKW9MYTLZJDXBNOHURUXSYWMGGD9UDGLHCSZO9'),
                nonce=Nonce(b'AAKVYZOEZSOXTX9LOLHZYLNAS9C'),
                trunk_transaction_hash=TransactionHash(
                    b'ZYQGVZABMFVLJXHXXJMVAXOXHRJTTQUVDIIQOOXN'
                    b'NDPQGDFDRIDQMUWJGCQKKLGEUQRBFAJWZBC999999'),
                signature_message_fragment=Fragment(
                    b'YSNEGUCUHXEEFXPQEABV9ATGQMMXEVGMZWKKAFAVOVGUECOZZJFQDNRBCSXCOTBD'
                    b'BRUJ9HF9CITXQI9ZQGZFKCXMFZTOYHUTCXDIBIMTBKVXMMTPNKRDRLQESLWFZSQQ'
                    b'9BCGKVIZAHBWYTNXG9OWOXHAMQECMOVKN9SOEVJBBARPXUXYUQVFPYXWXQQMDIVP'
                    b'VITRWTNNBY9CYBHXJTZUVIPJJG9WLTNMFVPXGYZCNOGSLGVMS9YXXNSV9AYPXZTA'
                    b'QJYUNUFBCSZBZNKWCPMVMOGFIDENTOOOCPRDJTNGQRLA9YKMLYZQRO9QQJMCSYVF'
                    b'YLISFIWQQYMWMHUOEZPATYCEZARLWLAMCZWYWJZVD9WWKYJURTOLITFFRXQUBKST'
                    b'DG9CKDBLPXTPCIMKEKRGEXJGLRL9ZST9VOLV9NOFZLIMVOZBDZJUQISUWZKOJCRN'
                    b'YRBRJLCTNPV9QIWQJZDQFVPSTW9BJYWHNRVQTITWJYB9HBUQBXTAGK9BZCHYWYPE'
                    b'IREDOXCYRW9UXVSLZBBPAFIUEJABMBYKSUPNWVVKAFQJKDAYYRDICTGOTWWDSFLG'
                    b'BQFZZ9NBEHZHPHVQUYEETIRUDM9V9LBXFUXTUGUMZG9HRBLXCKMMWWMK9VTKVZSA'
                    b'PRSMJVBLFFDHTYCPDXKBUYYLZDPW9EVXANPZOPBASQUPRNCDGHNUK9NDUQSULUZI'
                    b'VMIJTPUGMZPCYR9AERBAGUYNGVEHWIIADAAPPMYQOAGBQCXEDTQOGHWHHSWDFZLC'
                    b'DVLNPYMGDPZWOZURT9OZKDJKFECXSFIALXJDRJWMWMTNUUNVDUCJAZLDRN9ZWLHH'
                    b'SNXDWULUBNLVRDJZQMKCTRCKULKS9VARFZSRYZCPNH9FHXCAFWKPNGOPOFMYXJLE'
                    b'LTKUHSZVDQRDJIGQRGOSKYWDCU9EBJMXQDBKTBNQTIZNCALHRNTHKN99WOBQVVEV'
                    b'HEDTDRKFPGLIWOSPLAAELQQXDCDWPIFED9OEUPYPKHZBOHPQGQGSEKO9BFIQFYZK'
                    b'YEULWSIBZVSPXBGOJTTYBVIIIPAXGL9ZJNNIELFYAUOUBRDWLJJMSAXHQOYGOWDV'
                    b'HHPISRZFSHPDLNQDFWRHLWNAJPYM9REAJLZDIAIVLQBFAUJIQKVHJDFPXENI9ZM9'
                    b'SFNGSQHDFEDC9CQVXAXTQVLWYMVSLEDCOVNSQLSANLVA9TWSY9BHAJKOCGI9YLAB'
                    b'VROCBJRVXRWBKNUXCAXJIAYWSFRDZHIPQSNBRYNKZAFXHDUENVLHFHYIKH9IANFV'
                    b'FKWVFJCSEELVTDDUHBPIYNFLTJLINNORIMDEAXMN9LGNGBWVWYWQIPWKBFDKNDOX'
                    b'WFKGBAMZIUFYA9DXGAL9OQQTJAUUXTINWZSQUTPUKUMOZCGOBKKFBXCVR9AGTAQS'
                    b'SVGTUBBHSIRHFRSIR9SKSZPXQFG9AOYAHZNQR9AHSEFCKWCJHUTLREDVGBQYVBZR'
                    b'CZDXFG9PTSAWQOURYKNWYAZNASV9UMUYUMFCQSFDHZD99WUMCORLYTIZMRGNBAY9'
                    b'UJYJMMRCLJP9XVLXTAZOHNVVYSCOSDHGUOPXIRBJDXJUCJYLQKUJOTNJCPRBDOKV'
                    b'ZEMIGZRNJOQKFFAXQVGGY9YRJORZCOD9REIIIDDTRQ9TJWTFYRKOPLAFNUUPCHXA'
                    b'WVPYUQXAFFCTYAESWAFUTQQYZRQVLVZW9OWAAJMPSAEPKWXVEZVTVPQEEBVXNZJP'
                    b'ZU9JJSIAEPIT9HE99XNAUYOAKRIFQQJQTFIMWEOKLCH9JKCQTGZPEGWORFB9ARNS'
                    b'DPYKRONBONYOGEVEFXGTMQTQBEMFQWEMIDSGAVEQHVHAPSMTCJ9FMEYBWAQWWJCE'
                    b'ABUUMMVNDMSBORFLHVIIDOUQHHXQKXTVGRAYTLMECCSVZOZM9JKUWIGGFLMMDGBU'
                    b'DBIHJFUINVOKSFTOGFCZEMIBSZNGPL9HXWGTNNAKYIMDITCRMSHFR9BDSFGHXQMR'
                    b'ACZOVUOTSJSKMNHNYIFEOD9CVBWYVVMG9ZDNR9FOIXSZSTIO9GLOLPLMW9RPAJYB'
                    b'WTCKV9JMSEVGD9ZPEGKXF9XYQMUMJPWTMFZJODFIEYNLI9PWODSPPW9MVJOWZQZU'
                    b'CIKXCVVXDKWHXV99GOEZ9CMGUH9OWGLLISNZEPSAPEDHVRKKGFFNGBXFLDBQTTQL'
                    b'WVLUITJQ9JM'),
                current_index=2,
                last_index=3,
                tag=Tag(b''),
                timestamp=1483033814,
                value=0,
                attachment_timestamp=0,
                attachment_timestamp_lower_bound=0,
                attachment_timestamp_upper_bound=0,
            ),

            # "Change" transaction, Part 1 of 1
            Transaction(
                hash_=TransactionHash(
                    b'ZYQGVZABMFVLJXHXXJMVAXOXHRJTTQUVDIIQOOXN'
                    b'NDPQGDFDRIDQMUWJGCQKKLGEUQRBFAJWZBC999999'),
                address=Address(b'YOTMYW9YLZQCSLHB9WRSTZDYYYGUUWLVDRHFQFEX'
                                b'UVOQARTQWZGLBU9DVSRDPCWYWQZHLFHY9NGLPZRAQ'),
                branch_transaction_hash=TransactionHash(
                    b'QCHKLZZBG9XQMNGCDVXZGDRXIJMFZP9XUGAWNNVP'
                    b'GXBWB9NVEKEFMUWOEACULFUR9Q9XCWPBRNF999999'),
                bundle_hash=BundleHash(
                    b'ZSATLX9HDENCIARERVLWYHXPQETFL9QKTNC9LUOL'
                    b'CDXKKW9MYTLZJDXBNOHURUXSYWMGGD9UDGLHCSZO9'),
                nonce=Nonce(b'TPGXQFUGNEYYFFKPFWJSXKTWEUK'),
                trunk_transaction_hash=TransactionHash(
                    b'UKGIAYNLALFGJOVUZYJGNIOZSXBBZDXVQLUMHGQE'
                    b'PZJWYDMGTPJIQXS9GOKXR9WIGWFRWRSKGCJ999999'),
                signature_message_fragment=Fragment(b''),
                current_index=3,
                last_index=3,
                tag=Tag(b''),
                timestamp=1483033814,
                value=98,
                attachment_timestamp=0,
                attachment_timestamp_lower_bound=0,
                attachment_timestamp_upper_bound=0,
            ),
        ])

        mock_get_bundles =\
          mock.Mock(return_value={
            'bundles': [bundle],
          })

        send_trytes_response = {
            'trytes': bundle.as_tryte_strings(),
        }

        def mock_send_trytes(_, request):
            """
      Ensures that the correct trytes are sent to the ``sendTrytes`` command
      to replay the bundle.

      References:
        - https://github.com/iotaledger/iota.lib.py/issues/74
      """
            self.assertEqual(request['trytes'], send_trytes_response['trytes'])
            return send_trytes_response

        with mock.patch(
                'iota.commands.extended.get_bundles.GetBundlesCommand._execute',
                mock_get_bundles,
        ):
            with mock.patch(
                    'iota.commands.extended.send_trytes.SendTrytesCommand._execute',
                    mock_send_trytes,
            ):
                response = self.command(
                    depth=100,
                    minWeightMagnitude=18,
                    transaction=bundle[0].hash,
                )

        self.assertDictEqual(response, send_trytes_response)
Beispiel #12
0
https://github.com/iotaledger/wiki/blob/master/multisigs.md#how-m-of-n-works

For this example, the structure of the bundle looks like this:

- Transaction 0:  Spend IOTAs.
- Transactions 1-8:  Transactions that will hold the signature
  fragments for the multisig input:
  - 1-3:  Generated from ``digest_1`` (security level 3).
  - 4-6:  Generated from ``digest_2`` (security level 3).
  - 7-8:  Generated from ``digest_3`` (security level 2).

Note that transactions 1-8 don't have signatures yet; we need the
corresponding private keys in order to create those!
"""
bundle = Bundle.from_tryte_strings(prepared_trytes)

# Note that we must use the same parameters that we provided to the
# ``get_digests`` method, in order to generate the correct value to
# sign the input!
gpk_result = api_1.get_private_keys(index=0, count=1, security_level=3)
private_key_1 = gpk_result['keys'][0] # type: PrivateKey
private_key_1.sign_input_transactions(bundle, 1)

gpk_result = api_2.get_private_keys(index=42, count=1, security_level=3)
private_key_2 = gpk_result['keys'][0] # type: PrivateKey
private_key_2.sign_input_transactions(bundle, 4)

gpk_result = api_3.get_private_keys(index=8, count=1, security_level=2)
private_key_3 = gpk_result['keys'][0] # type: PrivateKey
private_key_3.sign_input_transactions(bundle, 7)
Beispiel #13
0
  def setUp(self):
    super(BundleTestCase, self).setUp()

    # noinspection SpellCheckingInspection
    self.bundle = Bundle([
      # This transaction does not have a message.
      Transaction(
        signature_message_fragment = Fragment(b''),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999A9PG9A'
            b'XCQANAWGJBTFWEAEQCN9WBZB9BJAIIY9UDLIGFOAA'
          ),

        current_index                     = 0,
        last_index                        = 7,
        value                             = 0,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # This transaction has something that can't be decoded as a UTF-8
      # sequence.
      Transaction(
        signature_message_fragment =
          Fragment(b'OHCFVELH9GYEMHCF9GPHBGIEWHZFU'),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999HAA9UA'
            b'MHCGKEUGYFUBIARAXBFASGLCHCBEVGTBDCSAEBTBM'
          ),

        current_index                     = 1,
        last_index                        = 7,
        value                             = 10,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # This transaction has a message that fits into a single
      # fragment.
      Transaction(
        signature_message_fragment =
          Fragment.from_string('Hello, world!'),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999D99HEA'
            b'M9XADCPFJDFANCIHR9OBDHTAGGE9TGCI9EO9ZCRBN'
          ),

        current_index                     = 2,
        last_index                        = 7,
        value                             = 20,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # This transaction has a message that spans multiple fragments.
      Transaction(
        signature_message_fragment =
          Fragment(
            b'J9GAQBCDCDSCEAADCDFDBDXCBDVCQAGAEAGDPCXCSCEANBTCTCDDEACCWCCDIDVC'
            b'WCHDEAPCHDEA9DPCGDHDSAJ9GAOBFDSASASAEAQBCDCDSCEAADCDFDBDXCBDVCQA'
            b'EAYBEANBTCTCDDEACCWCCDIDVCWCHDQAGAEAGDPCXCSCEAVBCDCDBDEDIDPCKD9D'
            b'EABDTCFDJDCDIDGD9DMDSAJ9EAEAGANBCDEAMDCDIDEAWCPCJDTCSASASAEATCFD'
            b'QAEAHDWCPCHDEAXCGDSASASAGAJ9GASASASAEAPCBDEAPCBDGDKDTCFDEAUCCDFD'
            b'EAMDCDIDIBGAEAXCBDHDTCFDFDIDDDHDTCSCEANBTCTCDDEACCWCCDIDVCWCHDEA'
            b'ADPCYCTCGDHDXCRCPC9D9DMDSAEAGAHCTCGDSAEASBEAWCPCJDTCSAGAJ9CCWCTC'
            b'EAHDKDCDEAADTCBDEAGDWCXCJDTCFDTCSCEAKDXCHDWCEATCLDDDTCRCHDPCBDRC'
            b'MDSAEACCWCTCXCFDEAKDPCXCHDXCBDVCEAWCPCSCEABDCDHDEAQCTCTCBDEAXCBD'
            b'EAJDPCXCBDSAJ9GACCWCTCFDTCEAFDTCPC9D9DMDEAXCGDEACDBDTCIBGAEAQCFD'
            b'TCPCHDWCTCSCEAZBWCCDIDRCWCVCSAJ9GACCWCTCFDTCEAFDTCPC9D9DMDEAXCGD'
            b'EACDBDTCQAGAEARCCDBDUCXCFDADTCSCEANBTCTCDDEACCWCCDIDVCWCHDSAJ9GA'
            b'CCCDEAOBJDTCFDMDHDWCXCBDVCIBEACCCDEAHDWCTCEAVCFDTCPCHDEA9CIDTCGD'
            b'HDXCCDBDEACDUCEAVBXCUCTCQAEAHDWCTCEADCBDXCJDTCFDGDTCEAPCBDSCEAOB'
            b'JDTCFDMDHDWCXCBDVCIBGAJ9GAHCTCGDSAGAJ9LBCDHDWCEACDUCEAHDWCTCEAAD'
            b'TCBDEAWCPCSCEAQCTCTCBDEAHDFDPCXCBDTCSCEAUCCDFDEAHDWCXCGDEAADCDAD'
            b'TCBDHDEBEAHDWCTCXCFDEA9DXCJDTCGDEAWCPCSCEAQCTCTCBDEAPCJ9EAEADDFD'
            b'TCDDPCFDPCHDXCCDBDEAUCCDFDEAXCHDEBEAHDWCTCMDEAWCPCSCEAQCTCTCBDEA'
            b'GDTC9DTCRCHDTCSCEAPCHDEAQCXCFDHDWCEAPCGDEAHDWCCDGDTCEAKDWCCDEAKD'
            b'CDID9DSCJ9EAEAKDXCHDBDTCGDGDEAHDWCTCEAPCBDGDKDTCFDEBEAQCIDHDEATC'
            b'JDTCBDEAGDCDEAHDWCTCMDEAUCCDIDBDSCEAHDWCTCADGDTC9DJDTCGDEAVCPCGD'
            b'DDXCBDVCEAPCBDSCEAGDEDIDXCFDADXCBDVCJ9EAEA9DXCZCTCEATCLDRCXCHDTC'
            b'SCEARCWCXC9DSCFDTCBDSAJ9GAKBBDSCEAMDCDIDLAFDTCEAFDTCPCSCMDEAHDCD'
            b'EAVCXCJDTCEAXCHDEAHDCDEAIDGDIBGAEAIDFDVCTCSCEAVBCDCDBDEDIDPCKD9D'
            b'SAJ9GASBEAPCADSAGAJ9GAXBCDKDIBGAJ9GAXBCDKDQAGAEAGDPCXCSCEANBTCTC'
            b'DDEACCWCCDIDVCWCHDSAJ9CCWCTCMDEAQCCDHDWCEA9DXCRCZCTCSCEAHDWCTCXC'
            b'FDEASCFDMDEA9DXCDDGDSAJ9GACCWCCDIDVCWCEASBEASCCDBDLAHDEAHDWCXCBD'
            b'ZCQAGAEAPCSCSCTCSCEANBTCTCDDEACCWCCDIDVCWCHDQAEAGAHDWCPCHDEAMDCD'
            b'IDLAFDTCEAVCCDXCBDVCEAHDCDEA9DXCZCTCEAXCHDSAGAJ9GANBCDTCGDBDLAHD'
            b'EAADPCHDHDTCFDQAGAEAGDPCXCSCEAZBWCCDIDRCWCVCSAEAGAFCTCEAADIDGDHD'
            b'EAZCBDCDKDEAXCHDFAEAXBCDKDFAGAJ9GAXBCDKDIBGAEATCBDEDIDXCFDTCSCEA'
            b'NBTCTCDDEACCWCCDIDVCWCHDSAJ9GAHCTCGDFAEAXBCDKDFAGAJ9GAKB9D9DEAFD'
            b'XCVCWCHDQAGAEAGDPCXCSCEAHDWCTCEARCCDADDDIDHDTCFDEAPCBDSCEAGDTCHD'
            b'HD9DTCSCEAXCBDHDCDEAGDXC9DTCBDRCTCEAPCVCPCXCBDSAJ9EAEACCWCTCEAHD'
            b'KDCDEAADTCB'
          ),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999A9PG9A'
            b'XCQANAWGJBTFWEAEQCN9WBZB9BJAIIY9UDLIGFOAA'
          ),

        current_index           = 3,
        last_index              = 7,
        value                   = 30,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      Transaction(
        signature_message_fragment =
          Fragment(
            b'DEAUCXCSCVCTCHDTCSCSAEACCWCTCEAHDTCBDGDXCCDBDEAKDPCGDEAIDBDQCTCP'
            b'CFDPCQC9DTCSAJ9GAHCCDIDLAFDTCEAFDTCPC9D9DMDEABDCDHDEAVCCDXCBDVCE'
            b'AHDCDEA9DXCZCTCEAXCHDQAGAEACDQCGDTCFDJDTCSCEANBTCTCDDEACCWCCDIDV'
            b'CWCHDSAJ9GACCTC9D9DEAIDGDFAGAJ9GAKB9D9DEAFDXCVCWCHDQAGAEAGDPCXCS'
            b'CEANBTCTCDDEACCWCCDIDVCWCHDSAEAGACCWCTCEAKBBDGDKDTCFDEAHDCDEAHDW'
            b'CTCEAQBFDTCPCHDEA9CIDTCGDHDXCCDBDSASASAGAJ9GAHCTCGDIBGAJ9GAYBUCE'
            b'AVBXCUCTCQAEAHDWCTCEADCBDXCJDTCFDGDTCEAPCBDSCEAOBJDTCFDMDHDWCXCB'
            b'DVCSASASAGAEAGDPCXCSCEANBTCTCDDEACCWCCDIDVCWCHDSAJ9GAHCTCGDIBIBG'
            b'AJ9GASBGDSASASAGAJ9GAHCTCGDIBFAGAJ9GAPBCDFDHDMDRAHDKDCDQAGAEAGDP'
            b'CXCSCEANBTCTCDDEACCWCCDIDVCWCHDQAEAKDXCHDWCEAXCBDUCXCBDXCHDTCEAA'
            b'DPCYCTCGDHDMDEAPCBDSCEARCPC9DADSAJ9EAEAEAEAEAEAEAEA'
          ),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999A9PG9A'
            b'XCQANAWGJBTFWEAEQCN9WBZB9BJAIIY9UDLIGFOAA'
          ),

        current_index                     = 4,
        last_index                        = 7,
        value                             = 0,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # Input, Part 1 of 2
      Transaction(
        # Make the signature look like a message, so we can verify that
        # the Bundle skips it correctly.
        signature_message_fragment =
          Fragment.from_string('This is a signature, not a message!'),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999WGSBUA'
            b'HDVHYHOBHGP9VCGIZHNCAAQFJGE9YHEHEFTDAGXHY'
          ),

        current_index                     = 5,
        last_index                        = 7,
        value                             = -100,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # Input, Part 2 of 2
      Transaction(
        # Make the signature look like a message, so we can verify that
        # the Bundle skips it correctly.
        signature_message_fragment =
          Fragment.from_string('This is a signature, not a message!'),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999WGSBUA'
            b'HDVHYHOBHGP9VCGIZHNCAAQFJGE9YHEHEFTDAGXHY'
          ),

        current_index                     = 6,
        last_index                        = 7,
        value                             = 0,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # Change
      Transaction(
        # It's unusual for a change transaction to have a message, but
        # half the fun of unit tests is designing unusual scenarios!
        signature_message_fragment =
          Fragment.from_string('I can haz change?'),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999FFYALH'
            b'N9ACYCP99GZBSDK9CECFI9RAIH9BRCCAHAIAWEFAN'
          ),

        current_index                     = 7,
        last_index                        = 7,
        value                             = 40,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),
    ])
Beispiel #14
0
    "DQEUSNVVGKZUMYXKDUIEDYHCDVVAXGWU9RZUGOGFCFSTDVJEIWIETEGLKUIEKMKKFOKHVGUAELCMWE999",  # type: Optional[TransactionHash]
    tag="QA9999999999999999999999999",  # type: Optional[Tag]
    attachment_timestamp=1574903769168,  # type: Optional[int]
    attachment_timestamp_lower_bound=0,  # type: Optional[int]
    attachment_timestamp_upper_bound=3812798742493,  # type: Optional[int]
    nonce="CVREKSTNCZMMXIEWQJLPADWVEBB",  # type: Optional[Nonce]
    legacy_tag=None  # type: Optional[Tag]
)

trans = list()
trans.append(bundle_trans)
trans.append(bundle_trans_2)
trans.append(bundle_trans_3)
trans.append(bundle_trans_4)
print('\n in processing bundle')
bundle = Bundle(transactions=trans)
print(bundle.transactions[1].signature_message_fragment)
print('bundle creation is finished\n')
##
# Create digest 1 of 3.
#
# noinspection SpellCheckingInspection
api_1 = MultisigIota(
    adapter='http://localhost:14265',
    seed=Seed(
        b'TESTVALUE9DONTUSEINPRODUCTION99999XKMYQP'
        b'OIFGQSMIIWCQVMBSOKZASRQOFSIUSSHNDKVL9PJVS', ),
)

gd_result = api_1.get_digests(
    # Starting key index.
    async def test_happy_path(self):
        """
    Preparing a bundle with a multisig input.
    """
        self.adapter.seed_response(
            command=GetBalancesCommand.command,
            response={
                'balances': [42],

                # Would it be cheeky to put "7½ million years" here?
                'duration': 86,
            },
        )

        pmt_result =\
          await self.command(
            transfers = [
              ProposedTransaction(
                address = Address(self.trytes_1),
                value   = 42,
              ),
            ],

            multisigInput =
              MultisigAddress(
                digests = [self.digest_1, self.digest_2],
                trytes  = self.trytes_2,
              ),
          )

        # The command returns the raw trytes.  This is useful in a
        # real-world scenario because trytes are easier to transfer between
        # each entity that needs to apply their signature.
        #
        # However, for purposes of this test, we will convert the trytes
        # back into a bundle so that we can inspect the end result more
        # easily.
        bundle = Bundle.from_tryte_strings(pmt_result['trytes'])

        #
        # This bundle looks almost identical to what you would expect from
        # :py:meth:`iota.api.Iota.prepare_transfer`, except:
        # - There are 4 inputs (to hold all of the signature fragments).
        # - The inputs are unsigned.
        #
        self.assertEqual(len(bundle), 5)

        # Spend Transaction
        txn_1 = bundle[0]
        self.assertEqual(txn_1.address, self.trytes_1)
        self.assertEqual(txn_1.value, 42)

        # Input 1, Part 1 of 4
        txn_2 = bundle[1]
        self.assertEqual(txn_2.address, self.trytes_2)
        self.assertEqual(txn_2.value, -42)
        self.assertEqual(txn_2.signature_message_fragment, Fragment(b''))

        # Input 1, Part 2 of 4
        txn_3 = bundle[2]
        self.assertEqual(txn_3.address, self.trytes_2)
        self.assertEqual(txn_3.value, 0)
        self.assertEqual(txn_3.signature_message_fragment, Fragment(b''))

        # Input 1, Part 3 of 4
        txn_4 = bundle[3]
        self.assertEqual(txn_4.address, self.trytes_2)
        self.assertEqual(txn_4.value, 0)
        self.assertEqual(txn_4.signature_message_fragment, Fragment(b''))

        # Input 1, Part 4 of 4
        txn_5 = bundle[4]
        self.assertEqual(txn_5.address, self.trytes_2)
        self.assertEqual(txn_5.value, 0)
        self.assertEqual(txn_5.signature_message_fragment, Fragment(b''))
Beispiel #16
0
https://github.com/iotaledger/wiki/blob/master/multisigs.md#how-m-of-n-works

For this example, the structure of the bundle looks like this:

- Transaction 0:  Spend IOTAs.
- Transactions 1-8:  Transactions that will hold the signature
  fragments for the multisig input:
  - 1-3:  Generated from ``digest_1`` (security level 3).
  - 4-6:  Generated from ``digest_2`` (security level 3).
  - 7-8:  Generated from ``digest_3`` (security level 2).

Note that transactions 1-8 don't have signatures yet; we need the
corresponding private keys in order to create those!
"""
bundle = Bundle.from_tryte_strings(prepared_trytes)

# Note that we must use the same parameters that we provided to the
# ``get_digests`` method, in order to generate the correct value to
# sign the input!
gpk_result = api_1.get_private_keys(index=0, count=1, security_level=3)
private_key_1 = gpk_result['keys'][0]  # type: PrivateKey
private_key_1.sign_input_transactions(bundle, 1)

gpk_result = api_2.get_private_keys(index=42, count=1, security_level=3)
private_key_2 = gpk_result['keys'][0]  # type: PrivateKey
private_key_2.sign_input_transactions(bundle, 4)

gpk_result = api_3.get_private_keys(index=8, count=1, security_level=2)
private_key_3 = gpk_result['keys'][0]  # type: PrivateKey
private_key_3.sign_input_transactions(bundle, 7)
Beispiel #17
0
def search_hash(type, hash):
    result = None

    if type == "tag" or type == "search":
        try:
            result = api.find_transactions(tags=[hash])

            if result['hashes'][0]:
                return "tag", result['hashes']
        except BaseException as e:
            result = e

    if type == "address" or type =="search":
        try:
            result = api.find_transactions(addresses=[hash])
            if result['hashes'][0]:
                balance = get_price(api.get_balances([hash])['balances'][0])
                tx = api.get_trytes(result['hashes'])['trytes']
                for num in range(len(tx)):
                    tx[num] = Transaction.from_tryte_string(tx[num])
                confirm = confirmation([element.hash for element in tx])
                for t in tx:
                    t.is_confirmed = confirm[t.hash]
                    t.timestamp = calculate_time(t.attachment_timestamp/1000)
                    t.value = get_convert(t.value)
                tx = sorted(tx, key=lambda k: k.attachment_timestamp, reverse=True)
                results = {'balance':balance, 'transactions':tx}
                return "address", results
        except BaseException as e:
            result = e

    if type == "transaction" or type =="search":
        try:
            tx = api.get_trytes(hashes=[hash])
            result = Transaction.from_tryte_string(tx['trytes'][0])
            if result.hash != TransactionHash(b''):
                result.timestamp = calculate_time(result.attachment_timestamp/1000)
                result.is_confirmed = confirmation([result.hash])[result.hash]
                result.value = get_price(result.value)
                return "transaction", result
        except BaseException as e:
            result = e

    if type == "bundle" or type =="search":
        try:
            result = api.find_transactions(bundles=[hash])['hashes']
            if result[0]:
                results = Bundle.from_tryte_strings(api.get_trytes(result)['trytes'])
                if True in confirmation(result).values():
                    results.is_confirmed = True
                for result in results:
                    result.value = get_convert(result.value)
                newlis = sorted(results, key=lambda k: k.attachment_timestamp, reverse=True)
                size = newlis[0].last_index+1
                newlist = [newlis[i:i+size] for i  in range(0, len(newlis), size)]
                for x in newlist:
                    x[0].timestamp = calculate_time(x[0].attachment_timestamp/1000)
                return "bundle", newlist
        except BaseException as e:
            result = e

    return "error", str(result)
Beispiel #18
0
def attach_to_tangle(
        bundle_trytes,  # Iterable[TryteString]
        trunk_transaction_hash,  # TransactionHash
        branch_transaction_hash,  # TransactionHash
        mwm=14):  # Int
    """
    Attaches the bundle to the Tangle by doing Proof-of-Work
    locally. No connection to the Tangle is needed in this step.

    :param bundle_trytes:
        List of TryteString(s) that contain raw transaction trytes.

    :param trunk_transaction_hash:
        Trunk transaction hash obtained from an iota node.
        Result of the tip selection process.

    :param branch_transaction_hash:
        Branch transaction hash obtained from an iota node.
        Result of the tip selection process.

    :param mwm:
        Minimum Weight Magnitude to be used during the PoW.
        Number of trailing zero trits in transaction hash.

    :returns:
        The bundle as a list of transaction trytes (TryteStrings).
        Attachment timestamp and nonce included.
    """
    previoustx = None

    # Construct bundle object
    bundle = Bundle.from_tryte_strings(bundle_trytes)

    # reversed, beause pyota bundles look like [...tx2,tx1,tx0]
    # and we need the tail tx first (tx0)
    for txn in reversed(bundle.transactions):
        txn.attachment_timestamp = get_current_ms()
        txn.attachment_timestamp_upper_bound = (math.pow(3, 27) - 1) // 2

        if (not previoustx):  # this is the tail transaction
            if txn.current_index == txn.last_index:
                txn.branch_transaction_hash = branch_transaction_hash
                txn.trunk_transaction_hash = trunk_transaction_hash
            else:
                raise ValueError('Tail transaction is inconsistent in bundle')

        else:  # It is not a tail transaction
            txn.branch_transaction_hash = trunk_transaction_hash
            txn.trunk_transaction_hash = previoustx  # the previous transaction

        # Let's do the pow locally
        txn_string = txn.as_tryte_string().__str__()
        # returns a python unicode string
        powed_txn_string = get_powed_tx_trytes(txn_string, mwm)
        # construct trytestring from python string
        powed_txn_trytes = TryteString(powed_txn_string)
        # compute transaction hash
        hash_string = get_hash_trytes(powed_txn_string)
        hash_trytes = TryteString(hash_string)
        hash_ = TransactionHash(hash_trytes)

        # Create powed txn object
        powed_txn = Transaction.from_tryte_string(trytes=powed_txn_trytes,
                                                  hash_=hash_)

        previoustx = powed_txn.hash
        # put that back in the bundle
        bundle.transactions[txn.current_index] = powed_txn
    return bundle.as_tryte_strings()
Beispiel #19
0
    def setUp(self) -> None:
        # Need two valid bundles
        super().setUp()
        self.adapter = MockAdapter()

        self.single_bundle = Bundle.from_tryte_strings([
            TransactionTrytes(
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999POALVTTGQHJFGINKJ9'
                'EWRJZBQLLWMMNMNRUT9VFWDDMDWHPJMNDOFZXUQUABGCXZRH9OI9NWEUSHVYXDO'
                '999999999999999999999999999C99999999999999999999999999RIGEHBD99'
                '999999999999999999RPCKQTYDOV9IYVYYALBTBLHRFCLFMTCC9ZLOKKGENTDFY'
                'COKFUITXUIUJLBNWAEKBJKBYDSRLVHSGELCCCZGNHCYEAKJ9OPRZFIBYEEBTRFT'
                'QTWJUKRDKNSEESICPJRTDNZQQYNXOFVXI9CPRNBO9APJMEXATA9999CZGNHCYEA'
                'KJ9OPRZFIBYEEBTRFTQTWJUKRDKNSEESICPJRTDNZQQYNXOFVXI9CPRNBO9APJM'
                'EXATA9999C99999999999999999999999999FQFFNIHPF999999999MMMMMMMMM'
                'BCDJOVFVODAQEPAXIWDRFKCTOFI')
        ])

        self.three_tx_bundle = Bundle.from_tryte_strings(([
            TransactionTrytes(
                'PBXCFDGDHDEAHDFDPCBDGDPCRCHDXCCDBDEAXCBDEAHDWCTCEAQCIDBDSC9DTCS'
                'A99999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999M9OVNPOWKUNQYDHFN9'
                'YAL9WIQJDVAFKBU9ZPIHSGTZLGFJODRZINZMDALS9ERTNAJ9VTENWYLBSYALQQL'
                '999999999999999999999999999EYOTA9TESTS9999999999999999BOPIHBD99'
                '999999999B99999999JWFDGHYGEQIKSPCWEAHHQACOYHQWINSA9GELCEZNQEUHV'
                'DH9UAYJVSTIIKW9URTHHIJYGWXGE9AEWISYWZSLPKSJETGKZEQVPISQSNDHIAXQ'
                'RZVFJXFOXZAVMRUGALCQRHUEZPDFNLCIKQGWEKDJURLZLMUZVA99999BSJCSWTG'
                'RTJSGZPOXRPICUDATCLCVTF9BEDHSZZRLSH9IRMTFRVAMSSHC9TRYZGHPWRDVTX'
                'EXWTZ9999PYOTA9TESTS9999999999999999OSZRBMHPF999999999MMMMMMMMM'
                'IVL9PTSTAIRGJLGXFQGIWOJHBKF'),
            TransactionTrytes(
                'BCTCRCCDBDSCEAHDFDPCBDGDPCRCHDXCCDBDEAXCBDEAHDWCTCEAQCIDBDSC9DT'
                'CSA999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999LSTTHILAJWQEXWVOJQ'
                'GRANRLNHQLKYXVQFBYJ9QDFRISQR9WJYMSSZUBOCVLXF9TACHKGQUEGMJPICXVY'
                '999999999999999999999999999PYOTA9TESTS9999999999999999BOPIHBD99'
                'A99999999B99999999JWFDGHYGEQIKSPCWEAHHQACOYHQWINSA9GELCEZNQEUHV'
                'DH9UAYJVSTIIKW9URTHHIJYGWXGE9AEWISYWQQAWNWHDSGZWFTKTYSV99PJIFFM'
                'OPFWONAOTRBUEDGLORTHNMXM9EZNILYEIWCQIAVMAGDBHYWWOA99999BSJCSWTG'
                'RTJSGZPOXRPICUDATCLCVTF9BEDHSZZRLSH9IRMTFRVAMSSHC9TRYZGHPWRDVTX'
                'EXWTZ9999PYOTA9TESTS9999999999999999EMSRBMHPF999999999MMMMMMMMM'
                'NXTVOIJXAAJUS9SRVJEVDVOSIUE'),
            TransactionTrytes(
                'CCWCXCFDSCEAHDFDPCBDGDPCRCHDXCCDBDEAXCBDEAHDWCTCEAQCIDBDSC9DTCS'
                'A99999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999FSXLFSGAHTGSFPK9FH'
                'HURWZJAWQDQCRIFUHMSZWUTNRAIDNGEHGPHLNJOEAIDGLYQRCYSCYDTBZQFDGQK'
                '999999999999999999999999999PYOTA9TESTS9999999999999999BOPIHBD99'
                'B99999999B99999999JWFDGHYGEQIKSPCWEAHHQACOYHQWINSA9GELCEZNQEUHV'
                'DH9UAYJVSTIIKW9URTHHIJYGWXGE9AEWISYW9BSJCSWTGRTJSGZPOXRPICUDATC'
                'LCVTF9BEDHSZZRLSH9IRMTFRVAMSSHC9TRYZGHPWRDVTXEXWTZ99999BSJCSWTG'
                'RTJSGZPOXRPICUDATCLCVTF9BEDHSZZRLSH9IRMTFRVAMSSHC9TRYZGHPWRDVTX'
                'EXWTZ9999PYOTA9TESTS9999999999999999LUSRBMHPF999999999MMMMMMMMM'
                'BOCWSYQAKMZXDR9ZPHXTXZORELC'),
        ]))
Beispiel #20
0
 def _reattach(self, bundle: Bundle) -> Bundle:
     response = self._iota_api.replay_bundle(
         bundle.tail_transaction.hash,
         DEPTH,
     )
     return Bundle.from_tryte_strings(response['trytes'])
Beispiel #21
0
    def test_stop(self):
        """
    Scanning the Tangle for all transfers, with stop index.
    """

        # noinspection PyUnusedLocal
        def create_generator(ag, start, step=1):
            # Inject an invalid value into the generator, to ensure it is
            # skipped.
            for addy in [self.addy1, None][start::step]:
                yield addy

        # The first address received IOTA.
        self.adapter.seed_response(
            'findTransactions',
            {
                'duration':
                42,
                'hashes': [
                    'TESTVALUEFIVE9DONTUSEINPRODUCTION99999VH'
                    'YHRHJETGYCAFZGABTEUBWCWAS9WF99UHBHRHLIOFJ',
                ],
            },
        )

        self.adapter.seed_response(
            'getTrytes',
            {
                'duration': 99,
                'trytes': [''],
            },
        )

        bundle = Bundle([
            Transaction(
                address=self.addy1,
                timestamp=1483033814,

                # These values are not relevant to the test.
                hash_=None,
                signature_message_fragment=None,
                value=42,
                tag=Tag(b''),
                current_index=0,
                last_index=0,
                bundle_hash=None,
                trunk_transaction_hash=None,
                branch_transaction_hash=None,
                attachment_timestamp=1483033814,
                attachment_timestamp_lower_bound=12,
                attachment_timestamp_upper_bound=0,
                nonce=None,
            )
        ])

        mock_get_bundles = mock.Mock(return_value={
            'bundles': [bundle],
        })

        with mock.patch(
                'iota.crypto.addresses.AddressGenerator.create_iterator',
                create_generator,
        ):
            with mock.patch(
                    'iota.commands.extended.get_bundles.GetBundlesCommand._execute',
                    mock_get_bundles,
            ):
                response = self.command(seed=Seed.random(), stop=1)

        self.assertDictEqual(
            response,
            {
                'bundles': [bundle],
            },
        )
Beispiel #22
0
class BundleTestCase(TestCase):
  def setUp(self):
    super(BundleTestCase, self).setUp()

    self.bundle = Bundle([
      # This transaction does not have a message.
      Transaction(
        signature_message_fragment = Fragment(b''),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999A9PG9A'
            b'XCQANAWGJBTFWEAEQCN9WBZB9BJAIIY9UDLIGFOAA'
          ),

        current_index                     = 0,
        last_index                        = 7,
        value                             = 0,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # This transaction has something that can't be decoded as a UTF-8
      # sequence.
      Transaction(
        signature_message_fragment =
          Fragment(b'OHCFVELH9GYEMHCF9GPHBGIEWHZFU'),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999HAA9UA'
            b'MHCGKEUGYFUBIARAXBFASGLCHCBEVGTBDCSAEBTBM'
          ),

        current_index                     = 1,
        last_index                        = 7,
        value                             = 10,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # This transaction has a message that fits into a single
      # fragment.
      Transaction(
        signature_message_fragment =
          Fragment.from_unicode('Hello, world!'),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999D99HEA'
            b'M9XADCPFJDFANCIHR9OBDHTAGGE9TGCI9EO9ZCRBN'
          ),

        current_index                     = 2,
        last_index                        = 7,
        value                             = 20,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # This transaction has a message that spans multiple fragments.
      Transaction(
        signature_message_fragment =
          Fragment(
            b'J9GAQBCDCDSCEAADCDFDBDXCBDVCQAGAEAGDPCXCSCEANBTCTCDDEACCWCCDIDVC'
            b'WCHDEAPCHDEA9DPCGDHDSAJ9GAOBFDSASASAEAQBCDCDSCEAADCDFDBDXCBDVCQA'
            b'EAYBEANBTCTCDDEACCWCCDIDVCWCHDQAGAEAGDPCXCSCEAVBCDCDBDEDIDPCKD9D'
            b'EABDTCFDJDCDIDGD9DMDSAJ9EAEAGANBCDEAMDCDIDEAWCPCJDTCSASASAEATCFD'
            b'QAEAHDWCPCHDEAXCGDSASASAGAJ9GASASASAEAPCBDEAPCBDGDKDTCFDEAUCCDFD'
            b'EAMDCDIDIBGAEAXCBDHDTCFDFDIDDDHDTCSCEANBTCTCDDEACCWCCDIDVCWCHDEA'
            b'ADPCYCTCGDHDXCRCPC9D9DMDSAEAGAHCTCGDSAEASBEAWCPCJDTCSAGAJ9CCWCTC'
            b'EAHDKDCDEAADTCBDEAGDWCXCJDTCFDTCSCEAKDXCHDWCEATCLDDDTCRCHDPCBDRC'
            b'MDSAEACCWCTCXCFDEAKDPCXCHDXCBDVCEAWCPCSCEABDCDHDEAQCTCTCBDEAXCBD'
            b'EAJDPCXCBDSAJ9GACCWCTCFDTCEAFDTCPC9D9DMDEAXCGDEACDBDTCIBGAEAQCFD'
            b'TCPCHDWCTCSCEAZBWCCDIDRCWCVCSAJ9GACCWCTCFDTCEAFDTCPC9D9DMDEAXCGD'
            b'EACDBDTCQAGAEARCCDBDUCXCFDADTCSCEANBTCTCDDEACCWCCDIDVCWCHDSAJ9GA'
            b'CCCDEAOBJDTCFDMDHDWCXCBDVCIBEACCCDEAHDWCTCEAVCFDTCPCHDEA9CIDTCGD'
            b'HDXCCDBDEACDUCEAVBXCUCTCQAEAHDWCTCEADCBDXCJDTCFDGDTCEAPCBDSCEAOB'
            b'JDTCFDMDHDWCXCBDVCIBGAJ9GAHCTCGDSAGAJ9LBCDHDWCEACDUCEAHDWCTCEAAD'
            b'TCBDEAWCPCSCEAQCTCTCBDEAHDFDPCXCBDTCSCEAUCCDFDEAHDWCXCGDEAADCDAD'
            b'TCBDHDEBEAHDWCTCXCFDEA9DXCJDTCGDEAWCPCSCEAQCTCTCBDEAPCJ9EAEADDFD'
            b'TCDDPCFDPCHDXCCDBDEAUCCDFDEAXCHDEBEAHDWCTCMDEAWCPCSCEAQCTCTCBDEA'
            b'GDTC9DTCRCHDTCSCEAPCHDEAQCXCFDHDWCEAPCGDEAHDWCCDGDTCEAKDWCCDEAKD'
            b'CDID9DSCJ9EAEAKDXCHDBDTCGDGDEAHDWCTCEAPCBDGDKDTCFDEBEAQCIDHDEATC'
            b'JDTCBDEAGDCDEAHDWCTCMDEAUCCDIDBDSCEAHDWCTCADGDTC9DJDTCGDEAVCPCGD'
            b'DDXCBDVCEAPCBDSCEAGDEDIDXCFDADXCBDVCJ9EAEA9DXCZCTCEATCLDRCXCHDTC'
            b'SCEARCWCXC9DSCFDTCBDSAJ9GAKBBDSCEAMDCDIDLAFDTCEAFDTCPCSCMDEAHDCD'
            b'EAVCXCJDTCEAXCHDEAHDCDEAIDGDIBGAEAIDFDVCTCSCEAVBCDCDBDEDIDPCKD9D'
            b'SAJ9GASBEAPCADSAGAJ9GAXBCDKDIBGAJ9GAXBCDKDQAGAEAGDPCXCSCEANBTCTC'
            b'DDEACCWCCDIDVCWCHDSAJ9CCWCTCMDEAQCCDHDWCEA9DXCRCZCTCSCEAHDWCTCXC'
            b'FDEASCFDMDEA9DXCDDGDSAJ9GACCWCCDIDVCWCEASBEASCCDBDLAHDEAHDWCXCBD'
            b'ZCQAGAEAPCSCSCTCSCEANBTCTCDDEACCWCCDIDVCWCHDQAEAGAHDWCPCHDEAMDCD'
            b'IDLAFDTCEAVCCDXCBDVCEAHDCDEA9DXCZCTCEAXCHDSAGAJ9GANBCDTCGDBDLAHD'
            b'EAADPCHDHDTCFDQAGAEAGDPCXCSCEAZBWCCDIDRCWCVCSAEAGAFCTCEAADIDGDHD'
            b'EAZCBDCDKDEAXCHDFAEAXBCDKDFAGAJ9GAXBCDKDIBGAEATCBDEDIDXCFDTCSCEA'
            b'NBTCTCDDEACCWCCDIDVCWCHDSAJ9GAHCTCGDFAEAXBCDKDFAGAJ9GAKB9D9DEAFD'
            b'XCVCWCHDQAGAEAGDPCXCSCEAHDWCTCEARCCDADDDIDHDTCFDEAPCBDSCEAGDTCHD'
            b'HD9DTCSCEAXCBDHDCDEAGDXC9DTCBDRCTCEAPCVCPCXCBDSAJ9EAEACCWCTCEAHD'
            b'KDCDEAADTCB'
          ),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999A9PG9A'
            b'XCQANAWGJBTFWEAEQCN9WBZB9BJAIIY9UDLIGFOAA'
          ),

        current_index           = 3,
        last_index              = 7,
        value                   = 30,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      Transaction(
        signature_message_fragment =
          Fragment(
            b'DEAUCXCSCVCTCHDTCSCSAEACCWCTCEAHDTCBDGDXCCDBDEAKDPCGDEAIDBDQCTCP'
            b'CFDPCQC9DTCSAJ9GAHCCDIDLAFDTCEAFDTCPC9D9DMDEABDCDHDEAVCCDXCBDVCE'
            b'AHDCDEA9DXCZCTCEAXCHDQAGAEACDQCGDTCFDJDTCSCEANBTCTCDDEACCWCCDIDV'
            b'CWCHDSAJ9GACCTC9D9DEAIDGDFAGAJ9GAKB9D9DEAFDXCVCWCHDQAGAEAGDPCXCS'
            b'CEANBTCTCDDEACCWCCDIDVCWCHDSAEAGACCWCTCEAKBBDGDKDTCFDEAHDCDEAHDW'
            b'CTCEAQBFDTCPCHDEA9CIDTCGDHDXCCDBDSASASAGAJ9GAHCTCGDIBGAJ9GAYBUCE'
            b'AVBXCUCTCQAEAHDWCTCEADCBDXCJDTCFDGDTCEAPCBDSCEAOBJDTCFDMDHDWCXCB'
            b'DVCSASASAGAEAGDPCXCSCEANBTCTCDDEACCWCCDIDVCWCHDSAJ9GAHCTCGDIBIBG'
            b'AJ9GASBGDSASASAGAJ9GAHCTCGDIBFAGAJ9GAPBCDFDHDMDRAHDKDCDQAGAEAGDP'
            b'CXCSCEANBTCTCDDEACCWCCDIDVCWCHDQAEAKDXCHDWCEAXCBDUCXCBDXCHDTCEAA'
            b'DPCYCTCGDHDMDEAPCBDSCEARCPC9DADSAJ9EAEAEAEAEAEAEAEA'
          ),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999A9PG9A'
            b'XCQANAWGJBTFWEAEQCN9WBZB9BJAIIY9UDLIGFOAA'
          ),

        current_index                     = 4,
        last_index                        = 7,
        value                             = 0,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # Input, Part 1 of 2
      Transaction(
        # Make the signature look like a message, so we can verify that
        # the Bundle skips it correctly.
        signature_message_fragment =
          Fragment.from_unicode('This is a signature, not a message!'),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999WGSBUA'
            b'HDVHYHOBHGP9VCGIZHNCAAQFJGE9YHEHEFTDAGXHY'
          ),

        current_index                     = 5,
        last_index                        = 7,
        value                             = -100,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # Input, Part 2 of 2
      Transaction(
        # Make the signature look like a message, so we can verify that
        # the Bundle skips it correctly.
        signature_message_fragment =
          Fragment.from_unicode('This is a signature, not a message!'),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999WGSBUA'
            b'HDVHYHOBHGP9VCGIZHNCAAQFJGE9YHEHEFTDAGXHY'
          ),

        current_index                     = 6,
        last_index                        = 7,
        value                             = 0,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # Change
      Transaction(
        # It's unusual for a change transaction to have a message, but
        # half the fun of unit tests is designing unusual scenarios!
        signature_message_fragment =
          Fragment.from_unicode('I can haz change?'),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999FFYALH'
            b'N9ACYCP99GZBSDK9CECFI9RAIH9BRCCAHAIAWEFAN'
          ),

        current_index                     = 7,
        last_index                        = 7,
        value                             = 40,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),
    ])

  def test_get_messages_errors_drop(self):
    """
    Decoding messages from a bundle, with ``errors='drop'``.
    """
    messages = self.bundle.get_messages('drop')

    self.assertEqual(len(messages), 3)

    self.assertEqual(messages[0], 'Hello, world!')

    self.assertEqual(
      messages[1],

      '''
"Good morning," said Deep Thought at last.
"Er... Good morning, O Deep Thought," said Loonquawl nervously.
  "Do you have... er, that is..."
"... an answer for you?" interrupted Deep Thought majestically. "Yes. I have."
The two men shivered with expectancy. Their waiting had not been in vain.
"There really is one?" breathed Phouchg.
"There really is one," confirmed Deep Thought.
"To Everything? To the great Question of Life, the Universe and Everything?"
"Yes."
Both of the men had been trained for this moment; their lives had been a
  preparation for it; they had been selected at birth as those who would
  witness the answer; but even so they found themselves gasping and squirming
  like excited children.
"And you're ready to give it to us?" urged Loonquawl.
"I am."
"Now?"
"Now," said Deep Thought.
They both licked their dry lips.
"Though I don't think," added Deep Thought, "that you're going to like it."
"Doesn't matter," said Phouchg. "We must know it! Now!"
"Now?" enquired Deep Thought.
"Yes! Now!"
"All right," said the computer and settled into silence again.
  The two men fidgeted. The tension was unbearable.
"You're really not going to like it," observed Deep Thought.
"Tell us!"
"All right," said Deep Thought. "The Answer to the Great Question..."
"Yes?"
"Of Life, the Universe and Everything..." said Deep Thought.
"Yes??"
"Is..."
"Yes?!"
"Forty-two," said Deep Thought, with infinite majesty and calm.
        ''',
    )

    self.assertEqual(messages[2], 'I can haz change?')

  def test_get_messages_errors_strict(self):
    """
    Decoding messages from a bundle, with ``errors='strict'``.
    """
    with self.assertRaises(UnicodeDecodeError):
      self.bundle.get_messages('strict')

  def test_get_messages_errors_ignore(self):
    """
    Decoding messages from a bundle, with ``errors='ignore'``.
    """
    messages = self.bundle.get_messages('ignore')

    self.assertEqual(len(messages), 4)

    # The only message that is treated differently is the invalid one.
    self.assertEqual(messages[0], '祝你好运\x15')

  def test_get_messages_errors_replace(self):
    """
    Decoding messages from a bundle, with ``errors='replace'``.
    """
    messages = self.bundle.get_messages('replace')

    self.assertEqual(len(messages), 4)

    # The only message that is treated differently is the invalid one.
    self.assertEqual(messages[0], '祝你好运�\x15')
Beispiel #23
0
    def test_get_inclusion_states(self):
        """
    Fetching inclusion states with transactions.
    """

        # noinspection PyUnusedLocal
        def create_generator(ag, start, step=1):
            for addy in [self.addy1][start::step]:
                yield addy

        # The first address received IOTA.
        self.adapter.seed_response(
            'findTransactions',
            {
                'duration':
                42,
                'hashes': [
                    'TESTVALUEFIVE9DONTUSEINPRODUCTION99999VH'
                    'YHRHJETGYCAFZGABTEUBWCWAS9WF99UHBHRHLIOFJ',
                ],
            },
        )

        # For this test, we have to generate a real TryteString.
        transaction_trytes = \
            TryteString(
                b'KMYUMNEUAYODAQSNGWTAERRRHNZBZCOLMVVOBTVWLOFYCJKYMGRAMH9RQ9MTZOSZMH'
                b'QNZFHFEJEDFQ99HSUNVOTULDJGXEDULS9ZHABVDZODJUMCNWVCPNSCUVKVYWCEXBHW'
                b'RBZBSWFPQLWZWMUPGQIGAEGOVE9DDXBVCIPKQYCFZFBELTSMVFSIXLPTACTKAFMCTK'
                b'CPYD9BWDJMLKWAOBDSJNQYAHS9GFIQKZCROLFZJVUEIVXVNBRRLEIWTYVHURUXHSCG'
                b'DKEIEGPOCXKCYWIBUG9ABYCALYJVFLBNGMS9ARHGTQXBZFLENXCJVKHPVKD9KSAEOL'
                b'FFVAJCNKLDVHOCDARWUNKARDYMVKFKRSMUTYOUXSBFFYTKRREBDJZTLVUROQFCBXQN'
                b'SXDDYTZTEBRSXOBMLXHJKSJAVOOVCXATOWNQDWHT9CCUAAJUJKDOQLMAEZACSNFKXZ'
                b'IGWDQEUEFRZYAOSDNVMSXWYLVDAUXZSHNHAIBEMNPFUGORYUETNJK9UCEMSUJYBBDK'
                b'BHIPKEINQCGOVYCPKUPJMUCUVZOJSIWYRFMFXYUVSMOUALAQBWIMXBUBXSAETGKJRP'
                b'AHVAXHQJDMEVSRFYEXUSIEBKMGYCUKFD9JPGUV9AIYUVCRUURKMYUHMVE9OJCYYWTQ'
                b'WUWFMTBZYFXASHHVCMSWXKBRQFHHQVEQMEULJRWZKLWFFSGGKEHUZZFNDNITSRAUH9'
                b'PQK9OGLYMVBSHXQLLZHOBBIM9KVUWDLHZRDKQQVLQXGWYXEEVQPDZUO9PVXMALOMRQ'
                b'VCTHGIZLILSCFKTBRESYZGBZKHXEODNDJZ9GK9ROWYXNGFHZCCBHHZEYEOGWXRGSUD'
                b'SUZFUAUBXVXZHCUVJSYBWTCYCEDYKZNGWFZYKSQLW9FUYMWDVXKZEWT9SCVMQCODZK'
                b'DRNKTINTPNOJOLGQJDAJMFWRFSWZJLYZGSTSIDSXLUJBZRZNLEDNBKAUNGTCYUPDRW'
                b'JOCEBQ9YG9IZLLRMJITISJOTLQMOGXVQIZXHMTJVMMWM9FOIOT9KFZMANEPOEOV9HX'
                b'JNEGURUKRWDGYNPVGAWMWQVABIJNL9MDXKONEPMYACOZ9BE9UZMAFTKYWPFWIQWAPK'
                b'GUXQTOQVWYYVZYGQDLBIQDVOZIWGOMGOBAUARICQZVNXD9UVEFBBAJKQBHRHXTBUOW'
                b'VBFKYQWZWTMMXVKZRIZUBVPQ9XHLJHFHWFZUIZVSNAKBDHDFGJCYQETOMEDTOXIUT9'
                b'OAJVIHWAGTCNPEZTERMMN9EZEWSJHKQAUMXPBZTNQOEQCVXIMAAYO9NIUFLTCFIMK9'
                b'9AFAGWJFA9VOFPUDJLRAMORGSUDBLWWKXEDZ9XPQUZSGANGESHKKGGQSGSYDCRLHZD'
                b'PKA9HKYBKLKKCXYRQQIPXCFETJJDZYPCLUNHGBKEJDRCIHEXKCQQNOV9QFHLGFXOCR'
                b'HPAFCUTPMY9NOZVQHROYJSCMGRSVMOBWADAZNFIAHWGIQUUZBOVODSFAUNRTXSDU9W'
                b'EIRBXQNRSJXFRAQGHA9DYOQJGLVZUJKAQ9CTUOTT9ZKQOQNNLJDUPDXZJYPRCVLRZT'
                b'UCZPNBREYCCKHK9FUWGITAJATFPUOFLZDHPNJYUTXFGNYJOBRD9BVHKZENFXIUYDTL'
                b'CE9JYIIYMXMCXMWTHOLTQFKFHDLVPGMQNITEUXSYLAQULCZOJVBIPYP9M9X9QCNKBX'
                b'W9DVJEQFFY9KQVMKNVTAHQVRXUKEM9FZOJLHAGEECZBUHOQFZOSPRXKZOCCKAOHMSV'
                b'QCFG9CWAHKVWNA9QTLYQI9NKOSHWJCNGPJBLEQPUIWJBIOAWKLBXUCERTSL9FVCLYN'
                b'ADPYTPKJOIEMAQGWBVGSRCZINXEJODUDCT9FHOUMQM9ZHRMBJYSOMPNMEAJGEHICJI'
                b'PVXRKCYX9RZVT9TDZIMXGZJAIYJRGIVMSOICSUINRBQILMJOUQYXCYNJ9WGGJFHYTU'
                b'LWOIPUXXFNTIFNOJRZFSQQNAWBQZOLHHLVGHEPWTKKQEVIPVWZUN9ZBICZ9DZZBVII'
                b'BF9EPHARZJUFJGBQXQFQIBUECAWRSEKYJNYKNSVBCOWTFBZ9NAHFSAMRBPEYGPRGKW'
                b'WTWACZOAPEOECUO9OTMGABJVAIICIPXGSXACVINSYEQFTRCQPCEJXZCY9XZWVWVJRZ'
                b'CYEYNFUUBKPWCHICGJZXKE9GSUDXZYUAPLHAKAHYHDXNPHENTERYMMBQOPSQIDENXK'
                b'LKCEYCPVTZQLEEJVYJZV9BWU999999999999999999999999999FFL999999999999'
                b'9999999999999RJQGVD99999999999A99999999USGBXHGJUEWAUAKNPPRHJXDDMQV'
                b'YDSYZJSDWFYLOQVFGBOSLE9KHFDLDYHUYTXVSFAFCOCLQUHJXTEIQRNBTLHEGJFGVF'
                b'DJCE9IKAOCSYHLCLWPVVNWNESKLYAJG9FGGZOFXCEYOTWLVIJUHGY9QCU9FMZJY999'
                b'9999HYBUYQKKRNAVDPVGYBTVDZ9SVQBLCCVLJTPEQWWOIG9CQZIFQKCROH9YHUCNJT'
                b'SYPBVZVBNESX999999D9TARGPQTNIYRZURQGVHCAWEDRBJIIEJIUZYENVE9LLJQMXH'
                b'GSUUYUCPSOWBCXVFDCHHAZUDC9LUODYWO'
            )

        self.adapter.seed_response(
            'getTrytes',
            {
                'duration': 99,
                'trytes': [binary_type(transaction_trytes)],
            },
        )

        transaction = Transaction.from_tryte_string(transaction_trytes)

        mock_get_bundles = mock.Mock(return_value={
            'bundles': [Bundle([transaction])],
        })

        mock_get_latest_inclusion = mock.Mock(return_value={
            'states': {
                transaction.hash: True,
            },
        })

        with mock.patch(
                'iota.crypto.addresses.AddressGenerator.create_iterator',
                create_generator,
        ):
            with mock.patch(
                    'iota.commands.extended.get_bundles.GetBundlesCommand._execute',
                    mock_get_bundles,
            ):
                with mock.patch(
                        'iota.commands.extended.get_latest_inclusion.GetLatestInclusionCommand._execute',
                        mock_get_latest_inclusion,
                ):
                    response = self.command(
                        seed=Seed.random(),
                        inclusionStates=True,

                        # To keep the test focused, only retrieve a single
                        # transaction.
                        start=0,
                        stop=1,
                    )

        bundle = response['bundles'][0]  # type: Bundle
        self.assertTrue(bundle[0].is_confirmed)
Beispiel #24
0
 def extract_data(bundle):
     json = Bundle.as_json_compatible(bundle)
     data = json[0]["signature_message_fragment"]
     return data
    async def test_unspent_inputs_with_change_address(self):
        """
    The bundle has unspent inputs, so it uses the provided change
    address.
    """
        self.adapter.seed_response(
            command=GetBalancesCommand.command,
            response={
                'balances': [101],
                'duration': 86,
            },
        )

        pmt_result =\
          await self.command(
            transfers = [
              ProposedTransaction(
                address = Address(self.trytes_1),
                value   = 42,
              ),
            ],

            multisigInput =
              MultisigAddress(
                digests = [self.digest_1, self.digest_2],
                trytes  = self.trytes_2,
              ),

            changeAddress = Address(self.trytes_3),
          )

        bundle = Bundle.from_tryte_strings(pmt_result['trytes'])

        self.assertEqual(len(bundle), 6)

        # Spend Transaction
        txn_1 = bundle[0]
        self.assertEqual(txn_1.address, self.trytes_1)
        self.assertEqual(txn_1.value, 42)

        # Input 1, Part 1 of 4
        txn_2 = bundle[1]
        self.assertEqual(txn_2.address, self.trytes_2)
        self.assertEqual(txn_2.value, -101)
        self.assertEqual(txn_2.signature_message_fragment, Fragment(b''))

        # Input 1, Part 2 of 4
        txn_3 = bundle[2]
        self.assertEqual(txn_3.address, self.trytes_2)
        self.assertEqual(txn_3.value, 0)
        self.assertEqual(txn_3.signature_message_fragment, Fragment(b''))

        # Input 1, Part 3 of 4
        txn_4 = bundle[3]
        self.assertEqual(txn_4.address, self.trytes_2)
        self.assertEqual(txn_4.value, 0)
        self.assertEqual(txn_4.signature_message_fragment, Fragment(b''))

        # Input 1, Part 4 of 4
        txn_5 = bundle[4]
        self.assertEqual(txn_5.address, self.trytes_2)
        self.assertEqual(txn_5.value, 0)
        self.assertEqual(txn_5.signature_message_fragment, Fragment(b''))

        # Change
        txn_6 = bundle[5]
        self.assertEqual(txn_6.address, self.trytes_3)
        self.assertEqual(txn_6.value, 59)
Beispiel #26
0
    def setUpClass(self):
        # This is a valid bundle taken from the Tangle
        self.bundle = Bundle.from_tryte_strings([
            TransactionTrytes(
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999999999999999999999999999999999999999999999999'
                '999999999999999999999999999GTSOCZLYYATDVK9FYRZXRFEHYUWTSXNALBGHO9T9GHANN'
                '9YTJIZHOBWZHYSLDRTIVSYRRBUJZFUKWVNJAJSNA99999999999999999999999FBNGLE9BE'
                'AT9CYCLUX999999999RFAVOBD99999999999B99999999BGNBAIUZAHWWAIHAWHXIDGYQYKI'
                'LEWDCBQXYBNQBFNPOIICLCJKHSX9KLPECYBGWW9CGILRKTVEYTL99AAVSD99RCNCYGIVIRVI'
                'TNVOVQNQE9RFJIRAXCEXQEHEXQEKFXSDQVBQGJQWBRTRSAUPMXJLMFKUJKZ9999UIBLZWXJQ'
                'DMZCPEQRLSFYJLEPIFTOCY9ODVKIYAMXMKYKHFWKEHNGLVKEYDGR9GOXWWNXLOCQFD999999'
                'TANGLE9BEAT9CYCLUX999999999FIAMTJGOF999999999MMMMMMMMMZCJOZALASXIERYTDLY'
                'WMZTJF9HQ'),
            TransactionTrytes(
                '9PTKKTOZFZBKCJTYHMKZZDRHCOYXHOTDQY9ALYIBNGD9UDPTUKPHJBORIICRNLDTECKLGPOGE'
                'VQIVFHIYI9UUYWYEKGRDDGAAXD9EMFSKX9TDWGGPKTIXBCWQKPERPUIRYEEYXYPXGHBSRGQAH'
                'ZOIBPERAWSCMIFJZGYAFQ9XBVYDXVJAXXX9XPTXJTSDMJSLNCBACGQ9CHVCYMEKOKSEBRUGTX'
                'KMU9HLWRNWOZJGIOIKLPZEHDZKCQXFDMYOA9DRK9CJVRQSWZSDUWDCXWFPZIL9PJDQUQNMMBM'
                'STGMOFCXKKCRZKDCRCBYSVDSKXTDKFBYIRVSTIVHGWTBFRGNNAYXZBVNSZDQDQRSJBNMBRZTG'
                'VDWYAHHFEMSWF9CLSZPQYKFD9MOIR9CUZCPQAGBZSPSCRHSYVDKX9ZVEQONHOO9EAAHZSTHAW'
                'SLSVI9HSOYKIGDWSKXCHHPFXMKCIBEASGQXHEIGOAETCBLHWPUBSLMELCUVARTPHGOG9BEQTM'
                'NHA9MJHCRVNKXZTZTMEMSHFKJMWNBXLBLMVJDONO9JDYALFCBQ9GELAXSOEGOLNCPYGSKWRFF'
                'IZNUGVHECQKRIZ9NTCPAXEKIAZLTXCBM9PJCOKSFDL99YPEVKOMWEXED9IAAOVPZLLFBZHVAM'
                'DXEXCAZBGKWVQCXPFSEUNTPYVSLPEYKCTTGPVBSXQYFVWFUCGYLARMB9HA9PTRXAXKEOQLVXQ'
                'TTHYZEXSOLFSEHMVJ9QOLMBGFHPTEQAYDZWSAPADJSSHTBWOZGVSLLPTMOLFZWUQFVKJZQPMZ'
                'T9QACMCOEKJVWBOSKQHUTGLHAWMQHPDHCZEDKVUTYVMZCSMR9YPLRJGLUNTRGSEXLNBYJXLAR'
                'MWWAWVPLZXYAYACMJCNYWISCHBMQAAMGTCFOZN9OZCITSFGBUJVERM9FRYHJYVKXLBALTHKWM'
                'JMECDKGPKNWFWNHXAFQ9UEWBTUJADYFFMD9WAWE9PYEZIHGO9DSRBLLHCKIIVLHRPYR9UIYRN'
                'VDYAL9Y9AEPVYOKBEDXJDYYBKEOLOAZCNLSBOULLOHEYAAJBZDNTNKVULUSUAME9LTAIEEUJV'
                'QRVFXSDDTNDMNRSLAXKZTRCAGLIDVJJVGEJWSGDIH9HGVHDKLXVEEFTHAMLSUVEDMMVSDRPOI'
                'UJTSNZJVMGBCFZYOMUSARYNXTRMFVMZOCZYPTBSOZUXXSYBRKKLZEAQDPNGLYAKAWTSEJKLBK'
                'NASQQPZAB9MKOUZN9TO9ZYUVSTAPWGTMGO9ZARUWBVQT9ZLHAYEVJM9FNJCQNSBIRZ9AIXZEX'
                'N9QMLPZBHTVNVKRPIXMQIA9OAWQFPNHMXOOPEUJQCKXZQOOYLMMJXXQAIVHRLGDKLGBOSKERQ'
                'ZYNQOTVJW9IKMWZSORHMXFNOLSR9SIKBNTOANAZBGPGIPVVIFYWTUMATZAJPMUGYVITWCBBSQ'
                'RVAY9MXJCECVTYASSAVUGKKQBDXYVWLTSL9HCAD9NUEWEHQXQUCDJC9WPVAZEDLTGTLZXUUOH'
                'WCEUXCDYHATVRSJXJNLWCPEOENOBLXHTDOXSQCIDSEOHZHWBAYJV9ALDOBYMLXKNUQYQTEYAW'
                'ZFSWGQOAHFXHZDBNCJDIJXRJDGRIOPCLPGPLG9AVFGQQBWPKNJROPIQDLXHNDGWGZOVBXHRBP'
                'JQ9YHIJ9MNJFFLDTVLXJA9EBVPGVIAIHCDDHHTNX9KZARELDIZVQYUQGCPPCRTU9CDUXCVBYZ'
                'RAUJDUMGGTKKOFQQTEGXRQKYPQTGHBGRCJ9IENKLNBIZNRSPVQ9VBKQLCG9YPYBEKJEYNAIDJ'
                'PHABZJXBWHZLMADR9SDEWICFGRRTVAGZYCMJ9CANUSGIUKKHWUSWBQIBC9TXONXYDURJJWWE9'
                'FKPPRWEJVWVJVKFKLMD9HCYASRUYCZPKM9VUCLOUVBYSMWIRFYJMTNOYXNKLNDWZJSRRZKLQL'
                'YCODRSAKLMIRSPFYOANY9DUCYZYLEXDTGEJAKUDFWZNEGIBLMXZTW9OKF9SQGNNMHMUWIICFX'
                'LFQMSLLSVJIMDEEWGOG9PDAPTZCRAL9TJRFPIOPMSFJOTLPRMEOUWGLTTXODGD9LSDJBTKX9Y'
                '9JNNIYNERDRQWJGICGHUFJCMGBBUZWLHQJUSUMUXNWRNIVHSFSRGMBMO9VTBGBBFOMHGNZQYI'
                'OIIITMJDZLCJGNUWRJPJKOSSKRLUMGDXNRZFUFTZTSKXEZOCHUEWBONL9OBRYNWLPKSGCFE9W'
                'TBVEXQHMZ99999999999999999999999999999999999999999999999999RFAVOBD99A9999'
                '9999B99999999BGNBAIUZAHWWAIHAWHXIDGYQYKILEWDCBQXYBNQBFNPOIICLCJKHSX9KLPEC'
                'YBGWW9CGILRKTVEYTL99AYUMYMXIZRU9IIWNDROROZOINKOLXPOFCRZZTXAWDXUKVV9LMEMNG'
                'HYZUMAPCESBINZGITBMIOQYX99999UIBLZWXJQDMZCPEQRLSFYJLEPIFTOCY9ODVKIYAMXMKY'
                'KHFWKEHNGLVKEYDGR9GOXWWNXLOCQFD999999999999999999999999999999999ZS9MTJGOF'
                '999999999MMMMMMMMMMJVAHLRNJKJGTOLKSKNZWBTJNQP'),
            TransactionTrytes(
                'M9STFJDJXSROWSPZTZXDYCWQDOQPBPAGATRY9SOXIXJOQL99OMWXPNXKCKJHHRPGWEDBLT9EO'
                'IBTFDKZYXFMELEBQABMPIXUKYZKONEQESB9XHXYMQBULQVQLEEPHCZSFSMJKDGKEDRVBKLFKZ'
                'JFNKLZWQPMTQGJKWQNAN9NQRKGWHEMIVZNODTNQNPXOTISDNWT9WZKC9DGLYWHUD9EQ9VTZRF'
                'YUYU9BDHZULDGNUGUOUUXQTXZJVCBPZWYVTBEWVUJAOCZVNUJNMSMSVN9CPXWDSFCMRSWAMLP'
                'AJRAEGSCOPLWYEGWPKKSXYJSBNLGMBLDEQ9NQEM9XDCSYZLUHLLEICKFHBFPIYDNGEZJEJXBE'
                '9HJGFRMHAHNXIGDDZRPAOTUZPEEUGLZYDEJYIYFCMOUNRLZFBYC9BDPWUVIR9DE9QGBEPVMDL'
                'J9HUDJMGVDQNIDQQTCRXLCPNSLZXSUUPNKUCDHKWCMQ9HPVWXSZXKGXCDKX9BXNOFDUYUBBGD'
                'DOJEZISFJLFUMKJJHXNBMLUWZWBQ9QDITUUZWHFEXQVAAKBUEXCO9XFBPAD9IKEODAPALAGSG'
                'XFDLORKHCXSPINKO9HSJF9BXUIBRXNUX9APPTPIUYXVVWIYXGARPKDYNEGQXPWYCRAPZMZYKW'
                'ICPYJWUEBIBPTXNJTBSSQDFKH9ZFQXNNH9MUTVKEYQIYOJTLFJLAQOFZFIVMTHESCNDLGXZXA'
                'OWHXPEDVVBFJHIKCNFGPLUZQBYVRRMYCIAJOOJINAHSATUVCLQNMOAERIAJESBZOABTMBMJVQ'
                'DVBMLDBBONGRW9QJUAXS9LQWRRKH9PLQUEVUDHWRZFP9FPYSWOQQRINOCHSJYPVKEUQPDOHXQ'
                'WZFKOLZFXYQF9WDHKTHBVMACJMNUVYFLDBCCCHKTBJINNBPKVXYTVLVGADMYEYVLYROARFBWE'
                'ATEIHEENZVRNOJRJYIMQJRAOFKUWSDKFTNNDTLCFHXQNRFEUFJN9GFFJXWDPKIQUQBXDARMRK'
                'LSGUSATHVZMJSXFTWIJPCWNG9UWDGQYUGPMSGJSZBCSUPAKQKIHP9EGIXNRNMDGUVJNVMW9RL'
                'TOHXUXI9UZTCRLVMMREWFSRUOBKFVQYH9PUVOWATYNDULLZ9RCBHDUVNJDMOJETQ9H9RKOSQF'
                'XEVDVVJNZZSMFMLLQJTYXAALRIHQJWDCZYFZBLODYGYUP9XGPZVILG9WBGOVVYRUTHDGF9TRZ'
                'GSFIYHAAAGXJTJKRG9ZYBFDSRQPQAOIJHDENVQAPJMBLOIVUZIGHMVXHBKZOFUJVEWCZJNCTS'
                'TDEPQTYCPGGG9ZEDEYTSDBOMLOO9QO9LMJKNRXHLWNJUOLVNGXMLNHXZVKTRJGDD9CERBOTKR'
                'EDGEGUQDBFIKPYPOXXF9KLYAX9SDCCDTCFULSOZRYJSORRZUUN9CCNRQKTCDCOGIYHAHWYBUX'
                'EYVIJTGXCPGIGBFQWOTJX9APYNDCPQ9FSNXUZF9MDRLZIJSYDGYKBQGWTQLEKZSATDKVWFFMH'
                'QNTMNWWJNBKVGI9QDXYYWOFAKI9OZRBOWMZZHLXUJQKIICFTBZAHUTZFIZIAUO9CWSTYMGZPO'
                'PBKIO9ZYNSRHXCCIMKD9SPDQNXALFLNTXWVVYDAFHWLD9YSDGGRQJUBWZXQHVULYVDON9WADY'
                'XPEVAGKTXIUTDRMLE9TTKD9TSHXFHQSOLHOCQ9SYWJWTOC99GAKHRSREJKHCBLYSHPOEYJNYX'
                'IYNSQITTFSMKFL9HRNEKDZSJSYEBJACGTVBRVQGUREAYZEIQQIGWVRWIWSDGBRLAMPKQGZCEO'
                'JPHANGFVYRXZJCDO9MGKBPYPQYVHQWDJVSUKA9VGLJELXFJKTNMQYZYGBHNFLGETZ9SWLDRNO'
                'OUCAWNFOTBFICNEQJNPAZABLPOR99DPWTZZWLIRA9MFPXXHMJL9QWVJOAPYA9REAHBATJYJYJ'
                'DYAGCKFDRSVTXMFFIBDPIBXBINGXTWMM9PSRVAKQEEQGRDJNOHKJDCCFBZZRLIVXPGEZYAV9G'
                'CUGCATAQLMSOABNYLSNSTRPOGIRMKCGDDITKO9TEVOWPRGQHJDYWPZTZ9RVLPWGFDZOZICSUZ'
                'AUPZJVTXCMUEADAKPZMNOTHLMGDJKTQWJQBK9TIGUTLDWYEPNDLJLDDYHQUWNLLH9MJUFAQYI'
                'OIIITMJDZLCJGNUWRJPJKOSSKRLUMGDXNRZFUFTZTSKXEZOCHUEWBONL9OBRYNWLPKSGCFE9W'
                'TBVEX999999999999999999999999999999999999999999999999999999RFAVOBD99B9999'
                '9999B99999999BGNBAIUZAHWWAIHAWHXIDGYQYKILEWDCBQXYBNQBFNPOIICLCJKHSX9KLPEC'
                'YBGWW9CGILRKTVEYTL99AUIBLZWXJQDMZCPEQRLSFYJLEPIFTOCY9ODVKIYAMXMKYKHFWKEHN'
                'GLVKEYDGR9GOXWWNXLOCQFD999999IFJ9JLPZON9CZJWMKJWPMUWHKOYTUOSBWQYCTCGBXAJG'
                'T9KRVDDLBCNXFYKRXDEKJYQMTAMYJXJRA9999999999999999999999999999999BGYMTJGOF'
                '999999999MMMMMMMMMOGZMHCGFJIGGC9JYILNUCHZSDGV')
        ])

        self.single_tx_bundle = Bundle.from_tryte_strings([
            TransactionTrytes(
                'VBCDFDTCADEAXCDDGDIDADEASCCD9DCDFDEAGDXCHDEAPCADTCHDQAEARCCDBDGDTCRCHDTCH'
                'DIDFDEAPCSCXCDDXCGDRCXCBDVCEATC9DXCHDSAEASBBDEABDCDBDEA9DXCQCTCFDCDEAXCSC'
                'EABDXCQCWCEAUCPCRCXC9DXCGDXCGDEAXCADDDTCFDSCXCTCHDEATCIDEAGDTCSCEAGDPCDDX'
                'CTCBDSAEABCTCSCEASCXCVCBDXCGDGDXCADEA9DXCVCID9DPCEAXCBDEATCGDHDEAADPC9DTC'
                'GDIDPCSCPCEA9DCDQCCDFDHDXCGDSAEAOBHDXCPCADEAJDPCFDXCIDGDEAADCD9DTCGDHDXCT'
                'CEABDID9D9DPCEADDFDTCHDXCIDADEAHDXCBDRCXCSCIDBDHDSAEAXBPCADEAJDTCWCXCRCID'
                '9DPCEA9DPCRCXCBDXCPCEA9DXCQCTCFDCDSAEAMBIDFDPCQCXCHDIDFDEAXCBDEACDFDBDPCF'
                'DTCEA9DTCCDSAEAMBFDPCGDEATCIDEASCCD9DCDFDEAEDIDXCGDEAHDCDFDHDCDFDEAXCADDD'
                'TCFDSCXCTCHDEAPC9DXCEDIDTCHDSAEANBCDBDTCRCEAPCEAHDTC9D9DIDGDEATCFDPCHDSAE'
                'AXBIDBDRCEAXCSCEAXCPCRCID9DXCGDEASCIDXCSA99999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999MZW'
                'YYLQNAKEWITJSJZJCPFZWMEYGOVYOKUZYUWMUDLGAAAHTBYNQQNGHLUMSGZNQCJCHOULIZSDC'
                'ATEXD999999999999999999999999999VHURLINTERFACE9TEST9TX999999KGVOBD9999999'
                '9999999999999DLWTLGSTHZKRDSIRWCZ9HCJWNUJBKTWHCBZGRIFTASCTBIBZZNNWFVGHEGJB'
                'EWWXKRFOXD9GLTXPFGRBY9999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999999999999999999999999999999999999999'
                '9999999999999999999999999999999999999CCURLINTERFACE9TEST9TX99999999999999'
                '999999999999999999999999999999999999999999999')
        ])

        self.trunk = TransactionHash('TRUNKTXHASH9TESTVALUEONLY')
        self.branch = TransactionHash('BRANCHTXHASH9TESTVALUEONLY')

        # Result is reused accross tests, no need to calculate it
        # multiple times.
        # Mock away current time calculation, timestamps are imaginary from
        # this point on.
        self.before = 99
        with patch('pow.ccurl_interface.get_current_ms',
                   MagicMock(return_value=100)):
            self.powed = ccurl_interface.attach_to_tangle(
                self.bundle.as_tryte_strings(),
                self.branch,
                self.trunk,
                mwm=14)
        self.after = 101
        self.powed_bundle = Bundle.from_tryte_strings(self.powed)
Beispiel #27
0
    def test_multiple_transactions(self):
        """
    Getting a bundle that contains multiple transactions.
    """
        bundle = Bundle.from_tryte_strings([
            TransactionTrytes(
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999WUQXEGBVIECGIWO9IGSYKWWPYCIVUJJGSJPWGIAFJPYSF9NSQOHWAHS9P'
                b'9PWQHOBXNNQIF9IRHVQXKPZW999999999999999999999999999XZUIENOTTBKJMDP'
                b'RXWGQYG9PWGTHNLFMVD99A99999999A99999999PDQWLVVDPUU9VIBODGMRIAZPGQX'
                b'DOGSEXIHKIBWSLDAWUKZCZMK9Z9YZSPCKBDJSVDPRQLJSTKUMTNVSXBGUEHHGAIWWQ'
                b'BCJZHZAQOWZMAIDAFUZBVMUVPWQJLUGGQKNKLMGTWXXNZKUCBJLEDAMYVRGABAWBY9'
                b'999MYIYBTGIOQYYZFJBLIAWMPSZEFFTXUZPCDIXSLLQDQSFYGQSQOGSPKCZNLVSZ9L'
                b'MCUWVNGEN9EJEW9999XZUIENOTTBKJMDPRXWGQYG9PWGTXUO9AXMP9FLMDRMADLRPW'
                b'CZCJBROYCDRJMYU9HDYJM9NDBFUPIZVTR'),

            # Well, it was bound to happen sooner or later... the ASCII
            # representation of this tryte sequence contains a very naughty
            # phrase.  But I don't feel like doing another POW, so... enjoy.
            TransactionTrytes(
                b'NBTCPCFDEACCPCBDVC9DTCQAJ9RBTC9D9DCDQAEAKDCDFD9DSCFAJ9VBCDJDTCQAJ9'
                b'ZBMDYBCCKB99999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999999999999999999'
                b'999999999999999999999999999999999999999999999999999SYRABNN9JD9PNDL'
                b'IKUNCECUELTOHNLFMVD99999999999A99999999PDQWLVVDPUU9VIBODGMRIAZPGQX'
                b'DOGSEXIHKIBWSLDAWUKZCZMK9Z9YZSPCKBDJSVDPRQLJSTKUMTNVSXFSEWUNJOEGNU'
                b'I9QOCRFMYSIFAZLJHKZBPQZZYFG9ORYCRDX9TOMJPFCRB9R9KPUUGFPVOWYXFIWEW9'
                b'999BGUEHHGAIWWQBCJZHZAQOWZMAIDAFUZBVMUVPWQJLUGGQKNKLMGTWXXNZKUCBJL'
                b'EDAMYVRGABAWBY9999SYRABNN9JD9PNDLIKUNCECUELTOQZPSBDILVHJQVCEOICFAD'
                b'YKZVGMOAXJRQNTCKMHGTAUMPGJJMX9LNF'),
        ])

        for txn in bundle:
            self.adapter.seed_response('getTrytes', {
                'trytes': [txn.as_tryte_string()],
            })

        self.adapter.seed_response(
            'getTrytes', {
                'trytes': [
                    'SPAMSPAMSPAM999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999999999999999999'
                    '999999999999999999999999999999999999999999999999999JECDITWO9999999'
                    '999999999999ONLFMVD99999999999999999999VVCHSQSRVFKSBONDWB9EAQEMQOY'
                    'YRBIZHTBJLYNAVDHZPUZAZ9LYHXWKBEJ9IPR9FAMFLT9EEOHVYWUPRHHSRCILCLWFD'
                    'GBYBFFOKMCSAPVD9VGZZRRGBLGMZMXD9RMZQDBLMGN9BATWZGULRBCYQEIKIRBPHC9'
                    '999KTLTRSYOWBD9HVNP9GCUABARNGMYXUZKXWRPGOPETZLKYYC9Z9EYXIWVARUBMBM'
                    'BPXGORN9WPBLY99999ZRBVQWULRFXDNDYZKRKIXPZQT9JJJH9FZU9PVWZJWLXBPODP'
                    'EHMKTTAGEPLPHUQCZNLDSHERONOMHJCOI'
                ],
            })

        response = self.command(transaction=TransactionHash(
            b'TOYJPHKMLQNDVLDHDILARUJCCIUMQBLUSWPCTIVA'
            b'DRXICGYDGSVPXFTILFFGAPICYHGGJ9OHXINFX9999'), )
        self.maxDiff = None
        self.assertListEqual(
            response['bundles'][0].as_json_compatible(),
            bundle.as_json_compatible(),
        )
Beispiel #28
0
class BundleTestCase(TestCase):
  def setUp(self):
    super(BundleTestCase, self).setUp()

    # noinspection SpellCheckingInspection
    self.bundle = Bundle([
      # This transaction does not have a message.
      Transaction(
        signature_message_fragment = Fragment(b''),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999A9PG9A'
            b'XCQANAWGJBTFWEAEQCN9WBZB9BJAIIY9UDLIGFOAA'
          ),

        current_index                     = 0,
        last_index                        = 7,
        value                             = 0,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # This transaction has something that can't be decoded as a UTF-8
      # sequence.
      Transaction(
        signature_message_fragment =
          Fragment(b'OHCFVELH9GYEMHCF9GPHBGIEWHZFU'),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999HAA9UA'
            b'MHCGKEUGYFUBIARAXBFASGLCHCBEVGTBDCSAEBTBM'
          ),

        current_index                     = 1,
        last_index                        = 7,
        value                             = 10,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # This transaction has a message that fits into a single
      # fragment.
      Transaction(
        signature_message_fragment =
          Fragment.from_string('Hello, world!'),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999D99HEA'
            b'M9XADCPFJDFANCIHR9OBDHTAGGE9TGCI9EO9ZCRBN'
          ),

        current_index                     = 2,
        last_index                        = 7,
        value                             = 20,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # This transaction has a message that spans multiple fragments.
      Transaction(
        signature_message_fragment =
          Fragment(
            b'J9GAQBCDCDSCEAADCDFDBDXCBDVCQAGAEAGDPCXCSCEANBTCTCDDEACCWCCDIDVC'
            b'WCHDEAPCHDEA9DPCGDHDSAJ9GAOBFDSASASAEAQBCDCDSCEAADCDFDBDXCBDVCQA'
            b'EAYBEANBTCTCDDEACCWCCDIDVCWCHDQAGAEAGDPCXCSCEAVBCDCDBDEDIDPCKD9D'
            b'EABDTCFDJDCDIDGD9DMDSAJ9EAEAGANBCDEAMDCDIDEAWCPCJDTCSASASAEATCFD'
            b'QAEAHDWCPCHDEAXCGDSASASAGAJ9GASASASAEAPCBDEAPCBDGDKDTCFDEAUCCDFD'
            b'EAMDCDIDIBGAEAXCBDHDTCFDFDIDDDHDTCSCEANBTCTCDDEACCWCCDIDVCWCHDEA'
            b'ADPCYCTCGDHDXCRCPC9D9DMDSAEAGAHCTCGDSAEASBEAWCPCJDTCSAGAJ9CCWCTC'
            b'EAHDKDCDEAADTCBDEAGDWCXCJDTCFDTCSCEAKDXCHDWCEATCLDDDTCRCHDPCBDRC'
            b'MDSAEACCWCTCXCFDEAKDPCXCHDXCBDVCEAWCPCSCEABDCDHDEAQCTCTCBDEAXCBD'
            b'EAJDPCXCBDSAJ9GACCWCTCFDTCEAFDTCPC9D9DMDEAXCGDEACDBDTCIBGAEAQCFD'
            b'TCPCHDWCTCSCEAZBWCCDIDRCWCVCSAJ9GACCWCTCFDTCEAFDTCPC9D9DMDEAXCGD'
            b'EACDBDTCQAGAEARCCDBDUCXCFDADTCSCEANBTCTCDDEACCWCCDIDVCWCHDSAJ9GA'
            b'CCCDEAOBJDTCFDMDHDWCXCBDVCIBEACCCDEAHDWCTCEAVCFDTCPCHDEA9CIDTCGD'
            b'HDXCCDBDEACDUCEAVBXCUCTCQAEAHDWCTCEADCBDXCJDTCFDGDTCEAPCBDSCEAOB'
            b'JDTCFDMDHDWCXCBDVCIBGAJ9GAHCTCGDSAGAJ9LBCDHDWCEACDUCEAHDWCTCEAAD'
            b'TCBDEAWCPCSCEAQCTCTCBDEAHDFDPCXCBDTCSCEAUCCDFDEAHDWCXCGDEAADCDAD'
            b'TCBDHDEBEAHDWCTCXCFDEA9DXCJDTCGDEAWCPCSCEAQCTCTCBDEAPCJ9EAEADDFD'
            b'TCDDPCFDPCHDXCCDBDEAUCCDFDEAXCHDEBEAHDWCTCMDEAWCPCSCEAQCTCTCBDEA'
            b'GDTC9DTCRCHDTCSCEAPCHDEAQCXCFDHDWCEAPCGDEAHDWCCDGDTCEAKDWCCDEAKD'
            b'CDID9DSCJ9EAEAKDXCHDBDTCGDGDEAHDWCTCEAPCBDGDKDTCFDEBEAQCIDHDEATC'
            b'JDTCBDEAGDCDEAHDWCTCMDEAUCCDIDBDSCEAHDWCTCADGDTC9DJDTCGDEAVCPCGD'
            b'DDXCBDVCEAPCBDSCEAGDEDIDXCFDADXCBDVCJ9EAEA9DXCZCTCEATCLDRCXCHDTC'
            b'SCEARCWCXC9DSCFDTCBDSAJ9GAKBBDSCEAMDCDIDLAFDTCEAFDTCPCSCMDEAHDCD'
            b'EAVCXCJDTCEAXCHDEAHDCDEAIDGDIBGAEAIDFDVCTCSCEAVBCDCDBDEDIDPCKD9D'
            b'SAJ9GASBEAPCADSAGAJ9GAXBCDKDIBGAJ9GAXBCDKDQAGAEAGDPCXCSCEANBTCTC'
            b'DDEACCWCCDIDVCWCHDSAJ9CCWCTCMDEAQCCDHDWCEA9DXCRCZCTCSCEAHDWCTCXC'
            b'FDEASCFDMDEA9DXCDDGDSAJ9GACCWCCDIDVCWCEASBEASCCDBDLAHDEAHDWCXCBD'
            b'ZCQAGAEAPCSCSCTCSCEANBTCTCDDEACCWCCDIDVCWCHDQAEAGAHDWCPCHDEAMDCD'
            b'IDLAFDTCEAVCCDXCBDVCEAHDCDEA9DXCZCTCEAXCHDSAGAJ9GANBCDTCGDBDLAHD'
            b'EAADPCHDHDTCFDQAGAEAGDPCXCSCEAZBWCCDIDRCWCVCSAEAGAFCTCEAADIDGDHD'
            b'EAZCBDCDKDEAXCHDFAEAXBCDKDFAGAJ9GAXBCDKDIBGAEATCBDEDIDXCFDTCSCEA'
            b'NBTCTCDDEACCWCCDIDVCWCHDSAJ9GAHCTCGDFAEAXBCDKDFAGAJ9GAKB9D9DEAFD'
            b'XCVCWCHDQAGAEAGDPCXCSCEAHDWCTCEARCCDADDDIDHDTCFDEAPCBDSCEAGDTCHD'
            b'HD9DTCSCEAXCBDHDCDEAGDXC9DTCBDRCTCEAPCVCPCXCBDSAJ9EAEACCWCTCEAHD'
            b'KDCDEAADTCB'
          ),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999A9PG9A'
            b'XCQANAWGJBTFWEAEQCN9WBZB9BJAIIY9UDLIGFOAA'
          ),

        current_index           = 3,
        last_index              = 7,
        value                   = 30,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      Transaction(
        signature_message_fragment =
          Fragment(
            b'DEAUCXCSCVCTCHDTCSCSAEACCWCTCEAHDTCBDGDXCCDBDEAKDPCGDEAIDBDQCTCP'
            b'CFDPCQC9DTCSAJ9GAHCCDIDLAFDTCEAFDTCPC9D9DMDEABDCDHDEAVCCDXCBDVCE'
            b'AHDCDEA9DXCZCTCEAXCHDQAGAEACDQCGDTCFDJDTCSCEANBTCTCDDEACCWCCDIDV'
            b'CWCHDSAJ9GACCTC9D9DEAIDGDFAGAJ9GAKB9D9DEAFDXCVCWCHDQAGAEAGDPCXCS'
            b'CEANBTCTCDDEACCWCCDIDVCWCHDSAEAGACCWCTCEAKBBDGDKDTCFDEAHDCDEAHDW'
            b'CTCEAQBFDTCPCHDEA9CIDTCGDHDXCCDBDSASASAGAJ9GAHCTCGDIBGAJ9GAYBUCE'
            b'AVBXCUCTCQAEAHDWCTCEADCBDXCJDTCFDGDTCEAPCBDSCEAOBJDTCFDMDHDWCXCB'
            b'DVCSASASAGAEAGDPCXCSCEANBTCTCDDEACCWCCDIDVCWCHDSAJ9GAHCTCGDIBIBG'
            b'AJ9GASBGDSASASAGAJ9GAHCTCGDIBFAGAJ9GAPBCDFDHDMDRAHDKDCDQAGAEAGDP'
            b'CXCSCEANBTCTCDDEACCWCCDIDVCWCHDQAEAKDXCHDWCEAXCBDUCXCBDXCHDTCEAA'
            b'DPCYCTCGDHDMDEAPCBDSCEARCPC9DADSAJ9EAEAEAEAEAEAEAEA'
          ),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999A9PG9A'
            b'XCQANAWGJBTFWEAEQCN9WBZB9BJAIIY9UDLIGFOAA'
          ),

        current_index                     = 4,
        last_index                        = 7,
        value                             = 0,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # Input, Part 1 of 2
      Transaction(
        # Make the signature look like a message, so we can verify that
        # the Bundle skips it correctly.
        signature_message_fragment =
          Fragment.from_string('This is a signature, not a message!'),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999WGSBUA'
            b'HDVHYHOBHGP9VCGIZHNCAAQFJGE9YHEHEFTDAGXHY'
          ),

        current_index                     = 5,
        last_index                        = 7,
        value                             = -100,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # Input, Part 2 of 2
      Transaction(
        # Make the signature look like a message, so we can verify that
        # the Bundle skips it correctly.
        signature_message_fragment =
          Fragment.from_string('This is a signature, not a message!'),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999WGSBUA'
            b'HDVHYHOBHGP9VCGIZHNCAAQFJGE9YHEHEFTDAGXHY'
          ),

        current_index                     = 6,
        last_index                        = 7,
        value                             = 0,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # Change
      Transaction(
        # It's unusual for a change transaction to have a message, but
        # half the fun of unit tests is designing unusual scenarios!
        signature_message_fragment =
          Fragment.from_string('I can haz change?'),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999FFYALH'
            b'N9ACYCP99GZBSDK9CECFI9RAIH9BRCCAHAIAWEFAN'
          ),

        current_index                     = 7,
        last_index                        = 7,
        value                             = 40,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),
    ])

  def test_get_messages_errors_drop(self):
    """
    Decoding messages from a bundle, with ``errors='drop'``.
    """
    messages = self.bundle.get_messages('drop')

    self.assertEqual(len(messages), 3)

    self.assertEqual(messages[0], 'Hello, world!')

    # noinspection SpellCheckingInspection
    self.assertEqual(
      messages[1],

      '''
"Good morning," said Deep Thought at last.
"Er... Good morning, O Deep Thought," said Loonquawl nervously.
  "Do you have... er, that is..."
"... an answer for you?" interrupted Deep Thought majestically. "Yes. I have."
The two men shivered with expectancy. Their waiting had not been in vain.
"There really is one?" breathed Phouchg.
"There really is one," confirmed Deep Thought.
"To Everything? To the great Question of Life, the Universe and Everything?"
"Yes."
Both of the men had been trained for this moment; their lives had been a
  preparation for it; they had been selected at birth as those who would
  witness the answer; but even so they found themselves gasping and squirming
  like excited children.
"And you're ready to give it to us?" urged Loonquawl.
"I am."
"Now?"
"Now," said Deep Thought.
They both licked their dry lips.
"Though I don't think," added Deep Thought, "that you're going to like it."
"Doesn't matter," said Phouchg. "We must know it! Now!"
"Now?" enquired Deep Thought.
"Yes! Now!"
"All right," said the computer and settled into silence again.
  The two men fidgeted. The tension was unbearable.
"You're really not going to like it," observed Deep Thought.
"Tell us!"
"All right," said Deep Thought. "The Answer to the Great Question..."
"Yes?"
"Of Life, the Universe and Everything..." said Deep Thought.
"Yes??"
"Is..."
"Yes?!"
"Forty-two," said Deep Thought, with infinite majesty and calm.
        ''',
    )

    self.assertEqual(messages[2], 'I can haz change?')

  def test_get_messages_errors_strict(self):
    """
    Decoding messages from a bundle, with ``errors='strict'``.
    """
    with self.assertRaises(UnicodeDecodeError):
      self.bundle.get_messages('strict')

  def test_get_messages_errors_ignore(self):
    """
    Decoding messages from a bundle, with ``errors='ignore'``.
    """
    messages = self.bundle.get_messages('ignore')

    self.assertEqual(len(messages), 4)

    # The only message that is treated differently is the invalid one.
    self.assertEqual(messages[0], '祝你好运\x15')

  def test_get_messages_errors_replace(self):
    """
    Decoding messages from a bundle, with ``errors='replace'``.
    """
    messages = self.bundle.get_messages('replace')

    self.assertEqual(len(messages), 4)

    # The only message that is treated differently is the invalid one.
    self.assertEqual(messages[0], '祝你好运�\x15')
Beispiel #29
0
]).get('trytes')

gtta_response = api.get_transactions_to_approve(3)

trunk = gtta_response.get('trunkTransaction')
branch = gtta_response.get('branchTransaction')

attached_original_trytes = api.attach_to_tangle(trunk, branch,
                                                original_trytes).get('trytes')

# So we have the original bundle attached, time to construct the new one
# We need to re-attach, but take special care, so we dont use the api, rather we do it ourself

re_attached_trytes = custom_attach(attached_original_trytes, 9)

original_bundle = Bundle.from_tryte_strings(attached_original_trytes)

re_attached_bundle = Bundle.from_tryte_strings(re_attached_trytes)

pprint('Original bundle is:')
pprint(original_bundle.as_json_compatible())

pprint('Reattached bundle is:')
pprint(re_attached_bundle.as_json_compatible())

#api.broadcast_and_store(attached_original_trytes)
api.broadcast_and_store(re_attached_trytes)

# bundles
# BJRYHWKLREEUQCAZSUQFDNQAIL9LFRBZVEFFWPQZ99GNKATZBUZKFJYJIRYTFBPPESFJYDQRAYHNHH9LW good
# UYBVN9EZKNA9KGGCSILJJGRTNGI9ZHVIUEYB9VXZXHLKZBTFGPHGJPJ9OHCUILSRBAA9XYSDKIXHYVLJW bad
Beispiel #30
0
def attach_to_tangle(
        bundle_trytes,  # Iterable[TryteString]
        trunk_transaction_hash,  # TransactionHash
        branch_transaction_hash,  # TransactionHash
        mwm=14):  # Int
    """
    Attaches the bundle to the Tangle by doing Proof-of-Work
    locally. No connection to the Tangle is needed in this step.

    :param bundle_trytes:
        List of TryteString(s) that contain raw transaction trytes.

    :param trunk_transaction_hash:
        Trunk transaction hash obtained from an iota node.
        Result of the tip selection process.

    :param branch_transaction_hash:
        Branch transaction hash obtained from an iota node.
        Result of the tip selection process.

    :param mwm:
        Minimum Weight Magnitude to be used during the PoW.
        Number of trailing zero trits in transaction hash.

    :returns:
        The bundle as a list of transaction trytes (TryteStrings).
        Attachment timestamp and nonce included.
    """
    previoustx = None

    # Construct bundle object
    bundle = Bundle.from_tryte_strings(bundle_trytes)

    # Used for checking hash
    trailing_zeros = [0] * mwm

    # reversed, beause pyota bundles look like [tx0,tx1,...]
    # and we need the head (last) tx first
    for txn in reversed(bundle.transactions):
        # Ccurl lib sometimes needs a kick to return the correct powed trytes.
        # We can check the correctness by examining trailing zeros of the
        # transaction hash. If that fails, we try calculating the pow again.
        # Use `max_iter` to prevent infinite loop. Calculation error appears
        # rarely, and usually the second try yields correct result. If we reach
        # `max_iter`, we raise a ValueError.
        max_iter = 5
        i = 0

        # If calculation is successful, we break out from the while loop.
        while i != max_iter:
            # Fill timestamps
            txn.attachment_timestamp = get_current_ms()
            txn.attachment_timestamp_upper_bound = (math.pow(3, 27) - 1) // 2

            # Determine correct trunk and branch transaction
            if (not previoustx):  # this is the head transaction
                if txn.current_index == txn.last_index:
                    txn.branch_transaction_hash = branch_transaction_hash
                    txn.trunk_transaction_hash = trunk_transaction_hash
                else:
                    raise ValueError(
                        'Head transaction is inconsistent in bundle')

            else:  # It is not the head transaction
                txn.branch_transaction_hash = trunk_transaction_hash
                txn.trunk_transaction_hash = previoustx  # the previous transaction

            # Let's do the pow locally
            txn_string = txn.as_tryte_string().__str__()
            # returns a python unicode string
            powed_txn_string = get_powed_tx_trytes(txn_string, mwm)
            # construct trytestring from python string
            powed_txn_trytes = TryteString(powed_txn_string)

            # Create powed txn object
            # This method calculates the hash for the transaction
            powed_txn = Transaction.from_tryte_string(trytes=powed_txn_trytes)
            previoustx = powed_txn.hash
            # put that back in the bundle
            bundle.transactions[txn.current_index] = powed_txn

            # Check for inconsistency in hash
            hash_trits = powed_txn.hash.as_trits()
            if hash_trits[-mwm:] == trailing_zeros:
                # We are good to go, exit from while loop
                break
            else:
                i = i + 1
                logger.info(
                    'Ooops, wrong hash detected in try'
                    ' #{rounds}. Recalculating pow... '.format(rounds=i))

        # Something really bad happened
        if i == max_iter:
            raise with_context(
                exc=ValueError(
                    'PoW calculation failed for {max_iter} times.'
                    ' Make sure that the transaction is valid: {tx}'.format(
                        max_iter=max_iter, tx=powed_txn.as_json_compatible())),
                context={
                    'original': txn,
                },
            )

    return bundle.as_tryte_strings()
Beispiel #31
0
  def setUp(self):
    super(BundleTestCase, self).setUp()

    self.bundle = Bundle([
      # This transaction does not have a message.
      Transaction(
        signature_message_fragment = Fragment(b''),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999A9PG9A'
            b'XCQANAWGJBTFWEAEQCN9WBZB9BJAIIY9UDLIGFOAA'
          ),

        current_index                     = 0,
        last_index                        = 7,
        value                             = 0,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # This transaction has something that can't be decoded as a UTF-8
      # sequence.
      Transaction(
        signature_message_fragment =
          Fragment(b'OHCFVELH9GYEMHCF9GPHBGIEWHZFU'),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999HAA9UA'
            b'MHCGKEUGYFUBIARAXBFASGLCHCBEVGTBDCSAEBTBM'
          ),

        current_index                     = 1,
        last_index                        = 7,
        value                             = 10,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # This transaction has a message that fits into a single
      # fragment.
      Transaction(
        signature_message_fragment =
          Fragment.from_unicode('Hello, world!'),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999D99HEA'
            b'M9XADCPFJDFANCIHR9OBDHTAGGE9TGCI9EO9ZCRBN'
          ),

        current_index                     = 2,
        last_index                        = 7,
        value                             = 20,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # This transaction has a message that spans multiple fragments.
      Transaction(
        signature_message_fragment =
          Fragment(
            b'J9GAQBCDCDSCEAADCDFDBDXCBDVCQAGAEAGDPCXCSCEANBTCTCDDEACCWCCDIDVC'
            b'WCHDEAPCHDEA9DPCGDHDSAJ9GAOBFDSASASAEAQBCDCDSCEAADCDFDBDXCBDVCQA'
            b'EAYBEANBTCTCDDEACCWCCDIDVCWCHDQAGAEAGDPCXCSCEAVBCDCDBDEDIDPCKD9D'
            b'EABDTCFDJDCDIDGD9DMDSAJ9EAEAGANBCDEAMDCDIDEAWCPCJDTCSASASAEATCFD'
            b'QAEAHDWCPCHDEAXCGDSASASAGAJ9GASASASAEAPCBDEAPCBDGDKDTCFDEAUCCDFD'
            b'EAMDCDIDIBGAEAXCBDHDTCFDFDIDDDHDTCSCEANBTCTCDDEACCWCCDIDVCWCHDEA'
            b'ADPCYCTCGDHDXCRCPC9D9DMDSAEAGAHCTCGDSAEASBEAWCPCJDTCSAGAJ9CCWCTC'
            b'EAHDKDCDEAADTCBDEAGDWCXCJDTCFDTCSCEAKDXCHDWCEATCLDDDTCRCHDPCBDRC'
            b'MDSAEACCWCTCXCFDEAKDPCXCHDXCBDVCEAWCPCSCEABDCDHDEAQCTCTCBDEAXCBD'
            b'EAJDPCXCBDSAJ9GACCWCTCFDTCEAFDTCPC9D9DMDEAXCGDEACDBDTCIBGAEAQCFD'
            b'TCPCHDWCTCSCEAZBWCCDIDRCWCVCSAJ9GACCWCTCFDTCEAFDTCPC9D9DMDEAXCGD'
            b'EACDBDTCQAGAEARCCDBDUCXCFDADTCSCEANBTCTCDDEACCWCCDIDVCWCHDSAJ9GA'
            b'CCCDEAOBJDTCFDMDHDWCXCBDVCIBEACCCDEAHDWCTCEAVCFDTCPCHDEA9CIDTCGD'
            b'HDXCCDBDEACDUCEAVBXCUCTCQAEAHDWCTCEADCBDXCJDTCFDGDTCEAPCBDSCEAOB'
            b'JDTCFDMDHDWCXCBDVCIBGAJ9GAHCTCGDSAGAJ9LBCDHDWCEACDUCEAHDWCTCEAAD'
            b'TCBDEAWCPCSCEAQCTCTCBDEAHDFDPCXCBDTCSCEAUCCDFDEAHDWCXCGDEAADCDAD'
            b'TCBDHDEBEAHDWCTCXCFDEA9DXCJDTCGDEAWCPCSCEAQCTCTCBDEAPCJ9EAEADDFD'
            b'TCDDPCFDPCHDXCCDBDEAUCCDFDEAXCHDEBEAHDWCTCMDEAWCPCSCEAQCTCTCBDEA'
            b'GDTC9DTCRCHDTCSCEAPCHDEAQCXCFDHDWCEAPCGDEAHDWCCDGDTCEAKDWCCDEAKD'
            b'CDID9DSCJ9EAEAKDXCHDBDTCGDGDEAHDWCTCEAPCBDGDKDTCFDEBEAQCIDHDEATC'
            b'JDTCBDEAGDCDEAHDWCTCMDEAUCCDIDBDSCEAHDWCTCADGDTC9DJDTCGDEAVCPCGD'
            b'DDXCBDVCEAPCBDSCEAGDEDIDXCFDADXCBDVCJ9EAEA9DXCZCTCEATCLDRCXCHDTC'
            b'SCEARCWCXC9DSCFDTCBDSAJ9GAKBBDSCEAMDCDIDLAFDTCEAFDTCPCSCMDEAHDCD'
            b'EAVCXCJDTCEAXCHDEAHDCDEAIDGDIBGAEAIDFDVCTCSCEAVBCDCDBDEDIDPCKD9D'
            b'SAJ9GASBEAPCADSAGAJ9GAXBCDKDIBGAJ9GAXBCDKDQAGAEAGDPCXCSCEANBTCTC'
            b'DDEACCWCCDIDVCWCHDSAJ9CCWCTCMDEAQCCDHDWCEA9DXCRCZCTCSCEAHDWCTCXC'
            b'FDEASCFDMDEA9DXCDDGDSAJ9GACCWCCDIDVCWCEASBEASCCDBDLAHDEAHDWCXCBD'
            b'ZCQAGAEAPCSCSCTCSCEANBTCTCDDEACCWCCDIDVCWCHDQAEAGAHDWCPCHDEAMDCD'
            b'IDLAFDTCEAVCCDXCBDVCEAHDCDEA9DXCZCTCEAXCHDSAGAJ9GANBCDTCGDBDLAHD'
            b'EAADPCHDHDTCFDQAGAEAGDPCXCSCEAZBWCCDIDRCWCVCSAEAGAFCTCEAADIDGDHD'
            b'EAZCBDCDKDEAXCHDFAEAXBCDKDFAGAJ9GAXBCDKDIBGAEATCBDEDIDXCFDTCSCEA'
            b'NBTCTCDDEACCWCCDIDVCWCHDSAJ9GAHCTCGDFAEAXBCDKDFAGAJ9GAKB9D9DEAFD'
            b'XCVCWCHDQAGAEAGDPCXCSCEAHDWCTCEARCCDADDDIDHDTCFDEAPCBDSCEAGDTCHD'
            b'HD9DTCSCEAXCBDHDCDEAGDXC9DTCBDRCTCEAPCVCPCXCBDSAJ9EAEACCWCTCEAHD'
            b'KDCDEAADTCB'
          ),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999A9PG9A'
            b'XCQANAWGJBTFWEAEQCN9WBZB9BJAIIY9UDLIGFOAA'
          ),

        current_index           = 3,
        last_index              = 7,
        value                   = 30,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      Transaction(
        signature_message_fragment =
          Fragment(
            b'DEAUCXCSCVCTCHDTCSCSAEACCWCTCEAHDTCBDGDXCCDBDEAKDPCGDEAIDBDQCTCP'
            b'CFDPCQC9DTCSAJ9GAHCCDIDLAFDTCEAFDTCPC9D9DMDEABDCDHDEAVCCDXCBDVCE'
            b'AHDCDEA9DXCZCTCEAXCHDQAGAEACDQCGDTCFDJDTCSCEANBTCTCDDEACCWCCDIDV'
            b'CWCHDSAJ9GACCTC9D9DEAIDGDFAGAJ9GAKB9D9DEAFDXCVCWCHDQAGAEAGDPCXCS'
            b'CEANBTCTCDDEACCWCCDIDVCWCHDSAEAGACCWCTCEAKBBDGDKDTCFDEAHDCDEAHDW'
            b'CTCEAQBFDTCPCHDEA9CIDTCGDHDXCCDBDSASASAGAJ9GAHCTCGDIBGAJ9GAYBUCE'
            b'AVBXCUCTCQAEAHDWCTCEADCBDXCJDTCFDGDTCEAPCBDSCEAOBJDTCFDMDHDWCXCB'
            b'DVCSASASAGAEAGDPCXCSCEANBTCTCDDEACCWCCDIDVCWCHDSAJ9GAHCTCGDIBIBG'
            b'AJ9GASBGDSASASAGAJ9GAHCTCGDIBFAGAJ9GAPBCDFDHDMDRAHDKDCDQAGAEAGDP'
            b'CXCSCEANBTCTCDDEACCWCCDIDVCWCHDQAEAKDXCHDWCEAXCBDUCXCBDXCHDTCEAA'
            b'DPCYCTCGDHDMDEAPCBDSCEARCPC9DADSAJ9EAEAEAEAEAEAEAEA'
          ),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999A9PG9A'
            b'XCQANAWGJBTFWEAEQCN9WBZB9BJAIIY9UDLIGFOAA'
          ),

        current_index                     = 4,
        last_index                        = 7,
        value                             = 0,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # Input, Part 1 of 2
      Transaction(
        # Make the signature look like a message, so we can verify that
        # the Bundle skips it correctly.
        signature_message_fragment =
          Fragment.from_unicode('This is a signature, not a message!'),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999WGSBUA'
            b'HDVHYHOBHGP9VCGIZHNCAAQFJGE9YHEHEFTDAGXHY'
          ),

        current_index                     = 5,
        last_index                        = 7,
        value                             = -100,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # Input, Part 2 of 2
      Transaction(
        # Make the signature look like a message, so we can verify that
        # the Bundle skips it correctly.
        signature_message_fragment =
          Fragment.from_unicode('This is a signature, not a message!'),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999WGSBUA'
            b'HDVHYHOBHGP9VCGIZHNCAAQFJGE9YHEHEFTDAGXHY'
          ),

        current_index                     = 6,
        last_index                        = 7,
        value                             = 0,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),

      # Change
      Transaction(
        # It's unusual for a change transaction to have a message, but
        # half the fun of unit tests is designing unusual scenarios!
        signature_message_fragment =
          Fragment.from_unicode('I can haz change?'),

        address =
          Address(
            b'TESTVALUE9DONTUSEINPRODUCTION99999FFYALH'
            b'N9ACYCP99GZBSDK9CECFI9RAIH9BRCCAHAIAWEFAN'
          ),

        current_index                     = 7,
        last_index                        = 7,
        value                             = 40,

        # These values are not relevant to the tests.
        branch_transaction_hash           = TransactionHash(b''),
        bundle_hash                       = BundleHash(b''),
        hash_                             = TransactionHash(b''),
        nonce                             = Nonce(b''),
        timestamp                         = 1485020456,
        trunk_transaction_hash            = TransactionHash(b''),
        tag                               = Tag(b''),
        attachment_timestamp              = 1485020456,
        attachment_timestamp_upper_bound  = 1485020456,
        attachment_timestamp_lower_bound  = 1485020456,
      ),
    ])
Beispiel #32
0
  def execute(self, api, **arguments):
    # type: (Iota, ...) -> int
    channel_key_index     = arguments['channel_key_index'] # type: int
    count                 = arguments['count'] # type: int
    depth                 = arguments['depth'] # type: int
    dry_run               = arguments['dry_run'] # type: bool
    mam_encrypt_path      = arguments['mam_encrypt_path'] # type: Text
    min_weight_magnitude  = arguments['min_weight_magnitude'] # type: int
    message_encoding      = arguments['message_encoding'] # type: Text
    message_file          = arguments['message_file'] # type: Optional[Text]
    security_level        = arguments['security_level'] # type: int
    start                 = arguments['start'] # type: int

    if message_file:
      with codecs.open(message_file, 'r', message_encoding) as f_: # type: codecs.StreamReaderWriter
        message = f_.read()

    else:
      self.stdout.write(
        'Enter message to send.  Press Ctrl-D on a blank line when done.\n\n',
      )

      message = self.stdin.read().strip()
      self.stdout.write('\n')

    # Generating the encrypted message may take a little while, so we
    # should provide some feedback to the user so that they know that
    # their input is being processed (this is especially important if
    # the user typed in their message, so that they don't press ^D
    # again, thinking that the program didn't register the first one).
    self.stdout.write('Encrypting message...\n')

    proc =\
      run(
        args = [
          # mam_encrypt.js
          mam_encrypt_path,

          # Required arguments
          binary_type(api.seed),
          message,

          # Options
          '--channel-key-index', text_type(channel_key_index),
          '--start', text_type(start),
          '--count', text_type(count),
          '--security-level', text_type(security_level),
        ],

        check   = True,
        stdout  = PIPE,
        stderr  = self.stderr,
      )

    # The output of the JS script is a collection of transaction
    # trytes, encoded as JSON.
    filter_ =\
      f.FilterRunner(
        starting_filter =
            f.Required
          | f.Unicode
          | f.JsonDecode
          | f.Array
          | f.FilterRepeater(
                f.ByteString(encoding='ascii')
              | Trytes(result_type=TransactionTrytes)
            ),

        incoming_data = proc.stdout,
      )

    if not filter_.is_valid():
      self.stderr.write(
        'Invalid output from {mam_encrypt_path}:\n'
        '\n'
        'Output:\n'
        '{output}\n'
        '\n'
        'Errors:\n'
        '{errors}\n'.format(
          errors            = pformat(filter_.get_errors(with_context=True)),
          mam_encrypt_path  = mam_encrypt_path,
          output            = proc.stdout,
        ),
      )

      return 2

    transaction_trytes = filter_.cleaned_data # type: List[TransactionTrytes]

    bundle = Bundle.from_tryte_strings(transaction_trytes)

    if dry_run:
      self.stdout.write('Transactions:\n\n')
      self.stdout.write(json.dumps(bundle, cls=JsonEncoder, indent=2))
    else:
      api.send_trytes(
        depth                 = depth,
        trytes                = transaction_trytes,
        min_weight_magnitude  = min_weight_magnitude,
      )

      self.stdout.write('Message broadcast successfully!\n')
      self.stdout.write(
        'Bundle ID: {bundle_hash}\n'.format(
          bundle_hash = bundle.hash,
        ),
      )

    return 0