Exemplo n.º 1
0
    def test_segwit_create_tx(self):
        from pycoin.tx.tx_utils import create_tx, sign_tx
        from pycoin.tx.Spendable import Spendable
        from pycoin.tx.pay_to.ScriptPayToAddress import ScriptPayToAddress
        from pycoin.tx.pay_to.ScriptPayToAddressWit import ScriptPayToAddressWit
        from pycoin.tx.pay_to.ScriptPayToScriptWit import ScriptPayToScriptWit
        from pycoin.ui import address_for_pay_to_script_wit, script_obj_from_address
        key1 = Key(1)
        coin_value = 5000000
        script = ScriptPayToAddressWit(b'\0', key1.hash160()).script()
        tx_hash = b'\ee' * 32
        tx_out_index = 0
        spendable = Spendable(coin_value, script, tx_hash, tx_out_index)
        key2 = Key(2)
        tx = create_tx([spendable], [(key2.address(), coin_value)])
        self.check_unsigned(tx)
        sign_tx(tx, [key1.wif()])
        self.check_signed(tx)
        self.assertEqual(len(tx.txs_in[0].witness), 2)

        s1 = ScriptPayToAddress(key1.hash160()).script()
        address = address_for_pay_to_script_wit(s1)
        spendable.script = script_obj_from_address(address).script()
        tx = create_tx([spendable], [(key2.address(), coin_value)])
        self.check_unsigned(tx)
        sign_tx(tx, [key1.wif()], p2sh_lookup=build_p2sh_lookup([s1]))
        self.check_signed(tx)
Exemplo n.º 2
0
    def test_segwit_create_tx(self):
        from pycoin.tx.tx_utils import create_tx, sign_tx
        from pycoin.tx.Spendable import Spendable
        from pycoin.tx.pay_to.ScriptPayToAddress import ScriptPayToAddress
        from pycoin.tx.pay_to.ScriptPayToAddressWit import ScriptPayToAddressWit
        from pycoin.tx.pay_to.ScriptPayToScriptWit import ScriptPayToScriptWit
        from pycoin.ui import address_for_pay_to_script_wit, script_obj_from_address
        key1 = Key(1)
        coin_value = 5000000
        script = ScriptPayToAddressWit(b'\0', key1.hash160()).script()
        tx_hash = b'\ee' * 32
        tx_out_index = 0
        spendable = Spendable(coin_value, script, tx_hash, tx_out_index)
        key2 = Key(2)
        tx = create_tx([spendable], [(key2.address(), coin_value)])
        self.check_unsigned(tx)
        sign_tx(tx, [key1.wif()])
        self.check_signed(tx)
        self.assertEqual(len(tx.txs_in[0].witness), 2)

        s1 = ScriptPayToAddress(key1.hash160()).script()
        address = address_for_pay_to_script_wit(s1)
        spendable.script = script_obj_from_address(address).script()
        tx = create_tx([spendable], [(key2.address(), coin_value)])
        self.check_unsigned(tx)
        sign_tx(tx, [key1.wif()], p2sh_lookup=build_p2sh_lookup([s1]))
        self.check_signed(tx)
Exemplo n.º 3
0
def txs_from_json(path):
    """
    Read tests from ./data/tx_??valid.json
    Format is an array of arrays
    Inner arrays are either [ "comment" ]
    or [[[prevout hash, prevout index, prevout scriptPubKey], [input 2], ...], serializedTransaction, verifyFlags]
    ... where all scripts are stringified scripts.

    verifyFlags is a comma separated list of script verification flags to apply, or "NONE"
    """
    with open(path, 'r') as f:
        for tvec in json.load(f):
            if len(tvec) == 1:
                continue
            assert len(tvec) == 3
            prevouts = tvec[0]
            for prevout in prevouts:
                assert len(prevout) == 3

            tx_hex = tvec[1]

            flags = set()
            for flag in tvec[2].split(','):
                assert flag in FLAGS
                flags.add(flag)

            try:
                tx = Tx.from_hex(tx_hex)
            except:
                print("Cannot parse tx_hex: %s" % tx_hex)
                raise

            spendable_db = {}
            blank_spendable = Spendable(0, b'', b'\0' * 32, 0)
            for prevout in prevouts:
                spendable = Spendable(coin_value=1000000,
                                      script=compile_script(prevout[2]),
                                      tx_hash=h2b_rev(prevout[0]),
                                      tx_out_index=prevout[1])
                spendable_db[(spendable.tx_hash,
                              spendable.tx_out_index)] = spendable
            unspents = [
                spendable_db.get((tx_in.previous_hash, tx_in.previous_index),
                                 blank_spendable) for tx_in in tx.txs_in
            ]
            tx.set_unspents(unspents)

            yield (tx, flags)
Exemplo n.º 4
0
    def test_simple_spend(self):

        FEE = 10000

        # create a fake Spendable
        COIN_VALUE = 100000000
        spendables = [Spendable(COIN_VALUE, standard_tx_out_script(BITCOIN_ADDRESSES[0]), FAKE_HASHES[1], 0)]

        EXPECTED_IDS = [
            "d28bff6c4a8a0f9e7d5b7df0670d07b43c5613d8c9b14e84707b1e2c0154a978",
            "7afbe63b00171b18f806ebd48190ebc1c68cadf286a85489c06ebe43d146489e",
            "2b90c150ba1d080a0816952f5d9c2642d408989cbc4d4c540591c8c9241294bd",
            "17b0b5b22887081595c1a9ad153e903f63bb8682ae59d6082df018dc617e5e67",
            "dff1b34c243becb096ad2a2d6119973067a8137cc8bf95615e742bbf6f0944c1",
            "206bbfbb759a8f91901d86b62390d7587f6097a32994ece7752d143fc8a02cee",
            "7841412716ad35cbc9954e547ba85be89e5ed0b34ed5fb8d7594517318dc10d6",
            "8b7e643bf47db46ada7a75b8498990b111fe20917b5610ca6759b8b0078ccd5e",
            "5756f0a6d5a2bbb93a07f0729d3773aaafd21393ede3ec0e20b0b5219ca45548",
            "32dcbb34965ea72d2caa59eb1e907aa28bac2afea43214c1809f5d8ed360f30e",
        ]

        for count in range(1, 11):
            tx = create_signed_tx(spendables, BITCOIN_ADDRESSES[1:count+1], wifs=WIFS[:1])
            self.assertEqual(tx.bad_signature_count(), 0)
            self.assertEqual(tx.fee(), FEE)
            self.assertEqual(tx.id(), EXPECTED_IDS[count-1])
            # TODO: add check that s + s < generator for each signature
            for i in range(count):
                extra = (1 if i < ((COIN_VALUE - FEE) % count) else 0)
                self.assertEqual(tx.txs_out[i].coin_value, (COIN_VALUE - FEE)//count + extra)
Exemplo n.º 5
0
    def get_spendables(self, address: str, amount: int = None, get_all=False):
        spendables = []

        # Safety for some very good code.
        if not amount and not get_all and amount <= 0:
            raise Exception("Amount or get_all flag must be given.")

        # Check for unspents.
        unspents = self.connection.listunspent(0, 9999999, [address])
        if not unspents:
            raise Exception(f"No unspent inputs found on adddress {address}.")

        for tx in unspents:
            spendables.append(
                Spendable.from_dict(
                    dict(coin_value=tx["amount"] * 1000000,
                         script_hex="0000",
                         tx_hash_hex=tx["txid"],
                         tx_out_index=tx["vout"])))

            if not get_all and (amount < 0):
                break

            if amount:
                amount -= tx["amount"] * 1000000

        return spendables
Exemplo n.º 6
0
def createTX(payment):

    (content,(addrToSend,amountToSend)) = payment
    
    if content is None:
        pass
        # it should include a reason for the  error....
        # raise an exception

        return None # actually instead of returning it should raise an exception....

    else:

        (utxos,retAddr) = content
        keys            = []
        spendings       = []

        for ((txid,index),amount,key) in utxos:

            keys      += [key.wif()]

            spendings += [ Spendable( amount
                                    , ScriptPayToAddress( key.hash160()).script()
                                    , h2b_rev(txid)
                                    , index
                                    )
                         ]
        print "########################################################################################"
        print ('spendings     :',spendings)
        print ('addr to send  :',addrToSend)
        print ('amountToSend  :',amountToSend)
        print ('retAddr       :',retAddr)
        print ('wif list      :',keys)
        print ('transaction   :',create_signed_tx(spendings,[(addrToSend,amountToSend),retAddr],wifs=keys, fee="standard").as_hex())
        print "########################################################################################"
Exemplo n.º 7
0
    def test_confirm_input(self):
        FEE = 10000

        # create a fake Spendable
        COIN_VALUE = 100000000
        spendables = [
            Spendable(COIN_VALUE, standard_tx_out_script(BITCOIN_ADDRESSES[0]),
                      FAKE_HASHES[1], 0)
        ]

        tx_1 = create_signed_tx(spendables,
                                BITCOIN_ADDRESSES[1:2],
                                wifs=WIFS[:1])

        spendables = tx_1.tx_outs_as_spendable()

        tx_db = dict((tx.hash(), tx) for tx in [tx_1])

        tx_2 = create_signed_tx(spendables,
                                BITCOIN_ADDRESSES[2:3],
                                wifs=WIFS[:3])
        tx_2.validate_unspents(tx_db)

        tx_2 = create_signed_tx([s.as_dict() for s in spendables],
                                BITCOIN_ADDRESSES[2:3],
                                wifs=WIFS[:3])
        tx_2.validate_unspents(tx_db)

        tx_2 = create_signed_tx([s.as_text() for s in spendables],
                                BITCOIN_ADDRESSES[2:3],
                                wifs=WIFS[:3])
        tx_2.validate_unspents(tx_db)
Exemplo n.º 8
0
 def test_create_trx(self):
     SelectParams('testnet')
     b = h2b('8443b07464c762d7fb404ea918a5ac9b3618d5cd6a0c5ea6e4dd5d7bbe28b154')
     tx_input = Spendable(200, b'18eKkAWyU9kvRNHPKxnZb6wwtPMrNmRRRA',
                          b, 0)
     tx_outs = [tx_utils.create_transaction_output('mgAqW5ZCnEp7fjvpj8RUL3WxsBy8rcDcCi', 0.0000275)]
     tx = tx_utils.create_trx('TEST'.encode('utf-8'), 3, 'mgAqW5ZCnEp7fjvpj8RUL3WxsBy8rcDcCi', tx_outs, [tx_input])
     hextx = b2h(tx.serialize())
     self.assertEquals(hextx,
                       '01000000018443b07464c762d7fb404ea918a5ac9b3618d5cd6a0c5ea6e4dd5d7bbe28b1540000000000ffffffff0300000000000000001976a914072a22e5913cd939904c46bbd0bc56755543384b88acc5000000000000001976a914072a22e5913cd939904c46bbd0bc56755543384b88ac0000000000000000066a045445535400000000')
Exemplo n.º 9
0
 async def get_spendable_list_for_addr(self, addr: str) -> List[Spendable]:
     unspent_list = await self.get_listunspent_for_addr(addr)
     return [
         Spendable(
             unspent['amount'],
             bytes(unspent['scriptPubKey']),
             unspent['outpoint'].hash,
             unspent['outpoint'].n,
         ) for unspent in unspent_list
     ]
Exemplo n.º 10
0
    def test_verify_transaction(self):
        SelectParams('testnet')
        b = h2b('8443b07464c762d7fb404ea918a5ac9b3618d5cd6a0c5ea6e4dd5d7bbe28b154')
        tx_input = Spendable(200, b'18eKkAWyU9kvRNHPKxnZb6wwtPMrNmRRRA', b, 0)
        tx_outs = [tx_utils.create_transaction_output('mgAqW5ZCnEp7fjvpj8RUL3WxsBy8rcDcCi', 0.0000275)]
        op_return_val = h2b('e9cee71ab932fde863338d08be4de9dfe39ea049bdafb342ce659ec5450b69ae')
        tx = tx_utils.create_trx(op_return_val, 3, 'mgAqW5ZCnEp7fjvpj8RUL3WxsBy8rcDcCi', tx_outs, [tx_input])

        hextx = b2h(tx.serialize())

        tx_utils.verify_transaction(hextx, b2h(op_return_val))
Exemplo n.º 11
0
 def test_BloomFilter(self):
     bf = BloomFilter(20, hash_function_count=5, tweak=127)
     bf.add_hash160(h2b("751e76e8199196d454941c45d1b3a323f1433bd6"))
     tx_hash = h2b(
         "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798")
     spendable = Spendable(coin_value=1000,
                           script=b'foo',
                           tx_hash=tx_hash,
                           tx_out_index=1)
     bf.add_spendable(spendable)
     self.assertEqual(bf.filter_bytes,
                      h2b("0000400000000000090030400042100100000000"))
Exemplo n.º 12
0
def spend_sh_fund(tx_ins, wif_keys, tx_outs):
    """
    spend script hash fund
    the key point of an input comes from multisig address is that,
    its sign script is combined with several individual signs
    :param tx_ins: list with tuple(tx_id, idx, balance, address, redeem_script)
    :param wif_keys: private keys in wif format,
        technical should be the same order with the pubkey in redeem script,
        but pycoin has inner control, so here order is not mandatory
    :param tx_outs: balance, receiver_address
    :return: raw hex and tx id
    """
    _txs_in = []
    _un_spent = []
    for tx_id, idx, balance, address, _ in tx_ins:
        # must h2b_rev NOT h2b
        tx_id_b = h2b_rev(tx_id)
        _txs_in.append(TxIn(tx_id_b, idx))

        _un_spent.append(
            Spendable(
                balance,
                script_obj_from_address(address, netcodes=[NET_CODE]).script(),
                tx_id_b, idx))

    _txs_out = []
    for balance, receiver_address in tx_outs:
        _txs_out.append(
            TxOut(
                balance,
                script_obj_from_address(receiver_address,
                                        netcodes=[NET_CODE]).script()))

    version, lock_time = 1, 0
    tx = Tx(version, _txs_in, _txs_out, lock_time)
    tx.set_unspents(_un_spent)

    # construct hash160_lookup[hash160] = (secret_exponent, public_pair, compressed) for each individual key
    hash160_lookup = build_hash160_lookup(
        [Key.from_text(wif_key).secret_exponent() for wif_key in wif_keys])

    for i in range(0, len(tx_ins)):
        # you can add some conditions that if the input script is not p2sh type, not provide p2sh_lookup,
        # so that all kinds of inputs can work together
        p2sh_lookup = build_p2sh_lookup([binascii.unhexlify(tx_ins[i][-1])])
        tx.sign_tx_in(hash160_lookup,
                      i,
                      tx.unspents[i].script,
                      hash_type=SIGHASH_ALL,
                      p2sh_lookup=p2sh_lookup)

    return tx.as_hex(), tx.id()
Exemplo n.º 13
0
    def test_confirm_input_raises(self):
        FEE = 10000

        # create a fake Spendable
        COIN_VALUE = 100000000
        spendables = [Spendable(COIN_VALUE, standard_tx_out_script(BITCOIN_ADDRESSES[0]), FAKE_HASHES[1], 0)]

        tx_1 = create_signed_tx(spendables, BITCOIN_ADDRESSES[1:2], wifs=WIFS[:1])
        spendables = tx_1.tx_outs_as_spendable()
        spendables[0].coin_value += 100

        tx_db = dict((tx.hash(), tx) for tx in [tx_1])
        tx_2 = create_signed_tx(spendables, BITCOIN_ADDRESSES[2:3], wifs=WIFS[:3])

        self.assertRaises(BadSpendableError, tx_2.validate_unspents, tx_db)
Exemplo n.º 14
0
    def test_p2sh_multisig_sequential_signing(self):
        raw_scripts = [
            h2b("52210234abcffd2e80ad01c2ec0276ad02682808169c6fafdd25ebfb60703df272b461"
                "2102e5baaafff8094e4d77ce8b009d5ebc3de9110085ebd3d96e50cc7ce70faf175221"
                "0316ee25e80eb6e6fc734d9c86fa580cbb9c4bfd94a19f0373a22353ececd4db6853ae"
                )
        ]
        spendable = {
            'script_hex':
            'a914c4ed4de526461e3efbb79c8b688a6f9282c0464687',
            'does_seem_spent':
            0,
            'block_index_spent':
            0,
            'coin_value':
            10000,
            'block_index_available':
            0,
            'tx_out_index':
            0,
            'tx_hash_hex':
            '0ca152ba6b88db87a7ef1afd24554102aca1ab86cf2c10ccbc374472145dc943'
        }

        key_1 = 'Kz6pytJCigYHeMsGLmfHQPJhN5og2wpeSVrU43xWwgHLCAvpsprh'
        key_2 = 'Kz7NHgX7MBySA3RSKj9GexUSN6NepEDoPNugSPr5absRDoKgn2dT'
        for ordered_keys in [(key_1, key_2), (key_2, key_1)]:
            txs_in = [
                TxIn(previous_hash=h2b(
                    '43c95d14724437bccc102ccf86aba1ac02415524fd1aefa787db886bba52a10c'
                ),
                     previous_index=0)
            ]
            txs_out = [
                TxOut(10000,
                      script_for_address('3KeGeLFmsbmbVdeMLrWp7WYKcA3tdsB4AR'))
            ]
            unspents = [Spendable.from_dict(spendable)]
            tx = Tx(version=DEFAULT_VERSION,
                    txs_in=txs_in,
                    txs_out=txs_out,
                    unspents=unspents)
            for key in ordered_keys:
                self.assertEqual(tx.bad_signature_count(), 1)
                p2sh_lookup = build_p2sh_lookup(raw_scripts)
                tx.sign(LazySecretExponentDB([key], {}, [secp256k1_generator]),
                        p2sh_lookup=p2sh_lookup)
            self.assertEqual(tx.bad_signature_count(), 0)
Exemplo n.º 15
0
 def spendables_for_address(self, bitcoin_address):
     """
     Return a list of Spendable objects for the
     given bitcoin address.
     """
     URL = "https://blockchain.info/unspent?active=%s" % bitcoin_address
     r = json.loads(urlopen(URL).read().decode("utf8"))
     spendables = []
     for u in r["unspent_outputs"]:
         coin_value = u["value"]
         script = h2b(u["script"])
         previous_hash = h2b(u["tx_hash"])
         previous_index = u["tx_output_n"]
         spendables.append(
             Spendable(coin_value, script, previous_hash, previous_index))
     return spendables
Exemplo n.º 16
0
    def createTransaction(self,
                          address,
                          amount,
                          keychain,
                          fee="standard",
                          confirms=0):
        unspents_result = yield self.unspents()
        spendables = []
        p2sh = []
        chain_paths = []
        # Strip leading /
        keychain_path = keychain['path'][1:]
        for unspent in unspents_result["unspents"]:
            if unspent["confirmations"] < confirms:
                continue
            p2sh.append(h2b(unspent["redeemScript"]))
            spendable = Spendable(unspent["value"], h2b(unspent["script"]),
                                  h2b_rev(unspent["tx_hash"]),
                                  unspent["tx_output_n"])
            spendables.append(spendable)
            chain_paths.append(keychain_path + unspent['chainPath'])
        p2sh_lookup = build_p2sh_lookup(p2sh)
        address_result = yield self.createAddress(1)
        change = address_result["address"]
        tx = tx_utils.create_tx(spendables, [(address, amount), change], fee)

        # address_keys = [BIP32Node.from_hwif(keychain["xprv"]).subkey_for_path("0/0/0/0"),
        #                 BIP32Node.from_hwif(keychain["xprv"]).subkey_for_path(address_result['path'])]

        spendable_keys = [
            BIP32Node.from_hwif(keychain["xprv"]).subkey_for_path(path)
            for path in chain_paths
        ]
        # all_keys = address_keys + spendable_keys

        hash160_lookup = build_hash160_lookup(
            [key.secret_exponent() for key in spendable_keys])

        pprint(tx)

        tx.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup)

        pprint(tx)

        returnValue({'tx': tx.as_hex(), 'fee': tx.fee()})
Exemplo n.º 17
0
 def spendables_for_address(self, address):
     """
     Return a list of Spendable objects for the
     given bitcoin address.
     """
     logging.debug('spendables_for_address %s', address)
     spendables = []
     url_append = "?unspentOnly=true&token=%s&includeScript=true" % self.api_token
     url = self.base_url + '/addrs/' + address + url_append
     result = json.loads(urlopen(url).read().decode("utf8"))
     for txn in result.get("txrefs", []):
         coin_value = txn.get("value")
         script = h2b(txn.get("script"))
         previous_hash = h2b_rev(txn.get("tx_hash"))
         previous_index = txn.get("tx_output_n")
         spendables.append(
             Spendable(coin_value, script, previous_hash, previous_index))
     return spendables
Exemplo n.º 18
0
    def spendables_for_address(self, address):
        """
        Converts to pycoin Spendable type
        :param address:
        :return: list of Spendables
        """
        unspent_outputs = bitcoin.rpc.Proxy().listunspent(addrs=[address])
        logging.debug('spendables_for_address %s', address)

        spendables = []
        for unspent in unspent_outputs:
            coin_value = unspent.get('amount', 0)
            outpoint = unspent.get('outpoint')
            script = unspent.get('scriptPubKey')
            previous_hash = outpoint.hash
            previous_index = outpoint.n
            spendables.append(Spendable(coin_value, script, previous_hash, previous_index))
        return spendables
Exemplo n.º 19
0
def tether_tx(tx_ins, private_key, send_amount, receiver):
    """
    simple usdt transaction
    here assume utxo comes from the sender and is used for mine fee
    bitcoin change will be sent back to sender address

    of course different address's utxo can be used for mine fee,
    but should be aware sender is determined by the first input in the tx
    bitcoin change can also be sent back to different address,
    but should be aware receiver is indicated by the last output address that is not the sender

    for full customization, use btc sample p2pkh_tx
    :param tx_ins: utxo from the sender
    :param private_key: private key of the same sender
    :param send_amount: (display amount) * (10 ** 8)
    :param receiver: address to receive usdt
    """
    _txs_in = []
    _un_spent = []
    total_bal = 0

    for tx_id, idx, balance, address in tx_ins:
        total_bal += balance

        # must h2b_rev NOT h2b
        tx_id_b = h2b_rev(tx_id)
        _txs_in.append(TxIn(tx_id_b, idx))

        _un_spent.append(Spendable(balance, standard_tx_out_script(address), tx_id_b, idx))

    txn_fee = estimate_p2pkh_tx_bytes(len(tx_ins), 3) * recommend_satoshi_per_byte()

    _txs_out = [TxOut(total_bal - txn_fee - 546, standard_tx_out_script(tx_ins[0][3])),
                TxOut(0, binascii.unhexlify(omni_tether_script(send_amount))),
                TxOut(546, standard_tx_out_script(receiver))]

    version, lock_time = 1, 0
    tx = Tx(version, _txs_in, _txs_out, lock_time)
    tx.set_unspents(_un_spent)

    solver = build_hash160_lookup([int(private_key, 16)] * len(tx_ins))
    signed_tx = tx.sign(solver, hash_type=SIGHASH_ALL)

    return signed_tx.as_hex(), signed_tx.id()
Exemplo n.º 20
0
 def spendables_for_address(self, address):
     """
     Return a list of Spendable objects for the
     given bitcoin address.
     """
     logging.info('trying to get spendables from blockcypher')
     spendables = []
     url_append = '?unspentOnly=true&includeScript=true'
     if self.api_token:
         url_append += '&token=' + self.api_token
     url = self.base_url + '/addrs/' + address + url_append
     response = requests.get(url)
     if int(response.status_code) == 200:
         for txn in response.json().get('txrefs', []):
             coin_value = txn.get('value')
             script = h2b(txn.get('script'))
             previous_hash = h2b_rev(txn.get('tx_hash'))
             previous_index = txn.get('tx_output_n')
             spendables.append(Spendable(coin_value, script, previous_hash, previous_index))
     return spendables
Exemplo n.º 21
0
	def _spendables (self, value):
		r = self._do_request ('listunspent')['result']
		random.shuffle (r)
		sps = []
		tot = 0
		for s in r:
				if s['address'] != self.address:
					continue

				txid = ''
				for x in range (len (s['txid']), -2, -2):
					txid += s['txid'][x:x+2]

				tot += int (float (s['amount']) * 100000000)
				sps.append (Spendable.from_dict ({'coin_value': int (float (s['amount']) * 100000000),
						'script_hex': s['scriptPubKey'], 'tx_hash_hex': txid, 'tx_out_index': int (s['vout'])}))

				if tot >= value:
					return sps

		return sps
Exemplo n.º 22
0
    def test_is_invalid(self):
        for (prevouts, tx_hex, flags) in txs_from_json(TX_INVALID_JSON):
            try:
                tx = Tx.from_hex(tx_hex)
                if not check_transaction(tx):
                    continue
                unspents = [
                    Spendable(coin_value=1000000,
                              script=compile_script(prevout[2]),
                              tx_hash=prevout[0],
                              tx_out_index=prevout[1]) for prevout in prevouts
                ]
                tx.set_unspents(unspents)

                bs = tx.bad_signature_count()
                self.assertEqual(bs, 0)
            except:
                continue

            self.fail("Invalid transaction: " + tx.id() +
                      " appears to be valid.")
Exemplo n.º 23
0
    def test_p2sh_multisig_sequential_signing(self):
        raw_scripts = [h2b(
            "52210234abcffd2e80ad01c2ec0276ad02682808169c6fafdd25ebfb60703df272b461"
            "2102e5baaafff8094e4d77ce8b009d5ebc3de9110085ebd3d96e50cc7ce70faf175221"
            "0316ee25e80eb6e6fc734d9c86fa580cbb9c4bfd94a19f0373a22353ececd4db6853ae")]
        txs_in = [TxIn(previous_hash=h2b('43c95d14724437bccc102ccf86aba1ac02415524fd1aefa787db886bba52a10c'),
                       previous_index=0)]
        txs_out = [TxOut(10000, standard_tx_out_script('3KeGeLFmsbmbVdeMLrWp7WYKcA3tdsB4AR'))]
        spendable = {'script_hex': 'a914c4ed4de526461e3efbb79c8b688a6f9282c0464687', 'does_seem_spent': 0,
                     'block_index_spent': 0, 'coin_value': 10000, 'block_index_available': 0, 'tx_out_index': 0,
                     'tx_hash_hex': '0ca152ba6b88db87a7ef1afd24554102aca1ab86cf2c10ccbc374472145dc943'}

        tx__prototype = Tx(version=DEFAULT_VERSION, txs_in=txs_in, txs_out=txs_out,
                           unspents=[Spendable.from_dict(spendable)])
        key_1 = 'Kz6pytJCigYHeMsGLmfHQPJhN5og2wpeSVrU43xWwgHLCAvpsprh'
        key_2 = 'Kz7NHgX7MBySA3RSKj9GexUSN6NepEDoPNugSPr5absRDoKgn2dT'
        for ordered_keys in [(key_1, key_2), (key_2, key_1)]:
            tx = copy.deepcopy(tx__prototype)
            for key in ordered_keys:
                self.assertEqual(tx.bad_signature_count(), 1)
                tx.sign(LazySecretExponentDB([key], {}), p2sh_lookup=build_p2sh_lookup(raw_scripts))
            self.assertEqual(tx.bad_signature_count(), 0)
Exemplo n.º 24
0
	def _spendables (self, value):
		code = self._chaincodeToChainSoName (self.chain)

		u = 'https://chain.so/api/v2/get_tx_unspent/'+code+'/'+self.address
		#print (u)

		while True:
			try:
				d = requests.get (u, headers={'content-type': 'application/json'}).json()
			except:
				time.sleep (5)
				continue
			

			sps = []
			tot = 0
			random.shuffle (d['data']['txs'])
			for s in d['data']['txs']:
				#if int (s['confirmations']) > 0:
				txid = s['txid'] #''
				#for x in range (len (s['txid']), -2, -2):
				#	txid += s['txid'][x:x+2]
	
				if (txid+':'+str (s['output_no'])) in self.lockedspendables:
					#print ('Locked spendable')
					continue

				tot += int (float (s['value']) * 100000000)
				sps.append (Spendable.from_dict ({'coin_value': int (float (s['value']) * 100000000),
					'script_hex': s['script_hex'], 'tx_hash_hex': txid, 'tx_out_index': int (s['output_no'])}))

				self.lockedspendables.append (txid+':'+str (s['output_no']))

				if tot >= value:
					#print (sps)
					return sps

			return sps
Exemplo n.º 25
0
    def test_is_valid(self):
        for (prevouts, tx_hex, flags) in txs_from_json(TX_VALID_JSON):
            try:
                tx = Tx.from_hex(tx_hex)
            except:
                self.fail("Cannot parse tx_hex: " + tx_hex)

            if not check_transaction(tx):
                self.fail("check_transaction(tx) = False for valid tx: " +
                          tx_hex)

            unspents = [
                Spendable(coin_value=1000000,
                          script=compile_script(prevout[2]),
                          tx_hash=prevout[0],
                          tx_out_index=prevout[1]) for prevout in prevouts
            ]
            tx.set_unspents(unspents)

            bs = tx.bad_signature_count()
            if bs > 0:
                msg = str(tx_hex) + " bad_signature_count() = " + str(bs)
                self.fail(msg)
Exemplo n.º 26
0
def spend_pkh_fund(tx_ins, in_keys, tx_outs):
    """
    p2pkh address send to p2pkh p2sh transaction
    :param tx_ins: list with tuple(tx_id, idx, balance, address)
    :param in_keys: list of private keys in hex format corresponding to each input
    :param tx_outs: balance, receiver_address
    :return: raw hex and tx id
    """
    _txs_in = []
    _un_spent = []
    for tx_id, idx, balance, address in tx_ins:
        # must h2b_rev NOT h2b
        tx_id_b = h2b_rev(tx_id)
        _txs_in.append(TxIn(tx_id_b, idx))

        _un_spent.append(
            Spendable(
                balance,
                script_obj_from_address(address, netcodes=[NET_CODE]).script(),
                tx_id_b, idx))

    _txs_out = []
    for balance, receiver_address in tx_outs:
        _txs_out.append(
            TxOut(
                balance,
                script_obj_from_address(receiver_address,
                                        netcodes=[NET_CODE]).script()))

    version, lock_time = 1, 0
    tx = Tx(version, _txs_in, _txs_out, lock_time)
    tx.set_unspents(_un_spent)

    solver = build_hash160_lookup([int(pri_hex, 16) for pri_hex in in_keys])
    tx.sign(solver, hash_type=SIGHASH_ALL)

    return tx.as_hex(), tx.id()
Exemplo n.º 27
0
def build_single_utxo_signed_bch_tx(args, wallet_key, destination_address,
                                    ga_address_pointer, redeem_script_hex,
                                    tx_hash_hex, utxo_index, incoming_satoshis,
                                    total_fee_satoshis):
    '''Builds and signs a single-output Bitcoin Cash (BCH) transaction for a single UTXO.

    This method prepares a transaction that sends all BCH from a single UTXO (unspent transaction output) held by a
    2of2 GreenAddress multisig wallet to a single destination address (minus fees). If you have multiple UTXOs in your
    GreenAddress wallet (e.g. from multiple deposits to the wallet) you'll need to run the method once for each UTXO
    and broadcast each resulting TX separately.

    Very briefly, a UTXO represents some BTC (or BCH) that is currently held by the wallet. The UTXO is defined by the
    hash of the transaction that created it (tx_hash_hex) and the index of the output in the list of outputs for that
    transaction (utxo_index). If you're not clear on what "outputs" or UTXOs are, please spend a couple minutes
    familiarizing yourself with Bitcoin/BCH transaction basics, https://bitcoin.org/en/developer-guide#transactions or
    other references below, before trying to manually craft these parameters. I've documented them below, but some
    broader context is going to be helpful.

    This method is primarily intended for helping recover BCH associated with BTC you had in your GreenAddress wallet at
    the time of the August 1, 2017 hard fork that created BCH, but should also be usable if you accidentally sent BCH
    (instead of BTC) to a GreenAddress address post-fork.

    This method currently does not support:
        * 2of3 wallets
        * GreenAddress subaccounts
    Support for either of these should be manageable to add, so please contact me if it would be useful for you.

    References:
        P2SH multisigs: https://bitcoin.org/en/developer-guide#multisig
        OP_CHECKMULTISIG details: https://bitcoin.org/en/developer-reference#term-op-checkmultisig
        Opcodes: https://en.bitcoin.it/wiki/Script#Opcodes
        Detailed multisig TX breakdown (great if you want to parse through your TX or signature script):
            http://www.soroushjp.com/2014/12/20/bitcoin-multisig-the-hard-way-understanding-raw-multisignature-bitcoin-transactions/
        Decode a transaction (does not break down the scripts): https://blockchain.info/decode-tx
        Glossary entries:
            https://bitcoin.org/en/developer-guide#transactions
            https://bitcoin.org/en/glossary/address
            https://bitcoin.org/en/glossary/signature-script
            https://bitcoin.org/en/glossary/pubkey-script
            https://bitcoin.org/en/glossary/public-key
            https://bitcoin.org/en/glossary/output
            https://bitcoin.org/en/glossary/unspent-transaction-output
        My pre-fork and post-fork transactions from which I'm pulling my examples:
            Pre:    https://btc.com/e65e67cef4078f0a44f46bd1740c21e3dc8577c90c71e49fea876cb7bf135b70
            Post:   https://btc.com/a922ab0a66e66afe2ddb3141d88f8304e79c134e0bce8178823658b88b0e2b7a

    Args:
        args: Command-line args.

        wallet_key (int):
            GreenAddress wallet key, as returned by bip32_key_from_seed in
            https://github.com/ElementsProject/libwally-core/blob/master/include/wally_bip32.h

        destination_address (string):
            Standard-format BCH address to which you want to send the recovered BCH.
            Example: 19JRdfanvKzU7d6KvKgGTYar6kzBDba6Jn (author's BCH address -- use your own)
            These are generally base58check-encoded hashes. See https://bitcoin.org/en/glossary/address

        ga_address_pointer (int):
            GreenAddress's internal pointer to the address used by the UTXO (not destination address). This number let's
            GreenAddress know which keys to use when signing the transaction. You can find this by looking at the output
            of calls to GreenAddress's addressbook.get_my_addresses API method, and finding the entry that matches your
            UTXO's address. Other recovery tools pull this from the 'prev_pointers' field in nlocktimes.zip.

            Example:
                In my case, GreenAddress returned the following record (among others) when I called get_my_addresses.
                ga_address: {u'pointer': 15, u'addr_type': u'p2sh', u'num_tx': 2, u'ad': u'3FQBSLAsFF4NMuiEVShMae7Uu9JcVSRQvA'}
                Since 3FQBSLAsFF4NMuiEVShMae7Uu9JcVSRQvA was the address holding my UTXO, I'd set ga_address_pointer = 15.

        redeem_script_hex (string):
            Hex string encoding of the full redeem script for the UTXO (unspent transaction) you're trying
            to spend. Since we're extracting from a 2of2 P2SH multisig wallet (GreenAddress default), this
            string should start with '52' (the OP_2 opcode that represents the first '2' in '2of2'), and end with
            '52ae' (the OP_2 opcode that represents the second '2' in '2of2' and the OP_CHECKMULTISIG opcode).
            The middle contains the two Pubkeys for which signatures are needed in order to spend the UTXO.
            The string should be roughly 142 hex characters long, but could potentially vary a bit if GreenAddress
            employs pubkeys of different lengths.

            The redeem script will form the tail of the input script in the final transaction, and will be exactly the
            same for the BCH transaction as for the BTC transaction. The rest of the signature script will differ, since
            the signatures depend on other pieces of the transaction as well.

            The redeem script for a UTXO is generally not public. There are roughly three ways to get it in our case:
                1)  Extract it from the Input Script used by a BTC transaction that spent your UTXO (BTC, not BCH. As
                    noted, it starts with '52' and ends with '52ae', and is probably just the last 142 hex characters
                    of the input script. If you use the advanced view on the blockchain.info viewer, this will be the
                    last long string under the relevant ScriptSig. See this example link, which matches up with the
                    example redeemscript hex given below.
                    https://blockchain.info/tx/e65e67cef4078f0a44f46bd1740c21e3dc8577c90c71e49fea876cb7bf135b70?show_adv=true
                2)  Extract it from the nlocktimes.zip generated when you initiated the transaction holding the UTXO.
                    For recovery, this would be your last pre-fork nlocktimes.zip, though if you already have it, you
                    may want to instead just use one of the recovery tools that depends on nlocktimes.zip, such as
                    https://github.com/dumpyourbcash/garecovery
                3)  Figure out which pointer GreenAddress is supposed to use next, and determine both public keys from
                    that. I haven't done this, but it shouldn't be necessary in any case. If the pre-fork BTC funds
                    have already been spent, you can do (1). If they haven't, you can do (2), since GreenAddress lets
                    you re-request the "latest" nlocktimes through the wallet.

            Example: 5221036a08f0f8a665da604b3b4e1330ac7172e1e5a9a3466c95fc79bb50fe39eba8a22103649737c9a453eb7efa99c106117614c90ca96211542fea013ae5fda8d913bbb252ae

        tx_hash_hex (string):
            Hex string encoding of the transaction hash for the transaction containing the UTXO you're trying to spend.
            Example: e65e67cef4078f0a44f46bd1740c21e3dc8577c90c71e49fea876cb7bf135b70

        utxo_index (int):
            Index (0-based) of the unspent transaction output in the list of outputs in the transaction you're trying to
            spend.

            Example: My pre-fork transaction had two outputs, in order:
                0: 24870700 satoshis to 12HdJmPZPNo6hyYa224aUPPw1j7fhruemZ (address of person I was paying)
                1: 18232197 satoshis to 3FQBSLAsFF4NMuiEVShMae7Uu9JcVSRQvA (new multisig address where GA put my balance)
            Since my leftovers address was second, I'd set utxo_index = 1. Had it been first, I'd set utxo_index = 0.

        incoming_satoshis (int):
            Number of satoshis (BCH * 10^8) you want to spend from the UTXO. This should generally be the full amount in
            the UTXO if it's less, you'll be implicitly giving all the leftovers to the miners as a fee.
            Example: 18232197 in my case (0.18 BCH)

        total_fee_satoshis (int):
            The total number of satoshis you want to pay to the miners as a fee. Divide total_fee_satoshis by size of
            transaction (~350 bytes) to get the fee in satoshis per byte.

            See current fees by looking at recent transactions or sites like https://bitcointicker.co/bccnetworkstats/,
            though beware the units may differ.

            I've set the default to 30000 (0.0003 BCH), which is unnecessarily high (~100 satoshis per byte), to be safe
            and to ensure the transaction get processed immediately, and because it's what I used.

    Returns:
        pycoin.tx.Tx: The fully signed transaction object.

    '''

    # The UTXO you want to spend.
    spendable = Spendable.from_dict({
        "coin_value": incoming_satoshis,
        "script_hex": redeem_script_hex,
        "tx_hash_hex": tx_hash_hex,
        "tx_out_index": utxo_index
    })

    tx = pycoin.tx.tx_utils.create_tx(spendables=[spendable],
                                      payables=[destination_address],
                                      fee=total_fee_satoshis)
    logging.info("raw unsigned tx: %s", tx.as_hex())

    # SIGNING

    # User Signature
    redeem_script = spendable.script

    # The sighash of the transaction, which is the thing that will be signed independently by the wallet and
    # GreenAddress (via their API call). The hash is independent of the TX input signature scripts, since those will
    # end up including the signatures themselves.
    tx_in_sighash = tx_segwit_hash(tx, 0, redeem_script, incoming_satoshis)

    # The user signature depends only on the private key (derived from the user's wallet mnemonic) and the sighash
    # (derived from the transaction).
    private_key = bip32_key_get_priv_key(
        bip32_key_from_parent_path(wallet_key, [1, ga_address_pointer],
                                   BIP32_FLAG_SKIP_HASH))
    user_signature = ec_sig_to_der(
        ec_sig_from_bytes(private_key, tx_in_sighash,
                          EC_FLAG_ECDSA)) + bytearray([
                              0x41,
                          ])

    # Updating the script at this point would not be necessary, except that the GreenAddress API method has expectations
    # for what the input script should look like when it signs the transaction (likely because it wants to be able to
    # return an updated version of the script, which we ignore anyway). The GreenAddress signature itself will not
    # depend on the script set here, only on the redeem script, which is passed to the API method separately.
    # If this isn't done, the API method will fail with 'Invalid signature placeholder'.
    tx.txs_in[0].script = inscript.prep_for_vault_sign_alt_tx(
        redeem_script, user_signature)

    # GreenAddress Signature
    twofactor = request_twofactor_if_needed(tx)
    vault_sign_inputs = [{
        "value": incoming_satoshis,
        "script": redeem_script_hex,
        "subaccount":
        None,  # This recovery tool currently does not support subaccounts.
        "pointer": ga_address_pointer,
    }]
    # GreenAddress needs the tx.as_hex so that it can compute the hash and return an updated input script along with
    # the signature, but we're only interested in the signature, since we're rebuilding the input script below anyway.
    ga_signatures = args.conn.call("vault.sign_alt_tx", tx.as_hex(), "bcash",
                                   vault_sign_inputs, twofactor)

    # Signature order matters, and is determined by the order of the pubkeys used when creating the redeem script, and
    # thus the hash that forms the pubkey script stored in the UTXO. Since we have the redeem script, we could check the
    # order that the pubkeys appear in the redeem script, and make sure the signatures (derived from the corresponding
    # private keys) appear in the same order. However, for now we're assuming that GreenAddress always puts their
    # signature first, which means it should appear first in the signatures list below.
    signatures = [hex_to_bytes(ga_signatures['signatures'][0]), user_signature]
    tx.txs_in[0].script = inscript.multisig(redeem_script, signatures)
    logging.warning("fully signed tx: " + tx.as_hex())

    return tx
Exemplo n.º 28
0
def searchSpendById(id):
    c = CoinSqlite3()._exec_sql(
        'Select * from TransactionInfoOut where id = ? ', id)
    tmp = c.fetchone()
    spend = Spendable(tmp[1], tmp[2], tmp[4], tmp[6])
    return spend
Exemplo n.º 29
0
    def send(self,
             wallet_id,
             passcode,
             address,
             amount,
             message='',
             fee=10000):
        """
        Send bitcoins to address

        :param wallet_id: bitgo wallet id
        :param address: bitcoin address
        :param amount: btc amount in satoshis
        :return: boolean
        """
        wallet = self.get_wallet(wallet_id)
        if not wallet['spendingAccount']:
            raise NotSpendableWallet()

        if not wallet['isActive']:
            raise NotActiveWallet()

        if amount < 10000:
            raise Exception('amount to small')

        if wallet['confirmedBalance'] < amount:
            raise NotEnoughFunds('Not enough funds: balance %s amount %s' %
                                 (wallet['confirmedBalance'], amount))

        change_address = self.create_address(wallet_id, chain=1)
        usableKeychain = False
        spendables = []
        chain_paths = []
        p2sh = []
        payables = [(address, amount)]
        keychain_path = ""

        for keychain in wallet['private']['keychains']:
            keychain_path = keychain['path'][1:]
            keychain = self.get_keychain(keychain['xpub'])
            if 'encryptedXprv' not in keychain:
                continue
            usableKeychain = True
            break

        if not usableKeychain:
            raise BitGoError("didn't found a spendable keychain")

        data = json.loads(keychain['encryptedXprv'])
        #add base64 paddings
        for k in ['iv', 'salt', 'ct']:
            data[k] = data[k] + "=="
        cipher = sjcl.SJCL()
        xprv = cipher.decrypt(data, passcode)

        unspents = self.get_unspents(wallet_id)
        total_value = 0
        for d in unspents['unspents'][::-1]:
            path = keychain_path + d['chainPath']
            chain_paths.append(path)
            p2sh.append(h2b(d["redeemScript"]))
            spendables.append(
                Spendable(d["value"], h2b(d["script"]), h2b_rev(d["tx_hash"]),
                          d["tx_output_n"]))

            total_value += d['value']
            if total_value > amount:
                break

        if total_value > (amount + fee):
            #add a change address
            #TODO: create address
            payables.append(change_address)

        p2sh_lookup = build_p2sh_lookup(p2sh)

        spendable_keys = []

        priv_key = BIP32Node.from_hwif(xprv)

        spendable_keys = [
            priv_key.subkey_for_path(path) for path in chain_paths
        ]

        hash160_lookup = build_hash160_lookup(
            [key.secret_exponent() for key in spendable_keys])

        tx = create_tx(spendables, payables)

        tx.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup)

        r = requests.post(self.url + '/tx/send', {
            'tx': tx.as_hex(),
            'message': message
        },
                          headers={
                              'Authorization': 'Bearer %s' % self.access_token,
                          })

        return r.json()
Exemplo n.º 30
0
def test_spendable(spendable_small_hex_small_vout):
    spendable = Spendable.from_tx_out(TxOut(0, b"\x00"), b"\x00", 0)
    assert isinstance(spendable, Spendable)
    assert spendable.tx_hash == b"\x00"
    assert spendable.tx_out_index == 0
Exemplo n.º 31
0
def spendable_small_hex_large_vout(txout_small_coin_large_script):
    return Spendable.from_tx_out(txout_small_coin_large_script, b"\x00", 10)
Exemplo n.º 32
0
def spendable_large_hex_large_vout(txout_large_coin_large_script):
    return Spendable.from_tx_out(txout_large_coin_large_script, b"\xFF", 10)