示例#1
0
 def test_issue_225(self):
     script = tools.compile("OP_RETURN 'foobar'")
     tx_out = TxOut(1, script)
     address = tx_out.bitcoin_address(netcode="XTN")
     self.assertEqual(address, "(nulldata 666f6f626172)")
     address = tx_out.bitcoin_address(netcode="BTC")
     self.assertEqual(address, "(nulldata 666f6f626172)")
示例#2
0
def make_bare_tx(candidate, change_address, rs_asm, version=1):

    # <Tx> components
    spendables = []
    ins = []
    outs = []

    # estimate the final (signed) bytesize per input based on the redeemscript
    redeem_script = tools.compile(rs_asm)
    in_size = estimate_input_size(redeem_script)

    # initialize size and amount counters
    in_amount = Decimal(0)
    est_size = TX_COMPONENTS.version + TX_COMPONENTS.out_count + TX_COMPONENTS.in_count

    # add output size
    est_size += OUTSIZE * 2

    # iterate over unspents
    for utxo in candidate.utxos:

        value = Decimal(utxo.amount) * COIN
        in_amount += value

        script = h2b(utxo.script)
        # for now: test if the in_script we figured we would need, actually matches the in script :D

        # reverse that tx hash
        prevtx = h2b_rev(utxo.hash)

        # output index
        outnum = utxo.outpoint

        # create "spendable"
        spdbl = Spendable(value, script, prevtx, outnum)
        spendables.append(spdbl)

        # also create this as input
        as_input = spdbl.tx_in()
        as_input.sigs = []
        ins.append(as_input)

        # add the estimated size per input
        est_size += in_size

    # calc fee and out amount
    fee = (Decimal(math.ceil(est_size / 1000)) * COIN *
           NETWORK_FEE) + FEE_MARGIN
    change_amount = Decimal(
        math.floor(in_amount - (candidate.amount * COIN) - fee))

    # create outputs
    outs.append(
        TxOut(int(candidate.amount * COIN), make_payto(candidate.address)))
    outs.append(TxOut(int(change_amount), make_payto_script(change_address)))

    # create bare tx without sigs
    tx = Tx(version, ins, outs, 0, spendables)

    return tx
示例#3
0
    def post(self):
        logging.info("transaction coming in")
        hextx = self.get_argument('hextx', None)
        subkeys = self.get_argument('subkeys', None)
        payoutaddress = self.get_argument('payoutaddress', None)
        fees = self.get_argument('fees', None)

        print subkeys

        if not hextx or not subkeys or not payoutaddress or not fees:
            logging.error("Did not receive trans or tree argument")
            return

        fees = tornado.escape.json_decode(fees)
        subkeys = tornado.escape.json_decode(subkeys)
        seed = mnemonic.Mnemonic.to_seed(PHRASE)
        wallet = BIP32Node.from_master_secret(seed)

        wifs = []
        keys = []
        for subkey in subkeys:
            key = wallet.subkey_for_path(subkey)
            keys.append(key)
            wifs.append(key.wif())

        underlying_script = ScriptMultisig(
            n=N, sec_keys=[key.sec() for key in keys[:M]]).script()
        address = address_for_pay_to_script(underlying_script)

        tx2 = Tx.tx_from_hex(hextx)

        # first tx out, need another for the 1% to our wallet
        script = standard_tx_out_script(payoutaddress)
        tx_out = TxOut(fees['seller'], script)
        # TODO: figure out final wallet. This is sending to my phone
        script = standard_tx_out_script("1LhkvTTxFXam672vjwbABtkp9td7dxCwyB")
        tx2_out = TxOut(fees['bestcrow'], script)

        txs_out = [tx_out, tx2_out]
        tx2.txs_out = txs_out

        hash160_lookup = build_hash160_lookup(key.secret_exponent()
                                              for key in keys)
        p2sh_lookup = build_p2sh_lookup([underlying_script])
        tx2.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup)

        print tx2.as_hex()
        self.write(tx2.as_hex())
def sign_tx(certificate_metadata, last_input, allowable_wif_prefixes=None):
    """sign the transaction with private key"""
    with open(certificate_metadata.unsigned_tx_file_name, 'rb') as in_file:
        hextx = str(in_file.read(), 'utf-8')

        logging.info('Signing tx with private key for recipient id: %s ...',
                     certificate_metadata.uid)

        tx = Tx.from_hex(hextx)
        if allowable_wif_prefixes:
            wif = wif_to_secret_exponent(helpers.import_key(),
                                         allowable_wif_prefixes)
        else:
            wif = wif_to_secret_exponent(helpers.import_key())

        lookup = build_hash160_lookup([wif])

        tx.set_unspents([
            TxOut(coin_value=last_input.amount,
                  script=last_input.script_pub_key)
        ])

        signed_tx = tx.sign(lookup)
        signed_hextx = signed_tx.as_hex()
        with open(certificate_metadata.unsent_tx_file_name, 'wb') as out_file:
            out_file.write(bytes(signed_hextx, 'utf-8'))

    logging.info('Finished signing transaction for certificate uid=%s',
                 certificate_metadata.uid)
示例#5
0
    def create_raw_transaction(self, escrow, fees):
        logging.info('starting raw transaction to payout address %s' %
                     escrow['sellerpayoutaddress'])

        # convenience method provided by pycoin to get spendables from insight server
        insight = InsightService(INSIGHT)
        spendables = insight.spendables_for_address(escrow['multisigaddress'])

        # create the tx_in
        txs_in = []
        for s in spendables:
            txs_in.append(s.tx_in())

        script = standard_tx_out_script(escrow['multisigaddress'])

        tx_out = TxOut(fees['seller'], script)
        txs_out = [tx_out]

        tx1 = Tx(version=1, txs_in=txs_in, txs_out=txs_out)
        tx1.set_unspents(txs_out)

        # this will be the hex of the tx we're going to send in the POST request
        hex_tx = tx1.as_hex(include_unspents=True)

        return hex_tx
示例#6
0
def sign_tx(hextx, tx_input, allowable_wif_prefixes=None):
    """
    Sign the transaction with private key
    :param hextx:
    :param tx_input:
    :param allowable_wif_prefixes:
    :return:
    """

    logging.info('Signing tx with private key')

    tx = Tx.from_hex(hextx)
    if allowable_wif_prefixes:
        wif = wif_to_secret_exponent(
            helpers.import_key(), allowable_wif_prefixes)
    else:
        wif = wif_to_secret_exponent(helpers.import_key())

    lookup = build_hash160_lookup([wif])

    tx.set_unspents(
        [TxOut(coin_value=tx_input.amount, script=tx_input.script_pub_key)])

    signed_tx = tx.sign(lookup)
    signed_hextx = signed_tx.as_hex()

    logging.info('Finished signing transaction')
    return signed_hextx
示例#7
0
def tx_from_json_dict(r):
    version = r.get("version")
    lock_time = r.get("locktime")
    txs_in = []
    for vin in r.get("vin"):
        if "coinbase" in vin:
            previous_hash = b'\0' * 32
            script = h2b(vin.get("coinbase"))
            previous_index = 4294967295
        else:
            previous_hash = h2b_rev(vin.get("txid"))
            scriptSig = vin.get("scriptSig")
            if "hex" in scriptSig:
                script = h2b(scriptSig.get("hex"))
            else:
                script = tools.compile(scriptSig.get("asm"))
            previous_index = vin.get("vout")
        sequence = vin.get("sequence")
        txs_in.append(TxIn(previous_hash, previous_index, script, sequence))
    txs_out = []
    for vout in r.get("vout"):
        coin_value = btc_to_satoshi(decimal.Decimal(vout.get("value")))
        script = tools.compile(vout.get("scriptPubKey").get("asm"))
        txs_out.append(TxOut(coin_value, script))
    tx = Tx(version, txs_in, txs_out, lock_time)
    bh = r.get("blockhash")
    if bh:
        bh = h2b_rev(bh)
    tx.confirmation_block_hash = bh
    return tx
示例#8
0
 def test_multisig_one_at_a_time(self):
     N = 3
     M = 3
     keys = [Key(secret_exponent=i) for i in range(1, M + 2)]
     tx_in = TxIn.coinbase_tx_in(script=b'')
     script = ScriptMultisig(n=N, sec_keys=[key.sec()
                                            for key in keys[:M]]).script()
     tx_out = TxOut(1000000, script)
     tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out])
     tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(),
                              [keys[-1].address()])
     ids = [
         "403e5bfc59e097bb197bf77a692d158dd3a4f7affb4a1fa41072dafe7bec7058",
         "5931d9995e83721243dca24772d7012afcd4378996a8b953c458175f15a544db",
         "9bb4421088190bbbb5b42a9eaa9baed7ec7574a407c25f71992ba56ca43d9c44",
         "03a1dc2a63f93a5cf5a7cb668658eb3fc2eda88c06dc287b85ba3e6aff751771"
     ]
     for i in range(1, M + 1):
         self.assertEqual(tx2.bad_signature_count(), 1)
         self.assertEqual(tx2.id(), ids[i - 1])
         hash160_lookup = build_hash160_lookup(key.secret_exponent()
                                               for key in keys[i - 1:i])
         tx2.sign(hash160_lookup=hash160_lookup)
         self.assertEqual(tx2.id(), ids[i])
     self.assertEqual(tx2.bad_signature_count(), 0)
示例#9
0
 def check_bip143_tx(self, tx_u_hex, tx_s_hex, txs_out_value_scripthex_pair,
                     tx_in_count, tx_out_count, version, lock_time):
     tx_u = Tx.from_hex(tx_u_hex)
     tx_s = Tx.from_hex(tx_s_hex)
     txs_out = [
         TxOut(int(coin_value * 1e8), h2b(script_hex))
         for coin_value, script_hex in txs_out_value_scripthex_pair
     ]
     for tx in (tx_u, tx_s):
         self.assertEqual(len(tx.txs_in), tx_in_count)
         self.assertEqual(len(tx.txs_out), tx_out_count)
         self.assertEqual(tx.version, version)
         self.assertEqual(tx.lock_time, lock_time)
         tx.set_unspents(txs_out)
     self.check_unsigned(tx_u)
     self.check_signed(tx_s)
     tx_hex = tx_u.as_hex()
     self.assertEqual(tx_hex, tx_u_hex)
     tx_hex = tx_s.as_hex()
     self.assertEqual(tx_hex, tx_s_hex)
     tx_u_prime = self.unsigned_copy(tx_s)
     tx_hex = tx_u_prime.as_hex()
     self.assertEqual(tx_hex, tx_u_hex)
     self.assertEqual(b2h_rev(double_sha256(h2b(tx_s_hex))), tx_s.w_id())
     self.assertEqual(b2h_rev(double_sha256(h2b(tx_u_hex))), tx_u.w_id())
     self.assertEqual(b2h_rev(double_sha256(h2b(tx_u_hex))), tx_u.id())
     return tx_u, tx_s
示例#10
0
def build_spending_tx(script_in_bin, credit_tx):
    txs_in = [TxIn(credit_tx.hash(), 0, script_in_bin, sequence=4294967295)]
    txs_out = [TxOut(credit_tx.txs_out[0].coin_value, b'')]
    spend_tx = Tx(1,
                  txs_in,
                  txs_out,
                  unspents=credit_tx.tx_outs_as_spendable())
    return spend_tx
示例#11
0
def prepare_tx_for_signing(hex_tx, tx_inputs):
    logging.info('Preparing tx for signing')
    transaction = Tx.from_hex(hex_tx)
    unspents = [
        TxOut(coin_value=tx_input.coin_value, script=tx_input.script)
        for tx_input in tx_inputs
    ]
    transaction.set_unspents(unspents)
    return transaction
示例#12
0
 def test_nulldata(self):
     # note that because chr() is used samples with length > 255 will not work
     for sample in [b'test', b'me', b'a', b'39qEwuwyb2cAX38MFtrNzvq3KV9hSNov3q']:
         sample_script = b'\x6a' + chr(len(sample)).encode() + sample
         nd = ScriptNulldata(sample)
         self.assertEqual(nd.nulldata, sample)
         self.assertEqual(nd.script(), sample_script)
         nd2 = ScriptNulldata.from_script(sample_script)
         self.assertEqual(nd.nulldata, nd2.nulldata)
         out = TxOut(1, nd.script())
         tx = Tx(0, [], [out])  # ensure we can create a tx
         self.assertEqual(nd.script(), tools.compile(tools.disassemble(nd.script())))  # convert between asm and back to ensure no bugs with compilation
示例#13
0
 def multisig_M_of_N(self, M, N, unsigned_id, signed_id):
     keys = [Key(secret_exponent=i) for i in range(1, N+2)]
     tx_in = TxIn.coinbase_tx_in(script=b'')
     script = ScriptMultisig(m=M, sec_keys=[key.sec() for key in keys[:N]]).script()
     tx_out = TxOut(1000000, script)
     tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out])
     tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()])
     self.assertEqual(tx2.id(), unsigned_id)
     self.assertEqual(tx2.bad_signature_count(), 1)
     hash160_lookup = build_hash160_lookup(key.secret_exponent() for key in keys)
     tx2.sign(hash160_lookup=hash160_lookup)
     self.assertEqual(tx2.id(), signed_id)
     self.assertEqual(tx2.bad_signature_count(), 0)
示例#14
0
 def multisig_M_of_N_individually(self, M, N):
     keys = [Key(secret_exponent=i) for i in range(1, N + 2)]
     tx_in = TxIn.coinbase_tx_in(script=b'')
     script = ScriptMultisig(n=M, sec_keys=[key.sec()
                                            for key in keys[:N]]).script()
     tx_out = TxOut(1000000, script)
     tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out])
     for partial_key_list in itertools.permutations(keys[:N], M):
         tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(),
                                  [keys[-1].address()])
         for key in partial_key_list:
             self.assertEqual(tx2.bad_signature_count(), 1)
             hash160_lookup = build_hash160_lookup([key.secret_exponent()])
             tx2.sign(hash160_lookup=hash160_lookup)
         self.assertEqual(tx2.bad_signature_count(), 0)
示例#15
0
def main():
    if len(sys.argv) != 2:
        print("usage: %s address" % sys.argv[0])
        sys.exit(-1)

    # validate the address
    address = sys.argv[1]
    assert is_address_valid(address)

    print("creating coinbase transaction to %s" % address)

    tx_in = TxIn.coinbase_tx_in(script=b'')
    tx_out = TxOut(50 * 1e8, standard_tx_out_script(address))
    tx = Tx(1, [tx_in], [tx_out])
    print("Here is the tx as hex:\n%s" % tx.as_hex())
示例#16
0
def sign_tx(hex_tx, tx_input):
    """
    Sign the transaction with private key
    :param hex_tx:
    :param tx_input:
    :return:
    """
    logging.info('Signing tx with private key')
    transaction = Tx.from_hex(hex_tx)
    wif = wif_to_secret_exponent(helpers.import_key(), ALLOWABLE_WIF_PREFIXES)
    lookup = build_hash160_lookup([wif])
    transaction.set_unspents([TxOut(coin_value=tx_input.coin_value, script=tx_input.script)])
    signed_tx = transaction.sign(lookup)
    logging.info('Finished signing transaction')
    return signed_tx
示例#17
0
 def test_sign_pay_to_script_multisig(self):
     M, N = 3, 3
     keys = [Key(secret_exponent=i) for i in range(1, N+2)]
     tx_in = TxIn.coinbase_tx_in(script=b'')
     underlying_script = ScriptMultisig(m=M, sec_keys=[key.sec() for key in keys[:N]]).script()
     address = address_for_pay_to_script(underlying_script)
     self.assertEqual(address, "39qEwuwyb2cAX38MFtrNzvq3KV9hSNov3q")
     script = standard_tx_out_script(address)
     tx_out = TxOut(1000000, script)
     tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out])
     tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [address])
     hash160_lookup = build_hash160_lookup(key.secret_exponent() for key in keys[:N])
     p2sh_lookup = build_p2sh_lookup([underlying_script])
     tx2.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup)
     self.assertEqual(tx2.bad_signature_count(), 0)
示例#18
0
 def test_p2sh_multisig_sequential_signing(self):
     raw_scripts = [h2b('52210234abcffd2e80ad01c2ec0276ad02682808169c6fafdd25ebfb60703df272b4612102e5baaafff8094e4d77ce8b009d5ebc3de9110085ebd3d96e50cc7ce70faf1752210316ee25e80eb6e6fc734d9c86fa580cbb9c4bfd94a19f0373a22353ececd4db6853ae')]
     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, 'tx_hash_hex': '0ca152ba6b88db87a7ef1afd24554102aca1ab86cf2c10ccbc374472145dc943',
                  'coin_value': 10000, 'block_index_available': 0, 'tx_out_index': 0}
     tx__prototype = Tx(version=DEFAULT_VERSION, txs_in=txs_in, txs_out=txs_out, unspents=[Spendable.from_dict(spendable)])
     key_1, key_2 = 'Kz6pytJCigYHeMsGLmfHQPJhN5og2wpeSVrU43xWwgHLCAvpsprh', '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)
示例#19
0
    def tx(self, payables, change_address=None):
        """
        Construct a transaction with available spendables
        :param list[(str, int)] payables: tuple of address and amount
        :return Tx or None: the transaction or None if not enough balance
        """
        all_spendables = self.spendables()

        send_amount = 0
        for address, coin_value in payables:
            send_amount += coin_value

        txs_out = []
        for address, coin_value in payables:
            script = standard_tx_out_script(address)
            txs_out.append(TxOut(coin_value, script))

        total = 0
        txs_in = []
        spendables = []
        while total < send_amount and all_spendables:
            spend = all_spendables.pop(0)
            self.add_spend(spend, spendables, txs_in)
            total += spend.coin_value

        tx_for_fee = Tx(txs_in=txs_in, txs_out=txs_out, version=DEFAULT_VERSION, unspents=spendables)
        fee = recommended_fee_for_tx(tx_for_fee)

        while total < send_amount + fee and all_spendables:
            spend = all_spendables.pop(0)
            self.add_spend(spend, spendables, txs_in)
            total += spend.coin_value

        if total > send_amount + fee + DUST:
            addr = change_address or self.current_change_address()
            script = standard_tx_out_script(addr)
            txs_out.append(AccountTxOut(total - send_amount - fee, script, self.path_for_check(addr)))
        elif total < send_amount + fee:
            raise InsufficientBalanceException(total)

        # check total >= amount + fee
        tx = AccountTx(version=DEFAULT_VERSION, txs_in=txs_in, txs_out=txs_out, unspents=spendables)
        return tx
示例#20
0
 def test_sign_bitcoind_partially_signed_2_of_2(self):
     # Finish signing a 2 of 2 transaction, that already has one signature signed by bitcoind
     # This tx can be found on testnet3 blockchain, txid: 9618820d7037d2f32db798c92665231cd4599326f5bd99cb59d0b723be2a13a2
     raw_script = "522103e33b41f5ed67a77d4c4c54b3e946bd30d15b8f66e42cb29fde059c16885116552102b92cb20a9fb1eb9656a74eeb7387636cf64cdf502ff50511830328c1b479986452ae"
     p2sh_lookup = build_p2sh_lookup([h2b(raw_script)])
     partially_signed_raw_tx = "010000000196238f11a5fd3ceef4efd5a186a7e6b9217d900418e72aca917cd6a6e634e74100000000910047304402201b41b471d9dd93cf97eed7cfc39a5767a546f6bfbf3e0c91ff9ad23ab9770f1f02205ce565666271d055be1f25a7e52e34cbf659f6c70770ff59bd783a6fcd1be3dd0147522103e33b41f5ed67a77d4c4c54b3e946bd30d15b8f66e42cb29fde059c16885116552102b92cb20a9fb1eb9656a74eeb7387636cf64cdf502ff50511830328c1b479986452aeffffffff01a0bb0d00000000001976a9143b3beefd6f7802fa8706983a76a51467bfa36f8b88ac00000000"
     tx = Tx.from_hex(partially_signed_raw_tx)
     tx_out = TxOut(1000000,
                    h2b("a914a10dfa21ee8c33b028b92562f6fe04e60563d3c087"))
     tx.set_unspents([tx_out])
     key = Key.from_text(
         "cThRBRu2jAeshWL3sH3qbqdq9f4jDiDbd1SVz4qjTZD2xL1pdbsx")
     hash160_lookup = build_hash160_lookup([key.secret_exponent()])
     self.assertEqual(tx.bad_signature_count(), 1)
     tx.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup)
     self.assertEqual(tx.bad_signature_count(), 0)
     self.assertEqual(
         tx.id(),
         "9618820d7037d2f32db798c92665231cd4599326f5bd99cb59d0b723be2a13a2")
示例#21
0
def json_to_tx(json_text):
    # transactions with non-standard lock time are not decoded properly
    # for example, d1ef46055a84fd02ee82580d691064780def18614d98646371c3448ca20019ac
    # there is no way to fix this until biteasy add a lock_time field to their output
    d = json.loads(json_text).get("data")
    txs_in = []
    for d1 in d.get("inputs"):
        previous_hash = h2b_rev(d1.get("outpoint_hash"))
        previous_index = d1.get("outpoint_index")
        script = h2b(d1.get("script_sig"))
        sequence = 4294967295 # BRAIN DAMAGE
        txs_in.append(TxIn(previous_hash, previous_index, script, sequence))
    txs_out = []
    for d1 in d.get("outputs"):
        coin_value = d1.get("value")
        script = h2b(d1.get("script_pub_key"))
        txs_out.append(TxOut(coin_value, script))
    version = d.get("version")
    lock_time = 0 # BRAIN DAMAGE
    return Tx(version, txs_in, txs_out, lock_time)
示例#22
0
 def parse_with_paths(class_, f, input_chain_paths, output_chain_paths):
     """Parse a Bitcoin transaction AccountTx from the file-like object f, attaching relevant chain paths."""
     version, count = parse_struct("LI", f)
     txs_in = []
     for i in range(count):
         txin = AccountTxIn.parse(f)
         txin.path = input_chain_paths[i]
         txs_in.append(txin)
     count, = parse_struct("I", f)
     txs_out = []
     for i in range(count):
         path = output_chain_paths[i]
         if path:
             txout = AccountTxOut.parse(f)
             txout.path = path
         else:
             txout = TxOut.parse(f)
         txs_out.append(txout)
     lock_time, = parse_struct("L", f)
     return class_(version, txs_in, txs_out, lock_time)
示例#23
0
 def parse_with_paths(class_, f, input_chain_paths, output_chain_paths):
     """Parse a Bitcoin transaction AccountTx from the file-like object f, attaching relevant chain paths."""
     version, count = parse_struct("LI", f)
     txs_in = []
     for i in range(count):
         txin = AccountTxIn.parse(f)
         txin.path = input_chain_paths[i]
         txs_in.append(txin)
     count, = parse_struct("I", f)
     txs_out = []
     for i in range(count):
         path = output_chain_paths[i]
         if path:
             txout = AccountTxOut.parse(f)
             txout.path = path
         else:
             txout = TxOut.parse(f)
         txs_out.append(txout)
     lock_time, = parse_struct("L", f)
     return class_(version, txs_in, txs_out, lock_time)
示例#24
0
def get_unsigned_tx(parser):
    args = parser.parse_args()
    # if there is only one item passed, it's assumed to be hex
    if len(args.txinfo) == 1:
        try:
            s = io.BytesIO(binascii.unhexlify(args.txinfo[0].decode("utf8")))
            return UnsignedTx.parse(s)
        except Exception:
            parser.error("can't parse %s as hex\n" % args.txinfo[0])

    coins_from = []
    coins_to = []
    for txinfo in args.txinfo:
        if '/' in txinfo:
            parts = txinfo.split("/")
            if len(parts) == 2:
                # we assume it's an output
                address, amount = parts
                amount = btc_to_satoshi(amount)
                coins_to.append((amount, address))
            else:
                try:
                    # we assume it's an input of the form
                    #  tx_hash_hex/tx_output_index_decimal/tx_out_val/tx_out_script_hex
                    tx_hash_hex, tx_output_index_decimal, tx_out_val, tx_out_script_hex = parts
                    tx_hash = binascii.unhexlify(tx_hash_hex)
                    tx_output_index = int(tx_output_index_decimal)
                    tx_out_val = btc_to_satoshi(decimal.Decimal(tx_out_val))
                    tx_out_script = binascii.unhexlify(tx_out_script_hex)
                    tx_out = TxOut(tx_out_val, tx_out_script)
                    coins_source = (tx_hash, tx_output_index, tx_out)
                    coins_from.append(coins_source)
                except Exception:
                    parser.error("can't parse %s\n" % txinfo)
        else:
            print("looking up funds for %s from blockchain.info" % txinfo)
            coins_sources = blockchain_info.unspent_tx_outs_info_for_address(txinfo)
            coins_from.extend(coins_sources)

    unsigned_tx = UnsignedTx.standard_tx(coins_from, coins_to)
    return unsigned_tx
示例#25
0
def construct_data_tx(data, _from, unused_utxo):

    coins_from = spendables_for_address(_from, unused_utxo)  #Ahora

    if len(coins_from) < 1:
        ErrorNotification.new('No bitcoins available to spend')
        return 'No bitcoins available to spend'

    txs_in = [
        TxIn(coins_from[0].tx_hash, coins_from[0].tx_out_index,
             coins_from[0].script)
    ]
    script_text = 'OP_RETURN %s' % data.encode('hex')

    script_bin = tools.compile(script_text)

    new_txs_out = [TxOut(0, script_bin)]
    version = 1
    lock_time = 0
    unsigned_tx = Tx(version, txs_in, new_txs_out, lock_time, coins_from)

    return unsigned_tx
示例#26
0
    def sign_tx(self, hex_tx, tx_input, netcode):
        """
        Sign the transaction with private key
        :param hex_tx:
        :param tx_input:
        :param netcode:
        :return:
        """
        logging.info('Signing tx with private key')

        self.secret_manager.start()
        wif = self.secret_manager.get_wif()

        transaction = Tx.from_hex(hex_tx)
        allowable_wif_prefixes = wif_prefix_for_netcode(netcode)

        se = wif_to_secret_exponent(wif, allowable_wif_prefixes)
        lookup = build_hash160_lookup([se])
        transaction.set_unspents([TxOut(coin_value=tx_input.coin_value, script=tx_input.script)])
        signed_tx = transaction.sign(lookup)
        self.secret_manager.stop()
        logging.info('Finished signing transaction')
        return signed_tx
示例#27
0
def construct_data_tx(data, _from):
    # inputs
    coins_from = blockchain_info.coin_sources_for_address(_from)
    if len(coins_from) < 1:
        return "No free outputs to spend"
    max_coin_value, _, max_idx, max_h, max_script = max(
        (tx_out.coin_value, random(), idx, h, tx_out.script)
        for h, idx, tx_out in coins_from)
    unsigned_txs_out = [
        UnsignedTxOut(max_h, max_idx, max_coin_value, max_script)
    ]

    # outputs
    if max_coin_value > TX_FEES * 2:
        return 'max output greater than twice the threshold, too big.'
    if max_coin_value < TX_FEES:
        return 'max output smaller than threshold, too small.'
    script_text = 'OP_RETURN %s' % data.encode('hex')
    script_bin = tools.compile(script_text)
    new_txs_out = [TxOut(0, script_bin)]
    version = 1
    lock_time = 0
    unsigned_tx = UnsignedTx(version, unsigned_txs_out, new_txs_out, lock_time)
    return unsigned_tx
示例#28
0
文件: sweep.py 项目: bizcoine/mop-py
def make_bare_tx(network, from_address, to_address, redeem_script, version=1):

    # <Tx> components
    spendables = []
    ins = []
    outs = []

    # estimate the final (signed) bytesize per input based on the redeemscript
    in_size = estimate_input_size(redeem_script)

    # initialize size and amount counters
    in_amount = Decimal(0)
    est_size = TX_COMPONENTS.version + TX_COMPONENTS.out_count + TX_COMPONENTS.in_count

    # add output size (we"ll only have 1)
    est_size += TX_COMPONENTS.out_scriptlen + TX_COMPONENTS.out_scriptsize + TX_COMPONENTS.out_scriptlen

    unspent_response = sochain_get_unspents(network, from_address)

    unspents = unspent_response.get("txs", [])

    # iterate over unspents
    for tx in unspents:

        value = Decimal(tx.get("value")) * Decimal(1e8)
        in_amount += value

        script = h2b(tx.get("script_hex"))
        # for now: test if the in_script we figured we would need, actually matches the in script :D

        # reverse that tx hash
        txhex = tx.get("txid")
        prevtx = h2b_rev(txhex)

        # output index
        outnum = tx.get("output_no")

        # create "spendable"
        spdbl = Spendable(value, script, prevtx, outnum)
        spendables.append(spdbl)

        # also create this as input
        as_input = spdbl.tx_in()
        as_input.sigs = []
        ins.append(as_input)

        # add the estimated size per input
        est_size += in_size

    # calc fee and out amount
    fee = Decimal(math.ceil(
        est_size / 1000.0)) * Decimal(1e8) * NETWORK_FEES.get(network)
    out_amount = in_amount - fee

    if (is_p2sh(to_address)):
        outscript = make_payto_script(to_address)
    else:
        outscript = make_payto_address(to_address)

    # create output
    outs.append(TxOut(out_amount, outscript))

    # create bare tx without sigs
    tx = Tx(version, ins, outs, 0, spendables)

    return tx
示例#29
0
underlying_script = ScriptMultisig(n=N, sec_keys=[key.sec() for key in keys[:M]]).script()
# I hash the script and transform it into a p2sh address
address = address_for_pay_to_script(underlying_script)
print(address)
# Filling up the new created address with the fake coinbase transaction. No signature rquired.
# Very important part. When you move funds to a p2sh address you write a special scriptPubKey:
# Instead of: OP_DUP OP_HASH160 <PubkeyHash> OP_EQUALVERIFY OP_CHECKSIG
# your p2sh scriptPubKey will be:
# OP_HASH160 <hash(redeemScript)> OP_EQUAL
# standard_tx_out_script(address) gives the scriptPubKey for a given multisig address
script = standard_tx_out_script(address)
# Fake coinbase transaction to fill our p2sh address
# It it is a coinbase transaction we put in a newly constructed block.
tx_in = TxIn.coinbase_tx_in(script=b'')
print("TxIn: %s" %  tx_in.__str__())
tx_out = TxOut(1000000, script)
print("TxOut: %s" %  tx_out.__str__())
tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out])
tx1.as_hex()
# we now have an UTXO redeemable by supplying the script and the required sigs.
# tx_utils.create_tx() allows to spend all the UTXO from the preavious tx to an arbitrary address.
tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [keys[-1].address()])
# to split the input in each of the generated addresses
# tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [keys[i].address() for i in range(len(keys))])
print("unsigned transaction:")
print("bad signatures: %s" % tx2.bad_signature_count())
print(tx2.as_hex())
for i in range(1, N+1):
    print("signining with key number: %s" % i)
    hash160_lookup = build_hash160_lookup([keys[i].secret_exponent()])
    p2sh_lookup = build_p2sh_lookup([underlying_script])
示例#30
0
def build_credit_tx(script_out_bin, coin_value=0):
    txs_in = [TxIn(b'\0' * 32, 4294967295, b'\0\0', sequence=4294967295)]
    txs_out = [TxOut(coin_value, script_out_bin)]
    return Tx(1, txs_in, txs_out)
示例#31
0
文件: tx.py 项目: stafur/pycoin
def main():
    parser = argparse.ArgumentParser(
        description="Manipulate bitcoin (or alt coin) transactions.",
        epilog=EPILOG)

    parser.add_argument('-t', "--transaction-version", type=int,
                        help='Transaction version, either 1 (default) or 3 (not yet supported).')

    parser.add_argument('-l', "--lock-time", type=parse_locktime, help='Lock time; either a block'
                        'index, or a date/time (example: "2014-01-01T15:00:00"')

    parser.add_argument('-n', "--network", default="BTC",
                        help='Define network code (M=Bitcoin mainnet, T=Bitcoin testnet).')

    parser.add_argument('-a', "--augment", action='store_true',
                        help='augment tx by adding any missing spendable metadata by fetching'
                             ' inputs from cache and/or web services')

    parser.add_argument("-i", "--fetch-spendables", metavar="address", action="append",
                        help='Add all unspent spendables for the given bitcoin address. This information'
                        ' is fetched from web services.')

    parser.add_argument('-f', "--private-key-file", metavar="path-to-private-keys", action="append",
                        help='file containing WIF or BIP0032 private keys. If file name ends with .gpg, '
                        '"gpg -d" will be invoked automatically. File is read one line at a time, and if '
                        'the file contains only one WIF per line, it will also be scanned for a bitcoin '
                        'address, and any addresses found will be assumed to be public keys for the given'
                        ' private key.',
                        type=argparse.FileType('r'))

    parser.add_argument('-g', "--gpg-argument", help='argument to pass to gpg (besides -d).', default='')

    parser.add_argument("--remove-tx-in", metavar="tx_in_index_to_delete", action="append", type=int,
                        help='remove a tx_in')

    parser.add_argument("--remove-tx-out", metavar="tx_out_index_to_delete", action="append", type=int,
                        help='remove a tx_out')

    parser.add_argument('-F', "--fee", help='fee, in satoshis, to pay on transaction, or '
                        '"standard" to auto-calculate. This is only useful if the "split pool" '
                        'is used; otherwise, the fee is automatically set to the unclaimed funds.',
                        default="standard", metavar="transaction-fee", type=parse_fee)

    parser.add_argument('-C', "--cache", help='force the resultant transaction into the transaction cache.'
                        ' Mostly for testing.', action='store_true'),

    parser.add_argument('-u', "--show-unspents", action='store_true',
                        help='show TxOut items for this transaction in Spendable form.')

    parser.add_argument('-b', "--bitcoind-url",
                        help='URL to bitcoind instance to validate against (http://user:pass@host:port).')

    parser.add_argument('-o', "--output-file", metavar="path-to-output-file", type=argparse.FileType('wb'),
                        help='file to write transaction to. This supresses most other output.')

    parser.add_argument("argument", nargs="+", help='generic argument: can be a hex transaction id '
                        '(exactly 64 characters) to be fetched from cache or a web service;'
                        ' a transaction as a hex string; a path name to a transaction to be loaded;'
                        ' a spendable 4-tuple of the form tx_id/tx_out_idx/script_hex/satoshi_count '
                        'to be added to TxIn list; an address/satoshi_count to be added to the TxOut '
                        'list; an address to be added to the TxOut list and placed in the "split'
                        ' pool".')

    args = parser.parse_args()

    # defaults

    txs = []
    spendables = []
    payables = []

    key_iters = []

    TX_ID_RE = re.compile(r"^[0-9a-fA-F]{64}$")

    # there are a few warnings we might optionally print out, but only if
    # they are relevant. We don't want to print them out multiple times, so we
    # collect them here and print them at the end if they ever kick in.

    warning_tx_cache = None
    warning_get_tx = None
    warning_spendables = None

    if args.private_key_file:
        wif_re = re.compile(r"[1-9a-km-zA-LMNP-Z]{51,111}")
        # address_re = re.compile(r"[1-9a-kmnp-zA-KMNP-Z]{27-31}")
        for f in args.private_key_file:
            if f.name.endswith(".gpg"):
                gpg_args = ["gpg", "-d"]
                if args.gpg_argument:
                    gpg_args.extend(args.gpg_argument.split())
                gpg_args.append(f.name)
                popen = subprocess.Popen(gpg_args, stdout=subprocess.PIPE)
                f = popen.stdout
            for line in f.readlines():
                # decode
                if isinstance(line, bytes):
                    line = line.decode("utf8")
                # look for WIFs
                possible_keys = wif_re.findall(line)

                def make_key(x):
                    try:
                        return Key.from_text(x)
                    except Exception:
                        return None

                keys = [make_key(x) for x in possible_keys]
                for key in keys:
                    if key:
                        key_iters.append((k.wif() for k in key.subkeys("")))

                # if len(keys) == 1 and key.hierarchical_wallet() is None:
                #    # we have exactly 1 WIF. Let's look for an address
                #   potential_addresses = address_re.findall(line)

    # we create the tx_db lazily
    tx_db = None

    for arg in args.argument:

        # hex transaction id
        if TX_ID_RE.match(arg):
            if tx_db is None:
                warning_tx_cache = message_about_tx_cache_env()
                warning_get_tx = message_about_get_tx_env()
                tx_db = get_tx_db()
            tx = tx_db.get(h2b_rev(arg))
            if not tx:
                for m in [warning_tx_cache, warning_get_tx, warning_spendables]:
                    if m:
                        print("warning: %s" % m, file=sys.stderr)
                parser.error("can't find Tx with id %s" % arg)
            txs.append(tx)
            continue

        # hex transaction data
        try:
            tx = Tx.tx_from_hex(arg)
            txs.append(tx)
            continue
        except Exception:
            pass

        try:
            key = Key.from_text(arg)
            # TODO: check network
            if key.wif() is None:
                payables.append((key.address(), 0))
                continue
            # TODO: support paths to subkeys
            key_iters.append((k.wif() for k in key.subkeys("")))
            continue
        except Exception:
            pass

        if os.path.exists(arg):
            try:
                with open(arg, "rb") as f:
                    if f.name.endswith("hex"):
                        f = io.BytesIO(codecs.getreader("hex_codec")(f).read())
                    tx = Tx.parse(f)
                    txs.append(tx)
                    try:
                        tx.parse_unspents(f)
                    except Exception as ex:
                        pass
                    continue
            except Exception:
                pass

        parts = arg.split("/")
        if len(parts) == 4:
            # spendable
            try:
                spendables.append(Spendable.from_text(arg))
                continue
            except Exception:
                pass

        # TODO: fix allowable_prefixes
        allowable_prefixes = b'\0'
        if len(parts) == 2 and encoding.is_valid_bitcoin_address(
                parts[0], allowable_prefixes=allowable_prefixes):
            try:
                payables.append(parts)
                continue
            except ValueError:
                pass

        parser.error("can't parse %s" % arg)

    if args.fetch_spendables:
        warning_spendables = message_about_spendables_for_address_env()
        for address in args.fetch_spendables:
            spendables.extend(spendables_for_address(address))

    for tx in txs:
        if tx.missing_unspents() and args.augment:
            if tx_db is None:
                warning_tx_cache = message_about_tx_cache_env()
                warning_get_tx = message_about_get_tx_env()
                tx_db = get_tx_db()
            tx.unspents_from_db(tx_db, ignore_missing=True)

    txs_in = []
    txs_out = []
    unspents = []
    # we use a clever trick here to keep each tx_in corresponding with its tx_out
    for tx in txs:
        smaller = min(len(tx.txs_in), len(tx.txs_out))
        txs_in.extend(tx.txs_in[:smaller])
        txs_out.extend(tx.txs_out[:smaller])
        unspents.extend(tx.unspents[:smaller])
    for tx in txs:
        smaller = min(len(tx.txs_in), len(tx.txs_out))
        txs_in.extend(tx.txs_in[smaller:])
        txs_out.extend(tx.txs_out[smaller:])
        unspents.extend(tx.unspents[smaller:])
    for spendable in spendables:
        txs_in.append(spendable.tx_in())
        unspents.append(spendable)
    for address, coin_value in payables:
        script = standard_tx_out_script(address)
        txs_out.append(TxOut(coin_value, script))

    lock_time = args.lock_time
    version = args.transaction_version

    # if no lock_time is explicitly set, inherit from the first tx or use default
    if lock_time is None:
        if txs:
            lock_time = txs[0].lock_time
        else:
            lock_time = DEFAULT_LOCK_TIME

    # if no version is explicitly set, inherit from the first tx or use default
    if version is None:
        if txs:
            version = txs[0].version
        else:
            version = DEFAULT_VERSION

    if args.remove_tx_in:
        s = set(args.remove_tx_in)
        txs_in = [tx_in for idx, tx_in in enumerate(txs_in) if idx not in s]

    if args.remove_tx_out:
        s = set(args.remove_tx_out)
        txs_out = [tx_out for idx, tx_out in enumerate(txs_out) if idx not in s]

    tx = Tx(txs_in=txs_in, txs_out=txs_out, lock_time=lock_time, version=version, unspents=unspents)

    fee = args.fee
    try:
        distribute_from_split_pool(tx, fee)
    except ValueError as ex:
        print("warning: %s" % ex.args[0], file=sys.stderr)

    unsigned_before = tx.bad_signature_count()
    if unsigned_before > 0 and key_iters:
        def wif_iter(iters):
            while len(iters) > 0:
                for idx, iter in enumerate(iters):
                    try:
                        wif = next(iter)
                        yield wif
                    except StopIteration:
                        iters = iters[:idx] + iters[idx+1:]
                        break

        print("signing...", file=sys.stderr)
        sign_tx(tx, wif_iter(key_iters))

    unsigned_after = tx.bad_signature_count()
    if unsigned_after > 0 and key_iters:
        print("warning: %d TxIn items still unsigned" % unsigned_after, file=sys.stderr)

    if len(tx.txs_in) == 0:
        print("warning: transaction has no inputs", file=sys.stderr)

    if len(tx.txs_out) == 0:
        print("warning: transaction has no outputs", file=sys.stderr)

    include_unspents = (unsigned_after > 0)
    tx_as_hex = tx.as_hex(include_unspents=include_unspents)

    if args.output_file:
        f = args.output_file
        if f.name.endswith(".hex"):
            f.write(tx_as_hex.encode("utf8"))
        else:
            tx.stream(f)
            if include_unspents:
                tx.stream_unspents(f)
        f.close()
    elif args.show_unspents:
        for spendable in tx.tx_outs_as_spendable():
            print(spendable.as_text())
    else:
        if not tx.missing_unspents():
            check_fees(tx)
        dump_tx(tx, args.network)
        if include_unspents:
            print("including unspents in hex dump since transaction not fully signed")
        print(tx_as_hex)

    if args.cache:
        if tx_db is None:
            warning_tx_cache = message_about_tx_cache_env()
            warning_get_tx = message_about_get_tx_env()
            tx_db = get_tx_db()
        tx_db.put(tx)

    if args.bitcoind_url:
        if tx_db is None:
            warning_tx_cache = message_about_tx_cache_env()
            warning_get_tx = message_about_get_tx_env()
            tx_db = get_tx_db()
        validate_bitcoind(tx, tx_db, args.bitcoind_url)

    if tx.missing_unspents():
        print("\n** can't validate transaction as source transactions missing", file=sys.stderr)
    else:
        try:
            if tx_db is None:
                warning_tx_cache = message_about_tx_cache_env()
                warning_get_tx = message_about_get_tx_env()
                tx_db = get_tx_db()
            tx.validate_unspents(tx_db)
            print('all incoming transaction values validated')
        except BadSpendableError as ex:
            print("\n**** ERROR: FEES INCORRECTLY STATED: %s" % ex.args[0], file=sys.stderr)
        except Exception as ex:
            print("\n*** can't validate source transactions as untampered: %s" %
                  ex.args[0], file=sys.stderr)

    # print warnings
    for m in [warning_tx_cache, warning_get_tx, warning_spendables]:
        if m:
            print("warning: %s" % m, file=sys.stderr)
示例#32
0
    def _test_sighash_single(self, netcode):
        k0 = Key(secret_exponent=PRIV_KEYS[0],
                 is_compressed=True,
                 netcode=netcode)
        k1 = Key(secret_exponent=PRIV_KEYS[1],
                 is_compressed=True,
                 netcode=netcode)
        k2 = Key(secret_exponent=PRIV_KEYS[2],
                 is_compressed=True,
                 netcode=netcode)
        k3 = Key(secret_exponent=PRIV_KEYS[3],
                 is_compressed=True,
                 netcode=netcode)
        k4 = Key(secret_exponent=PRIV_KEYS[4],
                 is_compressed=True,
                 netcode=netcode)
        k5 = Key(secret_exponent=PRIV_KEYS[5],
                 is_compressed=True,
                 netcode=netcode)

        # Fake a coinbase transaction
        coinbase_tx = Tx.coinbase_tx(k0.sec(), 500000000)
        coinbase_tx.txs_out.append(
            TxOut(1000000000,
                  pycoin_compile('%s OP_CHECKSIG' % b2h(k1.sec()))))
        coinbase_tx.txs_out.append(
            TxOut(1000000000,
                  pycoin_compile('%s OP_CHECKSIG' % b2h(k2.sec()))))

        self.assertEqual(
            '2acbe1006f7168bad538b477f7844e53de3a31ffddfcfc4c6625276dd714155a',
            b2h_rev(coinbase_tx.hash()))

        # Make the test transaction
        txs_in = [
            TxIn(coinbase_tx.hash(), 0),
            TxIn(coinbase_tx.hash(), 1),
            TxIn(coinbase_tx.hash(), 2),
        ]
        txs_out = [
            TxOut(900000000, standard_tx_out_script(k3.address())),
            TxOut(800000000, standard_tx_out_script(k4.address())),
            TxOut(800000000, standard_tx_out_script(k5.address())),
        ]
        tx = Tx(1, txs_in, txs_out)
        tx.set_unspents(coinbase_tx.txs_out)

        self.assertEqual(
            '791b98ef0a3ac87584fe273bc65abd89821569fd7c83538ac0625a8ca85ba587',
            b2h_rev(tx.hash()))

        sig_type = SIGHASH_SINGLE

        sig_hash = tx.signature_hash(coinbase_tx.txs_out[0].script, 0,
                                     sig_type)
        self.assertEqual(
            'cc52d785a3b4133504d1af9e60cd71ca422609cb41df3a08bbb466b2a98a885e',
            b2h(to_bytes_32(sig_hash)))

        sig = sigmake(k0, sig_hash, sig_type)
        self.assertTrue(sigcheck(k0, sig_hash, sig[:-1]))

        tx.txs_in[0].script = pycoin_compile(b2h(sig))
        self.assertTrue(tx.is_signature_ok(0))

        sig_hash = tx.signature_hash(coinbase_tx.txs_out[1].script, 1,
                                     sig_type)
        self.assertEqual(
            '93bb883d70fccfba9b8aa2028567aca8357937c65af7f6f5ccc6993fd7735fb7',
            b2h(to_bytes_32(sig_hash)))

        sig = sigmake(k1, sig_hash, sig_type)
        self.assertTrue(sigcheck(k1, sig_hash, sig[:-1]))

        tx.txs_in[1].script = pycoin_compile(b2h(sig))
        self.assertTrue(tx.is_signature_ok(1))

        sig_hash = tx.signature_hash(coinbase_tx.txs_out[2].script, 2,
                                     sig_type)
        self.assertEqual(
            '53ef7f67c3541bffcf4e0d06c003c6014e2aa1fb38ff33240b3e1c1f3f8e2a35',
            b2h(to_bytes_32(sig_hash)))

        sig = sigmake(k2, sig_hash, sig_type)
        self.assertTrue(sigcheck(k2, sig_hash, sig[:-1]))

        tx.txs_in[2].script = pycoin_compile(b2h(sig))
        self.assertTrue(tx.is_signature_ok(2))

        sig_type = SIGHASH_SINGLE | SIGHASH_ANYONECANPAY

        sig_hash = tx.signature_hash(coinbase_tx.txs_out[0].script, 0,
                                     sig_type)
        self.assertEqual(
            '2003393d246a7f136692ce7ab819c6eadc54ffea38eb4377ac75d7d461144e75',
            b2h(to_bytes_32(sig_hash)))

        sig = sigmake(k0, sig_hash, sig_type)
        self.assertTrue(sigcheck(k0, sig_hash, sig[:-1]))

        tx.txs_in[0].script = pycoin_compile(b2h(sig))
        self.assertTrue(tx.is_signature_ok(0))

        sig_hash = tx.signature_hash(coinbase_tx.txs_out[1].script, 1,
                                     sig_type)
        self.assertEqual(
            'e3f469ac88e9f35e8eff0bd8ad4ad3bf899c80eb7645947d60860de4a08a35df',
            b2h(to_bytes_32(sig_hash)))

        sig = sigmake(k1, sig_hash, sig_type)
        self.assertTrue(sigcheck(k1, sig_hash, sig[:-1]))

        tx.txs_in[1].script = pycoin_compile(b2h(sig))
        self.assertTrue(tx.is_signature_ok(1))

        sig_hash = tx.signature_hash(coinbase_tx.txs_out[2].script, 2,
                                     sig_type)
        self.assertEqual(
            'bacd7c3ab79cad71807312677c1788ad9565bf3c00ab9a153d206494fb8b7e6a',
            b2h(to_bytes_32(sig_hash)))

        sig = sigmake(k2, sig_hash, sig_type)
        self.assertTrue(sigcheck(k2, sig_hash, sig[:-1]))

        tx.txs_in[2].script = pycoin_compile(b2h(sig))
        self.assertTrue(tx.is_signature_ok(2))