Пример #1
0
    def kill(self, killSignal):
        if Utils.Debug: Utils.Print("Killing node: %s" % (self.cmd))
        assert (self.pid is not None)
        try:
            os.kill(self.pid, killSignal)
        except OSError as ex:
            Utils.Print("ERROR: Failed to kill node (%d)." % (self.cmd), ex)
            return False

        # wait for kill validation
        def myFunc():
            try:
                os.kill(self.pid, 0)  # check if process with pid is running
            except OSError as _:
                return True
            return False

        if not Utils.waitForBool(myFunc):
            Utils.Print("ERROR: Failed to kill node (%s)." % (self.cmd))
            return False

        # mark node as killed
        self.pid = None
        self.killed = True
        return True
Пример #2
0
    def waitOnClusterBlockNumSync(self, targetHeadBlockNum, timeout=None):
        def doNodesHaveBlockNum(nodes, targetHeadBlockNum):
            for node in nodes:
                if (not node.killed) and (
                        not node.doesNodeHaveBlockNum(targetHeadBlockNum)):
                    return False

            return True

        lam = lambda: doNodesHaveBlockNum(self.nodes, targetHeadBlockNum)
        ret = Utils.waitForBool(lam, timeout)
        return ret
Пример #3
0
 def waitForNextBlock(self, timeout=None):
     num = self.getIrreversibleBlockNum()
     lam = lambda: self.getIrreversibleBlockNum() > num
     ret = Utils.waitForBool(lam, timeout)
     return ret
Пример #4
0
 def waitForTransIdOnNode(self, transId, timeout=None):
     lam = lambda: self.doesNodeHaveTransId(transId)
     ret = Utils.waitForBool(lam, timeout)
     return ret
Пример #5
0
 def waitForBlockNumOnNode(self, blockNum, timeout=None):
     lam = lambda: self.doesNodeHaveBlockNum(blockNum)
     ret = Utils.waitForBool(lam, timeout)
     return ret
Пример #6
0
    def bootstrap(totalNodes,
                  prodCount,
                  biosHost,
                  biosPort,
                  dontKill=False,
                  onlyBios=False):
        """Create 'prodCount' init accounts and deposits 10000000000 EOS in each. If prodCount is -1 will initialize all possible producers.
        Ensure nodes are inter-connected prior to this call. One way to validate this will be to check if every node has block 1."""

        Utils.Print("Starting cluster bootstrap.")
        biosNode = Node(biosHost, biosPort)
        if not biosNode.checkPulse():
            Utils.Print("ERROR: Bios node doesn't appear to be running...")
            return False

        producerKeys = Cluster.parseClusterKeys(totalNodes)
        # should have totalNodes node plus bios node
        if producerKeys is None or len(producerKeys) < (totalNodes + 1):
            Utils.Print(
                "ERROR: Failed to parse private keys from cluster config files."
            )
            return False

        walletMgr = WalletMgr(True)
        walletMgr.killall()
        walletMgr.cleanup()

        if not walletMgr.launch():
            Utils.Print("ERROR: Failed to launch bootstrap wallet.")
            return False
        biosNode.setWalletEndpointArgs(walletMgr.walletEndpointArgs)

        try:
            ignWallet = walletMgr.create("ignition")
            if ignWallet is None:
                Utils.Print("ERROR: Failed to create ignition wallet.")
                return False

            eosioName = "eosio"
            eosioKeys = producerKeys[eosioName]
            eosioAccount = Account(eosioName)
            eosioAccount.ownerPrivateKey = eosioKeys["private"]
            eosioAccount.ownerPublicKey = eosioKeys["public"]
            eosioAccount.activePrivateKey = eosioKeys["private"]
            eosioAccount.activePublicKey = eosioKeys["public"]

            if not walletMgr.importKey(eosioAccount, ignWallet):
                Utils.Print(
                    "ERROR: Failed to import %s account keys into ignition wallet."
                    % (eosioName))
                return False

            contract = "eosio.bios"
            contractDir = "contracts/%s" % (contract)
            wastFile = "contracts/%s/%s.wast" % (contract, contract)
            abiFile = "contracts/%s/%s.abi" % (contract, contract)
            Utils.Print("Publish %s contract" % (contract))
            trans = biosNode.publishContract(eosioAccount.name,
                                             contractDir,
                                             wastFile,
                                             abiFile,
                                             waitForTransBlock=True)
            if trans is None:
                Utils.Print("ERROR: Failed to publish contract %s." %
                            (contract))
                return False

            Node.validateTransaction(trans)

            Utils.Print("Creating accounts: %s " %
                        ", ".join(producerKeys.keys()))
            producerKeys.pop(eosioName)
            accounts = []
            for name, keys in producerKeys.items():
                initx = None
                initx = Account(name)
                initx.ownerPrivateKey = keys["private"]
                initx.ownerPublicKey = keys["public"]
                initx.activePrivateKey = keys["private"]
                initx.activePublicKey = keys["public"]
                trans = biosNode.createAccount(initx, eosioAccount, 0)
                if trans is None:
                    Utils.Print("ERROR: Failed to create account %s" % (name))
                    return False
                Node.validateTransaction(trans)
                accounts.append(initx)

            transId = Node.getTransId(trans)
            biosNode.waitForTransIdOnNode(transId)

            Utils.Print("Validating system accounts within bootstrap")
            biosNode.validateAccounts(accounts)

            if not onlyBios:
                if prodCount == -1:
                    setProdsFile = "setprods.json"
                    if Utils.Debug:
                        Utils.Print("Reading in setprods file %s." %
                                    (setProdsFile))
                    with open(setProdsFile, "r") as f:
                        setProdsStr = f.read()

                        Utils.Print("Setting producers.")
                        opts = "--permission eosio@active"
                        myTrans = biosNode.pushMessage("eosio", "setprods",
                                                       setProdsStr, opts)
                        if myTrans is None or not myTrans[0]:
                            Utils.Print("ERROR: Failed to set producers.")
                            return False
                else:
                    counts = dict.fromkeys(
                        range(totalNodes),
                        0)  # initialize node prods count to 0
                    setProdsStr = '{"schedule": ['
                    firstTime = True
                    prodNames = []
                    for name, keys in producerKeys.items():
                        if counts[keys["node"]] >= prodCount:
                            continue
                        if firstTime:
                            firstTime = False
                        else:
                            setProdsStr += ','

                        setProdsStr += ' { "producer_name": "%s", "block_signing_key": "%s" }' % (
                            keys["name"], keys["public"])
                        prodNames.append(keys["name"])
                        counts[keys["node"]] += 1

                    setProdsStr += ' ] }'
                    if Utils.Debug: Utils.Print("setprods: %s" % (setProdsStr))
                    Utils.Print("Setting producers: %s." %
                                (", ".join(prodNames)))
                    opts = "--permission eosio@active"
                    # pylint: disable=redefined-variable-type
                    trans = biosNode.pushMessage("eosio", "setprods",
                                                 setProdsStr, opts)
                    if trans is None or not trans[0]:
                        Utils.Print("ERROR: Failed to set producer %s." %
                                    (keys["name"]))
                        return False

                trans = trans[1]
                transId = Node.getTransId(trans)
                if not biosNode.waitForTransIdOnNode(transId):
                    return False

                # wait for block production handover (essentially a block produced by anyone but eosio).
                lam = lambda: biosNode.getInfo()["head_block_producer"
                                                 ] != "eosio"
                ret = Utils.waitForBool(lam)
                if not ret:
                    Utils.Print("ERROR: Block production handover failed.")
                    return False

            eosioTokenAccount = copy.deepcopy(eosioAccount)
            eosioTokenAccount.name = "eosio.token"
            trans = biosNode.createAccount(eosioTokenAccount, eosioAccount, 0)
            if trans is None:
                Utils.Print("ERROR: Failed to create account %s" %
                            (eosioTokenAccount.name))
                return False

            Node.validateTransaction(trans)
            transId = Node.getTransId(trans)
            biosNode.waitForTransIdOnNode(transId)

            contract = "eosio.token"
            contractDir = "contracts/%s" % (contract)
            wastFile = "contracts/%s/%s.wast" % (contract, contract)
            abiFile = "contracts/%s/%s.abi" % (contract, contract)
            Utils.Print("Publish %s contract" % (contract))
            trans = biosNode.publishContract(eosioTokenAccount.name,
                                             contractDir,
                                             wastFile,
                                             abiFile,
                                             waitForTransBlock=True)
            if trans is None:
                Utils.Print("ERROR: Failed to publish contract %s." %
                            (contract))
                return False

            # Create currency0000, followed by issue currency0000
            contract = eosioTokenAccount.name
            Utils.Print("push create action to %s contract" % (contract))
            action = "create"
            data = "{\"issuer\":\"%s\",\"maximum_supply\":\"1000000000.0000 %s\",\"can_freeze\":\"0\",\"can_recall\":\"0\",\"can_whitelist\":\"0\"}" % (
                eosioTokenAccount.name, CORE_SYMBOL)
            opts = "--permission %s@active" % (contract)
            trans = biosNode.pushMessage(contract, action, data, opts)
            if trans is None or not trans[0]:
                Utils.Print(
                    "ERROR: Failed to push create action to eosio contract.")
                return False

            Node.validateTransaction(trans[1])
            transId = Node.getTransId(trans[1])
            biosNode.waitForTransIdOnNode(transId)

            contract = eosioTokenAccount.name
            Utils.Print("push issue action to %s contract" % (contract))
            action = "issue"
            data = "{\"to\":\"%s\",\"quantity\":\"1000000000.0000 %s\",\"memo\":\"initial issue\"}" % (
                eosioAccount.name, CORE_SYMBOL)
            opts = "--permission %s@active" % (contract)
            trans = biosNode.pushMessage(contract, action, data, opts)
            if trans is None or not trans[0]:
                Utils.Print(
                    "ERROR: Failed to push issue action to eosio contract.")
                return False

            Node.validateTransaction(trans[1])
            Utils.Print(
                "Wait for issue action transaction to become finalized.")
            transId = Node.getTransId(trans[1])
            biosNode.waitForTransIdOnNode(transId)

            expectedAmount = "1000000000.0000 {0}".format(CORE_SYMBOL)
            Utils.Print("Verify eosio issue, Expected: %s" % (expectedAmount))
            actualAmount = biosNode.getAccountEosBalanceStr(eosioAccount.name)
            if expectedAmount != actualAmount:
                Utils.Print(
                    "ERROR: Issue verification failed. Excepted %s, actual: %s"
                    % (expectedAmount, actualAmount))
                return False

            contract = "eosio.system"
            contractDir = "contracts/%s" % (contract)
            wastFile = "contracts/%s/%s.wast" % (contract, contract)
            abiFile = "contracts/%s/%s.abi" % (contract, contract)
            Utils.Print("Publish %s contract" % (contract))
            trans = biosNode.publishContract(eosioAccount.name,
                                             contractDir,
                                             wastFile,
                                             abiFile,
                                             waitForTransBlock=True)
            if trans is None:
                Utils.Print("ERROR: Failed to publish contract %s." %
                            (contract))
                return False

            Node.validateTransaction(trans)

            initialFunds = "1000000.0000 {0}".format(CORE_SYMBOL)
            Utils.Print("Transfer initial fund %s to individual accounts." %
                        (initialFunds))
            trans = None
            contract = eosioTokenAccount.name
            action = "transfer"
            for name, keys in producerKeys.items():
                data = "{\"from\":\"%s\",\"to\":\"%s\",\"quantity\":\"%s\",\"memo\":\"%s\"}" % (
                    eosioAccount.name, name, initialFunds, "init transfer")
                opts = "--permission %s@active" % (eosioAccount.name)
                trans = biosNode.pushMessage(contract, action, data, opts)
                if trans is None or not trans[0]:
                    Utils.Print(
                        "ERROR: Failed to transfer funds from %s to %s." %
                        (eosioTokenAccount.name, name))
                    return False

                Node.validateTransaction(trans[1])

            Utils.Print(
                "Wait for last transfer transaction to become finalized.")
            transId = Node.getTransId(trans[1])
            if not biosNode.waitForTransIdOnNode(transId):
                return False

            Utils.Print("Cluster bootstrap done.")
        finally:
            if not dontKill:
                walletMgr.killall()
                walletMgr.cleanup()

        return True