示例#1
0
    def createNewWalletFromWizard(self):
        entropy = None
        if self.walletCreationPage.isManualEncryption():
            entropy = SecureBinaryData(
                int_to_binary(self.manualEntropyPage.pageFrame.getEntropy()))
        else:
            entropy = self.main.getExtraEntropyForKeyGen()
        self.newWallet = PyBtcWallet().createNewWallet(
            securePassphrase=self.setPassphrasePage.pageFrame.getPassphrase(),
            kdfTargSec=self.walletCreationPage.pageFrame.getKdfSec(),
            kdfMaxMem=self.walletCreationPage.pageFrame.getKdfBytes(),
            shortLabel=self.walletCreationPage.pageFrame.getName(),
            longLabel=self.walletCreationPage.pageFrame.getDescription(),
            doRegisterWithBDM=False,
            extraEntropy=entropy,
        )

        self.newWallet.unlock(securePassphrase=SecureBinaryData(
            self.setPassphrasePage.pageFrame.getPassphrase()))
        # We always want to fill the address pool, right away.
        fillPoolProgress = DlgProgress(self, self.main, HBar=1, \
                                       Title="Creating Wallet")
        fillPoolProgress.exec_(self.newWallet.fillAddressPool,
                               doRegister=False,
                               Progress=fillPoolProgress.UpdateHBar)

        # Reopening from file helps make sure everything is correct -- don't
        # let the user use a wallet that triggers errors on reading it
        wltpath = self.newWallet.walletPath
        walletFromDisk = PyBtcWallet().readWalletFile(wltpath)
        self.main.addWalletToApplication(walletFromDisk, walletIsNew=True)
示例#2
0
    def createNewWalletFromWizard(self):
        self.newWallet = PyBtcWallet().createNewWallet( \
                       securePassphrase=self.setPassphrasePage.pageFrame.getPassphrase(), \
                       kdfTargSec=self.walletCreationPage.pageFrame.getKdfSec(), \
                       kdfMaxMem=self.walletCreationPage.pageFrame.getKdfBytes(), \
                       shortLabel=self.walletCreationPage.pageFrame.getName(), \
                       longLabel=self.walletCreationPage.pageFrame.getDescription(), \
                       doRegisterWithBDM=False, \
                       extraEntropy=self.main.getExtraEntropyForKeyGen())

        self.newWallet.unlock(securePassphrase=SecureBinaryData(
            self.setPassphrasePage.pageFrame.getPassphrase()))
        # We always want to fill the address pool, right away.
        fillpool = lambda: self.newWallet.fillAddressPool(doRegister=False)
        DlgExecLongProcess(fillpool, 'Creating Wallet...', self, self).exec_()

        # Reopening from file helps make sure everything is correct -- don't
        # let the user use a wallet that triggers errors on reading it
        wltpath = self.newWallet.walletPath
        walletFromDisk = PyBtcWallet().readWalletFile(wltpath)
        self.main.addWalletToApplication(walletFromDisk, walletIsNew=True)
        if TheBDM.getBDMState() in ('Uninitialized', 'Offline'):
            TheBDM.registerWallet(walletFromDisk, isFresh=True, wait=False)
        else:
            self.main.newWalletList.append([walletFromDisk, True])
示例#3
0
def breakDownWallet(walletPath, fragSize):
    print 'breaking down wallet in packs of %d addresses' % fragSize
    print 'reading wallet'
    theWallet = PyBtcWallet().readWalletFile(walletPath)

    nAddresses = len(theWallet.addrMap)

    addrIndex = 0
    wltIndex = 1

    if walletPath[-7:] == '.wallet':
        newDir = walletPath[:-7]
    else:
        newDir = os.path.dirname(walletPath)

    if not os.path.exists(newDir):
        os.mkdir(newDir)

    rootAddr = theWallet.addrMap['ROOT']
    withEncrypt = theWallet.useEncryption
    addrIter = theWallet.addrMap.iteritems()

    while nAddresses > 0:

        print 'breaking down wallet from address #%d to #%d' % (
            addrIndex, addrIndex + fragSize - 1)
        nAddresses -= fragSize

        newWalletPath = os.path.join(newDir,
                                     'armory_wlt_%05d_.wallet' % wltIndex)
        wltIndex += 1

        walletFragment = PyBtcWallet()
        createNewWallet(walletFragment, rootAddr, newWalletPath, withEncrypt,
                        theWallet.kdf)

        fileData = BinaryPacker()
        i = 0

        try:
            while i < fragSize:
                addrItem = addrIter.next()[1]
                addrItem.chainIndex = -2

                fileData.put(
                    BINARY_CHUNK,
                    '\x00' + addrItem.addrStr20 + addrItem.serialize())
                #walletFragment.walletFileSafeUpdate([[WLT_UPDATE_ADD, \
                #WLT_DATATYPE_KEYDATA, addrItem.addrStr20, addrItem]])
                i += 1

        except StopIteration:
            pass

        walletFile = open(newWalletPath, 'ab')
        walletFile.write(fileData.getBinaryString())
        walletFile.close()

        addrIndex += i
    print 'Done'
    def setUp(self):
        self.fileA = os.path.join(ARMORY_HOME_DIR,
                                  'armory_%s_.wallet' % TEST_WALLET_ID)
        self.fileB = os.path.join(ARMORY_HOME_DIR,
                                  'armory_%s_backup.wallet' % TEST_WALLET_ID)
        self.fileAupd = os.path.join(
            ARMORY_HOME_DIR,
            'armory_%s_backup_unsuccessful.wallet' % TEST_WALLET_ID)
        self.fileBupd = os.path.join(
            ARMORY_HOME_DIR,
            'armory_%s_update_unsuccessful.wallet' % TEST_WALLET_ID)

        self.removeFileList(
            [self.fileA, self.fileB, self.fileAupd, self.fileBupd])

        # We need a controlled test, so we script the all the normally-random stuff
        self.privKey = SecureBinaryData('\xaa' * 32)
        self.privKey2 = SecureBinaryData('\x33' * 32)
        self.chainstr = SecureBinaryData('\xee' * 32)
        theIV = SecureBinaryData(hex_to_binary('77' * 16))
        self.passphrase = SecureBinaryData('A self.passphrase')
        self.passphrase2 = SecureBinaryData('A new self.passphrase')

        self.wallet = PyBtcWallet().createNewWallet(withEncrypt=False, \
                                            plainRootKey=self.privKey, \
                                            chaincode=self.chainstr,   \
                                            IV=theIV, \
                                            shortLabel=TEST_WALLET_NAME, \
                                            longLabel=TEST_WALLET_DESCRIPTION)
        self.jsonServer = Armory_Json_Rpc_Server(self.wallet)
        TheBDM.registerWallet(self.wallet)
示例#5
0
    def setUp(self):
        self.shortlabel = 'TestWallet1'
        self.wltID = '3VB8XSoY' if USE_TESTNET else '3VB8XSmd'

        self.fileA = os.path.join(ARMORY_HOME_DIR,
                                  'armory_%s_.wallet' % self.wltID)
        self.fileB = os.path.join(ARMORY_HOME_DIR,
                                  'armory_%s_backup.wallet' % self.wltID)
        self.fileAupd = os.path.join(
            ARMORY_HOME_DIR,
            'armory_%s_backup_unsuccessful.wallet' % self.wltID)
        self.fileBupd = os.path.join(
            ARMORY_HOME_DIR,
            'armory_%s_update_unsuccessful.wallet' % self.wltID)

        self.removeFileList(
            [self.fileA, self.fileB, self.fileAupd, self.fileBupd])

        # We need a controlled test, so we script the all the normally-random stuff
        self.privKey = SecureBinaryData('\xaa' * 32)
        self.privKey2 = SecureBinaryData('\x33' * 32)
        self.chainstr = SecureBinaryData('\xee' * 32)
        theIV = SecureBinaryData(hex_to_binary('77' * 16))
        self.passphrase = SecureBinaryData('A self.passphrase')
        self.passphrase2 = SecureBinaryData('A new self.passphrase')

        self.wlt = PyBtcWallet().createNewWallet(withEncrypt=False, \
                                            plainRootKey=self.privKey, \
                                            chaincode=self.chainstr,   \
                                            IV=theIV, \
                                            shortLabel=self.shortlabel)
示例#6
0
 def __init__(self, wallet=None, walletPath=''):
     if wallet != None:
         self.wallet = wallet
     else:
         if not os.path.exists(walletPath):
             print 'Wallet does not exist:'
             print '  ', walletPath
             raise WalletNotFound
         self.wallet = PyBtcWallet().readWalletFile(walletPath)
示例#7
0
    def setUp(self):

        self.verifyBlockHeight()
        self.fileA = os.path.join(self.armoryHomeDir,
                                  'armory_%s_.wallet' % TEST_WALLET_ID)
        self.fileB = os.path.join(self.armoryHomeDir,
                                  'armory_%s_backup.wallet' % TEST_WALLET_ID)
        self.fileAupd = os.path.join(
            self.armoryHomeDir,
            'armory_%s_backup_unsuccessful.wallet' % TEST_WALLET_ID)
        self.fileBupd = os.path.join(
            self.armoryHomeDir,
            'armory_%s_update_unsuccessful.wallet' % TEST_WALLET_ID)

        self.removeFileList(
            [self.fileA, self.fileB, self.fileAupd, self.fileBupd])

        # We need a controlled test, so we script the all the normally-random stuff
        self.privKey = SecureBinaryData('\xaa' * 32)
        self.privKey2 = SecureBinaryData('\x33' * 32)
        self.chainstr = SecureBinaryData('\xee' * 32)
        theIV = SecureBinaryData(hex_to_binary('77' * 16))
        self.passphrase = SecureBinaryData('A self.passphrase')
        self.passphrase2 = SecureBinaryData('A new self.passphrase')

        #register a callback
        TheBDM.registerCppNotification(self.armoryDTestCallback)

        #flag to check on wallet scan status
        self.walletIsScanned = False

        #create the wallet
        self.wallet = PyBtcWallet().createNewWallet(withEncrypt=False, \
                                            plainRootKey=self.privKey, \
                                            chaincode=self.chainstr,   \
                                            IV=theIV, \
                                            shortLabel=TEST_WALLET_NAME, \
                                            longLabel=TEST_WALLET_DESCRIPTION,
                                            armoryHomeDir = self.armoryHomeDir)
        self.jsonServer = Armory_Json_Rpc_Server(self.wallet)

        #register it
        self.wallet.registerWallet()

        #wait on scan for 2 min then raise if the scan hasn't finished yet
        i = 0
        while not self.walletIsScanned:
            time.sleep(0.5)
            i += 1
            if i >= 60 * 4:
                raise RuntimeError(
                    "Timeout waiting for TheBDM to register the wallet.")
示例#8
0
def createWalletList(n, nameString):
   walletList = []
   for i in range(n):
      name = "%s #%d" % (nameString, i)
      newWallet = PyBtcWallet().createNewWallet( \
                                           withEncrypt=False, \
                                           shortLabel=name, \
                                           longLabel=name, \
                                           doRegisterWithBDM=False)
      walletList.append(newWallet)
   return walletList
示例#9
0
 def testIsWltSigningAnyLockbox(self):
    lockboxList = readLockboxesFile(os.path.join(self.armoryHomeDir, MULTISIG_FILE_NAME))
    self.assertFalse(self.wlt.isWltSigningAnyLockbox(lockboxList))
    
    lboxWltAFile   = os.path.join(self.armoryHomeDir,'armory_%s_.wallet' % FIRST_WLT_NAME)
    lboxWltA = PyBtcWallet().readWalletFile(lboxWltAFile, doScanNow=True)
    self.assertTrue(lboxWltA.isWltSigningAnyLockbox(lockboxList))
    
    lboxWltBFile   = os.path.join(self.armoryHomeDir,'armory_%s_.wallet' % SECOND_WLT_NAME)
    lboxWltB = PyBtcWallet().readWalletFile(lboxWltBFile, doScanNow=True)
    self.assertTrue(lboxWltB.isWltSigningAnyLockbox(lockboxList))
示例#10
0
 def setUp(self):
     self.verifyBlockHeight()
     # Load the primary file from the test net in a box
     self.fileA = os.path.join(self.tiab.tiabDirectory, 'tiab', 'armory', \
                               'armory_%s_.wallet' % FIRST_WLT_NAME)
     self.wltA = PyBtcWallet().readWalletFile(self.fileA, doScanNow=True)
     self.fileB = os.path.join(self.tiab.tiabDirectory, 'tiab', 'armory', \
                               'armory_%s_.wallet' % SECOND_WLT_NAME)
     self.wltB = PyBtcWallet().readWalletFile(self.fileB, doScanNow=True)
     self.fileC = os.path.join(self.tiab.tiabDirectory, 'tiab', 'armory', \
                               'armory_%s_.wallet' % THIRD_WLT_NAME)
     self.wltC = PyBtcWallet().readWalletFile(self.fileC, doScanNow=True)
     self.jsonServer = Armory_Json_Rpc_Server(self.wltA, \
                                   inWltMap={SECOND_WLT_NAME : self.wltB, \
                                             THIRD_WLT_NAME : self.wltC}, \
                      armoryHomeDir=os.path.join(self.tiab.tiabDirectory, \
                                                 'tiab','armory'))
     TheBDM.registerWallet(self.wltA)
示例#11
0
    def setUp(self):
        self.verifyBlockHeight()
        # Load the primary file from the test net in a box
        self.fileA = os.path.join(self.tiab.tiabDirectory, 'tiab', 'armory', \
                                  'armory_%s_.wallet' % FIRST_WLT_NAME)
        self.wltA = PyBtcWallet().readWalletFile(self.fileA)
        self.fileB = os.path.join(self.tiab.tiabDirectory, 'tiab', 'armory', \
                                  'armory_%s_.wallet' % SECOND_WLT_NAME)
        self.wltB = PyBtcWallet().readWalletFile(self.fileB)
        self.fileC = os.path.join(self.tiab.tiabDirectory, 'tiab', 'armory', \
                                  'armory_%s_.wallet' % THIRD_WLT_NAME)
        self.wltC = PyBtcWallet().readWalletFile(self.fileC)
        self.jsonServer = Armory_Json_Rpc_Server(self.wltA, \
                                      inWltMap={SECOND_WLT_NAME : self.wltB, \
                                                THIRD_WLT_NAME : self.wltC}, \
                         armoryHomeDir=os.path.join(self.tiab.tiabDirectory, \
                                                    'tiab','armory'))

        self.wltIDs = [
            self.wltA.uniqueIDB58, self.wltB.uniqueIDB58, self.wltC.uniqueIDB58
        ]
        #register a callback
        TheBDM.registerCppNotification(self.armoryDTiabTestCallback)

        #flag to check on wallet scan status
        self.numberOfWalletsScanned = 0

        self.wltA.registerWallet()
        time.sleep(0.5)
        self.wltB.registerWallet()
        time.sleep(0.5)
        self.wltC.registerWallet()
        time.sleep(0.5)
        #wait on scan for 20sec then raise if the scan hasn't finished yet
        i = 0
        while self.numberOfWalletsScanned < 3:
            time.sleep(0.5)
            i += 1
            if i >= 40:
                raise RuntimeError("self.numberOfWalletsScanned = %d" %
                                   self.numberOfWalletsScanned)
示例#12
0
class ArmoryDTest(TiabTest):
    def removeFileList(self, fileList):
        for f in fileList:
            if os.path.exists(f):
                os.remove(f)

    def armoryDTestCallback(self, action, args):
        if action == REFRESH_ACTION:
            self.walletIsScanned = True

    def setUp(self):

        self.verifyBlockHeight()
        self.fileA = os.path.join(self.armoryHomeDir,
                                  'armory_%s_.wallet' % TEST_WALLET_ID)
        self.fileB = os.path.join(self.armoryHomeDir,
                                  'armory_%s_backup.wallet' % TEST_WALLET_ID)
        self.fileAupd = os.path.join(
            self.armoryHomeDir,
            'armory_%s_backup_unsuccessful.wallet' % TEST_WALLET_ID)
        self.fileBupd = os.path.join(
            self.armoryHomeDir,
            'armory_%s_update_unsuccessful.wallet' % TEST_WALLET_ID)

        self.removeFileList(
            [self.fileA, self.fileB, self.fileAupd, self.fileBupd])

        # We need a controlled test, so we script the all the normally-random stuff
        self.privKey = SecureBinaryData('\xaa' * 32)
        self.privKey2 = SecureBinaryData('\x33' * 32)
        self.chainstr = SecureBinaryData('\xee' * 32)
        theIV = SecureBinaryData(hex_to_binary('77' * 16))
        self.passphrase = SecureBinaryData('A self.passphrase')
        self.passphrase2 = SecureBinaryData('A new self.passphrase')

        #register a callback
        TheBDM.registerCppNotification(self.armoryDTestCallback)

        #flag to check on wallet scan status
        self.walletIsScanned = False

        #create the wallet
        self.wallet = PyBtcWallet().createNewWallet(withEncrypt=False, \
                                            plainRootKey=self.privKey, \
                                            chaincode=self.chainstr,   \
                                            IV=theIV, \
                                            shortLabel=TEST_WALLET_NAME, \
                                            longLabel=TEST_WALLET_DESCRIPTION,
                                            armoryHomeDir = self.armoryHomeDir)
        self.jsonServer = Armory_Json_Rpc_Server(self.wallet)

        #register it
        self.wallet.registerWallet()

        #wait on scan for 2 min then raise if the scan hasn't finished yet
        i = 0
        while not self.walletIsScanned:
            time.sleep(0.5)
            i += 1
            if i >= 60 * 4:
                raise RuntimeError(
                    "Timeout waiting for TheBDM to register the wallet.")

    def tearDown(self):
        TheBDM.unregisterCppNotification(self.armoryDTestCallback)
        self.wallet.unregisterWallet()
        self.removeFileList(
            [self.fileA, self.fileB, self.fileAupd, self.fileBupd])

    # Can't test with actual transactions in this environment. See ARMORY-34.
    # This wallet has no txs
    # def testListunspent(self):
    #    actualResult = self.jsonServer.jsonrpc_listunspent()
    #    self.assertEqual(actualResult, [])
    def testImportprivkey(self):
        originalLength = len(self.wallet.linearAddr160List)
        self.jsonServer.jsonrpc_importprivkey(
            binary_to_hex(self.privKey2.toBinStr()))
        self.assertEqual(len(self.wallet.linearAddr160List),
                         originalLength + 1)

    # Requires Supernode
    @SkipTest
    def testGettxout(self):
        txOut = self.jsonServer.jsonrpc_gettxout(TX_ID1, 0)
        self.assertEquals(txOut['value'], TX_ID1_OUTPUT0_VALUE)
        txOut = self.jsonServer.jsonrpc_gettxout(TX_ID1, 1)
        self.assertEquals(txOut['value'], TX_ID1_OUTPUT1_VALUE)

    def testGetreceivedbyaddress(self):
        a160 = hash160(
            self.wallet.getNextUnusedAddress().binPublicKey65.toBinStr())
        testAddr = hash160_to_addrStr(a160)
        result = self.jsonServer.jsonrpc_getreceivedbyaddress(testAddr)
        self.assertEqual(result, 0)

    # Requires Supernode
    @SkipTest
    def testGetrawtransaction(self):
        actualRawTx = self.jsonServer.jsonrpc_getrawtransaction(TX_ID1)
        pyTx = PyTx().unserialize(hex_to_binary(actualRawTx))
        self.assertEquals(TX_ID1, binary_to_hex(pyTx.getHash(), BIGENDIAN))

    def testBackupWallet(self):
        backupTestPath = os.path.join(
            self.armoryHomeDir,
            'armory_%s_.wallet.backup.test' % TEST_WALLET_ID)
        # Remove backupTestPath in case it exists
        backupFileList = [backupTestPath, self.fileB]
        self.removeFileList(backupFileList)
        # Remove the backup test path that is to be created after tear down.
        self.addCleanup(self.removeFileList, backupFileList)
        self.jsonServer.jsonrpc_backupwallet(backupTestPath)
        self.assertTrue(os.path.exists(backupTestPath))
        self.wallet.backupWalletFile()
        self.assertTrue(os.path.exists(self.fileB))

    def testDecoderawtransaction(self):
        actualDD = self.jsonServer.jsonrpc_decoderawtransaction(RAW_TX1)
        # Test specific values pulled from bitcoin daemon's output for the test raw TX
        expectScriptStr = 'OP_DUP OP_HASH160 PUSHDATA(20) [62d978319c7d7ac6cceed722c3d08aa81b371012] OP_EQUALVERIFY OP_CHECKSIG'
        self.assertEqual(actualDD['locktime'], 0)
        self.assertEqual(actualDD['version'], 1)
        self.assertEqual(len(actualDD['vin']), 1)
        self.assertEqual(actualDD['vin'][0]['sequence'], 4294967295L)
        self.assertEqual(
            actualDD['vin'][0]['scriptSig']['hex'],
            '4830450220081341a4e803c7c8e64c3a3fd285dca34c9f7c71c4dfc2b576d761c5783ce735022100eea66ba382d00e628d86fc5bc1928a93765e26fd8252c4d01efe22147c12b91a01410458fec9d580b0c6842cae00aecd96e89af3ff56f5be49dae425046e64057e0f499acc35ec10e1b544e0f01072296c6fa60a68ea515e59d24ff794cf8923cd30f4'
        )
        self.assertEqual(actualDD['vin'][0]['vout'], 1)
        self.assertEqual(
            actualDD['vin'][0]['txid'],
            '04b865ecf5fca3a56f6ce73a571a09a668f4b7aa5a7547a5f51fae08eadcdbb5')
        self.assertEqual(len(actualDD['vout']), 2)
        self.assertEqual(actualDD['vout'][0]['value'], 20.0)
        self.assertEqual(actualDD['vout'][0]['n'], 0)
        self.assertEqual(actualDD['vout'][0]['scriptPubKey']['reqSigs'], 1)
        self.assertEqual(actualDD['vout'][0]['scriptPubKey']['hex'],
                         '76a91462d978319c7d7ac6cceed722c3d08aa81b37101288ac')
        self.assertEqual(actualDD['vout'][0]['scriptPubKey']['addresses'],
                         ['mpXd2u8fPVYdL1Nf9bZ4EFnqhkNyghGLxL'])
        self.assertEqual(actualDD['vout'][0]['scriptPubKey']['asm'],
                         expectScriptStr)
        self.assertEqual(actualDD['vout'][0]['scriptPubKey']['type'],
                         'Standard (PKH)')
        self.assertEqual(actualDD['vout'][1]['scriptPubKey']['type'],
                         'Standard (PKH)')

    def testDumpprivkey(self):
        testPrivKey = self.privKey.toBinStr()
        hash160 = convertKeyDataToAddress(testPrivKey)
        addr58 = hash160_to_addrStr(hash160)

        # Verify that a bogus addrss Raises InvalidBitcoinAddress Exception
        result = self.jsonServer.jsonrpc_dumpprivkey('bogus', 'hex')
        self.assertEqual(result['Error Type'], 'InvalidBitcoinAddress')

        result = self.jsonServer.jsonrpc_dumpprivkey(addr58, 'hex')
        self.assertEqual(result['Error Type'], 'PrivateKeyNotFound')

        # verify that the first private key can be found
        firstHash160 = self.wallet.getNextUnusedAddress().getAddr160()
        firstAddr58 = hash160_to_addrStr(firstHash160)
        actualPrivateKeyHex = self.jsonServer.jsonrpc_dumpprivkey(firstAddr58, \
                                                                  'hex')
        actualPrivateKeyB58 = self.jsonServer.jsonrpc_dumpprivkey(firstAddr58, \
                                                                  'base58')
        self.privKey = self.wallet.getAddrByHash160(
            firstHash160).serializePlainPrivateKey()
        expectedPrivateKeyHex = binary_to_hex(self.privKey)
        expectedPrivateKeyB58 = privKey_to_base58(self.privKey)
        self.assertEqual(actualPrivateKeyHex, expectedPrivateKeyHex)
        self.assertEqual(actualPrivateKeyB58, expectedPrivateKeyB58)

        # Verify that a locked wallet Raises WalletUnlockNeeded Exception
        kdfParams = self.wallet.computeSystemSpecificKdfParams(0.1)
        self.wallet.changeKdfParams(*kdfParams)
        self.wallet.changeWalletEncryption(securePassphrase=self.passphrase)
        self.wallet.lock()
        result = self.jsonServer.jsonrpc_dumpprivkey(addr58, 'hex')
        self.assertEqual(result['Error Type'], 'WalletUnlockNeeded')

    def testEncryptwallet(self):
        kdfParams = self.wallet.computeSystemSpecificKdfParams(0.1)
        self.wallet.changeKdfParams(*kdfParams)
        self.jsonServer.jsonrpc_encryptwallet(PASSPHRASE1)
        self.assertTrue(self.wallet.isLocked)

        # Verify that a locked wallet Raises WalletUnlockNeeded Exception
        # self.assertRaises(WalletUnlockNeeded, self.jsonServer.jsonrpc_encryptwallet, PASSPHRASE1)
        result = self.jsonServer.jsonrpc_encryptwallet(PASSPHRASE1)
        print result

    def testUnlockwallet(self):
        kdfParams = self.wallet.computeSystemSpecificKdfParams(0.1)
        self.wallet.changeKdfParams(*kdfParams)
        self.jsonServer.jsonrpc_encryptwallet(PASSPHRASE1)
        self.assertTrue(self.wallet.isLocked)
        self.jsonServer.jsonrpc_walletpassphrase(PASSPHRASE1, UNLOCK_TIMEOUT)
        self.assertFalse(self.wallet.isLocked)
        time.sleep(UNLOCK_TIMEOUT + 1)
        self.wallet.checkWalletLockTimeout()
        self.assertTrue(self.wallet.isLocked)

    def testGetWalletInfo(self):
        wltInfo = self.jsonServer.jsonrpc_getwalletinfo()
        self.assertEqual(wltInfo['name'], TEST_WALLET_NAME)
        self.assertEqual(wltInfo['description'], TEST_WALLET_DESCRIPTION)
        self.assertEqual(wltInfo['balance'],
                         AmountToJSON(self.wallet.getBalance('Spend')))
        self.assertEqual(wltInfo['keypoolsize'], self.wallet.addrPoolSize)
        self.assertEqual(wltInfo['numaddrgen'], len(self.wallet.addrMap))
        self.assertEqual(wltInfo['highestusedindex'],
                         self.wallet.highestUsedChainIndex)

    # This should always return 0 balance
    # Need to create our own test net to test with balances
    def testGetBalance(self):
        for ballanceType in ['spendable','spend', 'unconf', \
                             'unconfirmed', 'total', 'ultimate','unspent', 'full']:
            self.assertEqual(
                self.jsonServer.jsonrpc_getbalance(ballanceType),
                AmountToJSON(self.wallet.getBalance(ballanceType)))
示例#13
0
class WalletWizard(ArmoryWizard):
    def __init__(self, parent, main):
        super(WalletWizard, self).__init__(parent, main)
        self.newWallet = None
        self.isBackupCreated = False
        self.setWindowTitle(tr("Wallet Creation Wizard"))
        self.setOption(QWizard.HaveFinishButtonOnEarlyPages, on=True)
        self.setOption(QWizard.IgnoreSubTitles, on=True)

        # Page 1: Create Wallet
        self.walletCreationPage = WalletCreationPage(self)
        self.addPage(self.walletCreationPage)

        # Page 2: Set Passphrase
        self.setPassphrasePage = SetPassphrasePage(self)
        self.addPage(self.setPassphrasePage)

        # Page 3: Verify Passphrase
        self.verifyPassphrasePage = VerifyPassphrasePage(self)
        self.addPage(self.verifyPassphrasePage)

        # Page 4: Create Paper Backup
        self.walletBackupPage = WalletBackupPage(self)
        self.addPage(self.walletBackupPage)

        # Page 5: Create Watching Only Wallet -- but only if expert, or offline
        self.hasCWOWPage = False
        if self.main.usermode == USERMODE.Expert or not self.main.internetAvail:
            self.hasCWOWPage = True
            self.createWOWPage = CreateWatchingOnlyWalletPage(self)
            self.addPage(self.createWOWPage)

        self.setButtonLayout([
            QWizard.BackButton, QWizard.Stretch, QWizard.NextButton,
            QWizard.FinishButton
        ])

    def initializePage(self, *args, **kwargs):

        if self.currentPage() == self.verifyPassphrasePage:
            self.verifyPassphrasePage.setPassphrase(
                self.setPassphrasePage.pageFrame.getPassphrase())
        elif self.hasCWOWPage and self.currentPage() == self.createWOWPage:
            self.createWOWPage.pageFrame.setWallet(self.newWallet)

        if self.currentPage() == self.walletBackupPage:
            self.createNewWalletFromWizard()
            self.walletBackupPage.pageFrame.setPassphrase(
                self.setPassphrasePage.pageFrame.getPassphrase())
            self.walletBackupPage.pageFrame.setWallet(self.newWallet)

            # Only hide the back button on wallet backup page
            self.setButtonLayout(
                [QWizard.Stretch, QWizard.NextButton, QWizard.FinishButton])
        else:
            self.setButtonLayout([
                QWizard.BackButton, QWizard.Stretch, QWizard.NextButton,
                QWizard.FinishButton
            ])

    def done(self, event):
        if self.newWallet and not self.walletBackupPage.pageFrame.isBackupCreated:
            reply = QMessageBox.question(self, tr('Wallet Backup Warning'), tr("""
               You have not made a backup for your new wallet.  You only have 
               to make a backup of your wallet <u>one time</u> to protect 
               all the funds held by this wallet <i>any time in the future</i>
               (it is a backup of the signing keys, not the coins themselves).
               <br><br>
               If you do not make a backup, you will <u>permanently</u> lose
               the money in this wallet if you ever forget your password, or 
               suffer from hardware failure.
               <br><br>
               Are you sure that you want to leave this wizard without backing 
               up your wallet?"""), \
                  QMessageBox.Yes | QMessageBox.No)
            if reply == QMessageBox.No:
                # Stay in the wizard
                return None
        return super(WalletWizard, self).done(event)

    def createNewWalletFromWizard(self):
        self.newWallet = PyBtcWallet().createNewWallet( \
                       securePassphrase=self.setPassphrasePage.pageFrame.getPassphrase(), \
                       kdfTargSec=self.walletCreationPage.pageFrame.getKdfSec(), \
                       kdfMaxMem=self.walletCreationPage.pageFrame.getKdfBytes(), \
                       shortLabel=self.walletCreationPage.pageFrame.getName(), \
                       longLabel=self.walletCreationPage.pageFrame.getDescription(), \
                       doRegisterWithBDM=False, \
                       extraEntropy=self.main.getExtraEntropyForKeyGen())

        self.newWallet.unlock(securePassphrase=SecureBinaryData(
            self.setPassphrasePage.pageFrame.getPassphrase()))
        # We always want to fill the address pool, right away.
        fillpool = lambda: self.newWallet.fillAddressPool(doRegister=False)
        DlgExecLongProcess(fillpool, 'Creating Wallet...', self, self).exec_()

        # Reopening from file helps make sure everything is correct -- don't
        # let the user use a wallet that triggers errors on reading it
        wltpath = self.newWallet.walletPath
        walletFromDisk = PyBtcWallet().readWalletFile(wltpath)
        self.main.addWalletToApplication(walletFromDisk, walletIsNew=True)
        if TheBDM.getBDMState() in ('Uninitialized', 'Offline'):
            TheBDM.registerWallet(walletFromDisk, isFresh=True, wait=False)
        else:
            self.main.newWalletList.append([walletFromDisk, True])

    def cleanupPage(self, *args, **kwargs):
        if self.hasCWOWPage and self.currentPage() == self.createWOWPage:
            self.setButtonLayout(
                [QWizard.Stretch, QWizard.NextButton, QWizard.FinishButton])
        else:
            self.setButtonLayout([
                QWizard.BackButton, QWizard.Stretch, QWizard.NextButton,
                QWizard.FinishButton
            ])
示例#14
0
class ArmoryDTest(unittest.TestCase):
    def removeFileList(self, fileList):
        for f in fileList:
            if os.path.exists(f):
                os.remove(f)

    @classmethod
    def setUpClass(self):
        # This is not a UI so no need to worry about the main thread being blocked.
        # Any UI that uses this Daemon can put the call to the Daemon on it's own thread.
        TheBDM.setBlocking(True)
        TheBDM.setOnlineMode(True)
        while not TheBDM.getBDMState() == 'BlockchainReady':
            time.sleep(2)

    def setUp(self):
        self.fileA = os.path.join(ARMORY_HOME_DIR,
                                  'armory_%s_.wallet' % TEST_WALLET_ID)
        self.fileB = os.path.join(ARMORY_HOME_DIR,
                                  'armory_%s_backup.wallet' % TEST_WALLET_ID)
        self.fileAupd = os.path.join(
            ARMORY_HOME_DIR,
            'armory_%s_backup_unsuccessful.wallet' % TEST_WALLET_ID)
        self.fileBupd = os.path.join(
            ARMORY_HOME_DIR,
            'armory_%s_update_unsuccessful.wallet' % TEST_WALLET_ID)

        self.removeFileList(
            [self.fileA, self.fileB, self.fileAupd, self.fileBupd])

        # We need a controlled test, so we script the all the normally-random stuff
        self.privKey = SecureBinaryData('\xaa' * 32)
        self.privKey2 = SecureBinaryData('\x33' * 32)
        self.chainstr = SecureBinaryData('\xee' * 32)
        theIV = SecureBinaryData(hex_to_binary('77' * 16))
        self.passphrase = SecureBinaryData('A self.passphrase')
        self.passphrase2 = SecureBinaryData('A new self.passphrase')

        self.wallet = PyBtcWallet().createNewWallet(withEncrypt=False, \
                                            plainRootKey=self.privKey, \
                                            chaincode=self.chainstr,   \
                                            IV=theIV, \
                                            shortLabel=TEST_WALLET_NAME, \
                                            longLabel=TEST_WALLET_DESCRIPTION)
        self.jsonServer = Armory_Json_Rpc_Server(self.wallet)
        TheBDM.registerWallet(self.wallet)

    def tearDown(self):
        self.removeFileList(
            [self.fileA, self.fileB, self.fileAupd, self.fileBupd])

    # Can't test with actual transactions in this environment. See ARMORY-34.
    # This wallet has no txs
    def testListunspent(self):
        actualResult = self.jsonServer.jsonrpc_listunspent()
        self.assertEqual(actualResult, [])

    def testImportprivkey(self):
        originalLength = len(self.wallet.linearAddr160List)
        self.jsonServer.jsonrpc_importprivkey(self.privKey2)
        self.assertEqual(len(self.wallet.linearAddr160List),
                         originalLength + 1)

    def testGettxout(self):
        txOut = self.jsonServer.jsonrpc_gettxout(TX_ID1, 0)
        self.assertEquals(TX_ID1_OUTPUT0_VALUE, txOut.value)
        txOut = self.jsonServer.jsonrpc_gettxout(TX_ID1, 1)
        self.assertEquals(TX_ID1_OUTPUT1_VALUE, txOut.value)

    # Cannot unit test actual balances. Only verify that getreceivedbyaddress return a 0 result.
    def testGetreceivedbyaddress(self):
        a160 = hash160(
            self.wallet.getNextUnusedAddress().binPublicKey65.toBinStr())
        testAddr = hash160_to_addrStr(a160)
        result = self.jsonServer.jsonrpc_getreceivedbyaddress(testAddr)
        self.assertEqual(result, 0)

    def testGetrawtransaction(self):
        actualRawTx = self.jsonServer.jsonrpc_getrawtransaction(TX_ID1)
        pyTx = PyTx().unserialize(hex_to_binary(actualRawTx))
        self.assertEquals(TX_ID1, binary_to_hex(pyTx.getHash(), BIGENDIAN))

    def testBackupWallet(self):
        backupTestPath = os.path.join(
            ARMORY_HOME_DIR, 'armory_%s_.wallet.backup.test' % TEST_WALLET_ID)
        # Remove backupTestPath in case it exists
        backupFileList = [backupTestPath, self.fileB]
        self.removeFileList(backupFileList)
        # Remove the backup test path that is to be created after tear down.
        self.addCleanup(self.removeFileList, backupFileList)
        self.jsonServer.jsonrpc_backupwallet(backupTestPath)
        self.assertTrue(os.path.exists(backupTestPath))
        self.wallet.backupWalletFile()
        self.assertTrue(os.path.exists(self.fileB))

    def testDecoderawtransaction(self):
        actualDD = self.jsonServer.jsonrpc_decoderawtransaction(RAW_TX1)
        # Test specific values pulled from bitcoin daemon's output for the test raw TX
        expectScriptStr = 'OP_DUP OP_HASH160 PUSHDATA(20) [be17ec0fc1f8aa029223dbe5f53109d0faf8c797] OP_EQUALVERIFY OP_CHECKSIG'
        self.assertEqual(actualDD['locktime'], 0)
        self.assertEqual(actualDD['version'], 1)
        self.assertEqual(actualDD['vin'][0]['sequence'], 4294967295L)
        self.assertEqual(actualDD['vin'][0]['scriptSig']['hex'], '')
        self.assertEqual(actualDD['vin'][0]['scriptSig']['asm'], '')
        self.assertEqual(actualDD['vin'][0]['vout'], 1201)
        self.assertEqual(
            actualDD['vin'][0]['txid'],
            'e450dc7394f8432d89c68d0df6a5506cb81eac60c977bfc7932633aaf835a31f')
        self.assertEqual(actualDD['vin'][1]['vout'], 294)
        self.assertEqual(
            actualDD['vin'][1]['txid'],
            '8867f0f84e80588ed00a05e604487442546ef42ab4c93445a09b00a6d487e74b')
        self.assertEqual(actualDD['vout'][0]['value'], 0.0001944)
        self.assertEqual(actualDD['vout'][0]['n'], 0)
        self.assertEqual(actualDD['vout'][0]['scriptPubKey']['reqSigs'], 1)
        self.assertEqual(actualDD['vout'][0]['scriptPubKey']['hex'],
                         '76a914be17ec0fc1f8aa029223dbe5f53109d0faf8c79788ac')
        self.assertEqual(actualDD['vout'][0]['scriptPubKey']['addresses'],
                         ['mxr5Le3bt7dfbFqmpK6saUYPt5xtcDB7Yw'])
        self.assertEqual(actualDD['vout'][0]['scriptPubKey']['asm'],
                         expectScriptStr)
        self.assertEqual(actualDD['vout'][0]['scriptPubKey']['type'],
                         'Standard (PKH)')
        self.assertEqual(actualDD['vout'][1]['scriptPubKey']['type'],
                         'Standard (PKH)')
        self.assertEqual(actualDD['vout'][2]['scriptPubKey']['type'],
                         'Non-Standard')

    def testDumpprivkey(self):

        testPrivKey = self.privKey.toBinStr()
        hash160 = convertKeyDataToAddress(testPrivKey)
        addr58 = hash160_to_addrStr(hash160)

        # Verify that a bogus addrss Raises InvalidBitcoinAddress Exception
        self.assertRaises(InvalidBitcoinAddress,
                          self.jsonServer.jsonrpc_dumpprivkey, 'bogus')

        # verify that the root private key is not found
        self.assertRaises(PrivateKeyNotFound,
                          self.jsonServer.jsonrpc_dumpprivkey, addr58)

        # verify that the first private key can be found
        firstHash160 = self.wallet.getNextUnusedAddress().getAddr160()
        firstAddr58 = hash160_to_addrStr(firstHash160)
        actualPrivateKey = self.jsonServer.jsonrpc_dumpprivkey(firstAddr58)
        expectedPrivateKey = self.wallet.getAddrByHash160(
            firstHash160).serializePlainPrivateKey()
        self.assertEqual(actualPrivateKey, expectedPrivateKey)

        # Verify that a locked wallet Raises WalletUnlockNeeded Exception
        kdfParams = self.wallet.computeSystemSpecificKdfParams(0.1)
        self.wallet.changeKdfParams(*kdfParams)
        self.wallet.changeWalletEncryption(securePassphrase=self.passphrase)
        self.wallet.lock()
        self.assertRaises(WalletUnlockNeeded,
                          self.jsonServer.jsonrpc_dumpprivkey, addr58)

    def testEncryptwallet(self):
        kdfParams = self.wallet.computeSystemSpecificKdfParams(0.1)
        self.wallet.changeKdfParams(*kdfParams)
        self.jsonServer.jsonrpc_encryptwallet(PASSPHRASE1)
        self.assertTrue(self.wallet.isLocked)

        # Verify that a locked wallet Raises WalletUnlockNeeded Exception
        self.assertRaises(WalletUnlockNeeded,
                          self.jsonServer.jsonrpc_encryptwallet, PASSPHRASE1)

    def testUnlockwallet(self):
        kdfParams = self.wallet.computeSystemSpecificKdfParams(0.1)
        self.wallet.changeKdfParams(*kdfParams)
        self.jsonServer.jsonrpc_encryptwallet(PASSPHRASE1)
        self.assertTrue(self.wallet.isLocked)
        self.jsonServer.jsonrpc_unlockwallet(PASSPHRASE1, UNLOCK_TIMEOUT)
        self.assertFalse(self.wallet.isLocked)
        time.sleep(UNLOCK_TIMEOUT + 1)
        self.wallet.checkWalletLockTimeout()
        self.assertTrue(self.wallet.isLocked)

    def testGetWalletInfo(self):
        wltInfo = self.jsonServer.jsonrpc_getwalletinfo()
        self.assertEqual(wltInfo['name'], TEST_WALLET_NAME)
        self.assertEqual(wltInfo['description'], TEST_WALLET_DESCRIPTION)
        self.assertEqual(wltInfo['balance'],
                         AmountToJSON(self.wallet.getBalance('Spend')))
        self.assertEqual(wltInfo['keypoolsize'], self.wallet.addrPoolSize)
        self.assertEqual(wltInfo['numaddrgen'], len(self.wallet.addrMap))
        self.assertEqual(wltInfo['highestusedindex'],
                         self.wallet.highestUsedChainIndex)

    # This should always return 0 balance
    # Need to create our own test net to test with balances
    def testGetBalance(self):
        for ballanceType in ['spendable','spend', 'unconf', \
                             'unconfirmed', 'total', 'ultimate','unspent', 'full']:
            self.assertEqual(
                self.jsonServer.jsonrpc_getbalance(ballanceType),
                AmountToJSON(self.wallet.getBalance(ballanceType)))
        self.assertEqual(self.jsonServer.jsonrpc_getbalance('bogus'), -1)
示例#15
0
# Main execution path
# Do not ever access the same wallet file from two different processes at the same time
print '\n'
raw_input(
    'PLEASE CLOSE ARMORY BEFORE RUNNING THIS SCRIPT!  (press enter to continue)\n'
)

if len(promoKitArgList) < 3:
    printHelp()

operation = promoKitArgList[1]
walletFile = promoKitArgList[2]
if not os.path.exists(walletFile):
    print 'Wallet file was not found: %s' % walletFile
masterWallet = PyBtcWallet().readWalletFile(walletFile, False)
if operation == '--create':
    if len(promoKitArgList) < 6:
        printHelp()
    else:
        numWallets = int(promoKitArgList[3])
        addrsPerWallet = int(promoKitArgList[4])
        walletLabel = promoKitArgList[5]
        walletList = createWalletList(numWallets, walletLabel)
        masterWallet = importAddrsToMasterWallet( \
              masterWallet, walletList, addrsPerWallet, "Master Promo Wallet", )
        # Didn't want to fit these into the argument list. Need to edit based on event
        printWalletList(walletList, "$10 in Bitcoins. ", "November 1st, 2014")
elif operation == '--distribute':
    if len(promoKitArgList) < 4:
        printHelp()
示例#16
0
class PasswordFinder(object):
    def __init__(self, wallet=None, walletPath=''):
        if wallet != None:
            self.wallet = wallet
        else:
            if not os.path.exists(walletPath):
                print 'Wallet does not exist:'
                print '  ', walletPath
                raise WalletNotFound
            self.wallet = PyBtcWallet().readWalletFile(walletPath)

    def countPasswords(self, segList, segOrdList):
        return reduce(add, [
            reduce(mul, [len(segList[segIndex]) for segIndex in segOrd])
            for segOrd in segOrdList
        ])

    def recursivePasswordGenerator(self, segList):
        if len(segList) > 0:
            for a in segList[0]:
                for b in self.recursivePasswordGenerator(segList[1:]):
                    yield a + b
        else:
            yield ''

    # Generates passwords from segs in segList
    #     Example Input: [['Andy','b','c'],['1','2'],['!']]
    # The segOrdList contains a list of ordered
    # permutations of the segList:
    #     Example Input: [[0,1,2],[2,0,1,],[0,1]]
    # Yields one password at a time until all permutations are exhausted
    #     Example: Andy1!, Andy2!, b1!, b2!, c1!, c2!,
    #              !Andy1, !Andy2, !b1, !b2, !c1, !c2,
    #              Andy1, Andy2, b1, b2, c1, c2
    # The above example is a test case found in test/FindPassTest.py
    def passwordGenerator(self, segList, segOrdList):
        for segOrd in segOrdList:
            orderedSegList = [segList[segIndex] for segIndex in segOrd]
            for result in self.recursivePasswordGenerator(orderedSegList):
                yield result

    def searchForPassword(self, segList, segOrdList=[]):
        if len(segOrdList) == 0:
            segOrdList = [range(len(segList))]
        passwordCount = self.countPasswords(segList, segOrdList)
        startTime = RightNow()
        found = False
        result = None
        for i, p in enumerate(self.passwordGenerator(segList, segOrdList)):
            isValid = self.wallet.verifyPassphrase(SecureBinaryData(p))

            if isValid:
                # If the passphrase was wrong, it would error out, and not continue
                print 'Passphrase found!'
                print ''
                print '\t', p
                print ''
                print 'Thanks for using this script.  If you recovered coins because of it, '
                print 'please consider donating :) '
                print '   1ArmoryXcfq7TnCSuZa9fQjRYwJ4bkRKfv'
                print ''
                found = True
                open('FOUND_PASSWORD.txt', 'w').write(p)
                result = p
                break
            elif i % 100 == 0:
                telapsed = (RightNow() - startTime) / 3600.
                print('%d/%d passphrases tested... (%0.1f hours so far)' %
                      (i, passwordCount, telapsed)).rjust(40)
            print p,
            if i % 10 == 9:
                print
        if not found:
            print ''

            print 'Script finished!'
            print 'Sorry, none of the provided passphrases were correct :('
            print ''
        return result
示例#17
0
   print '   or: %s --sweep <master wallet file path>' % sys.argv[0]
   exit(0)
   
# Main execution path
# Do not ever access the same wallet file from two different processes at the same time
print '\n'
raw_input('PLEASE CLOSE ARMORY BEFORE RUNNING THIS SCRIPT!  (press enter to continue)\n')

if len(promoKitArgList)<3:
   printHelp()

operation = promoKitArgList[1]
walletFile = promoKitArgList[2]
if not os.path.exists(walletFile):
   print 'Wallet file was not found: %s' % walletFile
masterWallet = PyBtcWallet().readWalletFile(walletFile, False)
if operation == '--create':
   if len(promoKitArgList)<6:
      printHelp()
   else:
      numWallets = int(promoKitArgList[3])
      addrsPerWallet = int(promoKitArgList[4])
      walletLabel = promoKitArgList[5]
      walletList = createWalletList(numWallets, walletLabel)
      masterWallet = importAddrsToMasterWallet( \
            masterWallet, walletList, addrsPerWallet, "Master Promo Wallet", )
      # Didn't want to fit these into the argument list. Need to edit based on event
      printWalletList(walletList, "$10 in Bitcoins. ", "November 1st, 2014")
elif operation == '--distribute':
   if len(promoKitArgList)<4:
      printHelp()
示例#18
0
class WalletWizard(ArmoryWizard):
    def __init__(self, parent, main):
        super(WalletWizard, self).__init__(parent, main)
        self.newWallet = None
        self.isBackupCreated = False
        self.setWindowTitle(tr("Wallet Creation Wizard"))
        self.setOption(QWizard.HaveFinishButtonOnEarlyPages, on=True)
        self.setOption(QWizard.IgnoreSubTitles, on=True)

        self.walletCreationId, self.manualEntropyId, self.setPassphraseId, self.verifyPassphraseId, self.walletBackupId, self.WOWId = range(
            6)

        # Page 1: Create Wallet
        self.walletCreationPage = WalletCreationPage(self)
        self.setPage(self.walletCreationId, self.walletCreationPage)

        # Page 1.5: Add manual entropy
        self.manualEntropyPage = ManualEntropyPage(self)
        self.setPage(self.manualEntropyId, self.manualEntropyPage)

        # Page 2: Set Passphrase
        self.setPassphrasePage = SetPassphrasePage(self)
        self.setPage(self.setPassphraseId, self.setPassphrasePage)

        # Page 3: Verify Passphrase
        self.verifyPassphrasePage = VerifyPassphrasePage(self)
        self.setPage(self.verifyPassphraseId, self.verifyPassphrasePage)

        # Page 4: Create Paper Backup
        self.walletBackupPage = WalletBackupPage(self)
        self.setPage(self.walletBackupId, self.walletBackupPage)

        # Page 5: Create Watching Only Wallet -- but only if expert, or offline
        self.hasCWOWPage = False
        if self.main.usermode == USERMODE.Expert or TheBDM.getState(
        ) == BDM_OFFLINE:
            self.hasCWOWPage = True
            self.createWOWPage = CreateWatchingOnlyWalletPage(self)
            self.setPage(self.WOWId, self.createWOWPage)

        self.setButtonLayout([
            QWizard.BackButton, QWizard.Stretch, QWizard.NextButton,
            QWizard.FinishButton
        ])

    def initializePage(self, *args, **kwargs):

        if self.currentPage() == self.verifyPassphrasePage:
            self.verifyPassphrasePage.setPassphrase(
                self.setPassphrasePage.pageFrame.getPassphrase())
        elif self.hasCWOWPage and self.currentPage() == self.createWOWPage:
            self.createWOWPage.pageFrame.setWallet(self.newWallet)

        if self.currentPage() == self.walletBackupPage:
            self.createNewWalletFromWizard()
            self.walletBackupPage.pageFrame.setPassphrase(
                self.setPassphrasePage.pageFrame.getPassphrase())
            self.walletBackupPage.pageFrame.setWallet(self.newWallet)

            # Hide the back button on wallet backup page
            self.setButtonLayout(
                [QWizard.Stretch, QWizard.NextButton, QWizard.FinishButton])
        elif self.currentPage() == self.walletCreationPage:
            # Hide the back button on the first page
            self.setButtonLayout(
                [QWizard.Stretch, QWizard.NextButton, QWizard.FinishButton])
        else:
            self.setButtonLayout([
                QWizard.BackButton, QWizard.Stretch, QWizard.NextButton,
                QWizard.FinishButton
            ])

    def done(self, event):
        if self.newWallet and not self.walletBackupPage.pageFrame.isBackupCreated:
            reply = QMessageBox.question(self, tr('Wallet Backup Warning'), tr("""<qt>
               You have not made a backup for your new wallet.  You only have 
               to make a backup of your wallet <u>one time</u> to protect 
               all the funds held by this wallet <i>any time in the future</i>
               (it is a backup of the signing keys, not the coins themselves).
               <br><br>
               If you do not make a backup, you will <u>permanently</u> lose
               the money in this wallet if you ever forget your password, or 
               suffer from hardware failure.
               <br><br>
               Are you sure that you want to leave this wizard without backing 
               up your wallet?</qt>"""), \
                  QMessageBox.Yes | QMessageBox.No)
            if reply == QMessageBox.No:
                # Stay in the wizard
                return None
        return super(WalletWizard, self).done(event)

    def createNewWalletFromWizard(self):
        entropy = None
        if self.walletCreationPage.isManualEncryption():
            entropy = SecureBinaryData(
                int_to_binary(self.manualEntropyPage.pageFrame.getEntropy()))
        else:
            entropy = self.main.getExtraEntropyForKeyGen()
        self.newWallet = PyBtcWallet().createNewWallet(
            securePassphrase=self.setPassphrasePage.pageFrame.getPassphrase(),
            kdfTargSec=self.walletCreationPage.pageFrame.getKdfSec(),
            kdfMaxMem=self.walletCreationPage.pageFrame.getKdfBytes(),
            shortLabel=self.walletCreationPage.pageFrame.getName(),
            longLabel=self.walletCreationPage.pageFrame.getDescription(),
            doRegisterWithBDM=False,
            extraEntropy=entropy,
        )

        self.newWallet.unlock(securePassphrase=SecureBinaryData(
            self.setPassphrasePage.pageFrame.getPassphrase()))
        # We always want to fill the address pool, right away.
        fillPoolProgress = DlgProgress(self, self.main, HBar=1, \
                                       Title="Creating Wallet")
        fillPoolProgress.exec_(self.newWallet.fillAddressPool,
                               doRegister=False,
                               Progress=fillPoolProgress.UpdateHBar)

        # Reopening from file helps make sure everything is correct -- don't
        # let the user use a wallet that triggers errors on reading it
        wltpath = self.newWallet.walletPath
        walletFromDisk = PyBtcWallet().readWalletFile(wltpath)
        self.main.addWalletToApplication(walletFromDisk, walletIsNew=True)

    def cleanupPage(self, *args, **kwargs):
        if self.hasCWOWPage and self.currentPage() == self.createWOWPage:
            self.setButtonLayout(
                [QWizard.Stretch, QWizard.NextButton, QWizard.FinishButton])
        # If we are backing up from setPassphrasePage must be going
        # to the first page.
        elif self.currentPage() == self.setPassphrasePage:
            # Hide the back button on the first page
            self.setButtonLayout(
                [QWizard.Stretch, QWizard.NextButton, QWizard.FinishButton])
        else:
            self.setButtonLayout([
                QWizard.BackButton, QWizard.Stretch, QWizard.NextButton,
                QWizard.FinishButton
            ])
示例#19
0
    def testWalletRecovery(self):
        #run recovery on broken wallet
        recThread = PyBtcWalletRecovery().RecoverWallet(self.corruptWallet, \
                                                        'testing', RECOVERMODE.Full, \
                                                        returnError = 'Dict')
        recThread.join()
        brkWltResult = recThread.output

        self.assertTrue(len(brkWltResult['sequenceGaps'])==1, \
                        "Sequence Gap Undetected")
        self.assertTrue(len(brkWltResult['forkedPublicKeyChain'])==3, \
                        "Address Chain Forks Undetected")
        self.assertTrue(len(brkWltResult['unmatchedPair'])==100, \
                        "Unmatched Priv/Pub Key Undetected")
        self.assertTrue(len(brkWltResult['misc'])==50, \
                        "Wallet Encryption Inconsistency Undetected")
        self.assertTrue(len(brkWltResult['importedErr'])==50, \
                        "Unexpected Errors Found")
        self.assertTrue(brkWltResult['nErrors']==204, \
                        "Unexpected Errors Found")

        #check obfuscated keys yield the valid key
        #grab root key
        badWlt = PyBtcWallet()
        badWlt.readWalletFile(self.corruptWallet, False, False)
        rootAddr = badWlt.addrMap['ROOT']

        SecurePassphrase = SecureBinaryData('testing')
        secureKdfOutput = badWlt.kdf.DeriveKey(SecurePassphrase)

        #HMAC Q
        rootAddr.unlock(secureKdfOutput)
        Q = rootAddr.binPrivKey32_Plain.toBinStr()

        nonce = 0
        while 1:
            hmacQ = HMAC256(Q, 'LogMult%d' % nonce)
            if binary_to_int(hmacQ, BIGENDIAN) < SECP256K1_ORDER:
                hmacQ = SecureBinaryData(hmacQ)
                break
            nonce = nonce + 1

        #Bad Private Keys
        import operator
        badKeys = [
            addrObj
            for addrObj in (sorted(badWlt.addrMap.values(),
                                   key=operator.attrgetter('chainIndex')))
        ]

        #run through obdsPrivKey
        for i in range(0, len(brkWltResult['privMult'])):
            obfsPKey = SecureBinaryData(
                hex_to_binary(brkWltResult['privMult'][i]))
            pKey = CryptoECDSA().ECMultiplyScalars(obfsPKey.toBinStr(), \
                                                   hmacQ.toBinStr())

            try:
                badKeys[i + 201].unlock(secureKdfOutput)
            except:
                continue

            self.assertTrue(binary_to_hex(pKey) == \
                            badKeys[i+201].binPrivKey32_Plain.toHexStr(), \
                            'key mult error')

        #run recovery on recovered wallet
        recThread = PyBtcWalletRecovery().RecoverWallet( \
                                   'armory_%s_RECOVERED.wallet' % self.wltID, \
                                   'testing', RECOVERMODE.Full, \
                                   returnError = 'Dict')
        recThread.join()
        rcvWltResult = recThread.output

        self.assertTrue(len(rcvWltResult['importedErr'])==50, \
                        "Unexpected Errors Found")
        self.assertTrue(rcvWltResult['nErrors']==50, \
                        "Unexpected Errors Found")
        self.assertTrue(len(rcvWltResult['negativeImports'])==99, \
                        "Missing neg Imports")


# Running tests with "python <module name>" will NOT work for any Armory tests
# You must run tests with "python -m unittest <module name>" or run all tests with "python -m unittest discover"
# if __name__ == "__main__":
#    unittest.main()
    def buildCorruptWallet(self, walletPath):
        from armoryengine.PyBtcWallet import PyBtcWallet
        crpWlt = PyBtcWallet()
        crpWlt.createNewWallet(walletPath,
                               securePassphrase='testing',
                               doRegisterWithBDM=False)
        #not registering with the BDM, have to fill the wallet address pool manually
        crpWlt.fillAddressPool(100)

        #grab the last computed address
        lastaddr = crpWlt.addrMap[crpWlt.lastComputedChainAddr160]

        #corrupt the pubkey
        PubKey = hex_to_binary(
            '0478d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71a1518063243acd4dfe96b66e3f2ec8013c8e072cd09b3834a19f81f659cc3455'
        )
        lastaddr.binPublicKey65 = SecureBinaryData(PubKey)
        crpWlt.addrMap[crpWlt.lastComputedChainAddr160] = lastaddr

        crpWlt.fillAddressPool(200)

        #insert a gap and inconsistent encryption
        newAddr = PyBtcAddress()
        newAddr.chaincode = lastaddr.chaincode
        newAddr.chainIndex = 250
        PrivKey = hex_to_binary(
            'e3b0c44298fc1c149afbf4c8996fb92427ae41e5978fe51ca495991b7852b855')
        newAddr.binPrivKey32_Plain = SecureBinaryData(PrivKey)
        newAddr.binPublicKey65 = CryptoECDSA().ComputePublicKey(
            newAddr.binPrivKey32_Plain)
        newAddr.addrStr20 = newAddr.binPublicKey65.getHash160()
        newAddr.isInitialized = True

        crpWlt.addrMap[newAddr.addrStr20] = newAddr
        crpWlt.lastComputedChainAddr160 = newAddr.addrStr20
        crpWlt.fillAddressPool(250)

        #TODO: corrupt a private key
        #break an address entry at binary level
        return crpWlt.uniqueIDB58
示例#21
0
    def testPyBtcWallet(self):

        self.wlt.addrPoolSize = 5
        # No block chain loaded so this should return -1
        # self.assertEqual(self.wlt.detectHighestUsedIndex(True), -1)
        self.assertEqual(self.wlt.kdfKey, None)
        self.assertEqual(binary_to_hex(self.wlt.addrMap['ROOT'].addrStr20),
                         WALLET_ROOT_ADDR)

        #############################################################################
        # (1) Getting a new address:
        newAddr = self.wlt.getNextUnusedAddress()
        self.wlt.pprint(indent=' ' * 5)
        self.assertEqual(binary_to_hex(newAddr.addrStr20), NEW_UNUSED_ADDR)

        # (1) Re-reading wallet from file, compare the two wallets
        wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
        self.assertTrue(self.wlt.isEqualTo(wlt2))

        #############################################################################
        # (2)Testing unencrypted wallet import-address'
        originalLength = len(self.wlt.linearAddr160List)
        self.wlt.importExternalAddressData(privKey=self.privKey2)
        self.assertEqual(len(self.wlt.linearAddr160List), originalLength + 1)

        # (2) Re-reading wallet from file, compare the two wallets
        wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
        self.assertTrue(self.wlt.isEqualTo(wlt2))

        # (2a)Testing deleteImportedAddress
        # Wallet size before delete:',  os.path.getsize(self.wlt.walletPath)
        # Addresses before delete:', len(self.wlt.linearAddr160List)
        toDelete160 = convertKeyDataToAddress(self.privKey2)
        self.wlt.deleteImportedAddress(toDelete160)
        self.assertEqual(len(self.wlt.linearAddr160List), originalLength)

        # (2a) Reimporting address for remaining tests
        # Wallet size before reimport:',  os.path.getsize(self.wlt.walletPath)
        self.wlt.importExternalAddressData(privKey=self.privKey2)
        self.assertEqual(len(self.wlt.linearAddr160List), originalLength + 1)

        # (2b)Testing ENCRYPTED wallet import-address
        privKey3 = SecureBinaryData('\xbb' * 32)
        privKey4 = SecureBinaryData('\x44' * 32)
        self.chainstr2 = SecureBinaryData('\xdd' * 32)
        theIV2 = SecureBinaryData(hex_to_binary('66' * 16))
        self.passphrase2 = SecureBinaryData('hello')
        wltE = PyBtcWallet().createNewWallet(withEncrypt=True, \
                                            plainRootKey=privKey3, \
                                            securePassphrase=self.passphrase2, \
                                            chaincode=self.chainstr2,   \
                                            IV=theIV2, \
                                            shortLabel=self.shortlabel)

        #  We should have thrown an error about importing into a  locked wallet...
        self.assertRaises(WalletLockError,
                          wltE.importExternalAddressData,
                          privKey=self.privKey2)

        wltE.unlock(securePassphrase=self.passphrase2)
        wltE.importExternalAddressData(privKey=self.privKey2)

        # (2b) Re-reading wallet from file, compare the two wallets
        wlt2 = PyBtcWallet().readWalletFile(wltE.walletPath)
        self.assertTrue(wltE.isEqualTo(wlt2))

        # (2b) Unlocking wlt2 after re-reading locked-import-wallet
        wlt2.unlock(securePassphrase=self.passphrase2)
        self.assertFalse(wlt2.isLocked)

        #############################################################################
        # Now play with encrypted wallets
        # *********************************************************************'
        # (3)Testing conversion to encrypted wallet

        kdfParams = self.wlt.computeSystemSpecificKdfParams(0.1)
        self.wlt.changeKdfParams(*kdfParams)

        self.assertEqual(self.wlt.kdf.getSalt(), kdfParams[2])
        self.wlt.changeWalletEncryption(securePassphrase=self.passphrase)
        self.assertEqual(self.wlt.kdf.getSalt(), kdfParams[2])

        # (3) Re-reading wallet from file, compare the two wallets'
        wlt2 = PyBtcWallet().readWalletFile(self.wlt.getWalletPath())
        self.assertTrue(self.wlt.isEqualTo(wlt2))
        # NOTE:  this isEqual operation compares the serializations
        #        of the wallet addresses, which only contains the
        #        encrypted versions of the private keys.  However,
        #        self.wlt is unlocked and contains the plaintext keys, too
        #        while wlt2 does not.
        self.wlt.lock()
        for key in self.wlt.addrMap:
            self.assertTrue(self.wlt.addrMap[key].isLocked)
            self.assertEqual(
                self.wlt.addrMap[key].binPrivKey32_Plain.toHexStr(), '')

        #############################################################################
        # (4)Testing changing self.passphrase on encrypted wallet',

        self.wlt.unlock(securePassphrase=self.passphrase)
        for key in self.wlt.addrMap:
            self.assertFalse(self.wlt.addrMap[key].isLocked)
            self.assertNotEqual(
                self.wlt.addrMap[key].binPrivKey32_Plain.toHexStr(), '')
        # ...to same self.passphrase'
        origKdfKey = self.wlt.kdfKey
        self.wlt.changeWalletEncryption(securePassphrase=self.passphrase)
        self.assertEqual(origKdfKey, self.wlt.kdfKey)

        # (4)And now testing new self.passphrase...'
        self.wlt.changeWalletEncryption(securePassphrase=self.passphrase2)
        self.assertNotEqual(origKdfKey, self.wlt.kdfKey)

        # (4) Re-reading wallet from file, compare the two wallets'
        wlt2 = PyBtcWallet().readWalletFile(self.wlt.getWalletPath())
        self.assertTrue(self.wlt.isEqualTo(wlt2))

        #############################################################################
        # (5)Testing changing KDF on encrypted wallet'

        self.wlt.unlock(securePassphrase=self.passphrase2)

        MEMORY_REQT_BYTES = 1024
        NUM_ITER = 999
        SALT_ALL_0 = '00' * 32
        self.wlt.changeKdfParams(MEMORY_REQT_BYTES, NUM_ITER,
                                 hex_to_binary(SALT_ALL_0), self.passphrase2)
        self.assertEqual(self.wlt.kdf.getMemoryReqtBytes(), MEMORY_REQT_BYTES)
        self.assertEqual(self.wlt.kdf.getNumIterations(), NUM_ITER)
        self.assertEqual(self.wlt.kdf.getSalt().toHexStr(), SALT_ALL_0)

        self.wlt.changeWalletEncryption(securePassphrase=self.passphrase2)
        # I don't know why this shouldn't be ''
        # Commenting out because it's a broken assertion
        # self.assertNotEqual(origKdfKey.toHexStr(), '')

        # (5) Get new address from locked wallet'
        # Locking wallet'
        self.wlt.lock()
        for i in range(10):
            self.wlt.getNextUnusedAddress()
        self.assertEqual(len(self.wlt.addrMap), originalLength + 13)

        # (5) Re-reading wallet from file, compare the two wallets'
        wlt2 = PyBtcWallet().readWalletFile(self.wlt.getWalletPath())
        self.assertTrue(self.wlt.isEqualTo(wlt2))

        #############################################################################
        # !!!  #forkOnlineWallet()
        # (6)Testing forking encrypted wallet for online mode'
        self.wlt.forkOnlineWallet('OnlineVersionOfEncryptedWallet.bin')
        wlt2.readWalletFile('OnlineVersionOfEncryptedWallet.bin')
        for key in wlt2.addrMap:
            self.assertTrue(self.wlt.addrMap[key].isLocked)
            self.assertEqual(
                self.wlt.addrMap[key].binPrivKey32_Plain.toHexStr(), '')
        # (6)Getting a new addresses from both wallets'
        for i in range(self.wlt.addrPoolSize * 2):
            self.wlt.getNextUnusedAddress()
            wlt2.getNextUnusedAddress()

        newaddr1 = self.wlt.getNextUnusedAddress()
        newaddr2 = wlt2.getNextUnusedAddress()
        self.assertTrue(newaddr1.getAddr160() == newaddr2.getAddr160())
        self.assertEqual(len(wlt2.addrMap), 3 * originalLength + 14)

        # (6) Re-reading wallet from file, compare the two wallets
        wlt3 = PyBtcWallet().readWalletFile(
            'OnlineVersionOfEncryptedWallet.bin')
        self.assertTrue(wlt3.isEqualTo(wlt2))
        #############################################################################
        # (7)Testing removing wallet encryption'
        # Wallet is locked?  ', self.wlt.isLocked
        self.wlt.unlock(securePassphrase=self.passphrase2)
        self.wlt.changeWalletEncryption(None)
        for key in self.wlt.addrMap:
            self.assertFalse(self.wlt.addrMap[key].isLocked)
            self.assertNotEqual(
                self.wlt.addrMap[key].binPrivKey32_Plain.toHexStr(), '')

        # (7) Re-reading wallet from file, compare the two wallets'
        wlt2 = PyBtcWallet().readWalletFile(self.wlt.getWalletPath())
        self.assertTrue(self.wlt.isEqualTo(wlt2))

        #############################################################################
        # \n'
        # *********************************************************************'
        # (8)Doing interrupt tests to test wallet-file-update recovery'
        def hashfile(fn):
            f = open(fn, 'r')
            d = hash256(f.read())
            f.close()
            return binary_to_hex(d[:8])

        def verifyFileStatus(fileAExists = True, fileBExists = True, \
                             fileAupdExists = True, fileBupdExists = True):
            self.assertEqual(os.path.exists(self.fileA), fileAExists)
            self.assertEqual(os.path.exists(self.fileB), fileBExists)
            self.assertEqual(os.path.exists(self.fileAupd), fileAupdExists)
            self.assertEqual(os.path.exists(self.fileBupd), fileBupdExists)

        correctMainHash = hashfile(self.fileA)
        try:
            self.wlt.interruptTest1 = True
            self.wlt.getNextUnusedAddress()
        except InterruptTestError:
            # Interrupted!'
            pass
        self.wlt.interruptTest1 = False

        # (8a)Interrupted getNextUnusedAddress on primary file update'
        verifyFileStatus(True, True, False, True)
        # (8a)Do consistency check on the wallet'
        self.wlt.doWalletFileConsistencyCheck()
        verifyFileStatus(True, True, False, False)
        self.assertEqual(correctMainHash, hashfile(self.fileA))

        try:
            self.wlt.interruptTest2 = True
            self.wlt.getNextUnusedAddress()
        except InterruptTestError:
            # Interrupted!'
            pass
        self.wlt.interruptTest2 = False

        # (8b)Interrupted getNextUnusedAddress on between primary/backup update'
        verifyFileStatus(True, True, True, True)
        # (8b)Do consistency check on the wallet'
        self.wlt.doWalletFileConsistencyCheck()
        verifyFileStatus(True, True, False, False)
        self.assertEqual(hashfile(self.fileA), hashfile(self.fileB))
        # (8c) Try interrupting at state 3'
        verifyFileStatus(True, True, False, False)

        try:
            self.wlt.interruptTest3 = True
            self.wlt.getNextUnusedAddress()
        except InterruptTestError:
            # Interrupted!'
            pass
        self.wlt.interruptTest3 = False

        # (8c)Interrupted getNextUnusedAddress on backup file update'
        verifyFileStatus(True, True, True, False)
        # (8c)Do consistency check on the wallet'
        self.wlt.doWalletFileConsistencyCheck()
        verifyFileStatus(True, True, False, False)
        self.assertEqual(hashfile(self.fileA), hashfile(self.fileB))

        #############################################################################
        # \n'
        # *********************************************************************'
        # (9)Checksum-based byte-error correction tests!'
        # (9)Start with a good primary and backup file...'

        # (9a)Open primary wallet, change second byte in KDF'
        wltfile = open(self.wlt.walletPath, 'r+b')
        wltfile.seek(326)
        wltfile.write('\xff')
        wltfile.close()
        # (9a)Byte changed, file hashes:'
        verifyFileStatus(True, True, False, False)

        # (9a)Try to read wallet from file, should correct KDF error, write fix'
        wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
        verifyFileStatus(True, True, False, False)
        self.assertNotEqual(hashfile(self.fileA), hashfile(self.fileB))

        # \n'
        # *********************************************************************'
        # (9b)Change a byte in each checksummed field in root addr'
        wltfile = open(self.wlt.walletPath, 'r+b')
        wltfile.seek(838)
        wltfile.write('\xff')
        wltfile.seek(885)
        wltfile.write('\xff')
        wltfile.seek(929)
        wltfile.write('\xff')
        wltfile.seek(954)
        wltfile.write('\xff')
        wltfile.seek(1000)
        wltfile.write('\xff')
        wltfile.close()
        # (9b) New file hashes...'
        verifyFileStatus(True, True, False, False)

        # (9b)Try to read wallet from file, should correct address errors'
        wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
        verifyFileStatus(True, True, False, False)
        self.assertNotEqual(hashfile(self.fileA), hashfile(self.fileB))

        # \n'
        # *********************************************************************'
        # (9c)Change a byte in each checksummed field, of first non-root addr'
        wltfile = open(self.wlt.walletPath, 'r+b')
        wltfile.seek(1261 + 21 + 838)
        wltfile.write('\xff')
        wltfile.seek(1261 + 21 + 885)
        wltfile.write('\xff')
        wltfile.seek(1261 + 21 + 929)
        wltfile.write('\xff')
        wltfile.seek(1261 + 21 + 954)
        wltfile.write('\xff')
        wltfile.seek(1261 + 21 + 1000)
        wltfile.write('\xff')
        wltfile.close()
        # (9c) New file hashes...'
        verifyFileStatus(True, True, False, False)

        # (9c)Try to read wallet from file, should correct address errors'
        wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
        verifyFileStatus(True, True, False, False)
        self.assertNotEqual(hashfile(self.fileA), hashfile(self.fileB))

        # \n'
        # *********************************************************************'
        # (9d)Now butcher the CHECKSUM, see if correction works'
        wltfile = open(self.wlt.walletPath, 'r+b')
        wltfile.seek(977)
        wltfile.write('\xff')
        wltfile.close()
        # (9d) New file hashes...'
        verifyFileStatus(True, True, False, False)

        # (9d)Try to read wallet from file, should correct address errors'
        wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
        verifyFileStatus(True, True, False, False)
        self.assertNotEqual(hashfile(self.fileA), hashfile(self.fileB))

        # *******'
        # (9z) Test comment I/O'
        comment1 = 'This is my normal unit-testing address.'
        comment2 = 'This is fake tx... no tx has this hash.'
        comment3 = comment1 + '  Corrected!'
        hash1 = '\x1f' * 20  # address160
        hash2 = '\x2f' * 32  # tx hash
        self.wlt.setComment(hash1, comment1)
        self.wlt.setComment(hash2, comment2)
        self.wlt.setComment(hash1, comment3)

        wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
        c3 = wlt2.getComment(hash1)
        c2 = wlt2.getComment(hash2)
        self.assertEqual(c3, comment3)
        self.assertEqual(c2, comment2)
示例#22
0
class ArmoryDTiabTest(TiabTest):
    def armoryDTiabTestCallback(self, action, args):
        if action == REFRESH_ACTION:
            for wltID in args:
                print wltID
                if wltID in self.wltIDs:
                    self.numberOfWalletsScanned += 1

    def setUp(self):
        self.verifyBlockHeight()
        # Load the primary file from the test net in a box
        self.fileA = os.path.join(self.tiab.tiabDirectory, 'tiab', 'armory', \
                                  'armory_%s_.wallet' % FIRST_WLT_NAME)
        self.wltA = PyBtcWallet().readWalletFile(self.fileA)
        self.fileB = os.path.join(self.tiab.tiabDirectory, 'tiab', 'armory', \
                                  'armory_%s_.wallet' % SECOND_WLT_NAME)
        self.wltB = PyBtcWallet().readWalletFile(self.fileB)
        self.fileC = os.path.join(self.tiab.tiabDirectory, 'tiab', 'armory', \
                                  'armory_%s_.wallet' % THIRD_WLT_NAME)
        self.wltC = PyBtcWallet().readWalletFile(self.fileC)
        self.jsonServer = Armory_Json_Rpc_Server(self.wltA, \
                                      inWltMap={SECOND_WLT_NAME : self.wltB, \
                                                THIRD_WLT_NAME : self.wltC}, \
                         armoryHomeDir=os.path.join(self.tiab.tiabDirectory, \
                                                    'tiab','armory'))

        self.wltIDs = [
            self.wltA.uniqueIDB58, self.wltB.uniqueIDB58, self.wltC.uniqueIDB58
        ]
        #register a callback
        TheBDM.registerCppNotification(self.armoryDTiabTestCallback)

        #flag to check on wallet scan status
        self.numberOfWalletsScanned = 0

        self.wltA.registerWallet()
        time.sleep(0.5)
        self.wltB.registerWallet()
        time.sleep(0.5)
        self.wltC.registerWallet()
        time.sleep(0.5)
        #wait on scan for 20sec then raise if the scan hasn't finished yet
        i = 0
        while self.numberOfWalletsScanned < 3:
            time.sleep(0.5)
            i += 1
            if i >= 40:
                raise RuntimeError("self.numberOfWalletsScanned = %d" %
                                   self.numberOfWalletsScanned)

    def tearDown(self):
        TheBDM.unregisterCppNotification(self.armoryDTiabTestCallback)
        self.wltA.unregisterWallet()
        self.wltB.unregisterWallet()
        self.wltC.unregisterWallet()
        self.resetWalletFiles()

    def testActiveWallet(self):
        self.jsonServer.jsonrpc_setactivewallet(FIRST_WLT_NAME)
        result = self.jsonServer.jsonrpc_getactivewallet()
        self.assertEqual(result, FIRST_WLT_NAME)

        bogusResult = self.jsonServer.jsonrpc_setactivewallet(
            'bogus wallet name')
        self.assertTrue('does not exist' in bogusResult)

    # Tests all of the address meta data functions at once

    def testAddressMetaData(self):
        testInput = {
            TIAB_WLT_1_ADDR_1: {
                'chain': 5,
                'index': 2
            },
            TIAB_WLT_1_ADDR_2: {
                'CrazyField': 'what',
                '1': 1,
                '2': 2
            }
        }
        self.jsonServer.jsonrpc_setaddressmetadata(testInput)
        testOutput1 = self.jsonServer.jsonrpc_getaddressmetadata()
        self.assertEqual(testOutput1, testInput)
        self.jsonServer.jsonrpc_clearaddressmetadata()
        testOutput2 = self.jsonServer.jsonrpc_getaddressmetadata()
        self.assertEqual(testOutput2, {})

    def testListloadedwallets(self):
        result = self.jsonServer.jsonrpc_listloadedwallets()
        self.assertEqual(len(result.keys()), 3)
        self.assertTrue(FIRST_WLT_NAME in result.values())
        self.assertTrue(SECOND_WLT_NAME in result.values())
        self.assertTrue(THIRD_WLT_NAME in result.values())

    def getPrivateKey(self, address):
        hash160 = addrStr_to_hash160(address)[1]
        if self.wltA.isLocked:
            self.wltA.unlock(securePassphrase=SecureBinaryData(PASSPHRASE1),
                             tempKeyLifetime=1000000)
        return self.wltA.addrMap[hash160].binPrivKey32_Plain.toBinStr()

    # Test Create lockbox and list loaded lockbox at the same time.
    # Also test set and get active lockbox.

    def testLockboxMethods(self):
        self.assertEqual(self.jsonServer.jsonrpc_getactivelockbox(), None)
        addrFromFirstWlt = self.wltA.peekNextUnusedAddr().getPubKey().toHexStr(
        )
        addrFromSecondWlt = self.wltB.peekNextUnusedAddr().getPubKey(
        ).toHexStr()
        addrFromThirdWlt = self.wltC.peekNextUnusedAddr().getPubKey().toHexStr(
        )

        # This test should succeed.
        actualResult1 = self.jsonServer.jsonrpc_createlockbox(2, 3, \
                                                              addrFromFirstWlt, \
                                                              SECOND_WLT_NAME, \
                                                              THIRD_WLT_NAME)
        self.assertTrue(TWO_OF_THREE_LB_NAME in actualResult1.values())

        # This test should fail because the first createlockbox() used the 2nd &
        # 3rd addresses.
        actualResult2 = self.jsonServer.jsonrpc_createlockbox(2, 3, \
                                                              addrFromFirstWlt, \
                                                              addrFromSecondWlt, \
                                                              addrFromThirdWlt)
        self.assertTrue(TWO_OF_THREE_LB_NAME in actualResult2['Error'])

        # This test should succeed.
        actualResult3 = self.jsonServer.jsonrpc_createlockbox(2, 2, \
                                                              addrFromSecondWlt, \
                                                              addrFromThirdWlt)
        self.assertEqual(TWO_OF_TWO_LB_NAME, actualResult3['id'])
        listResult3 = self.jsonServer.jsonrpc_listloadedlockboxes()
        self.assertEqual(len(listResult3.keys()), 2)
        self.assertTrue(TWO_OF_TWO_LB_NAME in listResult3.values())

        # This test should fail because of a bad wallet name.
        actualResult4 = self.jsonServer.jsonrpc_createlockbox(2, 2, \
                                                              addrFromFirstWlt, \
                                                              BAD_WLT_NAME)
        self.assertTrue(BAD_WLT_NAME in actualResult4['Error'])

        # This test should fail because of a malformed, uncompressed public key.
        actualResult5 = self.jsonServer.jsonrpc_createlockbox(2, 2, \
                                                              addrFromFirstWlt, \
                                                              BAD_PK_UNCOMP_1)
        self.assertTrue(BAD_PK_UNCOMP_1 in actualResult5['Error'])

        # This test should fail because of a malformed, compressed public key.
        actualResult6 = self.jsonServer.jsonrpc_createlockbox(2, 2, \
                                                              addrFromFirstWlt, \
                                                              BAD_PK_COMP_1)
        self.assertTrue(BAD_PK_COMP_1 in actualResult6['Error'])

        # This test should fail due to a compressed public key being used.
        foundUncompAddr = False
        actualResult7 = self.jsonServer.jsonrpc_createlockbox(2, 2, \
                                                              addrFromFirstWlt, \
                                                              GOOD_PK_COMP_1)
        self.assertTrue(GOOD_PK_COMP_1 in actualResult7['Error'])

        # This test should fail due to a malformed public key (incorrect length).
        actualResult8 = self.jsonServer.jsonrpc_createlockbox(2, 2, \
                                                              addrFromFirstWlt, \
                                                              BAD_PK)
        self.assertTrue(BAD_PK in actualResult8['Error'])

        # These tests should fail for various reasons related to the # of inputs.
        actualResult09 = self.jsonServer.jsonrpc_createlockbox(3, 2, \
                                                               addrFromFirstWlt, \
                                                               addrFromThirdWlt)
        self.assertTrue(ERRSTR09 in actualResult09['Error'])
        actualResult10 = self.jsonServer.jsonrpc_createlockbox(8, 8, \
                                                               addrFromFirstWlt, \
                                                               addrFromSecondWlt, \
                                                               addrFromThirdWlt, \
                                                               FIRST_WLT_NAME, \
                                                               SECOND_WLT_NAME, \
                                                               THIRD_WLT_NAME, \
                                                               GOOD_PK_UNCOMP_1, \
                                                               GOOD_PK_UNCOMP_2)
        self.assertTrue(ERRSTR10 in actualResult10['Error'])
        actualResult11 = self.jsonServer.jsonrpc_createlockbox(1, 8, \
                                                               addrFromFirstWlt, \
                                                               addrFromSecondWlt, \
                                                               addrFromThirdWlt, \
                                                               FIRST_WLT_NAME, \
                                                               SECOND_WLT_NAME, \
                                                               THIRD_WLT_NAME, \
                                                               GOOD_PK_UNCOMP_1, \
                                                               GOOD_PK_UNCOMP_2)
        self.assertTrue(ERRSTR11 in actualResult11['Error'])
        actualResult12 = self.jsonServer.jsonrpc_createlockbox(1, 4)
        self.assertTrue(ERRSTR12 in actualResult12['Error'])
        actualResult13 = self.jsonServer.jsonrpc_createlockbox(1, 2, \
                                                               addrFromFirstWlt, \
                                                               addrFromSecondWlt, \
                                                               addrFromThirdWlt)
        self.assertTrue(ERRSTR13 in actualResult13['Error'])
        actualResult14 = self.jsonServer.jsonrpc_createlockbox(1, 2, \
                                                               addrFromFirstWlt)
        self.assertTrue(ERRSTR14 in actualResult14['Error'])

        # These tests should succeed.
        self.jsonServer.jsonrpc_setactivelockbox(TWO_OF_TWO_LB_NAME)
        self.assertEqual(self.jsonServer.jsonrpc_getactivelockbox(), \
                         TWO_OF_TWO_LB_NAME)
        self.jsonServer.jsonrpc_setactivelockbox(TWO_OF_THREE_LB_NAME)
        self.assertEqual(self.jsonServer.jsonrpc_getactivelockbox(), \
                         TWO_OF_THREE_LB_NAME)

    def testVerifysignature(self):
        clearSignMessage = ASv1CS(self.getPrivateKey(TIAB_WLT_1_ADDR_1), \
                                  TEST_MESSAGE)
        inMsg = '\"' + clearSignMessage + '\"'
        result = self.jsonServer.jsonrpc_verifysignature(inMsg)
        self.assertEqual(result['message'], TEST_MESSAGE)
        self.assertEqual(result['address'], TIAB_WLT_1_ADDR_1)

    # Requires Supernode
    @SkipTest
    def testReceivedfromsigner(self):
        clearSignMessage2 = ASv1CS(self.getPrivateKey(TIAB_WLT_1_ADDR_3), \
                                   TEST_MESSAGE)
        inMsg2 = '\"' + clearSignMessage2 + '\"'
        result2 = self.jsonServer.jsonrpc_getreceivedfromsigner(inMsg2)
        self.assertEqual(result2['message'], TEST_MESSAGE)
        self.assertEqual(result2['amount'], 0)

    # Requires Supernode
    @SkipTest
    def testReceivedfromaddress(self):
        result = self.jsonServer.jsonrpc_getreceivedfromaddress(
            TIAB_WLT_3_ADDR_3)
        self.assertEqual(result, 0)
        result = self.jsonServer.jsonrpc_getreceivedfromaddress(
            TIAB_WLT_1_ADDR_2)
        self.assertEqual(result, EXPECTED_RECEIVED_FROM_TIAB_WLT_1_ADDR_2)

    def testGettransaction(self):
        tx = self.jsonServer.jsonrpc_gettransaction(
            'db0ee46beff3a61f38bfc563f92c11449ed57c3d7d5cd5aafbe0114e5a9ceee4')
        self.assertEqual(
            tx, {
                'category':
                'send',
                'inputs': [{
                    'fromtxid':
                    '04b865ecf5fca3a56f6ce73a571a09a668f4b7aa5a7547a5f51fae08eadcdbb5',
                    'ismine': True,
                    'fromtxindex': 1,
                    'value': 1000.0,
                    'address': 'mtZ2d1jFZ9YNp3Ku5Fb2u8Tfu3RgimBHAD'
                }],
                'direction':
                'send',
                'fee':
                0.0001,
                'totalinputs':
                1000.0,
                'outputs': [{
                    'address': 'mpXd2u8fPVYdL1Nf9bZ4EFnqhkNyghGLxL',
                    'value': 20.0,
                    'ismine': False
                }, {
                    'address': 'mgLjhTCUtbeLPP9fDkBnG8oztWgJaXZQjn',
                    'value': 979.9999,
                    'ismine': True
                }],
                'txid':
                'db0ee46beff3a61f38bfc563f92c11449ed57c3d7d5cd5aafbe0114e5a9ceee4',
                'confirmations':
                10,
                'orderinblock':
                1,
                'mainbranch':
                True,
                'numtxin':
                1,
                'numtxout':
                2,
                'netdiff':
                -20.0001,
                'infomissing':
                False
            })

    def testGetblock(self):
        block = self.jsonServer.jsonrpc_getblock(
            '0000000064a1ad1f15981a713a6ef08fd98f69854c781dc7b8789cc5f678e01f')
        # This method is broken in a couple ways.
        # For no just verify that raw transaction is correct
        self.assertEqual(
            block['rawheader'],
            '02000000d8778a50d43d3e02c4c20bdd0ed97077a3c4bef3e86ce58975f6f43a00000000d25912cfc67228748494d421512c7a6cc31668fa82b72265261558802a89f4c2e0350153ffff001d10bcc285',
        )

    def testGetinfo(self):
        info = self.jsonServer.jsonrpc_getarmorydinfo()
        self.assertEqual(info['blocks'], TOP_TIAB_BLOCK)
        self.assertEqual(info['bdmstate'], BDM_BLOCKCHAIN_READY)
        self.assertEqual(info['walletversionstr'], '1.35')
        self.assertEqual(info['difficulty'], 1.0)
        self.assertEqual(info['balance'], FIRST_WLT_BALANCE)

    def testListtransactions(self):
        #takes a history page count now, not an amount of transactions to return
        txList = self.jsonServer.jsonrpc_listtransactions(0)
        self.assertTrue(len(txList) > 10)
        self.assertEqual(
            txList[0], {
                'blockhash':
                '0000000064a1ad1f15981a713a6ef08fd98f69854c781dc7b8789cc5f678e01f',
                'blockindex': 1,
                'confirmations': 31,
                'address': 'mtZ2d1jFZ9YNp3Ku5Fb2u8Tfu3RgimBHAD',
                'category': 'receive',
                'account': '',
                'txid':
                '04b865ecf5fca3a56f6ce73a571a09a668f4b7aa5a7547a5f51fae08eadcdbb5',
                'blocktime': 1392588256,
                'amount': 1000.0,
                'timereceived': 1392588256,
                'time': 1392588256
            })

    def testGetledgersimple(self):
        ledger = self.jsonServer.jsonrpc_getledgersimple(FIRST_WLT_NAME)
        self.assertTrue(len(ledger) > 4)
        amountList = [row['amount'] for row in ledger]
        expectedAmountList = [20.0, 6.0, 10.0, 0.8, 30.0]
        self.assertEqual(amountList[:5], expectedAmountList)

    def testGetledger(self):
        ledger = self.jsonServer.jsonrpc_getledger(FIRST_WLT_NAME)
        self.assertTrue(len(ledger) > 6)
        amountList = [row['amount'] for row in ledger]
        #expectedAmountList = [1000.0, 20.0, 30.0, 0.8, 10.0, 6.0, 20.0]
        expectedAmountList = [20.0, 6.0, 10.0, 0.8, 30.0, 20.0, 1000.0]
        self.assertEqual(amountList, expectedAmountList)
        self.assertEqual(ledger[0]['direction'], 'receive')
        self.assertEqual(len(ledger[0]['recipme']), 1)
        self.assertEqual(ledger[0]['recipme'][0]['amount'], 20.0)
        self.assertEqual(len(ledger[0]['recipother']), 1)
        self.assertEqual(ledger[0]['recipother'][0]['amount'], 0.8998)
        self.assertEqual(len(ledger[0]['senderme']), 0)
        self.assertEqual(ledger[0]['senderother'][0]['amount'], 11.8999)

        self.assertEqual(ledger[5]['direction'], 'send')
        self.assertEqual(len(ledger[5]['senderother']), 0)
        self.assertEqual(len(ledger[5]['senderme']), 1)
        self.assertEqual(ledger[5]['senderme'][0]['amount'], 1000.0)

    def testSendtoaddress(self):
        # Send 1 BTC
        serializedUnsignedTx = \
           self.jsonServer.jsonrpc_createustxtoaddress(TIAB_WLT_3_ADDR_3, \
                                                       BTC_TO_SEND)
        unsignedTx = UnsignedTransaction().unserializeAscii(
            serializedUnsignedTx)
        # Should have 2 txouts to TIAB_WLT_3_ADDR_3 and the change
        self.assertEqual(len(unsignedTx.decorTxOuts), 2)
        foundTxOut = False
        for txout in unsignedTx.decorTxOuts:
            if script_to_addrStr(txout.binScript) == TIAB_WLT_3_ADDR_3:
                self.assertEqual(txout.value, JSONtoAmount(BTC_TO_SEND))
                foundTxOut = True
        self.assertTrue(foundTxOut)

        # Test two paths through signing method and make sure they are equal
        # Wallets in the TIAB start out unencrypted
        f = open(TX_FILENAME, 'w')
        f.write(serializedUnsignedTx)
        f.close()
        serializedSignedTxUnencrypted = \
              self.jsonServer.jsonrpc_signasciitransaction(TX_FILENAME)
        self.jsonServer.jsonrpc_encryptwallet(PASSPHRASE1)
        self.jsonServer.jsonrpc_walletpassphrase(PASSPHRASE1)
        serializedSignedTxEncrypted = \
              self.jsonServer.jsonrpc_signasciitransaction(TX_FILENAME)
        # Other tests expect wallet to be unencrypted
        self.wltA.unlock(securePassphrase=SecureBinaryData(PASSPHRASE1),
                         tempKeyLifetime=1000000)
        self.wltA.changeWalletEncryption()
        signedTxUnencrypted = UnsignedTransaction().unserializeAscii(
            serializedSignedTxUnencrypted)
        signedTxEncrypted = UnsignedTransaction().unserializeAscii(
            serializedSignedTxEncrypted)
        # check number of outputs 1 Btc goes to a single output and the other goes to change
        self.assertEqual(len(signedTxUnencrypted.decorTxOuts), 2)
        self.assertEqual(len(signedTxEncrypted.decorTxOuts), 2)
        self.assertEqual(signedTxUnencrypted.asciiID,
                         signedTxEncrypted.asciiID)
        self.assertTrue(
            JSONtoAmount(BTC_TO_SEND) in [
                signedTxEncrypted.decorTxOuts[0].value,
                signedTxEncrypted.decorTxOuts[1].value
            ])
        self.assertTrue(
            JSONtoAmount(BTC_TO_SEND) in [
                signedTxUnencrypted.decorTxOuts[0].value,
                signedTxUnencrypted.decorTxOuts[1].value
            ])
        f = open(TX_FILENAME, 'w')
        f.write(signedTxEncrypted.serializeAscii())
        f.close()
        txHexToBroadcast = self.jsonServer.jsonrpc_gethextxtobroadcast(
            TX_FILENAME)
        finalPyTx = PyTx().unserialize(hex_to_binary(txHexToBroadcast))
        self.assertEqual(len(finalPyTx.outputs), 2)
        self.assertTrue(
            JSONtoAmount(BTC_TO_SEND) in
            [finalPyTx.outputs[0].value, finalPyTx.outputs[1].value])

    def testSendmany(self):
        # Send 1 BTC
        serializedUnsignedTx = \
           self.jsonServer.jsonrpc_createustxformany(None, ','.join([TIAB_WLT_3_ADDR_2, str(BTC_TO_SEND)]), \
                                                     ','.join([TIAB_WLT_3_ADDR_3, str(BTC_TO_SEND)]))
        unsignedTx = UnsignedTransaction().unserializeAscii(
            serializedUnsignedTx)
        # Should have 2 txouts to TIAB_WLT_3_ADDR_3 and the change
        self.assertEqual(len(unsignedTx.decorTxOuts), 3)
        txOutsFound = 0
        for txout in unsignedTx.decorTxOuts:
            if script_to_addrStr(
                    txout.binScript) in [TIAB_WLT_3_ADDR_2, TIAB_WLT_3_ADDR_3]:
                self.assertEqual(txout.value, JSONtoAmount(BTC_TO_SEND))
                txOutsFound += 1
        self.assertEqual(txOutsFound, 2)

    def testListUnspent(self):
        actualResult = self.jsonServer.jsonrpc_listunspent()

        tx1Found = False
        tx5Found = False
        for i in range(len(actualResult)):
            if actualResult[i]['txid'] == EXPECTED_UNSPENT_TX1_HEX:
                self.assertEqual(actualResult[i]['amount'], \
                                 EXPECTED_UNSPENT_TX1_BAL)
                self.assertEqual(actualResult[i]['confirmations'], \
                                 EXPECTED_UNSPENT_TX1_CONF)
                self.assertEqual(actualResult[i]['priority'], \
                                 EXPECTED_UNSPENT_TX1_PRI)
                tx1Found = True
            elif actualResult[i]['txid'] == EXPECTED_UNSPENT_TX5_HEX:
                self.assertEqual(actualResult[i]['amount'], \
                                 EXPECTED_UNSPENT_TX5_BAL)
                self.assertEqual(actualResult[i]['confirmations'], \
                                 EXPECTED_UNSPENT_TX5_CONF)
                self.assertEqual(actualResult[i]['priority'], \
                                 EXPECTED_UNSPENT_TX5_PRI)
                tx5Found = True
        self.assertTrue(tx1Found)
        self.assertTrue(tx5Found)

    def testListAddrUnspent(self):
        totStr = '%s,%s' % (TIAB_WLT_1_ADDR_3, TIAB_WLT_1_ADDR_8)
        actualResult = self.jsonServer.jsonrpc_listaddrunspent(totStr)

        self.assertEqual(actualResult['addrbalance'][TIAB_WLT_1_ADDR_3], \
                         TIAB_WLT_1_PK_UTXO_BAL_3)
        self.assertEqual(actualResult['addrbalance'][TIAB_WLT_1_ADDR_8], \
                         TIAB_WLT_1_PK_UTXO_BAL_8)
        # NB: Ideally, the TAB asserts would be against addresses with multiple
        # UTXOs. As is, this test case works but could be better.
        self.assertEqual(actualResult['totalbalance'],
                         TIAB_WLT_1_PK_UTXO_BAL_3 + TIAB_WLT_1_PK_UTXO_BAL_8)
        self.assertEqual(actualResult['numutxo'], 2)

    def testGetNewAddress(self):
        actualResult = self.jsonServer.jsonrpc_getnewaddress()
        self.assertEqual(actualResult, EXPECTED_TIAB_NEXT_ADDR)

    def testGetBalance(self):
        balances = {'spendable' : FIRST_WLT_BALANCE, \
                    'spend' : FIRST_WLT_BALANCE, \
                    'unconf' : 0, \
                    'unconfirmed' :  0, \
                    'total' : FIRST_WLT_BALANCE, \
                    'ultimate'  :  FIRST_WLT_BALANCE, \
                    'unspent' :  FIRST_WLT_BALANCE, \
                    'full' :  FIRST_WLT_BALANCE}
        for balanceType in balances.keys():
            result = self.jsonServer.jsonrpc_getbalance(balanceType)
            self.assertEqual(result,
                             AmountToJSON(self.wltA.getBalance(balanceType)))
示例#23
0
class PyBtcWalletTest(TiabTest):

   def setUp(self):
      self.shortlabel = 'TestWallet1'
      self.wltID ='3VB8XSoY'
      
      self.fileA    = os.path.join(self.armoryHomeDir, 'armory_%s_.wallet' % self.wltID)
      self.fileB    = os.path.join(self.armoryHomeDir, 'armory_%s_backup.wallet' % self.wltID)
      self.fileAupd = os.path.join(self.armoryHomeDir, 'armory_%s_backup_unsuccessful.wallet' % self.wltID)
      self.fileBupd = os.path.join(self.armoryHomeDir, 'armory_%s_update_unsuccessful.wallet' % self.wltID)

      self.removeFileList([self.fileA, self.fileB, self.fileAupd, self.fileBupd])
   
      # We need a controlled test, so we script the all the normally-random stuff
      self.privKey   = SecureBinaryData('\xaa'*32)
      self.privKey2  = SecureBinaryData('\x33'*32)
      self.chainstr  = SecureBinaryData('\xee'*32)
      theIV     = SecureBinaryData(hex_to_binary('77'*16))
      self.passphrase  = SecureBinaryData('A self.passphrase')
      self.passphrase2 = SecureBinaryData('A new self.passphrase')
      
      self.wlt = PyBtcWallet().createNewWallet(withEncrypt=False, \
                                          plainRootKey=self.privKey, \
                                          chaincode=self.chainstr,   \
                                          IV=theIV, \
                                          shortLabel=self.shortlabel,
                                          armoryHomeDir = self.armoryHomeDir)
      
   def tearDown(self):
      self.removeFileList([self.fileA, self.fileB, self.fileAupd, self.fileBupd])
      

   # *********************************************************************
   # Testing deterministic, encrypted wallet features'
   # *********************************************************************
   def removeFileList(self, fileList):
      for f in fileList:
         if os.path.exists(f):
            os.remove(f)

   def testBackupWallet(self):
      backupTestPath = os.path.join(self.armoryHomeDir, 'armory_%s_.wallet.backup.test' % self.wltID)
      # Remove backupTestPath in case it exists
      backupFileList = [backupTestPath, self.fileB]
      self.removeFileList(backupFileList)
      # Remove the backup test path that is to be created after tear down.
      self.addCleanup(self.removeFileList, backupFileList)
      self.wlt.backupWalletFile(backupTestPath)
      self.assertTrue(os.path.exists(backupTestPath))
      self.wlt.backupWalletFile()
      self.assertTrue(os.path.exists(self.fileB))
            
   def testIsWltSigningAnyLockbox(self):
      lockboxList = readLockboxesFile(os.path.join(self.armoryHomeDir, MULTISIG_FILE_NAME))
      self.assertFalse(self.wlt.isWltSigningAnyLockbox(lockboxList))
      
      lboxWltAFile   = os.path.join(self.armoryHomeDir,'armory_%s_.wallet' % FIRST_WLT_NAME)
      lboxWltA = PyBtcWallet().readWalletFile(lboxWltAFile, doScanNow=True)
      self.assertTrue(lboxWltA.isWltSigningAnyLockbox(lockboxList))
      
      lboxWltBFile   = os.path.join(self.armoryHomeDir,'armory_%s_.wallet' % SECOND_WLT_NAME)
      lboxWltB = PyBtcWallet().readWalletFile(lboxWltBFile, doScanNow=True)
      self.assertTrue(lboxWltB.isWltSigningAnyLockbox(lockboxList))
      
   # Remove wallet files, need fresh dir for this test
   def testPyBtcWallet(self):

      self.wlt.addrPoolSize = 5
      # No block chain loaded so this should return -1
      # self.assertEqual(self.wlt.detectHighestUsedIndex(True), -1)
      self.assertEqual(self.wlt.kdfKey, None)
      self.assertEqual(binary_to_hex(self.wlt.addrMap['ROOT'].addrStr20), WALLET_ROOT_ADDR )

      #############################################################################
      # (1) Getting a new address:
      newAddr = self.wlt.getNextUnusedAddress()
      self.wlt.pprint(indent=' '*5)
      self.assertEqual(binary_to_hex(newAddr.addrStr20), NEW_UNUSED_ADDR)
   
      # (1) Re-reading wallet from file, compare the two wallets
      wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
      self.assertTrue(self.wlt.isEqualTo(wlt2))
      
      #############################################################################
      # Test locking an unencrypted wallet does not lock
      self.assertFalse(self.wlt.useEncryption)
      self.wlt.lock()
      self.assertFalse(self.wlt.isLocked)
      # (2)Testing unencrypted wallet import-address'
      originalLength = len(self.wlt.linearAddr160List)
      self.wlt.importExternalAddressData(privKey=self.privKey2)
      self.assertEqual(len(self.wlt.linearAddr160List), originalLength+1)
      
      # (2) Re-reading wallet from file, compare the two wallets
      wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
      self.assertTrue(self.wlt.isEqualTo(wlt2))
   
      # (2a)Testing deleteImportedAddress
      # Wallet size before delete:',  os.path.getsize(self.wlt.walletPath)
      # Addresses before delete:', len(self.wlt.linearAddr160List)
      toDelete160 = convertKeyDataToAddress(self.privKey2)
      self.wlt.deleteImportedAddress(toDelete160)
      self.assertEqual(len(self.wlt.linearAddr160List), originalLength)
      
   
      # (2a) Reimporting address for remaining tests
      # Wallet size before reimport:',  os.path.getsize(self.wlt.walletPath)
      self.wlt.importExternalAddressData(privKey=self.privKey2)
      self.assertEqual(len(self.wlt.linearAddr160List), originalLength+1)
      
   
      # (2b)Testing ENCRYPTED wallet import-address
      privKey3  = SecureBinaryData('\xbb'*32)
      privKey4  = SecureBinaryData('\x44'*32)
      self.chainstr2  = SecureBinaryData('\xdd'*32)
      theIV2     = SecureBinaryData(hex_to_binary('66'*16))
      self.passphrase2= SecureBinaryData('hello')
      wltE = PyBtcWallet().createNewWallet(withEncrypt=True, \
                                          plainRootKey=privKey3, \
                                          securePassphrase=self.passphrase2, \
                                          chaincode=self.chainstr2,   \
                                          IV=theIV2, \
                                          shortLabel=self.shortlabel,
                                          armoryHomeDir = self.armoryHomeDir)
      
      #  We should have thrown an error about importing into a  locked wallet...
      self.assertRaises(WalletLockError, wltE.importExternalAddressData, privKey=self.privKey2)


   
      wltE.unlock(securePassphrase=self.passphrase2)
      wltE.importExternalAddressData(privKey=self.privKey2)
   
      # (2b) Re-reading wallet from file, compare the two wallets
      wlt2 = PyBtcWallet().readWalletFile(wltE.walletPath)
      self.assertTrue(wltE.isEqualTo(wlt2))
   
      # (2b) Unlocking wlt2 after re-reading locked-import-wallet
      wlt2.unlock(securePassphrase=self.passphrase2)
      self.assertFalse(wlt2.isLocked)

      #############################################################################
      # Now play with encrypted wallets
      # *********************************************************************'
      # (3)Testing conversion to encrypted wallet
   
      kdfParams = self.wlt.computeSystemSpecificKdfParams(0.1)
      self.wlt.changeKdfParams(*kdfParams)
   
      self.assertEqual(self.wlt.kdf.getSalt(), kdfParams[2])
      self.wlt.changeWalletEncryption( securePassphrase=self.passphrase )
      self.assertEqual(self.wlt.kdf.getSalt(), kdfParams[2])
      
      # (3) Re-reading wallet from file, compare the two wallets'
      wlt2 = PyBtcWallet().readWalletFile(self.wlt.getWalletPath())
      self.assertTrue(self.wlt.isEqualTo(wlt2))
      # NOTE:  this isEqual operation compares the serializations
      #        of the wallet addresses, which only contains the 
      #        encrypted versions of the private keys.  However,
      #        self.wlt is unlocked and contains the plaintext keys, too
      #        while wlt2 does not.
      self.wlt.lock()
      for key in self.wlt.addrMap:
         self.assertTrue(self.wlt.addrMap[key].isLocked)
         self.assertEqual(self.wlt.addrMap[key].binPrivKey32_Plain.toHexStr(), '')
   
      #############################################################################
      # (4)Testing changing self.passphrase on encrypted wallet',
   
      self.wlt.unlock( securePassphrase=self.passphrase )
      for key in self.wlt.addrMap:
         self.assertFalse(self.wlt.addrMap[key].isLocked)
         self.assertNotEqual(self.wlt.addrMap[key].binPrivKey32_Plain.toHexStr(), '')
      # ...to same self.passphrase'
      origKdfKey = self.wlt.kdfKey
      self.wlt.changeWalletEncryption( securePassphrase=self.passphrase )
      self.assertEqual(origKdfKey, self.wlt.kdfKey)
   
      # (4)And now testing new self.passphrase...'
      self.wlt.changeWalletEncryption( securePassphrase=self.passphrase2 )
      self.assertNotEqual(origKdfKey, self.wlt.kdfKey)
      
      # (4) Re-reading wallet from file, compare the two wallets'
      wlt2 = PyBtcWallet().readWalletFile(self.wlt.getWalletPath())
      self.assertTrue(self.wlt.isEqualTo(wlt2))
   
      #############################################################################
      # (5)Testing changing KDF on encrypted wallet'
   
      self.wlt.unlock( securePassphrase=self.passphrase2 )
   
      MEMORY_REQT_BYTES = 1024
      NUM_ITER = 999
      SALT_ALL_0 ='00'*32
      self.wlt.changeKdfParams(MEMORY_REQT_BYTES, NUM_ITER, hex_to_binary(SALT_ALL_0), self.passphrase2)
      self.assertEqual(self.wlt.kdf.getMemoryReqtBytes(), MEMORY_REQT_BYTES)
      self.assertEqual(self.wlt.kdf.getNumIterations(), NUM_ITER)
      self.assertEqual(self.wlt.kdf.getSalt().toHexStr(),  SALT_ALL_0)
   
      self.wlt.changeWalletEncryption( securePassphrase=self.passphrase2 )
      # I don't know why this shouldn't be ''
      # Commenting out because it's a broken assertion
      # self.assertNotEqual(origKdfKey.toHexStr(), '')
   
      # (5) Get new address from locked wallet'
      # Locking wallet'
      self.wlt.lock()
      for i in range(10):
         self.wlt.getNextUnusedAddress()
      self.assertEqual(len(self.wlt.addrMap), originalLength+13)
      
      # (5) Re-reading wallet from file, compare the two wallets'
      wlt2 = PyBtcWallet().readWalletFile(self.wlt.getWalletPath())
      self.assertTrue(self.wlt.isEqualTo(wlt2))
   
      #############################################################################
      # !!!  #forkOnlineWallet()
      # (6)Testing forking encrypted wallet for online mode'
      self.wlt.forkOnlineWallet('OnlineVersionOfEncryptedWallet.bin')
      wlt2.readWalletFile('OnlineVersionOfEncryptedWallet.bin')
      for key in wlt2.addrMap:
         self.assertTrue(self.wlt.addrMap[key].isLocked)
         self.assertEqual(self.wlt.addrMap[key].binPrivKey32_Plain.toHexStr(), '')
      # (6)Getting a new addresses from both wallets'
      for i in range(self.wlt.addrPoolSize*2):
         self.wlt.getNextUnusedAddress()
         wlt2.getNextUnusedAddress()
   
      newaddr1 = self.wlt.getNextUnusedAddress()
      newaddr2 = wlt2.getNextUnusedAddress()   
      self.assertTrue(newaddr1.getAddr160() == newaddr2.getAddr160())
      self.assertEqual(len(wlt2.addrMap), 3*originalLength+14)
   
      # (6) Re-reading wallet from file, compare the two wallets
      wlt3 = PyBtcWallet().readWalletFile('OnlineVersionOfEncryptedWallet.bin')
      self.assertTrue(wlt3.isEqualTo(wlt2))
      #############################################################################
      # (7)Testing removing wallet encryption'
      # Wallet is locked?  ', self.wlt.isLocked
      self.wlt.unlock(securePassphrase=self.passphrase2)
      self.wlt.changeWalletEncryption( None )
      for key in self.wlt.addrMap:
         self.assertFalse(self.wlt.addrMap[key].isLocked)
         self.assertNotEqual(self.wlt.addrMap[key].binPrivKey32_Plain.toHexStr(), '')
   
      # (7) Re-reading wallet from file, compare the two wallets'
      wlt2 = PyBtcWallet().readWalletFile(self.wlt.getWalletPath())
      self.assertTrue(self.wlt.isEqualTo(wlt2))
   
      #############################################################################
      # \n'
      # *********************************************************************'
      # (8)Doing interrupt tests to test wallet-file-update recovery'
      def hashfile(fn):
         f = open(fn,'r')
         d = hash256(f.read())
         f.close()
         return binary_to_hex(d[:8])

      def verifyFileStatus(fileAExists = True, fileBExists = True, \
                           fileAupdExists = True, fileBupdExists = True):
         self.assertEqual(os.path.exists(self.fileA), fileAExists)
         self.assertEqual(os.path.exists(self.fileB), fileBExists)
         self.assertEqual(os.path.exists(self.fileAupd), fileAupdExists)
         self.assertEqual(os.path.exists(self.fileBupd), fileBupdExists)

      correctMainHash = hashfile(self.fileA)
      try:
         self.wlt.interruptTest1 = True
         self.wlt.getNextUnusedAddress()
      except InterruptTestError:
         # Interrupted!'
         pass
      self.wlt.interruptTest1 = False
   
      # (8a)Interrupted getNextUnusedAddress on primary file update'
      verifyFileStatus(True, True, False, True)
      # (8a)Do consistency check on the wallet'
      self.wlt.doWalletFileConsistencyCheck()
      verifyFileStatus(True, True, False, False)
      self.assertEqual(correctMainHash, hashfile(self.fileA))

      try:
         self.wlt.interruptTest2 = True
         self.wlt.getNextUnusedAddress()
      except InterruptTestError:
         # Interrupted!'
         pass
      self.wlt.interruptTest2 = False
   
      # (8b)Interrupted getNextUnusedAddress on between primary/backup update'
      verifyFileStatus(True, True, True, True)
      # (8b)Do consistency check on the wallet'
      self.wlt.doWalletFileConsistencyCheck()
      verifyFileStatus(True, True, False, False)
      self.assertEqual(hashfile(self.fileA), hashfile(self.fileB))
      # (8c) Try interrupting at state 3'
      verifyFileStatus(True, True, False, False)
   
      try:
         self.wlt.interruptTest3 = True
         self.wlt.getNextUnusedAddress()
      except InterruptTestError:
         # Interrupted!'
         pass
      self.wlt.interruptTest3 = False
   
      # (8c)Interrupted getNextUnusedAddress on backup file update'
      verifyFileStatus(True, True, True, False)
      # (8c)Do consistency check on the wallet'
      self.wlt.doWalletFileConsistencyCheck()
      verifyFileStatus(True, True, False, False)
      self.assertEqual(hashfile(self.fileA), hashfile(self.fileB))
   
      #############################################################################
      # \n'
      # *********************************************************************'
      # (9)Checksum-based byte-error correction tests!'
      # (9)Start with a good primary and backup file...'
   
      # (9a)Open primary wallet, change second byte in KDF'
      wltfile = open(self.wlt.walletPath,'r+b')
      wltfile.seek(326)
      wltfile.write('\xff')
      wltfile.close()
      # (9a)Byte changed, file hashes:'
      verifyFileStatus(True, True, False, False)
   
      # (9a)Try to read wallet from file, should correct KDF error, write fix'
      wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
      verifyFileStatus(True, True, False, False)
      self.assertNotEqual(hashfile(self.fileA), hashfile(self.fileB))
   
      # \n'
      # *********************************************************************'
      # (9b)Change a byte in each checksummed field in root addr'
      wltfile = open(self.wlt.walletPath,'r+b')
      wltfile.seek(838);  wltfile.write('\xff')
      wltfile.seek(885);  wltfile.write('\xff')
      wltfile.seek(929);  wltfile.write('\xff')
      wltfile.seek(954);  wltfile.write('\xff')
      wltfile.seek(1000);  wltfile.write('\xff')
      wltfile.close()
      # (9b) New file hashes...'
      verifyFileStatus(True, True, False, False)
   
      # (9b)Try to read wallet from file, should correct address errors'
      wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
      verifyFileStatus(True, True, False, False)
      self.assertNotEqual(hashfile(self.fileA), hashfile(self.fileB))
      
      # \n'
      # *********************************************************************'
      # (9c)Change a byte in each checksummed field, of first non-root addr'
      wltfile = open(self.wlt.walletPath,'r+b')
      wltfile.seek(1261+21+838);  wltfile.write('\xff')
      wltfile.seek(1261+21+885);  wltfile.write('\xff')
      wltfile.seek(1261+21+929);  wltfile.write('\xff')
      wltfile.seek(1261+21+954);  wltfile.write('\xff')
      wltfile.seek(1261+21+1000);  wltfile.write('\xff')
      wltfile.close()
      # (9c) New file hashes...'
      verifyFileStatus(True, True, False, False)
   
      # (9c)Try to read wallet from file, should correct address errors'
      wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
      verifyFileStatus(True, True, False, False)
      self.assertNotEqual(hashfile(self.fileA), hashfile(self.fileB))
   
      # \n'
      # *********************************************************************'
      # (9d)Now butcher the CHECKSUM, see if correction works'
      wltfile = open(self.wlt.walletPath,'r+b')
      wltfile.seek(977); wltfile.write('\xff')
      wltfile.close()
      # (9d) New file hashes...'
      verifyFileStatus(True, True, False, False)
   
      # (9d)Try to read wallet from file, should correct address errors'
      wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
      verifyFileStatus(True, True, False, False)
      self.assertNotEqual(hashfile(self.fileA), hashfile(self.fileB))
   
   
      # *******'
      # (9z) Test comment I/O'
      comment1 = 'This is my normal unit-testing address.'
      comment2 = 'This is fake tx... no tx has this hash.'
      comment3 = comment1 + '  Corrected!'
      hash1 = '\x1f'*20  # address160
      hash2 = '\x2f'*32  # tx hash
      self.wlt.setComment(hash1, comment1)
      self.wlt.setComment(hash2, comment2)
      self.wlt.setComment(hash1, comment3)
   
      wlt2 = PyBtcWallet().readWalletFile(self.wlt.walletPath)
      c3 = wlt2.getComment(hash1)
      c2 = wlt2.getComment(hash2)
      self.assertEqual(c3, comment3)
      self.assertEqual(c2, comment2)

# Running tests with "python <module name>" will NOT work for any Armory tests
# You must run tests with "python -m unittest <module name>" or run all tests with "python -m unittest discover"
# if __name__ == "__main__":
#    unittest.main()