예제 #1
0
def find_secret(p2sh, vinid):
    zcashd.importaddress(p2sh, '', True)

    # is this working?

    print ('vinid:', vinid)
    txs = zcashd.listtransactions()
    print ('LENNNNNNN2:', len(txs))
    for tx in txs:

        # print("tx addr:", tx['address'], "tx id:", tx['txid'])
        # print(type(tx['address']))
        # print(type(p2sh))
        # print('type::',type(tx['txid']))

        raw = zcashd.gettransaction(lx(tx['txid']))['hex']
        decoded = zcashd.decoderawtransaction(raw)
        print ('fdsfdfds', decoded['vin'][0])
        if 'txid' in decoded['vin'][0]:
            sendid = decoded['vin'][0]['txid']
            print ('sendid:', sendid)

            if sendid == vinid:

                # print(type(tx['txid']))
                # print(str.encode(tx['txid']))

                print 'in if'
                return parse_secret(lx(tx['txid']))
    print 'Redeem transaction with secret not found'
    return ''
예제 #2
0
파일: zXcat.py 프로젝트: jasondavies/ZBXCAT
def find_secret(p2sh, vinid):
    zcashd.importaddress(p2sh, "", True)
    # is this working?

    txs = zcashd.listtransactions()
    # print("==========================================LISTTT============", txs)
    # print()
    # print('LENNNNNNN:', len(txs))
    # print('LENNNNNNN2:', len(txs))
    for tx in txs:
        # print("tx addr:", tx['address'], "tx id:", tx['txid'])
        # print(type(tx['address']))
        # print(type(p2sh))
        # print('type::',type(tx['txid']))
        raw = zcashd.gettransaction(lx(tx['txid']))['hex']
        decoded = zcashd.decoderawtransaction(raw)
        # print("fdsfdfds", decoded['vin'][0])
        if ('txid' in decoded['vin'][0]):
            sendid = decoded['vin'][0]['txid']
            # print("sendid:", sendid)

            if (sendid == vinid):
                # print(type(tx['txid']))
                # print(str.encode(tx['txid']))
                return parse_secret(lx(tx['txid']))
            print("Redeem transaction with secret not found")
            return ""
예제 #3
0
    def redeem_contract(self, contract, secret):
        # How to find redeemScript and redeemblocknum from blockchain?
        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))

            # Where can you find redeemblocknum in the transaction?
            # redeemblocknum = find_redeemblocknum(contract)
            blockcount = self.zcashd.getblockcount()
            print("\nCurrent blocknum at time of redeem on Zcash:", blockcount)
            if blockcount < contract.redeemblocknum:
                # TODO: parse the script once, up front.
                redeemPubKey = self.find_redeemAddr(contract)

                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: figure out how to better protect privkey
                privkey = self.zcashd.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, zec_redeemScript])
                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 redeem transaction...")
                txid = self.zcashd.sendrawtransaction(tx)
                redeem_tx = b2x(lx(b2x(txid)))
                fund_tx = str(fundtx['outpoint'])
                return {"redeem_tx": redeem_tx, "fund_tx": fund_tx}
            else:
                print("nLocktime exceeded, refunding")
                refundPubKey = self.find_refundAddr(contract)
                print('refundPubKey', refundPubKey)
                txid = self.zcashd.sendtoaddress(refundPubKey,
                                                 fundtx['amount'] - FEE)
                refund_tx = b2x(lx(b2x(txid)))
                fund_tx = str(fundtx['outpoint'])
                return {"refund_tx": refund_tx, "fund_tx": fund_tx}
        else:
            print("No contract for this p2sh found in database", p2sh)
예제 #4
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 = zcashd.dumpprivkey(redeemPubKey)
        sig = privkey.sign(sighash) + bytes([SIGHASH_ALL])
        print ('SECRET', secret)

        # secret = get_secret()

        preimage = secret.encode('utf-8')
        txin.scriptSig = CScript([sig, privkey.pub, preimage, OP_TRUE,
                                 redeemScript])

        # 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 = zcashd.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)
예제 #5
0
 def find_secret(self, p2sh, fundtx_input):
     txs = self.zcashd.call('listtransactions', "*", 20, 0, True)
     for tx in txs:
         raw = self.zcashd.gettransaction(lx(tx['txid']))['hex']
         decoded = self.zcashd.decoderawtransaction(raw)
         if ('txid' in decoded['vin'][0]):
             sendid = decoded['vin'][0]['txid']
             if (sendid == fundtx_input):
                 print("Found funding tx: ", sendid)
                 return self.parse_secret(lx(tx['txid']))
     print("Redeem transaction with secret not found")
     return
예제 #6
0
def redeem_after_timelock(contract):
    print(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 = zcashd.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

    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 = zcashd.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 = zcashd.sendrawtransaction(tx)
    print("Txid of submitted redeem tx: ", b2x(lx(b2x(txid))))
    return b2x(lx(b2x(txid)))
예제 #7
0
    def getrawtransaction(self, txid, verbose=False):
        """Return transaction with hash txid

        Raises IndexError if transaction not found.

        verbose - If true a dict is returned instead with additional
        information on the transaction.

        Note that if all txouts are spent and the transaction index is not
        enabled the transaction may not be available.
        """
        try:
            r = self._call('getrawtransaction', b2lx(txid),
                           1 if verbose else 0)
        except InvalidAddressOrKeyError as ex:
            raise IndexError('%s.getrawtransaction(): %s (%d)' %
                             (self.__class__.__name__, ex.error['message'],
                              ex.error['code']))
        if verbose:
            r['tx'] = CTransaction.deserialize(unhexlify(r['hex']))
            r['hex']
            del r['txid']
            del r['version']
            del r['locktime']
            del r['vin']
            del r['vout']
            r['blockhash'] = lx(r['blockhash']) if 'blockhash' in r else None
        else:
            r = CTransaction.deserialize(unhexlify(r))

        return r
예제 #8
0
    def getblockheader(self, block_hash, verbose=False):
        """Get block header <block_hash>

        verbose - If true a dict is returned with the values returned by
                  getblockheader that are not in the block header itself
                  (height, nextblockhash, etc.)

        Raises IndexError if block_hash is not valid.
        """
        try:
            block_hash = b2lx(block_hash)
        except TypeError:
            raise TypeError(
                '%s.getblockheader(): block_hash must be bytes; got %r instance'
                % (self.__class__.__name__, block_hash.__class__))
        try:
            r = self._call('getblockheader', block_hash, verbose)
        except InvalidAddressOrKeyError as ex:
            raise IndexError('%s.getblockheader(): %s (%d)' %
                             (self.__class__.__name__, ex.error['message'],
                              ex.error['code']))

        if verbose:
            nextblockhash = None
            if 'nextblockhash' in r:
                nextblockhash = lx(r['nextblockhash'])
            return {
                'confirmations': r['confirmations'],
                'height': r['height'],
                'mediantime': r['mediantime'],
                'nextblockhash': nextblockhash,
                'chainwork': x(r['chainwork'])
            }
        else:
            return CBlockHeader.deserialize(unhexlify(r))
예제 #9
0
    def listunspent(self, minconf=0, maxconf=9999999, addrs=None):
        """Return unspent transaction outputs in wallet

        Outputs will have between minconf and maxconf (inclusive)
        confirmations, optionally filtered to only include txouts paid to
        addresses in addrs.
        """
        r = None
        if addrs is None:
            r = self._call('listunspent', minconf, maxconf)
        else:
            addrs = [str(addr) for addr in addrs]
            r = self._call('listunspent', minconf, maxconf, addrs)

        r2 = []
        for unspent in r:
            unspent['outpoint'] = COutPoint(lx(unspent['txid']),
                                            unspent['vout'])

            unspent['address'] = CBitcoinAddress(unspent['address'])
            unspent['scriptPubKey'] = CScript(
                unhexlify(unspent['scriptPubKey']))
            unspent['amount'] = int(unspent['amount'] * COIN)
            r2.append(unspent)
        return r2
예제 #10
0
 def redeem(self, contract, fundtx, secret):
     # TODO: parse the script once, up front.
     redeemPubKey = self.find_redeemAddr(contract)
     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: figure out how to better protect privkey
     privkey = self.zcashd.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, zec_redeemScript])
     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 redeem transaction...")
     txid = self.zcashd.sendrawtransaction(tx)
     redeem_tx = b2x(lx(b2x(txid)))
     fund_tx = str(fundtx['outpoint'])
     return {"redeem_tx": redeem_tx, "fund_tx": fund_tx}
예제 #11
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
        # Create the unsigned raw transaction.
        sighash = SignatureHash(redeemScript, tx, 0, SIGHASH_ALL)
        privkey = self.zcashd.dumpprivkey(refundPubKey)
        sig = privkey.sign(sighash) + bytes([SIGHASH_ALL])
        # Sign without secret
        txin.scriptSig = CScript([sig, privkey.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 = self.zcashd.sendrawtransaction(tx)
        refund_tx = b2x(lx(b2x(txid)))
        fund_tx = str(fundtx['outpoint'])
        return {"refund_tx": refund_tx, "fund_tx": fund_tx}
예제 #12
0
 def fund_htlc(self, p2sh, amount):
     send_amount = float(amount) * COIN
     # Import addr at same time as you fund
     self.zcashd.importaddress(p2sh, "", False)
     fund_txid = self.zcashd.sendtoaddress(p2sh, send_amount)
     txid = b2x(lx(b2x(fund_txid)))
     return txid
예제 #13
0
    def getrawmempool(self, verbose=False):
        """Return the mempool"""
        if verbose:
            return self._call('getrawmempool', verbose)

        else:
            r = self._call('getrawmempool')
            r = [lx(txid) for txid in r]
            return r
예제 #14
0
    def getblockhash(self, height):
        """Return hash of block in best-block-chain at height.

        Raises IndexError if height is not valid.
        """
        try:
            return lx(self._call('getblockhash', height))
        except InvalidParameterError as ex:
            raise IndexError('%s.getblockhash(): %s (%d)' %
                             (self.__class__.__name__, ex.error['message'],
                              ex.error['code']))
예제 #15
0
 def sendtoaddress(self,
                   addr,
                   amount,
                   comment='',
                   commentto='',
                   subtractfeefromamount=False):
     """Send amount to a given address"""
     addr = str(addr)
     amount = float(amount) / COIN
     r = self._call('sendtoaddress', addr, amount, comment, commentto,
                    subtractfeefromamount)
     return lx(r)
예제 #16
0
    def sendrawtransaction(self, tx, allowhighfees=False):
        """Submit transaction to local node and network.

        allowhighfees - Allow even if fees are unreasonably high.
        """
        hextx = hexlify(tx.serialize())
        r = None
        if allowhighfees:
            r = self._call('sendrawtransaction', hextx, True)
        else:
            r = self._call('sendrawtransaction', hextx)
        return lx(r)
예제 #17
0
 def find_recipient(self, contract):
     # make this dependent on actual fund tx to p2sh, not contract
     txid = contract.fund_tx
     raw = self.zcashd.gettransaction(lx(txid), True)['hex']
     decoded = self.zcashd.decoderawtransaction(raw)
     scriptSig = decoded['vin'][0]['scriptSig']
     print("Decoded", scriptSig)
     asm = scriptSig['asm'].split(" ")
     pubkey = asm[1]
     initiator = CBitcoinAddress(contract.initiator)
     fulfiller = CBitcoinAddress(contract.fulfiller)
     print("Initiator", b2x(initiator))
     print("Fulfiller", b2x(fulfiller))
     print('pubkey', pubkey)
     redeemPubkey = P2PKHBitcoinAddress.from_pubkey(x(pubkey))
     print('redeemPubkey', redeemPubkey)
예제 #18
0
    def sendmany(self,
                 fromaccount,
                 payments,
                 minconf=1,
                 comment='',
                 subtractfeefromamount=[]):
        """Send amount to given addresses.

        payments - dict with {address: amount}
        """
        json_payments = {
            str(addr): float(amount) / COIN
            for addr, amount in payments.items()
        }
        r = self._call('sendmany', fromaccount, json_payments, minconf,
                       comment, subtractfeefromamount)
        return lx(r)
예제 #19
0
    def gettxout(self, outpoint, includemempool=True):
        """Return details about an unspent transaction output.

        Raises IndexError if outpoint is not found or was spent.

        includemempool - Include mempool txouts
        """
        r = self._call('gettxout', b2lx(outpoint.hash), outpoint.n,
                       includemempool)

        if r is None:
            raise IndexError('%s.gettxout(): unspent txout %r not found' %
                             (self.__class__.__name__, outpoint))

        r['txout'] = CTxOut(int(r['value'] * COIN),
                            CScript(unhexlify(r['scriptPubKey']['hex'])))
        del r['value']
        del r['scriptPubKey']
        r['bestblock'] = lx(r['bestblock'])
        return r
예제 #20
0
# https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki
txin_scriptPubKey = txin_redeemScript.to_p2sh_scriptPubKey()
print('scriptPubKey:', str(txin_scriptPubKey))

# Convert the P2SH scriptPubKey to a base58 zcash 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

# Create the txin structure, which includes the outpoint. The scriptSig
# defaults to being empty.
txin = CMutableTxIn(COutPoint(txid, vout))

# Create the txout. This time we create the scriptPubKey from a Bitcoin
# address.
txout = CMutableTxOut(
    0.0005 * COIN,
    CBitcoinAddress('tmKBPqa8qqKA7vrGq1AaXHSAr9vqa3GczzK').to_scriptPubKey())

# Create the unsigned transaction.
tx = CMutableTransaction([txin], [txout])
예제 #21
0
def fund_htlc(p2sh, amount):
    send_amount = float(amount) * COIN
    fund_txid = zcashd.sendtoaddress(p2sh, send_amount)
    txid = b2x(lx(b2x(fund_txid)))
    return txid
예제 #22
0
# ========================= TX1: CREATE BITCOIN P2SH FROM SCRIPT =========================
txin_scriptPubKey = zec_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)
print('Alice -- send funds to this p2sh address to initiate atomic swap:',
      p2sh)

response = input(
    "Alice -- Type 'enter' to allow zbxcat to fund the Zcash p2sh on your behalf:"
)
send_amount = 10.0 * COIN
fund_tx = zcashd.sendtoaddress(txin_p2sh_address, send_amount)
print(
    'Bob -- Alice send fund tx to the Zcash p2sh. Please wait for confirmation. Txid:',
    b2x(lx(b2x(fund_tx))))

# ========================= CONFIRM ZCASH FUNDING TX TO P2SH =========================
zcashd.importaddress(p2sh)

fund_txinfo = zcashd.gettransaction(fund_tx)
fund_details = fund_txinfo[
    'details']  # "fund_details" is an array, for now we can assume it only has one destination address
outputAddress = fund_details[0]['address']
fund_vout = fund_details[0]['vout']
if (outputAddress != p2sh):
    print(
        'Fund tx sent to wrong address! p2sh was {0}, funding tx was sent to {1}'
        .format(p2sh, outputAddress))
    quit()
# Get amount in address
예제 #23
0
 def getbestblockhash(self):
     """Return hash of best (tip) block in longest block chain."""
     return lx(self._call('getbestblockhash'))
예제 #24
0
from zcash.core.scripteval import VerifyScript, SCRIPT_VERIFY_P2SH
from zcash.wallet import CBitcoinAddress, CBitcoinSecret

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)

# 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('7e195aa3de827814f172c362fcf838d92ba10e3f9fdd9c3ecaf79522b311b22d')
vout = 0

# Create the txin structure, which includes the outpoint. The scriptSig
# defaults to being empty.
txin = CMutableTxIn(COutPoint(txid, vout))

# We also need the scriptPubKey of the output we're spending because
# SignatureHash() replaces the transaction scriptSig's with it.
#
# Here we'll create that scriptPubKey from scratch using the pubkey that
# corresponds to the secret key we generated above.
txin_scriptPubKey = CScript(
    [OP_DUP, OP_HASH160,
     Hash160(seckey.pub), OP_EQUALVERIFY, OP_CHECKSIG])
예제 #25
0
파일: zXcat.py 프로젝트: jasondavies/ZBXCAT
def auto_redeem(contract, secret):
    # How to find redeemScript and redeemblocknum from blockchain?
    print("Contract in auto redeem", contract.__dict__)
    p2sh = contract.p2sh
    #checking there are funds in the address
    amount = check_funds(p2sh)
    if (amount == 0):
        print("address ", p2sh, " not funded")
        quit()
    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))

        # Parsing redeemblocknum from the redeemscript of the p2sh
        redeemblocknum = find_redeemblocknum(contract)
        blockcount = zcashd.getblockcount()
        print("\nCurrent blocknum at time of redeem on Zcash chain:",
              blockcount)
        if blockcount < redeemblocknum:
            redeemPubKey = find_redeemAddr(contract)
            print('redeemPubKey', redeemPubKey)
        else:
            print("nLocktime exceeded, refunding")
            redeemPubKey = find_refundAddr(contract)
            print('refundPubKey', redeemPubKey)
        # redeemPubKey = CBitcoinAddress.from_scriptPubKey(redeemPubKey)
        # exit()

        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])
        # nLockTime needs to be at least as large as parameter of CHECKLOCKTIMEVERIFY for script to verify
        # TODO: these things like redeemblocknum should really be properties of a tx class...
        # Need: redeemblocknum, zec_redeemScript, secret (for creator...), txid, redeemer...
        if blockcount >= redeemblocknum:
            print("\nLocktime exceeded")
            tx.nLockTime = redeemblocknum
        sighash = SignatureHash(zec_redeemScript, tx, 0, SIGHASH_ALL)
        # TODO: figure out how to better protect privkey
        privkey = zcashd.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, zec_redeemScript])

        # exit()

        # print("txin.scriptSig", b2x(txin.scriptSig))
        txin_scriptPubKey = zec_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)