Ejemplo n.º 1
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)))
   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)
Ejemplo n.º 3
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
            ])
Ejemplo n.º 4
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])
Ejemplo n.º 5
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)))
Ejemplo n.º 6
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)
Ejemplo n.º 7
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
            ])
Ejemplo n.º 8
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])
Ejemplo n.º 9
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()