Example #1
0
 def isRunningBitcoind(self):
     """
   armoryengine satoshiIsAvailable() only tells us whether there's a
   running bitcoind that is actively responding on its port.  But it
   won't be responding immediately after we've started it (still doing
   startup operations).  If bitcoind was started and still running,
   then poll() will return None.  Any othe poll() return value means
   that the process terminated
   """
     if self.bitcoind == None:
         return False
     # Assume Bitcoind is running if manually started
     if self.bitcoind == False:
         return True
     else:
         if not self.bitcoind.poll() == None:
             LOGDEBUG('Bitcoind is no more')
             if self.btcOut == None:
                 self.btcOut, self.btcErr = self.bitcoind.communicate()
                 LOGWARN('bitcoind exited, bitcoind STDOUT:')
                 for line in self.btcOut.split('\n'):
                     LOGWARN(line)
                 LOGWARN('bitcoind exited, bitcoind STDERR:')
                 for line in self.btcErr.split('\n'):
                     LOGWARN(line)
         return self.bitcoind.poll() == None
Example #2
0
    def callJSON(self, func, *args):
        state = self.getSDMState()
        if not state in ('GroestlcoindReady', 'GroestlcoindSynchronizing'):
            LOGWARN('Called callJSON(%s, %s)', func, str(args))
            LOGWARN('Current SDM state: %s', state)
            raise self.BitcoindError, 'callJSON while %s' % state

        return self.proxy.__getattr__(func)(*args)
Example #3
0
 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
Example #4
0
   def shouldTryBootstrapTorrent(self):
      if DISABLE_TORRENTDL or TheTDM.getTDMState()=='Disabled':
         return False

      # The only torrent we have is for the primary Bitcoin network
      if not MAGIC_BYTES=='\xf9\xbe\xb4\xd9':
         return False
      
         

      if TheTDM.torrentSize:
         bootfile = os.path.join(self.satoshiHome, 'bootstrap.dat')
         if os.path.exists(bootfile):
            if os.path.getsize(bootfile) >= TheTDM.torrentSize/2:
               LOGWARN('Looks like a full bootstrap is already here')
               LOGWARN('Skipping torrent download')
               return False
               

      # If they don't even have a BTC_HOME_DIR, corebtc never been installed
      blockDir = os.path.join(self.satoshiHome, 'blocks')
      if not os.path.exists(self.satoshiHome) or not os.path.exists(blockDir):
         return True
      
      # Get the cumulative size of the blk*.dat files
      blockDirSize = sum([os.path.getsize(os.path.join(blockDir, a)) \
                  for a in os.listdir(blockDir) if a.startswith('blk')])
      sizeStr = bytesToHumanSize(blockDirSize)
      LOGINFO('Total size of files in %s is %s' % (blockDir, sizeStr))

      # If they have only a small portion of the blockchain, do it
      szThresh = 100*MEGABYTE if USE_TESTNET else 6*GIGABYTE
      if blockDirSize < szThresh:
         return True

      # So far we know they have a BTC_HOME_DIR, with more than 6GB in blocks/
      # The only thing that can induce torrent now is if we have a partially-
      # finished bootstrap file bigger than the blocks dir.
      bootFiles = ['','']
      bootFiles[0] = os.path.join(self.satoshiHome, 'bootstrap.dat')
      bootFiles[1] = os.path.join(self.satoshiHome, 'bootstrap.dat.partial')
      for fn in bootFiles:
         if os.path.exists(fn):
            if os.path.getsize(fn) > blockDirSize:
               return True
            
      # Okay, we give up -- just download [the rest] via P2P
      return False
Example #5
0
    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
Example #6
0
    def setupSDM(self, pathToBitcoindExe=None, satoshiHome=None, \
                       extraExeSearch=[], createHomeIfDNE=True):
        LOGDEBUG('Exec setupSDM')
        # If the client is remote, don't do anything.
        if not self.localClient:
            LOGWARN("No SDM since the client is remote")
            return

        self.failedFindExe = False
        self.failedFindHome = False
        # If we are supplied a path, then ignore the extra exe search paths
        if pathToBitcoindExe == None:
            pathToBitcoindExe = self.findBitcoind(extraExeSearch)
            if len(pathToBitcoindExe) == 0:
                LOGDEBUG('Failed to find bitcoind')
                self.failedFindExe = True
            else:
                LOGINFO('Found bitcoind in the following places:')
                for p in pathToBitcoindExe:
                    LOGINFO('   %s', p)
                pathToBitcoindExe = pathToBitcoindExe[0]
                LOGINFO('Using: %s', pathToBitcoindExe)

                if not os.path.exists(pathToBitcoindExe):
                    LOGINFO(
                        'Somehow failed to find exe even after finding it...?')
                    self.failedFindExe = True

        self.executable = pathToBitcoindExe

        # Four possible conditions for already-set satoshi home dir, and input arg
        if satoshiHome is not None:
            self.satoshiHome = satoshiHome
        else:
            if self.satoshiHome is None:
                self.satoshiHome = BTC_HOME_DIR

        # If no new dir is specified, leave satoshi home if it's already set
        # Give it a default BTC_HOME_DIR if not.
        if not os.path.exists(self.satoshiHome):
            if createHomeIfDNE:
                LOGINFO('Making satoshi home dir')
                os.makedirs(self.satoshiHome)
            else:
                LOGINFO('No home dir, makedir not requested')
                self.failedFindHome = True

        if self.failedFindExe: raise self.BitcoindError, 'bitcoind not found'
        if self.failedFindHome: raise self.BitcoindError, 'homedir not found'

        self.disabled = False
        self.proxy = None
        self.bitcoind = None  # this will be a Popen object
        self.isMidQuery = False
        self.last20queries = []

        self.readBitcoinConf()
Example #7
0
    def launchBitcoindAndGuardian(self):

        pargs = [self.executable]

        if USE_TESTNET:
            pargs.append('-testnet')
        elif USE_REGTEST:
            pargs.append('-regtest')

        pargs.append('-datadir=%s' % self.satoshiHome)

        try:
            # Don't want some strange error in this size-check to abort loading
            blocksdir = os.path.join(self.satoshiHome, 'blocks')
            sz = long(0)
            if os.path.exists(blocksdir):
                for fn in os.listdir(blocksdir):
                    fnpath = os.path.join(blocksdir, fn)
                    sz += long(os.path.getsize(fnpath))

            if sz < 5 * GIGABYTE:
                if SystemSpecs.Memory > 9.0:
                    pargs.append('-dbcache=2000')
                elif SystemSpecs.Memory > 5.0:
                    pargs.append('-dbcache=1000')
                elif SystemSpecs.Memory > 3.0:
                    pargs.append('-dbcache=500')
        except:
            LOGEXCEPT('Failed size check of blocks directory')

        kargs = {}
        if OS_WINDOWS:
            import win32process
            kargs['shell'] = True
            kargs['creationflags'] = win32process.CREATE_NO_WINDOW

        # Startup bitcoind and get its process ID (along with our own)
        argStr = " ".join(astr for astr in pargs)
        LOGWARN('Spawning bitcoind with command: ' + argStr)
        self.bitcoind = launchProcess(pargs, **kargs)

        self.btcdpid = self.bitcoind.pid
        self.selfpid = os.getpid()

        LOGINFO('PID of bitcoind: %d', self.btcdpid)
        LOGINFO('PID of armory:   %d', self.selfpid)

        # Startup guardian process -- it will watch Armory's PID
        gpath = self.getGuardianPath()
        pargs = [gpath, str(self.selfpid), str(self.btcdpid)]
        if not OS_WINDOWS:
            pargs.insert(0, 'python')
        launchProcess(pargs, **kargs)
Example #8
0
    def spawnDB(self, dataDir, dbDir):
        pargs = [self.dbExecutable]

        pargs.append('--db-type="' + ARMORY_DB_TYPE + '"')
        pargs.append('--cookie')

        if USE_TESTNET:
            pargs.append('--testnet')
        if USE_REGTEST:
            pargs.append('--regtest')

        haveSatoshiDir = False
        blocksdir = self.satoshiHome
        if os.path.exists(blocksdir):
            haveSatoshiDir = True
        else:
            blocksdir = os.path.join(self.satoshiHome, 'blocks')
            if os.path.exists(blocksdir):
                haveSatoshiDir = True

        if haveSatoshiDir:
            pargs.append('--satoshi-datadir="' + blocksdir + '"')

        pargs.append('--datadir="' + dataDir + '"')
        pargs.append('--dbdir="' + dbDir + '"')

        if CLI_OPTIONS.rebuild:
            pargs.append('--rebuild')
        elif CLI_OPTIONS.rescan:
            pargs.append('--rescan')
        elif CLI_OPTIONS.rescanBalance:
            pargs.append('--rescanSSH')

        if CLI_OPTIONS.clearMempool:
            pargs.append('--clear_mempool')

        if ARMORY_RAM_USAGE != -1:
            pargs.append('--ram-usage=' + ARMORY_RAM_USAGE)
        if ARMORY_THREAD_COUNT != -1:
            pargs.append('--thread-count=' + ARMORY_THREAD_COUNT)

        kargs = {}
        if OS_WINDOWS:
            import win32process
            kargs['shell'] = True
            kargs['creationflags'] = win32process.CREATE_NO_WINDOW

        argStr = " ".join(astr for astr in pargs)
        LOGWARN('Spawning DB with command:' + argStr)

        launchProcess(pargs, **kargs)
Example #9
0
    def processMessage(self, msg):
        # TODO:  when I start expanding this class to be more versatile,
        #        I'll consider chaining/setting callbacks from the calling
        #        application.  For now, it's pretty static.
        #msg.payload.pprint(nIndent=2)
        if msg.cmd == 'inv':
            invobj = msg.payload
            getdataMsg = PyMessage('getdata')
            for inv in invobj.invList:
                if inv[0] == MSG_INV_BLOCK:
                    if self.factory.bdm and (self.factory.bdm.getState()==BDM_SCANNING or \
                          self.factory.bdm.bdv().blockchain().hasHeaderWithHash(inv[1])):
                        continue
                    getdataMsg.payload.invList.append(inv)
                if inv[0] == MSG_INV_TX:
                    if not self.factory.bdm or self.factory.bdm.getState(
                    ) != BDM_BLOCKCHAIN_READY:
                        continue
                    getdataMsg.payload.invList.append(inv)

            # Now send the full request
            if self.factory.bdm and not self.factory.bdm.getState(
            ) == BDM_SCANNING:
                self.sendMessage(getdataMsg)

        if msg.cmd == 'tx':
            pytx = msg.payload.tx
            self.factory.func_newTx(pytx)
        elif msg.cmd == 'inv':
            invList = msg.payload.invList
            self.factory.func_inv(invList)
        elif msg.cmd == 'block':
            pyHeader = msg.payload.header
            pyTxList = msg.payload.txList
            LOGINFO('Received new block.  %s',
                    binary_to_hex(pyHeader.getHash(), BIGENDIAN))
            self.factory.func_newBlock(pyHeader, pyTxList)
        elif msg.cmd == 'alert':
            # store the alert in our map
            id = msg.payload.uniqueID
            if not self.alerts.get(id):
                self.alerts[id] = msg.payload
            LOGWARN("received alert: %s" % msg.payload.statusBar)
Example #10
0
    def setupManualSDM(self):
        LOGDEBUG('Exec setupManualSDM')
        # If the client is remote, don't do anything.
        if not self.localClient:
            LOGWARN("No SDM since the client is remote")
            return

        # Setup bitcoind stuff
        self.bitcoind = False
        self.readBitcoinConf()
        self.readCookieFile()

        # Check bitcoind is actually up. If it is not, remove self.bitcoind
        try:
            self.createProxy()
            self.proxy.getinfo()
        except:
            LOGDEBUG("bitcoind rpc is not actually availalbe")
            self.bitcoind = None
            self.proxy = None
Example #11
0
    def setupSDM(self, pathToBitcoindExe=None, satoshiHome=None, \
                       extraExeSearch=[], createHomeIfDNE=True):
        LOGDEBUG('Exec setupSDM')
        # If the client is remote, don't do anything.
        if not self.localDB:
            LOGWARN("No SDM since the client is remote")
            return

        self.failedFindExe = False

        # If we are supplied a path, then ignore the extra exe search paths
        if pathToBitcoindExe == None:
            pathToBitcoindExe = self.findBitcoind(extraExeSearch)
            if len(pathToBitcoindExe) == 0:
                LOGDEBUG('Failed to find bitcoind')
                self.failedFindExe = True
            else:
                LOGINFO('Found bitcoind in the following places:')
                for p in pathToBitcoindExe:
                    LOGINFO('   %s', p)
                pathToBitcoindExe = pathToBitcoindExe[0]
                LOGINFO('Using: %s', pathToBitcoindExe)

                if not os.path.exists(pathToBitcoindExe):
                    LOGINFO(
                        'Somehow failed to find exe even after finding it...?')
                    self.failedFindExe = True

        self.executable = pathToBitcoindExe

        # Four possible conditions for already-set satoshi home dir, and input arg
        if satoshiHome is not None:
            self.satoshiHome = satoshiHome
        else:
            if self.satoshiHome is None:
                self.satoshiHome = BTC_HOME_DIR

        if self.failedFindExe: raise self.BitcoindError, 'bitcoind not found'

        self.disabled = False
        self.bitcoind = None  # this will be a Popen object
Example #12
0
    def readBitcoinConf(self, makeIfDNE=False):
        LOGINFO('Reading groestlcoin.conf file')
        bitconf = os.path.join(self.satoshiRoot, 'groestlcoin.conf')
        if not os.path.exists(bitconf):
            if not makeIfDNE:
                raise self.BitcoinDotConfError, 'Could not find groestlcoin.conf'
            else:
                LOGINFO('No groestlcoin.conf available.  Creating it...')
                touchFile(bitconf)

        # Guarantee that bitcoin.conf file has very strict permissions
        if OS_WINDOWS:
            if OS_VARIANT[0].lower() == 'xp':
                LOGERROR('Cannot set permissions correctly in XP!')
                LOGERROR('Please confirm permissions on the following file ')
                LOGERROR('are set to exclusive access only for your user ')
                LOGERROR(
                    '(it usually is, but Groestlcoin Armory cannot guarantee it '
                )
                LOGERROR('on XP systems):')
                LOGERROR('    %s', bitconf)
            else:
                LOGINFO('Setting permissions on groestlcoin.conf')
                import ctypes
                username_u16 = ctypes.create_unicode_buffer(u'\0', 512)
                str_length = ctypes.c_int(512)
                ctypes.windll.Advapi32.GetUserNameW(ctypes.byref(username_u16),
                                                    ctypes.byref(str_length))

                CLI_OPTIONS.disableConfPermis = True  #!!!GRS
                if not CLI_OPTIONS.disableConfPermis:
                    import win32process
                    LOGINFO('Setting permissions on groestlcoin.conf')
                    cmd_icacls = [
                        u'icacls', bitconf, u'/inheritance:r', u'/grant:r',
                        u'%s:F' % username_u16.value
                    ]
                    kargs = {}
                    kargs['shell'] = True
                    kargs['creationflags'] = win32process.CREATE_NO_WINDOW
                    icacls_out = subprocess_check_output(cmd_icacls, **kargs)
                    LOGINFO('icacls returned: %s', icacls_out)
                else:
                    LOGWARN(
                        'Skipped setting permissions on groestlcoin.conf file')

        else:
            if not CLI_OPTIONS.disableConfPermis:
                LOGINFO('Setting permissions on groestlcoin.conf')
                os.chmod(bitconf, stat.S_IRUSR | stat.S_IWUSR)
            else:
                LOGWARN('Skipped setting permissions on groestlcoin.conf file')

        with open(bitconf, 'r') as f:
            # Find the last character of the each line:  either a newline or '#'
            endchr = lambda line: line.find('#') if line.find(
                '#') > 1 else len(line)

            # Reduce each line to a list of key,value pairs separated with '='
            allconf = [l[:endchr(l)].strip().split('=') for l in f.readlines()]

            # Need to convert to (x[0],x[1:]) in case the password has '=' in it
            allconfPairs = [[x[0], '='.join(x[1:])] for x in allconf
                            if len(x) > 1]

            # Convert the list of pairs to a dictionary
            self.bitconf = dict(allconfPairs)

        # Look for rpcport, use default if not there
        self.bitconf['rpcport'] = int(
            self.bitconf.get('rpcport', BITCOIN_RPC_PORT))

        # We must have a username and password.  If not, append to file
        if not self.bitconf.has_key('rpcuser'):
            LOGDEBUG('No rpcuser: creating one')
            with open(bitconf, 'a') as f:
                f.write('\n')
                f.write('rpcuser=generated_by_armory\n')
                self.bitconf['rpcuser'] = '******'

        if not self.bitconf.has_key('rpcpassword'):
            LOGDEBUG('No rpcpassword: creating one')
            with open(bitconf, 'a') as f:
                randBase58 = SecureBinaryData().GenerateRandom(32).toBinStr()
                randBase58 = binary_to_base58(randBase58)
                f.write('\n')
                f.write('rpcpassword=%s' % randBase58)
                self.bitconf['rpcpassword'] = randBase58

        if not isASCII(self.bitconf['rpcuser']):
            LOGERROR('Non-ASCII character in bitcoin.conf (rpcuser)!')
        if not isASCII(self.bitconf['rpcpassword']):
            LOGERROR('Non-ASCII character in bitcoin.conf (rpcpassword)!')

        self.bitconf['host'] = '127.0.0.1'
Example #13
0
    def tryToSetupTorrentDL(self, torrentPath):
        if self.torrentDisabled:
            LOGWARN('Tried to setup torrent download mgr but we are disabled')
            return False

        if not torrentPath or not os.path.exists(torrentPath):
            self.useTorrentFinalAnswer = False
            return False

        bootfile = os.path.join(self.satoshiHome, 'bootstrap.dat')
        bootfilePart = bootfile + '.partial'
        bootfileOld = bootfile + '.old'

        # cleartorrent.flag means we should remove any pre-existing files
        delTorrentFlag = os.path.join(ARMORY_HOME_DIR, 'cleartorrent.flag')
        if os.path.exists(delTorrentFlag):
            LOGWARN('Flag found to delete any pre-existing torrent files')
            if os.path.exists(bootfile): os.remove(bootfile)
            if os.path.exists(bootfilePart): os.remove(bootfilePart)
            if os.path.exists(bootfileOld): os.remove(bootfileOld)
            if os.path.exists(delTorrentFlag): os.remove(delTorrentFlag)

        TheTDM.setupTorrent(torrentPath, bootfile)
        if not TheTDM.getTDMState() == 'ReadyToStart':
            LOGERROR('Unknown error trying to start torrent manager')
            self.useTorrentFinalAnswer = False
            return False

        # We will tell the TDM to write status updates to the log file, and only
        # every 90 seconds.  After it finishes (or fails), simply launch groestlcoind
        # as we would've done without the torrent
        #####
        def torrentLogToFile(dpflag=Event(),
                             fractionDone=None,
                             timeEst=None,
                             downRate=None,
                             upRate=None,
                             activity=None,
                             statistics=None,
                             **kws):
            statStr = ''
            if fractionDone:
                statStr += '   Done: %0.1f%%  ' % (fractionDone * 100)
            if downRate:
                statStr += ' / DLRate: %0.1f/sec' % (downRate / 1024.)
            if timeEst:
                statStr += ' / TLeft: %s' % secondsToHumanTime(timeEst)
            if statistics:
                statStr += ' / Seeds: %d' % (statistics.numSeeds)
                statStr += ' / Peers: %d' % (statistics.numPeers)

            if len(statStr) == 0:
                statStr = 'No torrent info available'

            LOGINFO('Torrent: %s' % statStr)

        #####
        def torrentFinished():
            bootsz = '<Unknown>'
            if os.path.exists(bootfile):
                bootsz = bytesToHumanSize(os.path.getsize(bootfile))

            LOGINFO('Torrent finished; size of %s is %s', torrentPath, bootsz)
            LOGINFO('Remove the core btc databases before doing bootstrap')
            deleteBitcoindDBs()
            self.launchBitcoindAndGuardian()

        #####
        def warnUserHashFail():
            from PyQt4.QtGui import QMessageBox
            QMessageBox.warning(
                self, tr('Hash Failure'),
                tr("""The torrent download 
            is currently encountering too many packet hash failures to allow it to 
            progress properly. As a result, the torrent engine has been halted. You 
            should report this incident to the Groestlcoin Armory team and turn off this feature 
            until further notice."""), QMessageBox.Ok)

        #####
        def torrentFailed(errMsg=''):
            # Not sure there's actually anything we need to do here...
            if errMsg == 'hashFail':
                warnUserHashFail()

            bootsz = '<Unknown>'
            if os.path.exists(bootfile):
                bootsz = bytesToHumanSize(os.path.getsize(bootfile))

            LOGERROR('Torrent failed; size of %s is %s', torrentPath, bootsz)
            self.launchBitcoindAndGuardian()

        TheTDM.setSecondsBetweenUpdates(90)
        TheTDM.setCallback('displayFunc', torrentLogToFile)
        TheTDM.setCallback('finishedFunc', torrentFinished)
        TheTDM.setCallback('failedFunc', torrentFailed)

        LOGINFO('Bootstrap file is %s' % bytesToHumanSize(TheTDM.torrentSize))

        self.useTorrentFinalAnswer = True
        self.useTorrentFile = torrentPath
        return True
Example #14
0
   def tryToSetupTorrentDL(self, torrentPath):
      if self.torrentDisabled:
         LOGWARN('Tried to setup torrent download mgr but we are disabled')
         return False
      
      if not torrentPath or not os.path.exists(torrentPath):
         self.useTorrentFinalAnswer = False
         return False

      bootfile = os.path.join(self.satoshiHome, 'bootstrap.dat')
      TheTDM.setupTorrent(torrentPath, bootfile)
      if not TheTDM.getTDMState()=='ReadyToStart':
         LOGERROR('Unknown error trying to start torrent manager')
         self.useTorrentFinalAnswer = False
         return False


      # We will tell the TDM to write status updates to the log file, and only
      # every 90 seconds.  After it finishes (or fails), simply launch bitcoind
      # as we would've done without the torrent
      #####
      def torrentLogToFile(dpflag=Event(), fractionDone=None, timeEst=None,
                           downRate=None, upRate=None, activity=None,
                           statistics=None, **kws):
         statStr = ''
         if fractionDone:
            statStr += '   Done: %0.1f%%  ' % (fractionDone*100)
         if downRate:
            statStr += ' / DLRate: %0.1f/sec' % (downRate/1024.)
         if timeEst:
            statStr += ' / TLeft: %s' % secondsToHumanTime(timeEst)
         if statistics:
            statStr += ' / Seeds: %d' % (statistics.numSeeds)
            statStr += ' / Peers: %d' % (statistics.numPeers)

         if len(statStr)==0:
            statStr = 'No torrent info available'

         LOGINFO('Torrent: %s' % statStr)

      #####
      def torrentFinished():
         bootsz = '<Unknown>'
         if os.path.exists(bootfile):
            bootsz = bytesToHumanSize(os.path.getsize(bootfile))

         LOGINFO('Torrent finished; size of %s is %s', torrentPath, bootsz)
         LOGINFO('Remove the core btc databases before doing bootstrap')
         deleteBitcoindDBs()
         self.launchBitcoindAndGuardian()

      #####
      def torrentFailed():
         # Not sure there's actually anything we need to do here...
         bootsz = '<Unknown>'
         if os.path.exists(bootfile):
            bootsz = bytesToHumanSize(os.path.getsize(bootfile))

         LOGERROR('Torrent failed; size of %s is %s', torrentPath, bootsz)
         self.launchBitcoindAndGuardian()
 
      TheTDM.setSecondsBetweenUpdates(90)
      TheTDM.setCallback('displayFunc',  torrentLogToFile)
      TheTDM.setCallback('finishedFunc', torrentFinished)
      TheTDM.setCallback('failedFunc',   torrentFailed)

      LOGINFO('Bootstrap file is %s' % bytesToHumanSize(TheTDM.torrentSize))
         
      self.useTorrentFinalAnswer = True
      self.useTorrentFile = torrentPath
      return True
Example #15
0
    def readBitcoinConf(self):
        LOGINFO('Reading bitcoin.conf file')
        bitconf = os.path.join(self.satoshiRoot, 'bitcoin.conf')
        if os.path.exists(bitconf):
            # Guarantee that bitcoin.conf file has very strict permissions
            if OS_WINDOWS:
                if OS_VARIANT[0].lower() == 'xp':
                    LOGERROR('Cannot set permissions correctly in XP!')
                    LOGERROR(
                        'Please confirm permissions on the following file ')
                    LOGERROR('are set to exclusive access only for your user ')
                    LOGERROR('(it usually is, but Armory cannot guarantee it ')
                    LOGERROR('on XP systems):')
                    LOGERROR('    %s', bitconf)
                else:
                    LOGINFO('Setting permissions on bitcoin.conf')
                    import ctypes
                    username_u16 = ctypes.create_unicode_buffer(u'\0', 512)
                    str_length = ctypes.c_int(512)
                    ctypes.windll.Advapi32.GetUserNameW(
                        ctypes.byref(username_u16), ctypes.byref(str_length))

                    if not CLI_OPTIONS.disableConfPermis:
                        import win32process
                        LOGINFO('Setting permissions on bitcoin.conf')
                        cmd_icacls = [
                            u'icacls', bitconf, u'/inheritance:r', u'/grant:r',
                            u'%s:F' % username_u16.value
                        ]
                        kargs = {}
                        kargs['shell'] = True
                        kargs['creationflags'] = win32process.CREATE_NO_WINDOW
                        icacls_out = subprocess_check_output(
                            cmd_icacls, **kargs)
                        LOGINFO('icacls returned: %s', icacls_out)
                    else:
                        LOGWARN(
                            'Skipped setting permissions on bitcoin.conf file')

            else:
                if not CLI_OPTIONS.disableConfPermis:
                    LOGINFO('Setting permissions on bitcoin.conf')
                    os.chmod(bitconf, stat.S_IRUSR | stat.S_IWUSR)
                else:
                    LOGWARN('Skipped setting permissions on bitcoin.conf file')

            with open(bitconf, 'r') as f:
                # Find the last character of the each line:  either a newline or '#'
                endchr = lambda line: line.find('#') if line.find(
                    '#') > 1 else len(line)

                # Reduce each line to a list of key,value pairs separated with '='
                allconf = [
                    l[:endchr(l)].strip().split('=') for l in f.readlines()
                ]

                # Need to convert to (x[0],x[1:]) in case the password has '=' in it
                allconfPairs = [[x[0], '='.join(x[1:])] for x in allconf
                                if len(x) > 1]

                # Convert the list of pairs to a dictionary
                self.bitconf = dict(allconfPairs)

            # If there is no password, use cookie auth
            if not self.bitconf.has_key('rpcpassword'):
                LOGDEBUG('No rpcpassword: Using cookie Auth')
                self.readCookieFile()

        # defaults
        self.bitconf['host'] = '127.0.0.1'
        self.bitconf['rpcport'] = BITCOIN_RPC_PORT