def __init__(self, walletd=False, localCluster=True, host="localhost", port=8888, walletHost="localhost", walletPort=9899, enableMongo=False , mongoHost="localhost", mongoPort=27017, mongoDb="EOStest", defproduceraPrvtKey=None, defproducerbPrvtKey=None, staging=False): """Cluster container. walletd [True|False] Is wallet keosd running. If not load the wallet plugin localCluster [True|False] Is cluster local to host. host: eos server host port: eos server port walletHost: eos wallet host walletPort: wos wallet port enableMongo: Include mongoDb support, configures eos mongo plugin mongoHost: MongoDB host mongoPort: MongoDB port defproduceraPrvtKey: Defproducera account private key defproducerbPrvtKey: Defproducerb account private key """ self.accounts={} self.nodes={} self.localCluster=localCluster self.wallet=None self.walletd=walletd self.enableMongo=enableMongo self.mongoHost=mongoHost self.mongoPort=mongoPort self.mongoDb=mongoDb self.walletMgr=None self.host=host self.port=port self.walletHost=walletHost self.walletPort=walletPort self.walletEndpointArgs="" if self.walletd: self.walletEndpointArgs += " --wallet-url http://%s:%d" % (self.walletHost, self.walletPort) self.mongoEndpointArgs="" self.mongoUri="" if self.enableMongo: self.mongoUri="mongodb://%s:%d/%s" % (mongoHost, mongoPort, mongoDb) self.mongoEndpointArgs += "--host %s --port %d %s" % (mongoHost, mongoPort, mongoDb) self.staging=staging # init accounts self.defProducerAccounts={} self.defproduceraAccount=self.defProducerAccounts["defproducera"]= Account("defproducera") self.defproducerbAccount=self.defProducerAccounts["defproducerb"]= Account("defproducerb") self.eosioAccount=self.defProducerAccounts["eosio"]= Account("eosio") self.defproduceraAccount.ownerPrivateKey=defproduceraPrvtKey self.defproduceraAccount.activePrivateKey=defproduceraPrvtKey self.defproducerbAccount.ownerPrivateKey=defproducerbPrvtKey self.defproducerbAccount.activePrivateKey=defproducerbPrvtKey
def createAccountKeys(count): accounts=[] p = re.compile('Private key: (.+)\nPublic key: (.+)\n', re.MULTILINE) for _ in range(0, count): try: cmd="%s create key" % (Utils.EosClientPath) if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) keyStr=Utils.checkOutput(cmd.split()) m=p.search(keyStr) if m is None: Utils.Print("ERROR: Owner key creation regex mismatch") break ownerPrivate=m.group(1) ownerPublic=m.group(2) cmd="%s create key" % (Utils.EosClientPath) if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) keyStr=Utils.checkOutput(cmd.split()) m=p.match(keyStr) if m is None: Utils.Print("ERROR: Active key creation regex mismatch") break activePrivate=m.group(1) activePublic=m.group(2) name=''.join(random.choice(string.ascii_lowercase) for _ in range(12)) account=Account(name) account.ownerPrivateKey=ownerPrivate account.ownerPublicKey=ownerPublic account.activePrivateKey=activePrivate account.activePublicKey=activePublic accounts.append(account) if Utils.Debug: Utils.Print("name: %s, key(owner): ['%s', '%s], key(active): ['%s', '%s']" % (name, ownerPublic, ownerPrivate, activePublic, activePrivate)) except subprocess.CalledProcessError as ex: msg=ex.output.decode("utf-8") Utils.Print("ERROR: Exception during key creation. %s" % (msg)) break if count != len(accounts): Utils.Print("Account keys creation failed. Expected %d, actual: %d" % (count, len(accounts))) return None return accounts
def createAccountKeys(count): accounts = [] p = re.compile('Private key: (.+)\nPublic key: (.+)\n', re.MULTILINE) for _ in range(0, count): try: cmd = "%s create key" % (Utils.EnuClientPath) if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) keyStr = Utils.checkOutput(cmd.split()) m = p.search(keyStr) if m is None: Utils.Print("ERROR: Owner key creation regex mismatch") break ownerPrivate = m.group(1) ownerPublic = m.group(2) cmd = "%s create key" % (Utils.EnuClientPath) if Utils.Debug: Utils.Print("cmd: %s" % (cmd)) keyStr = Utils.checkOutput(cmd.split()) m = p.match(keyStr) if m is None: Utils.Print("ERROR: Active key creation regex mismatch") break activePrivate = m.group(1) activePublic = m.group(2) name = ''.join( random.choice(string.ascii_lowercase) for _ in range(12)) account = Account(name) account.ownerPrivateKey = ownerPrivate account.ownerPublicKey = ownerPublic account.activePrivateKey = activePrivate account.activePublicKey = activePublic accounts.append(account) if Utils.Debug: Utils.Print( "name: %s, key(owner): ['%s', '%s], key(active): ['%s', '%s']" % (name, ownerPublic, ownerPrivate, activePublic, activePrivate)) except subprocess.CalledProcessError as ex: msg = ex.output.decode("utf-8") Utils.Print("ERROR: Exception during key creation. %s" % (msg)) break if count != len(accounts): Utils.Print( "Account keys creation failed. Expected %d, actual: %d" % (count, len(accounts))) return None return accounts
def launch(self, pnodes=1, totalNodes=1, prodCount=1, topo="mesh", p2pPlugin="net", delay=1, onlyBios=False, dontKill=False , dontBootstrap=False, totalProducers=None, extraNodeosArgs=None): """Launch cluster. pnodes: producer nodes count totalNodes: producer + non-producer nodes count prodCount: producers per prodcuer node count topo: cluster topology (as defined by launcher) delay: delay between individual nodes launch (as defined by launcher) delay 0 exposes a bootstrap bug where producer handover may have a large gap confusing nodes and bringing system to a halt. """ if not self.localCluster: Utils.Print("WARNING: Cluster not local, not launching %s." % (Utils.EosServerName)) return True if len(self.nodes) > 0: raise RuntimeError("Cluster already running.") producerFlag="" if totalProducers: assert(isinstance(totalProducers, (str,int))) producerFlag="--producers %s" % (totalProducers) if not Cluster.arePortsAvailable(set(range(self.port, self.port+totalNodes+1))): Utils.Print("ERROR: Another process is listening on nodeos default port.") return False cmd="%s -p %s -n %s -s %s -d %s -i %s -f --p2p-plugin %s %s" % ( Utils.EosLauncherPath, pnodes, totalNodes, topo, delay, datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3], p2pPlugin, producerFlag) cmdArr=cmd.split() if self.staging: cmdArr.append("--nogen") nodeosArgs="--max-transaction-time 50000 --abi-serializer-max-time-ms 990000 --filter-on * --p2p-max-nodes-per-host %d" % (totalNodes) if not self.walletd: nodeosArgs += " --plugin eosio::wallet_api_plugin" if self.enableMongo: nodeosArgs += " --plugin eosio::mongo_db_plugin --mongodb-wipe --delete-all-blocks --mongodb-uri %s" % self.mongoUri if extraNodeosArgs is not None: assert(isinstance(extraNodeosArgs, str)) nodeosArgs += extraNodeosArgs if Utils.Debug: nodeosArgs += " --contracts-console" if nodeosArgs: cmdArr.append("--nodeos") cmdArr.append(nodeosArgs) s=" ".join(cmdArr) if Utils.Debug: Utils.Print("cmd: %s" % (s)) if 0 != subprocess.call(cmdArr): Utils.Print("ERROR: Launcher failed to launch.") return False self.nodes=list(range(totalNodes)) # placeholder for cleanup purposes only nodes=self.discoverLocalNodes(totalNodes, timeout=Utils.systemWaitTimeout) if nodes is None or totalNodes != len(nodes): Utils.Print("ERROR: Unable to validate %s instances, expected: %d, actual: %d" % (Utils.EosServerName, totalNodes, len(nodes))) return False self.nodes=nodes if onlyBios: biosNode=Node(Cluster.__BiosHost, Cluster.__BiosPort) biosNode.setWalletEndpointArgs(self.walletEndpointArgs) if not biosNode.checkPulse(): Utils.Print("ERROR: Bios node doesn't appear to be running...") return False self.nodes=[biosNode] # ensure cluster node are inter-connected by ensuring everyone has block 1 Utils.Print("Cluster viability smoke test. Validate every cluster node has block 1. ") if not self.waitOnClusterBlockNumSync(1): Utils.Print("ERROR: Cluster doesn't seem to be in sync. Some nodes missing block 1") return False if dontBootstrap: Utils.Print("Skipping bootstrap.") return True Utils.Print("Bootstrap cluster.") self.biosNode=Cluster.bootstrap(totalNodes, prodCount, Cluster.__BiosHost, Cluster.__BiosPort, dontKill, onlyBios) if self.biosNode is None: Utils.Print("ERROR: Bootstrap failed.") return False # validate iniX accounts can be retrieved producerKeys=Cluster.parseClusterKeys(totalNodes) if producerKeys is None: Utils.Print("ERROR: Unable to parse cluster info") return False def initAccountKeys(account, keys): account.ownerPrivateKey=keys["private"] account.ownerPublicKey=keys["public"] account.activePrivateKey=keys["private"] account.activePublicKey=keys["public"] for name,_ in producerKeys.items(): account=Account(name) initAccountKeys(account, producerKeys[name]) self.defProducerAccounts[name] = account self.eosioAccount=self.defProducerAccounts["eosio"] self.defproduceraAccount=self.defProducerAccounts["defproducera"] self.defproducerbAccount=self.defProducerAccounts["defproducerb"] return True
def bootstrap(totalNodes, prodCount, biosHost, biosPort, dontKill=False, onlyBios=False): """Create 'prodCount' init accounts and deposits 10000000000 SYS 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 None 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 None walletMgr=WalletMgr(True) walletMgr.killall() walletMgr.cleanup() if not walletMgr.launch(): Utils.Print("ERROR: Failed to launch bootstrap wallet.") return None biosNode.setWalletEndpointArgs(walletMgr.walletEndpointArgs) try: ignWallet=walletMgr.create("ignition") 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 None contract="eosio.bios" contractDir="contracts/%s" % (contract) wasmFile="%s.wasm" % (contract) abiFile="%s.abi" % (contract) Utils.Print("Publish %s contract" % (contract)) trans=biosNode.publishContract(eosioAccount.name, contractDir, wasmFile, abiFile, waitForTransBlock=True) if trans is None: Utils.Print("ERROR: Failed to publish contract %s." % (contract)) return None 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 None Node.validateTransaction(trans) accounts.append(initx) transId=Node.getTransId(trans) if not biosNode.waitForTransInBlock(transId): Utils.Print("ERROR: Failed to validate transaction %s got rolled into a block on server port %d." % (transId, biosNode.port)) return None 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 None 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 None trans=trans[1] transId=Node.getTransId(trans) if not biosNode.waitForTransInBlock(transId): Utils.Print("ERROR: Failed to validate transaction %s got rolled into a block on server port %d." % (transId, biosNode.port)) return None # wait for block production handover (essentially a block produced by anyone but eosio). lam = lambda: biosNode.getInfo(exitOnError=True)["head_block_producer"] != "eosio" ret=Utils.waitForBool(lam) if not ret: Utils.Print("ERROR: Block production handover failed.") return None 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 None eosioRamAccount=copy.deepcopy(eosioAccount) eosioRamAccount.name="eosio.ram" trans=biosNode.createAccount(eosioRamAccount, eosioAccount, 0) if trans is None: Utils.Print("ERROR: Failed to create account %s" % (eosioRamAccount.name)) return None eosioRamfeeAccount=copy.deepcopy(eosioAccount) eosioRamfeeAccount.name="eosio.ramfee" trans=biosNode.createAccount(eosioRamfeeAccount, eosioAccount, 0) if trans is None: Utils.Print("ERROR: Failed to create account %s" % (eosioRamfeeAccount.name)) return None eosioStakeAccount=copy.deepcopy(eosioAccount) eosioStakeAccount.name="eosio.stake" trans=biosNode.createAccount(eosioStakeAccount, eosioAccount, 0) if trans is None: Utils.Print("ERROR: Failed to create account %s" % (eosioStakeAccount.name)) return None Node.validateTransaction(trans) transId=Node.getTransId(trans) if not biosNode.waitForTransInBlock(transId): Utils.Print("ERROR: Failed to validate transaction %s got rolled into a block on server port %d." % (transId, biosNode.port)) return None contract="eosio.token" contractDir="contracts/%s" % (contract) wasmFile="%s.wasm" % (contract) abiFile="%s.abi" % (contract) Utils.Print("Publish %s contract" % (contract)) trans=biosNode.publishContract(eosioTokenAccount.name, contractDir, wasmFile, abiFile, waitForTransBlock=True) if trans is None: Utils.Print("ERROR: Failed to publish contract %s." % (contract)) return None # 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 None Node.validateTransaction(trans[1]) transId=Node.getTransId(trans[1]) if not biosNode.waitForTransInBlock(transId): Utils.Print("ERROR: Failed to validate transaction %s got rolled into a block on server port %d." % (transId, biosNode.port)) return None 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 None Node.validateTransaction(trans[1]) Utils.Print("Wait for issue action transaction to become finalized.") transId=Node.getTransId(trans[1]) # biosNode.waitForTransInBlock(transId) # guesstimating block finalization timeout. Two production rounds of 12 blocks per node, plus 60 seconds buffer timeout = .5 * 12 * 2 * len(producerKeys) + 60 if not biosNode.waitForTransFinalization(transId, timeout=timeout): Utils.Print("ERROR: Failed to validate transaction %s got rolled into a finalized block on server port %d." % (transId, biosNode.port)) return None 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 None contract="eosio.system" contractDir="contracts/%s" % (contract) wasmFile="%s.wasm" % (contract) abiFile="%s.abi" % (contract) Utils.Print("Publish %s contract" % (contract)) trans=biosNode.publishContract(eosioAccount.name, contractDir, wasmFile, abiFile, waitForTransBlock=True) if trans is None: Utils.Print("ERROR: Failed to publish contract %s." % (contract)) return None 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 None Node.validateTransaction(trans[1]) Utils.Print("Wait for last transfer transaction to become finalized.") transId=Node.getTransId(trans[1]) if not biosNode.waitForTransInBlock(transId): Utils.Print("ERROR: Failed to validate transaction %s got rolled into a block on server port %d." % (transId, biosNode.port)) return None Utils.Print("Cluster bootstrap done.") finally: if not dontKill: walletMgr.killall() walletMgr.cleanup() return biosNode
}) producerNodeId = 0 irrNodeId = 1 producerNode = cluster.getNode(producerNodeId) irrNode = cluster.getNode(irrNodeId) # Create delayed transaction to create "generated_transaction_object" cmd = "create account -j picoio sample PICO6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV\ PICO6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV --delay-sec 600 -p picoio" trans = producerNode.processClpicoCmd(cmd, cmd, silentErrors=False) assert trans # Schedule a new producer to trigger new producer schedule for "global_property_object" newProducerAcc = Account("newprod") newProducerAcc.ownerPublicKey = "PICO6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" newProducerAcc.activePublicKey = "PICO6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" producerNode.createAccount(newProducerAcc, cluster.picoioAccount) setProdsStr = '{"schedule": [' setProdsStr += '{"producer_name":' + newProducerAcc.name + ',"block_signing_key":' + newProducerAcc.activePublicKey + '}' setProdsStr += ']}' cmd = "push action -j picoio setprods '{}' -p picoio".format(setProdsStr) trans = producerNode.processClpicoCmd(cmd, cmd, silentErrors=False) assert trans setProdsBlockNum = int(trans["processed"]["block_num"]) # Wait until the block where set prods is executed become irreversible so the producer schedule def isSetProdsBlockNumIrr(): return producerNode.getIrreversibleBlockNum() >= setProdsBlockNum
totalNodes=1, useBiosBootFile=False, loadSystemContract=False, specificExtraNodeosArgs={ 0: ("--plugin eosio::state_history_plugin --trace-history --chain-state-history --disable-replay-opts --state-history-stride 20 --max-retained-history-files 3 " "--state-history-endpoint {} --plugin eosio::net_api_plugin --wasm-runtime eos-vm-jit -l logging.json" ).format(stateHistoryEndpoint) }) producerNodeIndex = 0 producerNode = cluster.getNode(producerNodeIndex) # Create a transaction to create an account Utils.Print("create a new account payloadless from the producer node") payloadlessAcc = Account("payloadless") payloadlessAcc.ownerPublicKey = "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" payloadlessAcc.activePublicKey = "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV" producerNode.createAccount(payloadlessAcc, cluster.eosioAccount) contractDir = "unittests/test-contracts/payloadless" wasmFile = "payloadless.wasm" abiFile = "payloadless.abi" Utils.Print("Publish payloadless contract") trans = producerNode.publishContract(payloadlessAcc, contractDir, wasmFile, abiFile, waitForTransBlock=True) trx = {
def bootstrap(totalNodes, prodCount, biosHost, biosPort, dontKill=False, onlyBios=False): """Create 'prodCount' init accounts and deposits 10000000000 SYS 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) if not biosNode.waitForTransInBlock(transId): Utils.Print("ERROR: Failed to validate transaction %s got rolled into a block on server port %d." % (transId, biosNode.port)) return False 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.waitForTransInBlock(transId): Utils.Print("ERROR: Failed to validate transaction %s got rolled into a block on server port %d." % (transId, biosNode.port)) 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 eosioRamAccount=copy.deepcopy(eosioAccount) eosioRamAccount.name="eosio.ram" trans=biosNode.createAccount(eosioRamAccount, eosioAccount, 0) if trans is None: Utils.Print("ERROR: Failed to create account %s" % (eosioRamAccount.name)) return False eosioRamfeeAccount=copy.deepcopy(eosioAccount) eosioRamfeeAccount.name="eosio.ramfee" trans=biosNode.createAccount(eosioRamfeeAccount, eosioAccount, 0) if trans is None: Utils.Print("ERROR: Failed to create account %s" % (eosioRamfeeAccount.name)) return False eosioStakeAccount=copy.deepcopy(eosioAccount) eosioStakeAccount.name="eosio.stake" trans=biosNode.createAccount(eosioStakeAccount, eosioAccount, 0) if trans is None: Utils.Print("ERROR: Failed to create account %s" % (eosioStakeAccount.name)) return False Node.validateTransaction(trans) transId=Node.getTransId(trans) if not biosNode.waitForTransInBlock(transId): Utils.Print("ERROR: Failed to validate transaction %s got rolled into a block on server port %d." % (transId, biosNode.port)) return False 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]) if not biosNode.waitForTransInBlock(transId): Utils.Print("ERROR: Failed to validate transaction %s got rolled into a block on server port %d." % (transId, biosNode.port)) return False 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.waitForTransInBlock(transId) # guesstimating block finalization timeout. Two production rounds of 12 blocks per node, plus 60 seconds buffer timeout = .5 * 12 * 2 * len(producerKeys) + 60 if not biosNode.waitForTransFinalization(transId, timeout=timeout): Utils.Print("ERROR: Failed to validate transaction %s got rolled into a finalized block on server port %d." % (transId, biosNode.port)) return False 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.waitForTransInBlock(transId): Utils.Print("ERROR: Failed to validate transaction %s got rolled into a block on server port %d." % (transId, biosNode.port)) return False Utils.Print("Cluster bootstrap done.") finally: if not dontKill: walletMgr.killall() walletMgr.cleanup() return True
}) producerNodeId = 0 irrNodeId = 1 producerNode = cluster.getNode(producerNodeId) irrNode = cluster.getNode(irrNodeId) # Create delayed transaction to create "generated_transaction_object" cmd = "create account -j arisen sample RSN7yTxtZr3EKN4S8pE1rrRHjYzXN3SnZCzq77zj4dzwFcrJC97jp\ RSN7yTxtZr3EKN4S8pE1rrRHjYzXN3SnZCzq77zj4dzwFcrJC97jp --delay-sec 600 -p arisen" trans = producerNode.processArisecliCmd(cmd, cmd, silentErrors=False) assert trans # Schedule a new producer to trigger new producer schedule for "global_property_object" newProducerAcc = Account("newprod") newProducerAcc.ownerPublicKey = "RSN7yTxtZr3EKN4S8pE1rrRHjYzXN3SnZCzq77zj4dzwFcrJC97jp" newProducerAcc.activePublicKey = "RSN7yTxtZr3EKN4S8pE1rrRHjYzXN3SnZCzq77zj4dzwFcrJC97jp" producerNode.createAccount(newProducerAcc, cluster.arisenAccount) setProdsStr = '{"schedule": [' setProdsStr += '{"producer_name":' + newProducerAcc.name + ',"block_signing_key":' + newProducerAcc.activePublicKey + '}' setProdsStr += ']}' cmd = "push action -j arisen setprods '{}' -p arisen".format(setProdsStr) trans = producerNode.processArisecliCmd(cmd, cmd, silentErrors=False) assert trans setProdsBlockNum = int(trans["processed"]["block_num"]) # Wait until the block where set prods is executed become irreversible so the producer schedule def isSetProdsBlockNumIrr(): return producerNode.getIrreversibleBlockNum() >= setProdsBlockNum