def run_test(self):
        tmpdir = self.options.tmpdir
        nodes = self.nodes

        nodes[0].extkeyimportmaster(nodes[0].mnemonic('new')['master'])
        nodes[1].extkeyimportmaster(
            'abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb'
        )

        address0 = nodes[0].getnewaddress()  # Will be different each run
        address1 = nodes[1].getnewaddress()
        assert (address1 == 'pX9N6S76ZtA5BfsiJmqBbjaEgLMHpt58it')

        sx_addr0 = nodes[0].getnewstealthaddress()
        nodes[1].sendtypeto('rhom', 'rhom', [
            {
                'address': sx_addr0,
                'amount': 20
            },
        ])

        ro = nodes[0].smsglocalkeys()
        assert (len(ro['wallet_keys']) == 0)

        ro = nodes[0].smsgaddlocaladdress(address0)
        assert ('Receiving messages enabled for address' in ro['result'])

        ro = nodes[0].smsglocalkeys()
        assert (len(ro['wallet_keys']) == 1)

        ro = nodes[1].smsgaddaddress(address0,
                                     ro['wallet_keys'][0]['public_key'])
        assert (ro['result'] == 'Public key added to db.')

        text_1 = "['data':'test','value':1]"
        ro = nodes[1].smsgsend(address1, address0, text_1, True, 4, True)
        assert (ro['result'] == 'Not Sent.')
        assert (isclose(ro['fee'], 0.00086600))

        ro = nodes[1].smsgsend(address1, address0, text_1, True, 4)
        assert (ro['result'] == 'Sent.')

        self.stakeBlocks(1, nStakeNode=1)
        for i in range(20):
            nodes[0].sendtypeto('rhom', 'anon', [
                {
                    'address': sx_addr0,
                    'amount': 0.5
                },
            ])
        self.waitForSmsgExchange(1, 1, 0)

        ro = nodes[0].smsginbox()
        assert (len(ro['messages']) == 1)
        assert (ro['messages'][0]['text'] == text_1)

        self.log.info('Test smsgimportprivkey and smsgdumpprivkey')
        test_privkey = '7pHSJFY1tNwi6d68UttGzB8YnXq2wFWrBVoadLv4Y6ekJD3L1iKs'
        address0_1 = 'pasdoMwEn35xQUXFvsChWAQjuG8rEKJQW9'
        nodes[0].smsgimportprivkey(test_privkey, 'smsg test key')
        assert (nodes[0].smsgdumpprivkey(address0_1) == test_privkey)

        text_2 = "['data':'test','value':2]"
        ro = nodes[0].smsglocalkeys()
        assert (len(ro['smsg_keys']) == 1)
        assert (ro['smsg_keys'][0]['address'] == address0_1)

        ro = nodes[1].smsgaddaddress(address0_1,
                                     ro['smsg_keys'][0]['public_key'])
        assert (ro['result'] == 'Public key added to db.')

        ro = nodes[1].smsgsend(address1, address0_1, text_2, True, 4)
        assert (ro['result'] == 'Sent.')

        self.stakeBlocks(1, nStakeNode=1)
        self.waitForSmsgExchange(2, 1, 0)

        ro = nodes[0].smsginbox()
        assert (len(ro['messages']) == 1)
        assert (ro['messages'][0]['text'] == text_2)

        nodes[0].encryptwallet('qwerty234')
        time.sleep(2)

        ro = nodes[0].getwalletinfo()
        assert (ro['encryptionstatus'] == 'Locked')

        localkeys0 = nodes[0].smsglocalkeys()
        assert (len(localkeys0['smsg_keys']) == 1)
        assert (len(localkeys0['wallet_keys']) == 1)
        assert (localkeys0['smsg_keys'][0]['address'] == address0_1)
        assert (localkeys0['wallet_keys'][0]['address'] == address0)

        text_3 = "['data':'test','value':3]"
        ro = nodes[0].smsglocalkeys()
        assert (len(ro['smsg_keys']) == 1)
        assert (ro['smsg_keys'][0]['address'] == address0_1)

        ro = nodes[1].smsgsend(address1, address0, 'Non paid msg')
        assert (ro['result'] == 'Sent.')

        ro = nodes[1].smsgsend(address1, address0_1, text_3, True, 4)
        assert (ro['result'] == 'Sent.')
        assert (len(ro['txid']) == 64)

        self.sync_all()
        self.stakeBlocks(1, nStakeNode=1)
        self.waitForSmsgExchange(4, 1, 0)

        msgid = ro['msgid']
        for i in range(5):
            try:
                ro = nodes[1].smsg(msgid)
                assert (ro['location'] == 'outbox')
                break
            except Exception as e:
                time.sleep(1)
        assert (ro['text'] == text_3)
        assert (ro['from'] == address1)
        assert (ro['to'] == address0_1)

        ro = nodes[0].walletpassphrase("qwerty234", 300)
        ro = nodes[0].smsginbox()
        assert (len(ro['messages']) == 2)
        flat = self.dumpj(ro)
        assert ('Non paid msg' in flat)
        assert (text_3 in flat)

        ro = nodes[0].walletlock()

        ro = nodes[0].smsginbox("all")
        assert (len(ro['messages']) == 4)
        flat = self.dumpj(ro)
        assert (flat.count('Wallet is locked') == 2)

        ro = nodes[0].smsg(msgid)
        assert (ro['read'] == True)

        ro = nodes[0].smsg(msgid, {'setread': False})
        assert (ro['read'] == False)

        ro = nodes[0].smsg(msgid, {'delete': True})
        assert (ro['operation'] == 'Deleted')

        try:
            ro = nodes[0].smsg(msgid)
            assert (False), 'Read deleted msg.'
        except:
            pass

        ro = nodes[0].smsggetpubkey(address0_1)
        assert (
            ro['publickey'] == 'h2UfzZxbhxQPcXDfYTBRGSC7GM77qrLjhtqcmfAnAia9')

        filepath = tmpdir + '/sendfile.txt'
        msg = b"msg in file\0after null sep"
        with open(filepath, 'wb', encoding=None) as fp:
            fp.write(msg)

        sendoptions = {'fromfile': True}
        ro = nodes[1].smsgsend(address1, address0_1, filepath, True, 4, False,
                               sendoptions)
        assert (ro['result'] == 'Sent.')
        msgid = ro['msgid']

        sendoptions = {'decodehex': True}
        ro = nodes[1].smsgsend(address1, address0_1,
                               binascii.hexlify(msg).decode("utf-8"), True, 4,
                               False, sendoptions)
        msgid2 = ro['msgid']
        self.stakeBlocks(1, nStakeNode=1)

        for i in range(5):
            try:
                ro = nodes[1].smsg(msgid, {'encoding': 'hex'})
                assert (ro['location'] == 'outbox')
                break
            except:
                time.sleep(1)
        assert (msg == bytes.fromhex(ro['hex'][:-2])
                )  # Extra null byte gets tacked on

        for i in range(5):
            try:
                ro = nodes[1].smsg(msgid2, {'encoding': 'hex'})
                assert (ro['location'] == 'outbox')
                break
            except:
                time.sleep(1)
        assert (msg == bytes.fromhex(ro['hex'][:-2]))
        assert (ro['daysretention'] == 4)

        ro = nodes[0].smsgoptions('list', True)
        assert (len(ro['options']) == 3)
        assert (len(ro['options'][0]['description']) > 0)

        ro = nodes[0].smsgoptions('set', 'newAddressAnon', 'false')
        assert ('newAddressAnon = false' in json.dumps(ro))

        addr = nodes[0].getnewaddress('smsg test')
        pubkey = nodes[0].getaddressinfo(addr)['pubkey']
        ro = nodes[1].smsgaddaddress(addr, pubkey)
        assert ('Public key added to db' in json.dumps(ro))

        # Wait for sync
        i = 0
        for i in range(10):
            ro = nodes[0].smsginbox('all')
            if len(ro['messages']) >= 5:
                break
            time.sleep(1)
        assert (i < 10)

        self.log.info('Test filtering')
        ro = nodes[0].smsginbox('all', "'vAlue':2")
        assert (len(ro['messages']) == 1)

        ro = nodes[1].smsgoutbox('all', "'vAlue':2")
        assert (len(ro['messages']) == 1)

        self.log.info('Test clear and rescan')
        ro = nodes[0].smsginbox('clear')
        assert ('Deleted 5 messages' in ro['result'])

        ro = nodes[0].walletpassphrase("qwerty234", 300)
        ro = nodes[0].smsgscanbuckets()
        assert ('Scan Buckets Completed' in ro['result'])

        ro = nodes[0].smsginbox('all')
        # Recover 5 + 1 dropped msg
        assert (len(ro['messages']) == 6)

        self.log.info('Test smsglocalkeys')
        addr = nodes[0].getnewaddress()

        ro = nodes[0].smsglocalkeys('recv', '+', addr)
        assert ('Address not found' in ro['result'])
        ro = nodes[0].smsglocalkeys('anon', '+', addr)
        assert ('Address not found' in ro['result'])

        ro = nodes[0].smsgaddlocaladdress(addr)
        assert ('Receiving messages enabled for address' in ro['result'])

        ro = nodes[0].smsglocalkeys('recv', '-', addr)
        assert ('Receive off' in ro['key'])
        assert (addr in ro['key'])

        ro = nodes[0].smsglocalkeys('anon', '-', addr)
        assert ('Anon off' in ro['key'])
        assert (addr in ro['key'])

        ro = nodes[0].smsglocalkeys('all')

        n = getIndexAtProperty(ro['wallet_keys'], 'address', addr)
        assert (ro['wallet_keys'][n]['receive'] == '0')
        assert (ro['wallet_keys'][n]['anon'] == '0')

        self.log.info('Test smsgpurge')
        ro = nodes[0].smsg(msgid, {'encoding': 'hex'})
        assert (ro['msgid'] == msgid)

        nodes[0].smsgpurge(msgid)

        try:
            nodes[0].smsg(msgid, {'encoding': 'hex'})
            assert (False), 'Purged message in inbox'
        except JSONRPCException as e:
            assert ('Unknown message id' in e.error['message'])

        ro = nodes[0].smsgbuckets()
        assert (int(ro['total']['numpurged']) == 1)
        # Sum all buckets
        num_messages = 0
        num_active = 0
        for b in ro['buckets']:
            num_messages += int(b['no. messages'])
            num_active += int(b['active messages'])
        assert (num_messages == num_active + 1)

        self.log.info('Test listunspent include_immature')
        without_immature = nodes[1].listunspent()

        with_immature = nodes[1].listunspent(
            query_options={'include_immature': True})
        assert (len(with_immature) > len(without_immature))

        self.log.info('Test encoding options')
        options = {'encoding': 'hex'}
        ro = nodes[0].smsginbox('all', '', options)
        assert (len(ro['messages']) == 5)
        for msg in ro['messages']:
            assert ('hex' in msg)
        options = {'encoding': 'text'}
        ro = nodes[0].smsginbox('all', '', options)
        assert (len(ro['messages']) == 5)
        for msg in ro['messages']:
            assert ('text' in msg)
        options = {'encoding': 'none'}
        ro = nodes[0].smsginbox('all', '', options)
        assert (len(ro['messages']) == 5)
        for msg in ro['messages']:
            assert ('text' not in msg)
            assert ('hex' not in msg)

        self.log.info('Test disablewallet')
        assert ('SMSG'
                in self.dumpj(nodes[2].getnetworkinfo()['localservicesnames']))
        assert_raises_rpc_error(-32601, 'Method not found',
                                nodes[2].getwalletinfo)
        for i in range(20):
            if nodes[0].smsgbuckets('total')['total']['messages'] != nodes[
                    2].smsgbuckets('total')['total']['messages']:
                time.sleep(0.5)
                continue
            break
        assert (nodes[0].smsgbuckets('total')['total']['messages'] ==
                nodes[2].smsgbuckets('total')['total']['messages'])

        self.log.info('Test smsggetinfo and smsgsetwallet')
        ro = nodes[0].smsggetinfo()
        assert (ro['enabled'] is True)
        assert (ro['active_wallet'] == '')
        assert_raises_rpc_error(-1, 'Wallet not found: "abc"',
                                nodes[0].smsgsetwallet, 'abc')
        nodes[0].smsgsetwallet()
        ro = nodes[0].smsggetinfo()
        assert (ro['enabled'] is True)
        assert (ro['active_wallet'] == 'Not set.')
        nodes[0].createwallet('new_wallet')
        assert (len(nodes[0].listwallets()) == 2)
        nodes[0].smsgsetwallet('new_wallet')
        ro = nodes[0].smsggetinfo()
        assert (ro['enabled'] is True)
        assert (ro['active_wallet'] == 'new_wallet')
        nodes[0].smsgdisable()
        ro = nodes[0].smsggetinfo()
        assert (ro['enabled'] is False)
        nodes[0].smsgenable()
        ro = nodes[0].smsggetinfo()
        assert (ro['enabled'] is True)

        self.log.info('Test funding from RCT balance')
        nodes[1].smsginbox()  # Clear inbox
        ro = nodes[1].smsgaddlocaladdress(address1)
        assert ('Receiving messages enabled for address' in ro['result'])

        msg = 'Test funding from RCT balance'
        sendoptions = {'fund_from_rct': True, 'rct_ring_size': 6}
        sent_msg = nodes[0].smsgsend(address0, address1, msg, True, 4, False,
                                     sendoptions)
        assert (sent_msg['result'] == 'Sent.')
        fund_tx = nodes[0].getrawtransaction(sent_msg['txid'], True)
        assert (fund_tx['vin'][0]['type'] == 'anon')

        ro = nodes[0].smsgoutbox('all', '', {'sending': True})
        assert (ro['messages'][0]['msgid'] == sent_msg['msgid'])

        sync_mempools([nodes[0], nodes[1]])
        self.stakeBlocks(1, nStakeNode=1)
        i = 0
        for i in range(20):
            ro = nodes[1].smsginbox()
            if len(ro['messages']) > 0:
                break
            time.sleep(1)
        assert (i < 19)
        assert (msg == ro['messages'][0]['text'])

        ro = nodes[0].smsgoutbox('all', '', {'sending': True})
        assert (len(ro['messages']) == 0)
    def test_cttx(self):
        nodes = self.nodes
        # Test confidential transactions
        addrA_sx = nodes[0].getnewstealthaddress() # party A
        addrB_sx = nodes[1].getnewstealthaddress() # party B

        outputs = [ {
            'address':addrA_sx,
            'type':'blind',
            'amount':100,
        }, {
            'address':addrB_sx,
            'type':'blind',
            'amount':100,
        }, ]
        ro = nodes[0].createrawparttransaction([], outputs)

        ro = nodes[0].fundrawtransactionfrom('standard', ro['hex'], {}, ro['amounts'])
        rawtx = ro['hex']

        ro = nodes[0].signrawtransactionwithwallet(rawtx)
        assert(ro['complete'] == True)

        ro = nodes[0].sendrawtransaction(ro['hex'])
        txnid = ro

        self.stakeBlocks(1)

        ro = nodes[0].getwalletinfo()
        assert(isclose(ro['blind_balance'], 100.0))

        ro = nodes[0].filtertransactions()
        n = getIndexAtProperty(ro, 'txid', txnid)
        assert(n > -1)
        assert(isclose(ro[n]['amount'], -100.00203200))

        ro = nodes[1].getwalletinfo()
        assert(isclose(ro['blind_balance'], 100.0))

        ro = nodes[1].filtertransactions()
        n = getIndexAtProperty(ro, 'txid', txnid)
        assert(n > -1)
        assert(isclose(ro[n]['amount'], 100.0))


        # Initiate A -> B
        # A has address (addrB_sx) of B

        amountA = 7.0
        amountB = 7.0

        secretA = os.urandom(32)
        secretAHash = sha256(secretA)
        lockTime = int(time.time()) + 10000 # future locktime


        destA = nodes[0].derivefromstealthaddress(addrA_sx)
        pkh0_0 = b58decode(destA['address'])[1:-4]

        ro = nodes[0].derivefromstealthaddress(addrA_sx, destA['ephemeral_pubkey'])
        privKeyA = ro['privatekey']
        pubKeyA = ro['pubkey']


        destB = nodes[0].derivefromstealthaddress(addrB_sx)
        pkh1_0 = b58decode(destB['address'])[1:-4]

        ro = nodes[1].derivefromstealthaddress(addrB_sx, destB['ephemeral_pubkey'])
        privKeyB = ro['privatekey']
        pubKeyB = ro['pubkey']


        scriptInitiate = CreateAtomicSwapScript(payTo=pkh1_0, refundTo=pkh0_0, lockTime=lockTime, secretHash=secretAHash)
        p2sh_initiate = script_to_p2sh_part(scriptInitiate)

        outputs = [ {
            'address':p2sh_initiate,
            'pubkey':destB['pubkey'],
            'type':'blind',
            'amount':amountA,
        }, ]
        ro = nodes[0].createrawparttransaction([], outputs)
        ro = nodes[0].fundrawtransactionfrom('blind', ro['hex'], {}, ro['amounts'])
        output_amounts_i = ro['output_amounts']
        ro = nodes[0].signrawtransactionwithwallet(ro['hex'])
        assert(ro['complete'] == True)
        rawtx_i = ro['hex']


        rawtx_i_refund = createRefundTxCT(nodes[0], rawtx_i, output_amounts_i, scriptInitiate, lockTime, privKeyA, pubKeyA, addrA_sx)
        ro = nodes[0].testmempoolaccept([rawtx_i_refund,])
        print(ro)
        assert('non-final' in ro[0]['reject-reason'])

        txnid1 = nodes[0].sendrawtransaction(rawtx_i)
        self.stakeBlocks(1)


        # Party A sends B rawtx_i/txnid1, script and output_amounts_i


        # auditcontract
        # Party B extracts the secrethash and verifies the txn:

        ro = nodes[1].decoderawtransaction(rawtx_i)
        n = getOutputByAddr(ro, p2sh_initiate)
        valueCommitment = ro['vout'][n]['valueCommitment']

        amount = output_amounts_i[str(n)]['value']
        blind = output_amounts_i[str(n)]['blind']

        assert(nodes[1].verifycommitment(valueCommitment, blind, amount)['result'] == True)



        # Participate B -> A
        # needs address and publickey from A, amount and secretAHash

        lockTimeP = int(time.time()) + 10000 # future locktime
        scriptParticipate = CreateAtomicSwapScript(payTo=pkh0_0, refundTo=pkh1_0, lockTime=lockTimeP, secretHash=secretAHash)
        p2sh_participate = script_to_p2sh_part(scriptParticipate)

        outputs = [ {
            'address':p2sh_participate,
            'pubkey':destA['pubkey'],
            'type':'blind',
            'amount':amountB,
        }, ]

        ro = nodes[1].createrawparttransaction([], outputs)
        ro = nodes[1].fundrawtransactionfrom('blind', ro['hex'], {}, ro['amounts'])
        output_amounts_p = ro['output_amounts']
        ro = nodes[1].signrawtransactionwithwallet(ro['hex'])
        rawtx_p = ro['hex']

        rawtx_p_refund = createRefundTxCT(nodes[1], rawtx_p, output_amounts_p, scriptParticipate, lockTime, privKeyB, pubKeyB, addrB_sx)
        ro = nodes[1].testmempoolaccept([rawtx_p_refund,])
        assert('non-final' in ro[0]['reject-reason'])

        txnid_p = nodes[0].sendrawtransaction(rawtx_p)
        self.stakeBlocks(1)
        assert(txnid_p in nodes[0].getblock(nodes[0].getblockhash(nodes[0].getblockcount()))['tx'])

        # B sends output_amounts to A

        # Party A Redeem/Claim from participate txn
        # Party A spends the funds from the participate txn, and to do so must reveal secretA

        rawtxclaimA = createClaimTxCT(nodes[0], rawtx_p, output_amounts_p, scriptParticipate, secretA, privKeyA, pubKeyA, addrA_sx)
        txnidAClaim = nodes[0].sendrawtransaction(rawtxclaimA)


        # Party B claims from initiate txn
        # Get secret from txnidAClaim

        #ro = nodes[1].getrawtransaction(txnidAClaim, True)
        #print('ro', json.dumps(ro, indent=4, default=jsonDecimal))

        rawtxclaimB = createClaimTxCT(nodes[1], rawtx_i, output_amounts_i, scriptInitiate, secretA, privKeyB, pubKeyB, addrB_sx)
        txnidBClaim = nodes[0].sendrawtransaction(rawtxclaimB)

        nodes[0].getmempoolentry(txnidAClaim)
        nodes[0].getmempoolentry(txnidBClaim)


        # Test Refund expired initiate tx
        secretA = os.urandom(32)
        secretAHash = sha256(secretA)
        lockTime = int(time.time()) - 100000 # past locktime

        amountA = 7.1
        scriptInitiate = CreateAtomicSwapScript(payTo=pkh1_0, refundTo=pkh0_0, lockTime=lockTime, secretHash=secretAHash)
        p2sh_initiate = script_to_p2sh_part(scriptInitiate)

        outputs = [ {
            'address':p2sh_initiate,
            'pubkey':destB['pubkey'],
            'type':'blind',
            'amount':amountA,
        }, ]
        ro = nodes[0].createrawparttransaction([], outputs)
        ro = nodes[0].fundrawtransactionfrom('blind', ro['hex'], {}, ro['amounts'])

        r2 = nodes[0].verifyrawtransaction(ro['hex'])
        assert(r2['complete'] == False)

        output_amounts_i = ro['output_amounts']
        ro = nodes[0].signrawtransactionwithwallet(ro['hex'])
        assert(ro['complete'] == True)
        rawtx_i = ro['hex']

        r2 = nodes[0].verifyrawtransaction(rawtx_i)
        assert(r2['complete'] == True)


        rawtx_i_refund = createRefundTxCT(nodes[0], rawtx_i, output_amounts_i, scriptInitiate, lockTime, privKeyA, pubKeyA, addrA_sx)
        ro = nodes[0].testmempoolaccept([rawtx_i_refund,])
        assert('missing-inputs' in ro[0]['reject-reason'])


        txnid1 = nodes[0].sendrawtransaction(rawtx_i)
        ro = nodes[0].getwalletinfo()
        assert(ro['unconfirmed_blind'] > 6.0 and ro['unconfirmed_blind'] < 7.0)

        txnidRefund = nodes[0].sendrawtransaction(rawtx_i_refund)
        nodes[0].getmempoolentry(txnidRefund)

        ro = nodes[0].getwalletinfo()
        assert(ro['unconfirmed_blind'] > 14.0 and ro['unconfirmed_blind'] < 14.1)
    def run_test(self):

        # Check that rhombus has been built with USB device enabled
        config = configparser.ConfigParser()
        if not self.options.configfile:
            self.options.configfile = os.path.dirname(__file__) + "/../config.ini"
        config.read_file(open(self.options.configfile))

        if not config["components"].getboolean("ENABLE_USBDEVICE"):
            raise SkipTest("rhombusd has not been built with usb device enabled.")

        nodes = self.nodes

        nodes[0].extkeyimportmaster('abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb')
        assert(nodes[0].getwalletinfo()['total_balance'] == 100000)

        ro = nodes[1].listdevices()
        assert(len(ro) == 1)
        assert(ro[0]['vendor'] == 'Debug')
        assert(ro[0]['product'] == 'Device')

        ro = nodes[1].getdeviceinfo()
        assert(ro['device'] == 'debug')

        ro = nodes[1].getdevicepublickey('0')
        assert(ro['address'] == 'praish9BVxVdhykpqBYEs6L65AQ7iKd9z1')
        assert(ro['path'] == "m/44'/1'/0'/0")

        ro = nodes[1].getdevicepublickey('0/1')
        assert(ro['address'] == 'peWvjy33QptC2Gz3ww7jTTLPjC2QJmifBR')
        assert(ro['path'] == "m/44'/1'/0'/0/1")

        ro = nodes[1].getdevicexpub("m/44'/1'/0'", "")
        assert(ro == 'pparszKXPyRegWYwPacdPduNPNEryRbZDCAiSyo8oZYSsbTjc6FLP4TCPEX58kAeCB6YW9cSdR6fsbpeWDBTgjbkYjXCoD9CNoFVefbkg3exzpQE')

        message = 'This is just a test message'
        sig = nodes[1].devicesignmessage('0/1', message)
        assert(True == nodes[1].verifymessage('peWvjy33QptC2Gz3ww7jTTLPjC2QJmifBR', sig, message))

        ro = nodes[1].initaccountfromdevice('test_acc')
        assert(ro['extkey'] == 'pparszKXPyRegWYwPacdPduNPNEryRbZDCAiSyo8oZYSsbTjc6FLP4TCPEX58kAeCB6YW9cSdR6fsbpeWDBTgjbkYjXCoD9CNoFVefbkg3exzpQE')
        assert(ro['path'] == "m/44'/1'/0'")

        ro = nodes[1].extkey('list', 'true')
        assert(len(ro) == 1)
        assert(ro[0]['path'] == "m/44h/1h/0h")
        assert(ro[0]['epkey'] == 'pparszKXPyRegWYwPacdPduNPNEryRbZDCAiSyo8oZYSsbTjc6FLP4TCPEX58kAeCB6YW9cSdR6fsbpeWDBTgjbkYjXCoD9CNoFVefbkg3exzpQE')
        assert(ro[0]['label'] == 'test_acc')
        assert(ro[0]['hardware_device'] == '0xffff 0x0001')

        ro = nodes[1].extkey('account')
        n = getIndexAtProperty(ro['chains'], 'use_type', 'stealth_spend')
        assert(n > -1)
        assert(ro['chains'][n]['path'] == "m/0h/444445h")


        addr1_0 = nodes[1].getnewaddress('lbl1_0')
        ro = nodes[1].filteraddresses()
        assert(len(ro) == 1)
        assert(ro[0]['path'] == 'm/0/0')
        assert(ro[0]['owned'] == 'true')
        assert(ro[0]['label'] == 'lbl1_0')

        va_addr1_0 = nodes[1].getaddressinfo(addr1_0)
        assert(va_addr1_0['ismine'] == True)
        assert(va_addr1_0['iswatchonly'] == False)
        assert(va_addr1_0['isondevice'] == True)
        assert(va_addr1_0['path'] == 'm/0/0')

        try:
            nodes[1].getnewstealthaddress()
            raise AssertionError('Should have failed.')
        except JSONRPCException as e:
            pass

        extaddr1_0 = nodes[1].getnewextaddress()

        txnid0 = nodes[0].sendtoaddress(addr1_0, 6)
        txnid1 = nodes[0].sendtoaddress(extaddr1_0, 6)

        self.stakeBlocks(1)
        block_txns = nodes[0].getblock(nodes[0].getblockhash(nodes[0].getblockcount()))['tx']
        assert(txnid0 in block_txns)
        assert(txnid1 in block_txns)

        ro = nodes[1].getwalletinfo()
        assert(isclose(ro['balance'], 12.0))

        addr0_0 = nodes[0].getnewaddress()
        hexRaw = nodes[1].createrawtransaction([], {addr0_0:10})
        hexFunded = nodes[1].fundrawtransaction(hexRaw)['hex']
        txDecoded = nodes[1].decoderawtransaction(hexFunded)

        ro = nodes[1].devicesignrawtransaction(hexFunded)
        assert(ro['complete'] == True)

        txnid1 = nodes[1].sendrawtransaction(ro['hex'])

        self.sync_all()
        self.stakeBlocks(1)

        ro = nodes[1].devicesignrawtransaction(hexFunded)
        assert(ro['errors'][0]['error'] == 'Input not found or already spent')

        prevtxns = []
        for vin in txDecoded['vin']:
            rtx = nodes[1].getrawtransaction(vin['txid'], True)
            prev_out = rtx['vout'][vin['vout']]
            prevtxns.append({'txid': vin['txid'], 'vout': vin['vout'], 'scriptPubKey': prev_out['scriptPubKey']['hex'], 'amount': prev_out['value']})
        ro = nodes[1].devicesignrawtransaction(hexFunded, prevtxns, ['0/0', '2/0'])
        assert(ro['complete'] == True)

        ro = nodes[1].listunspent()
        assert(ro[0]['ondevice'] == True)

        txnid2 = nodes[1].sendtoaddress(addr0_0, 0.1)

        self.sync_all()
        nodes[0].syncwithvalidationinterfacequeue()
        assert(nodes[0].filtertransactions()[0]['txid'] == txnid2)

        hwsxaddr = nodes[1].devicegetnewstealthaddress()
        assert(hwsxaddr == 'tps1qqpdwu7gqjqz9s9wfek843akvkzvw0xq3tkzs93sj4ceq60cp54mvzgpqf4tp6d7h0nza2xe362am697dax24hcr33yxqwvq58l5cf6j6q5hkqqqgykgrc')

        hwsxaddr2 = nodes[1].devicegetnewstealthaddress('lbl2 4bits', '4', '0xaaaa', True)
        assert(hwsxaddr2 == 'tps1qqpewyspjp93axk82zahx5xfjyprpvypfgnp95n9aynxxw3w0qs63acpq0s5z2rwk0raczg8jszl9qy5stncud76ahr5etn9hqmp30e3e86w2qqypgh9sgv0')

        ro = nodes[1].getaddressinfo(hwsxaddr2)
        assert(ro['prefix_num_bits'] == 4)
        assert(ro['prefix_bitfield'] == '0x000a')
        assert(ro['isondevice'] == True)

        ro = nodes[1].liststealthaddresses()
        assert(len(ro[0]['Stealth Addresses']) == 2)


        ro = nodes[1].filteraddresses()
        assert(len(ro) == 3)


        txnid3 = nodes[0].sendtoaddress(hwsxaddr, 0.1, '', '', False, 'test msg')
        self.stakeBlocks(1)

        ro = nodes[1].listtransactions()
        assert(len(ro) == 5)
        assert('test msg' in self.dumpj(ro[4]))

        ro = nodes[1].listunspent()
        inputs = []
        for output in ro:
            if output['txid'] == txnid3:
                inputs.append({'txid' : txnid3, 'vout' : output['vout']})
                break
        assert(len(inputs) > 0)
        hexRaw = nodes[1].createrawtransaction(inputs, {addr0_0:0.09})

        ro = nodes[1].devicesignrawtransaction(hexRaw)
        assert(ro['complete'] == True)

        # import privkey in node2
        rootkey = nodes[2].extkeyaltversion('xparFdrwJK7K2nfYzrkEqAKr5EcJNdY4c6ZNoLFFx1pMXQSQpo5MAufjogrS17RkqsLAijZJaBDHhG3G7SuJjtsTmRRTEKZDzGMnVCeX59cQCiR')
        ro = nodes[2].extkey('import', rootkey, 'master key', True)
        ro = nodes[2].extkey('setmaster', ro['id'])
        assert(ro['result'] == 'Success.')
        ro = nodes[2].extkey('deriveaccount', 'test account')
        ro = nodes[2].extkey('setdefaultaccount', ro['account'])
        assert(ro['result'] == 'Success.')

        ro = nodes[1].extkey('account')
        n = getIndexAtProperty(ro['chains'], 'use_type', 'stealth_spend')
        assert(n > -1)
        assert(ro['chains'][n]['path'] == "m/0h/444445h")

        addrtest = nodes[2].getnewaddress()
        ro = nodes[1].getdevicepublickey('0/0')
        assert(addrtest == ro['address'])


        addrtest = nodes[2].getnewstealthaddress('', '0', '', True, True)
        assert(addrtest == hwsxaddr)

        addrtest2 = nodes[2].getnewstealthaddress('lbl2 4bits', '4', '0xaaaa', True, True)
        assert(addrtest2 == hwsxaddr2)

        extaddr2_0 = nodes[2].getnewextaddress()
        assert(extaddr1_0 == extaddr2_0)

        # Ensure account matches after node restarts
        account1 = nodes[1].extkey('account')
        self.restart_node(1)
        account1_r = nodes[1].extkey('account')
        assert(json.dumps(account1) == json.dumps(account1_r))

        # Test for coverage
        assert(nodes[1].promptunlockdevice()['sent'] is True)
        assert(nodes[1].unlockdevice('123')['unlocked'] is True)
        assert_raises_rpc_error(-8, 'Neither a pin nor a passphraseword was provided.', nodes[1].unlockdevice)
        assert('complete' in nodes[1].devicebackup())
        assert('complete' in nodes[1].deviceloadmnemonic())
    def test_standardtx(self):
        nodes = self.nodes

        addrA_0 = nodes[0].getnewaddress() # party A
        addrB_0 = nodes[1].getnewaddress() # party B

        # Initiate A -> B
        # A has address (addrB_0) of B

        amountA = 5.0
        amountB = 5.0
        pkh0_0 = b58decode(addrA_0)[1:-4]
        pkh1_0 = b58decode(addrB_0)[1:-4]

        secretA = os.urandom(32)
        secretAHash = sha256(secretA)

        lockTime = int(time.time()) + 10000 # future locktime

        scriptInitiate = CreateAtomicSwapScript(payTo=pkh1_0, refundTo=pkh0_0, lockTime=lockTime, secretHash=secretAHash)
        p2sh_initiate = script_to_p2sh_part(scriptInitiate)
        rawtxInitiate = nodes[0].createrawtransaction([], {p2sh_initiate:amountA})
        rawtxInitiate = nodes[0].fundrawtransaction(rawtxInitiate)['hex']
        ro = nodes[0].signrawtransactionwithwallet(rawtxInitiate)
        assert(ro['complete'] == True)
        rawtxInitiate = ro['hex']

        rawtx1refund = createRefundTx(nodes[0], rawtxInitiate, scriptInitiate, lockTime, addrA_0, addrA_0)

        nodes[0].sendrawtransaction(rawtxInitiate)
        self.stakeBlocks(1)

        ro = nodes[0].getblockchaininfo()
        assert(ro['mediantime'] < lockTime)
        try:
            txnidrefund = nodes[0].sendrawtransaction(rawtx1refund)
            assert(False)
        except JSONRPCException as e:
            assert('non-final' in e.error['message'])

        # Party A sends B rawtxInitiate/txnid1 and script

        # auditcontract
        # Party B extracts the secrethash and verifies the txn:
        assert(len(scriptInitiate) == 97)
        extractedSecretAHash = scriptInitiate[7:7+32]
        assert(extractedSecretAHash == secretAHash)
        tx1 = nodes[1].decoderawtransaction(rawtxInitiate)
        self.log.info("Verify txn " + tx1['txid']) # TODO

        # Participate B -> A
        # needs address from A, amount and secretAHash

        lockTimeP = int(time.time()) + 10000 # future locktime
        scriptParticipate = CreateAtomicSwapScript(payTo=pkh0_0, refundTo=pkh1_0, lockTime=lockTimeP, secretHash=secretAHash)
        p2sh_participate = script_to_p2sh_part(scriptParticipate)

        rawtx_p = nodes[1].createrawtransaction([], {p2sh_participate:amountB})
        rawtx_p = nodes[1].fundrawtransaction(rawtx_p)['hex']

        ro = nodes[1].signrawtransactionwithwallet(rawtx_p)
        assert(ro['complete'] == True)
        rawtx_p = ro['hex']

        rawtxRefundP = createRefundTx(nodes[1], rawtx_p, scriptParticipate, lockTimeP, addrB_0, addrB_0)

        txnidParticipate = nodes[1].sendrawtransaction(rawtx_p)
        self.sync_all()
        self.stakeBlocks(1)
        assert(txnidParticipate in nodes[0].getblock(nodes[0].getblockhash(nodes[0].getblockcount()))['tx'])

        ro = nodes[0].getblockchaininfo()
        assert(ro['mediantime'] < lockTimeP)
        try:
            txnidrefund = nodes[1].sendrawtransaction(rawtxRefundP)
            assert(False)
        except JSONRPCException as e:
            assert('non-final' in e.error['message'])

        # auditcontract
        # Party A verifies the participate txn from B


        # Party A Redeem/Claim from participate txn
        # Party A spends the funds from the participate txn, and to do so must reveal secretA

        rawtxclaimA = createClaimTx(nodes[0], rawtx_p, scriptParticipate, secretA, addrA_0, addrA_0)
        txnidAClaim = nodes[0].sendrawtransaction(rawtxclaimA)


        # Party B Redeem/Claim from initiate txn
        # Get secret from txnidAClaim

        #ro = nodes[1].getrawtransaction(txnidAClaim, True)
        #print('ro', json.dumps(ro, indent=4, default=jsonDecimal))

        rawtxclaimB = createClaimTx(nodes[1], rawtxInitiate, scriptInitiate, secretA, addrB_0, addrB_0)
        txnidBClaim = nodes[0].sendrawtransaction(rawtxclaimB) # send from staking node to avoid syncing

        self.stakeBlocks(1)
        last_block_txns = nodes[0].getblock(nodes[0].getblockhash(nodes[0].getblockcount()))['tx']
        assert(txnidAClaim in last_block_txns)
        assert(txnidBClaim in last_block_txns)

        ftxB = nodes[1].filtertransactions()
        assert(ftxB[0]['confirmations'] == 1)
        assert(ftxB[0]['outputs'][0]['amount'] < 5.0 and ftxB[-1]['outputs'][0]['amount'] > 4.9)
        assert(isclose(ftxB[1]['outputs'][0]['amount'], -5.0))


        # Test Refund expired initiate tx
        lockTime = int(time.time()) - 100000 # past locktime

        scriptInitiate2 = CreateAtomicSwapScript(payTo=pkh1_0, refundTo=pkh0_0, lockTime=lockTime, secretHash=secretAHash)

        p2sh_initiate = script_to_p2sh_part(scriptInitiate2)
        rawtxInitiate = nodes[0].createrawtransaction([], {p2sh_initiate:6.0})
        rawtxInitiate = nodes[0].fundrawtransaction(rawtxInitiate)['hex']
        ro = nodes[0].signrawtransactionwithwallet(rawtxInitiate)
        assert(ro['complete'] == True)
        rawtxInitiate = ro['hex']


        rawtx2refund = createRefundTx(nodes[0], rawtxInitiate, scriptInitiate2, lockTime, addrA_0, addrA_0)
        txnid2 = nodes[0].sendrawtransaction(rawtxInitiate)

        self.stakeBlocks(1)

        ro = nodes[0].getblockchaininfo()
        assert(ro['mediantime'] > lockTime)

        txnidrefund = nodes[0].sendrawtransaction(rawtx2refund)

        ftxA = nodes[0].filtertransactions()
        n = getIndexAtProperty(ftxA, 'txid', txnidrefund)
        assert(n > -1)
        assert(ftxA[n]['outputs'][0]['amount'] > 5.9 and ftxA[n]['outputs'][0]['amount'] < 6.0)