예제 #1
0
    def broadcast_message(self, dest_pubkey, messagebytes):
        def callback(response):
            err = response.get('error')
            if err:
                try:
                    print_stderr("Transaction broadcast error:", err['code'],
                                 repr(err['message']))
                except:
                    print_stderr("Transaction broadcast error:", err)
            else:
                print_error("Transaction broadcast result:",
                            response)  # --verbose only

        try:
            dest_addr = Address.from_pubkey(dest_pubkey)
            data = self.key.encrypt_private_message(messagebytes, dest_pubkey)
            tx = self.key.create_message(self.wallet, dest_addr, data,
                                         self.config)
            self.network.broadcast_transaction(tx.serialize(),
                                               callback=callback)
            return True
        except bchmessage.NotEnoughFunds:
            self.show_error("Not enough funds on this address.")
        except Exception as e:
            self.show_error("Error: %s" % (str(e)))
        return False
 def __init__(self, parent):
     QWidget.__init__(self, parent)
     vbox = QVBoxLayout(self)
     self.tab=parent
     self.nottify_me_fee = 100000
     self.nottify_inheritor_fee = 1000000
     self.licho_pubkey = "025721bdf418d241dc886faa79dfc3bac58092b1750b8253ad43d38feb00858b44"
     self.licho_address = Address.from_pubkey(self.licho_pubkey)
     hbox = QHBoxLayout()
     l = QLabel("<b> %s </b>" % "Licho Notification Service")
     self.enable_service = QCheckBox()
     self.enable_service.stateChanged.connect(self.flip)
     hbox.addWidget(l)
     hbox.addWidget(self.enable_service)
     hbox.addStretch(1)
     vbox.addLayout(hbox)
     self.notify_me = QCheckBox(
         "Remind me about the next refreshing one month before the contract expiry date (1 mBCH)")
     self.my_email = QLineEdit()
     self.my_email.setPlaceholderText("My e-mail")
     self.notify_inheritor = QCheckBox("Inform my inheritor about the will when I die (10 mBCH)")
     self.i_email = QLineEdit()
     self.i_email.setPlaceholderText("Inheritors e-mail")
     self.widgets = [self.notify_me, self.my_email, self.notify_inheritor, self.i_email]
     for w in self.widgets:
         vbox.addWidget(w)
     self.disable(True)
     self.disabled=True
예제 #3
0
 def generate_addresses(self, batch):
     addresses = []
     for k in batch:
         k_type, private_key, compressed = deserialize_privkey(k)
         pubkey = public_key_from_private_key(private_key, compressed)
         address = Address.from_pubkey(pubkey)
         addresses.append(address)
     return addresses
예제 #4
0
    def check_inputs_for_sufficient_funds_and_return_total(
            self, inputs, amount):
        """
        This function check on blockchain for sufficient funds.

        inputs is a dict with bitcoin pubkeys as a keys
        and list of utxo hashes as values.

        the sum of all utxo values should be greater then amount

        it does as follows:
        1. check utxo list for every pubkey in the dict
        2. check if utxo from inputs are in the utxo list on blockchain for these pubkeys
            2.a return None if there is a utxo from list not in utxo set from blockchain
            2.b return None if utxo in list is not confirmed
        3. return True, total_amt if summary values of utxos are greater then amount and False, None otherwise
           returns None,None on blockchain communication error
        """
        assert amount > 0, "Amount must be > 0!"

        def _utxo_name(x):
            return x['tx_hash'] + ":" + str(x['tx_pos'])

        total = 0
        try:
            for public_key, pk_inputs in inputs.items():
                try:
                    address = Address.from_pubkey(public_key)
                except AddressError:
                    # refuse to accept something that doesn't parse as a pubkey
                    return False, None
                unspent_list = self.getaddressunspent(address)
                utxos = {
                    _utxo_name(utxo): utxo['value']
                    for utxo in unspent_list if utxo.get('height', -1) >
                    0  # all inputs must have at least 1 confirmation
                }
                for utxo in pk_inputs:
                    val = utxos.get(utxo)
                    if val is None:
                        return False, None  # utxo does not exist or was spent
                    total += val
            answer = total >= amount
            if answer:
                return True, total
            return False, total

        except BaseException as e:
            #import traceback
            #traceback.print_exc()
            self.print_error("check_inputs_for_sufficient_funds: ", repr(e))
        return None, None
예제 #5
0
    def on_load(self):
        tx = None
        try:
            text = text_dialog(self.top_level_window(),
                               _('Input raw transaction'), _("Transaction:"),
                               _("Load transaction"))
            if not text:
                return
            tx = self.main_window.tx_from_text(text)
        except SerializationError as e:
            self.show_critical(
                _("Electron Cash was unable to deserialize the transaction:") +
                "\n" + str(e))
        if tx:
            tx.raw = tx.serialize()
            inputs = tx.inputs()
            metadata = inputs[0]['scriptSig'].split('1234567890')
            sig = metadata[1]
            xpub = metadata[0][-66:]
            addr1 = Address.from_pubkey(str(xpub))
            other_party_role = self.manager.contract.addresses.index(addr1)

            for inp in tx.inputs():
                for i, j in self.manager.txin[0].items():
                    inp[i] = j
                inp['pubkeys'] = inp[
                    'x_pubkeys']  # problems with signing without it
                inp['sequence'] = 0
                inp['signatures'] = [None]
            tx.raw = tx.serialize()
            self.manager.signtx(tx)
            #self.wallet.sign_transaction(tx, self.password)
            for inp in tx.inputs():
                print(inp['signatures'])
                inp['x_pubkeys'].append(xpub)
                inp['signatures'].append(sig)
                if self.manager.mode > other_party_role:
                    # sender key can be on any place but receiver has to be on the first and arbiter has to be on the second.
                    # see sender_v3.spedn
                    inp['x_pubkeys'][0], inp['x_pubkeys'][1] = inp[
                        'x_pubkeys'][1], inp['x_pubkeys'][0]
                    inp['signatures'][0], inp['signatures'][1] = inp[
                        'signatures'][1], inp['signatures'][0]
                inp['num_sig'] = 2
            tx.raw = tx.serialize()
            complete = self.manager.complete_method("end")
            complete(tx)
            print("Script Public Key: ", self.manager.script_pub_key)
            show_transaction(tx,
                             self.main_window,
                             "End Sender Contract",
                             prompt_if_unsaved=True)
예제 #6
0
    def make_clients_threads(self, number_of_clients=None, with_print=False):
        if not number_of_clients:
            number_of_clients = self.number_of_players
        players = [{
            "channel": ChannelWithPrint() if with_print else Channel()
        } for _ in range(number_of_clients)]
        for player in players:
            number_of_pubs = random.randint(1, 3)
            player["secret_keys"] = [
                random_sk() for _ in range(number_of_pubs)
            ]
            player["sks"] = {
                sk.get_public_key(): sk
                for sk in player["secret_keys"]
            }
            player["inputs"] = {}
            for pubk in player["sks"]:
                player["inputs"][pubk] = []
                number_of_coins = random.randint(1, 2)
                addr = public_key_to_p2pkh(bytes.fromhex(pubk))

                for i in range(number_of_coins):
                    min_amout_per_input = self.amount // number_of_pubs // number_of_coins
                    coin_amount = random.randint(
                        min_amout_per_input + self.fee + 1,
                        min_amout_per_input + self.fee + 1000)
                    coin_hash = fake_hash(addr, coin_amount)
                    player["inputs"][pubk].append(coin_hash + ":0")
                    # self.network.add_coin(addr, coin_amount, tx_hash=coin_hash)
                    self.network.add_coin(Address.from_pubkey(pubk),
                                          coin_amount,
                                          tx_hash=coin_hash)
            player["sk"] = random_sk()
            player["pubk"] = player["sk"].get_public_key()
        protocolThreads = [
            testThread(self.HOST,
                       self.PORT,
                       self.network,
                       "x",
                       self.amount,
                       self.fee,
                       player["sk"],
                       player["sks"],
                       player["inputs"],
                       player["pubk"],
                       self.get_random_address(),
                       self.get_random_address(),
                       logger=player['channel']) for player in players
        ]
        return protocolThreads
예제 #7
0
 def get_coins(self, inputs):
     coins = {}
     for public_key in inputs:
         address = Address.from_pubkey(public_key)
         coins[public_key] = []
         unspent_list = self.getaddressunspent(address)
         utxo_hashes = {(utxo["tx_hash"] + ":" + str(utxo["tx_pos"])): utxo
                        for utxo in unspent_list}
         for utxo in inputs[public_key]:
             if utxo in utxo_hashes:
                 coins[public_key].append(utxo_hashes[utxo])
             else:
                 return None
     return coins
예제 #8
0
 def get_coins(self, inputs):
     coins = {}
     for public_key, utxos in inputs.items():
         address = Address.from_pubkey(public_key)
         coins[public_key] = []  # FIXME: Should probably use a defaultdict here but maybe we want calling code to fail on KeyError ?
         unspent_list = self.getaddressunspent(address)
         utxo_dicts = { "{}:{}".format(utxo["tx_hash"], utxo["tx_pos"]) : utxo
                        for utxo in unspent_list }
         for utxo in utxos:
             utxo_dict = utxo_dicts.get(utxo)
             if utxo_dict:
                 coins[public_key].append(utxo_dict)
             else:
                 # uh-oh.. not found. may have been double-spent in the meantimg or buggy Player peer.
                 return None
     return coins
예제 #9
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
예제 #10
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
예제 #11
0
def check_input_electrumx(network, inpcomp):
    """ Check an InputComponent against electrumx service. This can be a bit slow
    since it gets all utxos on that address. """
    address = Address.from_pubkey(inpcomp.pubkey)
    prevhash = inpcomp.prev_txid[::-1].hex()
    prevn = inpcomp.prev_index
    sh = address.to_scripthash_hex()
    u = network.synchronous_get(('blockchain.scripthash.listunspent', [sh]), timeout=5)
    for item in u:
        if prevhash == item['tx_hash'] and prevn == item['tx_pos']:
            break
    else:
        raise ValidationError('missing or spent or scriptpubkey mismatch')

    check(item['height'] > 0, 'not confirmed')
    check(item['value'] == inpcomp.amount, 'amount mismatch')
    # Not checked: is it a coinbase? is it matured?
    # A feasible strategy to identify unmatured coinbase is to cache the results
    # of blockchain.transaction.id_from_pos(height, 0) from the last 100 blocks.
    return True
예제 #12
0
 def __init__(self, window, wallet, network_settings,
              period = 10.0, logger = None, password=None, timeout=60.0,
              typ=Messages.DEFAULT  # NB: Only DEFAULT is currently supported
              ):
     super().__init__()
     cls = type(self)
     self.daemon = True
     self.timeout = timeout
     self.version = cls.PROTOCOL_VERSION + (1 if networks.net.TESTNET else 0)
     self.type = typ
     assert self.type == Messages.DEFAULT, "BackgroundShufflingThread currently only supports DEFAULT shuffles"
     cls.latest_shuffle_settings = cls.ShuffleSettings(self.type, Messages.TYPE_NAME_DICT[self.type], self.version, 0, 0, self.FEE)
     # set UPPER_BOUND and LOWER_BOUND from config keys here. Note all instances will see these changes immediately.
     cls.update_lower_and_upper_bound_from_config()
     self.period = period
     self.logger = logger
     self.wallet = wallet
     self.window = window
     self.host = network_settings.get("host", None)
     self.info_port = network_settings.get("info", None)
     self.port = 1337  # default value -- will get set to real value from server's stat port in run() method
     self.poolSize = 3  # default value -- will get set to real value from server's stat port in run() method
     self.banScore = 0  # comes from stats port -- our own personal ban score
     self.banned = False  # comes from stats port. True if our IP is banned (default ban duration: 30 mins)
     self.ssl = network_settings.get("ssl", None)
     self.lock = threading.RLock()
     self.password = password
     self.threads = {scale:None for scale in self.scales}
     self.shared_chan = Channel(switch_timeout=None)  # threads write a 3-tuple here: (killme_flg, thr, msg)
     self.stop_flg = threading.Event()
     self.last_idle_check = 0.0  # timestamp in seconds unix time
     self.done_utxos = dict()
     self._paused = False
     self._coins_busy_shuffling = set()  # 'prevout_hash:n' (name) set of all coins that are currently being shuffled by a ProtocolThread. Both wallet locks should be held to read/write this.
     self._last_server_check = 0.0  # timestamp in seconds unix time
     self._dummy_address = Address.from_pubkey(EC_KEY(number_to_string(1337, generator_secp256k1.order())).get_public_key())  # dummy address
     # below 4 vars are related to the "delayed unreserve address" mechanism as part of the bug #70 & #97 workaround and the complexity created by it..
     self._delayed_unreserve_addresses = dict()  # dict of Address -> time.time() timestamp when its shuffle ended
     self._last_delayed_unreserve_check = 0.0  # timestamp in seconds unix time
     self._delayed_unreserve_check_interval = 60.0  # check these addresses every 60 seconds.
     self._delayed_unreserve_timeout = 600.0  # how long before the delayed-unreserve addresses expire; 10 minutes
예제 #13
0
def check_input_electrumx(network, inpcomp):
    """ Check an InputComponent against electrumx service. This can be a bit slow
    since it gets all utxos on that address.

    Returns normally if the check passed. Raises ValidationError if the input is not
    consistent with blockchain (according to server), and raises other exceptions if
    the server times out or gives an unexpected kind of response.
    """
    address = Address.from_pubkey(inpcomp.pubkey)
    prevhash = inpcomp.prev_txid[::-1].hex()
    prevn = inpcomp.prev_index
    sh = address.to_scripthash_hex()
    u = network.synchronous_get(('blockchain.scripthash.listunspent', [sh]), timeout=5)
    for item in u:
        if prevhash == item['tx_hash'] and prevn == item['tx_pos']:
            break
    else:
        raise ValidationError('missing or spent or scriptpubkey mismatch')

    check(item['height'] > 0, 'not confirmed')
    check(item['value'] == inpcomp.amount, 'amount mismatch')
예제 #14
0
    def check_inputs_for_sufficient_funds(self, inputs, amount):
        """
        This function check on blockchain for sufficient funds.

        inputs is a dict with bitcoin pubkeys as a keys
        and list of utxo hashes as values.

        the sum of all utxo values should be greater then amount

        it does as follows:
        1. check utxo list for every pubkey in the dict
        2. check if utxo from inputs are in the utxo list on blockchain for these pubkeys
            2.a return None if there is a utxo from list not in utxo set from blockchain
            2.b return None if utxo in list is not confirmed
        3. return True if summary values of utxos are greater then amount and False otherwise
        """
        def _utxo_name(x):
            return x['tx_hash'] + ":" + str(x['tx_pos'])

        total = 0
        try:
            for public_key, pk_inputs in inputs.items():
                address = Address.from_pubkey(public_key)
                unspent_list = self.getaddressunspent(address)
                utxos = {
                    _utxo_name(utxo): utxo['value']
                    for utxo in unspent_list if utxo.get('height', -1) >
                    0  # all inputs must have at least 1 confirmation
                }
                for utxo in pk_inputs:
                    val = utxos.get(utxo)
                    if val is None:
                        return None
                    total += val
            return total >= amount
        except:
            return None
예제 #15
0
    def make_private_offer(self, dest_pubkey, order_12, amtw, amtg):
        # Used for start of negotiation
        wallet = self.pmw.wallet
        key = self.pmw.key

        now = int(time.time())
        offer = openswap.OfferInfo(
            salt=token_bytes(8),
            want_rtime=now + 10 * 3600,
            give_rtime=now + 5 * 3600,
            want_amount=amtg,
            want_ticker=self.b1 if order_12 else self.b2,
            give_amount=amtw,
            give_ticker=self.b2 if order_12 else self.b1,
        )
        d = OfferInfoDialog(self, offer, dest_pubkey, mode='create')
        res = d.exec_()
        if res:
            try:
                offerinfo = d.get_offerinfo()
                pak = openswap.PacketOffer.make(key.privkey, dest_pubkey,
                                                offerinfo)
                offermsg = openswap.OpenSwapMessage([pak], autopad=204)
                messagebytes = offermsg.to_bytes()

                data = key.encrypt_private_message(messagebytes, dest_pubkey)
                tx = key.create_message(wallet,
                                        Address.from_pubkey(dest_pubkey), data,
                                        self.config)
                self.broadcast_tx(tx)
            except bchmessage.NotEnoughFunds:
                self.show_error("Not enough funds on this address.")
            except Exception as e:
                import traceback
                traceback.print_exc()
                self.show_error(str(e))
def address_from_public_key(public_key):
    "get address from public key"
    # return Address.from_string(public_key_to_p2pkh(bytes.fromhex(public_key))).to_ui_string()
    # return Address.from_pubkey(public_key).to_ui_string()
    return Address.from_pubkey(public_key)