Skip to content

Commit

Permalink
Merge pull request #31 from aquarius-kuchain/scripts/boot
Browse files Browse the repository at this point in the history
Add a testnet boot script by python
  • Loading branch information
aquarius-kuchain authored Aug 13, 2020
2 parents 4afe04a + 80a552e commit d218adb
Show file tree
Hide file tree
Showing 2 changed files with 307 additions and 1 deletion.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ testchain/
.idea

# Chain testing directories
test_chain/testing
test_chain/testing
scripts/testnet
305 changes: 305 additions & 0 deletions scripts/boot-testnet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,305 @@
#!/usr/bin/env python

import argparse
import json
import os
import subprocess
import sys
import time
import logging
import re
import random

# Keys
testKey = "kuchain1ysggxvhq3aqxp2dnzw8ucqf0hgjn44tqcp7l3s"
testKeyMnemonic = "warm law where bid turtle tenant story logic air ancient gesture way main rabbit sock enlist hollow wealth stereo position fiscal expand mosquito latin"

# Symbols
chainID = 'testing'
mainChainSymbol = 'kuchain'
coreCoinSymbol = 'sys'
coreCoinDenom = '%s/%s' % (mainChainSymbol, coreCoinSymbol)
cliCmd = 'kucli'
nodeCmd = 'kucd'

# auths for test
auths = {}

# node info for test
nodes = {}

logging.basicConfig(level=logging.DEBUG)

args = None

def run(args):
logging.debug('%s', args)
if subprocess.call(args, shell=True):
logging.error('run \"%s\" error, exitting', args)
sys.exit(1)

def sleep(t):
time.sleep(t)

def run_output(args):
logging.debug('%s', args)

try:
out_bytes = subprocess.check_output(args, shell=True)
except subprocess.CalledProcessError as e:
out_bytes = e.output
out_text = out_bytes.decode('utf-8')
code = e.returncode
logging.error('run \"%s\" error by %d and %s', args, code, out_text)
sys.exit(1)

return out_bytes.decode('utf-8')

def cli(cmd):
cliParams = "--home %s/cli/ --keyring-backend test" % (args.home)
return run_output('%s/%s %s %s' % (args.build_path, cliCmd, cliParams, cmd))

def cliByHome(home, cmd):
cliParams = "--home %s" % (home)
return run_output('%s/%s %s %s' % (args.build_path, cliCmd, cliParams, cmd))

def getNodeHomePath(name):
return "%s/nodes/%s/" % (args.home, name)

def node(name, cmd):
cliParams = "--home %s" % (getNodeHomePath(name))
cmdRun = '%s/%s %s %s' % (args.build_path, nodeCmd, cliParams, cmd)
return run_output(cmdRun)

def nodeInBackground(name, logPath, cmd):
cliParams = "--home %s" % (getNodeHomePath(name))
cmdRun = '%s/%s %s %s' % (args.build_path, nodeCmd, cliParams, cmd)

with open(logPath, mode='w') as f:
f.write(cmdRun + '\n')
subprocess.Popen(cmdRun + ' 2>>' + logPath, shell=True)

def nodeByCli(name, cmd):
cliParams = "--home-client %s/cli/ --keyring-backend test" % (args.home)
return node(name, '%s %s' % (cliParams, cmd))

def coreCoin(amt):
return '%s%s' % (amt, coreCoinDenom)

def initWallet():
logging.debug("init wallet")

run('rm -rf %s/cli' % (args.home))

genAuth(mainChainSymbol)
genAuth('test')

return

def genAuth(name):
cli('keys add ' + name)
valAuth = cli('keys show %s -a' % (name))
valAuth = valAuth[:-1]
auths[name] = valAuth
return valAuth

def getAuth(name):
return auths[name]

def getNodeName(num):
return "validator%d" % (num)

def addValidatorToGenesis(name):
valAuth = genAuth(name)
logging.info("add validator %s %s", name, valAuth)

# add to genesis
node(mainChainSymbol, 'genesis add-address %s' % (valAuth))
node(mainChainSymbol, 'genesis add-account %s %s' % (name, valAuth))
node(mainChainSymbol, 'genesis add-account-coin %s %s' % (valAuth, coreCoin(10000000000000)))
node(mainChainSymbol, 'genesis add-account-coin %s %s' % (name, coreCoin(100000000000000000000000000000000)))

def initGenesis(nodeNum):
mainAuth = getAuth(mainChainSymbol)
testAuth = getAuth('test')

node(mainChainSymbol, 'genesis add-address %s' % (mainAuth))
node(mainChainSymbol, 'genesis add-account %s %s' % (mainChainSymbol, mainAuth))
node(mainChainSymbol, 'genesis add-coin %s \"%s\"' % (coreCoin(1000000000000000000000000000000000000000), "main core"))
node(mainChainSymbol, 'genesis add-account-coin %s %s' % (mainAuth, coreCoin(100000000000000000000000000000000)))
node(mainChainSymbol, 'genesis add-account-coin %s %s' % (mainChainSymbol, coreCoin(100000000000000000000000000000000)))

genesisAccounts = ['testacc1', 'testacc2']
for genesisAccount in genesisAccounts:
node(mainChainSymbol, 'genesis add-account %s %s' % (genesisAccount, testAuth))
node(mainChainSymbol, 'genesis add-account-coin %s %s' % (genesisAccount, coreCoin(10000000000000000000000)))

for i in range(0, nodeNum):
addValidatorToGenesis(getNodeName(i + 1))

genTx()

def modifyNodeCfg(name, key, oldValue, newValue=None):
file = "%s/config/config.toml" % (getNodeHomePath(name))

patternStr = r"^%s = .+" % (key)
newStr = '%s = %s' % (key, oldValue)

if (newValue is not None):
patternStr = r"^%s = %s" % (key, oldValue)
newStr = '%s = %s' % (key, newValue)

with open(file, "r") as f1, open("%s.bak" % file, "w") as f2:
for line in f1:
f2.write(re.sub(patternStr, newStr, line))

os.remove(file)
os.rename("%s.bak" % file, file)

def appendNodeCfg(name, key, value):
cliByHome(getNodeHomePath(name), "config %s %s" % (key, value))

def mkNodeDatas(name, num, totalNum):
if name is not mainChainSymbol:
# cp genesis from main node
run('cp %s/config/genesis.json %s/config/genesis.json' % (getNodeHomePath(mainChainSymbol), getNodeHomePath(name)))

# bind ports, use 3XX56, 3XX57 and 3XX58
modifyNodeCfg(name, 'proxy_app', '"tcp://127.0.0.1:26658"', '"tcp://127.0.0.1:3%02d58"' % (num))
modifyNodeCfg(name, 'laddr', '"tcp://127.0.0.1:26657"', '"tcp://127.0.0.1:3%02d57"' % (num))
modifyNodeCfg(name, 'laddr', '"tcp://0.0.0.0:26656"', '"tcp://0.0.0.0:3%02d56"' % (num))

# connect to root and next
toNum = num + 1
if (toNum > totalNum):
toNum = 1

peers = "%[email protected]:26656," % nodes[mainChainSymbol]['nodeID']
peers += "%[email protected]:3%02d56" % (nodes[getNodeName(toNum)]['nodeID'], toNum)

modifyNodeCfg(name, 'persistent_peers', '"%s"' % peers)

modifyNodeCfg(name, 'max_num_outbound_peers', '128')
modifyNodeCfg(name, 'allow_duplicate_ip', 'true')
appendNodeCfg(name, 'chain-id', chainID)
appendNodeCfg(name, 'trust-node', 'true')


def initChain(nodeNum):
logging.debug("init chain")

initNode(mainChainSymbol, 0)
initGenesis(nodeNum)

for i in range(0, nodeNum):
initNode(getNodeName(i + 1), i + 1)

for i in range(0, nodeNum):
mkNodeDatas(getNodeName(i + 1), i + 1, nodeNum)

mkNodeDatas(mainChainSymbol, 0, nodeNum)
return

def genTx():
nodeByCli(mainChainSymbol, 'gentx %s --name %s ' % (getAuth(mainChainSymbol), mainChainSymbol))
node(mainChainSymbol, 'collect-gentxs')

def initNode(name, num):
run('rm -rf %s' % (getNodeHomePath(name)))
node(name, 'init --chain-id %s %s' % (chainID, name))

nodeID = node(name, 'tendermint show-node-id')
logging.info('init node %s, id: %s', name, nodeID)

nodes[name] = {
'name' : name,
'nodeID' : nodeID[:-1],
'num' : num
}

def startChainNode(name):
logPath = '%s/logs/%s.log' % (args.home, name)
run('mkdir -p %s/logs/' % args.home)

bootParams = 'start --log_level "%s"' % (args.log_level)
if( args.trace is not None ):
bootParams += ' --trace'

nodeInBackground(name, logPath, bootParams)

def message(msg, *args):
for arg in args:
print(msg + ' comes from ' + arg)

def tx(fromAcc, cmd, *params):
cmd = 'tx ' + cmd
cmd += (" --yes --chain-id=%s" % chainID)
cmd += (" --from=%s" % fromAcc)
cmd += (" --node=%s" % "tcp://localhost:30157")

if len(params) % 2 is not 0:
logging.error("tx params len should be div by 2")

paramsKVlen = len(params) / 2
for pi in range(0, paramsKVlen):
key = params[pi * 2]
value = params[pi * 2 + 1]
cmd += (" --%s=%s" % (key, value))

logging.debug("run tx: %s", cmd)

cli(cmd)

def createValidator(name):
# create validator
cmd = 'kustaking create-validator %s' % name
tx(name, cmd,
"pubkey", node(name, 'tendermint show-validator')[:-1],
"commission-rate", "0.10",
"moniker", name)

def voteValidator(acc, node, coin):
cmd = 'kustaking delegate %s %s %s' % (acc, node, coin)
tx(acc, cmd)

def regNodes(totalNum):
logging.info("reg nodes")
for i in range(0, totalNum):
createValidator(getNodeName(i + 1))

# wait for create
sleep(5)

for i in range(0, totalNum):
coreCoinBase = 10000000000000000000000000000
randomVoteCoin = "%d" % random.uniform(coreCoinBase * 4 / 5, coreCoinBase - 100)
voteValidator(getNodeName(i + 1), getNodeName(i + 1), coreCoin(randomVoteCoin))



# Parse args
parser = argparse.ArgumentParser()
parser.add_argument('--build-path', metavar='', help='Kuchain build path', default='../build')
parser.add_argument('--home', metavar='', help='testnet data home path', default='./testnet')
parser.add_argument('--trace', action='store_true', help='if --trace to kucd')
parser.add_argument('--log-level', metavar='', help='log level for kucd', default='*:info')
parser.add_argument('--node-num', type=int, metavar='', help='val node number', default=12)

args = parser.parse_args()
logging.debug("args %s", args)

# Start Chain
logging.info("start kuchain testnet by %s to %s", args.home, args.build_path)

initWallet()
initChain(int(args.node_num))

# Start main first
startChainNode(mainChainSymbol)
sleep(1)

for i in range(0, int(args.node_num)):
startChainNode(getNodeName(i + 1))

sleep(5)
regNodes(int(args.node_num))

0 comments on commit d218adb

Please sign in to comment.