Exemplo n.º 1
0
def submit_opreturn(rpc_connection, address, data):
    from bitcoin.core import CTxIn, CMutableTxOut, CScript, CMutableTransaction, COIN, CENT, b2x, b2lx
    from bitcoin.core.script import OP_CHECKSIG, OP_RETURN

    txouts = []

    unspent = sorted([y for y in rpc_connection.listunspent(0) if str(y['address']) == address], key=lambda x: hash(x['amount']))

    txins = [CTxIn(unspent[-1]['outpoint'])]

    value_in = unspent[-1]['amount']

    change_pubkey = rpc_connection.validateaddress(address)['pubkey']
    change_out = CMutableTxOut(int(value_in - 2*CENT), CScript([change_pubkey, OP_CHECKSIG]))
    digest_outs = [CMutableTxOut(CENT, CScript([OP_RETURN, data]))]
    txouts = [change_out] + digest_outs
    tx = CMutableTransaction(txins, txouts)
    
    print tx.serialize().encode('hex')
    r = rpc_connection.signrawtransaction(tx)
    assert r['complete']
    tx = r['tx']


    #print b2x(tx.serialize())
    #print len(tx.serialize()), 'bytes'
    print(b2lx(rpc_connection.sendrawtransaction(tx)))
Exemplo n.º 2
0
def test_emergency_txout(bitcoind):
    """Test mostly the emergency tx locktime"""
    amount = Decimal("50") - Decimal("500") / Decimal(COIN)
    privkeys = [CKey(os.urandom(32)) for _ in range(4)]
    pubkeys = [k.pub for k in privkeys]
    txo = emergency_txout(pubkeys, COIN * amount)
    addr = str(CBitcoinAddress.from_scriptPubKey(txo.scriptPubKey))
    # This makes a transaction with only one vout
    txid = bitcoind.pay_to(addr, amount)
    new_amount = amount - Decimal("500") / Decimal(COIN)
    addr = bitcoind.getnewaddress()
    txin = CTxIn(COutPoint(lx(txid), 0), nSequence=4464)
    txout = CTxOut(new_amount * COIN, CBitcoinAddress(addr).to_scriptPubKey())
    tx = CMutableTransaction([txin], [txout], nVersion=2)
    tx_hash = SignatureHash(emergency_script(pubkeys), tx, 0, SIGHASH_ALL,
                            int(amount * COIN), SIGVERSION_WITNESS_V0)
    sigs = [k.sign(tx_hash) + bytes([SIGHASH_ALL]) for k in privkeys]
    witness_script = [bytes(0), *sigs, emergency_script(pubkeys)]
    tx.wit = CTxWitness([CTxInWitness(CScriptWitness(witness_script))])
    # 1 month of locktime
    bitcoind.generate_block(4464 - 2)
    with pytest.raises(VerifyRejectedError, match="non-BIP68-final"):
        bitcoind.send_tx(tx.serialize().hex())
    bitcoind.generate_block(1)
    bitcoind.send_tx(tx.serialize().hex())
    assert bitcoind.has_utxo(addr)
Exemplo n.º 3
0
def main():

    proxy = bitcoin.rpc.Proxy()

    assert len(sys.argv) > 1

    digests = []
    for f in sys.argv[1:]:
        try:
            with open(f, 'rb') as fd:
                digests.append(Hash(fd.read()))
        except FileNotFoundError as exp:
            if len(f)/2 in (20, 32):
                digests.append(x(f))
            else:
                raise exp
        except IOError as exp:
            print(exp, file=sys.stderr)
            continue

    for digest in digests:
        unspent = sorted(proxy.listunspent(0),
                         key=lambda _x: hash(_x['amount']))

        txins = [CTxIn(unspent[-1]['outpoint'])]
        value_in = unspent[-1]['amount']

        change_addr = proxy.getnewaddress()
        change_pubkey = proxy.validateaddress(change_addr)['pubkey']
        change_out = CMutableTxOut(params.MAX_MONEY, CScript([change_pubkey, OP_CHECKSIG]))

        digest_outs = [CMutableTxOut(0, CScript([OP_RETURN, digest]))]

        txouts = [change_out] + digest_outs

        tx = CMutableTransaction(txins, txouts)


        FEE_PER_BYTE = 0.00025*COIN/1000
        while True:
            tx.vout[0].nValue = int(value_in - max(len(tx.serialize()) * FEE_PER_BYTE, 0.00011*COIN))

            r = proxy.signrawtransaction(tx)
            assert r['complete']
            tx = r['tx']

            if value_in - tx.vout[0].nValue >= len(tx.serialize()) * FEE_PER_BYTE:
                print(b2x(tx.serialize()))
                print(len(tx.serialize()), 'bytes', file=sys.stderr)
                print(b2lx(proxy.sendrawtransaction(tx)))
                break
Exemplo n.º 4
0
    def as_tx(self):
        sum_in = sum(prevtx.nValue for _, prevtx, _ in self.prevouts)
        sig_size = sum(redeemer.spendbytes for _, _, redeemer in self.prevouts)
        tx_size = (
            4 +  # version field
            2 +  # # of txins
            len(self.prevouts) * 41 +  # txins, excluding sigs
            sig_size +  # txins, sigs only
            1 +  # # of txouts
            34 +  # txout
            4  # nLockTime field
        )
        feerate = int(self.proxy._call('estimatefee', 1) * COIN)
        # satoshi's per KB
        if feerate <= 0:
            feerate = 10000
        fees = int(tx_size * feerate / 1000)

        tx = CMutableTransaction(
            [CTxIn(outpoint, nSequence=0) for outpoint, _, _ in self.prevouts],
            [CTxOut(sum_in - fees, self.payto.to_scriptPubKey())], 0)

        for n, (_, _, redeemer) in enumerate(self.prevouts):
            redeemer.mutate_spend(tx, n)

        unsigned_tx = CTransaction.from_tx(tx)

        for n, (_, _, redeemer) in enumerate(self.prevouts):
            txin = CMutableTxIn.from_txin(tx.vin[n])
            txin.scriptSig = redeemer.sign_spend(unsigned_tx, n)
            tx.vin[n] = CTxIn.from_txin(txin)

        print(b2x(tx.serialize()))
Exemplo n.º 5
0
def refund(proxy, refundGuy, contract):
    redeemScript = CScript(x(contract['redeemScript']))
    txin = CMutableTxIn(fundtx['outpoint'])
    txout = CMutableTxOut(fundtx['amount'] - FEE,
                          refundGuy['addr'].to_scriptPubKey())

    tx = CMutableTransaction([txin], [txout])
    txin.nSequence = 0
    tx.nLockTime = contract['redeemblocknum']
    sighash = SignatureHash(redeemScript, tx, 0, SIGHASH_ALL)

    sig = refundGuy['key'].sign(sighash) + bytes([SIGHASH_ALL])

    txin.scriptSig = CScript([sig, refundGuy['key'].pub, OP_FALSE, redeemScript])

    txin_scriptPubKey = redeemScript.to_p2sh_scriptPubKey()
    print('Raw redeem transaction hex: {0}'.format(b2x(tx.serialize())))
    res = VerifyScript(txin.scriptSig, txin_scriptPubKey,
                       tx, 0, (SCRIPT_VERIFY_P2SH,))
    print("Script verified, sending raw transaction... (NOT)", res)

    txid = proxy.sendrawtransaction(tx)
    refund_tx = b2x(lx(b2x(txid)))
    fund_tx = str(fundtx['outpoint'])
    return {"refund_tx": refund_tx, "fund_tx": fund_tx}
Exemplo n.º 6
0
def redeem(proxy, redeemerGuy, contract, fundtx, secret):
    print('redeemPubKey', redeemerGuy['addr'])
    # TODO: Compare with script on blockchain?
    redeemScript = CScript(x(contract['redeemScript']))
    txin = CMutableTxIn(fundtx['outpoint'])
    txout = CMutableTxOut(fundtx['amount'] - FEE,
                          redeemerGuy['addr'].to_scriptPubKey())

    # Create the unsigned raw transaction.
    tx = CMutableTransaction([txin], [txout])
    sighash = SignatureHash(redeemScript, tx, 0, SIGHASH_ALL)
    # TODO: protect privkey better, separate signing from rawtx creation
    #privkey = self.bitcoind.dumpprivkey(self.redeemPubKey)
    sig = redeemerGuy['key'].sign(sighash) + bytes([SIGHASH_ALL])
    preimage = secret.encode('utf-8')
    # preimage = x(secret)
    txin.scriptSig = CScript([sig, redeemerGuy['key'].pub, preimage,
                              OP_TRUE, redeemScript])

    # print("txin.scriptSig", b2x(txin.scriptSig))
    txin_scriptPubKey = redeemScript.to_p2sh_scriptPubKey()
    print('Raw redeem transaction hex: ', b2x(tx.serialize()))
    VerifyScript(txin.scriptSig, txin_scriptPubKey,
                 tx, 0, (SCRIPT_VERIFY_P2SH,))
    print("Script verified, sending raw transaction...")
    txid = proxy.sendrawtransaction(tx)
    fund_tx = str(fundtx['outpoint'])
    redeem_tx = b2x(lx(b2x(txid)))
    return {"redeem_tx": redeem_tx, "fund_tx": fund_tx}
Exemplo n.º 7
0
    def close_tx(self, fee: int, privkey_dest: str) -> str:
        """Create a (mutual) close tx"""
        txin = CTxIn(COutPoint(bytes.fromhex(self.txid), self.output_index))

        out_privkey = privkey_expand(privkey_dest)

        txout = CTxOut(self.amount - fee,
                       CScript([script.OP_0,
                                Hash160(coincurve.PublicKey.from_secret(out_privkey.secret).format())]))

        tx = CMutableTransaction(vin=[txin], vout=[txout])
        sighash = script.SignatureHash(self.redeemscript(), tx, inIdx=0,
                                       hashtype=script.SIGHASH_ALL,
                                       amount=self.amount,
                                       sigversion=script.SIGVERSION_WITNESS_V0)

        sigs = [key.sign(sighash, hasher=None) for key in self.funding_privkeys_for_tx()]
        # BOLT #3:
        # ## Closing Transaction
        # ...
        #    * `txin[0]` witness: `0 <signature_for_pubkey1> <signature_for_pubkey2>`
        witness = CScriptWitness([bytes(),
                                  sigs[0] + bytes([script.SIGHASH_ALL]),
                                  sigs[1] + bytes([script.SIGHASH_ALL]),
                                  self.redeemscript()])
        tx.wit = CTxWitness([CTxInWitness(witness)])
        return tx.serialize().hex()
Exemplo n.º 8
0
def main():
    ''' Our main function. '''

    SelectParams('mainnet')

    decoded_transaction = eval(open('transaction_to_sign.txt').read()) # pylint: disable=eval-used

    txin_txid = lx(decoded_transaction['vin'][0]['txid'])
    txin_vout = 0
    tx_in = CMutableTxIn(COutPoint(txin_txid, txin_vout))

    tx_out = []
    for idx in range(len(decoded_transaction['vout'])):
        satoshis = int(COIN * decoded_transaction['vout'][idx]['value'])
        script_pub_key = CScript(bytes.fromhex(decoded_transaction['vout'][idx]['scriptPubKey']['hex']))
        tx_out.append(CMutableTxOut(satoshis, script_pub_key))

    tx_to_spend = CMutableTransaction([tx_in], tx_out)

    priv_1 = CBitcoinSecret.from_secret_bytes(bytes.fromhex(PRIV_HEX_1))
    priv_2 = CBitcoinSecret.from_secret_bytes(bytes.fromhex(PRIV_HEX_2))

    txin_redeem_script = CScript(bytes.fromhex(decoded_transaction['vin'][0]['scriptSig']['hex']))
    # Input 0 is fixed.
    sighash = SignatureHash(txin_redeem_script, tx_to_spend, 0, SIGHASH_ALL)
    signatures = []
    for priv in [priv_1, priv_2]:
        signatures.append(priv.sign(sighash) + bytes([SIGHASH_ALL]))

    tx_in.scriptSig = CScript([CScriptOp(0x00), signatures[0], signatures[1], txin_redeem_script])

    # script_pub_key Defined in cycle.
    VerifyScript(tx_in.scriptSig, txin_redeem_script, tx_to_spend, 0, (SCRIPT_VERIFY_P2SH,))

    print(b2x(tx_to_spend.serialize()))
Exemplo n.º 9
0
    def refund(self, contract):
        fundtx = self.find_transaction_to_address(contract.p2sh)
        print("Fund tx found in refund: ", fundtx)
        refundPubKey = self.find_refundAddr(contract)
        print('refundPubKey: {0}'.format(refundPubKey))

        redeemScript = CScript(x(contract.redeemScript))
        txin = CMutableTxIn(fundtx['outpoint'])
        txout = CMutableTxOut(fundtx['amount'] - FEE,
                              refundPubKey.to_scriptPubKey())

        # Create the unsigned raw transaction.
        tx = CMutableTransaction([txin], [txout])
        # Set nSequence and nLockTime
        txin.nSequence = 0
        tx.nLockTime = contract.redeemblocknum
        sighash = SignatureHash(redeemScript, tx, 0, SIGHASH_ALL)
        privkey = self.bitcoind.dumpprivkey(refundPubKey)
        sig = privkey.sign(sighash) + bytes([SIGHASH_ALL])

        # Sign without secret
        txin.scriptSig = CScript([sig, privkey.pub, OP_FALSE, redeemScript])

        # txin.nSequence = 2185
        txin_scriptPubKey = redeemScript.to_p2sh_scriptPubKey()
        print('Raw redeem transaction hex: {0}'.format(b2x(tx.serialize())))
        res = VerifyScript(txin.scriptSig, txin_scriptPubKey,
                           tx, 0, (SCRIPT_VERIFY_P2SH,))
        print("Script verified, sending raw transaction... (NOT)", res)
        txid = self.bitcoind.sendrawtransaction(tx)
        refund_tx = b2x(lx(b2x(txid)))
        fund_tx = str(fundtx['outpoint'])
        return {"refund_tx": refund_tx, "fund_tx": fund_tx}
Exemplo n.º 10
0
def spend_p2sh_mediator(redeemScript, txins_str, amounts, daddrs, sig, rein):
    txin_redeemScript = CScript(x(redeemScript))
    txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey()
    txins_obj = []
    for txin_str in txins_str.split():
        txin_list = txin_str.split("-")
        txins_obj.append(
            CMutableTxIn(COutPoint(lx(txin_list[0]), int(txin_list[1]))))
    txouts = []
    len_amounts = len(amounts)
    for i in range(0, len_amounts):
        txouts.append(
            CMutableTxOut(
                round(amounts[i], 8) * COIN,
                CBitcoinAddress(daddrs[i]).to_scriptPubKey()))
    tx = CMutableTransaction(txins_obj, txouts)
    seckey = CBitcoinSecret(rein.user.dkey)
    ntxins = len(txins_obj)
    sig_list = []
    for s in sig.split():
        sig_list.append(x(s))
    sig2_str = ""
    for i in range(0, ntxins):
        sighash = SignatureHash(txin_redeemScript, tx, i, SIGHASH_ALL)
        sig2 = seckey.sign(sighash) + x("01")
        sig2_str += " " + b2x(sig2)
        txins_obj[i].scriptSig = CScript(
            [OP_0, sig2, sig_list[i], txin_redeemScript])
        VerifyScript(txins_obj[i].scriptSig, txin_scriptPubKey, tx, i,
                     (SCRIPT_VERIFY_P2SH, ))
    tx_bytes = tx.serialize()
    hash = sha256(sha256(tx_bytes).digest()).digest()
    txid = b2x(hash[::-1])
    txid_causeway = broadcast_tx(b2x(tx_bytes), rein)
    return (txid, sig2_str[1:])
Exemplo n.º 11
0
    def as_tx(self):
        sum_in = sum(prevtx.nValue for _,prevtx,_ in self.prevouts)
        sig_size = sum(redeemer.spendbytes for _,_,redeemer in self.prevouts)
        tx_size = (4                        + # version field
                   2                        + # # of txins
                   len(self.prevouts) * 41  + # txins, excluding sigs
                   sig_size                 + # txins, sigs only
                   1                        + # # of txouts
                   34                       + # txout
                   4                          # nLockTime field
                   )
        feerate = int(self.proxy._call('estimatefee', 1) * COIN) 
        # satoshi's per KB
        if feerate <= 0:
            feerate = 10000
        fees = int(tx_size * feerate / 1000)

        tx = CMutableTransaction(
                [CTxIn(outpoint, nSequence=0)
                    for outpoint,_,_ in self.prevouts],
                [CTxOut(sum_in - fees, self.payto.to_scriptPubKey())],
                0)

        for n,(_,_,redeemer) in enumerate(self.prevouts):
            redeemer.mutate_spend(tx, n)

        unsigned_tx = CTransaction.from_tx(tx)

        for n,(_,_,redeemer) in enumerate(self.prevouts):
            txin = CMutableTxIn.from_txin(tx.vin[n])
            txin.scriptSig = redeemer.sign_spend(unsigned_tx, n)
            tx.vin[n] = CTxIn.from_txin(txin)

        print(b2x(tx.serialize()))
Exemplo n.º 12
0
def submit_opreturn(rpc_raw, rpc_connection, address, data):
    from bitcoin.core import CTxIn, CMutableTxOut, CScript, CMutableTransaction, COIN, CENT, b2x, b2lx
    from bitcoin.core.script import OP_CHECKSIG, OP_RETURN

    txouts = []

    unspent = sorted(
        [y for y in rpc_connection.listunspent(0) if str(y["address"]) == address], key=lambda x: hash(x["amount"])
    )

    txins = [CTxIn(unspent[-1]["outpoint"])]

    value_in = unspent[-1]["amount"]

    change_pubkey = rpc_connection.validateaddress(address)["pubkey"]
    change_out = CMutableTxOut(int(value_in - 1 * CENT), CScript([change_pubkey, OP_CHECKSIG]))
    digest_outs = [CMutableTxOut(0, CScript([OP_RETURN, data]))]
    txouts = [change_out] + digest_outs
    tx = CMutableTransaction(txins, txouts)

    tx_hex = tx.serialize().encode("hex")
    print "decoderawtransaction", tx_hex
    transaction_decoded = rpc_raw.decoderawtransaction(tx_hex)
    print json.dumps(transaction_decoded, indent=4, default=json_custom_parser)
    r = rpc_connection.signrawtransaction(tx)
    assert r["complete"]
    tx = r["tx"]

    # print b2x(tx.serialize())
    # print len(tx.serialize()), 'bytes'
    sent_tx_id = rpc_connection.sendrawtransaction(tx)
    return b2lx(sent_tx_id)
 def test_sendrawtransaction(self):
     num_outputs = 5
     given_transaction = CMutableTransaction([], [make_txout() for x in range(0, num_outputs)])
     expected_txid = b2lx(given_transaction.GetHash())
     given_transaction_hex = b2x(given_transaction.serialize())
     proxy = FakeBitcoinProxy()
     resulting_txid = proxy.sendrawtransaction(given_transaction_hex)
     self.assertEqual(resulting_txid, expected_txid)
Exemplo n.º 14
0
 def put(self):
     """Persist self."""
     commitment = CMutableTransaction([self.anchor], [self.our, self.their])
     commitment = CMutableTransaction.from_tx(commitment)
     commitment.vin[0].scriptSig = commitment.vin[0].scriptSig.to_script()
     for tx_out in commitment.vout:
         tx_out.scriptPubKey = tx_out.scriptPubKey.to_scriptPubKey()
     with g.dat:
         g.dat.execute("INSERT OR REPLACE INTO CHANNELS VALUES (?, ?)",
                       (self.address, commitment.serialize()))
    def test_fundrawtransaction_adds_output(self):
        num_outputs = 5
        unfunded_transaction = CMutableTransaction([], [make_txout() for x in range(0, num_outputs)])
        proxy = FakeBitcoinProxy()

        funded_transaction_hex = proxy.fundrawtransaction(b2x(unfunded_transaction.serialize()))["hex"]
        funded_transaction = CMutableTransaction.deserialize(x(funded_transaction_hex))

        self.assertTrue(len(funded_transaction.vout) > num_outputs)
        self.assertEqual(len(funded_transaction.vout), num_outputs + 1)
Exemplo n.º 16
0
def test_create_transaction_object_1(inputs_1, outputs_1):
    r = PaymentService.create_transaction_object(inputs=inputs_1, outputs=outputs_1)

    tx_in: List[CMutableTxIn] = [
        CMutableTxIn(COutPoint(lx('4521418569de2f78d5d2d3c535567ac9c48c95314c53a67788d4dcdc9a8d915b'), 0))]

    pk = CBitcoinAddress('16moGJwkzWhNC1pfnfJptKj9G1ogQz16xd').to_scriptPubKey()
    tx_out: List[CMutableTxOut] = [CMutableTxOut(100000, pk)]

    expected = CMutableTransaction(tx_in, tx_out)
    assert b2x(r.serialize()) == b2x(expected.serialize())
Exemplo n.º 17
0
    def redeem_contract(self, contract, secret):
        print("Parsing script for redeem_contract...")
        scriptarray = self.parse_script(contract.redeemScript)
        redeemblocknum = scriptarray[8]
        redeemPubKey = P2PKHBitcoinAddress.from_bytes(x(scriptarray[6]))
        refundPubKey = P2PKHBitcoinAddress.from_bytes(x(scriptarray[13]))
        p2sh = contract.p2sh
        #checking there are funds in the address
        amount = self.check_funds(p2sh)
        if(amount == 0):
            print("address ", p2sh, " not funded")
            quit()
        fundtx = self.find_transaction_to_address(p2sh)
        amount = fundtx['amount'] / COIN
        # print("Found fund_tx: ", fundtx)
        p2sh = P2SHBitcoinAddress(p2sh)
        if fundtx['address'] == p2sh:
            print("Found {0} in p2sh {1}, redeeming...".format(amount, p2sh))

            blockcount = self.bitcoind.getblockcount()
            print("\nCurrent blocknum at time of redeem on Zcash:", blockcount)
            if blockcount < int(redeemblocknum):
                print('redeemPubKey', redeemPubKey)
                zec_redeemScript = CScript(x(contract.redeemScript))
                txin = CMutableTxIn(fundtx['outpoint'])
                txout = CMutableTxOut(fundtx['amount'] - FEE, redeemPubKey.to_scriptPubKey())
                # Create the unsigned raw transaction.
                tx = CMutableTransaction([txin], [txout])
                sighash = SignatureHash(zec_redeemScript, tx, 0, SIGHASH_ALL)
                # TODO: protect privkey better, separate signing from rawtx creation
                privkey = self.bitcoind.dumpprivkey(redeemPubKey)
                sig = privkey.sign(sighash) + bytes([SIGHASH_ALL])
                preimage = secret.encode('utf-8')
                txin.scriptSig = CScript([sig, privkey.pub, preimage, OP_TRUE, zec_redeemScript])

                # print("txin.scriptSig", b2x(txin.scriptSig))
                txin_scriptPubKey = zec_redeemScript.to_p2sh_scriptPubKey()
                print('Raw redeem transaction hex: ', b2x(tx.serialize()))
                VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,))
                print("Script verified, sending raw transaction...")
                txid = self.bitcoind.sendrawtransaction(tx)
                fund_tx = str(fundtx['outpoint'])
                redeem_tx =  b2x(lx(b2x(txid)))
                return  {"redeem_tx": redeem_tx, "fund_tx": fund_tx}
            else:
                print("nLocktime exceeded, refunding")
                print('refundPubKey', refundPubKey)
                txid = self.bitcoind.sendtoaddress(refundPubKey, fundtx['amount'] - FEE)
                fund_tx = str(fundtx['outpoint'])
                refund_tx =  b2x(lx(b2x(txid)))
                return  {"refund_tx": refund_tx, "fund_tx": fund_tx}
        else:
            print("No contract for this p2sh found in database", p2sh)
    def test_fundrawtransaction_hex_hash(self):
        unfunded_transaction = CMutableTransaction([], [make_txout() for x in range(0, 5)])
        proxy = FakeBitcoinProxy()

        funded_transaction_hex = proxy.fundrawtransaction(b2x(unfunded_transaction.serialize()))["hex"]
        funded_transaction = CMutableTransaction.deserialize(x(funded_transaction_hex))

        self.assertTrue(unfunded_transaction is not funded_transaction)
        self.assertEqual(type(funded_transaction), type(unfunded_transaction))
        self.assertNotEqual(len(funded_transaction.vin), 0)
        self.assertTrue(len(funded_transaction.vin) > len(unfunded_transaction.vin))
        self.assertEqual(type(funded_transaction.vin[0]), CTxIn)
Exemplo n.º 19
0
    def from_utxo(txid_in: str,
                  tx_index_in: int,
                  sats: int,
                  privkey: str,
                  fee: int,
                  local_node_privkey: str,
                  local_funding_privkey: str,
                  remote_node_privkey: str,
                  remote_funding_privkey: str,
                  chain_hash: str = regtest_hash) -> Tuple['Funding', str]:
        """Make a funding transaction by spending this utxo using privkey: return Funding, tx."""

        # Create dummy one to start: we will fill in txid at the end.
        funding = Funding('', 0, sats - fee, local_node_privkey,
                          local_funding_privkey, remote_node_privkey,
                          remote_funding_privkey, chain_hash)

        # input private key.
        inkey = privkey_expand(privkey)
        inkey_pub = coincurve.PublicKey.from_secret(inkey.secret)

        # use RBF'able input (requirement for dual-funded things)
        txin = CTxIn(COutPoint(bytes.fromhex(txid_in), tx_index_in),
                     nSequence=0xFFFFFFFD)
        txout = CTxOut(
            sats - fee,
            CScript([script.OP_0,
                     sha256(funding.redeemscript()).digest()]))
        tx = CMutableTransaction([txin], [txout],
                                 nVersion=2,
                                 nLockTime=funding.locktime)

        # now fill in funding txid.
        funding.txid = tx.GetTxid().hex()
        funding.tx = tx

        # while we're here, sign the transaction.
        address = P2WPKHBitcoinAddress.from_scriptPubKey(
            CScript([script.OP_0, Hash160(inkey_pub.format())]))

        sighash = script.SignatureHash(address.to_redeemScript(),
                                       tx,
                                       0,
                                       script.SIGHASH_ALL,
                                       amount=sats,
                                       sigversion=script.SIGVERSION_WITNESS_V0)
        sig = inkey.sign(sighash, hasher=None) + bytes([script.SIGHASH_ALL])

        tx.wit = CTxWitness(
            [CTxInWitness(CScriptWitness([sig, inkey_pub.format()]))])
        return funding, tx.serialize().hex()
Exemplo n.º 20
0
def get_unsigned_tx(funding_tx,
                    redeem_script,
                    address,
                    amount,
                    lock_time=0,
                    n_sequence=0,
                    vout=0):
    """
    Returns a raw transaction and it's signature hash
    that pays to address from funding_tx

    Arguments:
        funding_tx (str): the 'input' tx
        redeem_script (str): The redeem script
        address (str): The output address that would receive `amount`
        lock_time (int, optional): The time the tx should be locked to
        n_sequence (int, optional): The sequence number to use in tx
        vout (int, optional):  The index of the output point of `funding_tx`

    Returns:
        A tuple containing:
            1/ The serial tx
            2/ The tx hash
    """

    # Set P2SH funding tx in little-endian
    fx = lx(funding_tx)

    # nSequence must be any number less than 0xffffffff to enable nLockTime
    txin = CMutableTxIn(COutPoint(fx, vout), nSequence=n_sequence)

    # if(nlock_time != 0):
    #     txin = CMutableTxIn(COutPoint(fx, vout), nSequence=n_sequence)
    # else:
    #     txin = CMutableTxIn(COutPoint(fx, vout))

    # Convert amount to Satoshi's
    amount *= COIN

    # Create the txout to address
    script_pubkey = CBitcoinAddress(address).to_scriptPubKey()
    txout = CMutableTxOut(amount, script_pubkey)

    # Create the unsigned transaction.
    tx = CMutableTransaction([txin], [txout], nLockTime=lock_time)

    # Calculte TX sig hash
    sighash = SignatureHash(CScript(redeem_script), tx, 0, SIGHASH_ALL)

    return (tx.serialize(), sighash)
Exemplo n.º 21
0
def _build_certificate_transactions(wallet, issuing_address,
                                    revocation_address, certificate_metadata,
                                    fees, tail):
    """Make transactions for the certificates.
    """
    logging.info('Creating tx of certificate for recipient uid: %s ...',
                 certificate_metadata.uid)

    with open(certificate_metadata.certificate_hash_file_name,
              'rb') as in_file:
        # this is the recipient-specific hash that will be recorded on the
        # blockchain
        hashed_certificate = in_file.read()
        cert_out = CMutableTxOut(0, CScript([OP_RETURN, hashed_certificate]))

        # send a transaction to the recipient's public key, and to a revocation
        # address
        txouts = create_recipient_outputs(certificate_metadata.pubkey,
                                          revocation_address,
                                          fees.min_per_output)

        # define transaction inputs
        unspent_outputs = wallet.get_unspent_outputs(issuing_address)
        last_input = unspent_outputs[tail]

        txins = [CTxIn(last_input.outpoint)]
        value_in = last_input.amount

        # very important! If we don't send the excess change back to ourselves,
        # some lucky miner gets it!
        amount = value_in - fees.cost_per_transaction
        if amount > 0:
            change_out = create_transaction_output(issuing_address, amount)
            txouts = txouts + [change_out]

        txouts = txouts + [cert_out]
        tx = CMutableTransaction(txins, txouts)

        # this is the transaction for a recipient, unsigned
        hextx = hexlify(tx.serialize())
        with open(certificate_metadata.unsigned_tx_file_name,
                  'wb') as out_file:
            out_file.write(bytes(hextx, 'utf-8'))

        logging.info('Created unsigned tx for recipient; last_input=%s',
                     last_input)
        return last_input
Exemplo n.º 22
0
    def get_tx(self,
               redeem_script,
               address,
               amount,
               funding_tx,
               lock_time=0,
               vout=0):
        '''
               Returns a raw transaction and it's signature hash
               that pays to address from funding_tx

               Options:
               vout -> which vout of funding_tx
               nLockTime -> set's transaction locktime
        '''

        # Set P2SH funding tx in little-endian
        fx = lx(funding_tx)

        if lock_time > 0:
            nlock_time = lock_time
        else:
            nlock_time = 0

        # nSequence must be any number less than 0xffffffff to enable nLockTime
        if (nlock_time != 0):
            txin = CMutableTxIn(COutPoint(fx, vout), nSequence=0)
        else:
            txin = CMutableTxIn(COutPoint(fx, vout))

        # Convert amount to Satoshi's
        amount *= COIN

        # Create the txout to address
        script_pubkey = CBitcoinAddress(address).to_scriptPubKey()
        txout = CMutableTxOut(amount, script_pubkey)

        # Create the unsigned transaction.
        tx = CMutableTransaction([txin], [txout], nLockTime=nlock_time)

        # Calculte TX sig hash
        sighash = SignatureHash(CScript(redeem_script), tx, 0, SIGHASH_ALL)

        self.logger.info("get_tx: TX SIGHASH is %s", b2x(sighash))

        return (tx.serialize(), sighash)
Exemplo n.º 23
0
def maketx(tx):
    #txid from blockr. bitcoind does not support tx index!
    txid = lx(tx)
    vout = 0

    outp = COutPoint(txid, vout)
    print("output: %s" % outp)
    # Create the txin structure, which includes the outpoint
    txin = CMutableTxIn(outp)
    print(txin)

    txin_scriptPubKey = CScript(
        [OP_DUP, OP_HASH160,
         Hash160(seckey.pub), OP_EQUALVERIFY, OP_CHECKSIG])

    print(txin_scriptPubKey)

    amount = 0.001 * COIN
    txout = CMutableTxOut(amount, CBitcoinAddress(a).to_scriptPubKey())

    print(txout)

    # Create the unsigned transaction.
    newtx = CMutableTransaction([txin], [txout])
    print(newtx)

    sighash = SignatureHash(txin_scriptPubKey, newtx, 0, SIGHASH_ALL)
    print(sighash)

    # Now sign it. We have to append the type of signature we want to the end, in
    # this case the usual SIGHASH_ALL.
    sig = seckey.sign(sighash) + bytes([SIGHASH_ALL])
    print(sig)

    # Set the scriptSig of our transaction input appropriately.
    txin.scriptSig = CScript([sig, seckey.pub])

    try:
        VerifyScript(txin.scriptSig, txin_scriptPubKey, newtx, 0,
                     (SCRIPT_VERIFY_P2SH, ))
    except:
        pass

    print('*' * 20)
    print(b2x(newtx.serialize()))
    """
Exemplo n.º 24
0
def partial_spend_p2sh_mediator_2 (redeemScript,txins_str,amount,daddr,rein):
    txin_redeemScript = CScript(x(redeemScript))
    txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey()
    txins_obj = []
    for txin_str in txins_str.split():
        txin_list = txin_str.split("-")
        txins_obj.append(CMutableTxIn(COutPoint(lx(txin_list[0]),int(txin_list[1]))))
    txout = CMutableTxOut(amount*COIN,CBitcoinAddress(daddr).to_scriptPubKey())
    tx = CMutableTransaction(txins_obj,[txout])
    seckey = CBitcoinSecret(rein.user.dkey)
    ntxins = len(txins_obj)
    for i in range(0,ntxins):
        sighash = SignatureHash(txin_redeemScript,tx,i,SIGHASH_ALL)
        sig = seckey.sign(sighash)+x("01")
        txins_obj[i].scriptSig = CScript([OP_0, sig, txin_redeemScript])
        #VerifyScript(txins_obj[i].scriptSig, txin_scriptPubKey, tx, i, (SCRIPT_VERIFY_P2SH,))
    tx_bytes = tx.serialize()
    return b2x(tx_bytes)
Exemplo n.º 25
0
def maketx(tx):
    #txid from blockr. bitcoind does not support tx index!
    txid = lx(tx)
    vout = 0

    outp = COutPoint(txid, vout)
    print ("output: %s"%outp)
    # Create the txin structure, which includes the outpoint
    txin = CMutableTxIn(outp)
    print (txin)

    txin_scriptPubKey = CScript([OP_DUP, OP_HASH160, Hash160(seckey.pub), OP_EQUALVERIFY, OP_CHECKSIG])

    print (txin_scriptPubKey)

    amount = 0.001*COIN
    txout = CMutableTxOut(amount, CBitcoinAddress(a).to_scriptPubKey())

    print (txout)

    # Create the unsigned transaction.
    newtx = CMutableTransaction([txin], [txout])
    print (newtx)

    sighash = SignatureHash(txin_scriptPubKey, newtx, 0, SIGHASH_ALL)
    print (sighash)

    # Now sign it. We have to append the type of signature we want to the end, in
    # this case the usual SIGHASH_ALL.
    sig = seckey.sign(sighash) + bytes([SIGHASH_ALL])
    print (sig)

    # Set the scriptSig of our transaction input appropriately.
    txin.scriptSig = CScript([sig, seckey.pub])

    try:
        VerifyScript(txin.scriptSig, txin_scriptPubKey, newtx, 0, (SCRIPT_VERIFY_P2SH,))
    except:
        pass

    print ('*'*20)
    print(b2x(newtx.serialize()))

    """
Exemplo n.º 26
0
def test_create_transaction_object_2(inputs_2, outputs_2):
    r = PaymentService.create_transaction_object(inputs=inputs_2, outputs=outputs_2)

    tx_in: List[CMutableTxIn] = [
        CMutableTxIn(COutPoint(lx('4521418569de2f78d5d2d3c535567ac9c48c95314c53a67788d4dcdc9a8d915b'), 0)),
        CMutableTxIn(COutPoint(lx('0bb4abea99101197cf2ddf43a2af1e73f868887d5f4a3619241cbb67413a34e7'), 0)),
    ]

    pk1 = CBitcoinAddress('34s7MXyL5sEbgsto6SRdvV3YYUu8XVs4xg').to_scriptPubKey()
    pk2 = CBitcoinAddress('16moGJwkzWhNC1pfnfJptKj9G1ogQz16xd').to_scriptPubKey()
    pk3 = CBitcoinAddress('17A16QmavnUfCW11DAApiJxp7ARnxN5pGX').to_scriptPubKey()
    tx_out: List[CMutableTxOut] = [
        CMutableTxOut(100000, pk1),
        CMutableTxOut(2000, pk2),
        CMutableTxOut(20000000, pk3),
    ]

    expected = CMutableTransaction(tx_in, tx_out)
    assert b2x(r.serialize()) == b2x(expected.serialize())
Exemplo n.º 27
0
def _build_certificate_transactions(wallet, issuing_address, revocation_address, certificate_metadata, fees, tail):
    """Make transactions for the certificates.
    """
    logging.info('Creating tx of certificate for recipient uid: %s ...',
                 certificate_metadata.uid)

    with open(certificate_metadata.certificate_hash_file_name, 'rb') as in_file:
        # this is the recipient-specific hash that will be recorded on the
        # blockchain
        hashed_certificate = in_file.read()
        cert_out = CMutableTxOut(0, CScript([OP_RETURN, hashed_certificate]))

        # send a transaction to the recipient's public key, and to a revocation
        # address
        txouts = create_recipient_outputs(
            certificate_metadata.pubkey, revocation_address, fees.min_per_output)

        # define transaction inputs
        unspent_outputs = wallet.get_unspent_outputs(issuing_address)
        last_input = unspent_outputs[tail]

        txins = [CTxIn(last_input.outpoint)]
        value_in = last_input.amount

        # very important! If we don't send the excess change back to ourselves,
        # some lucky miner gets it!
        amount = value_in - fees.cost_per_transaction
        if amount > 0:
            change_out = create_transaction_output(issuing_address, amount)
            txouts = txouts + [change_out]

        txouts = txouts + [cert_out]
        tx = CMutableTransaction(txins, txouts)

        # this is the transaction for a recipient, unsigned
        hextx = hexlify(tx.serialize())
        with open(certificate_metadata.unsigned_tx_file_name, 'wb') as out_file:
            out_file.write(bytes(hextx, 'utf-8'))

        logging.info(
            'Created unsigned tx for recipient; last_input=%s', last_input)
        return last_input
Exemplo n.º 28
0
    def generate_tx(self):
        tx_chain = self.get_next_tx_chain()
        txid = lx(tx_chain.current_unspent_tx)
        txins = [
            CMutableTxIn(COutPoint(txid, 0)),
            CMutableTxIn(COutPoint(txid, 1))
        ]
        txin_seckeys = [tx_chain.seckey, self._spent_to.seckey]

        amount_in = tx_chain.amount
        tx_chain.amount -= int(config.transaction_fee / 2)

        txout1 = CMutableTxOut(
            tx_chain.amount,
            CBitcoinAddress(tx_chain.address).to_scriptPubKey())
        txout2 = CMutableTxOut(
            tx_chain.amount,
            CBitcoinAddress(self._spent_to.address).to_scriptPubKey())

        tx = CMutableTransaction(txins, [txout1, txout2], nVersion=2)

        for i, txin in enumerate(txins):
            txin_scriptPubKey = CScript([
                OP_DUP, OP_HASH160,
                Hash160(txin_seckeys[i].pub), OP_EQUALVERIFY, OP_CHECKSIG
            ])
            sighash = SignatureHash(txin_scriptPubKey, tx, i, SIGHASH_ALL)
            sig = txin_seckeys[i].sign(sighash) + bytes([SIGHASH_ALL])
            txin.scriptSig = CScript([sig, txin_seckeys[i].pub])

        tx_serialized = tx.serialize()
        logging.debug('{} trying to sendrawtransaction'
                      ' (in=2x{} out=2x{} fee={} bytes={})'
                      ' using tx_chain number={}'.format(
                          self._name, amount_in, txout1.nValue,
                          (amount_in * 2) - (txout1.nValue * 2),
                          len(tx_serialized), self._current_tx_chain_index))
        tx_hash = self.execute_rpc('sendrawtransaction', b2x(tx_serialized))
        tx_chain.current_unspent_tx = tx_hash
        logging.info(
            '{} sendrawtransaction was successful; tx got hash={}'.format(
                self._name, tx_hash))
Exemplo n.º 29
0
def make_signed_tx(ins, outs, priv):
    print('####### in make_signed_tx #######')
    print('ins: {}'.format(ins))
    print('outs: {}'.format(outs))
    print('priv: {}'.format(priv))
    txins = []
    txouts = []
    txin_scriptPubKeys = []
    # txin_scriptPubKeys = []
    for i, inp in enumerate(ins):
        print('inp[tx_id]: {}'.format(inp['tx_id']))
        txin = CMutableTxIn(COutPoint(lx(inp['tx_id']), inp['index']))
        seckey = CBitcoinSecret.from_secret_bytes(
            pygcoinlib.script_to_address(inp['script']).encode('utf-8'))
        txin_scriptPubKeys.append(
            CScript([
                OP_DUP, OP_HASH160,
                Hash160(seckey.pub), OP_EQUALVERIFY, OP_CHECKSIG
            ]))
        # txin_scriptPubKeys.append(CScript([OP_DUP, OP_HASH160, Hash160(seckey.pub), OP_EQUALVERIFY, OP_CHECKSIG]))
        txins.append(txin)
    for o, out in enumerate(outs):
        # print('out[\'address\']: {}'.format(out['address']))
        if 'script' in out:
            # txouts.append(CMutableTxOut(0, CScript([bytes(out['script'], encoding='UTF-8')]), 2))
            print('song')
        else:
            txouts.append(
                CMutableTxOut(
                    out['value'],
                    CBitcoinAddress(out['address']).to_scriptPubKey(),
                    out['color']))
        # print('address: {}'.format(pygcoinlib.script_to_address(spk['script'])))
    tx = CMutableTransaction(txins, txouts)
    for i, inp in enumerate(ins):
        sighash = SignatureHash(txin_scriptPubKeys[i], tx, i, SIGHASH_ALL)
        sig = seckey.sign(sighash) + bytes([SIGHASH_ALL])
        txins[i].scriptSig = CScript([sig, seckey.pub])
        VerifyScript(txins[i].scriptSig, txin_scriptPubKeys[i], tx, i,
                     (SCRIPT_VERIFY_P2SH, ))
    return b2x(tx.serialize())
Exemplo n.º 30
0
# Create the txout. This time we create the scriptPubKey from a Bitcoin
# address.
txout = CMutableTxOut(0.0005*COIN, CBitcoinAddress('323uf9MgLaSn9T7vDaK1cGAZ2qpvYUuqSp').to_scriptPubKey())

# Create the unsigned transaction.
tx = CMutableTransaction([txin], [txout])

# Calculate the signature hash for that transaction. Note how the script we use
# is the redeemScript, not the scriptPubKey. That's because when the CHECKSIG
# operation happens EvalScript() will be evaluating the redeemScript, so the
# corresponding SignatureHash() function will use that same script when it
# replaces the scriptSig in the transaction being hashed with the script being
# executed.
sighash = SignatureHash(txin_redeemScript, tx, 0, SIGHASH_ALL)

# Now sign it. We have to append the type of signature we want to the end, in
# this case the usual SIGHASH_ALL.
sig = seckey.sign(sighash) + bytes([SIGHASH_ALL])

# Set the scriptSig of our transaction input appropriately.
txin.scriptSig = CScript([sig, txin_redeemScript])

# Verify the signature worked. This calls EvalScript() and actually executes
# the opcodes in the scripts to see if everything worked out. If it doesn't an
# exception will be raised.
VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,))

# Done! Print the transaction to standard output with the bytes-to-hex
# function.
print(b2x(tx.serialize()))
    def transfer(self,
                 src_addrs_key_map: OrderedDict,
                 dst_addrs_amount_map: dict,
                 txfee: Decimal,
                 auto_calc_pay_back: bool,
                 pay_back_index: int = 0xfffffff,
                 ensure_one_txout: bool = False) -> str:
        """

        :param src_addrs_key_map: {'addr1': 'privkey1', 'addr2': 'privkey2'  }   私钥为  hex字符串
        :param dst_addrs_amount_map: {'addr1':Decimal(0.1234), 'addr2':Deciaml(0.234) }
        :param txfee:  矿工费
        :param auto_calc_pay_back: 是否自动计算并找零
        :param pay_back_index: 找零地址索引  即在 src_addrs_key_map 中的索引
        :param ensure_one_txout:   确认只有一个交易输出(比如: 提币不需要找零的情况, 归集)
        :return: txid
        """
        #仅支持 P2PKH 类型的from地址

        assert isinstance(src_addrs_key_map,
                          OrderedDict), 'src_addrs_key_map is not OrderedDict'
        assert isinstance(dst_addrs_amount_map,
                          dict), 'dst_addrs_amount_map is not dict'
        assert Decimal('0.00001') <= txfee <= Decimal(
            '0.001'), 'invalid txfee, please check txfee'
        assert len(
            src_addrs_key_map) >= 1, 'src_addrs_key_map length must >= 1'
        assert  not (True == auto_calc_pay_back  == ensure_one_txout) , \
                'True == auto_calc_pay_back  == ensure_one_txout , must be mutex '

        if ensure_one_txout:
            assert (len(dst_addrs_amount_map) == 1
                    ), 'dst_addrs_amount_map length must equal 1'
        elif not auto_calc_pay_back:
            assert (len(dst_addrs_amount_map) >=
                    1), 'dst_addrs_amount_map length must >= 2'

        if auto_calc_pay_back and pay_back_index >= len(src_addrs_key_map):
            raise Exception('pay_back_index is to large')

        self.logger.info(
            f'dst_addrs_amount_map is { json.dumps(dst_addrs_amount_map, indent=4, default=decimal_default) }'
        )

        assert self.ping() == True, 'bitcoind rpc is gone'

        total_amount = sum(dst_addrs_amount_map.values()) + txfee
        self.logger.info(f'total_amount is {total_amount}')

        source_addrs = list(src_addrs_key_map.keys())  #WARNING: 禁止打印私钥!!!

        is_enough, founded_utxos = self.search_utxo(addrs=source_addrs,
                                                    total_amount=total_amount)
        if not is_enough:
            msg = 'balance is not enough'
            self.logger.error(msg)
            raise Exception(msg)

        self.logger.info(
            f'founded_utxos is { json.dumps(founded_utxos, indent=4, default=decimal_default) }'
        )

        #设置全局变量
        SelectParams(self.net_type)

        #构造inputs
        txins = []
        utxo_owner_map = dict()
        for addr, utxos in founded_utxos.items():

            assert addr in src_addrs_key_map, 'addr is not in src_addrs_key_map'

            for utxo in utxos:
                txin = CMutableTxIn(
                    prevout=COutPoint(hash=lx(utxo['txid']), n=utxo['vout']))
                txins.append(txin)

                #因为顺序不会被打乱, 所以可以直接使用 索引进行对应
                utxo_owner_map[len(txins) - 1] = addr

        #构造outputs
        txouts = []
        for to_addr, amount in dst_addrs_amount_map.items():
            out = CMutableTxOut(
                nValue=amount * COIN,
                scriptPubKey=CBitcoinAddress(to_addr).to_scriptPubKey())
            txouts.append(out)

        #自动结算
        if auto_calc_pay_back:
            sum_in_satoshi = 0
            for addr, utxos in founded_utxos.items():
                for utxo in utxos:
                    sum_in_satoshi += utxo['value']
            pay_back_in_satoshi = int(sum_in_satoshi -
                                      int(total_amount * COIN))

            #判断找零的金额, 如果太小就不要了, 作为矿工费
            if pay_back_in_satoshi >= MIN_AVAILABLE_UTXO_VALUE_IN_SATOSHI:
                pay_back_addr = list(src_addrs_key_map.keys())[pay_back_index]
                pay_back_out = CMutableTxOut(
                    nValue=pay_back_in_satoshi,
                    scriptPubKey=CBitcoinAddress(
                        pay_back_addr).to_scriptPubKey())
                txouts.append(pay_back_out)

        muttx = CMutableTransaction(vin=txins, vout=txouts)

        #对每个 input 进行签名
        for n in range(len(txins)):

            #查找这个utxo属于哪个地址
            owner_addr = utxo_owner_map[n]
            privkey = src_addrs_key_map[owner_addr]

            if len(privkey) == 64:  # hex
                wif_key = PrivKeyToWIFCompress(privkey,
                                               self.net_type != 'mainnet')
                seckey = CBitcoinSecret(s=wif_key)
            elif len(privkey) == 52:  #base58格式
                seckey = CBitcoinSecret(s=privkey)
            else:
                raise Exception("invalid privkey")

            txin_script_pubkey = CScript([
                OP_DUP, OP_HASH160,
                Hash160(seckey.pub), OP_EQUALVERIFY, OP_CHECKSIG
            ])
            sig_hash = SignatureHash(txin_script_pubkey, muttx, n, SIGHASH_ALL)
            sig = seckey.sign(sig_hash) + bytes([SIGHASH_ALL])
            muttx.vin[n].scriptSig = CScript([sig, seckey.pub])

            #TODO: 处理验签失败抛异常
            VerifyScript(muttx.vin[n].scriptSig, txin_script_pubkey, muttx, n,
                         (SCRIPT_VERIFY_P2SH, ))
            pass

        raw_tx_hex = b2x(muttx.serialize())
        self.logger.info(f'raw_tx_hex is: {raw_tx_hex}')

        # local_tx_hash = muttx.GetTxid()
        # self.logger.info(f'local_tx_hash is: {b2x(local_tx_hash)}')

        #广播交易
        assert self.ping(
        ) == True, 'bitcoind rpc is gone'  #测试 bitcoind的 rpc服务是否还在
        txid = self.send_raw_tx(raw_tx_hex=raw_tx_hex)
        self.logger.info(f'send_raw_tx txid is: {txid}')

        return txid
Exemplo n.º 32
0
class BitcoinTransaction(object):
    '''Bitcoin transaction object.'''
    @auto_switch_params(1)
    def __init__(self,
                 network,
                 recipient_address: str,
                 value: float,
                 solvable_utxo: list,
                 tx_locktime: int = 0):
        self.recipient_address = recipient_address
        self.value = value
        self.network = network
        self.symbol = network.default_symbol

        self.validate_address()

        self.solvable_utxo = solvable_utxo
        self.utxo_value = sum(utxo.value for utxo in self.solvable_utxo)
        self.tx_in_list = [utxo.tx_in for utxo in self.solvable_utxo]
        self.tx_out_list = []

        self.tx = None
        self.tx_locktime = tx_locktime
        self.fee = 0.0
        self.fee_per_kb = 0.0
        self.signed = False

    def validate_address(self):
        if not self.network.is_valid_address(self.recipient_address):
            raise ValueError('Given recipient address is invalid.')

    def build_outputs(self):
        self.tx_out_list = [
            CMutableTxOut(
                to_base_units(self.value),
                CBitcoinAddress(self.recipient_address).to_scriptPubKey())
        ]

    def add_fee_and_sign(self, default_wallet=None):
        """Signing transaction and adding fee under the hood."""

        # signing the transaction for the first time to get the right transaction size
        self.sign(default_wallet)

        # adding fee based on transaction size (this will modify the transaction)
        self.add_fee()

        # signing the modified transaction
        self.sign(default_wallet)

    def sign(self, default_wallet: BitcoinWallet = None):
        """Signing transaction using the wallet object."""

        for tx_index, tx_in in enumerate(self.tx.vin):
            utxo = self.solvable_utxo[tx_index]
            wallet = utxo.wallet or default_wallet

            if wallet is None:
                raise RuntimeError('Cannot sign transaction without a wallet.')

            tx_script = utxo.parsed_script
            if utxo.contract:
                sig_hash = script.SignatureHash(
                    script.CScript.fromhex(utxo.contract), self.tx, tx_index,
                    script.SIGHASH_ALL)
            else:
                sig_hash = script.SignatureHash(tx_script, self.tx, tx_index,
                                                script.SIGHASH_ALL)
            sig = wallet.private_key.sign(sig_hash) + struct.pack(
                '<B', script.SIGHASH_ALL)
            script_sig = [sig, wallet.private_key.pub
                          ] + utxo.unsigned_script_sig
            tx_in.scriptSig = script.CScript(script_sig)

            VerifyScript(tx_in.scriptSig, tx_script, self.tx, tx_index,
                         (SCRIPT_VERIFY_P2SH, ))
        self.signed = True

    def create_unsigned_transaction(self):
        assert self.utxo_value >= self.value, 'You want to spend more than you\'ve got. Add more UTXO\'s.'
        self.build_outputs()
        self.tx = CMutableTransaction(self.tx_in_list,
                                      self.tx_out_list,
                                      nLockTime=self.tx_locktime)

    def publish(self):
        return self.network.publish(self.raw_transaction)

    @property
    def size(self) -> int:
        """Returns the size of a transaction represented in bytes."""
        return len(self.tx.serialize())

    def calculate_fee(self, add_sig_size=False):
        """Calculating fee for given transaction based on transaction size and estimated fee per kb."""
        if not self.fee_per_kb:
            self.fee_per_kb = self.network.get_current_fee_per_kb()
        size = self.size
        if add_sig_size:
            size += len(self.tx_in_list) * SIGNATURE_SIZE
        self.fee = round((self.fee_per_kb / 1000) * size, 8)

    def add_fee(self):
        """Adding fee to the transaction by decreasing 'change' transaction."""
        if not self.fee:
            self.calculate_fee()
        fee_in_satoshi = to_base_units(self.fee)
        if self.tx.vout[0].nValue < fee_in_satoshi:
            raise RuntimeError(
                'Cannot subtract fee from transaction. You need to add more input transactions.'
            )
        self.tx.vout[0].nValue -= fee_in_satoshi

    @property
    def raw_transaction(self):
        return b2x(self.tx.serialize())

    @property
    def address(self):
        return b2lx(self.tx.GetHash())

    def show_details(self):
        details = {
            'transaction': self.raw_transaction,
            'transaction_address': self.address,
            'fee': self.fee,
            'fee_per_kb': self.fee_per_kb,
            'fee_per_kb_text': f'{self.fee_per_kb:.8f} {self.symbol} / 1 kB',
            'fee_text': f'{self.fee:.8f} {self.symbol}',
            'recipient_address': self.recipient_address,
            'size': self.size,
            'size_text': f'{self.size} bytes',
            'value': self.value,
            'value_text': f'{self.value:.8f} {self.symbol}',
        }
        if self.signed:
            details['transaction_link'] = self.network.get_transaction_url(
                self.address)
        return details

    def get_transaction_url(self) -> Optional[str]:
        '''Wrapper around the `get_transaction_url` method from base network.'''
        if not self.tx:
            return
        return self.network.get_transaction_url(self.address)
Exemplo n.º 33
0
            CScript([1, x('0378d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71'),
                        b'\x00'*33,
                     2, OP_CHECKMULTISIG]))
    tx.vout.append(multisig_txout)

for bad_addr in args.bad_addr:
    bad_addr = CBitcoinAddress(bad_addr)
    txout = CMutableTxOut(args.dust, bad_addr.to_scriptPubKey())
    tx.vout.append(txout)


# Add inputs until we meet the fee1 threshold
unspent = sorted(rpc.listunspent(1), key=lambda x: x['amount'])
value_in = 0
value_out = sum([vout.nValue for vout in tx.vout])
while (value_in - value_out) / len(tx.serialize()) < feeperbyte1:
    # What's the delta fee that we need to get to our desired fees per byte at
    # the current tx size?
    delta_fee = math.ceil((feeperbyte1 * len(tx.serialize())) - (value_in - value_out))

    logging.debug('Delta fee: %s' % str_money_value(delta_fee))

    # If we simply subtract that from the change outpoint are we still above
    # the dust threshold?
    if change_txout.nValue - delta_fee > args.dust:
        change_txout.nValue -= delta_fee
        value_out -= delta_fee

    # Do we need to add another input?
    if value_in - value_out < 0:
        new_outpoint = unspent[-1]['outpoint']
Exemplo n.º 34
0
def test_unvault_txout(bitcoind):
    """Test that unvault_txout() produces a valid and conform txo.

    Note that we use python-bitcoinlib for this one, as
    signrawtransactionwithkey is (apparently?) not happy dealing with exotic
    scripts.
    Note also that bitcoinlib's API uses sats, while bitcoind's one uses BTC..
    """
    amount = 50 * COIN - 500
    # The stakeholders
    stk_privkeys = [CKey(os.urandom(32)) for i in range(4)]
    stk_pubkeys = [k.pub for k in stk_privkeys]
    # The cosigning server
    serv_privkey = CKey(os.urandom(32))
    # First, pay to the unvault tx script
    txo = unvault_txout(stk_pubkeys,
                        serv_privkey.pub, amount)
    txo_addr = str(CBitcoinAddress.from_scriptPubKey(txo.scriptPubKey))
    amount_for_bitcoind = float(Decimal(amount) / Decimal(COIN))
    txid = bitcoind.pay_to(txo_addr, amount_for_bitcoind)
    # We can spend it immediately if all stakeholders sign (emergency or cancel
    # tx)
    txin = CTxIn(COutPoint(lx(txid), 0))
    amount_min_fees = amount - 500
    addr = bitcoind.getnewaddress()
    new_txo = CTxOut(amount_min_fees,
                     CBitcoinAddress(addr).to_scriptPubKey())
    tx = CMutableTransaction([txin], [new_txo], nVersion=2)
    # We can't test the signing against bitcoind, but we can at least test the
    # transaction format
    bitcoind_tx = bitcoind.rpc.createrawtransaction([
        {"txid": txid, "vout": 0}
    ], [
        {addr: float(Decimal(amount_min_fees) / Decimal(COIN))}
    ])
    assert b2x(tx.serialize()) == bitcoind_tx
    tx_hash = SignatureHash(unvault_script(*stk_pubkeys, serv_privkey.pub), tx,
                            0, SIGHASH_ALL, amount, SIGVERSION_WITNESS_V0)
    sigs = [key.sign(tx_hash) + bytes([SIGHASH_ALL])
            for key in stk_privkeys[::-1]]  # Note the reverse here
    witness_script = [*sigs,
                      unvault_script(*stk_pubkeys, serv_privkey.pub)]
    witness = CTxInWitness(CScriptWitness(witness_script))
    tx.wit = CTxWitness([witness])
    bitcoind.send_tx(b2x(tx.serialize()))
    assert bitcoind.has_utxo(addr)

    # If two out of three stakeholders sign, we need the signature from the
    # cosicosigning server and we can't spend it before 6 blocks (csv).
    # Pay back to the unvault tx script
    txo = unvault_txout(stk_pubkeys,
                        serv_privkey.pub, amount)
    txo_addr = str(CBitcoinAddress.from_scriptPubKey(txo.scriptPubKey))
    txid = bitcoind.pay_to(txo_addr, amount_for_bitcoind)
    # Reconstruct the transaction but with only two stakeholders signatures
    txin = CTxIn(COutPoint(lx(txid), 0), nSequence=6)
    amount_min_fees = amount - 500
    addr = bitcoind.getnewaddress()
    new_txo = CTxOut(amount_min_fees,
                     CBitcoinAddress(addr).to_scriptPubKey())
    tx = CMutableTransaction([txin], [new_txo], nVersion=2)
    # We can't test the signing against bitcoind, but we can at least test the
    # transaction format
    bitcoind_tx = bitcoind.rpc.createrawtransaction([
        {"txid": txid, "vout": 0, "sequence": 6}
    ], [
        {addr: float(Decimal(amount_min_fees) / Decimal(COIN))}
    ])
    assert b2x(tx.serialize()) == bitcoind_tx
    tx_hash = SignatureHash(unvault_script(*stk_pubkeys, serv_privkey.pub), tx,
                            0, SIGHASH_ALL, amount, SIGVERSION_WITNESS_V0)
    # The cosigning server
    sigs = [serv_privkey.sign(tx_hash) + bytes([SIGHASH_ALL])]
    # We fail the third CHECKSIG !!
    sigs += [empty_signature()]
    sigs += [key.sign(tx_hash) + bytes([SIGHASH_ALL])
             for key in stk_privkeys[::-1][2:]]  # Just the first two
    witness_script = [*sigs,
                      unvault_script(*stk_pubkeys, serv_privkey.pub)]
    witness = CTxInWitness(CScriptWitness(witness_script))
    tx.wit = CTxWitness([witness])
    # Relative locktime !
    for i in range(5):
        with pytest.raises(VerifyRejectedError, match="non-BIP68-final"):
            bitcoind.send_tx(b2x(tx.serialize()))
        bitcoind.generate_block(1)
    # It's been 6 blocks now
    bitcoind.send_tx(b2x(tx.serialize()))
    assert bitcoind.has_utxo(addr)
Exemplo n.º 35
0
  def test_send_script_spend(self):
    """
    Run more in-depth execution checks on the script generated for the send transaction
    """
    sender_private_key = CBitcoinSecret.from_secret_bytes(x('4f65da9b656de4036076911707d2b2dbf065689245b8674faa8790e36d7e5850'))
    sender_public_key = sender_private_key.pub
    recipient_private_key = CBitcoinSecret.from_secret_bytes(x('cfe8e33672f7045f020210f3c7afbca660e053e4c9415c542ff185e97b175cf0'))
    recipient_public_key = recipient_private_key.pub
    secret = x('88d6e51f777b0b8dc0f429da9f372fbc')
    secret_hash = Hash(secret)
    send_to_key = CBitcoinSecret.from_secret_bytes(x('15a249b4c09286b877d4708191f1ee8de09903bae034dd9dc8e3286451fa1c80'))
    send_to_address = P2PKHBitcoinAddress.from_pubkey(send_to_key.pub)
    random_tx_id = x('8390b4c8198198c6447da1a6fad498209436a785459936b95a1e3b63618c1d8a')
    value = 10 * COIN

    send_tx_script_pub_key = build_send_out_script(sender_public_key, recipient_public_key, secret_hash)

    send_txins = [CMutableTxIn(COutPoint(random_tx_id, 0))]
    send_txouts = [CMutableTxOut(value, send_tx_script_pub_key)]
    send_tx = CMutableTransaction(send_txins, send_txouts)

    # Test the standard spend transaction

    txins = [CMutableTxIn(COutPoint(Hash(send_tx.serialize()), 0))]
    txouts = [CMutableTxOut(value, send_to_address.to_scriptPubKey())]
    recv_tx = CMutableTransaction(txins, txouts)

    sighash = SignatureHash(send_tx_script_pub_key, recv_tx, 0, SIGHASH_ALL)
    recipient_sig = recipient_private_key.sign(sighash) + (b'\x01') # bytes([SIGHASH_ALL])
    recv_tx.vin[0].scriptSig = CScript([secret, 0, recipient_sig, recipient_public_key])

    VerifyScript(recv_tx.vin[0].scriptSig, send_tx.vout[0].scriptPubKey, recv_tx, 0, (SCRIPT_VERIFY_P2SH,))

    # Test a refund transaction
    refund_tx = CMutableTransaction(txins, txouts)

    sighash = SignatureHash(send_tx_script_pub_key, refund_tx, 0, SIGHASH_ALL)
    sender_sig = sender_private_key.sign(sighash) + (b'\x01') # bytes([SIGHASH_ALL])
    recipient_sig = recipient_private_key.sign(sighash) + (b'\x01') # bytes([SIGHASH_ALL])
    refund_tx.vin[0].scriptSig = CScript([sender_sig, sender_public_key, 1, recipient_sig, recipient_public_key])

    VerifyScript(refund_tx.vin[0].scriptSig, send_tx_script_pub_key, refund_tx, 0, (SCRIPT_VERIFY_P2SH,))

    # Test invalid transactions are rejected

    invalid_tx = CMutableTransaction(txins, txouts)

    sighash = SignatureHash(send_tx_script_pub_key, invalid_tx, 0, SIGHASH_ALL)
    sender_sig = sender_private_key.sign(sighash) + (b'\x01') # bytes([SIGHASH_ALL])
    recipient_sig = recipient_private_key.sign(sighash) + (b'\x01') # bytes([SIGHASH_ALL])

    invalid_tx.vin[0].scriptSig = CScript([])
    with self.assertRaises(MissingOpArgumentsError):
      VerifyScript(invalid_tx.vin[0].scriptSig, send_tx_script_pub_key, invalid_tx, 0, (SCRIPT_VERIFY_P2SH,))

    invalid_tx.vin[0].scriptSig = CScript([recipient_sig, recipient_public_key, 0])
    with self.assertRaises(VerifyOpFailedError):
      VerifyScript(invalid_tx.vin[0].scriptSig, send_tx_script_pub_key, invalid_tx, 0, (SCRIPT_VERIFY_P2SH,))

    invalid_tx.vin[0].scriptSig = CScript([recipient_sig, recipient_public_key, 1])
    with self.assertRaises(VerifyOpFailedError):
      VerifyScript(invalid_tx.vin[0].scriptSig, send_tx_script_pub_key, invalid_tx, 0, (SCRIPT_VERIFY_P2SH,))

    invalid_tx.vin[0].scriptSig = CScript([recipient_sig, recipient_public_key, 1, recipient_sig, recipient_public_key])
    with self.assertRaises(VerifyOpFailedError):
      VerifyScript(invalid_tx.vin[0].scriptSig, send_tx_script_pub_key, invalid_tx, 0, (SCRIPT_VERIFY_P2SH,))

    invalid_tx.vin[0].scriptSig = CScript([sender_sig, sender_public_key, 1, sender_sig, sender_public_key])
    with self.assertRaises(VerifyOpFailedError):
      VerifyScript(invalid_tx.vin[0].scriptSig, send_tx_script_pub_key, invalid_tx, 0, (SCRIPT_VERIFY_P2SH,))
Exemplo n.º 36
0
# is the redeemScript, not the scriptPubKey. That's because when the CHECKSIG
# operation happens EvalScript() will be evaluating the redeemScript, so the
# corresponding SignatureHash() function will use that same script when it
# replaces the scriptSig in the transaction being hashed with the script being
# executed.

## override module method
SignatureHash = MySignatureHash

sighash = SignatureHash(txin_redeemScript, tx, 0, SIGHASH_ALL)

# Now sign it. We have to append the type of signature we want to the end, in
# this case the usual SIGHASH_ALL.
sig = seckey.sign(sighash) + bytes([SIGHASH_ALL])

# Set the scriptSig of our transaction input appropriately.
txin.scriptSig = CScript([sig, txin_redeemScript])

# Verify the signature worked. This calls EvalScript() and actually executes
# the opcodes in the scripts to see if everything worked out. If it doesn't an
# exception will be raised.
VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,))

# Done! Print the transaction to standard output with the bytes-to-hex
# function.
print("Transaction:\n", b2x(tx.serialize()))

pycoin_tx = Tx.from_bin(tx.serialize())
print("Pycoin tx:\n", pycoin_tx.__repr__())

Exemplo n.º 37
0
def construct_signed_transaction(redeem_script: str,
                                 sig_files: List[str],
                                 inputs_file: str,
                                 outputs_file: str,
                                 testnet: bool = False) -> str:
    """
    Construct a hex-encoded serialized bitcoin transaction 
    fully-signed and ready for broadcast for a 2-of-3 P2SH-multisig
    address

    Args:
        redeem_script: hex-encoded redeem script (see generate_multisig_redeem_script.py)
        sig_files: List of 2 JSON signature files containing a public key and 
                   signatures for each UTXO (see sign_multisig_spend.py)
        inputs_file: JSON file of UTXOs to be spent (see get_utxo_set.py)
        outputs_file: JSON file of destination addresses (see generate_outputs.py)
        testnet: Is this a testnet or mainnet transaction?

    Returns:
        fully-signed hex-encoded serialized Bitcoin transaction

    Raises:
        ValueError: If sig_files doesn't have exactly 2 elements.

    Example:
        TODO
    """

    if testnet:
        SelectParams('testnet')
    else:
        SelectParams('mainnet')

    # Input validation
    if len(sig_files) != 2:
        raise ValueError("Two Signature Files are Required")

    # load inputs, outputs, and signatures
    with open(inputs_file, 'r') as f:
        inputs = json.load(f)

    with open(outputs_file, 'r') as f:
        outputs = json.load(f)

    signatures = []
    for sig_file in sig_files:
        with open(sig_file, 'r') as f:
            signatures.append(json.load(f))

    # Order Signatures
    parsed_redeem_script = btc_utils.parse_redeem_script(redeem_script)
    sig1_index = parsed_redeem_script['pubkeys'].index(signatures[0]['pubkey'])
    sig2_index = parsed_redeem_script['pubkeys'].index(signatures[1]['pubkey'])
    if sig2_index < sig1_index:
        signatures = [signatures[1], signatures[0]]

    # Construct ScriptSigs
    zipped_sigs = zip(signatures[0]['signatures'], signatures[1]['signatures'])
    scriptsigs = [
        script.CScript([
            OP_0,
            x(sig1) + bytes([SIGHASH_ALL]),
            x(sig2) + bytes([SIGHASH_ALL]),
            x(redeem_script)
        ]) for (sig1, sig2) in zipped_sigs
    ]

    # Construct Inputs List
    TxIns = []
    for input in inputs:
        txid = lx(input['txid'])
        vout = input['n']
        TxIns.append(CMutableTxIn(COutPoint(txid, vout)))

    # Insert ScriptSigs
    for i in range(len(TxIns)):
        TxIns[i].scriptSig = scriptsigs[i]

    # Construct Outputs List
    TxOuts = []
    for output in outputs:
        output_script = CBitcoinAddress(output['address']).to_scriptPubKey()
        TxOuts.append(CMutableTxOut(output['amount'], output_script))

    # Construct TX
    tx = CMutableTransaction(TxIns, TxOuts)

    return b2x(tx.serialize())