示例#1
0
    def test_happy_path(self):
        """
    Successfully promoting a bundle.
    """

        self.adapter.seed_response('checkConsistency', {
            'state': True,
        })

        result_bundle = Bundle.from_tryte_strings([
            TransactionTrytes(self.trytes1),
            TransactionTrytes(self.trytes2),
        ])
        mock_send_transfer = mock.Mock(return_value={
            'bundle': result_bundle,
        })

        with mock.patch(
                'iota.commands.extended.send_transfer.SendTransferCommand._execute',
                mock_send_transfer,
        ):

            response = self.command(
                transaction=self.hash1,
                depth=3,
                minWeightMagnitude=16,
            )

        self.assertDictEqual(response, {
            'bundle': result_bundle,
        })
示例#2
0
    async def test_happy_path_multiple_bundles(self):
        """
        Get two bundles with multiple transactions.
        """
        # We will fetch the same two bundle
        for _ in range(2):
            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.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(),
        )

        self.assertListEqual(
            response['bundles'][1].as_json_compatible(),
            original_bundle.as_json_compatible(),
        )
示例#3
0
    async def _execute(self, request: dict) -> dict:
        change_address: Optional[Address] = request['changeAddress']
        depth: int = request['depth']
        inputs: Optional[List[Address]] = request['inputs']
        min_weight_magnitude: int = request['minWeightMagnitude']
        seed: Seed = request['seed']
        transfers: List[ProposedTransaction] = request['transfers']
        reference: Optional[TransactionHash] = request['reference']
        security_level: int = request['securityLevel']

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

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

        return {
            'bundle': Bundle.from_tryte_strings(st_response['trytes']),
        }
示例#4
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]
    reference             = request['reference'] # type: Optional[TransactionHash]

    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'],
      reference           = reference,
    )

    return {
      'bundle': Bundle.from_tryte_strings(st_response['trytes']),
    }
示例#5
0
    def fetch_tail_transaction(self, bundle_hash):
        ft_result = self.api.find_transactions(bundles=[bundle_hash])
        transaction_hashes = ft_result['hashes']

        gt_result = self.api.get_trytes(transaction_hashes)
        bundle = Bundle.from_tryte_strings(gt_result['trytes'])

        return bundle.tail_transaction.hash
示例#6
0
def custom_attach(
    trytes: List[TransactionTrytes],
    mwm: int,
):
    """
    Custom attach to to tangle.

    Takes already attached bundle trytes, and except for the the head transaction,
    updates `attachment_timestamp` and re-does the pow, resulting in a new
    nonce and transaction hash.

    The head transaction remains the same as in the original bundle.

    """
    # Install the pow package together with pyota:
    # $ pip install pyota[pow]
    from pow.ccurl_interface import get_powed_tx_trytes, get_hash_trytes, \
        get_current_ms

    previoustx = None

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

    # and we need the head tx first
    for txn in reversed(bundle.transactions):
        if (not previoustx):  # this is the head transaction
            # head tx stays the same, it is the original
            previoustx = txn.hash
            continue

        #we only want to mess with tx at index 1
        if txn.current_index != 1:
            continue

        # set any old tx so that this bundles head.trunk != tx
        txn.branch_transaction_hash = 'TBLBTVTHAMPGMGQBUETQSOYHXLCDKSFRTLECTRKSTCHCEHJLCCRPGCUK9VUJNWGQCQNZCUM9IVVIOB999'  # the previous transaction
        txn.attachment_timestamp = get_current_ms()

        # 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()
示例#7
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
示例#8
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])
示例#9
0
    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 = 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(),
        )
示例#10
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())
示例#11
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']),
    }
示例#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)
示例#13
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
示例#14
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(),
        )
示例#15
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)
    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)
    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''))
示例#18
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
示例#19
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)
示例#20
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()
示例#21
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()
示例#22
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)
示例#23
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
示例#24
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'),
        ]))
示例#25
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'])