def getTableRow(self, contract, scope, table, idx): if idx < 0: Utils.Print("ERROR: Table index cannot be negative. idx: %d" % (idx)) return None rows = self.getTableRows(contract, scope, table) if rows is None or idx >= len(rows): Utils.Print("ERROR: Retrieved table does not contain row %d" % idx) return None row = rows[idx] return row
def killall(self, allInstances=False): """Kill kdfc instances. allInstances will kill all kdfc instances running on the system.""" if self.__walletPid: Utils.Print("Killing wallet manager process %d" % (self.__walletPid)) os.kill(self.__walletPid, signal.SIGKILL) if allInstances: cmd = "pkill -9 %s" % (Utils.FscWalletName) if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) subprocess.call(cmd.split())
def getTable(self, contract, scope, table): cmd = "%s %s get table %s %s %s" % ( Utils.EosClientPath, self.endpointArgs, contract, scope, table) if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) try: trans = Utils.runCmdReturnJson(cmd) return trans except subprocess.CalledProcessError as ex: msg = ex.output.decode("utf-8") Utils.Print("ERROR: Exception during table retrieval. %s" % (msg)) return None
def getInfo(self, silentErrors=False): cmd = "%s %s get info" % (Utils.EosClientPath, self.endpointArgs) if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) try: trans = Utils.runCmdReturnJson(cmd, silentErrors=silentErrors) return trans except subprocess.CalledProcessError as ex: if not silentErrors: msg = ex.output.decode("utf-8") Utils.Print("ERROR: Exception during get info. %s" % (msg)) return None
def launch(self): if not self.walletd: Utils.Print( "ERROR: Wallet Manager wasn't configured to launch kpicod") return False if self.isLaunched(): return True if self.isLocal(): self.port = self.findAvailablePort() pgrepCmd = Utils.pgrepCmd(Utils.PicoWalletName) if Utils.Debug: portTaken = False if self.isLocal(): if not Utils.arePortsAvailable(self.port): portTaken = True psOut = Utils.checkOutput(pgrepCmd.split(), ignoreError=True) if psOut or portTaken: statusMsg = "" if psOut: statusMsg += " %s - {%s}." % (pgrepCmd, psOut) if portTaken: statusMsg += " port %d is NOT available." % (self.port) Utils.Print( "Launching %s, note similar processes running. %s" % (Utils.PicoWalletName, statusMsg)) cmd = "%s --data-dir %s --config-dir %s --http-server-address=%s:%d --verbose-http-errors" % ( Utils.PicoWalletPath, WalletMgr.__walletDataDir, WalletMgr.__walletDataDir, self.host, self.port) if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) with open(WalletMgr.__walletLogOutFile, 'w') as sout, open(WalletMgr.__walletLogErrFile, 'w') as serr: popen = subprocess.Popen(cmd.split(), stdout=sout, stderr=serr) self.__walletPid = popen.pid # Give kpicod time to warm up time.sleep(2) try: if Utils.Debug: Utils.Print("Checking if %s launched. %s" % (Utils.PicoWalletName, pgrepCmd)) psOut = Utils.checkOutput(pgrepCmd.split()) if Utils.Debug: Utils.Print("Launched %s. {%s}" % (Utils.PicoWalletName, psOut)) except subprocess.CalledProcessError as ex: Utils.errorExit("Failed to launch the wallet manager") return True
def dumpErrorDetails(self): Utils.Print( "=================================================================" ) if self.__walletPid is not None: Utils.Print("Contents of %s:" % (WalletMgr.__walletLogFile)) Utils.Print( "=================================================================" ) with open(WalletMgr.__walletLogFile, "r") as f: shutil.copyfileobj(f, sys.stdout)
def getServants(self, name): cmd = "%s %s get servants %s" % (Utils.EosClientPath, self.endpointArgs, name) if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) try: trans = Utils.runCmdReturnJson(cmd) return trans except subprocess.CalledProcessError as ex: msg = ex.output.decode("utf-8") Utils.Print("ERROR: Exception during servants retrieval. %s" % (msg)) return None
def getEosAccountFromDb(self, name): cmd = "%s %s" % (Utils.MongoPath, self.mongoEndpointArgs) subcommand = 'db.accounts.findOne({"name" : "%s"})' % (name) if Utils.Debug: Utils.Print("cmd: echo '%s' | %s" % (subcommand, cmd)) try: trans = Node.runMongoCmdReturnJson(cmd.split(), subcommand) return trans except subprocess.CalledProcessError as ex: msg = ex.output.decode("utf-8") Utils.Print("ERROR: Exception during get account from db. %s" % (msg)) return None
def getEnuAccount(self, name): assert (isinstance(name, str)) cmd = "%s %s get account -j %s" % (Utils.EnuClientPath, self.endpointArgs, name) if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) try: trans = Utils.runCmdReturnJson(cmd) return trans except subprocess.CalledProcessError as ex: msg = ex.output.decode("utf-8") Utils.Print("ERROR: Exception during get account. %s" % (msg)) return None
def cleanup(self): for f in glob.glob("var/lib/node_*"): shutil.rmtree(f) for f in glob.glob("etc/eosio/node_*"): shutil.rmtree(f) if self.enableMongo: cmd="%s %s" % (Utils.MongoPath, self.mongoEndpointArgs) subcommand="db.dropDatabase()" if Utils.Debug: Utils.Print("echo %s | %s" % (subcommand, cmd)) ret,_,errs=Node.stdinAndCheckOutput(cmd.split(), subcommand) if ret is not 0: Utils.Print("ERROR: Failed to drop database: %s" % (Node.byteArrToStr(errs)) )
def getBlockFromDb(self, idx): cmd = "%s %s" % (Utils.MongoPath, self.mongoEndpointArgs) subcommand = "db.blocks.find().sort({\"_id\":%d}).limit(1).pretty()" % ( idx) if Utils.Debug: Utils.Print("cmd: echo \"%s\" | %s" % (subcommand, cmd)) try: trans = Node.runMongoCmdReturnJson(cmd.split(), subcommand) return trans except subprocess.CalledProcessError as ex: msg = ex.output.decode("utf-8") Utils.Print("ERROR: Exception during get db block. %s" % (msg)) return None
def getAccountsByKey(self, key): cmd = "%s %s get accounts %s" % (Utils.EosClientPath, self.endpointArgs, key) if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) try: trans = Utils.runCmdReturnJson(cmd) return trans except subprocess.CalledProcessError as ex: msg = ex.output.decode("utf-8") Utils.Print( "ERROR: Exception during accounts by key retrieval. %s" % (msg)) return None
def getTransactionMdb(self, transId, silentErrors=False): """Get transaction from MongoDB. Since DB only contains finalized blocks, transactions can take a while to appear in DB.""" cmd="%s %s" % (Utils.MongoPath, self.mongoEndpointArgs) #subcommand='db.Transactions.findOne( { $and : [ { "trx_id": "%s" }, {"irreversible":true} ] } )' % (transId) subcommand='db.transactions.findOne( { "trx_id": "%s" } )' % (transId) if Utils.Debug: Utils.Print("cmd: echo '%s' | %s" % (subcommand, cmd)) try: trans=Node.runMongoCmdReturnJson(cmd.split(), subcommand) return trans except subprocess.CalledProcessError as ex: if not silentErrors: msg=ex.output.decode("utf-8") Utils.Print("ERROR: Exception during get db node get trans. %s" % (msg)) return None
def getActions(self, account, pos=-1, offset=-1): assert(isinstance(account, Account)) assert(isinstance(pos, int)) assert(isinstance(offset, int)) cmd="%s %s get actions -j %s %d %d" % (Utils.EnuClientPath, self.endpointArgs, account.name, pos, offset) if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) try: actions=Utils.runCmdReturnJson(cmd) return actions except subprocess.CalledProcessError as ex: msg=ex.output.decode("utf-8") Utils.Print("ERROR: Exception during actions by account retrieval. %s" % (msg)) return None
def processCmd(self, cmd, cmdDesc, waitForTransBlock): if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) trans=None try: trans=Utils.runCmdReturnJson(cmd) except subprocess.CalledProcessError as ex: msg=ex.output.decode("utf-8") Utils.Print("ERROR: Exception during %s. %s" % (cmdDesc, msg)) return None transId=Node.getTransId(trans) if waitForTransBlock and not self.waitForTransInBlock(transId): return None return trans
def unlockWallet(self, wallet): cmd = "%s %s wallet unlock --name %s" % ( Utils.EosClientPath, self.endpointArgs, wallet.name) if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) popen = subprocess.Popen(cmd.split(), stdout=Utils.FNull, stdin=subprocess.PIPE) _, errs = popen.communicate(input=wallet.password.encode("utf-8")) if 0 != popen.wait(): Utils.Print("ERROR: Failed to unlock wallet %s: %s" % (wallet.name, errs.decode("utf-8"))) return False return True
def discoverLocalNodes(self, totalNodes, timeout=0): nodes = [] pgrepOpts = "-fl" # pylint: disable=deprecated-method if platform.linux_distribution()[0] in [ "Ubuntu", "LinuxMint", "Fedora", "CentOS Linux", "arch" ]: pgrepOpts = "-a" cmd = "pgrep %s %s" % (pgrepOpts, Utils.EnuServerName) def myFunc(): psOut = None try: if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) psOut = Utils.checkOutput(cmd.split()) return psOut except subprocess.CalledProcessError as _: pass return None psOut = Utils.waitForObj(myFunc, timeout) if psOut is None: Utils.Print("ERROR: No nodes discovered.") return nodes if Utils.Debug: Utils.Print("pgrep output: \"%s\"" % psOut) for i in range(0, totalNodes): pattern = r"[\n]?(\d+) (.* --data-dir var/lib/node_%02d .*)\n" % ( i) m = re.search(pattern, psOut, re.MULTILINE) if m is None: Utils.Print("ERROR: Failed to find %s pid. Pattern %s" % (Utils.EnuServerName, pattern)) break instance = Node(self.host, self.port + i, pid=int(m.group(1)), cmd=m.group(2), enableMongo=self.enableMongo, mongoHost=self.mongoHost, mongoPort=self.mongoPort, mongoDb=self.mongoDb) instance.setWalletEndpointArgs(self.walletEndpointArgs) if Utils.Debug: Utils.Print("Node>", instance) nodes.append(instance) return nodes
def getCurrencyStats(self, contract, symbol=CORE_SYMBOL): """returns Json output from get currency stats.""" assert(contract) assert(isinstance(contract, str)) assert(symbol) assert(isinstance(symbol, str)) cmd="%s %s get currency stats %s %s" % (Utils.EnuClientPath, self.endpointArgs, contract, symbol) if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) try: trans=Utils.runCmdReturnJson(cmd) return trans except subprocess.CalledProcessError as ex: msg=ex.output.decode("utf-8") Utils.Print("ERROR: Exception during get currency stats. %s" % (msg)) return None
def getBlockById(self, blockId, silentErrors=False): cmd="%s %s" % (Utils.MongoPath, self.mongoEndpointArgs) subcommand='db.blocks.findOne( { "block_id": "%s" } )' % (blockId) if Utils.Debug: Utils.Print("cmd: echo '%s' | %s" % (subcommand, cmd)) try: trans=Node.runMongoCmdReturnJson(cmd.split(), subcommand) if trans is not None: return trans except subprocess.CalledProcessError as ex: if not silentErrors: msg=ex.output.decode("utf-8") Utils.Print("ERROR: Exception during db get block by id. %s" % (msg)) return None return None
def validateAccounts(self, accounts): assert(accounts) assert(isinstance(accounts, list)) for account in accounts: assert(account) assert(isinstance(account, Account)) if Utils.Debug: Utils.Print("Validating account %s" % (account.name)) accountInfo=self.getEnuAccount(account.name) try: assert(accountInfo) assert(accountInfo["account_name"] == account.name) except (AssertionError, TypeError, KeyError) as _: Utils.Print("account validation failed. account: %s" % (account.name)) raise
def launch(self): if not self.walletd: Utils.Print("ERROR: Wallet Manager wasn't configured to launch kETAd") return False cmd="%s --data-dir %s --config-dir %s --http-server-address=%s:%d --verbose-http-errors" % ( Utils.ETAWalletPath, WalletMgr.__walletDataDir, WalletMgr.__walletDataDir, self.host, self.port) if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) with open(WalletMgr.__walletLogFile, 'w') as sout, open(WalletMgr.__walletLogFile, 'w') as serr: popen=subprocess.Popen(cmd.split(), stdout=sout, stderr=serr) self.__walletPid=popen.pid # Give kETAd time to warm up time.sleep(1) return True
def getKeys(self, wallet): keys=[] p = re.compile(r'\n\s+\"(\w+)\"\n', re.MULTILINE) cmd="%s %s wallet private_keys --name %s --password %s " % (Utils.ETAClientPath, self.endpointArgs, wallet.name, wallet.password) if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) retStr=Utils.checkOutput(cmd.split()) #Utils.Print("retStr: %s" % (retStr)) m=p.findall(retStr) if m is None: Utils.Print("ERROR: wallet private_keys parser failure") return None keys=m return keys
def getOpenWallets(self): wallets=[] p = re.compile(r'\s+\"(\w+)\s\*\",?\n', re.MULTILINE) cmd="%s %s wallet list" % (Utils.ETAClientPath, self.endpointArgs) if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) retStr=Utils.checkOutput(cmd.split()) #Utils.Print("retStr: %s" % (retStr)) m=p.findall(retStr) if m is None: Utils.Print("ERROR: wallet list parser failure") return None wallets=m return wallets
def initializeNodes(self, defproduceraPrvtKey=None, defproducerbPrvtKey=None, onlyBios=False): port = Cluster.__BiosPort if onlyBios else self.port host = Cluster.__BiosHost if onlyBios else self.host node = Node(host, port, enableMongo=self.enableMongo, mongoHost=self.mongoHost, mongoPort=self.mongoPort, mongoDb=self.mongoDb) node.setWalletEndpointArgs(self.walletEndpointArgs) if Utils.Debug: Utils.Print("Node:", node) node.checkPulse() self.nodes = [node] if defproduceraPrvtKey is not None: self.defproduceraAccount.ownerPrivateKey = defproduceraPrvtKey self.defproduceraAccount.activePrivateKey = defproduceraPrvtKey if defproducerbPrvtKey is not None: self.defproducerbAccount.ownerPrivateKey = defproducerbPrvtKey self.defproducerbAccount.activePrivateKey = defproducerbPrvtKey return True
def getAccountAacBalanceStr(self, scope): """Returns SYS currency0000 account balance from claac get table command. Returned balance is string following syntax "98.0311 SYS". """ assert isinstance(scope, str) amount=self.getTableAccountBalance("aacio.token", scope) if Utils.Debug: Utils.Print("getNodeAccountAacBalance %s %s" % (scope, amount)) assert isinstance(amount, str) return amount
def verifyProductionRounds(trans, node, prodsActive, rounds): temp = Utils.Debug Utils.Debug = False prods = [] for k,v in prodsActive.items(): if v: prods.append(k) maxBlocks = (schedulePeriodFactor + 1) * totalProducers * 2 + ((totalProducers*2//3)+1)*2 blockNum, synced = node.waitActiveSchedule(prods, maxBlocks) if not synced: blockNum = syncWithShuffle(node, blockNum) Utils.Print("Verify %s complete rounds of all producers producing" % (rounds)) for i in range(0, rounds): prodsSeen = {} reserveMax = reserve_producers for j in range(0, totalProducers): reserveMax = validBlockProducer(prodsActive, prodsSeen, blockNum, node, reserveMax) blockNum += 1 # make sure that we have seen all `top_producers` producers prodsSeenKeys=prodsSeen.keys() if len(prodsSeenKeys)!=top_producers: Utils.cmdError("only saw %s producers of expected %i. At blockNum %s only the following producers were seen: %s" % ( len(prodsSeenKeys), top_producers, blockNum, ",".join(prodsSeenKeys))) Utils.errorExit("Failed because of missing block producers") Utils.Debug = temp
def getActionsMdb(self, account, pos=-1, offset=-1): assert(isinstance(account, Account)) assert(isinstance(pos, int)) assert(isinstance(offset, int)) cmd="%s %s" % (Utils.MongoPath, self.mongoEndpointArgs) subcommand='db.actions.find({$or: [{"data.from":"%s"},{"data.to":"%s"}]}).sort({"_id":%d}).limit(%d)' % (account.name, account.name, pos, abs(offset)) if Utils.Debug: Utils.Print("cmd: echo '%s' | %s" % (subcommand, cmd)) try: actions=Node.runMongoCmdReturnJson(cmd.split(), subcommand) if actions is not None: return actions except subprocess.CalledProcessError as ex: msg=ex.output.decode("utf-8") Utils.Print("ERROR: Exception during get db actions. %s" % (msg)) return None
def setPermission(self, account, code, pType, requirement, waitForTransBlock=False): cmd="%s %s set action permission -j %s %s %s %s" % ( Utils.EnuClientPath, self.endpointArgs, account, code, pType, requirement) if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) trans=None try: trans=Utils.runCmdReturnJson(cmd) except subprocess.CalledProcessError as ex: msg=ex.output.decode("utf-8") Utils.Print("ERROR: Exception during set permission. %s" % (msg)) return None transId=Node.getTransId(trans) if waitForTransBlock and not self.waitForTransInBlock(transId): return None return trans
def getAccountEnuBalanceStr(self, scope): """Returns ENU currency0000 account balance from enucli get table command. Returned balance is string following syntax "98.0311 ENU". """ assert isinstance(scope, str) amount=self.getTableAccountBalance("enu.token", scope) if Utils.Debug: Utils.Print("getNodeAccountEnuBalance %s %s" % (scope, amount)) assert isinstance(amount, str) return amount
def create(self, name, accounts=None, exitOnError=True): wallet=self.wallets.get(name) if wallet is not None: if Utils.Debug: Utils.Print("Wallet \"%s\" already exists. Returning same." % name) return wallet p = re.compile(r'\n\"(\w+)\"\n', re.MULTILINE) cmdDesc="wallet create" cmd="%s %s %s --name %s --to-console" % (Utils.EosClientPath, self.endpointArgs, cmdDesc, name) if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) retStr=None maxRetryCount=4 retryCount=0 while True: try: retStr=Utils.checkOutput(cmd.split()) break except subprocess.CalledProcessError as ex: retryCount+=1 if retryCount<maxRetryCount: delay=10 if Utils.Debug: Utils.Print("%s was not accepted, delaying for %d seconds and trying again" % (cmdDesc, delay)) time.sleep(delay) continue msg=ex.output.decode("utf-8") errorMsg="ERROR: Failed to create wallet - %s. %s" % (name, msg) if exitOnError: Utils.errorExit("%s" % (errorMsg)) Utils.Print("%s" % (errorMsg)) return None m=p.search(retStr) if m is None: if exitOnError: Utils.cmdError("could not create wallet %s" % (name)) Utils.errorExit("Failed to create wallet %s" % (name)) Utils.Print("ERROR: wallet password parser failure") return None p=m.group(1) wallet=Wallet(name, p, self.host, self.port) self.wallets[name] = wallet if accounts: self.importKeys(accounts,wallet) return wallet