Esempio n. 1
0
 def end(self):
     inputs = self.manager.txin
     # Mark style fee estimation
     outputs = [
         (TYPE_ADDRESS, self.manager.contract.addresses[self.manager.mode],
          self.manager.value)
     ]
     tx = Transaction.from_io(inputs, outputs, locktime=0)
     tx.version = 2
     fee = len(tx.serialize(True)) // 2
     if fee > self.manager.value:
         self.show_error("Not enough funds to make the transaction!")
         return
     outputs = [
         (TYPE_ADDRESS, self.manager.contract.addresses[self.manager.mode],
          self.manager.value - fee)
     ]
     tx = Transaction.from_io(inputs, outputs, locktime=0)
     tx.version = 2
     if not self.wallet.is_watching_only():
         self.manager.signtx(tx)
         self.manager.completetx(tx)
     show_transaction(tx,
                      self.main_window,
                      "End Last Will contract",
                      prompt_if_unsaved=True)
     self.plugin.switch_to(Manage, self.wallet_name, None, None)
Esempio n. 2
0
    def showTransaction_desc_(self, txraw, desc) -> None:
        tx = Transaction(txraw, sign_schnorr=parent().prefs_use_schnorr)
        tx.deserialize()
        tx_hash, status_, label_, can_broadcast, amount, fee, height, conf, timestamp, exp_n = wallet(
        ).get_tx_info(tx)
        #print("send: status_",status_,"label_",label_,"amount",amount,"conf",conf)
        size = tx.estimated_size()
        conf = 0 if conf is None else conf
        timestamp = time.time() if timestamp is None else timestamp
        status, status_str = (
            status_, _("Unsigned")
        )  #wallet().get_tx_status(tx_hash, height, conf, timestamp)
        doFX = fx() and fx().is_enabled()
        ccy = fx().get_currency() if doFX else None
        fiat_amount_str = str(self.fiat.text) if doFX else None
        #HistoryEntry = namedtuple("HistoryEntry", "tx tx_hash status_str label v_str balance_str date ts conf status value fiat_amount fiat_balance fiat_amount_str fiat_balance_str ccy status_image")
        entry = HistoryEntry(
            tx, tx_hash, status_str, str(desc), self.amt.text, "",
            timestamp_to_datetime(time.time() if conf <= 0 else timestamp),
            timestamp, conf, status, amount, None, None, fiat_amount_str, None,
            ccy, None)

        def newLabel(l):
            self.descDel.text = l

        self.navigationController.pushViewController_animated_(
            txdetail.CreateTxDetailWithEntry(entry, on_label=newLabel), True)
 def on_tx(self, response):
     #self.print_error("--- got tx response: ", response)
     params, result, error = self.parse_response(response)
     tx_hash = params[0] or ''
     if error:
         self.print_error("error for tx_hash {}, skipping".format(tx_hash))
         return
     try:
         tx = Transaction(result)
         for o in tx.outputs():
             #self.print_error("   output", o)
             address = o[1]
             satoshis = o[2]
             tip = self.tips_by_address.get(address, None)
             if tip:
                 tip.registerPayment(tx_hash,
                                     Decimal("0.00000001") * satoshis,
                                     "chain")
             else:
                 self.tipless_payments_by_address[address] = {
                     "tx_hash": tx_hash,
                     "amount_bch": Decimal("0.00000001") * satoshis
                 }
             # else:
             # 	self.print_error("address", address, ": cannot find associated tip")
     except Exception:
         traceback.print_exc()
         self.print_msg("cannot deserialize transaction, skipping", tx_hash)
         return
def extract_contract_data(tx):
    transaction = Transaction(tx)
    address = get_contract_address(transaction.outputs())
    candidates = get_candidates(transaction.outputs())
    for c in candidates:
        will = LastWillContract(c)
        if will.address.to_ui_string() == address:
            return will
Esempio n. 5
0
 def input_script(self, txin, estimate_size=False, sign_schnorr=False):
     if txin['type'] == 'p2pkh':
         return Transaction.get_preimage_script(txin)
     if txin['type'] == 'p2sh':
         # Multisig verification has partial support, but is disabled. This is the
         # expected serialization though, so we leave it here until we activate it.
         return '00' + push_script(Transaction.get_preimage_script(txin))
     raise Exception("unsupported type %s" % txin['type'])
    def send_tx(self, coin: dict) -> str:
        """Returns the failure reason as a string on failure, or 'None'
        on success."""
        self.wallet.add_input_info(coin)
        inputs = [coin]
        recipient_address = self.recipient_wallet and self.recipient_wallet.get_unused_address(
            frozen_ok=False)
        if not recipient_address:
            self.print_error(
                "Could not get recipient_address; recipient wallet may have been cleaned up, "
                "aborting send_tx")
            return _("Unspecified failure")
        outputs = [(recipient_address.kind, recipient_address, coin['value'])]
        kwargs = {}
        if hasattr(self.wallet, 'is_schnorr_enabled'):
            # This EC version has Schnorr, query the flag
            kwargs['sign_schnorr'] = self.wallet.is_schnorr_enabled()
        # create the tx once to get a fee from the size
        tx = Transaction.from_io(inputs,
                                 outputs,
                                 locktime=self.wallet.get_local_height(),
                                 **kwargs)
        fee = tx.estimated_size()
        if coin['value'] - fee < self.wallet.dust_threshold():
            self.print_error(
                "Resulting output value is below dust threshold, aborting send_tx"
            )
            return _("Too small")
        # create the tx again, this time with the real fee
        outputs = [(recipient_address.kind, recipient_address,
                    coin['value'] - fee)]
        tx = Transaction.from_io(inputs,
                                 outputs,
                                 locktime=self.wallet.get_local_height(),
                                 **kwargs)
        tx.BIP_LI01_sort()
        try:
            self.wallet.sign_transaction(tx, self.password)
        except InvalidPassword as e:
            return str(e)
        except Exception:
            return _("Unspecified failure")

        self.set_label_signal.emit(
            tx.txid(),
            _("Inter-Wallet Transfer {amount} -> {address}").format(
                amount=self.main_window.format_amount(coin['value']) + " " +
                self.main_window.base_unit(),
                address=recipient_address.to_ui_string()))
        try:
            self.main_window.network.broadcast_transaction2(tx)
        except Exception as e:
            self.print_error("Error broadcasting tx:", repr(e))
            return (e.args and e.args[0]) or _("Unspecified failure")
        self.recipient_wallet.frozen_addresses.add(recipient_address)
        self.recipient_wallet.create_new_address(False)
        return None
Esempio n. 7
0
 def tx_from_text(self, txt):
     from electroncash.transaction import tx_from_str
     try:
         txt_tx = tx_from_str(txt)
         tx = Transaction(txt_tx, sign_schnorr=self.wallet.is_schnorr_enabled())
         tx.deserialize()
         return tx
     except:
         traceback.print_exc(file=sys.stdout)
         self.show_critical(_("Electron Cash was unable to parse your transaction"))
         return
def extract_contract_data(wallet, tx, utxo):
    contracts=[]
    print(tx)
    for i in range(len(tx)):
        transaction=Transaction(tx[i])
        address, v = get_contract_info(transaction.outputs())
        candidates = get_candidates(transaction.outputs())
        for c in candidates:
            will = LastWillContract(c, tx[i],v)
            if will.address.to_ui_string()==address:
                contracts.append((utxo[i], will, find_my_role(c, wallet)))
    remove_duplicates(contracts)
    return contracts
Esempio n. 9
0
 def end_tx(self, inputs, direction):
     outputs = [(TYPE_ADDRESS, self.contract.addresses[direction],
                 self.value)]
     tx = Transaction.from_io(inputs, outputs, locktime=0)
     tx.version = 2
     fee = 2 * (len(tx.serialize(True)) // 2 + 1)
     if fee > self.value:
         raise Exception("Not enough funds to make the transaction!")
     outputs = [(TYPE_ADDRESS, self.contract.addresses[direction],
                 self.value - fee)]
     tx = Transaction.from_io(inputs, outputs, locktime=0)
     tx.version = 2
     return tx
    def spend(self, mode):
        prevout_hash = self.fund_txid_e.text()
        prevout_n = int(self.fund_txout_e.text())
        value = int(self.fund_value_e.text())
        locktime = 0
        estimate_fee = lambda x: (1 * x)
        out_addr = Address.from_string(self.redeem_address_e.text())

        # generate the special spend
        inp = self.contract.makeinput(prevout_hash, prevout_n, value, mode)

        inputs = [inp]
        invalue = value

        # add on other spends
        if self.option1_rb.isChecked():
            domain = []
        elif self.option2_rb.isChecked():
            domain = [self.fund_change_address]
        elif self.option3_rb.isChecked():
            domain = None
        else:
            raise RuntimeError
        other_coins = self.wallet.get_utxos(domain,
                                            exclude_frozen=True,
                                            mature=True,
                                            confirmed_only=False)
        for coin in other_coins:
            self.wallet.add_input_info(coin)
            inputs.append(coin)
            invalue += coin['value']

        outputs = [(TYPE_ADDRESS, out_addr, 0)]
        tx1 = Transaction.from_io(inputs, outputs, locktime)
        txsize = len(tx1.serialize(True)) // 2
        fee = estimate_fee(txsize)

        outputs = [(TYPE_ADDRESS, out_addr, invalue - fee)]
        tx = Transaction.from_io(inputs, outputs, locktime)
        self.contract.signtx(tx)
        self.wallet.sign_transaction(tx, self.password)
        self.contract.completetx(tx)

        if mode == 'refund':
            desc = "Spend splittable coin (replayable on any chain)"
        elif mode == 'redeem':
            desc = "Spend splittable coin (CDS chain only!)"
        show_transaction(tx, self.main_window, desc, prompt_if_unsaved=True)
Esempio n. 11
0
 def tableView_didSelectRowAtIndexPath_(self, tv, indexPath):
     tv.deselectRowAtIndexPath_animated_(indexPath, True)
     parent = gui.ElectrumGui.gui
     if parent.wallet is None:
         return
     if not self.vc:
         utils.NSLog(
             "TxHistoryHelper: No self.vc defined, cannot proceed to tx detail screen"
         )
         return
     tx = None
     try:
         entry = _GetTxs(self)[indexPath.row]
         if entry.tx:
             tx = entry.tx
         else:
             tx = parent.wallet.transactions.get(entry.tx_hash, None)
             if tx and tx.raw: tx = Transaction(tx.raw)
     except:
         return
     if tx is None:
         # I'm not sure why this would happen but we did get issue #810 where it happened to 1 user.
         # Perhaps a chain split led to an "old" history view on-screen.  That's my theory, at least. -Calin
         parent.show_error(_(
             "The requested transaction has dropped out of the wallet history.\n\nIf this problem persists, please contact us at electroncash.org."
         ),
                           title=_("Transaction Not Found"),
                           onOk=lambda: parent.refresh_components('history')
                           )
         return
     txd = txdetail.CreateTxDetailWithEntry(entry, tx=tx)
     self.vc.navigationController.pushViewController_animated_(txd, True)
Esempio n. 12
0
    def got_network_response_chunk_slot(self, response, chunk_index):
        if response.get('error'):
            return self.fail_metadata_info("Download chunk data error!\n%r"%(response['error'].get('message')))
        raw = response.get('result')

        tx = Transaction(raw)
        self.handle_chunk_tx(tx, chunk_index)
Esempio n. 13
0
def CreateTxDetailWithTx(tx : Transaction, on_label = None, on_appear = None, asModalNav = False) -> ObjCInstance:
    parent = gui.ElectrumGui.gui
    wallet = parent.wallet
    import time

    tx_hash, status_, label_, can_broadcast, amount, fee, height, conf, timestamp, exp_n = wallet.get_tx_info(tx)
    size = tx.estimated_size()
    status_str = ""
    status = status_
    img = None
    if conf is not None:
        if tx_hash is not None and height is not None and timestamp is not None:
            status, status_str = wallet.get_tx_status(tx_hash, height, conf, timestamp)
            if status is not None and status >= 0 and status < len(StatusImages):
                img = StatusImages[status]
    else:
        conf = 0
    timestamp = time.time() if timestamp is None else timestamp
    doFX = False #fx() and fx().is_enabled()
    ccy = None #fx().get_currency() if doFX else None
    fiat_amount_str = None #str(self.fiat.text) if doFX else None
    #HistoryEntry = namedtuple("HistoryEntry", "extra_data tx_hash status_str label v_str balance_str date ts conf status value fiat_amount fiat_balance fiat_amount_str fiat_balance_str ccy status_image")
    entry = HistoryEntry(tx,tx_hash,status_str,label_,parent.format_amount(amount) if amount is not None else _("Transaction unrelated to your wallet"),
                         "",timestamp_to_datetime(time.time() if conf <= 0 else timestamp),
                         timestamp,conf,status,amount,None,None,fiat_amount_str,None,ccy,img)

    return CreateTxDetailWithEntry(entry, on_label = on_label, on_appear = on_appear, asModalNav = asModalNav)
Esempio n. 14
0
    def create_last_will(self, ):

        outputs = [(TYPE_SCRIPT, ScriptOutput(make_opreturn(self.contract.address.to_ui_string().encode('utf8'))),0),
                   (TYPE_ADDRESS, self.refresh_address, self.value+190),
                   (TYPE_ADDRESS, self.cold_address, 546),
                   (TYPE_ADDRESS, self.inheritor_address, 546)]
        try:
            tx = self.wallet.mktx(outputs, self.password, self.config,
                                  domain=self.fund_domain, change_addr=self.fund_change_address)
            id = tx.txid()
        except NotEnoughFunds:
            return self.show_critical(_("Not enough balance to fund smart contract."))
        except Exception as e:
            return self.show_critical(repr(e))

        # preparing transaction, contract can't give a change
        self.main_window.network.broadcast_transaction2(tx)
        self.create_button.setText("Creating Last Will...")
        self.create_button.setDisabled(True)
        coin = self.wait_for_coin(id,10)
        self.wallet.add_input_info(coin)
        inputs = [coin]
        outputs = [(TYPE_ADDRESS, self.contract.address, self.value)]
        tx = Transaction.from_io(inputs, outputs, locktime=0)
        tx.version=2
        show_transaction(tx, self.main_window, "Make Last Will contract", prompt_if_unsaved=True)

        if self.notification.do_anything() :
            outputs = self.notification.notification_outputs(self.contract.address)
            tx = self.wallet.mktx(outputs, self.password, self.config,
                              domain=self.fund_domain, change_addr=self.fund_change_address)
            show_transaction(tx, self.main_window, "Notification service payment", prompt_if_unsaved=True)

        self.plugin.switch_to(Intro, self.wallet_name, None, None)
Esempio n. 15
0
 def make_Bucket(desc, coins):
     size = sum(
         Transaction.estimated_input_size(coin,
                                          sign_schnorr=sign_schnorr)
         for coin in coins)
     value = sum(coin['value'] for coin in coins)
     min_height = min(coin['height'] for coin in coins)
     return Bucket(desc, size, value, coins, min_height)
 def build_slp_txn(coins, slp_output, receiver_output, postoffice_output,
                   change_output):
     slp_msg = SlpMessage.parseSlpOutputScript(slp_output[1])
     outputs = [slp_output, receiver_output]
     if len(slp_msg.op_return_fields["token_output"]) - 1 == 2:
         outputs.extend([postoffice_output])
     elif len(slp_msg.op_return_fields["token_output"]) - 1 == 3:
         outputs.extend([postoffice_output, change_output])
     tx = Transaction.from_io(coins, outputs)
     return tx
    def got_network_response_slot(self):
        self.download_finished = True

        resp = self.json_response
        if resp.get('error'):
            return self.fail_genesis_info("Download error!\n%r"%(resp['error'].get('message')))
        raw = resp.get('result')

        tx = Transaction(raw)
        self.handle_genesis_tx(tx)
Esempio n. 18
0
 def end(self):
     inputs = [self.manager.txin]
     outputs = [(TYPE_ADDRESS, self.manager.contract.addresses[self.manager.mode], self.manager.value - self.fee)]
     tx = Transaction.from_io(inputs, outputs, locktime=0)
     tx.version=2
     if not self.wallet.is_watching_only():
         self.manager.signtx(tx)
         self.manager.completetx(tx)
     show_transaction(tx, self.main_window, "End Last Will contract", prompt_if_unsaved=True)
     self.plugin.switch_to(Intro, self.wallet_name, None, None)
Esempio n. 19
0
 def _synch_full(self, wallet):
     c = self._get_contacts(wallet)
     if not c:
         # short-circuit abort function early if no contacts exist.
         return dict()
     h = self._get_history(wallet)
     seen = dict()  # Address -> dict of tx_hash_str -> hitem tuple
     for hitem in h:
         if self.stopFlag.is_set():
             # early return, another thread requested a stop
             return None
         # loop through ALL the history and see if relevant tx's exist for contacts we care about
         tx_hash = hitem[0]
         tx = wallet.transactions.get(tx_hash)
         if tx and tx.raw:
             tx = Transaction(tx.raw)  # take a copy
             ins = tx.inputs()  # implicit deserialize
             for x in ins:
                 xa = x['address']
                 if isinstance(xa, PublicKey):
                     xa = xa.toAddress()
                 if isinstance(xa, Address) and xa in c:
                     dct = seen.get(xa, dict())
                     wasEmpty = not dct
                     if tx_hash not in dct:
                         dct[tx_hash] = hitem
                         if wasEmpty: seen[xa] = dct
             outs = tx.outputs()
             for x in outs:
                 typ, xa, dummy = x
                 if isinstance(xa, Address) and xa in c:
                     dct = seen.get(xa, dict())
                     wasEmpty = not dct
                     if tx_hash not in dct:
                         dct[tx_hash] = hitem
                         if wasEmpty: seen[xa] = dct
     storable = dict()
     for addr, d in seen.items():
         addrstr = addr.to_storage_string()
         storable[addrstr] = d
     return storable
Esempio n. 20
0
 def on_qr(self, data):
     from electroncash.bitcoin import base_decode, is_address
     data = data.strip()
     if is_address(data):
         self.set_URI(data)
         return
     if data.startswith('bitcoincash:'):
         self.set_URI(data)
         return
     # try to decode transaction
     from electroncash.transaction import Transaction
     try:
         text = base_decode(data, None, base=43).encode('hex')
         tx = Transaction(text)
         tx.deserialize()
         if self.wallet:
             my_coins = self.wallet.get_spendable_coins(
                 None, self.electrum_config)
             my_outpoints = [
                 vin['prevout_hash'] + ':' + str(vin['prevout_n'])
                 for vin in my_coins
             ]
             for i, txin in enumerate(tx.inputs()):
                 outpoint = txin['prevout_hash'] + ':' + str(
                     txin['prevout_n'])
                 if outpoint in my_outpoints:
                     my_index = my_outpoints.index(outpoint)
                     tx._inputs[i]['value'] = my_coins[my_index]['value']
     except:
         tx = None
     if tx:
         self.tx_dialog(tx)
         return
     # show error
     self.show_error("Unable to decode QR data")
 def tx_from_text(self, txt):
     from electroncash.transaction import tx_from_str
     try:
         txt_tx = tx_from_str(txt)
         tx = Transaction(txt_tx,
                          sign_schnorr=self.wallet.is_schnorr_enabled())
         tx.deserialize()
         if self.wallet:
             my_coins = self.wallet.get_spendable_coins(
                 None, self.main_window.config)
             my_outpoints = [
                 vin['prevout_hash'] + ':' + str(vin['prevout_n'])
                 for vin in my_coins
             ]
             for i, txin in enumerate(tx.inputs()):
                 outpoint = txin['prevout_hash'] + ':' + str(
                     txin['prevout_n'])
                 if outpoint in my_outpoints:
                     my_index = my_outpoints.index(outpoint)
                     tx._inputs[i]['value'] = my_coins[my_index]['value']
         return tx
     except:
         traceback.print_exc(file=sys.stderr)
         self.show_critical(
             _("Electron Cash was unable to parse your transaction"))
         return
Esempio n. 22
0
 def ref_tx(self, contract, utxo_index, m):
     self.manager.choice(contract, utxo_index, m)
     inputs = self.manager.txin
     if self.manager.value - self.fee < 0:
         self.show_error("Not enough funds to make the transaction!")
         return
     outputs = [(TYPE_ADDRESS, self.manager.contract.address,
                 self.manager.value - self.fee)]
     tx = Transaction.from_io(inputs, outputs, locktime=0)
     tx.version = 2
     self.manager.signtx(tx)
     self.wallet.sign_transaction(tx, self.password)
     self.manager.completetx_ref(tx)
     return tx
Esempio n. 23
0
    def make_tx(self,
                coins,
                outputs,
                change_addrs,
                fee_estimator,
                dust_threshold,
                sign_schnorr=False):
        '''Select unspent coins to spend to pay outputs.  If the change is
        greater than dust_threshold (after adding the change output to
        the transaction) it is kept, otherwise none is sent and it is
        added to the transaction fee.'''

        # Deterministic randomness from coins
        utxos = [c['prevout_hash'] + str(c['prevout_n']) for c in coins]
        self.p = PRNG(''.join(sorted(utxos)))

        # Copy the outputs so when adding change we don't modify "outputs"
        tx = Transaction.from_io([], outputs, sign_schnorr=sign_schnorr)
        # Size of the transaction with no inputs and no change
        base_size = tx.estimated_size()
        spent_amount = tx.output_value()

        def sufficient_funds(buckets):
            '''Given a list of buckets, return True if it has enough
            value to pay for the transaction'''
            total_input = sum(bucket.value for bucket in buckets)
            total_size = sum(bucket.size for bucket in buckets) + base_size
            return total_input >= spent_amount + fee_estimator(total_size)

        # Collect the coins into buckets, choose a subset of the buckets
        buckets = self.bucketize_coins(coins, sign_schnorr=sign_schnorr)
        buckets = self.choose_buckets(buckets, sufficient_funds,
                                      self.penalty_func(tx))

        tx.add_inputs([coin for b in buckets for coin in b.coins])
        tx_size = base_size + sum(bucket.size for bucket in buckets)

        # This takes a count of change outputs and returns a tx fee;
        # each pay-to-bitcoin-address output serializes as 34 bytes
        fee = lambda count: fee_estimator(tx_size + count * 34)
        change, dust = self.change_outputs(tx, change_addrs, fee,
                                           dust_threshold)
        tx.add_outputs(change)
        tx.ephemeral['dust_to_fee'] = dust

        self.print_error("using %d inputs" % len(tx.inputs()))
        self.print_error("using buckets:", [bucket.desc for bucket in buckets])

        return tx
Esempio n. 24
0
    def pledge_tx(self):
        inputs = self.txin
        print("creating pledge tx")
        if self.value - self.fee - self.rpayment>0:
            outputs = [
                (TYPE_ADDRESS, self.contract.address, self.value - self.fee - self.rpayment),
                (TYPE_ADDRESS, self.contract.addresses[PROTEGE], self.rpayment)]
        else:
            print("single output")
            outputs = [
                (TYPE_ADDRESS, self.contract.addresses[PROTEGE], self.value - self.fee)]

        tx = Transaction.from_io(inputs, outputs, locktime=0)
        tx.version = 2
        #print(tx.outputs())
        return tx
Esempio n. 25
0
 def make_unsigned_transaction(self, amount, fee, all_inputs, outputs,
                               changes):
     ''' make unsigned transaction '''
     dust = self.dust_threshold(
     )  # always 546 for now, but this call is here in case something more sophisticated happens in the future
     coins = {}
     tx_inputs = []
     amounts = {}
     try:
         for player in all_inputs:
             inputs_coins = self.get_coins(all_inputs[player])
             # if there are no coins on input it terminates the process
             if inputs_coins:
                 coins[player] = inputs_coins
             else:
                 return None
     except BaseException as e:
         self.print_error('make_unsigned_transaction:', repr(e))
         return None
     for player, pubkey_utxos in coins.items():
         amounts[player] = 0
         for pubkey, utxos in pubkey_utxos.items():
             for utxo in utxos:
                 utxo['type'] = 'p2pkh'
                 utxo['address'] = Address.from_pubkey(pubkey)
                 utxo['pubkeys'] = [pubkey]
                 utxo['x_pubkeys'] = [pubkey]
                 utxo['prevout_hash'] = utxo['tx_hash']
                 utxo['prevout_n'] = utxo['tx_pos']
                 utxo['signatures'] = [None]
                 utxo['num_sig'] = 1
                 tx_inputs.append(utxo)
                 amounts[player] += utxo['value']
     tx_inputs.sort(key=lambda x: x['prevout_hash'] + str(x["tx_pos"]))
     tx_outputs = [(TYPE_ADDRESS, Address.from_string(output), int(amount))
                   for output in outputs]
     transaction = Transaction.from_io(tx_inputs,
                                       tx_outputs,
                                       sign_schnorr=False)
     tx_changes = [
         (TYPE_ADDRESS, Address.from_string(changes[player]),
          int(amounts[player] - amount - fee)) for player in sorted(changes)
         if Address.is_valid(changes[player]) and int(amounts[player] -
                                                      amount - fee) >= dust
     ]
     transaction.add_outputs(tx_changes)
     return transaction
Esempio n. 26
0
 def make_unsigned_transaction(self, amount, fee, inputs, outputs, changes):
     coins = {vk : self.get_first_sufficient_utxo(inputs[vk], amount) for vk in inputs}
     for vk in coins:
         coins[vk]['type'] = 'p2pkh'
         coins[vk]['address'] = Address.from_string(self.address(vk))
         coins[vk]['pubkeys'] = [vk]
         coins[vk]['x_pubkeys'] = [vk]
         coins[vk]['prevout_hash'] = coins[vk]['tx_hash']
         coins[vk]['prevout_n'] = coins[vk]['tx_pos']
         coins[vk]['signatures'] = [None]
         coins[vk]['num_sig'] = 1
     tx_inputs = [coins[vk] for vk in sorted(coins)]
     tx_outputs = [(TYPE_ADDRESS, Address.from_string(output), int(amount)) for output in outputs ]
     tx = Transaction.from_io(tx_inputs, tx_outputs)
     tx_changes = [(TYPE_ADDRESS, Address.from_string(changes[vk]), int(coins[vk]['value'] - amount - fee))  for vk in changes if Address.is_valid(changes[vk])]
     tx.add_outputs(tx_changes)
     return tx
Esempio n. 27
0
def tx_from_components(all_components, session_hash):
    """ Returns the tx and a list of indices matching inputs with components"""
    input_indices = []
    assert len(session_hash) == 32
    if Protocol.FUSE_ID is None:
        prefix = []
    else:
        assert len(Protocol.FUSE_ID) == 4
        prefix = [4, *Protocol.FUSE_ID]
    inputs = []
    outputs = [
        (TYPE_SCRIPT,
         ScriptOutput(bytes([OpCodes.OP_RETURN, *prefix, 32]) + session_hash),
         0)
    ]
    for i, compser in enumerate(all_components):
        comp = pb.Component()
        comp.ParseFromString(compser)
        ctype = comp.WhichOneof('component')
        if ctype == 'input':
            inp = comp.input
            if len(inp.prev_txid) != 32:
                raise FusionError("bad component prevout")
            inputs.append(
                dict(address=Address.from_P2PKH_hash(hash160(inp.pubkey)),
                     prevout_hash=inp.prev_txid[::-1].hex(),
                     prevout_n=inp.prev_index,
                     num_sig=1,
                     signatures=[None],
                     type='p2pkh',
                     x_pubkeys=[inp.pubkey.hex()],
                     pubkeys=[inp.pubkey.hex()],
                     sequence=0xffffffff,
                     value=inp.amount))
            input_indices.append(i)
        elif ctype == 'output':
            out = comp.output
            atype, addr = get_address_from_output_script(out.scriptpubkey)
            if atype != TYPE_ADDRESS:
                raise FusionError("bad component address")
            outputs.append((TYPE_ADDRESS, addr, out.amount))
        elif ctype != 'blank':
            raise FusionError("bad component")
    tx = Transaction.from_io(inputs, outputs, locktime=0, sign_schnorr=True)
    tx.version = 1
    return tx, input_indices
    def build_slp_txn(coins, slp_output, pre_postage_outputs,
                      postoffice_output, change_output, send_amount,
                      old_slp_msg):
        slp_msg = SlpMessage.parseSlpOutputScript(slp_output[1])
        pre_postage_outputs = list(pre_postage_outputs[1:])
        if sum(old_slp_msg.op_return_fields["token_output"]
               ) > send_amount:  # has change output
            pre_postage_outputs = pre_postage_outputs[:-1]

        outputs = [slp_output] + pre_postage_outputs
        if len(slp_msg.op_return_fields["token_output"]) - len(
                pre_postage_outputs) == 2:
            outputs.extend([postoffice_output])
        elif len(slp_msg.op_return_fields["token_output"]) - len(
                pre_postage_outputs) == 3:
            outputs.extend([postoffice_output, change_output])
        tx = Transaction.from_io(coins, outputs)
        return tx
Esempio n. 29
0
 def make_unsigned_transaction(self, amount, fee, all_inputs, outputs,
                               changes):
     "make unsigned transaction"
     dust = dust_threshold(self.network)
     coins = {}
     tx_inputs = []
     amounts = {}
     try:
         for player in all_inputs:
             inputs_coins = self.get_coins(all_inputs[player])
             # if there is no coins on input it terminates the process
             if inputs_coins:
                 coins[player] = inputs_coins
             else:
                 return None
     except:
         return None
     for player, pubkey_utxos in coins.items():
         amounts[player] = 0
         for pubkey, utxos in pubkey_utxos.items():
             for utxo in utxos:
                 utxo['type'] = 'p2pkh'
                 utxo['address'] = Address.from_pubkey(pubkey)
                 utxo['pubkeys'] = [pubkey]
                 utxo['x_pubkeys'] = [pubkey]
                 utxo['prevout_hash'] = utxo['tx_hash']
                 utxo['prevout_n'] = utxo['tx_pos']
                 utxo['signatures'] = [None]
                 utxo['num_sig'] = 1
                 tx_inputs.append(utxo)
                 amounts[player] += utxo['value']
     tx_inputs.sort(key=lambda x: x['prevout_hash'] + str(x["tx_pos"]))
     tx_outputs = [(TYPE_ADDRESS, Address.from_string(output), int(amount))
                   for output in outputs]
     transaction = Transaction.from_io(tx_inputs, tx_outputs)
     tx_changes = [
         (TYPE_ADDRESS, Address.from_string(changes[player]),
          int(amounts[player] - amount - fee)) for player in sorted(changes)
         if Address.is_valid(changes[player]) and int(amounts[player] -
                                                      amount - fee) >= dust
     ]
     transaction.add_outputs(tx_changes)
     return transaction
Esempio n. 30
0
    def refresh(self):
        if self.manager.mode!=0:
            print("This wallet can't refresh a contract!")
            return
        print("Notification Service: ")
        print(self.notification.do_anything())
        if self.notification.do_anything() :
            outputs = self.notification.notification_outputs(self.manager.contract.address)
            tx = self.wallet.mktx(outputs, self.password, self.config, None, None)
            show_transaction(tx, self.main_window, "Notification service payment", prompt_if_unsaved=True)

        inputs = [self.manager.txin]
        outputs = [(TYPE_ADDRESS, self.manager.contract.address, self.manager.value-self.fee)]
        tx = Transaction.from_io(inputs, outputs, locktime=0)
        tx.version = 2
        self.manager.signtx(tx)
        self.wallet.sign_transaction(tx, self.password)
        self.manager.completetx_ref(tx)
        show_transaction(tx, self.main_window, "Refresh Last Will contract", prompt_if_unsaved=True)

        self.plugin.switch_to(Intro, self.wallet_name,None,None)