Пример #1
0
    #probably the best solution would be ammending Peter's library: script.CTxIn.stream_selialize
    #f.write(struct.pack_into(b"<I", 22,value) and add it to the CMutableTxIn. I didn't have the time
    #to experience with it.

    unspent['outpoint'] = CMutableTxIn(COutPoint(lx(unspent['txid']),
                                                 unspent['vout']),
                                       nSequence=0xefffffff)
    del unspent['txid']
    del unspent['vout']
    total_amount += unspent['amount']
    txin.append(unspent['outpoint'])

txout = []
txout.append(
    CMutableTxOut(total_amount,
                  CBitcoinAddress(P2PKH_to_address).to_scriptPubKey()))

#This is a version 2 transaction and a time locked too
tx = CMutableTransaction(txin, txout, nLockTime=delay_value, nVersion=2)

#Create the redeem script that should become part of scriptSig
txin_redeemScript = CScript([
    byte_delay, OP_NOP3, OP_DROP, OP_DUP, OP_HASH160,
    Hash160(seckey_pub), OP_EQUALVERIFY, OP_CHECKSIG
])

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

sig = CKey(x(decode_hex_priv)).sign(sighash) + bytes([SIGHASH_ALL])

#I couldn't solve this issue. Something is not right here although I followed
Пример #2
0
def build_bitcoin_tx(utxos,
                     receiver_addr,
                     amount,
                     fee,
                     key_file,
                     change_addr=None):
    sorted_utxos = utxos.sort_values(by=['block_height', 'value'],
                                     ascending=[True, False])
    total_balance = 0
    utxos_to_spend = []
    for i, utxo in sorted_utxos.iterrows():
        if total_balance >= amount + fee:
            break

        balance = utxo['value']
        utxos_to_spend.append({
            'address': utxo['address'],
            'txHash': utxo['tx_hash'],
            'blockHeight': int(utxo['block_height']),
            'outputIdx': int(utxo['tx_output_n']),
            'value': int(utxo['value']),
            'sigScript': utxo['script']
        })

        total_balance += balance

    if total_balance < amount + fee:
        raise (
            f"Not enough balance to send! total balance: {total_balance}, required: {amount + fee}, amount to send: {amount}, fee: {fee}"
        )

    if not change_addr:
        change_addr = utxos_to_spend[0]['address']

    txins = []
    for utxo in utxos_to_spend:
        txin = CMutableTxIn(COutPoint(lx(utxo['txHash']), utxo['outputIdx']))
        txins.append(txin)

    txouts = []
    txout = CMutableTxOut(amount,
                          CBitcoinAddress(receiver_addr).to_scriptPubKey())
    txouts.append(txout)
    outs = [{'address': receiver_addr, 'value': amount}]

    if total_balance > amount + fee:
        change = total_balance - amount - fee
        txout = CMutableTxOut(change,
                              CBitcoinAddress(change_addr).to_scriptPubKey())
        txouts.append(txout)
        outs.append({'address': change_addr, 'value': change})

    tx = CMutableTransaction(txins, txouts)

    sig_data = []

    for i, utxo in enumerate(utxos_to_spend):
        sighash = SignatureHash(CScript(x(utxo['sigScript'])), tx, i,
                                SIGHASH_ALL)
        seckey = fetch_key_for_address(key_file, utxo['address'])
        if not seckey:
            raise (
                f"Could not find private key for address: {utxo['address']}")
        sig = seckey.sign(sighash) + bytes([SIGHASH_ALL])
        sig_data.append([sig, seckey.pub])

    for i, txin in enumerate(txins):
        txin.scriptSig = CScript(sig_data[i])

    tx_hash = b2lx(
        hashlib.sha256(hashlib.sha256(tx.serialize()).digest()).digest())

    return utxos_to_spend, outs, fee, b2x(tx.serialize()), tx_hash
Пример #3
0
 def getaccountaddress(self, account=None):
     """Return the current Bitcoin address for receiving payments to this
     account."""
     r = self._call('getaccountaddress', account)
     return CBitcoinAddress(r)
Пример #4
0
                    type=str,
                    help='Destination address')
parser.add_argument('amount',
                    action='store',
                    type=float,
                    help='Amount to send')
args = parser.parse_args()

if args.verbose:
    logging.root.setLevel('DEBUG')

if args.testnet:
    bitcoin.SelectParams('testnet')

args.amount = int(args.amount * COIN)
args.address = CBitcoinAddress(args.address)

rpc = bitcoin.rpc.Proxy()


def check_full_rbf_optin(tx):
    """Return true if tx opts in to full-RBF"""
    for vin in tx.vin:
        if vin.nSequence < 0xFFFFFFFF - 1:
            return True
    return False


tx1 = None
if args.prev_txid is not None:
    try:
Пример #5
0
def get_keys(funder_address, redeemer_address):
    fundpubkey = CBitcoinAddress(funder_address)
    redeempubkey = CBitcoinAddress(redeemer_address)
    # fundpubkey = bitcoind.getnewaddress()
    # redeempubkey = bitcoind.getnewaddress()
    return fundpubkey, redeempubkey
Пример #6
0
def createTransaction(txid, vout, value, output_address, escrow_index, state):
    """ Create an transaction from an escrow address, defined by a previous txid, to the output address """

    # This will be the return value, a little indirection to not return a Share.
    tx_deferred = Deferred()

    def _fire_response(tx):
        tx_deferred.callback(tx)
        return

    def _signatureCallback(signature, shares, hash, transaction):
        return signature

    def _computeSignatureShare(hash):
        def _get_R(R_deferred):
            R = R_deferred.x()
            return R

        def _compute_summand2(R, k_inv_d_share):
            summand2 = ConstantMultiplicationSmpcValue(state)
            summand2_deferred = summand2.initialize(R, k_inv_d_share)
            return summand2_deferred

        def _final_sum(deferreds):
            global transaction_ctr
            summand1 = WrapperSmpcValue(state)
            summand2 = WrapperSmpcValue(state)
            summand1.initialize(deferreds[0][1])
            summand2.initialize(deferreds[1][1])
            s = AdditionSmpcValue(
                state)  # add secret values of summand1, summand2 (see below)
            s_deferred = s.initialize(summand1, summand2)
            return s_deferred

        # Set parameters for creating the share of the signature
        e = int(hexlify(hash), 16)
        kG_deferred = state.smpc.getValue('k', escrow_index).getPublicValue()
        R = state.smpc.getValue('k', escrow_index).getPublicValue()
        k_inv_share = state.smpc.getValue('ki', escrow_index)
        k_inv_d_share = state.smpc.getValue('kid', escrow_index)
        """ Calculation to be performed: S_share = e * k_inv_share + R * k_inv_d_share """
        try:
            summand1 = ConstantMultiplicationSmpcValue(state)
            summand1_deferred = summand1.initialize(e, k_inv_share)
            kG_deferred.addCallback(_get_R)
            kG_deferred.addCallback(_compute_summand2,
                                    k_inv_d_share=k_inv_d_share)
            R.addCallback(_get_R)
            S_share = DeferredList([summand1_deferred, kG_deferred])
            S_share.addCallback(_final_sum)
            return (S_share, R)
        except BaseException as ex:
            log.critical('Error in signature generation! Error: ' + str(ex))
            raise RuntimeError('signing_share_failed')

    def _signatureToDER(S, R):
        S_der = der.encode_integer(int(S))
        R_der = der.encode_integer(int(R))

        signature_der = der.encode_sequence(R_der, S_der) + chr(0x01)
        return signature_der

    def _reconstruct_signature(S_share):
        try:
            global transaction_ctr
            final_sum = WrapperSmpcValue(state)
            final_sum.initialize(S_share)
            S = state.smpc.newValue('rec', state, 'S', transaction_ctr)
            return S.initialize(final_sum)
        except BaseException as e:
            log.critical('S reconstruction failed! ' + str(e))
            raise RuntimeError('signing_reconstruct_failed')

    def _computeSignature(S_share_R):
        S_share = S_share_R[0][1]
        R = S_share_R[1][1]

        def _extract_signature(_):
            global transaction_ctr
            signature = state.smpc.getValue('S',
                                            transaction_ctr).getPublicValue()
            transaction_ctr += 1
            return signature

        signature = _reconstruct_signature(S_share)
        signature.addCallback(_extract_signature)
        signature.addCallback(_signatureToDER, R=R)
        return signature

    def _computeTransaction(signature, tx, script_pubkey, pubkey):
        txin = tx.vin[0]
        txin.scriptSig = bc.core.script.CScript([signature, pubkey])

        try:
            VerifyScript(txin.scriptSig, script_pubkey, tx, 0,
                         (bc.core.scripteval.SCRIPT_VERIFY_P2SH, ))
        except BaseException as e:
            log.error(str(e))
            raise RuntimeError('signing_failed')

        transaction_serialized = bc.core.b2x(tx.serialize())
        return transaction_serialized

    cpub = CPubKey(state.input.getInputPeer('id', escrow_index)['pubkey'])
    txid = bc.core.lx(txid)

    # TXIN information
    txin = bc.core.CMutableTxIn(bc.core.COutPoint(txid, vout))
    txin_scriptPubKey = bc.core.script.CScript([
        bc.core.script.OP_DUP, bc.core.script.OP_HASH160,
        bc.core.Hash160(cpub), bc.core.script.OP_EQUALVERIFY,
        bc.core.script.OP_CHECKSIG
    ])

    # TXOUT information
    txout = bc.core.CMutableTxOut(
        int(value * bc.core.COIN),
        CBitcoinAddress(output_address).to_scriptPubKey())

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

    # Create signature hash
    sighash = bc.core.script.SignatureHash(txin_scriptPubKey, tx, 0,
                                           bc.core.script.SIGHASH_ALL)
    (S_share, R) = _computeSignatureShare(sighash)
    deferreds = DeferredList([S_share, R])
    deferreds.addCallback(_computeSignature)
    deferreds.addCallback(_computeTransaction,
                          tx=tx,
                          script_pubkey=txin_scriptPubKey,
                          pubkey=cpub)
    deferreds.addCallback(_fire_response)

    return tx_deferred
Пример #7
0
from bitcoin import SelectParams
from bitcoin.base58 import decode
from bitcoin.wallet import CBitcoinAddress, CBitcoinSecret, P2PKHBitcoinAddress

SelectParams('testnet')
#Kye37LGjYaDHEW5hreTtq3Mah2537tZdPFMUdcGHwvABJK2e2F5X

# TODO: Fill this in with your private key.
my_private_key = CBitcoinSecret(
    'cQhezNyeQknhnXrerkvV8yxiUnFWHQyaeQUinqnt7Qrmh7GsTnDv')
my_public_key = my_private_key.pub
my_address = P2PKHBitcoinAddress.from_pubkey(my_public_key)

faucet_address = CBitcoinAddress('mv4rnyY3Su5gjcDNzbMLKBQkBicCtHUtFB')
args = parser.parse_args()

logging.root.setLevel('DEBUG')

if args.testnet:
    bitcoin.SelectParams('testnet')

rpc = bitcoin.rpc.Proxy()

args.dust = int(args.dust * COIN)

feeperbyte1 = args.fee1 / 1000 * COIN
feeperbyte2 = args.fee2 / 1000 * COIN

# Construct payment tx
payment_address = CBitcoinAddress(args.address)

payment_txout = CMutableTxOut(int(args.amount * COIN),
                              payment_address.to_scriptPubKey())
change_txout = CMutableTxOut(0, rpc.getnewaddress().to_scriptPubKey())

tx = CMutableTransaction()
tx.vout.append(change_txout)
tx.vout.append(payment_txout)

# Add all undesirable txouts meant to reduce propagation
if args.op_return:
    op_ret_txout = CMutableTxOut(
        0, CScript([OP_RETURN, b'\x00unsuccessful double-spend attempt\x00']))
    tx.vout.append(op_ret_txout)
Пример #9
0
 def get_keys(self, funder_address, redeemer_address):
     fundpubkey = CBitcoinAddress(funder_address)
     redeempubkey = CBitcoinAddress(redeemer_address)
     return fundpubkey, redeempubkey
Пример #10
0
block_hash = bitcoin_rpc.generate(100)[0]
txin = CMutableTxIn(COutPoint(lx(coinbase["txid"]), 0))

# Now select input we received at the "burn" address.
listunspent = bitcoin_rpc.listunspent(0, 9999, [str(address)])
assert (len(listunspent) == 1)
unspent = listunspent[0]
txin2 = CMutableTxIn(COutPoint(lx(unspent["txid"]), unspent["vout"]))

# Create an output that sends the all input's coins minus fee
# to a newly created address.
dest_addr = bitcoin_rpc.getnewaddress()
coinbase_amount = coinbase["vout"][0]["value"]
fee = 10000  # in satoshi
out_amount = coinbase_amount * COIN + burn_amount * COIN - fee
txout = CMutableTxOut(out_amount, CBitcoinAddress(dest_addr).to_scriptPubKey())

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

# Sign inputs. Start with the coinbase input.
coinbase_address = coinbase["vout"][0]["scriptPubKey"]["addresses"][0]
seckey_coinbase = CBitcoinSecret(bitcoin_rpc.dumpprivkey(coinbase_address))
sighash = SignatureHash(CScript(x(coinbase["vout"][0]["scriptPubKey"]["hex"])),
                        tx, 0, SIGHASH_ALL)
sig = seckey_coinbase.sign(sighash) + bytes([SIGHASH_ALL])
txin.scriptSig = CScript([sig])

# Sign "burn" address input.
sighash = SignatureHash(CScript(multisig_script), tx, 1, SIGHASH_ALL)
sig = seckey_multisig.sign(sighash) + bytes([SIGHASH_ALL])
Пример #11
0
    def pay(self,
            pay,
            change_address=None,
            allow_zero_conf=False,
            randomize_change_idx=True,
            fee_strategy='optimal'):
        send = {}

        if isinstance(pay, list):
            for address, value in pay:
                send[address] = value
        else:
            send = pay

        coin_selection = self.client.coin_selection(
            self.identifier,
            send,
            lockUTXO=True,
            allow_zero_conf=allow_zero_conf,
            fee_strategy=fee_strategy)

        utxos = coin_selection['utxos']
        fee = coin_selection['fee']
        change = coin_selection['change']

        if change > 0:
            if change_address is None:
                _, change_address = self.get_new_address_pair()

            send[change_address] = change

        txins = []
        for utxo in utxos:
            txins.append(CMutableTxIn(COutPoint(lx(utxo['hash']),
                                                utxo['idx'])))

        txouts = []
        change_txout = None
        for address, value in send.items():
            txout = CMutableTxOut(value,
                                  CBitcoinAddress(address).to_scriptPubKey())
            if address == change_address:
                change_txout = txout
            txouts.append(txout)

        # randomly move the change_txout
        if randomize_change_idx and change_txout:
            txouts.remove(change_txout)
            txouts.insert(random.randrange(len(txouts) + 1), change_txout)

        tx = CMutableTransaction(txins, txouts)

        for idx, utxo in enumerate(utxos):
            path = utxo['path'].replace("M/", "")

            key = self.primary_private_key.subkey_for_path(path)
            redeemScript = CScript(x(utxo['redeem_script']))
            sighash = SignatureHash(redeemScript, tx, idx, SIGHASH_ALL)

            ckey = CBitcoinSecret(key.wif())

            sig = ckey.sign(sighash) + struct.pack("B", SIGHASH_ALL)

            txins[idx].scriptSig = CScript([OP_0, sig, redeemScript])

        signed = self.client.send_transaction(self.identifier,
                                              b2x(tx.serialize()),
                                              [utxo['path'] for utxo in utxos],
                                              check_fee=True)

        return signed['txid']
Пример #12
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 += [bytes(0)]
    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)