Exemplo n.º 1
0
   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.  
      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)
      if TheBDM.getBDMState() in ('Uninitialized', 'Offline'):
         TheBDM.registerWallet(walletFromDisk, isFresh=True, wait=False)
      else:
         self.main.newWalletList.append([walletFromDisk, True])
Exemplo n.º 2
0
    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)
Exemplo n.º 3
0
    def stopBitcoind(self):
        LOGINFO('Called stopBitcoind')
        if self.bitcoind == False:
            self.bitcoind = None
            return
        try:
            if not self.isRunningBitcoind():
                LOGINFO('...but bitcoind is not running, to be able to stop')
                return

            from armoryengine.BDM import TheBDM
            cookie = TheBDM.getCookie()
            TheBDM.bdv().shutdownNode(cookie)

            #poll the pid until it's gone, for as long as 2 minutes
            total = 0
            while self.bitcoind.poll() == None:
                time.sleep(0.1)
                total += 1

                if total > 1200:
                    LOGERROR(
                        "bitcoind failed to shutdown in less than 2 minutes."
                        " Terminating.")
                    return

            self.bitcoind = None
        except Exception as e:
            LOGERROR(e)
            return
Exemplo n.º 4
0
    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])
Exemplo n.º 5
0
   def stopBitcoind(self):
      LOGINFO('Called stopBitcoind')
      if self.bitcoind == False:
         self.bitcoind = None
         return
      try:
         if not self.isRunningBitcoind():
            LOGINFO('...but bitcoind is not running, to be able to stop')
            return
         
         from armoryengine.BDM import TheBDM
         cookie = TheBDM.getCookie()
         TheBDM.bdv().shutdownNode(cookie);

         #poll the pid until it's gone, for as long as 2 minutes
         total = 0
         while self.bitcoind.poll()==None:
            time.sleep(0.1)
            total += 1

            if total > 1200:
               LOGERROR("bitcoind failed to shutdown in less than 2 minutes."
                      " Terminating.")
               return

         self.bitcoind = None
      except Exception as e:
         LOGERROR(e)
         return
 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' % TEST_WALLET_ID)
    self.wlt = PyBtcWallet().readWalletFile(self.fileA, doScanNow=True)
    self.jsonServer = Armory_Json_Rpc_Server(self.wlt)
    TheBDM.registerWallet(self.wlt)
Exemplo n.º 7
0
 def setUpClass(self):
    # This is not a UI so no need to worry about the main thread being blocked.
    # Any UI that uses this Daemon can put the call to the Daemon on it's own thread.
    TheBDM.setBlocking(True)
    TheBDM.setOnlineMode(True)
    while not TheBDM.getBDMState()=='BlockchainReady':
       time.sleep(2)
Exemplo n.º 8
0
 def setUpClass(self):
     # This is not a UI so no need to worry about the main thread being blocked.
     # Any UI that uses this Daemon can put the call to the Daemon on it's own thread.
     TheBDM.setBlocking(True)
     TheBDM.setOnlineMode(True)
     while not TheBDM.getBDMState() == 'BlockchainReady':
         time.sleep(2)
Exemplo n.º 9
0
   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')

      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)
      TheBDM.registerWallet(self.wallet)
Exemplo n.º 10
0
def distributeBtc(masterWallet, amount, sendingAddrList):
   pytx = None
   setupTheBDM()
   try:
      recipValuePairs = []
      utxoList = []
      for sendingAddr in sendingAddrList:
         addr160 = sendingAddr.getAddr160()
         # Make sure the sending addresses are in the masterWallet
         if not masterWallet.hasAddr(addr160):
            raise WalletAddressError, 'Address is not in wallet! [%s]' % sendingAddr.getAddrStr()
         utxoList.extend(masterWallet.getAddrTxOutList(addr160))
   

      for importedAddr in masterWallet.getLinearAddrList():
         if importedAddr.chainIndex<0:
            recipValuePairs.append((importedAddr.getAddr160(),amount))
      totalSpend = len(recipValuePairs)*amount
      fee = calcMinSuggestedFees(utxoList, totalSpend, MIN_RELAY_TX_FEE, len(recipValuePairs))
      # Get the necessary utxo list
      selectedUtxoList = PySelectCoins(utxoList, totalSpend, fee)
      # get total value   
      totalAvailable = sum([u.getValue() for u in selectedUtxoList])
      totalChange = totalAvailable - (totalSpend + fee)

      # Make sure there are funds to cover the transaction.
      if totalChange < 0:
         print '***ERROR: you are trying to spend more than your balance!'
         raise NegativeValueError
      recipValuePairs.append((masterWallet.getNextUnusedAddress().getAddr160(), totalChange ))

      # ACR:  To support P2SH in general, had to change createFromTxOutSelection
      #       to take full scripts, not just hash160 values.  Convert the list
      #       before passing it in
      scrPairs = [[hash160_to_p2pkhash_script(r), v] for r,v in recipValuePairs]
            # we're providing a key map for the inputs.
      pubKeyMap = {}
      for utxo in selectedUtxoList:
         scrType = getTxOutScriptType(utxo.getScript())
         if scrType in CPP_TXOUT_STDSINGLESIG:
            scrAddr = utxo.getRecipientScrAddr()
            a160 = scrAddr_to_hash160(scrAddr)[1]
            addrObj = masterWallet.getAddrByHash160(a160)
            if addrObj:
               pubKeyMap[scrAddr] = addrObj.binPublicKey65.toBinStr()

      ustx = UnsignedTransaction().createFromTxOutSelection(selectedUtxoList, scrPairs, pubKeyMap)
      
      masterWallet.unlock(securePassphrase = SecureBinaryData(getpass('Enter your secret string:')))
      # Sign and prepare the final transaction for broadcast
      masterWallet.signUnsignedTx(ustx)
      pytx = ustx.getPyTxSignedIfPossible()
   
      print '\nSigned transaction to be broadcast using Armory "offline transactions"...'
      print ustx.serializeAscii()
   finally:
      TheBDM.beginCleanShutdown()
   return pytx
Exemplo n.º 11
0
def distributeBtc(masterWallet, amount, sendingAddrList):
   pytx = None
   setupTheBDM()
   try:
      recipValuePairs = []
      utxoList = []
      for sendingAddr in sendingAddrList:
         addr160 = sendingAddr.getAddr160()
         # Make sure the sending addresses are in the masterWallet
         if not masterWallet.hasAddr(addr160):
            raise WalletAddressError, 'Address is not in wallet! [%s]' % sendingAddr.getAddrStr()
         utxoList.extend(masterWallet.getAddrTxOutList(addr160))
   

      for importedAddr in masterWallet.getLinearAddrList():
         if importedAddr.chainIndex<0:
            recipValuePairs.append((importedAddr.getAddr160(),amount))
      totalSpend = len(recipValuePairs)*amount
      fee = calcMinSuggestedFees(utxoList, totalSpend, MIN_RELAY_TX_FEE, len(recipValuePairs))[1]
      # Get the necessary utxo list
      selectedUtxoList = PySelectCoins(utxoList, totalSpend, fee)
      # get total value   
      totalAvailable = sum([u.getValue() for u in selectedUtxoList])
      totalChange = totalAvailable - (totalSpend + fee)

      # Make sure there are funds to cover the transaction.
      if totalChange < 0:
         print '***ERROR: you are trying to spend more than your balance!'
         raise NegativeValueError
      recipValuePairs.append((masterWallet.getNextUnusedAddress().getAddr160(), totalChange ))

      # ACR:  To support P2SH in general, had to change createFromTxOutSelection
      #       to take full scripts, not just hash160 values.  Convert the list
      #       before passing it in
      scrPairs = [[hash160_to_p2pkhash_script(r), v] for r,v in recipValuePairs]
            # we're providing a key map for the inputs.
      pubKeyMap = {}
      for utxo in selectedUtxoList:
         scrType = getTxOutScriptType(utxo.getScript())
         if scrType in CPP_TXOUT_STDSINGLESIG:
            scrAddr = utxo.getRecipientScrAddr()
            a160 = scrAddr_to_hash160(scrAddr)[1]
            addrObj = masterWallet.getAddrByHash160(a160)
            if addrObj:
               pubKeyMap[scrAddr] = addrObj.binPublicKey65.toBinStr()

      ustx = UnsignedTransaction().createFromTxOutSelection(selectedUtxoList, scrPairs, pubKeyMap)
      
      masterWallet.unlock(securePassphrase = SecureBinaryData(getpass('Enter your secret string:')))
      # Sign and prepare the final transaction for broadcast
      masterWallet.signUnsignedTx(ustx)
      pytx = ustx.getPyTxSignedIfPossible()
   
      print '\nSigned transaction to be broadcast using Armory "offline transactions"...'
      print ustx.serializeAscii()
   finally:
      TheBDM.beginCleanShutdown()
   return pytx
Exemplo n.º 12
0
    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.")
Exemplo n.º 13
0
def setupTheBDM():
   TheBDM.setBlocking(True)
   if not TheBDM.isInitialized():
      TheBDM.registerWallet(masterWallet)
      TheBDM.setOnlineMode(True)
      # Only executed on the first call if blockchain not loaded yet.
      LOGINFO('Blockchain loading')
      while not TheBDM.getBDMState()=='BlockchainReady':
         LOGINFO('Blockchain Not Ready Yet %s' % TheBDM.getBDMState())
         time.sleep(2)
Exemplo n.º 14
0
   def setUp(self):
      TheBDM.Reset()
      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)
Exemplo n.º 15
0
 def searchItem():
     searchString = str(self.searchEntry.text())
     if len(searchString) > 0:
         likelyDataType = isLikelyDataType(searchString)
         for wltID, wlt in self.main.walletMap.iteritems():
             if wlt.hasAddr(searchString):
                 searchHash = searchString if likelyDataType == DATATYPE.Hex \
                       else addrStr_to_hash160(searchString)[1]
                 dialog = DlgAddressInfo(wlt,
                                         searchHash,
                                         main=self.main)
                 dialog.exec_()
                 break
             if likelyDataType == DATATYPE.Hex:
                 walletLedger = wlt.cppWallet.getTxLedger()
                 txHashToFind = hex_to_binary(searchString,
                                              endOut=BIGENDIAN)
                 txFound = False
                 for entry in walletLedger:
                     if entry.getTxHash() == txHashToFind:
                         cppTx = TheBDM.getTxByHash(txHashToFind)
                         serializedCppTx = cppTx.serialize()
                         pytx = PyTx().unserialize(serializedCppTx)
                         DlgDispTxInfo(pytx, wlt, self.main,
                                       self.main).exec_()
                         txFound = True
                         break
                 if txFound:
                     break
Exemplo n.º 16
0
   def updateOnCoinControl(self):
      useAllAddr = (self.altBalance == None)
      wlt = self.main.walletMap[self.getSelectedWltID()]
      fullBal = wlt.getBalance('Spendable')
      if useAllAddr:
         self.dispID.setText(wlt.uniqueIDB58)
         self.dispName.setText(wlt.labelName)
         self.dispDescr.setText(wlt.labelDescr)
         if fullBal == 0:
            self.dispBal.setText('0.0', color='TextRed', bold=True)
         else:
            self.dispBal.setValueText(fullBal, wBold=True)
      else:
         self.dispID.setText(wlt.uniqueIDB58 + '*')
         self.dispName.setText(wlt.labelName + '*')
         self.dispDescr.setText('*Coin Control Subset*', color='TextBlue', bold=True)
         self.dispBal.setText(coin2str(self.altBalance, maxZeros=0), color='TextBlue')
         rawValTxt = str(self.dispBal.text())
         self.dispBal.setText(rawValTxt + ' <font color="%s">(of %s)</font>' % \
                                    (htmlColor('DisableFG'), coin2str(fullBal, maxZeros=0)))

      if not TheBDM.getState() == BDM_BLOCKCHAIN_READY:
         self.dispBal.setText('(available when online)', color='DisableFG')
      self.repaint()
      if self.coinControlCallback:
         self.coinControlCallback(self.sourceAddrList, self.altBalance)
    def __init__(self, parent, main):
        super(WalletWizard, self).__init__(parent, main)
        self.newWallet = None
        self.isBackupCreated = False
        self.setWindowTitle(tr("Wallet Creation Wizard"))
        self.setOption(QWizard.HaveFinishButtonOnEarlyPages, on=True)
        self.setOption(QWizard.IgnoreSubTitles, on=True)

        # Page 1: Create Wallet
        self.walletCreationPage = WalletCreationPage(self)
        self.addPage(self.walletCreationPage)

        # Page 2: Set Passphrase
        self.setPassphrasePage = SetPassphrasePage(self)
        self.addPage(self.setPassphrasePage)

        # Page 3: Verify Passphrase
        self.verifyPassphrasePage = VerifyPassphrasePage(self)
        self.addPage(self.verifyPassphrasePage)

        # Page 4: Create Paper Backup
        self.walletBackupPage = WalletBackupPage(self)
        self.addPage(self.walletBackupPage)

        # Page 5: Create Watching Only Wallet -- but only if expert, or offline
        self.hasCWOWPage = False
        if self.main.usermode == USERMODE.Expert or TheBDM.getState() == BDM_OFFLINE:
            self.hasCWOWPage = True
            self.createWOWPage = CreateWatchingOnlyWalletPage(self)
            self.addPage(self.createWOWPage)

        self.setButtonLayout([QWizard.BackButton, QWizard.Stretch, QWizard.NextButton, QWizard.FinishButton])
Exemplo n.º 18
0
    def updateOnCoinControl(self):
        useAllAddr = (self.altBalance == None)
        wlt = self.main.walletMap[self.getSelectedWltID()]
        fullBal = wlt.getBalance('Spendable')
        if useAllAddr:
            self.dispID.setText(wlt.uniqueIDB58)
            self.dispName.setText(wlt.labelName)
            self.dispDescr.setText(wlt.labelDescr)
            if fullBal == 0:
                self.dispBal.setText('0.0', color='TextRed', bold=True)
            else:
                self.dispBal.setValueText(fullBal, wBold=True)
        else:
            self.dispID.setText(wlt.uniqueIDB58 + '*')
            self.dispName.setText(wlt.labelName + '*')
            self.dispDescr.setText('*Coin Control Subset*',
                                   color='TextBlue',
                                   bold=True)
            self.dispBal.setText(coin2str(self.altBalance, maxZeros=0),
                                 color='TextBlue')
            rawValTxt = str(self.dispBal.text())
            self.dispBal.setText(rawValTxt + ' <font color="%s">(of %s)</font>' % \
                                       (htmlColor('DisableFG'), coin2str(fullBal, maxZeros=0)))

        if not TheBDM.getState() == BDM_BLOCKCHAIN_READY:
            self.dispBal.setText('(available when online)', color='DisableFG')
        self.repaint()
        if self.coinControlCallback:
            self.coinControlCallback(self.sourceAddrList, self.altBalance)
Exemplo n.º 19
0
 def searchItem():
    searchString = str(self.searchEntry.text())
    if len(searchString) > 0:
       likelyDataType = isLikelyDataType(searchString)    
       for wltID, wlt in self.main.walletMap.iteritems():
          if wlt.hasAddr(searchString):
             searchHash = searchString if likelyDataType == DATATYPE.Hex \
                   else addrStr_to_hash160(searchString)[1]
             dialog = DlgAddressInfo(wlt, searchHash, main=self.main)
             dialog.exec_()
             break
          if likelyDataType == DATATYPE.Hex:
             walletLedger = wlt.cppWallet.getTxLedger()
             txHashToFind = hex_to_binary(searchString, endOut=BIGENDIAN)
             txFound = False
             for entry in walletLedger:
                if entry.getTxHash() ==  txHashToFind:
                   cppTx = TheBDM.getTxByHash(txHashToFind)
                   serializedCppTx = cppTx.serialize()
                   pytx = PyTx().unserialize(serializedCppTx)
                   DlgDispTxInfo(pytx, wlt, self.main, self.main).exec_()
                   txFound = True
                   break
             if txFound:
                break
Exemplo n.º 20
0
def distributeBtc(masterWallet, amount, sendingAddrList):
   pytx = None
   setupTheBDM()
   try:
      recipValuePairs = []
      utxoList = []
      for sendingAddr in sendingAddrList:
         addr160 = sendingAddr.getAddr160()
         # Make sure the sending addresses are in the masterWallet
         if not masterWallet.hasAddr(addr160):
            raise WalletAddressError, 'Address is not in wallet! [%s]' % sendingAddr.getAddrStr()
         utxoList.extend(masterWallet.getAddrTxOutList(addr160))
   

      for importedAddr in masterWallet.getLinearAddrList():
         if importedAddr.chainIndex<0:
            recipValuePairs.append((importedAddr.getAddr160(),amount))
      totalSpend = len(recipValuePairs)*amount
      fee = calcMinSuggestedFees(utxoList, totalSpend, MIN_RELAY_TX_FEE, len(recipValuePairs))[1]
      # Get the necessary utxo list
      selectedUtxoList = PySelectCoins(utxoList, totalSpend, fee)
      # get total value   
      totalAvailable = sum([u.getValue() for u in selectedUtxoList])
      totalChange = totalAvailable - (totalSpend + fee)

      # Make sure there are funds to cover the transaction.
      if totalChange < 0:
         print '***ERROR: you are trying to spend more than your balance!'
         raise NegativeValueError
      recipValuePairs.append((masterWallet.getNextUnusedAddress().getAddr160(), totalChange ))

      # ACR:  To support P2SH in general, had to change createFromTxOutSelection
      #       to take full scripts, not just hash160 values.  Convert the list
      #       before passing it in
      scrPairs = [[hash160_to_p2pkhash_script(r), v] for r,v in recipValuePairs]
      txdp = PyTxDistProposal().createFromTxOutSelection(selectedUtxoList, scrPairs)
      
      masterWallet.unlock(securePassphrase = SecureBinaryData(getpass('Enter your secret string:')))
      # Sign and prepare the final transaction for broadcast
      masterWallet.signTxDistProposal(txdp)
      pytx = txdp.prepareFinalTx()
   
      print '\nSigned transaction to be broadcast using Armory "offline transactions"...'
      print txdp.serializeAscii()
   finally:
      TheBDM.execCleanShutdown()
   return pytx
Exemplo n.º 21
0
 def tearDownClass(self):
    def tiabBDMShutdownCallback(action, arg):
       global doneShuttingDownBDM
       if action == STOPPED_ACTION:
          doneShuttingDownBDM = True
    
    TheBDM.registerCppNotification(tiabBDMShutdownCallback)
    TheBDM.beginCleanShutdown()
    
    i = 0
    while not doneShuttingDownBDM:
       time.sleep(0.5)
       i += 1
       if i >= 40:
          raise RuntimeError("Timeout waiting for TheBDM to shutdown.")
    
    self.tiab.clean()
Exemplo n.º 22
0
    def getTxFee(tx):
        btcIn, btcOut = 0, 0

        for i in range(tx.getNumTxIn()):
            btcIn += TheBDM.getSentValue(tx.getTxIn(i))
        for i in range(tx.getNumTxOut()):
            btcOut += tx.getTxOut(i).getValue()
        return (btcIn - btcOut)
 def getTxFee(tx):
    btcIn, btcOut = 0,0
    
    for i in range(tx.getNumTxIn()):
       btcIn += TheBDM.getSentValue(tx.getTxIn(i))
    for i in range(tx.getNumTxOut()):
       btcOut += tx.getTxOut(i).getValue()
    return (btcIn - btcOut)
Exemplo n.º 24
0
 def setUpClass(self):
    global doneShuttingDownBDM
    doneShuttingDownBDM = False
    
    # Handle both calling the this test from the context of the test directory
    # and calling this test from the context of the main directory. 
    # The latter happens if you run all of the tests in the directory
    if os.path.exists(TIAB_ZIPFILE_NAME):
       tiabZipPath = TIAB_ZIPFILE_NAME
    elif os.path.exists(os.path.join('pytest',TIAB_ZIPFILE_NAME)):
       tiabZipPath = (os.path.join('pytest',TIAB_ZIPFILE_NAME))
    else:
       self.fail(NEED_TIAB_MSG)
    self.tiab = TiabSession(tiabZipPath=tiabZipPath)
    
    newTheBDM()
    self.armoryHomeDir = os.path.join(self.tiab.tiabDirectory,'tiab','armory')
    TheBDM.setSatoshiDir(os.path.join(self.tiab.tiabDirectory,'tiab','1','testnet3'))
    TheBDM.setArmoryDBDir(os.path.join(self.tiab.tiabDirectory,'tiab','armory','databases'))
    TheBDM.goOnline(armoryDBDir=self.armoryHomeDir)
    
    i = 0
    while not TheBDM.getState()==BDM_BLOCKCHAIN_READY:
       time.sleep(2)
       i += 1
       if i >= 60:
          raise RuntimeError("Timeout waiting for TheBDM to get into BlockchainReady state.")
Exemplo n.º 25
0
 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)
Exemplo n.º 26
0
 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)
Exemplo n.º 27
0
   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.")
Exemplo n.º 28
0
      def sendDust():
         try:
            utxiList = []
            for utxo in self.dustTableModel.dustTxOutlist:
               # The PyCreateAndSignTx method require PyTx and PyBtcAddress objects
               rawTx = TheBDM.getTxByHash(utxo.getTxHash()).serialize()
               a160 = CheckHash160(utxo.getRecipientScrAddr())
               for pyAddr in self.dustTableModel.wlt.addrMap.values():
                  if a160 == pyAddr.getAddr160():
                     pubKey = pyAddr.binPublicKey65.toBinStr()
                     txoIdx = utxo.getTxOutIndex()
                     utxiList.append(UnsignedTxInput(rawTx, txoIdx, None, pubKey))
                     break
            # Make copies, destroy them in the finally clause
            privKeyMap = {}
            for addrObj in self.dustTableModel.wlt.addrMap.values():
               scrAddr = SCRADDR_P2PKH_BYTE + addrObj.getAddr160()
               if self.dustTableModel.wlt.useEncryption and self.dustTableModel.wlt.isLocked:
                  # Target wallet is encrypted...
                  unlockdlg = DlgUnlockWallet(self.dustTableModel.wlt,
                        self.main, self.main, 'Unlock Wallet to Import')
                  if not unlockdlg.exec_():
                     QMessageBox.critical(self, 'Wallet is Locked', \
                        'Cannot send dust without unlocking the wallet!', \
                        QMessageBox.Ok)
                     return
               privKeyMap[scrAddr] = addrObj.binPrivKey32_Plain.copy()
            signedTx = PyCreateAndSignTx(utxiList,
                  [],
                  privKeyMap, SIGHASH_NONE|SIGHASH_ANYONECANPAY )
            
            print "-------------"
            print binary_to_hex(signedTx.serialize())
            
            # sock = socket.create_connection(('dust-b-gone.bitcoin.petertodd.org',80))
            # sock.send(signedTx.serialize())
            # sock.send(b'\n')
            # sock.close()
                  

         except socket.error as err:
            QMessageBox.critical(self.main, tr('Negative Value'), tr("""
               Failed to connect to dust-b-gone server: %s""" % err.strerror), QMessageBox.Ok)            
         except NegativeValueError:
            QMessageBox.critical(self.main, tr('Negative Value'), tr("""
               You must enter a positive value of at least 0.0000 0001 
               and less than %s for the dust limit.""" % MAX_DUST_LIMIT_STR), QMessageBox.Ok)
         except TooMuchPrecisionError:
            QMessageBox.critical(self.main.main, tr('Too much precision'), tr("""
               Bitcoins can only be specified down to 8 decimal places. 
               The smallest unit of a Groestlcoin is 0.0000 0001 GRS.
               Please enter a dust limit of at least 0.0000 0001 and less than %s.""" % MAX_DUST_LIMIT_STR), QMessageBox.Ok)
         finally:
            for scraddr in privKeyMap:
               privKeyMap[scraddr].destroy()
Exemplo n.º 29
0
    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)
Exemplo n.º 30
0
def setupTheBDM():
   TheBDM.setBlocking(True)
   if not TheBDM.getState()==BDM_BLOCKCHAIN_READY:
      masterWallet.registerWallet()
      TheBDM.setOnlineMode(True)
      # Only executed on the first call if blockchain not loaded yet.
      LOGINFO('Blockchain loading')
      while not TheBDM.getState()==BDM_BLOCKCHAIN_READY:
         LOGINFO('Blockchain Not Ready Yet %s' % TheBDM.getState())
         time.sleep(2)
Exemplo n.º 31
0
def setupTheBDM():
   TheBDM.setBlocking(True)
   if not TheBDM.getState()==BDM_BLOCKCHAIN_READY:
      masterWallet.registerWallet()
      TheBDM.setOnlineMode(True)
      # Only executed on the first call if blockchain not loaded yet.
      LOGINFO('Blockchain loading')
      while not TheBDM.getState()==BDM_BLOCKCHAIN_READY:
         LOGINFO('Blockchain Not Ready Yet %s' % TheBDM.getState())
         time.sleep(2)
Exemplo n.º 32
0
   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)
Exemplo n.º 33
0
    def __init__(self, parent, main):
        super(WalletWizard, self).__init__(parent, main)
        self.newWallet = None
        self.isBackupCreated = False
        self.setWindowTitle(tr("Wallet Creation Wizard"))
        self.setOption(QWizard.HaveFinishButtonOnEarlyPages, on=True)
        self.setOption(QWizard.IgnoreSubTitles, on=True)

        self.walletCreationId, self.manualEntropyId, self.setPassphraseId, self.verifyPassphraseId, self.walletBackupId, self.WOWId = range(
            6)

        # Page 1: Create Wallet
        self.walletCreationPage = WalletCreationPage(self)
        self.setPage(self.walletCreationId, self.walletCreationPage)

        # Page 1.5: Add manual entropy
        self.manualEntropyPage = ManualEntropyPage(self)
        self.setPage(self.manualEntropyId, self.manualEntropyPage)

        # Page 2: Set Passphrase
        self.setPassphrasePage = SetPassphrasePage(self)
        self.setPage(self.setPassphraseId, self.setPassphrasePage)

        # Page 3: Verify Passphrase
        self.verifyPassphrasePage = VerifyPassphrasePage(self)
        self.setPage(self.verifyPassphraseId, self.verifyPassphrasePage)

        # Page 4: Create Paper Backup
        self.walletBackupPage = WalletBackupPage(self)
        self.setPage(self.walletBackupId, self.walletBackupPage)

        # Page 5: Create Watching Only Wallet -- but only if expert, or offline
        self.hasCWOWPage = False
        if self.main.usermode == USERMODE.Expert or TheBDM.getState(
        ) == BDM_OFFLINE:
            self.hasCWOWPage = True
            self.createWOWPage = CreateWatchingOnlyWalletPage(self)
            self.setPage(self.WOWId, self.createWOWPage)

        self.setButtonLayout([
            QWizard.BackButton, QWizard.Stretch, QWizard.NextButton,
            QWizard.FinishButton
        ])
Exemplo n.º 34
0
    def updateWalletTable(self):
        numWallets = len(self.main.walletMap)
        self.wltTable.setRowCount(numWallets)
        self.wltTable.setColumnCount(4)

        row = 0
        for wltID, wltObj in self.main.walletMap.iteritems():
            wltValueBTC = '(...)'
            wltValueUSD = '(...)'
            if TheBDM.getState() == BDM_BLOCKCHAIN_READY:
                convertVal = float(self.lastSellStr.replace(',', ''))
                wltBal = wltObj.getBalance('Total')
                wltValueBTC = coin2str(wltBal, maxZeros=2)
                wltValueUSD = '$' + self.addCommasToPrice(
                    '%0.2f' % (wltBal * convertVal / 1e8))

            rowItems = []
            rowItems.append(QTableWidgetItem(wltID))
            rowItems.append(QTableWidgetItem(wltObj.labelName))
            rowItems.append(QTableWidgetItem(wltValueBTC))
            rowItems.append(QTableWidgetItem(wltValueUSD))

            rowItems[-2].setTextAlignment(Qt.AlignRight)
            rowItems[-1].setTextAlignment(Qt.AlignRight)
            rowItems[-2].setFont(GETFONT('Fixed', 10))
            rowItems[-1].setFont(GETFONT('Fixed', 10))

            for i, item in enumerate(rowItems):
                self.wltTable.setItem(row, i, item)
                item.setFlags(Qt.NoItemFlags)

            self.wltTable.setHorizontalHeaderItem(
                0, QTableWidgetItem(tr('Wallet ID')))
            self.wltTable.setHorizontalHeaderItem(
                1, QTableWidgetItem(tr('Wallet Name')))
            self.wltTable.setHorizontalHeaderItem(
                2, QTableWidgetItem(tr('BTC Balance')))
            self.wltTable.setHorizontalHeaderItem(
                3, QTableWidgetItem(tr('USD ($) Value')))
            self.wltTable.verticalHeader().hide()

            row += 1
Exemplo n.º 35
0
    def updateOnWalletChange(self, ignoredInt=None):
        """
      "ignoredInt" is because the signals should call this function with the
      selected index of the relevant container, but we grab it again anyway
      using getSelectedWltID()
      """

        wltID = self.getSelectedWltID()

        if len(wltID) > 0:
            wlt = self.main.walletMap[wltID]

            self.dispID.setText(wltID)
            self.dispName.setText(wlt.labelName)
            self.dispDescr.setText(wlt.labelDescr)
            self.selectedID = wltID

            if not TheBDM.getState() == BDM_BLOCKCHAIN_READY:
                self.dispBal.setText('-' * 12)
            else:
                bal = wlt.getBalance('Spendable')
                balStr = coin2str(wlt.getBalance('Spendable'), maxZeros=1)
                if bal <= self.balAtLeast:
                    self.dispBal.setText('<font color="red"><b>%s</b></font>' %
                                         balStr)
                else:
                    self.dispBal.setText('<b>' + balStr + '</b>')

            if self.selectWltCallback:
                self.selectWltCallback(wlt)

            self.repaint()
            # Reset the coin control variables after a new wallet is selected
            if self.coinControlCallback:
                self.altBalance = None
                self.sourceAddrList = None
                self.btnCoinCtrl.setEnabled(wlt.getBalance('Spendable') > 0)
                self.lblCoinCtrl.setText('Source: All addresses' if wlt.getBalance('Spendable')>0 else\
                                         'Source: 0 addresses' )
                self.updateOnCoinControl()
Exemplo n.º 36
0
   def updateOnWalletChange(self, ignoredInt=None):
      """
      "ignoredInt" is because the signals should call this function with the
      selected index of the relevant container, but we grab it again anyway
      using getSelectedWltID()
      """

      wltID = self.getSelectedWltID()

      if len(wltID) > 0:
         wlt = self.main.walletMap[wltID]
               
         self.dispID.setText(wltID)
         self.dispName.setText(wlt.labelName)
         self.dispDescr.setText(wlt.labelDescr)
         self.selectedID = wltID
         
         if not TheBDM.getState() == BDM_BLOCKCHAIN_READY:
            self.dispBal.setText('-' * 12)
         else:
            bal = wlt.getBalance('Spendable')
            balStr = coin2str(wlt.getBalance('Spendable'), maxZeros=1)
            if bal <= self.balAtLeast:
               self.dispBal.setText('<font color="red"><b>%s</b></font>' % balStr)
            else:
               self.dispBal.setText('<b>' + balStr + '</b>')     

         if self.selectWltCallback:
            self.selectWltCallback(wlt)

         self.repaint()
         # Reset the coin control variables after a new wallet is selected
         if self.coinControlCallback:
            self.altBalance = None
            self.sourceAddrList = None
            self.btnCoinCtrl.setEnabled(wlt.getBalance('Spendable')>0)
            self.lblCoinCtrl.setText('Source: All addresses' if wlt.getBalance('Spendable')>0 else\
                                     'Source: 0 addresses' )
            self.updateOnCoinControl()
    def updateWalletTable(self):
        numWallets = len(self.main.walletMap)
        self.wltTable.setRowCount(numWallets)
        self.wltTable.setColumnCount(4)

        row = 0
        for wltID, wltObj in self.main.walletMap.iteritems():
            wltValueBTC = "(...)"
            wltValueUSD = "(...)"
            if TheBDM.getState() == BDM_BLOCKCHAIN_READY:
                convertVal = float(self.lastSellStr.replace(",", ""))
                wltBal = wltObj.getBalance("Total")
                wltValueBTC = coin2str(wltBal, maxZeros=2)
                wltValueUSD = "$" + self.addCommasToPrice("%0.2f" % (wltBal * convertVal / 1e8))

            rowItems = []
            rowItems.append(QTableWidgetItem(wltID))
            rowItems.append(QTableWidgetItem(wltObj.labelName))
            rowItems.append(QTableWidgetItem(wltValueBTC))
            rowItems.append(QTableWidgetItem(wltValueUSD))

            rowItems[-2].setTextAlignment(Qt.AlignRight)
            rowItems[-1].setTextAlignment(Qt.AlignRight)
            rowItems[-2].setFont(GETFONT("Fixed", 10))
            rowItems[-1].setFont(GETFONT("Fixed", 10))

            for i, item in enumerate(rowItems):
                self.wltTable.setItem(row, i, item)
                item.setFlags(Qt.NoItemFlags)

            self.wltTable.setHorizontalHeaderItem(0, QTableWidgetItem(tr("Wallet ID")))
            self.wltTable.setHorizontalHeaderItem(1, QTableWidgetItem(tr("Wallet Name")))
            self.wltTable.setHorizontalHeaderItem(2, QTableWidgetItem(tr("BTC Balance")))
            self.wltTable.setHorizontalHeaderItem(3, QTableWidgetItem(tr("USD ($) Value")))
            self.wltTable.verticalHeader().hide()

            row += 1
Exemplo n.º 38
0
 def setup(self):
    rbfList = self.wallet.getRBFTxOutList()
    
    self.rbfDict = {}
    
    #order outputs by parent hash
    for utxo in rbfList:
       parentHash = utxo.getTxHashStr()
       if not parentHash in self.rbfDict:
          self.rbfDict[parentHash] = []
       
       utxoList = self.rbfDict[parentHash]
       utxoList.append(utxo)
       
    for txhash in self.rbfDict:
       #get outpoints for spender tx
       entryList = self.rbfDict[txhash]
       cppTx = TheBDM.bdv().getTxByHash(txhash)
       
       if cppTx.isInitialized():
          pytx = PyTx().unserialize(cppTx.serialize())
       else:
          continue
       
       for _input in pytx.inputs:
          spentHash = _input.outpoint.txHash
          
          #if this tx redeems an output in our list of RBF tx,
          #link it to the spendee 
          if spentHash in self.rbfDict:
             spendeeList = self.rbfDict[spentHash]
             spendeeList.append([txhash, entryList])
             
    def getRBFDict():
       return self.rbfDict
    
    self.root = RBFTreeNode(None, "root", True, getRBFDict)
Exemplo n.º 39
0
   def updateWalletTable(self):
      numWallets = len(self.main.walletMap)
      self.wltTable.setRowCount(numWallets)
      self.wltTable.setColumnCount(4)

      row = 0
      for wltID,wltObj in self.main.walletMap.iteritems():
         wltValueBTC = '(...)'
         wltValueUSD = '(...)'
         if TheBDM.getBDMState()=='BlockchainReady':
            convertVal = float(self.lastSellStr.replace(',',''))
            wltBal = wltObj.getBalance('Total')
            wltValueBTC = coin2str(wltBal, maxZeros=2)
            wltValueUSD = '$' + self.addCommasToPrice('%0.2f' % (wltBal*convertVal/1e8))

         rowItems = []
         rowItems.append(QTableWidgetItem(wltID))
         rowItems.append(QTableWidgetItem(wltObj.labelName))
         rowItems.append(QTableWidgetItem(wltValueBTC))
         rowItems.append(QTableWidgetItem(wltValueUSD))

         rowItems[-2].setTextAlignment(Qt.AlignRight)
         rowItems[-1].setTextAlignment(Qt.AlignRight)
         rowItems[-2].setFont(GETFONT('Fixed', 10))
         rowItems[-1].setFont(GETFONT('Fixed', 10))

         for i,item in enumerate(rowItems):
            self.wltTable.setItem(row, i, item)
            item.setFlags(Qt.NoItemFlags)

         self.wltTable.setHorizontalHeaderItem(0, QTableWidgetItem(tr('Wallet ID')))
         self.wltTable.setHorizontalHeaderItem(1, QTableWidgetItem(tr('Wallet Name')))
         self.wltTable.setHorizontalHeaderItem(2, QTableWidgetItem(tr('BTC Balance')))
         self.wltTable.setHorizontalHeaderItem(3, QTableWidgetItem(tr('USD ($) Value')))
         self.wltTable.verticalHeader().hide()

         row += 1
Exemplo n.º 40
0
    def setup(self):
        rbfList = self.wallet.getRBFTxOutList()

        self.rbfDict = {}

        #order outputs by parent hash
        for utxo in rbfList:
            parentHash = utxo.getTxHashStr()
            if not parentHash in self.rbfDict:
                self.rbfDict[parentHash] = []

            utxoList = self.rbfDict[parentHash]
            utxoList.append(utxo)

        for txhash in self.rbfDict:
            #get outpoints for spender tx
            entryList = self.rbfDict[txhash]
            cppTx = TheBDM.bdv().getTxByHash(txhash)

            if cppTx.isInitialized():
                pytx = PyTx().unserialize(cppTx.serialize())
            else:
                continue

            for _input in pytx.inputs:
                spentHash = _input.outpoint.txHash

                #if this tx redeems an output in our list of RBF tx,
                #link it to the spendee
                if spentHash in self.rbfDict:
                    spendeeList = self.rbfDict[spentHash]
                    spendeeList.append([txhash, entryList])

        def getRBFDict():
            return self.rbfDict

        self.root = RBFTreeNode(None, "root", True, getRBFDict)
Exemplo n.º 41
0
 def tearDown(self):
     TheBDM.unregisterCppNotification(self.armoryDTiabTestCallback)
     self.wltA.unregisterWallet()
     self.wltB.unregisterWallet()
     self.wltC.unregisterWallet()
     self.resetWalletFiles()
Exemplo n.º 42
0
 def setUp(self):
     TheBDM.Reset(wait=True)
Exemplo n.º 43
0
 def fetchCpp(self):
    """ Convert a raw blockheader with no context, to a C++ BlockHeader """
    return TheBDM.getHeaderByHash(self.getHash())
Exemplo n.º 44
0
   def __init__(self, parent, main, layoutDir=VERTICAL, spendFromLBID=None):
      super(LockboxSelectFrame, self).__init__(parent, main)

      self.lbox = self.main.getLockboxByID(spendFromLBID)
      self.cppWlt = self.main.cppLockboxWltMap[spendFromLBID]

      if not self.lbox:
         QMessageBox.warning(self, tr("Invalid Lockbox"), tr(""" There was 
         an error loading the specified lockbox (%s).""") % spendFromLBID, 
         QMessageBox.Ok)
         self.reject()
         return

      lblSpendFromLB = QRichLabel(tr(""" <font color="%s" size=4><b><u>Lockbox   
         %s (%d-of-%d)</u></b></font>""") % (htmlColor('TextBlue'), \
         self.lbox.uniqueIDB58, self.lbox.M, self.lbox.N))
      lblSpendFromLB.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)

      lbls = []
      lbls.append(QRichLabel("Lockbox ID:", doWrap=False))
      lbls.append(QRichLabel("Name:", doWrap=False))
      lbls.append(QRichLabel("Description:", doWrap=False))
      lbls.append(QRichLabel("Spendable GRS:", doWrap=False))

      layoutDetails = QGridLayout()
      for i,lbl in enumerate(lbls):
         lbl.setAlignment(Qt.AlignLeft | Qt.AlignTop)
         lbl.setText('<b>' + str(lbls[i].text()) + '</b>')
         layoutDetails.addWidget(lbl, i+1, 0)
         
      # LockboxID
      self.dispID = QRichLabel(spendFromLBID)

      # Lockbox Short Description/Name
      self.dispName = QRichLabel(self.lbox.shortName)
      self.dispName.setWordWrap(True)
      self.dispName.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)

      # Lockbox long descr
      dispDescr = self.lbox.longDescr[:253]
      if len(self.lbox.longDescr)>253:
         dispDescr += '...'
      self.dispDescr = QRichLabel(dispDescr)
      self.dispDescr.setWordWrap(True)
      self.dispDescr.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
      bal = self.cppWlt.getSpendableBalance(TheBDM.getTopBlockHeight(), IGNOREZC)
      self.dispBal = QMoneyLabel(bal, wBold=True)
      self.dispBal.setTextFormat(Qt.RichText)

      layoutDetails.addWidget(self.dispID, 1, 1)
      layoutDetails.addWidget(self.dispName, 2, 1)
      layoutDetails.addWidget(self.dispDescr, 3, 1)
      layoutDetails.addWidget(self.dispBal, 4, 1)
      layoutDetails.setColumnStretch(0,0)
      layoutDetails.setColumnStretch(1,1)
      frmDetails = QFrame()
      frmDetails.setLayout(layoutDetails)
      frmDetails.setFrameStyle(STYLE_SUNKEN)

      layout = QVBoxLayout()
      layout.addWidget(lblSpendFromLB)
      layout.addWidget(frmDetails)

      self.setLayout(layout)
Exemplo n.º 45
0
 def tearDown(self):
     TheBDM.unregisterCppNotification(self.armoryDTestCallback)
     self.wallet.unregisterWallet()
     self.removeFileList(
         [self.fileA, self.fileB, self.fileAupd, self.fileBupd])
Exemplo n.º 46
0
 def fetchCpp(self):
     """ Convert a raw blockheader with no context, to a C++ BlockHeader """
     return TheBDM.getHeaderByHash(self.getHash())
   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()

################################################################################
if run_LoadBlockchain_Block:
    def __init__(self, parent, main, addrtype):
        super(AddressTypeSelectDialog, self).__init__(parent, main)

        self.type = "P2PKH"
        if addrtype is not None:
            self.type = addrtype

        #p2pkh
        self.radioP2PKH = QRadioButton(self.tr("P2PKH Address"))
        p2pkhDescr = QLabel(
            self.tr('Legacy Armory address type. Backwards compatible.'))

        frmP2PKH = QFrame()
        frmP2PKH.setFrameStyle(STYLE_RAISED)
        p2pkhLayout = QGridLayout()
        p2pkhLayout.addWidget(self.radioP2PKH, 0, 0, 1, 1)
        p2pkhLayout.addWidget(p2pkhDescr, 1, 0, 1, 1)
        frmP2PKH.setLayout(p2pkhLayout)

        def setP2PKH():
            self.selectType('P2PKH')

        self.connect(self.radioP2PKH, SIGNAL('clicked()'), setP2PKH)

        #nested p2wpkh
        self.radioSW = QRadioButton(self.tr("P2SH-P2WPKH address"))
        swDescr = QLabel(
            self.
            tr('P2WPKH (SegWit script) nested in P2SH script. Any wallet can pay to '
               'this address. Only wallets supporting SegWit can spend from it.'
               ))

        frmSW = QFrame()
        frmSW.setFrameStyle(STYLE_RAISED)
        swLayout = QGridLayout()
        swLayout.addWidget(self.radioSW, 0, 0, 1, 1)
        swLayout.addWidget(swDescr, 1, 0, 1, 1)
        frmSW.setLayout(swLayout)

        if TheBDM.isSegWitEnabled() == False:
            frmSW.setDisabled(True)

        def setSW():
            self.selectType('P2SH-P2WPKH')

        self.connect(self.radioSW, SIGNAL('clicked()'), setSW)

        #nested p2pk
        self.radioNP2PK = QRadioButton(self.tr("P2SH-P2PK address"))
        np2pkDescr = QLabel(
            self.
            tr('Compressed P2PK script nested in P2SH output. Any wallet can pay to this '
               'address. Only Armory 0.96+ can spend from it.<br><br>'
               'This format allow for more efficient transaction space use, resulting in '
               'smaller inputs and lower fees.'))

        frmNP2PK = QFrame()
        frmNP2PK.setFrameStyle(STYLE_RAISED)
        np2pkLayout = QGridLayout()
        np2pkLayout.addWidget(self.radioNP2PK, 0, 0, 1, 1)
        np2pkLayout.addWidget(np2pkDescr, 1, 0, 1, 1)
        frmNP2PK.setLayout(np2pkLayout)

        def setNP2PK():
            self.selectType('P2SH-P2PK')

        self.connect(self.radioNP2PK, SIGNAL('clicked()'), setNP2PK)

        #main layout
        layout = QGridLayout()
        layout.addWidget(frmP2PKH, 0, 0, 1, 4)
        layout.addWidget(frmNP2PK, 2, 0, 1, 4)
        layout.addWidget(frmSW, 4, 0, 1, 4)

        self.btnOk = QPushButton(self.tr('Apply'))
        self.btnCancel = QPushButton(self.tr('Cancel'))

        self.connect(self.btnOk, SIGNAL('clicked()'), self.accept)
        self.connect(self.btnCancel, SIGNAL('clicked()'), self.reject)

        layout.addWidget(self.btnOk, 5, 2, 1, 1)
        layout.addWidget(self.btnCancel, 5, 3, 1, 1)

        self.setLayout(layout)
        self.setWindowTitle(self.tr('Select Address Type'))

        self.selectType(self.type)
        self.setFocus()
Exemplo n.º 49
0
 def setUpClass(self):
     # Handle both calling the this test from the context of the test directory
     # and calling this test from the context of the main directory.
     # The latter happens if you run all of the tests in the directory
     if os.path.exists(TIAB_ZIPFILE_NAME):
         tiabZipPath = TIAB_ZIPFILE_NAME
     elif os.path.exists(os.path.join('pytest', TIAB_ZIPFILE_NAME)):
         tiabZipPath = (os.path.join('pytest', TIAB_ZIPFILE_NAME))
     else:
         self.fail(NEED_TIAB_MSG)
     self.tiab = TiabSession(tiabZipPath=tiabZipPath)
     # Need to destroy whatever BDM may have been created automatically
     CppBlockUtils.BlockDataManager().DestroyBDM()
     newTheBDM()
     TheBDM.setDaemon(True)
     TheBDM.start()
     TheBDM.setSatoshiDir(
         os.path.join(self.tiab.tiabDirectory, 'tiab', '1', 'testnet3'))
     self.armoryHomeDir = os.path.join(self.tiab.tiabDirectory, 'tiab',
                                       'armory')
     TheBDM.setLevelDBDir(
         os.path.join(self.tiab.tiabDirectory, 'tiab', 'armory',
                      'databases'))
     TheBDM.setBlocking(True)
     TheBDM.setOnlineMode(wait=True)
     i = 0
     while not TheBDM.getBDMState() == 'BlockchainReady' and i < 10:
         time.sleep(2)
         i += 1
     if i >= 10:
         raise RuntimeError(
             "Timeout waiting for TheBDM to get into BlockchainReady state."
         )
Exemplo n.º 50
0
 def setUpClass(self):
    # Handle both calling the this test from the context of the test directory
    # and calling this test from the context of the main directory. 
    # The latter happens if you run all of the tests in the directory
    if os.path.exists(TIAB_ZIPFILE_NAME):
       tiabZipPath = TIAB_ZIPFILE_NAME
    elif os.path.exists(os.path.join('test',TIAB_ZIPFILE_NAME)):
       tiabZipPath = (os.path.join('test',TIAB_ZIPFILE_NAME))
    else:
       self.fail(NEED_TIAB_MSG)
    self.tiab = TiabSession(tiabZipPath=tiabZipPath)
    # Need to destroy whatever BDM may have been created automatically 
    CppBlockUtils.BlockDataManager().DestroyBDM()
    newTheBDM()
    TheBDM.setDaemon(True)
    TheBDM.start()
    TheBDM.setSatoshiDir(os.path.join(self.tiab.tiabDirectory,'tiab','1','testnet3'))
    TheBDM.setLevelDBDir(os.path.join(self.tiab.tiabDirectory,'tiab','armory','databases'))
    TheBDM.setBlocking(True)
    TheBDM.setOnlineMode(wait=True)
    while not TheBDM.getBDMState()=='BlockchainReady':
       time.sleep(2)
Exemplo n.º 51
0
        def sendDust():
            try:
                utxiList = []
                for utxo in self.dustTableModel.dustTxOutlist:
                    # The PyCreateAndSignTx method require PyTx and PyBtcAddress objects
                    rawTx = TheBDM.getTxByHash(utxo.getTxHash()).serialize()
                    a160 = CheckHash160(utxo.getRecipientScrAddr())
                    for pyAddr in self.dustTableModel.wlt.addrMap.values():
                        if a160 == pyAddr.getAddr160():
                            pubKey = pyAddr.binPublicKey65.toBinStr()
                            txoIdx = utxo.getTxOutIndex()
                            utxiList.append(
                                UnsignedTxInput(rawTx, txoIdx, None, pubKey))
                            break
                # Make copies, destroy them in the finally clause
                privKeyMap = {}
                for addrObj in self.dustTableModel.wlt.addrMap.values():
                    scrAddr = SCRADDR_P2PKH_BYTE + addrObj.getAddr160()
                    if self.dustTableModel.wlt.useEncryption and self.dustTableModel.wlt.isLocked:
                        # Target wallet is encrypted...
                        unlockdlg = DlgUnlockWallet(self.dustTableModel.wlt,
                                                    self.main, self.main,
                                                    'Unlock Wallet to Import')
                        if not unlockdlg.exec_():
                            QMessageBox.critical(self, 'Wallet is Locked', \
                               'Cannot send dust without unlocking the wallet!', \
                               QMessageBox.Ok)
                            return
                    privKeyMap[scrAddr] = addrObj.binPrivKey32_Plain.copy()
                signedTx = PyCreateAndSignTx(
                    utxiList, [], privKeyMap,
                    SIGHASH_NONE | SIGHASH_ANYONECANPAY)

                print "-------------"
                print binary_to_hex(signedTx.serialize())

                # sock = socket.create_connection(('dust-b-gone.bitcoin.petertodd.org',80))
                # sock.send(signedTx.serialize())
                # sock.send(b'\n')
                # sock.close()

            except socket.error as err:
                QMessageBox.critical(
                    self.main, tr('Negative Value'),
                    tr("""
               Failed to connect to dust-b-gone server: %s""" % err.strerror),
                    QMessageBox.Ok)
            except NegativeValueError:
                QMessageBox.critical(
                    self.main, tr('Negative Value'),
                    tr("""
               You must enter a positive value of at least 0.0000 0001 
               and less than %s for the dust limit.""" % MAX_DUST_LIMIT_STR),
                    QMessageBox.Ok)
            except TooMuchPrecisionError:
                QMessageBox.critical(
                    self.main.main, tr('Too much precision'),
                    tr("""
               Bitcoins can only be specified down to 8 decimal places. 
               The smallest unit of a Bitcoin is 0.0000 0001 BTC. 
               Please enter a dust limit of at least 0.0000 0001 and less than %s."""
                       % MAX_DUST_LIMIT_STR), QMessageBox.Ok)
            finally:
                for scraddr in privKeyMap:
                    privKeyMap[scraddr].destroy()
Exemplo n.º 52
0
    def __init__(self, parent, main, layoutDir=VERTICAL, spendFromLBID=None):
        super(LockboxSelectFrame, self).__init__(parent, main)

        self.lbox = self.main.getLockboxByID(spendFromLBID)
        self.cppWlt = self.main.cppLockboxWltMap[spendFromLBID]

        if not self.lbox:
            QMessageBox.warning(
                self, tr("Invalid Lockbox"),
                tr(""" There was 
         an error loading the specified lockbox (%s).""") % spendFromLBID,
                QMessageBox.Ok)
            self.reject()
            return

        lblSpendFromLB = QRichLabel(tr(""" <font color="%s" size=4><b><u>Lockbox   
         %s (%d-of-%d)</u></b></font>""") % (htmlColor('TextBlue'), \
           self.lbox.uniqueIDB58, self.lbox.M, self.lbox.N))
        lblSpendFromLB.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)

        lbls = []
        lbls.append(QRichLabel("Lockbox ID:", doWrap=False))
        lbls.append(QRichLabel("Name:", doWrap=False))
        lbls.append(QRichLabel("Description:", doWrap=False))
        lbls.append(QRichLabel("Spendable BTC:", doWrap=False))

        layoutDetails = QGridLayout()
        for i, lbl in enumerate(lbls):
            lbl.setAlignment(Qt.AlignLeft | Qt.AlignTop)
            lbl.setText('<b>' + str(lbls[i].text()) + '</b>')
            layoutDetails.addWidget(lbl, i + 1, 0)

        # LockboxID
        self.dispID = QRichLabel(spendFromLBID)

        # Lockbox Short Description/Name
        self.dispName = QRichLabel(self.lbox.shortName)
        self.dispName.setWordWrap(True)
        self.dispName.setSizePolicy(QSizePolicy.Preferred,
                                    QSizePolicy.Preferred)

        # Lockbox long descr
        dispDescr = self.lbox.longDescr[:253]
        if len(self.lbox.longDescr) > 253:
            dispDescr += '...'
        self.dispDescr = QRichLabel(dispDescr)
        self.dispDescr.setWordWrap(True)
        self.dispDescr.setSizePolicy(QSizePolicy.Preferred,
                                     QSizePolicy.Preferred)
        bal = self.cppWlt.getSpendableBalance(TheBDM.getTopBlockHeight(),
                                              IGNOREZC)
        self.dispBal = QMoneyLabel(bal, wBold=True)
        self.dispBal.setTextFormat(Qt.RichText)

        layoutDetails.addWidget(self.dispID, 1, 1)
        layoutDetails.addWidget(self.dispName, 2, 1)
        layoutDetails.addWidget(self.dispDescr, 3, 1)
        layoutDetails.addWidget(self.dispBal, 4, 1)
        layoutDetails.setColumnStretch(0, 0)
        layoutDetails.setColumnStretch(1, 1)
        frmDetails = QFrame()
        frmDetails.setLayout(layoutDetails)
        frmDetails.setFrameStyle(STYLE_SUNKEN)

        layout = QVBoxLayout()
        layout.addWidget(lblSpendFromLB)
        layout.addWidget(frmDetails)

        self.setLayout(layout)
Exemplo n.º 53
0
 def tearDown(self):
    TheBDM.unregisterCppNotification(self.armoryDTiabTestCallback)
    self.wltA.unregisterWallet()
    self.wltB.unregisterWallet()
    self.wltC.unregisterWallet()
    self.resetWalletFiles()
Exemplo n.º 54
0
 def tearDown(self):
    TheBDM.unregisterCppNotification(self.armoryDTestCallback)
    self.wallet.unregisterWallet()
    self.removeFileList([self.fileA, self.fileB, self.fileAupd, self.fileBupd])
Exemplo n.º 55
0
 def verifyBlockHeight(self):
    blockHeight = TheBDM.getTopBlockHeight()
    self.assertEqual(blockHeight, TOP_TIAB_BLOCK, NEED_TIAB_MSG + str(blockHeight))