Exemplo n.º 1
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.º 2
0
def spend_escrow(serial_tx, redeem_script, payer_sig, redeemer_sig):
    '''
        Sends a transaction fulfilling the redeem script of escrow tx
    '''
    # Read in transaction
    temp_tx = CTransaction.deserialize(serial_tx)
    tx = CMutableTransaction.from_tx(temp_tx)

    txin = tx.vin[0]

    # Set script sig
    txin.scriptSig = CScript([OP_0,
                             payer_sig + '\x01',
                             redeemer_sig + '\x01',
                             redeem_script])

    # Verify script
    redeem_script = CScript(redeem_script)
    serial_tx = tx.serialize()
    VerifyScript(txin.scriptSig, redeem_script.to_p2sh_scriptPubKey(),
                 tx, 0, [SCRIPT_VERIFY_P2SH])

    serial_tx = tx.serialize()
    txid = b2lx(Hash(serial_tx))

    print("spend_escrow: TXID is %s" % txid)
    print("spend_escrow: RAW TX is %s" % b2x(serial_tx))

    return serial_tx
Exemplo n.º 3
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.º 4
0
def partial_spend_p2sh_mediator(redeemScript,
                                rein,
                                mediator_address,
                                mediator_sig=False):
    txin_redeemScript = CScript(x(redeemScript))
    txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey()
    txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey)
    (txins, total_value) = unspent_txins(txin_p2sh_address, rein.testnet)
    if len(txins) == 0:
        raise ValueError('No unspent txins found')
    txins_str = ""
    txins_obj = []
    for txid, vout in txins:
        txins_str += " " + txid + "-" + str(vout)
        txins_obj.append(CMutableTxIn(COutPoint(lx(txid), vout)))
    fee = 0.00025
    amount = round(total_value - fee, 8)
    if amount <= 0:
        raise ValueError('Not enough value in the inputs')
    if mediator_sig:
        txout = CMutableTxOut(
            amount * COIN,
            CBitcoinAddress(mediator_address).to_scriptPubKey())
        tx = CMutableTransaction(txins_obj, [txout])
        seckey = CBitcoinSecret(rein.user.dkey)
        ntxins = len(txins_obj)
        sig = ""
        for i in range(0, ntxins):
            sighash = SignatureHash(txin_redeemScript, tx, i, SIGHASH_ALL)
            sig += " " + b2x(seckey.sign(sighash) + x("01"))
        return (txins_str[1:], "{:.8f}".format(amount), str(mediator_address),
                sig[1:])
    return (txins_str[1:], "{:.8f}".format(amount), str(mediator_address))
Exemplo n.º 5
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.º 6
0
def hashtimelockcontract(proxy, funder, redeemer, commitment, locktime):
    funderAddr = CBitcoinAddress('ms6KpXRvUwwygwzgRoANRwgcGskXcnEwAr')
    redeemerAddr = CBitcoinAddress('mph94e6SCNUPpyZBhBXHdRZyz1f4DDzeJK')

    if type(commitment) == str:
        commitment = x(commitment)
    else:
        raise ValueError("Commitment was not a string: {0}".format(commitment))
    blocknum = proxy.getblockcount()
    print("Current blocknum on Bitcoin: ", blocknum)
    redeemblocknum = blocknum + locktime
    print("Redeemblocknum on Bitcoin: ", redeemblocknum)
    redeemScript = CScript([
        OP_IF, OP_SHA256, commitment, OP_EQUALVERIFY, OP_DUP, OP_HASH160,
        redeemerAddr, OP_ELSE, redeemblocknum, OP_CHECKLOCKTIMEVERIFY,
        OP_DROP, OP_DUP, OP_HASH160, funderAddr, OP_ENDIF, OP_EQUALVERIFY,
        OP_CHECKSIG])
    # print("Redeem script for p2sh contract on Bitcoin blockchain: "
    #        "{0}".format(b2x(redeemScript)))
    txin_scriptPubKey = redeemScript.to_p2sh_scriptPubKey()
    # Convert the P2SH scriptPubKey to a base58 Bitcoin address
    txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(
        txin_scriptPubKey)
    p2sh = str(txin_p2sh_address)
    # Import address at same time you create
    proxy.importaddress(p2sh, "", False)
    print("p2sh computed", p2sh)
    return {'p2sh': p2sh,
            'redeemblocknum': redeemblocknum,
            'redeemScript': b2x(redeemScript),
            'redeemer': redeemer,
            'funder': funder,
            'locktime': locktime}
Exemplo n.º 7
0
    def spend_escrow(self, payer_sig, redeemer_sig, serial_tx, redeem_script):
        '''
            Sends a transaction fulfilling the redeem script of escrow tx
        '''
        # Read in transaction
        temp_tx = CTransaction.deserialize(serial_tx)
        tx = CMutableTransaction.from_tx(temp_tx)

        txin = tx.vin[0]

        # Set script sig
        txin.scriptSig = CScript([
            OP_FALSE, payer_sig + '\x01', redeemer_sig + '\x01', OP_TRUE,
            redeem_script
        ])

        # Verify script
        redeem_script = CScript(redeem_script)
        serial_tx = tx.serialize()
        VerifyScript(txin.scriptSig, redeem_script.to_p2sh_scriptPubKey(), tx,
                     0, [SCRIPT_VERIFY_P2SH])

        serial_tx = tx.serialize()
        if not self.test:
            # txid = self.proxy.sendrawtransaction(tx)
            txid = b2lx(Hash(serial_tx))
        else:
            txid = b2lx(Hash(serial_tx))

        self.logger.info("spend_escrow: TXID is %s", txid)
        self.logger.info("spend_escrow: RAW TX is %s", b2x(serial_tx))

        return serial_tx
Exemplo n.º 8
0
def make_p2sh_encoding_redeemscript(datachunk,
                                    n,
                                    pubKey=None,
                                    multisig_pubkeys=None,
                                    multisig_pubkeys_required=None):
    _logger = logger.getChild('p2sh_encoding')
    assert len(datachunk) <= bitcoinlib.core.script.MAX_SCRIPT_ELEMENT_SIZE

    dataDropScript = [datachunk, bitcoinlib.core.script.OP_DROP
                      ]  # just drop the data chunk
    cleanupScript = [
        n, bitcoinlib.core.script.OP_DROP, bitcoinlib.core.script.OP_DEPTH, 0,
        bitcoinlib.core.script.OP_EQUAL
    ]  # unique offset + prevent scriptSig malleability

    if pubKey is not None:
        # a p2pkh script looks like this: {pubkey} OP_CHECKSIGVERIFY
        verifyOwnerScript = [pubKey, bitcoinlib.core.script.OP_CHECKSIGVERIFY]
    elif multisig_pubkeys_required is not None and multisig_pubkeys:
        # a 2-of-3 multisig looks like this:
        #   2 {pubkey1} {pubkey2} {pubkey3} 3 OP_CHECKMULTISIGVERIFY
        multisig_pubkeys_required = int(multisig_pubkeys_required)
        if multisig_pubkeys_required < 2 or multisig_pubkeys_required > 15:
            raise exceptions.TransactionError('invalid multisig pubkeys value')
        verifyOwnerScript = [multisig_pubkeys_required]
        for multisig_pubkey in multisig_pubkeys:
            verifyOwnerScript.append(multisig_pubkey)
        verifyOwnerScript = verifyOwnerScript + [
            len(multisig_pubkeys),
            bitcoinlib.core.script.OP_CHECKMULTISIGVERIFY
        ]
    else:
        raise exceptions.TransactionError(
            'Either pubKey or multisig pubKeys must be provided')

    #redeemScript = CScript(datachunk) + CScript(dataDropScript + verifyOwnerScript + cleanupScript)
    redeemScript = CScript(dataDropScript + verifyOwnerScript + cleanupScript)

    _logger.debug('datachunk %s' % (binascii.hexlify(datachunk)))
    _logger.debug('dataDropScript %s (%s)' % (repr(
        CScript(dataDropScript)), binascii.hexlify(CScript(dataDropScript))))
    _logger.debug('verifyOwnerScript %s (%s)' %
                  (repr(CScript(verifyOwnerScript)),
                   binascii.hexlify(CScript(verifyOwnerScript))))
    _logger.debug('entire redeemScript %s (%s)' %
                  (repr(redeemScript), binascii.hexlify(redeemScript)))

    #scriptSig = CScript([]) + redeemScript  # PUSH(datachunk) + redeemScript
    scriptSig = CScript([redeemScript])
    outputScript = redeemScript.to_p2sh_scriptPubKey()

    _logger.debug('scriptSig %s (%s)' %
                  (repr(scriptSig), binascii.hexlify(scriptSig)))
    _logger.debug('outputScript %s (%s)' %
                  (repr(outputScript), binascii.hexlify(outputScript)))

    # outputScript looks like OP_HASH160 {{ hash160([redeemScript]) }} OP_EQUALVERIFY
    # redeemScript looks like OP_DROP {{ pubkey }} OP_CHECKSIGVERIFY {{ n }} OP_DROP OP_DEPTH 0 OP_EQUAL
    # scriptSig is {{ datachunk }} OP_DROP {{ pubkey }} OP_CHECKSIGVERIFY {{ n }} OP_DROP OP_DEPTH 0 OP_EQUAL
    return scriptSig, redeemScript, outputScript
Exemplo n.º 9
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.º 10
0
    def refund_tx(self, payer_sig, serial_tx, redeem_script):
        '''
            Sends a transaction refunding the funder of
            the P2SH address.
        '''
        # Read in transaction
        temp_tx = CTransaction.deserialize(serial_tx)
        tx = CMutableTransaction.from_tx(temp_tx)

        txin = tx.vin[0]

        # Set script sig
        txin.scriptSig = CScript([payer_sig + '\x01', OP_FALSE, redeem_script])

        # Verify script
        redeem_script = CScript(redeem_script)
        VerifyScript(txin.scriptSig, redeem_script.to_p2sh_scriptPubKey(), tx,
                     0, [SCRIPT_VERIFY_P2SH])

        serial_tx = tx.serialize()
        if not self.test:
            # txid = self.self.proxy.sendrawtransaction(tx)
            txid = b2lx(Hash(serial_tx))
        else:
            txid = b2lx(Hash(serial_tx))

        self.logger.info("refund_tx: TXID is %s", txid)
        self.logger.info("refund_tx: RAW TX is %s", b2x(serial_tx))

        return serial_tx
Exemplo n.º 11
0
def hashtimelockcontract(funder, redeemer, secret, locktime):
    funderAddr = CBitcoinAddress(funder)
    redeemerAddr = CBitcoinAddress(redeemer)
    h = sha256(secret)
    blocknum = bitcoind.getblockcount()
    print("Current blocknum", blocknum)
    redeemblocknum = blocknum + locktime
    print("REDEEMBLOCKNUM BITCOIN", redeemblocknum)
    redeemScript = CScript([
        OP_IF, OP_SHA256, h, OP_EQUALVERIFY, OP_DUP, OP_HASH160, redeemerAddr,
        OP_ELSE, redeemblocknum, OP_CHECKLOCKTIMEVERIFY, OP_DROP, OP_DUP,
        OP_HASH160, funderAddr, OP_ENDIF, OP_EQUALVERIFY, OP_CHECKSIG
    ])
    print("Redeem script for p2sh contract on Bitcoin blockchain:",
          b2x(redeemScript))
    txin_scriptPubKey = redeemScript.to_p2sh_scriptPubKey()
    # Convert the P2SH scriptPubKey to a base58 Bitcoin address
    txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey)
    p2sh = str(txin_p2sh_address)
    return {
        'p2sh': p2sh,
        'redeemblocknum': redeemblocknum,
        'redeemScript': b2x(redeemScript),
        'redeemer': redeemer,
        'funder': funder
    }
Exemplo n.º 12
0
def build_mandatory_multisig(mandatory_pubkey, other_pubkeys):
    txin_redeemScript = CScript([
        x(mandatory_pubkey), OP_CHECKSIGVERIFY, 1,
        x(other_pubkeys[0]),
        x(other_pubkeys[1]), 2, OP_CHECKMULTISIG
    ])
    txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey()
    txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey)
    return (b2x(txin_redeemScript), str(txin_p2sh_address))
Exemplo n.º 13
0
def build_2_of_3(pubkeys):
    txin_redeemScript = CScript(
        [2,
         x(pubkeys[0]),
         x(pubkeys[1]),
         x(pubkeys[2]), 3, OP_CHECKMULTISIG])
    txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey()
    txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey)
    return (b2x(txin_redeemScript), str(txin_p2sh_address))
Exemplo n.º 14
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)
Exemplo n.º 15
0
def redeem_after_timelock(contract):
    p2sh = contract.p2sh
    fundtx = find_transaction_to_address(p2sh)
    amount = fundtx['amount'] / COIN

    if (fundtx['address'].__str__() != p2sh):
        print("no fund transaction found to the contract p2sh address ", p2sh)
        quit()
    print("Found fundtx:", fundtx)
    # Parsing redeemblocknum from the redeemscript of the p2sh
    redeemblocknum = find_redeemblocknum(contract)
    blockcount = bitcoind.getblockcount()
    print("Current block:", blockcount, "Can redeem from block:",
          redeemblocknum)
    if (still_locked(contract)):
        print("too early for redeeming with timelock try again at block",
              redeemblocknum, "or later")
        return 0

    print("Found {0} in p2sh {1}, redeeming...".format(amount, p2sh))

    redeemPubKey = find_refundAddr(contract)
    print('refundPubKey', redeemPubKey)

    redeemScript = CScript(x(contract.redeemScript))
    txin = CMutableTxIn(fundtx['outpoint'])
    txout = CMutableTxOut(fundtx['amount'] - FEE,
                          redeemPubKey.to_scriptPubKey())
    # Create the unsigned raw transaction.
    txin.nSequence = 0
    tx = CMutableTransaction([txin], [txout])
    tx.nLockTime = redeemblocknum

    sighash = SignatureHash(redeemScript, tx, 0, SIGHASH_ALL)
    # TODO: figure out how to better protect privkey
    privkey = bitcoind.dumpprivkey(redeemPubKey)
    sig = privkey.sign(sighash) + bytes([SIGHASH_ALL])
    txin.scriptSig = CScript([sig, privkey.pub, OP_FALSE, redeemScript])

    # exit()

    # print("txin.scriptSig", b2x(txin.scriptSig))
    txin_scriptPubKey = redeemScript.to_p2sh_scriptPubKey()
    # print('Redeem txhex', b2x(tx.serialize()))
    VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0,
                 (SCRIPT_VERIFY_P2SH, ))
    print("script verified, sending raw tx")
    txid = bitcoind.sendrawtransaction(tx)
    print("Txid of submitted redeem tx: ", b2x(lx(b2x(txid))))
    return b2x(lx(b2x(txid)))
Exemplo n.º 16
0
def partial_spend_p2sh(redeemScript,
                       rein,
                       daddr=None,
                       alt_amount=None,
                       alt_daddr=None):
    if daddr is None:
        daddr = rein.user.daddr
    txin_redeemScript = CScript(x(redeemScript))
    txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey()
    txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey)
    (txins, total_value) = unspent_txins(txin_p2sh_address, rein.testnet)
    if len(txins) == 0:
        raise ValueError(
            'Primary escrow is empty. Please inform client to add funds.')
    txins_str = ""
    txins_obj = []
    for txid, vout in txins:
        txins_str += " " + txid + "-" + str(vout)
        txins_obj.append(CMutableTxIn(COutPoint(lx(txid), vout)))
    fee = float(PersistConfig.get(rein, 'fee', 0.001))
    amount = round(total_value - fee, 8)
    if alt_amount:
        amount = round(amount - alt_amount, 8)
    if amount <= 0. or alt_amount > total_value - fee:
        click.echo("amount: " + str(amount) + " alt_amount: " +
                   str(alt_amount) + " total_value: " + str(total_value))
        raise ValueError(
            'Primary escrow balance too low. Please inform client to add funds.'
        )
    txouts = []
    txout = CMutableTxOut(amount * COIN,
                          CBitcoinAddress(daddr).to_scriptPubKey())
    txouts.append(txout)
    if alt_amount:
        txout_alt = CMutableTxOut(
            round(alt_amount, 8) * COIN,
            CBitcoinAddress(alt_daddr).to_scriptPubKey())
        txouts.append(txout_alt)
    tx = CMutableTransaction(txins_obj, txouts)
    ntxins = len(txins_obj)
    seckey = CBitcoinSecret(rein.user.dkey)
    sig = ""
    for i in range(0, ntxins):
        sighash = SignatureHash(txin_redeemScript, tx, i, SIGHASH_ALL)
        sig += " " + b2x(seckey.sign(sighash)) + "01"
    if alt_amount:
        return (txins_str[1:], "{:.8f}".format(amount), daddr,
                "{:.8f}".format(alt_amount), alt_daddr, sig[1:])
    return (txins_str[1:], "{:.8f}".format(amount), daddr, sig[1:])
Exemplo n.º 17
0
def redeem_with_secret(contract, secret):
    # How to find redeemScript and redeemblocknum from blockchain?
    print("Redeeming contract using secret", contract.__dict__)
    p2sh = contract.p2sh
    minamount = float(contract.amount)
    #checking there are funds in the address
    amount = check_funds(p2sh)
    if (amount < minamount):
        print("address ", p2sh, " not sufficiently funded")
        return false
    fundtx = find_transaction_to_address(p2sh)
    amount = fundtx['amount'] / COIN
    p2sh = P2SHBitcoinAddress(p2sh)
    if fundtx['address'] == p2sh:
        print("Found {0} in p2sh {1}, redeeming...".format(amount, p2sh))

        redeemPubKey = find_redeemAddr(contract)
        print('redeemPubKey', redeemPubKey)

        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(redeemScript, tx, 0, SIGHASH_ALL)
        # TODO: figure out how to better protect privkey
        privkey = bitcoind.dumpprivkey(redeemPubKey)
        sig = privkey.sign(sighash) + bytes([SIGHASH_ALL])
        print("SECRET", secret)
        preimage = secret.encode('utf-8')
        txin.scriptSig = CScript(
            [sig, privkey.pub, preimage, OP_TRUE, redeemScript])

        # exit()

        # print("txin.scriptSig", b2x(txin.scriptSig))
        txin_scriptPubKey = redeemScript.to_p2sh_scriptPubKey()
        # print('Redeem txhex', b2x(tx.serialize()))
        VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0,
                     (SCRIPT_VERIFY_P2SH, ))
        print("script verified, sending raw tx")
        txid = bitcoind.sendrawtransaction(tx)
        print("Txid of submitted redeem tx: ", b2x(lx(b2x(txid))))
        return b2x(lx(b2x(txid)))
    else:
        print("No contract for this p2sh found in database", p2sh)
Exemplo n.º 18
0
def spend_preimage(redeem_script, preimages, redeemer_sig, serial_tx):
    """
    Creates a transaction fulfilling the redeem script of the preimage P2SH.

    Arguements:
        redeem_script (bytes): The script that specifies the conditions that a tx has
                        to fulfill to transfer funds from the `funding_tx`
        preimages (list): The preimages that hash into the hash values
                          specified in the `redeem_script`
        redeemer_sig (bytes): The signature of the redeemer on the `serial_tx`
        serial_tx (bytes): The serial transaction

    Returns:
        The serial raw transaction that passes the script verification
    """
    # Read in transaction
    temp_tx = CTransaction.deserialize(serial_tx)
    tx = CMutableTransaction.from_tx(temp_tx)

    txin = tx.vin[0]

    # Setup preimages in reverse order
    script = []
    for p in reversed(preimages):
        script += [p]

    # Create script sig
    txin.scriptSig = CScript([redeemer_sig + '\x01'] + script +
                             [redeem_script])

    # Verify script
    redeem_script = CScript(redeem_script)
    try:
        VerifyScript(txin.scriptSig, redeem_script.to_p2sh_scriptPubKey(), tx,
                     0, [SCRIPT_VERIFY_P2SH])
    except ValidationError:
        print("spend_preimage: Script failed to verify")
        return None

    serial_tx = tx.serialize()
    txid = b2lx(Hash(serial_tx))

    print("spend_preimage: TXID is %s" % txid)
    print("spend_preimage: RAW TX is %s" % b2x(serial_tx))

    return serial_tx
Exemplo n.º 19
0
def setup_escrow(payer_pubkey, redeemer_pubkey, lock_time):
    """
    Setups a 2of2 escrow with payer and redeemer
    Also, sends a tx funding the escrow
    (Assumes payer calls the setup)

    Arguments:
        payer_pubkey (bytes): The payer's public key
        redeemer_pubkey (bytes): The payer's public key
        lock_time (int): The time the refund should be activated at

    Returns:
        A tuple containing:
            1/ redeem_script
            2/ p2sh_address, which should be funded
    """

    # (OP_DEPTH, 3, OP_EQUAL) Fixes a txid malliablity issue thanks to Nicolas
    #
    # This redeem_script is different from what's presented in the paper
    # It adds (OP_DEPTH, 3, OP_EQUAL) to the beggining of the script
    # to avoid the having a mallable fulfilling tx id.
    #
    # This is because in the old version if relied on a bool value
    # provided by the user in the script, and any number > 0 represents true
    #
    # The fix proposed by Nicolas Dorier relies on the number of stack items to
    # decide which condition to execute.

    redeem_script = CScript([
        OP_DEPTH, 3, OP_EQUAL, OP_IF, OP_2, payer_pubkey, redeemer_pubkey,
        OP_2, OP_CHECKMULTISIG, OP_ELSE, lock_time, OP_CHECKLOCKTIMEVERIFY,
        OP_DROP, payer_pubkey, OP_CHECKSIG, OP_ENDIF
    ])

    redeem = b2x(redeem_script)
    print("setup_escrow: Redeem script is %s" % redeem)

    # Get P2SH address
    script_pub_key = redeem_script.to_p2sh_scriptPubKey()
    p2sh_address = CBitcoinAddress.from_scriptPubKey(script_pub_key)

    print("setup_escrow: P2SH is %s" % str(p2sh_address))

    return (redeem_script, str(p2sh_address))
Exemplo n.º 20
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.º 21
0
    def setup_preimage(self, payer_pubkey, redeemer_pubkey, hashes, amount,
                       lock_time):
        '''
            Setups a P2SH that can only be redeemed
            if the redeemer is able to provide
            the hash preimages.
            Also, sends a tx funding the escrow
            (Assumes payer calls the setup)
        '''

        # Set locktime relative to current block
        if not self.test:
            lock = self.proxy.getblockcount() + lock_time
        else:
            lock = lock_time

        script = self.create_hash_script(redeemer_pubkey, hashes)
        redeem_script = CScript([OP_IF] + script + [
            OP_ELSE, lock, OP_CHECKLOCKTIMEVERIFY, OP_DROP, payer_pubkey,
            OP_CHECKSIG, OP_ENDIF
        ])

        redeem = b2x(redeem_script)
        self.logger.info("setup_preimage: Redeem script is %s", redeem)

        # Get P2SH address
        # 1. Get public key
        script_pub_key = redeem_script.to_p2sh_scriptPubKey()

        # 2. Get bitcoin address
        p2sh_address = CBitcoinAddress.from_scriptPubKey(script_pub_key)
        self.logger.info("setup_preimage: P2SH is %s", str(p2sh_address))

        # 3. Fund address
        if not self.test:
            # funding_tx = self.proxy.call("sendtoaddress", str(p2sh_address),
            #                              amount)
            funding_tx = FUNDING_TX
            self.logger.info("setup_preimage: P2SH Fund TX is %s", funding_tx)
        else:
            funding_tx = FUNDING_TX

        return (redeem_script, str(funding_tx), str(p2sh_address), str(lock))
Exemplo n.º 22
0
def spend_escrow(redeem_script, payer_sig, redeemer_sig, serial_tx):
    """
    Creates a transaction fulfilling the redeem script of the escrow P2SH.

    Arguements:
        redeem_script (bytes): The script that specifies the conditions that a tx has
                        to fulfill to transfer funds from the `funding_tx`
        payer_sig (bytes): The signature of the payer on the `serial_tx`
        redeemer_sig (bytes): The signature of the redeemer on the `serial_tx`
        serial_tx (bytes): The serial transaction

    Returns:
        The serial raw transaction that passes the script verification
    """
    # Read in transaction
    temp_tx = CTransaction.deserialize(serial_tx)
    tx = CMutableTransaction.from_tx(temp_tx)

    txin = tx.vin[0]

    # Set script sig
    txin.scriptSig = CScript(
        [OP_0, payer_sig + '\x01', redeemer_sig + '\x01', redeem_script])

    # Verify script
    redeem_script = CScript(redeem_script)
    serial_tx = tx.serialize()

    try:
        VerifyScript(txin.scriptSig, redeem_script.to_p2sh_scriptPubKey(), tx,
                     0, [SCRIPT_VERIFY_P2SH])
    except ValidationError:
        print("spend_escrow: Script failed to verify")
        return None

    serial_tx = tx.serialize()
    txid = b2lx(Hash(serial_tx))

    print("spend_escrow: TXID is %s" % txid)
    print("spend_escrow: RAW TX is %s" % b2x(serial_tx))

    return serial_tx
Exemplo n.º 23
0
    def htlc_p2sh(self) -> str:
        # TODO: cache the generated address
        # We create connections on the fly because they'll time out quickly if
        # we don't
        bitcoind = rpc.Proxy()

        # We can decipher the hash of the preimage without explicitly asking
        # for it by taking it out of the payment request supplied
        decoded_pr = json.loads(
            to_json(lnd.decode_payment_request(self.bolt11_invoice)))
        hashed_preimage = decoded_pr['payment_hash']

        # Once these assignments are made, we want to lock them in so this
        # functions generates deterministically
        if not self.final_address_pubkey:
            final_address = bitcoind.getnewaddress()
            seckey = bitcoind.dumpprivkey(final_address)
            self.final_address_pubkey = seckey.pub.hex()

        if not self.redeemblock:
            curr_blockheight = bitcoind.getblockcount()
            self.redeemblock = curr_blockheight + self.lockduration

        # HTLC locking script
        txin_redeemScript = CScript([
            OP_IF, OP_SHA256,
            bytes(hashed_preimage, 'utf8'), OP_EQUALVERIFY, OP_DUP, OP_HASH160,
            bytes(Hash160(bytes(self.final_address_pubkey,
                                'utf8'))), OP_ELSE, self.redeemblock,
            OP_CHECKLOCKTIMEVERIFY, OP_DROP, OP_DUP, OP_HASH160,
            bytes(Hash160(bytes(self.refund_address, 'utf8'))), OP_ENDIF,
            OP_EQUALVERIFY, OP_CHECKSIG
        ])

        self.save()

        # Generate a P2SH address from the locking script
        txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey()
        txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(
            txin_scriptPubKey)
        return str(txin_p2sh_address)
Exemplo n.º 24
0
    def setup_escrow(self, payer_pubkey, redeemer_pubkey, amount, lock_time):
        '''
            Setups a 2of2 escrow with payer and redeemer
            Also, sends a tx funding the escrow
            (Assumes payer calls the setup)
        '''

        # Set locktime relative to current block
        if not self.test:
            lock = self.proxy.getblockcount() + lock_time
            self.logger.info("setup_escrow: Locktime is %d", lock)
        else:
            lock = lock_time

        redeem_script = CScript([
            OP_IF, OP_2, payer_pubkey, redeemer_pubkey, OP_2, OP_CHECKMULTISIG,
            OP_ELSE, lock, OP_CHECKLOCKTIMEVERIFY, OP_DROP, payer_pubkey,
            OP_CHECKSIG, OP_ENDIF
        ])

        redeem = b2x(redeem_script)
        self.logger.info("setup_escrow: Redeem script is %s", redeem)

        # Get P2SH address
        # 1. Get public key
        script_pub_key = redeem_script.to_p2sh_scriptPubKey()

        # 2. Get bitcoin address
        p2sh_address = CBitcoinAddress.from_scriptPubKey(script_pub_key)
        self.logger.info("setup_escrow: P2SH is %s", str(p2sh_address))

        # 3. Fund address
        if not self.test:
            funding_tx = self.proxy.call("sendtoaddress", str(p2sh_address),
                                         amount)
            self.logger.info("setup_escrow: P2SH Fund TX is %s", funding_tx)
        else:
            funding_tx = FUNDING_TX

        return (redeem_script, str(funding_tx), str(p2sh_address), str(lock))
Exemplo n.º 25
0
 def hashtimelockcontract(self, funder, redeemer, commitment, locktime):
     funderAddr = CBitcoinAddress(funder)
     redeemerAddr = CBitcoinAddress(redeemer)
     if type(commitment) == str:
         commitment = x(commitment)
     # h = sha256(secret)
     blocknum = self.bitcoind.getblockcount()
     print("Current blocknum on Bitcoin: ", blocknum)
     redeemblocknum = blocknum + locktime
     print("Redeemblocknum on Bitcoin: ", redeemblocknum)
     redeemScript = CScript([OP_IF, OP_SHA256, commitment, OP_EQUALVERIFY,OP_DUP, OP_HASH160,
                                  redeemerAddr, OP_ELSE, redeemblocknum, OP_CHECKLOCKTIMEVERIFY, OP_DROP, OP_DUP, OP_HASH160,
                                  funderAddr, OP_ENDIF,OP_EQUALVERIFY, OP_CHECKSIG])
     # print("Redeem script for p2sh contract on Bitcoin blockchain: {0}".format(b2x(redeemScript)))
     txin_scriptPubKey = redeemScript.to_p2sh_scriptPubKey()
     # Convert the P2SH scriptPubKey to a base58 Bitcoin address
     txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey)
     p2sh = str(txin_p2sh_address)
     # Import address at same time you create
     self.bitcoind.importaddress(p2sh, "", False)
     print("p2sh computed", p2sh)
     return {'p2sh': p2sh, 'redeemblocknum': redeemblocknum, 'redeemScript': b2x(redeemScript), 'redeemer': redeemer, 'funder': funder, 'locktime': locktime}
Exemplo n.º 26
0
    def get_address_by_path(self, path, key=None):
        path = path.replace("M/", "")
        key_index = path.split("/")[0].replace("'", "")

        if key is None:
            key = self.primary_private_key.subkey_for_path(path)

        backup_public_key = self.backup_public_key.subkey_for_path(
            path.replace("'", ""))
        blocktrail_public_key = self.blocktrail_public_keys[str(
            key_index)].subkey_for_path("/".join(path.split("/")[1:]))

        redeemScript = CScript([2] + sorted([
            key.sec(use_uncompressed=False),
            backup_public_key.sec(use_uncompressed=False),
            blocktrail_public_key.sec(use_uncompressed=False),
        ]) + [3, OP_CHECKMULTISIG])

        scriptPubKey = redeemScript.to_p2sh_scriptPubKey()
        address = CBitcoinAddress.from_scriptPubKey(scriptPubKey)

        return str(address)
Exemplo n.º 27
0
    def spend_preimage(self, preimages, redeemer_sig, serial_tx,
                       redeem_script):
        '''
            Sends a transaction fulfilling the redeem script
            of the preimage P2SH
        '''
        # Read in transaction
        temp_tx = CTransaction.deserialize(serial_tx)
        tx = CMutableTransaction.from_tx(temp_tx)

        txin = tx.vin[0]

        # Setup preimages in reverse order
        script = []
        for p in reversed(preimages):
            script += [p]

        # Create script sig
        txin.scriptSig = CScript([redeemer_sig + '\x01'] + script +
                                 [OP_TRUE, redeem_script])

        # Verify script
        redeem_script = CScript(redeem_script)
        VerifyScript(txin.scriptSig, redeem_script.to_p2sh_scriptPubKey(), tx,
                     0, [SCRIPT_VERIFY_P2SH])

        serial_tx = tx.serialize()
        if not self.test:
            # txid = self.proxy.sendrawtransaction(tx)
            txid = b2lx(Hash(serial_tx))
        else:
            txid = b2lx(Hash(serial_tx))

        self.logger.info("spend_preimage: TXID is %s", txid)
        self.logger.info("spend_preimage: RAW TX is %s", b2x(serial_tx))

        return serial_tx
Exemplo n.º 28
0
def setup_preimage(payer_pubkey, redeemer_pubkey, hashes, lock_time):
    """
    Setups a P2SH that can only be redeemed if the redeemer is able
    to provide the hash preimages.

    Arguments:
        payer_pubkey (bytes): The public key of the party that funds the contract
        redeemer_pubkey (bytes): The public key of the party that wants
                                 to receive the funds
        hashes (list): The hashes that payer wants the preimages of
        lock_time (int): The time the refund should be activated at

    Returns:
        A tuple containing:
            1/ redeem_script
            2/ p2sh_address, which should be funded
    """

    script = create_hash_script(redeemer_pubkey, hashes)
    redeem_script = CScript([OP_IF] + script + [
        OP_ELSE, lock_time, OP_CHECKLOCKTIMEVERIFY, OP_DROP, payer_pubkey,
        OP_CHECKSIG, OP_ENDIF
    ])

    redeem = b2x(redeem_script)
    print("setup_preimage: Redeem script is %s" % redeem)

    # Get P2SH address
    # 1. Get public key
    script_pub_key = redeem_script.to_p2sh_scriptPubKey()

    # 2. Get bitcoin address
    p2sh_address = CBitcoinAddress.from_scriptPubKey(script_pub_key)
    print("setup_preimage: P2SH is %s" % str(p2sh_address))

    return (redeem_script, str(p2sh_address))
Exemplo n.º 29
0
def setup_escrow(payer_pubkey, redeemer_pubkey, amount, lock_time):
    '''
        Setups a 2of2 escrow with payer and redeemer
        Also, sends a tx funding the escrow
        (Assumes payer calls the setup)
    '''

    redeem_script = CScript([OP_DEPTH, 3, OP_EQUAL,  # Fixes a txid malliablity issue thanks to Nicolas
                            OP_IF, OP_2, payer_pubkey, redeemer_pubkey,
                            OP_2, OP_CHECKMULTISIG, OP_ELSE, lock_time,
                            OP_CHECKLOCKTIMEVERIFY, OP_DROP,
                            payer_pubkey, OP_CHECKSIG,
                            OP_ENDIF])

    redeem = b2x(redeem_script)
    print("setup_escrow: Redeem script is %s" % redeem)

    # Get P2SH address
    script_pub_key = redeem_script.to_p2sh_scriptPubKey()
    p2sh_address = CBitcoinAddress.from_scriptPubKey(script_pub_key)

    print("setup_escrow: P2SH is %s" %  str(p2sh_address))

    return (redeem_script, str(p2sh_address))
Exemplo n.º 30
0
def build_2_of_3(pubkeys):
    txin_redeemScript = CScript([2, x(pubkeys[0]), x(pubkeys[1]), x(pubkeys[2]), 3, OP_CHECKMULTISIG])
    txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey()
    txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey)
    return (b2x(txin_redeemScript), str(txin_p2sh_address))
Exemplo n.º 31
0
SelectParams('mainnet')

# Create the (in)famous correct brainwallet secret key.
h = hashlib.sha256(b'correct horse battery staple').digest()
seckey = CBitcoinSecret.from_secret_bytes(h)

# Create a redeemScript. Similar to a scriptPubKey the redeemScript must be
# satisfied for the funds to be spent.
txin_redeemScript = CScript([seckey.pub, OP_CHECKSIG])
print(b2x(txin_redeemScript))

# Create the magic P2SH scriptPubKey format from that redeemScript. You should
# look at the CScript.to_p2sh_scriptPubKey() function in bitcoin.core.script to
# understand what's happening, as well as read BIP16:
# https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki
txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey()

# Convert the P2SH scriptPubKey to a base58 Bitcoin address and print it.
# You'll need to send some funds to it to create a txout to spend.
txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey)
print('Pay to:',str(txin_p2sh_address))

# Same as the txid:vout the createrawtransaction RPC call requires
#
# lx() takes *little-endian* hex and converts it to bytes; in Bitcoin
# transaction hashes are shown little-endian rather than the usual big-endian.
# There's also a corresponding x() convenience function that takes big-endian
# hex and converts it to bytes.
txid = lx('bff785da9f8169f49be92fa95e31f0890c385bfb1bd24d6b94d7900057c617ae')
vout = 0
Exemplo n.º 32
0
def build_mandatory_multisig(mandatory_pubkey, other_pubkeys):
    txin_redeemScript = CScript([x(mandatory_pubkey), OP_CHECKSIGVERIFY, 1, x(other_pubkeys[0]), x(other_pubkeys[1]), 2, OP_CHECKMULTISIG])
    txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey()
    txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey)
    return (b2x(txin_redeemScript), str(txin_p2sh_address))