Esempio n. 1
0
def script_obj_from_address(address, netcodes=None):
    netcode, key_type, data = netcode_and_type_for_text(address)
    if key_type == 'pay_to_script':
        return ScriptPayToScript(hash160=data)
    if key_type == 'address':
        return ScriptPayToAddress(hash160=data)
    raise ValueError("bad text")
Esempio n. 2
0
File: ui.py Progetto: XertroV/pycoin
def script_obj_from_address(address, netcodes=None):
    netcode, key_type, data = netcode_and_type_for_text(address)
    if key_type == 'pay_to_script':
        return ScriptPayToScript(hash160=data)
    if key_type == 'address':
        return ScriptPayToAddress(hash160=data)
    raise ValueError("bad text")
Esempio n. 3
0
def script_obj_from_address(address, netcodes=None):
    netcode, key_type, data = netcode_and_type_for_text(address, netcodes)
    if key_type == 'pay_to_script':
        return ScriptPayToScript(hash160=data)
    if key_type == 'address':
        return ScriptPayToAddress(hash160=data)
    if key_type == 'address_wit':
        return ScriptPayToAddressWit(version=data[:1], hash160=data[2:])
    if key_type == 'pay_to_script_wit':
        return ScriptPayToScriptWit(version=data[:1], hash256=data[2:])
    raise ValueError("bad text")
Esempio n. 4
0
def script_obj_from_address(address, netcodes=None):
    netcode, key_type, data = netcode_and_type_for_text(address, netcodes)
    if key_type == 'pay_to_script':
        return ScriptPayToScript(hash160=data)
    if key_type == 'address':
        return ScriptPayToAddress(hash160=data)
    if key_type == 'address_wit':
        return ScriptPayToAddressWit(version=data[:1], hash160=data[2:])
    if key_type == 'pay_to_script_wit':
        return ScriptPayToScriptWit(version=data[:1], hash256=data[2:])
    raise ValueError("bad text")
Esempio n. 5
0
    def create_change(self, address: str, existing_txouts, balance: int):
        new_txouts = []
        change_size = 100 * 1000000  # 100 coins
        total_out = sum(txo.coin_value for txo in existing_txouts)
        balance = balance - total_out

        spendables = self.get_spendables(address, get_all=True)

        # Prune out spendables that we will spend.
        for spendable in spendables.copy():
            if total_out == 0:
                continue

            if total_out < 0:
                raise Exception(f"total_out is negative. ({total_out})")

            if spendable.coin_value > total_out:
                spendables.remove(spendable)
                break
            elif total_out > spendable.coin_value:
                spendables.remove(spendable)
                total_out -= spendable.coin_value

        # XXX: Find a way to cleanly unify this.
        _, _, address_hash160 = netcode_and_type_for_text(address)

        # 15 TXs in our own wallet should be a good buffer to have.
        if len(spendables) >= 15:
            return []

        # Create our payment to ourselves if we still have the coins.
        if (balance - (change_size * len(spendables))) < change_size:
            print("Warning: Low balance in address.")
            balance -= (change_size * len(spendables))

        for x in range(len(spendables), 50):
            balance -= change_size
            if balance < 0:
                break

            script_pay = ScriptPayToAddress(hash160=address_hash160).script()
            new_txouts.append(TxOut(change_size, script_pay))

        return new_txouts
Esempio n. 6
0
    def make_txs(self,
                 address: str,
                 chunker: Chunker,
                 use_sends: bool = False) -> bool:
        # We'll do our own chunking if we have to send to address hashes.
        if use_sends:
            chunker.chunk_size = 1024 * 128

        # Calculate hash160 for later.
        _, _, address_hash160 = netcode_and_type_for_text(address)

        # Calculate required TXes and their fees.
        total_fee_needed = self.fee(chunker.data_size)
        last_amount = float(self.get_balance(address))

        # Pick the generation function appropiate for our coin.
        if use_sends:
            gen_function = self.generate_addr_txouts
        else:
            gen_function = self.generate_return_txouts

        print(f"{chunker.chunk_count} TXs will be made.")
        print(f"{total_fee_needed / 1000000} coins will be burnt.")

        if total_fee_needed / 1000000 >= last_amount:
            raise Exception(
                f"Not enough coins to cover insertions. ({total_fee_needed / 1000000} or greater needed.)"
            )

        for nonce, payload in chunker.generate_return_payloads():
            last_amount = float(self.get_balance(address)) * 1000000
            fee_needed = self.fee(len(payload))

            # txout generate stage 1
            txs_out = []
            txs_out.extend(gen_function(address_hash160, payload, fee_needed))
            txs_out.extend(self.create_change(address, txs_out, last_amount))

            # txin generate
            total_amount_txout = sum(txo.coin_value for txo in txs_out)
            remainder_txout = total_amount_txout + fee_needed
            total_amount_txin = 0
            txs_in = []
            # We sort by reverse if we want to devour the latest large TXIn chunk for making change addresses.
            # Sort by random if we have enough spare change.
            creates_change_addrs = (
                total_amount_txout / 1000000
            ) > 100  # XXX/HACK This is assuming spending is not above 100 coins.
            spendables = self.get_spendables(address, total_amount_txout)
            if creates_change_addrs:
                spendables.sort(key=lambda _: _.coin_value,
                                reverse=creates_change_addrs)
            else:
                random.shuffle(spendables)
            for spendable in spendables:
                print(
                    f"OUT {remainder_txout / 1000000}; CV {spendable.coin_value / 1000000}"
                )
                if remainder_txout < 0:
                    break
                txs_in.append(spendable.tx_in())
                total_amount_txin += spendable.coin_value
                remainder_txout -= spendable.coin_value

            # We need to round the change. / txout generate stage 2
            round_change_tx, round_change_amount = self.round_change(
                address_hash160, total_amount_txin, total_amount_txout,
                fee_needed)
            # XXX/HACK This fixes a bug where the round change somehow gets to negative values.
            # I don't even know how that even happens... yet.
            if round_change_tx.coin_value > 0:
                txs_out.append(round_change_tx)
                total_amount_txout += round_change_amount

            # tx sanity checks
            total_combined = total_amount_txin - total_amount_txout

            print(f"[tx#{nonce}] IN {total_amount_txin / 1000000}")
            print(f"[tx#{nonce}] OUT {total_amount_txout / 1000000}")
            print(f"[tx#{nonce}] FEE {total_combined / 1000000}")

            if total_combined < 0:
                print(total_amount_txin)
                print(total_amount_txout)
                raise Exception(
                    f"[tx#{nonce}] negative transaction ({total_combined / 1000000})"
                )
            elif total_combined > HIGHWAY_ROBBERY:
                print(total_amount_txin)
                print(total_amount_txout)
                raise Exception(
                    f"[tx#{nonce}] overpaying fees ({total_combined / 1000000})"
                )

            # tx generate
            new_tx = Tx(1, txs_in, txs_out)

            yield new_tx.as_hex(with_time=True)