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)

   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)
      
   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)))
class PyBtcWalletTest(TiabTest):

   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)
      
   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(ARMORY_HOME_DIR, '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))

   # 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))
      
      #############################################################################
      # (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)
Esempio n. 3
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)))
Esempio n. 4
0
class PyBtcWalletTest(TiabTest):
    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)

    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(
            ARMORY_HOME_DIR, '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))

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

        #############################################################################
        # (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)
Esempio n. 5
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)
Esempio n. 6
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.Reset()
      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)