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()
Example #2
0
   def spawnDB(self, dataDir, dbDir):
      pargs = [self.dbExecutable]

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

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

      blocksdir = os.path.join(self.satoshiHome, 'blocks')
      if not os.path.exists(blocksdir):
         raise self.BadPath, "Invalid blockdata path"

      randBase58 = SecureBinaryData().GenerateRandom(32).toBinStr()
      spawnId = binary_to_base58(randBase58)

      pargs.append('--spawnId="' + spawnId + '"')
      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 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

      launchProcess(pargs, **kargs)

      return spawnId
Example #3
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 #4
0
   def readBitcoinConf(self, makeIfDNE=False):
      LOGINFO('Reading bitcoin.conf file')
      bitconf = os.path.join(self.satoshiRoot, 'bitcoin.conf')
      if not os.path.exists(bitconf):
         if not makeIfDNE:
            raise self.BitcoinDotConfError, 'Could not find bitcoin.conf'
         else:
            LOGINFO('No bitcoin.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 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)


      # 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 #5
0
   def readBitcoinConf(self, makeIfDNE=False):
      LOGINFO('Reading bitcoin.conf file')
      bitconf = os.path.join( self.satoshiHome, 'bitcoin.conf' )
      if not os.path.exists(bitconf):
         if not makeIfDNE:
            raise self.BitcoinDotConfError, 'Could not find bitcoin.conf'
         else:
            LOGINFO('No bitcoin.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 Armory cannot guarantee it ')
            LOGERROR('on XP systems):')
            LOGERROR('    %s', bitconf)
         else:
            LOGINFO('Setting permissions on bitcoin.conf')
            import win32api
            username = win32api.GetUserName()
            LOGINFO('Setting permissions on bitcoin.conf')
            cmd_icacls = ['icacls',bitconf,'/inheritance:r','/grant:r', '%s:F' % username]
            icacls_out = subprocess_check_output(cmd_icacls, shell=True)
            LOGINFO('icacls returned: %s', icacls_out)
      else:
         LOGINFO('Setting permissions on bitcoin.conf')
         os.chmod(bitconf, stat.S_IRUSR | stat.S_IWUSR)


      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 #6
0
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()