def callSplitSecret(self, secretHex, M, N, nbytes=1): secret = hex_to_binary(secretHex) print '\nSplitting secret into %d-of-%d: secret=%s' % (M,N,secretHex) tstart = RightNow() out = SplitSecret(secret, M, N) tsplit = RightNow() - tstart print 'Fragments:' for i in range(len(out)): x = binary_to_hex(out[i][0]) y = binary_to_hex(out[i][1]) print ' Fragment %d: [%s, %s]' % (i+1,x,y) trecon = 0 print 'Reconstructing secret from various subsets of fragments...' for i in range(10): shuffle(out) tstart = RightNow() reconstruct = ReconstructSecret(out, M, nbytes) trecon += RightNow() - tstart print ' The reconstructed secret is:', binary_to_hex(reconstruct) self.assertEqual(binary_to_hex(reconstruct), secretHex) print 'Splitting secret took: %0.5f sec' % tsplit print 'Reconstructing takes: %0.5f sec' % (trecon/10) # Running tests with "python <module name>" will NOT work for any Armory tests # You must run tests with "python -m unittest <module name>" or run all tests with "python -m unittest discover" # if __name__ == "__main__": # unittest.main()
def injectHeartbeatAlwaysFunc(self): # Check the price every 60 seconds, update widgets self.updateLastTimeStr() if RightNow() < self.lastPriceFetch+60: return self.lastPriceFetch = RightNow() self.checkUpdatePrice()
def startTimer(self, timerName): if not self.timerMap.has_key(timerName): self.timerMap[timerName] = [0, 0, 0, False] timerEntry = self.timerMap[timerName] timerEntry[1] += 1 timerEntry[2] = RightNow() timerEntry[3] = True
def connectionMade(self): """ Construct the initial version message and send it right away. Everything else will be handled by dataReceived. """ LOGINFO('Connection initiated. Start handshake') addrTo = str_to_quad(self.transport.getPeer().host) portTo = self.transport.getPeer().port addrFrom = str_to_quad(self.transport.getHost().host) portFrom = self.transport.getHost().port self.peer = [addrTo, portTo] services = '0' * 16 msgVersion = PayloadVersion() msgVersion.version = 40000 # TODO: this is what my Satoshi client says msgVersion.services = services msgVersion.time = long(RightNow()) msgVersion.addrRecv = PyNetAddress(0, services, addrTo, portTo) msgVersion.addrFrom = PyNetAddress(0, services, addrFrom, portFrom) msgVersion.nonce = random.randint(2**60, 2**64 - 1) msgVersion.subver = 'Armory:%s' % getVersionString(BTCARMORY_VERSION) msgVersion.height0 = -1 self.sendMessage(msgVersion) self.factory.func_madeConnect()
def getSDMState(self): """ As for why I'm doing this: it turns out that between "initializing" and "synchronizing", groestlcoind temporarily stops responding entirely, which causes "not-available" to be the state. I need to smooth that out because it wreaks havoc on the GUI which will switch to showing a nasty error. """ state = self.getSDMStateLogic() self.circBufferState.append(state) self.circBufferTime.append(RightNow()) if len(self.circBufferTime)>2 and \ (self.circBufferTime[-1] - self.circBufferTime[1]) > 5: # Only remove the first element if we have at least 5s history self.circBufferState = self.circBufferState[1:] self.circBufferTime = self.circBufferTime[1:] # Here's where we modify the output to smooth out the gap between # "initializing" and "synchronizing" (which is a couple seconds # of "not available"). "NotAvail" keeps getting added to the # buffer, but if it was "initializing" in the last 5 seconds, # we will keep "initializing" if state == 'GroestlcoindNotAvailable': if 'GroestlcoindInitializing' in self.circBufferState: LOGWARN( 'Overriding not-available state. This should happen 0-5 times' ) return 'GroestlcoindInitializing' return state
def getSDMStateLogic(self): if self.disabled: return 'BitcoindMgmtDisabled' if self.failedFindExe: return 'BitcoindExeMissing' if self.failedFindHome: return 'BitcoindHomeMissing' latestInfo = self.getTopBlockInfo() if self.bitcoind==None and latestInfo['error']=='Uninitialized': return 'BitcoindNeverStarted' if not self.isRunningBitcoind(): # Not running at all: either never started, or process terminated if not self.btcErr==None and len(self.btcErr)>0: errstr = self.btcErr.replace(',',' ').replace('.',' ').replace('!',' ') errPcs = set([a.lower() for a in errstr.split()]) runPcs = set(['cannot','obtain','lock','already','running']) dbePcs = set(['database', 'recover','backup','except','wallet','dat']) if len(errPcs.intersection(runPcs))>=(len(runPcs)-1): return 'BitcoindAlreadyRunning' elif len(errPcs.intersection(dbePcs))>=(len(dbePcs)-1): return 'BitcoindDatabaseEnvError' else: return 'BitcoindUnknownCrash' else: return 'BitcoindNotAvailable' elif not self.bitcoindIsResponsive(): # Running but not responsive... must still be initializing return 'BitcoindInitializing' else: # If it's responsive, get the top block and check # TODO: These conditionals are based on experimental results. May # not be accurate what the specific errors mean... if latestInfo['error']=='ValueError': return 'BitcoindWrongPassword' elif latestInfo['error']=='JsonRpcException': return 'BitcoindInitializing' elif latestInfo['error']=='SocketError': return 'BitcoindNotAvailable' if 'BitcoindReady' in self.circBufferState: # If ready, always ready return 'BitcoindReady' # If we get here, bitcoind is gave us a response. secSinceLastBlk = RightNow() - latestInfo['toptime'] blkspersec = latestInfo['blkspersec'] #print 'Blocks per 10 sec:', ('UNKNOWN' if blkspersec==-1 else blkspersec*10) if secSinceLastBlk > 4*HOUR or blkspersec==-1: return 'BitcoindSynchronizing' else: if blkspersec*20 > 2 and not 'BitcoindReady' in self.circBufferState: return 'BitcoindSynchronizing' else: return 'BitcoindReady'
def readTimer(self, timerName): if not self.timerMap.has_key(timerName): LOGERROR('Requested read timer that does not exist! (%s)' % timerName) return timerEntry = self.timerMap[timerName] return timerEntry[0] + (RightNow() - timerEntry[2])
def __backgroundRequestTopBlock(self): self.createProxy() self.isMidQuery = True try: numblks = self.proxy.getinfo()['blocks'] blkhash = self.proxy.getblockhash(numblks) toptime = self.proxy.getblock(blkhash)['time'] #LOGDEBUG('RPC Call: numBlks=%d, toptime=%d', numblks, toptime) # Only overwrite once all outputs are retrieved self.lastTopBlockInfo['numblks'] = numblks self.lastTopBlockInfo['tophash'] = blkhash self.lastTopBlockInfo['toptime'] = toptime self.lastTopBlockInfo['error'] = None # Holds error info if len(self.last20queries)==0 or \ (RightNow()-self.last20queries[-1][0]) > 0.99: # This conditional guarantees last 20 queries spans at least 20s self.last20queries.append([RightNow(), numblks]) self.last20queries = self.last20queries[-20:] t0, b0 = self.last20queries[0] t1, b1 = self.last20queries[-1] # Need at least 10s of data to give meaning answer if (t1 - t0) < 10: self.lastTopBlockInfo['blkspersec'] = -1 else: self.lastTopBlockInfo['blkspersec'] = float( b1 - b0) / float(t1 - t0) except ValueError: # I believe this happens when you used the wrong password LOGEXCEPT('ValueError in bkgd req top blk') self.lastTopBlockInfo['error'] = 'ValueError' except authproxy.JSONRPCException: # This seems to happen when groestlcoind is overwhelmed... not quite ready LOGDEBUG('generic jsonrpc exception') self.lastTopBlockInfo['error'] = 'JsonRpcException' except socket.error: # Connection isn't available... is groestlcoind not running anymore? LOGDEBUG('generic socket error') self.lastTopBlockInfo['error'] = 'SocketError' except: LOGEXCEPT('generic error') self.lastTopBlockInfo['error'] = 'UnknownError' raise finally: self.isMidQuery = False
def updateLastTimeStr(self): secs = RightNow() - self.lastPriceFetch tstr = 'Less than 1 min' if secs > 60: tstr = secondsToHumanTime(secs) self.lblLastTime.setText(tr("""<font color="%s">Last updated: %s ago</font>""") % (htmlColor('DisableFG'), tstr))
def callSplitSecret(self, secretHex, M, N, nbytes=1): secret = hex_to_binary(secretHex) print '\nSplitting secret into %d-of-%d: secret=%s' % (M,N,secretHex) tstart = RightNow() out = SplitSecret(secret, M, N) tsplit = RightNow() - tstart print 'Fragments:' for i in range(len(out)): x = binary_to_hex(out[i][0]) y = binary_to_hex(out[i][1]) print ' Fragment %d: [%s, %s]' % (i+1,x,y) trecon = 0 print 'Reconstructing secret from various subsets of fragments...' for i in range(10): shuffle(out) tstart = RightNow() reconstruct = ReconstructSecret(out, M, nbytes) trecon += RightNow() - tstart print ' The reconstructed secret is:', binary_to_hex(reconstruct) self.assertEqual(binary_to_hex(reconstruct), secretHex) print 'Splitting secret took: %0.5f sec' % tsplit print 'Reconstructing takes: %0.5f sec' % (trecon/10)
def stopTimer(self, timerName): if not self.timerMap.has_key(timerName): LOGWARN('Requested stop timer that does not exist! (%s)' % timerName) return if not self.timerMap[timerName][3]: LOGWARN('Requested stop timer that is not running! (%s)' % timerName) return timerEntry = self.timerMap[timerName] timerEntry[0] += RightNow() - timerEntry[2] timerEntry[2] = 0 timerEntry[3] = False
def searchForPassword(self, segList, segOrdList=[]): if len(segOrdList) == 0: segOrdList = [range(len(segList))] passwordCount = self.countPasswords(segList, segOrdList) startTime = RightNow() found = False result = None for i, p in enumerate(self.passwordGenerator(segList, segOrdList)): isValid = self.wallet.verifyPassphrase(SecureBinaryData(p)) if isValid: # If the passphrase was wrong, it would error out, and not continue print 'Passphrase found!' print '' print '\t', p print '' print 'Thanks for using this script. If you recovered coins because of it, ' print 'please consider donating :) ' print ' 1ArmoryXcfq7TnCSuZa9fQjRYwJ4bkRKfv' print '' found = True open('FOUND_PASSWORD.txt', 'w').write(p) result = p break elif i % 100 == 0: telapsed = (RightNow() - startTime) / 3600. print('%d/%d passphrases tested... (%0.1f hours so far)' % (i, passwordCount, telapsed)).rjust(40) print p, if i % 10 == 9: print if not found: print '' print 'Script finished!' print 'Sorry, none of the provided passphrases were correct :(' print '' return result
def testTouch(self): testAddr = PyBtcAddress().createFromPlainKeyData(PRIVATE_KEY, ADDRESS_20, publicKey65=PUBLIC_KEY) theIV = SecureBinaryData(hex_to_binary(INIT_VECTOR)) testAddr.enableKeyEncryption(theIV) rightNow = RightNow() testAddr.touch(rightNow) self.assertEqual(testAddr.timeRange[0], long(rightNow)) self.assertEqual(testAddr.timeRange[1], long(rightNow)) testAddr.touch(0) self.assertEqual(testAddr.timeRange[0], long(0)) self.assertEqual(testAddr.timeRange[1], long(rightNow)) testAddr.touch(blkNum=TEST_BLOCK_NUM) self.assertEqual(testAddr.blkRange[0], TEST_BLOCK_NUM) self.assertEqual(testAddr.blkRange[1], TOP_TIAB_BLOCK) testAddr.touch(blkNum=0) self.assertEqual(testAddr.blkRange[0], 0) self.assertEqual(testAddr.blkRange[1], TOP_TIAB_BLOCK) # Cover the case where the blkRange[0] starts at 0 testAddr.touch(blkNum=TEST_BLOCK_NUM) self.assertEqual(testAddr.blkRange[0], TEST_BLOCK_NUM) self.assertEqual(testAddr.blkRange[1], TOP_TIAB_BLOCK)
def checkUpdatePrice(self): urlBase = 'http://coinbase.com/api/v1/prices/' urlSell = urlBase + 'sell' urlBuy = urlBase + 'buy' try: self.lastSellStr = self.fetchFormattedPrice(urlSell) self.lastBuyStr = self.fetchFormattedPrice(urlBuy) self.lblSellPrice.setText('<b><font color="%s">$%s</font> / BTC</b>' % \ (htmlColor('TextBlue'), self.lastSellStr)) self.lblBuyPrice.setText( '<b><font color="%s">$%s</font> / BTC</b>' % \ (htmlColor('TextBlue'), self.lastBuyStr)) self.lastPriceFetch = RightNow() self.updateLastTimeStr() self.updateWalletTable() self.updateCalcUSD(self.edtEnterBTC.text()) except: #LOGEXCEPT('Failed to fetch price data from %s' % urlBase) pass
print '\n\nRegistering the wallet with the BlockDataManager & loading...' cppWallet.registerWallet() ################################################################################ if run_LoadBlockchain_Async: """ By setting blocking=False, most calls to TheBDM will return immediately, after queuing the BDM to execute the operation in the background. You have to check back later to see when it's done. However, even when blocking is false, any functions that return data must block so the data can be returned. If you are in asynchronous mode, and don't want to ever wait for anything, always check TheBDM.getState()==BDM_BLOCKCHAIN_READY before requesting data that will force blocking. """ start = RightNow() TheBDM.setBlocking(False) TheBDM.setOnlineMode(True) sleep(2) print 'Waiting for blockchain loading to finish', while not TheBDM.getState() == BDM_BLOCKCHAIN_READY: print '.', sys.stdout.flush() sleep(2) print 'Loading blockchain took %0.1f sec' % (RightNow() - start) topBlock = TheBDM.getTopBlockHeight() print '\n\nCurrent Top Block is:', topBlock TheBDM.blockchain().top().pprint() ################################################################################
def addTxToMemoryPool(self, pytx): if self.bdm and not self.bdm.getBDMState() == 'Offline': self.bdm.addNewZeroConfTx(pytx.serialize(), long(RightNow()), True)
def createNewWallet(wlt, rootEntry, newWalletFilePath, withEncrypt, kdfParam=None): """ This method will create a new wallet, using as much customizability as you want. You can enable encryption, and set the target params of the key-derivation function (compute-time and max memory usage). The KDF parameters will be experimentally determined to be as hard as possible for your computer within the specified time target (default, 0.25s). It will aim for maximizing memory usage and using only 1 or 2 iterations of it, but this can be changed by scaling down the kdfMaxMem parameter (default 32 MB). If you use encryption, don't forget to supply a 32-byte passphrase, created via SecureBinaryData(pythonStr). This method will apply the passphrase so that the wallet is "born" encrypted. The field plainRootKey could be used to recover a written backup of a wallet, since all addresses are deterministically computed from the root address. This obviously won't reocver any imported keys, but does mean that you can recover your ENTIRE WALLET from only those 32 plaintext bytes AND the 32-byte chaincode. We skip the atomic file operations since we don't even have a wallet file yet to safely update. DO NOT CALL THIS FROM BDM METHOD. IT MAY DEADLOCK. """ # Create the root address object rootAddr = rootEntry # Update wallet object with the new data # NEW IN WALLET VERSION 1.35: unique ID is now based on # the first chained address: this guarantees that the unique ID # is based not only on the private key, BUT ALSO THE CHAIN CODE wlt.useEncryption = withEncrypt wlt.addrMap['ROOT'] = rootAddr wlt.uniqueIDBin = (ADDRBYTE + str(random.getrandbits(48))[:5])[::-1] wlt.uniqueIDB58 = binary_to_base58(wlt.uniqueIDBin) wlt.labelName = '' wlt.labelDescr = '' wlt.lastComputedChainAddr160 = rootAddr wlt.lastComputedChainIndex = 0 wlt.highestUsedChainIndex = 0 wlt.wltCreateDate = long(RightNow()) wlt.kdf = kdfParam # We don't have to worry about atomic file operations when # creating the wallet: so we just do it naively here. wlt.walletPath = newWalletFilePath newfile = open(newWalletFilePath, 'wb') fileData = BinaryPacker() # packHeader method writes KDF params and root address headerBytes = wlt.packHeader(fileData) newfile.write(fileData.getBinaryString()) newfile.close()
def addTxToMemoryPool(self, pytx): if self.bdm and not self.bdm.getState() == BDM_OFFLINE: self.bdm.addNewZeroConfTx(pytx.serialize(), long(RightNow()), True)