Beispiel #1
0
def syncWallet(result, wallet, gaitwallet, path):

    hexprivkey = wallet.subkey(1).subkey(result['pointer']).wif()
    hexpubkey = wallet.subkey(1).subkey(result['pointer']).public_copy().sec_as_hex()
    tproxy = Proxy()

    GAKey = gaitwallet.subkey(1).subkey_for_path(path).subkey(result['pointer']).sec_as_hex()

    addrfromapi = P2SHBitcoinAddress.from_redeemScript(CScript(binascii.unhexlify(result['script'])))
    print(addrfromapi)

    #tproxy.call("importprivkey", hexprivkey, "", False)
    print(tproxy.call("createmultisig", 2, [GAKey, hexpubkey])['address'])
def bitcoinrpc(*args):
    host = BITCOIN_RPC_HOST
    if BITCOIN_RPC_USER and BITCOIN_RPC_PASSWORD:
        host = "%s:%s@%s" % (
            quote(BITCOIN_RPC_USER),
            quote(BITCOIN_RPC_PASSWORD),
            host,
        )
    if BITCOIN_RPC_PORT:
        host = "%s:%s" % (host, BITCOIN_RPC_PORT)
    service_url = "%s://%s" % (BITCOIN_RPC_SCHEME, host)
    proxy = Proxy(service_url=service_url)
    result = proxy.call(*args)
    return result
Beispiel #3
0
class BitcoinNode(Node):
    __slots__ = [
        '_path', '_spent_to', '_rpc_connection', '_current_tx_chain_index',
        '_tx_chains'
    ]

    def __init__(self, name, group, ip, docker_image, path):
        super().__init__(name, group, ip, docker_image)
        self._path = path
        self._spent_to = None
        self._rpc_connection = None
        self._current_tx_chain_index = 0
        self._tx_chains = []

    def exec_event_cmd(self, cmd: str, args: List[str] = []):
        if cmd == 'tx':
            self.generate_tx
        elif cmd == 'block':
            self.generate_blocks(amount=1)
        else:
            raise Exception("Unknown cmd {cmd} for node {node}", cmd, self)

    def exec_event_cmd_string(self, cmd: str, args: List[str] = []) -> str:
        if cmd == 'tx':
            # TODO fix transactions
            #return self.generate_tx_string()
            return ""
        elif cmd == 'block':
            return self.generate_blocks_string(amount=1)
        else:
            raise Exception("Unknown cmd {cmd} for node {node}", cmd, self)

    def create_conf_file(self):
        # file is needed for RPC connection
        with open(config.btc_conf_file.format(self.name), 'w') as file:
            file.write('rpcconnect={}\n'.format(self._ip))
            file.write('rpcport={}\n'.format(config.rpc_port))
            file.write('rpcuser={}\n'.format(config.rpc_user))
            file.write('rpcpassword={}\n'.format(config.rpc_password))

    def run(self, connect_to_ips):
        bash.check_output(
            bitcoincmd.start(self._name, str(self._ip), self._docker_image,
                             self._path, connect_to_ips))

    def is_running(self):
        return bash.check_output(dockercmd.check_if_running(
            self._name)) == 'true'

    def close_rpc_connection(self):
        if self._rpc_connection is not None:
            self._rpc_connection.__dict__['_BaseProxy__conn'].close()
            logging.debug('Closed rpc connection to node={}'.format(
                self._name))

    def stop(self):
        # self.execute_rpc('stop')
        # bash.check_output(self.execute_rpc_string(('stop', '')))
        bash.check_output(
            f"docker exec simcoin-{self._name} bitcoin-cli -regtest -rpcuser=admin -rpcpassword=admin  stop"
        )
        logging.info('Send stop to node={}'.format(self.name))

    def get_log_file(self):
        return self._path + config.bitcoin_log_file_name

    def wait_until_rpc_ready(self):
        logging.debug("# Waiting for docker instances to become ready")
        while True:
            try:
                bash.check_output("nc -z -w1 {} {}".format(
                    self._ip, config.rpc_port),
                                  purpose="Wait for port beeing open")
                logging.info(f"Success for {self.ip}")
                break
            except Exception:
                logging.debug("Waiting with netcat until port is open")

        while True:
            try:
                self.execute_rpc('getnetworkinfo')
                break
            except JSONRPCError:
                logging.debug('Waiting until RPC of node={} is ready.'.format(
                    self._name))
                utils.sleep(1)

    def connect_to_rpc(self):
        self._rpc_connection = Proxy(btc_conf_file=config.btc_conf_file.format(
            self.name),
                                     timeout=config.rpc_timeout)

    def rm_peers_file(self):
        return bash.check_output(bitcoincmd.rm_peers(self._name))

    def execute_rpc(self, *args):
        retry = 30
        while retry > 0:
            try:
                return self._rpc_connection.call(args[0], *args[1:])
            except (IOError, CannotSendRequest) as error:
                logging.exception(
                    'Could not execute RPC-call={} on node={} because of error={}.'
                    ' Reconnecting and retrying, {} retries left'.format(
                        args[0], self._name, error, retry))
                retry -= 1
                self.connect_to_rpc()
        raise Exception('Could not execute RPC-call={} on node {}'.format(
            args[0], self._name))

    def transfer_coinbases_to_normal_tx(self):
        for tx_chain in self._tx_chains:
            tx_chain.amount /= 2
            logging.info(
                f'transfer_coinbase_to_normal_tx tx_chain.amount = {tx_chain.amount}'
            )
            tx_chain.amount -= int(config.transaction_fee / 2)
            logging.info(
                f'transfer_coinbase_to_normal_tx tx_chain.amount = {tx_chain.amount}'
            )
            tx_chain.amount = math.floor(
                tx_chain.amount
            )  # TODO find better fix for 'Invalid amount' json_rpc error
            raw_transaction = self.execute_rpc(
                'createrawtransaction', [{
                    'txid': tx_chain.current_unspent_tx,
                    'vout': 0,
                }],
                OrderedDict([
                    (tx_chain.address, str(tx_chain.amount / 100000000)),
                    (self._spent_to.address, str(tx_chain.amount / 100000000))
                ]))
            signed_raw_transaction = self.execute_rpc('signrawtransaction',
                                                      raw_transaction)['hex']
            tx_chain.current_unspent_tx = self.execute_rpc(
                'sendrawtransaction', signed_raw_transaction)

    def generate_blocks(self, amount=1):
        logging.debug('{} trying to generate block'.format(self._name))
        block_hash = self.execute_rpc('generate', amount)
        logging.info('{} generated block with hash={}'.format(
            self._name, block_hash))

    def generate_blocks_string(self, amount=1) -> str:
        return self.execute_rpc_string('generate ', amount)  # TODO fix amount

    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))

    def generate_spent_to_address(self):
        address = self.execute_rpc('getnewaddress')
        seckey = CBitcoinSecret(self.execute_rpc('dumpprivkey', address))
        self._spent_to = SpentToAddress(address, seckey)

    def create_tx_chains(self):
        for unspent_tx in self.execute_rpc('listunspent'):
            seckey = CBitcoinSecret(
                self.execute_rpc('dumpprivkey', unspent_tx['address']))
            tx_chain = TxChain(unspent_tx['txid'], unspent_tx['address'],
                               seckey, unspent_tx['amount'] * 100000000)

            self._tx_chains.append(tx_chain)

    def get_next_tx_chain(self):
        tx_chain = self._tx_chains[self._current_tx_chain_index]
        self._current_tx_chain_index = ((self._current_tx_chain_index + 1) %
                                        len(self._tx_chains))

        return tx_chain
Beispiel #4
0
class BitcoinNode(Node):
    __slots__ = [
        '_path', '_spent_to', '_rpc_connection', '_current_tx_chain_index',
        '_tx_chains'
    ]

    def __init__(self, name, group, ip, path):
        super().__init__(name, group, ip)
        self._path = path
        self._spent_to = None
        self._rpc_connection = None
        self._current_tx_chain_index = 0
        self._tx_chains = []

    def create_conf_file(self):
        # file is needed for RPC connection
        # reading not possible at each node
        # create own file and push
        with open(config.btc_conf_file.format(self.name), 'w') as file:
            file.write('rpcconnect={}\n'.format(self._ip))
            file.write('rpcport={}\n'.format(config.rpc_port))
            file.write('rpcuser={}\n'.format(config.rpc_user))
            file.write('rpcpassword={}\n'.format(config.rpc_password))

    def run(self, connect_to_ips):
        bash.check_output(
            bitcoincmd.start(self._name, str(self._ip), self._path,
                             connect_to_ips))

    def is_running(self):
        return bash.check_output(bitcoincmd.check_if_running(
            self._name)) == 'true'

    def close_rpc_connection(self):
        if self._rpc_connection is not None:
            self._rpc_connection.__dict__['_BaseProxy__conn'].close()
            logging.debug('Closed rpc')

    def stop(self):
        self.execute_rpc('stop')
        logging.info('stopping node {}'.format(self.name))

    def get_log_file(self):
        return self._path + config.bitcoin_log_file_name

    def wait_until_rpc_ready(self):
        while True:
            try:
                bash.check_output("nc -z -w1 {} {}".format(
                    self._ip, config.rpc_port))
                break
            except Exception:
                logging.debug("Port not open")

        while True:
            try:
                self.execute_rpc('getnetworkinfo')
                break
            except JSONRPCError:
                logging.debug('RPC not ready yet, sleeping for 2')
                utils.sleep(2)

    def connect_to_rpc(self):
        self._rpc_connection = Proxy(btc_conf_file=config.btc_conf_file.format(
            self.name),
                                     timeout=config.rpc_timeout)

    def rm_peers_file(self):
        return bash.check_output(bitcoincmd.rm_peers(self._name))

    def execute_rpc(self, *args):
        # No clue whats the optimal
        retry = 10
        while retry > 0:
            try:
                return self._rpc_connection.call(args[0], *args[1:])
            except (IOError, CannotSendRequest) as error:
                logging.exception(
                    'Error: {}.'
                    ' Reconnecting and retrying, {} more tries left'.format(
                        error, retry))
                retry -= 1
                self.connect_to_rpc()

    def transfer_coinbases_to_normal_tx(self):
        # Readable format convert
        for tx_chain in self._tx_chains:
            tx_chain.amount /= 2
            tx_chain.amount -= int(config.transaction_fee / 2)
            raw_transaction = self.execute_rpc(
                'createrawtransaction', [{
                    'txid': tx_chain.current_unspent_tx,
                    'vout': 0,
                }],
                OrderedDict([
                    (tx_chain.address, str(tx_chain.amount / 100000000)),
                    (self._spent_to.address, str(tx_chain.amount / 100000000))
                ]))
            signed_raw_transaction = self.execute_rpc('signrawtransaction',
                                                      raw_transaction)['hex']
            tx_chain.current_unspent_tx = self.execute_rpc(
                'sendrawtransaction', signed_raw_transaction)

    def generate_blocks(self, amount=1):
        logging.debug('{} trying to generate mine'.format(self._name))
        block_hash = self.execute_rpc('generate', amount)
        logging.info('{} mined a block {}'.format(self._name, block_hash))

    def generate_tx(self):
        # Normal transaction signing and raw processing
        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('{} is sending raw transaction'
                      ' (input {} output {} fee {} bytes {})'
                      ' using tx_chain id {}'.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
        #print(tx_chain.current_unspent_tx)
        logging.info('{} send was ok; hash={}'.format(self._name, tx_hash))

    def generate_spent_to_address(self):
        # Get from wallet the list of address or generate one
        address = self.execute_rpc('getnewaddress')
        seckey = CBitcoinSecret(self.execute_rpc('dumpprivkey', address))
        self._spent_to = SpentToAddress(address, seckey)

    def create_tx_chains(self):
        for unspent_tx in self.execute_rpc('listunspent'):
            seckey = CBitcoinSecret(
                self.execute_rpc('dumpprivkey', unspent_tx['address']))
            tx_chain = TxChain(unspent_tx['txid'], unspent_tx['address'],
                               seckey, unspent_tx['amount'] * 100000000)

            self._tx_chains.append(tx_chain)

    def get_next_tx_chain(self):
        tx_chain = self._tx_chains[self._current_tx_chain_index]
        self._current_tx_chain_index = ((self._current_tx_chain_index + 1) %
                                        len(self._tx_chains))

        return tx_chain
Beispiel #5
0
class TX(object):
    def __init__(self, logger=None, test=False):
        self.logger = logger or logging.getLogger(__name__)

        # Setup logging file handler
        self.logger.setLevel(logging.DEBUG)
        self.handler = logging.FileHandler(__name__ + '.log')
        self.handler.setLevel(logging.DEBUG)
        formatter = logging.Formatter('%(asctime)s - %(name)s - ' +
                                      '%(levelname)s:\n\t %(message)s')
        self.handler.setFormatter(formatter)

        self.logger.addHandler(self.handler)
        self.test = test
        # if test:
        #     SelectParams('testnet')
        if not test:
            self.proxy = Proxy()

    def __del__(self):
        self.handler.close()

    ###########################################################################
    ## General TX Functions
    ###########################################################################

    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)

    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

    ###########################################################################
    ## Serialization related
    ###########################################################################

    def serialize_list(self, l):
        '''
            Serializes a python list
        '''
        serial = ""
        for i in range(len(l)):
            serial += l[i]
        return serial

    def get_keys_from_tx(self, serial_tx, n_keys=15):
        '''Extracts n_keys from tx in serial form'''
        # Read in transaction
        temp_tx = CTransaction.deserialize(serial_tx)
        tx = CMutableTransaction.from_tx(temp_tx)

        # Keys are in txin.scriptSig
        txin = tx.vin[0]
        script = txin.scriptSig

        # Extract keys from script
        keys = []
        for i, op in enumerate(script):
            if i in range(1, n_keys + 1):
                keys += [op]

        # Serialize keys in correct order
        serial_keys = ""
        for op in reversed(keys):
            serial_keys += op

        return serial_keys

    def get_keys_from_serial(self, serial, n_keys=15, key_len=16):
        ''' Returns a list of n_keys of key_len extracted from serial'''

        expected = (n_keys * key_len)
        if len(serial) != expected:
            self.logger.error(
                "get_keys_from_serial: serial len is %d " + "expected %d",
                len(serial), expected)
            return []

        keys = []
        for i in range(n_keys):
            keys += [serial[i * key_len:key_len * (i + 1)]]

        return keys

    def get_hashes_from_serial(self, serial, n_hashes, hash_len):
        ''' Returns a list of n_hashes of hash_len extracted from serial'''

        expected = (n_hashes * hash_len)
        if len(serial) != expected:
            self.logger.error(
                "get_hashes_from_serial: serial len is %d " + "expected %d",
                len(serial), expected)
            return []

        hashes = []
        for i in range(n_hashes):
            hashes += [serial[i * hash_len:hash_len * (i + 1)]]

        return hashes

    ###########################################################################
    ## Preimage P2SH wth Refund
    ###########################################################################

    def create_hash_script(self, redeemer_pubkey, hashes):
        '''
            Creates part of the redeem script that deals
            with the hashes
        '''
        script = []
        for h in hashes:
            script += [OP_RIPEMD160, h, OP_EQUALVERIFY]
        script += [redeemer_pubkey, OP_CHECKSIG]
        return script

    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))

    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

    ###########################################################################
    ## Two Party Escrow with Refund
    ###########################################################################

    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))

    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