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