예제 #1
0
파일: utils.py 프로젝트: meherett/swap
def get_address_hash(
        address: str,
        script: bool = False) -> Union[str, P2pkhScript, P2shScript]:
    """
    Get Bitcoin address hash.

    :param address: Bitcoin address.
    :type address: str
    :param script: Return script (P2pkhScript, P2shScript), default to False.
    :type script: bool

    :returns: str -- Bitcoin address hash.

    >>> from swap.providers.bitcoin.utils import get_address_hash
    >>> get_address_hash(address="mrmtGq2HMmqAogSsGDjCtXUpxrb7rHThFH", script=False)
    "7b7c4431a43b612a72f8229935c469f1f6903658"
    """

    if not is_address(address=address):
        raise AddressError(f"Invalid Bitcoin '{address}' address.")

    loaded_address = Address.from_string(address)
    get_type = loaded_address.get_type()
    if not script:
        return loaded_address.hash.hex()
    if str(get_type) == "p2pkh":
        return P2pkhScript(loaded_address)
    elif str(get_type) == "p2sh":
        return P2shScript(loaded_address)
예제 #2
0
    def build_transaction(self, wallet, htlc, amount, locktime=0):
        """
        Build bitcoin fund transaction.

        :param wallet: bitcoin sender wallet.
        :type wallet: bitcoin.wallet.Wallet
        :param htlc: bitcoin hash time lock contract (HTLC).
        :type htlc: bitcoin.htlc.HTLC
        :param amount: bitcoin amount to fund.
        :type amount: int
        :param locktime: bitcoin transaction lock time, defaults to 0.
        :type locktime: int
        :returns: FundTransaction -- bitcoin fund transaction instance.

        >>> from shuttle.providers.bitcoin.transaction import FundTransaction
        >>> fund_transaction = FundTransaction(network="testnet")
        >>> fund_transaction.build_transaction(sender_wallet, htlc, 10000)
        <shuttle.providers.bitcoin.transaction.FundTransaction object at 0x0409DAF0>
        """

        # Checking build transaction arguments instance
        if not isinstance(wallet, Wallet):
            raise TypeError(
                "invalid wallet instance, only takes bitcoin Wallet class")
        if not isinstance(htlc, HTLC):
            raise TypeError(
                "invalid htlc instance, only takes bitcoin HTLC class")
        if not isinstance(amount, int):
            raise TypeError("invalid amount instance, only takes integer type")
        # Setting wallet, htlc, amount and unspent
        self.wallet, self.htlc, self.amount = wallet, htlc, amount
        # Getting unspent transaction output
        self.unspent = self.wallet.unspent()
        # Setting previous transaction indexes
        self.previous_transaction_indexes = \
            self.get_previous_transaction_indexes(amount=self.amount)
        # Getting transaction inputs and amount
        inputs, amount = self.inputs(self.unspent,
                                     self.previous_transaction_indexes)
        # Calculating bitcoin fee
        self.fee = fee_calculator(len(inputs), 2)
        if amount < (self.amount + self.fee):
            raise BalanceError("insufficient spend utxos")
        # Building mutable bitcoin transaction
        self.transaction = MutableTransaction(
            version=self.version,
            ins=inputs,
            outs=[
                # Funding into hash time lock contract script hash
                TxOut(value=self.amount,
                      n=0,
                      script_pubkey=P2shScript.unhexlify(self.htlc.hash())),
                # Controlling amounts when we are funding on htlc script.
                TxOut(value=amount - (self.fee + self.amount),
                      n=1,
                      script_pubkey=P2pkhScript.unhexlify(self.wallet.p2pkh()))
            ],
            locktime=Locktime(locktime))
        return self
예제 #3
0
def p2pkh_script(network: str, address: str) -> P2pkhScript:
    '''create pay-to-key-hash (P2PKH) script'''

    network_params = net_query(network)

    addr = Address.from_string(network=network_params,
                               string=address)

    return P2pkhScript(addr)
예제 #4
0
def script_from_address(address, network="testnet"):

    if not is_address(address, network):
        raise AddressError("invalid %s %s address!" % (network, address))

    load_address = Address.from_string(address)
    get_type = load_address.get_type()
    if str(get_type) == "p2pkh":
        return P2pkhScript(load_address)
    elif str(get_type) == "p2sh":
        return P2shScript(load_address)
예제 #5
0
def p2sh_p2pkh_script(network: str, address: str) -> P2shScript:
    '''p2sh embedding p2pkh'''

    network_params = net_query(network)

    addr = Address.from_string(network=network_params,
                               string=address)

    p2pkh = P2pkhScript(addr)

    return P2shScript(p2pkh)
예제 #6
0
    def p2sh(self, address=None):
        """
        Get Bitcoin wallet p2sh.

        :param address: Bitcoin p2sh, default is None.
        :type address: str
        :return: str -- Bitcoin p2sh.

        >>> from shuttle.providers.bitcoin.wallet import Wallet
        >>> wallet = Wallet(network="testnet")
        >>> wallet.from_passphrase("meherett")
        >>> wallet.p2sh()
        "a914a3c4995d9cd0303e5f89ee1433212c797d04ee5d87"
        """
        if address is None:
            return P2shScript(P2pkhScript(self._address)).hexlify()
        if not is_address(address=address, network=self.network):
            raise AddressError("invalid %s %s address" %
                               (self.network, address))
        address = Address.from_string(address)
        return P2shScript(P2pkhScript(address)).hexlify()
예제 #7
0
    def p2pkh(self, address=None):
        """
        Get Bitcoin wallet p2pkh.

        :param address: Bitcoin p2pkh, default is None.
        :type address: str
        :return: str -- Bitcoin p2pkh.

        >>> from shuttle.providers.bitcoin.wallet import Wallet
        >>> wallet = Wallet(network="testnet")
        >>> wallet.from_passphrase("meherett")
        >>> wallet.p2pkh()
        "76a9143c8acde1c7cf370d970725f13eff03bf74b3fc6188ac"
        """
        if address is None:
            return P2pkhScript(self._address).hexlify()
        if not is_address(address=address, network=self.network):
            raise AddressError("invalid %s %s address" %
                               (self.network, address))
        address = Address.from_string(address)
        return P2pkhScript(address).hexlify()
예제 #8
0
파일: wallet.py 프로젝트: meherett/swap
    def p2pkh(self) -> str:
        """
        Get Bitcoin wallet public key/address p2pkh.

        :return: str -- Bitcoin wallet public key/address p2pkh.

        >>> from swap.providers.bitcoin.wallet import Wallet
        >>> wallet = Wallet(network="testnet")
        >>> wallet.from_entropy("72fee73846f2d1a5807dc8c953bf79f1")
        >>> wallet.from_path("m/44'/0'/0'/0/0")
        >>> wallet.p2pkh()
        "76a91433ecab3d67f0e2bde43e52f41ec1ecbdc73f11f888ac"
        """

        return P2pkhScript(Address.from_string(self.address())).hexlify()
예제 #9
0
파일: utils.py 프로젝트: pabraksas/shuttle
def script_from_address(address, network="testnet"):
    """
    Get script from address.

    :param address: Bitcoin address.
    :type address: str
    :param network: Bitcoin network, defaults to testnet.
    :type network: str
    :returns: P2pkhScript, P2shScript -- Bitcoin p2pkh or p2sh script instance.

    >>> from shuttle.providers.bitcoin.utils import script_from_address
    >>> script_from_address("mrmtGq2HMmqAogSsGDjCtXUpxrb7rHThFH", "testnet")
    P2pkhScript('7b7c4431a43b612a72f8229935c469f1f6903658')
    """

    if not is_address(address, network):
        raise AddressError("invalid %s %s address!" % (network, address))
    load_address = Address.from_string(address)
    get_type = load_address.get_type()
    if str(get_type) == "p2pkh":
        return P2pkhScript(load_address)
    elif str(get_type) == "p2sh":
        return P2shScript(load_address)
예제 #10
0
파일: dlcF.py 프로젝트: pewekar/dlc
def sweepTx(MultiSigTx, MultiSigTxOutput, MultiSigTxSolver, to_pubkey,
            to_index, to_value):
    to_spend = MultiSigTx
    unsigned = MutableSegWitTransaction(
        version=1,
        ins=[
            TxIn(
                txid=to_spend,  #.txid,
                txout=to_index,
                script_sig=ScriptSig.empty(),
                sequence=Sequence.max())
        ],
        outs=[
            TxOut(value=to_value - txFee,
                  n=0,
                  script_pubkey=P2pkhScript(to_pubkey))
        ],  # todo make funding_pubkey a parameter. This must sweep back tp A & B
        locktime=Locktime(0))

    solver = MultiSigTxSolver
    signed = unsigned.spend(
        [MultiSigTxOutput],
        [solver])  #print ("Return tx signed ",signed.hexlify())
    return signed.hexlify()
예제 #11
0
def get_outscript(
        pubContract):  #, pubkey_other): #ToDO generate using Pybtc library
    pubscript = P2pkhScript(pubContract)
    return pubscript
예제 #12
0
    def build_transaction(self, transaction_id, wallet, amount, locktime=0):
        """
        Build Bitcoin refund transaction.

        :param transaction_id: Bitcoin fund transaction id to redeem.
        :type transaction_id: str
        :param wallet: Bitcoin sender wallet.
        :type wallet: bitcoin.wallet.Wallet
        :param amount: Bitcoin amount to withdraw.
        :type amount: int
        :param locktime: Bitcoin transaction lock time, defaults to 0.
        :type locktime: int
        :returns: RefundTransaction -- Bitcoin refund transaction instance.

        >>> from shuttle.providers.bitcoin.transaction import RefundTransaction
        >>> from shuttle.providers.bitcoin.wallet import Wallet
        >>> sender_wallet = Wallet(network="testnet").from_passphrase("meherett")
        >>> refund_transaction = RefundTransaction(network="testnet")
        >>> refund_transaction.build_transaction(transaction_id="1006a6f537fcc4888c65f6ff4f91818a1c6e19bdd3130f59391c00212c552fbd", wallet=sender_wallet, amount=10000)
        <shuttle.providers.bitcoin.transaction.RefundTransaction object at 0x0409DAF0>
        """

        # Checking parameter instances
        if not isinstance(transaction_id, str):
            raise TypeError("invalid amount instance, only takes string type")
        if not isinstance(wallet, Wallet):
            raise TypeError(
                "invalid wallet instance, only takes Bitcoin Wallet class")

        # Setting transaction_id and wallet
        self.transaction_id, self.wallet = transaction_id, wallet
        # Getting transaction detail by id
        self.transaction_detail = get_transaction_detail(self.transaction_id)
        # Getting Hash time lock contract output detail
        self.htlc_detail = self.transaction_detail["outputs"][0]
        # Getting HTLC funded amount balance
        htlc_amount = self.htlc_detail["value"]

        # Calculating fee
        self._fee = fee_calculator(1, 1)
        if amount < self._fee:
            raise BalanceError("insufficient spend utxos")
        elif not htlc_amount >= (amount - self._fee):
            raise BalanceError("insufficient spend utxos",
                               f"maximum you can withdraw {htlc_amount}")

        # Building mutable Bitcoin transaction
        self.transaction = MutableTransaction(
            version=self.version,
            ins=[
                TxIn(txid=self.transaction_id,
                     txout=0,
                     script_sig=ScriptSig.empty(),
                     sequence=Sequence.max())
            ],
            outs=[
                TxOut(value=(amount - self._fee),
                      n=0,
                      script_pubkey=P2pkhScript.unhexlify(
                          hex_string=self.wallet.p2pkh()))
            ],
            locktime=Locktime(locktime))
        self._type = "bitcoin_refund_unsigned"
        return self
예제 #13
0
    def build_transaction(self, wallet, htlc, amount, locktime=0):
        """
        Build Bitcoin fund transaction.

        :param wallet: Bitcoin sender wallet.
        :type wallet: bitcoin.wallet.Wallet
        :param htlc: Bitcoin hash time lock contract (HTLC).
        :type htlc: bitcoin.htlc.HTLC
        :param amount: Bitcoin amount to fund.
        :type amount: int
        :param locktime: Bitcoin transaction lock time, defaults to 0.
        :type locktime: int
        :returns: FundTransaction -- Bitcoin fund transaction instance.

        >>> from shuttle.providers.bitcoin.htlc import HTLC
        >>> from shuttle.providers.bitcoin.transaction import FundTransaction
        >>> from shuttle.providers.bitcoin.wallet import Wallet
        >>> htlc = HTLC(network="testnet").init("821124b554d13f247b1e5d10b84e44fb1296f18f38bbaa1bea34a12c843e0158", "muTnffLDR5LtFeLR2i3WsKVfdyvzfyPnVB", "mphBPZf15cRFcL5tUq6mCbE84XobZ1vg7Q", 1000)
        >>> sender_wallet = Wallet(network="testnet").from_passphrase("meherett")
        >>> fund_transaction = FundTransaction(network="testnet")
        >>> fund_transaction.build_transaction(wallet=sender_wallet, htlc=htlc, amount=10000)
        <shuttle.providers.bitcoin.transaction.FundTransaction object at 0x0409DAF0>
        """

        # Checking parameter instances
        if not isinstance(wallet, Wallet):
            raise TypeError(
                "invalid wallet instance, only takes Bitcoin Wallet class")
        if not isinstance(htlc, HTLC):
            raise TypeError(
                "invalid htlc instance, only takes Bitcoin HTLC class")
        if not isinstance(amount, int):
            raise TypeError("invalid amount instance, only takes integer type")

        # Setting wallet, htlc, amount and unspent
        self.wallet, self.htlc, self.amount = wallet, htlc, amount
        # Getting unspent transaction output
        self.unspent = self.wallet.unspent()
        # Setting previous transaction indexes
        self.previous_transaction_indexes = \
            self.get_previous_transaction_indexes(amount=self.amount)

        # Getting transaction inputs and amount
        inputs, amount = self.inputs(
            utxos=self.unspent,
            previous_transaction_indexes=self.previous_transaction_indexes)

        # Calculating Bitcoin fee
        self._fee = fee_calculator(len(inputs), 2)
        if amount < (self.amount + self._fee):
            raise BalanceError("insufficient spend utxos")

        # Building mutable Bitcoin transaction
        self.transaction = MutableTransaction(
            version=self.version,
            ins=inputs,
            outs=[
                # Funding into hash time lock contract script hash
                TxOut(value=self.amount,
                      n=0,
                      script_pubkey=P2shScript.unhexlify(
                          hex_string=self.htlc.hash())),
                # Controlling amounts when we are funding on htlc script
                TxOut(value=(amount - (self._fee + self.amount)),
                      n=1,
                      script_pubkey=P2pkhScript.unhexlify(
                          hex_string=self.wallet.p2pkh()))
            ],
            locktime=Locktime(locktime))
        self._type = "bitcoin_fund_unsigned"
        return self
예제 #14
0
def p2pkh_script(address: str) -> P2pkhScript:
    '''create pay-to-key-hash (P2PKH) script'''

    addr = Address.from_string(address)

    return P2pkhScript(addr)
예제 #15
0
    def build_transaction(self,
                          transaction_id,
                          wallet,
                          amount,
                          secret=None,
                          locktime=0):
        """
        Build bitcoin refund transaction.

        :param transaction_id: bitcoin fund transaction id to redeem.
        :type transaction_id: str
        :param wallet: bitcoin sender wallet.
        :type wallet: bitcoin.wallet.Wallet
        :param amount: bitcoin amount to withdraw.
        :type amount: int
        :param secret: secret passphrase.
        :type secret: str
        :param locktime: bitcoin transaction lock time, defaults to 0.
        :type locktime: int
        :returns: RefundTransaction -- bitcoin refund transaction instance.

        >>> from shuttle.providers.bitcoin.transaction import RefundTransaction
        >>> refund_transaction = RefundTransaction(network="testnet")
        >>> refund_transaction.build_transaction(fund_transaction_id, sender_wallet, 10000)
        <shuttle.providers.bitcoin.transaction.RefundTransaction object at 0x0409DAF0>
        """

        # Checking build transaction arguments instance
        if not isinstance(transaction_id, str):
            raise TypeError("invalid amount instance, only takes string type")
        if not isinstance(wallet, Wallet):
            raise TypeError(
                "invalid wallet instance, only takes bitcoin Wallet class")
        if secret is not None and not isinstance(secret, str):
            raise TypeError("invalid secret instance, only takes string type")
        # Setting transaction_id and wallet
        self.transaction_id, self.wallet, self.secret = transaction_id, wallet, secret
        # Getting transaction detail by id
        self.transaction_detail = get_transaction_detail(self.transaction_id)
        # Checking transaction outputs
        if "outputs" not in self.transaction_detail:
            raise NotFoundError("not found htlc in this %s hash" %
                                self.transaction_id)
        # Hash time lock contract output
        self.htlc = self.transaction_detail["outputs"][0]
        # Sender account output
        sender_address = P2pkhScript.unhexlify(
            self.transaction_detail["outputs"][1]["script"]).address(
                mainnet=self.mainnet)
        self.sender_account = Wallet(network=self.network).from_address(
            str(sender_address))
        # HTLC info's
        htlc_amount = self.htlc["value"]
        htlc_script = P2shScript.unhexlify(self.htlc["script"])
        # Calculating fee
        self.fee = fee_calculator(1, 1)
        if amount < self.fee:
            raise BalanceError("insufficient spend utxos")
        elif not htlc_amount >= (amount - self.fee):
            raise BalanceError("insufficient spend utxos",
                               "maximum withdraw %d" % htlc_amount)
        # Building mutable bitcoin transaction
        self.transaction = MutableTransaction(
            version=self.version,
            ins=[
                TxIn(txid=self.transaction_id,
                     txout=0,
                     script_sig=ScriptSig.empty(),
                     sequence=Sequence.max())
            ],
            outs=[
                TxOut(value=(amount - self.fee),
                      n=0,
                      script_pubkey=P2pkhScript.unhexlify(
                          self.sender_account.p2pkh()))
            ],
            locktime=Locktime(locktime))
        return self
예제 #16
0
# committer
pubk_hex = '0380557a219119218f7830bf3cdb2bb3c8220cac15db97e255498fb992e68c04a9'
privk_hex = '385acd25450e50ecd5ad0fffec7b871c8f75eb3ba9ecded8d35a0765f4763d7e'
pubk = PublicKey.unhexlify(pubk_hex)
privk = PrivateKey.unhexlify(privk_hex)

# 创建输入脚本
secret = 'I have an apple'  # 需要展示的秘密
p2pkh_solver = P2pkhSolver(privk)
hasklock_solver = HashlockSolver(secret.encode(), p2pkh_solver)
if_solver = IfElseSolver(
    Branch.IF,  # branch selection
    hasklock_solver)
# 创建输出脚本
script = P2pkhScript(pubk)

# 获取commit交易
to_spend_hash = "5a98103afa86f00c54ef8cb971ec5b3ad03404e646c46f006efd654bd46d4073"
to_spend_raw = get_raw_tx(to_spend_hash, coin_symbol)
to_spend = TransactionFactory.unhexlify(to_spend_raw)

# 获取罚金数额
penalty = int(float(to_spend.to_json()['vout'][0]['value']) * (10**8))

# 估算挖矿费用
print('estimating mining fee...')
mining_fee_per_kb = get_mining_fee_per_kb(coin_symbol,
                                          api_key,
                                          condidence='high')
estimated_tx_size = cal_tx_size_in_byte(inputs_num=1, outputs_num=1)