def finalize(self): # type: () -> None """ Finalizes the bundle, preparing it to be attached to the Tangle. """ if self.hash: raise RuntimeError('Bundle is already finalized.') if not self: raise ValueError('Bundle has no transactions.') # Quick validation. balance = self.balance if balance < 0: if self.change_address: self.add_transaction( ProposedTransaction( address=self.change_address, value=-balance, tag=self.tag, )) else: raise ValueError( 'Bundle has unspent inputs (balance: {balance}); ' 'use ``send_unspent_inputs_to`` to create ' 'change transaction.'.format(balance=balance, ), ) elif balance > 0: raise ValueError( 'Inputs are insufficient to cover bundle spend ' '(balance: {balance}).'.format(balance=balance, ), ) # Generate bundle hash. sponge = Curl() last_index = len(self) - 1 for (i, txn) in enumerate(self): # type: Tuple[int, ProposedTransaction] txn.current_index = i txn.last_index = last_index sponge.absorb(txn.get_signature_validation_trytes().as_trits()) bundle_hash_trits = [0] * HASH_LENGTH # type: MutableSequence[int] sponge.squeeze(bundle_hash_trits) # Copy bundle hash to individual transactions. bundle_hash = BundleHash.from_trits(bundle_hash_trits) for txn in self: txn.bundle_hash = bundle_hash # Initialize signature/message fragment. txn.signature_message_fragment = Fragment(txn.message or b'')
def calc_hash(self, bundle): Trxn_HASH_Trytes = 81 HASH_LENGTH = Trxn_HASH_Trytes * 3 # Trits conversion # Generate bundle hash. (taken from python API client) while True: sponge = Kerl() last_index = len(bundle) - 1 for i, txn in enumerate(bundle): txn.current_index = i txn.last_index = last_index sponge.absorb(txn.get_bundle_essence_trits()) bundle_hash_trits = [0] * HASH_LENGTH sponge.squeeze(bundle_hash_trits) bundle_hash = BundleHash.from_trits( bundle_hash_trits) # Convert trits to ascii Trytes bundle.bundle_hash = bundle_hash # Check that we generated a secure bundle hash. # https://github.com/iotaledger/iota.py/issues/84 if any(13 in part for part in normalize(bundle_hash)): # Increment the legacy tag and try again. bundle.tail_transaction.increment_legacy_tag() else: break # Copy bundle hash to individual transactions. for txn in bundle: txn.bundle_hash = bundle_hash # Initialize signature/message fragment. if not txn.value_trxn: # Put dummy message in fragment. # txn.signature_message_fragment = Fragment('9' * 2187) # Fragment Length txn.signature_message_fragment = Fragment( TryteString.from_string( 'IOTA is cool! This is a meta transaction!') ) # Fragment Length else: # Generate signature for bundle transaction txn.signature_message_fragment = self.genSig( bundleHash=bundle_hash) bundle.data_payload = self.name + " (" + str( bundle.outputTrxn.value ) + ") ->" + bundle.outputTrxn.recName return self.conductPOW(bundle)
def finalize(self): # type: () -> None """ Finalizes the bundle, preparing it to be attached to the Tangle. """ if self.hash: raise RuntimeError('Bundle is already finalized.') if not self: raise ValueError('Bundle has no transactions.') # Quick validation. balance = self.balance if balance < 0: if self.change_address: self.add_transaction( ProposedTransaction( address=self.change_address, value=-balance, tag=self.tag, )) else: raise ValueError( 'Bundle has unspent inputs (balance: {balance}); ' 'use ``send_unspent_inputs_to`` to create ' 'change transaction.'.format(balance=balance, ), ) elif balance > 0: raise ValueError( 'Inputs are insufficient to cover bundle spend ' '(balance: {balance}).'.format(balance=balance, ), ) # Generate bundle hash. while True: sponge = Kerl() last_index = len(self) - 1 for (i, txn ) in enumerate(self): # type: Tuple[int, ProposedTransaction] txn.current_index = i txn.last_index = last_index sponge.absorb(txn.get_signature_validation_trytes().as_trits()) bundle_hash_trits = [0] * HASH_LENGTH # type: MutableSequence[int] sponge.squeeze(bundle_hash_trits) bundle_hash = BundleHash.from_trits(bundle_hash_trits) # Check that we generated a secure bundle hash. # https://github.com/iotaledger/iota.lib.py/issues/84 if any(13 in part for part in normalize(bundle_hash)): # Increment the legacy tag and try again. tail_transaction = self.tail_transaction # type: ProposedTransaction tail_transaction.increment_legacy_tag() else: break # Copy bundle hash to individual transactions. for txn in self: txn.bundle_hash = bundle_hash # Initialize signature/message fragment. txn.signature_message_fragment = Fragment(txn.message or b'')
def finalize(self): # type: () -> None """ Finalizes the bundle, preparing it to be attached to the Tangle. This operation includes checking if the bundle has zero balance, generating the bundle hash and updating the transactions with it, furthermore to initialize signature/message fragment fields. Once this method is invoked, no new transactions may be added to the bundle. :raises RuntimeError: if bundle is already finalized. :raises ValueError: - if bundle has no transactions. - if bundle has unspent inputs (there is no ``change_address`` attribute specified.) - if inputs are insufficient to cover bundle spend. """ if self.hash: raise RuntimeError('Bundle is already finalized.') if not self: raise ValueError('Bundle has no transactions.') # Quick validation. balance = self.balance if balance < 0: if self.change_address: self.add_transaction( ProposedTransaction( address=self.change_address, value=-balance, tag=self.tag, )) else: raise ValueError( 'Bundle has unspent inputs (balance: {balance}); ' 'use ``send_unspent_inputs_to`` to create ' 'change transaction.'.format(balance=balance, ), ) elif balance > 0: raise ValueError( 'Inputs are insufficient to cover bundle spend ' '(balance: {balance}).'.format(balance=balance, ), ) # Generate bundle hash. while True: sponge = Kerl() last_index = len(self) - 1 for i, txn in enumerate(self): txn.current_index = i txn.last_index = last_index sponge.absorb(txn.get_signature_validation_trytes().as_trits()) bundle_hash_trits = [0] * HASH_LENGTH sponge.squeeze(bundle_hash_trits) bundle_hash = BundleHash.from_trits(bundle_hash_trits) # Check that we generated a secure bundle hash. # https://github.com/iotaledger/iota.py/issues/84 if any(13 in part for part in normalize(bundle_hash)): # Increment the legacy tag and try again. tail_transaction = (self.tail_transaction ) # type: ProposedTransaction tail_transaction.increment_legacy_tag() else: break # Copy bundle hash to individual transactions. for txn in self: txn.bundle_hash = bundle_hash # Initialize signature/message fragment. txn.signature_message_fragment = Fragment(txn.message or b'')
def finalize(self): # type: () -> None """ Finalizes the bundle, preparing it to be attached to the Tangle. """ if self.hash: raise RuntimeError('Bundle is already finalized.') if not self: raise ValueError('Bundle has no transactions.') # Quick validation. balance = self.balance if balance < 0: if self.change_address: self.add_transaction(ProposedTransaction( address = self.change_address, value = -balance, tag = self.tag, )) else: raise ValueError( 'Bundle has unspent inputs (balance: {balance}); ' 'use ``send_unspent_inputs_to`` to create ' 'change transaction.'.format( balance = balance, ), ) elif balance > 0: raise ValueError( 'Inputs are insufficient to cover bundle spend ' '(balance: {balance}).'.format( balance = balance, ), ) # Generate bundle hash. while True: sponge = Kerl() last_index = len(self) - 1 for (i, txn) in enumerate(self): # type: Tuple[int, ProposedTransaction] txn.current_index = i txn.last_index = last_index sponge.absorb(txn.get_signature_validation_trytes().as_trits()) bundle_hash_trits = [0] * HASH_LENGTH # type: MutableSequence[int] sponge.squeeze(bundle_hash_trits) bundle_hash = BundleHash.from_trits(bundle_hash_trits) # Check that we generated a secure bundle hash. # https://github.com/iotaledger/iota.lib.py/issues/84 if any(13 in part for part in normalize(bundle_hash)): # Increment the legacy tag and try again. tail_transaction = self.tail_transaction # type: ProposedTransaction tail_transaction.increment_legacy_tag() else: break # Copy bundle hash to individual transactions. for txn in self: txn.bundle_hash = bundle_hash # Initialize signature/message fragment. txn.signature_message_fragment = Fragment(txn.message or b'')