def breakDownWallet(walletPath, fragSize): print 'breaking down wallet in packs of %d addresses' % fragSize print 'reading wallet' theWallet = PyBtcWallet().readWalletFile(walletPath) nAddresses = len(theWallet.addrMap) addrIndex = 0 wltIndex = 1 if walletPath[-7:] == '.wallet': newDir = walletPath[:-7] else: newDir = os.path.dirname(walletPath) if not os.path.exists(newDir): os.mkdir(newDir) rootAddr = theWallet.addrMap['ROOT'] withEncrypt = theWallet.useEncryption addrIter = theWallet.addrMap.iteritems() while nAddresses > 0: print 'breaking down wallet from address #%d to #%d' % ( addrIndex, addrIndex + fragSize - 1) nAddresses -= fragSize newWalletPath = os.path.join(newDir, 'armory_wlt_%05d_.wallet' % wltIndex) wltIndex += 1 walletFragment = PyBtcWallet() createNewWallet(walletFragment, rootAddr, newWalletPath, withEncrypt, theWallet.kdf) fileData = BinaryPacker() i = 0 try: while i < fragSize: addrItem = addrIter.next()[1] addrItem.chainIndex = -2 fileData.put( BINARY_CHUNK, '\x00' + addrItem.addrStr20 + addrItem.serialize()) #walletFragment.walletFileSafeUpdate([[WLT_UPDATE_ADD, \ #WLT_DATATYPE_KEYDATA, addrItem.addrStr20, addrItem]]) i += 1 except StopIteration: pass walletFile = open(newWalletPath, 'ab') walletFile.write(fileData.getBinaryString()) walletFile.close() addrIndex += i print 'Done'
def 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 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 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))
def setUp(self): self.shortlabel = 'TestWallet1' self.wltID = '3VB8XSoY' if USE_TESTNET else '3VB8XSmd' self.fileA = os.path.join(ARMORY_HOME_DIR, 'armory_%s_.wallet' % self.wltID) self.fileB = os.path.join(ARMORY_HOME_DIR, 'armory_%s_backup.wallet' % self.wltID) self.fileAupd = os.path.join( ARMORY_HOME_DIR, 'armory_%s_backup_unsuccessful.wallet' % self.wltID) self.fileBupd = os.path.join( ARMORY_HOME_DIR, 'armory_%s_update_unsuccessful.wallet' % self.wltID) self.removeFileList( [self.fileA, self.fileB, self.fileAupd, self.fileBupd]) # We need a controlled test, so we script the all the normally-random stuff self.privKey = SecureBinaryData('\xaa' * 32) self.privKey2 = SecureBinaryData('\x33' * 32) self.chainstr = SecureBinaryData('\xee' * 32) theIV = SecureBinaryData(hex_to_binary('77' * 16)) self.passphrase = SecureBinaryData('A self.passphrase') self.passphrase2 = SecureBinaryData('A new self.passphrase') self.wlt = PyBtcWallet().createNewWallet(withEncrypt=False, \ plainRootKey=self.privKey, \ chaincode=self.chainstr, \ IV=theIV, \ shortLabel=self.shortlabel)
def setUp(self): self.fileA = os.path.join(ARMORY_HOME_DIR, 'armory_%s_.wallet' % TEST_WALLET_ID) self.fileB = os.path.join(ARMORY_HOME_DIR, 'armory_%s_backup.wallet' % TEST_WALLET_ID) self.fileAupd = os.path.join( ARMORY_HOME_DIR, 'armory_%s_backup_unsuccessful.wallet' % TEST_WALLET_ID) self.fileBupd = os.path.join( ARMORY_HOME_DIR, 'armory_%s_update_unsuccessful.wallet' % TEST_WALLET_ID) self.removeFileList( [self.fileA, self.fileB, self.fileAupd, self.fileBupd]) # We need a controlled test, so we script the all the normally-random stuff self.privKey = SecureBinaryData('\xaa' * 32) self.privKey2 = SecureBinaryData('\x33' * 32) self.chainstr = SecureBinaryData('\xee' * 32) theIV = SecureBinaryData(hex_to_binary('77' * 16)) self.passphrase = SecureBinaryData('A self.passphrase') self.passphrase2 = SecureBinaryData('A new self.passphrase') self.wallet = PyBtcWallet().createNewWallet(withEncrypt=False, \ plainRootKey=self.privKey, \ chaincode=self.chainstr, \ IV=theIV, \ shortLabel=TEST_WALLET_NAME, \ longLabel=TEST_WALLET_DESCRIPTION) self.jsonServer = Armory_Json_Rpc_Server(self.wallet) TheBDM.registerWallet(self.wallet)
def __init__(self, wallet=None, walletPath=''): if wallet != None: self.wallet = wallet else: if not os.path.exists(walletPath): print 'Wallet does not exist:' print ' ', walletPath raise WalletNotFound self.wallet = PyBtcWallet().readWalletFile(walletPath)
def setUp(self): self.verifyBlockHeight() # Load the primary file from the test net in a box self.fileA = os.path.join(self.tiab.tiabDirectory, 'tiab', 'armory', \ 'armory_%s_.wallet' % FIRST_WLT_NAME) self.wltA = PyBtcWallet().readWalletFile(self.fileA, doScanNow=True) self.fileB = os.path.join(self.tiab.tiabDirectory, 'tiab', 'armory', \ 'armory_%s_.wallet' % SECOND_WLT_NAME) self.wltB = PyBtcWallet().readWalletFile(self.fileB, doScanNow=True) self.fileC = os.path.join(self.tiab.tiabDirectory, 'tiab', 'armory', \ 'armory_%s_.wallet' % THIRD_WLT_NAME) self.wltC = PyBtcWallet().readWalletFile(self.fileC, doScanNow=True) self.jsonServer = Armory_Json_Rpc_Server(self.wltA, \ inWltMap={SECOND_WLT_NAME : self.wltB, \ THIRD_WLT_NAME : self.wltC}, \ armoryHomeDir=os.path.join(self.tiab.tiabDirectory, \ 'tiab','armory')) TheBDM.registerWallet(self.wltA)
def createWalletList(n, nameString): walletList = [] for i in range(n): name = "%s #%d" % (nameString, i) newWallet = PyBtcWallet().createNewWallet( \ withEncrypt=False, \ shortLabel=name, \ longLabel=name, \ doRegisterWithBDM=False) walletList.append(newWallet) return walletList
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 setUp(self): self.verifyBlockHeight() self.fileA = os.path.join(self.armoryHomeDir, 'armory_%s_.wallet' % TEST_WALLET_ID) self.fileB = os.path.join(self.armoryHomeDir, 'armory_%s_backup.wallet' % TEST_WALLET_ID) self.fileAupd = os.path.join( self.armoryHomeDir, 'armory_%s_backup_unsuccessful.wallet' % TEST_WALLET_ID) self.fileBupd = os.path.join( self.armoryHomeDir, 'armory_%s_update_unsuccessful.wallet' % TEST_WALLET_ID) self.removeFileList( [self.fileA, self.fileB, self.fileAupd, self.fileBupd]) # We need a controlled test, so we script the all the normally-random stuff self.privKey = SecureBinaryData('\xaa' * 32) self.privKey2 = SecureBinaryData('\x33' * 32) self.chainstr = SecureBinaryData('\xee' * 32) theIV = SecureBinaryData(hex_to_binary('77' * 16)) self.passphrase = SecureBinaryData('A self.passphrase') self.passphrase2 = SecureBinaryData('A new self.passphrase') #register a callback TheBDM.registerCppNotification(self.armoryDTestCallback) #flag to check on wallet scan status self.walletIsScanned = False #create the wallet self.wallet = PyBtcWallet().createNewWallet(withEncrypt=False, \ plainRootKey=self.privKey, \ chaincode=self.chainstr, \ IV=theIV, \ shortLabel=TEST_WALLET_NAME, \ longLabel=TEST_WALLET_DESCRIPTION, armoryHomeDir = self.armoryHomeDir) self.jsonServer = Armory_Json_Rpc_Server(self.wallet) #register it self.wallet.registerWallet() #wait on scan for 2 min then raise if the scan hasn't finished yet i = 0 while not self.walletIsScanned: time.sleep(0.5) i += 1 if i >= 60 * 4: raise RuntimeError( "Timeout waiting for TheBDM to register the wallet.")
def buildCorruptWallet(self, walletPath): crpWlt = PyBtcWallet() crpWlt.createNewWallet(walletPath, securePassphrase='testing', doRegisterWithBDM=False) #not registering with the BDM, have to fill the wallet address pool manually crpWlt.fillAddressPool(100) #grab the last computed address lastaddr = crpWlt.addrMap[crpWlt.lastComputedChainAddr160] #corrupt the pubkey PubKey = hex_to_binary( '0478d430274f8c5ec1321338151e9f27f4c676a008bdf8638d07c0b6be9ab35c71a1518063243acd4dfe96b66e3f2ec8013c8e072cd09b3834a19f81f659cc3455' ) lastaddr.binPublicKey65 = SecureBinaryData(PubKey) crpWlt.addrMap[crpWlt.lastComputedChainAddr160] = lastaddr crpWlt.fillAddressPool(200) #insert a gap and inconsistent encryption newAddr = PyBtcAddress() newAddr.chaincode = lastaddr.chaincode newAddr.chainIndex = 250 PrivKey = hex_to_binary( 'e3b0c44298fc1c149afbf4c8996fb92427ae41e5978fe51ca495991b7852b855') newAddr.binPrivKey32_Plain = SecureBinaryData(PrivKey) newAddr.binPublicKey65 = CryptoECDSA().ComputePublicKey( \ newAddr.binPrivKey32_Plain) newAddr.addrStr20 = newAddr.binPublicKey65.getHash160() newAddr.isInitialized = True crpWlt.addrMap[newAddr.addrStr20] = newAddr crpWlt.lastComputedChainAddr160 = newAddr.addrStr20 crpWlt.fillAddressPool(250) lastAddr = crpWlt.addrMap[crpWlt.lastComputedChainAddr160] PrivKey = hex_to_binary( 'e3b0c44298fc1c149afbf4c8996fb92427ae41e5978fe51ca495991b00000000') lastAddr.binPrivKey32_Plain = SecureBinaryData(PrivKey) lastAddr.binPublicKey65 = CryptoECDSA().ComputePublicKey( \ lastAddr.binPrivKey32_Plain) lastAddr.keyChanged = True crpWlt.kdfKey = crpWlt.kdf.DeriveKey(SecureBinaryData('testing')) lastAddr.lock(secureKdfOutput=crpWlt.kdfKey) lastAddr.useEncryption = True crpWlt.fillAddressPool(350) #TODO: corrupt a private key #break an address entry at binary level return crpWlt.uniqueIDB58
print ' or: %s --sweep <master wallet file path>' % sys.argv[0] exit(0) # Main execution path # Do not ever access the same wallet file from two different processes at the same time print '\n' raw_input('PLEASE CLOSE ARMORY BEFORE RUNNING THIS SCRIPT! (press enter to continue)\n') if len(promoKitArgList)<3: printHelp() operation = promoKitArgList[1] walletFile = promoKitArgList[2] if not os.path.exists(walletFile): print 'Wallet file was not found: %s' % walletFile masterWallet = PyBtcWallet().readWalletFile(walletFile, False) if operation == '--create': if len(promoKitArgList)<6: printHelp() else: numWallets = int(promoKitArgList[3]) addrsPerWallet = int(promoKitArgList[4]) walletLabel = promoKitArgList[5] walletList = createWalletList(numWallets, walletLabel) masterWallet = importAddrsToMasterWallet( \ masterWallet, walletList, addrsPerWallet, "Master Promo Wallet", ) # Didn't want to fit these into the argument list. Need to edit based on event printWalletList(walletList, "$10 in Bitcoins. ", "November 1st, 2014") elif operation == '--distribute': if len(promoKitArgList)<4: printHelp()
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)
def testWalletRecovery(self): #run recovery on broken wallet recThread = PyBtcWalletRecovery().RecoverWallet(self.corruptWallet, \ 'testing', RECOVERMODE.Full, \ returnError = 'Dict') recThread.join() brkWltResult = recThread.output self.assertTrue(len(brkWltResult['sequenceGaps'])==1, \ "Sequence Gap Undetected") self.assertTrue(len(brkWltResult['forkedPublicKeyChain'])==3, \ "Address Chain Forks Undetected") self.assertTrue(len(brkWltResult['unmatchedPair'])==100, \ "Unmatched Priv/Pub Key Undetected") self.assertTrue(len(brkWltResult['misc'])==50, \ "Wallet Encryption Inconsistency Undetected") self.assertTrue(len(brkWltResult['importedErr'])==50, \ "Unexpected Errors Found") self.assertTrue(brkWltResult['nErrors']==204, \ "Unexpected Errors Found") #check obfuscated keys yield the valid key #grab root key badWlt = PyBtcWallet() badWlt.readWalletFile(self.corruptWallet, False, False) rootAddr = badWlt.addrMap['ROOT'] SecurePassphrase = SecureBinaryData('testing') secureKdfOutput = badWlt.kdf.DeriveKey(SecurePassphrase) #HMAC Q rootAddr.unlock(secureKdfOutput) Q = rootAddr.binPrivKey32_Plain.toBinStr() nonce = 0 while 1: hmacQ = HMAC256(Q, 'LogMult%d' % nonce) if binary_to_int(hmacQ, BIGENDIAN) < SECP256K1_ORDER: hmacQ = SecureBinaryData(hmacQ) break nonce = nonce + 1 #Bad Private Keys import operator badKeys = [ addrObj for addrObj in (sorted(badWlt.addrMap.values(), key=operator.attrgetter('chainIndex'))) ] #run through obdsPrivKey for i in range(0, len(brkWltResult['privMult'])): obfsPKey = SecureBinaryData( hex_to_binary(brkWltResult['privMult'][i])) pKey = CryptoECDSA().ECMultiplyScalars(obfsPKey.toBinStr(), \ hmacQ.toBinStr()) try: badKeys[i + 201].unlock(secureKdfOutput) except: continue self.assertTrue(binary_to_hex(pKey) == \ badKeys[i+201].binPrivKey32_Plain.toHexStr(), \ 'key mult error') #run recovery on recovered wallet recThread = PyBtcWalletRecovery().RecoverWallet( \ 'armory_%s_RECOVERED.wallet' % self.wltID, \ 'testing', RECOVERMODE.Full, \ returnError = 'Dict') recThread.join() rcvWltResult = recThread.output self.assertTrue(len(rcvWltResult['importedErr'])==50, \ "Unexpected Errors Found") self.assertTrue(rcvWltResult['nErrors']==50, \ "Unexpected Errors Found") self.assertTrue(len(rcvWltResult['negativeImports'])==99, \ "Missing neg Imports") # Running tests with "python <module name>" will NOT work for any Armory tests # You must run tests with "python -m unittest <module name>" or run all tests with "python -m unittest discover" # if __name__ == "__main__": # unittest.main()