From 1979728bdae071327915a222a083497ecb9d38c0 Mon Sep 17 00:00:00 2001 From: starsquidnodes Date: Sun, 22 Oct 2023 22:13:51 +0200 Subject: [PATCH 01/10] Start contract deployment --- .gitignore | 1 + contracts/Dockerfile | 16 +++ contracts/contracts.py | 126 +++++++++++++++++++++++ contracts/params/add_orca_queue.json | 12 +++ contracts/params/add_usk_collateral.json | 15 +++ devbuild.sh | 36 +++++++ kujira.sh | 9 ++ 7 files changed, 215 insertions(+) create mode 100644 .gitignore create mode 100644 contracts/Dockerfile create mode 100755 contracts/contracts.py create mode 100644 contracts/params/add_orca_queue.json create mode 100644 contracts/params/add_usk_collateral.json create mode 100755 devbuild.sh create mode 100755 kujira.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..722d5e7 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vscode diff --git a/contracts/Dockerfile b/contracts/Dockerfile new file mode 100644 index 0000000..7175d80 --- /dev/null +++ b/contracts/Dockerfile @@ -0,0 +1,16 @@ +ARG kujira_version +FROM teamkujira/kujirad:${kujira_version} + +RUN apt-get update && \ + apt-get install -y --no-install-recommends python3 && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +COPY contracts.py /usr/local/bin/ + +RUN chmod +x /usr/local/bin/* + +WORKDIR /tmp + +ENTRYPOINT ["contracts.py"] + diff --git a/contracts/contracts.py b/contracts/contracts.py new file mode 100755 index 0000000..02e0930 --- /dev/null +++ b/contracts/contracts.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python3 + +import argparse +import requests +import base64 +import subprocess +import json +import hashlib + + +class Chain: + def __init__(self, binary, chain_id): + self.binary = binary + self.chain_id = chain_id + # self.mnemonic = mnemonic + + # self.add_key() + + # get address + result = subprocess.run([ + binary, "keys", "show", "validator", "-a" + ], text=True, capture_output=True) + + self.address = result.stdout + + def add_key(self): + cmd = [ + self.binary, "--home", "/Users/christian/.pond/kujira01", + "keys", "add", "validator", "--recover", "--keyring-backend", "test" + ] + + print(" ".join(cmd)) + + result = subprocess.run( + cmd, text=True, input=self.mnemonic, capture_output=True + ) + + print(result.stderr) + print(result.stdout) + + def q(self, args): + cmd = [self.binary, "--home", "/Users/christian/.pond/kujira01", "q"] + args.split() + [ + "--node", "http://127.0.0.1:10157", + "--chain-id", self.chain_id, "--output", "json" + ] + result = subprocess.run(cmd, capture_output=True, text=True) + + return result.stdout + + def tx(self, args): + cmd = [self.binary, "--home", "/Users/christian/.pond/kujira01", "tx"] + args.split() + [ + "--node", "http://127.0.0.1:10157", + "--chain-id", self.chain_id, "--output", "json", + "--from", "validator", "--keyring-backend", "test", + "--gas", "auto", "--gas-adjustment", "2", "--yes" + ] + print(" ".join(cmd)) + result = subprocess.run(cmd, capture_output=True, text=True) + + print(result.stderr) + print(result.stdout) + + return result.stdout + + def create_denom(self, denom): + self.tx(f"denom create-denom {denom}") + + def add_orca_queue(self, usk, denom): + params = { + "bid_denom": f"factory/{self.address}/uusk", + "bid_threshold": "10000000000", + "collateral_denom": "factory/{self.address}/usquid", + "fee_address": "kujira17xpfvakm2amg962yls6f84z3kell8c5lp3pcxh", + "liquidation_fee": "0.01", + "max_slot": 30, + "owner": self.address, + "premium_rate_per_slot": "0.01", + "waiting_period": 600, + "withdrawal_fee": "0.005" + } + + +def parse_args(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--rpc", default="https://rest.cosmos.directory/kujira") + return parser.parse_args() + + +def main(): + args = parse_args() + + kujira = Chain( + "kujirad-v0.8.8-43-gc5a82f3", "pond-1") + + contracts = { + "usk_market": [73], + } + + # for name, ids in contracts.items(): + # for id in ids: + # url = f"{args.rpc}/cosmwasm/wasm/v1/code/{id}" + # print(url) + # response = requests.get(url) + + # if response.status_code != 200: + # raise f"response status: {response.status_code}" + + # data = response.json().get("data") + # if not data: + # raise "data is None" + + # bz = base64.b64decode(data) + + # open(f"{id}.wasm", "wb").write(bz) + + # print(hashlib.sha256(bz).hexdigest()) + + # # print(kujira.tx(f"wasm stor1 {id}.wasm")) + # print(kujira.q(f"wasm code-info 1")) + + kujira.create_denom("ufoo") + + +if __name__ == "__main__": + main() diff --git a/contracts/params/add_orca_queue.json b/contracts/params/add_orca_queue.json new file mode 100644 index 0000000..42ba92d --- /dev/null +++ b/contracts/params/add_orca_queue.json @@ -0,0 +1,12 @@ +{ + "bid_denom": "factory/kujira1qk00h5atutpsv900x202pxx42npjr9thg58dnqpa72f2p7m2luase444a7/uusk", + "bid_threshold": "10000000000", + "collateral_denom": "ibc/4F393C3FCA4190C0A6756CE7F6D897D5D1BE57D6CCB80D0BC87393566A7B6602", + "fee_address": "kujira17xpfvakm2amg962yls6f84z3kell8c5lp3pcxh", + "liquidation_fee": "0.01", + "max_slot": 30, + "owner": "kujira1tsekaqv9vmem0zwskmf90gpf0twl6k57e8vdnq", + "premium_rate_per_slot": "0.01", + "waiting_period": 600, + "withdrawal_fee": "0.005" +} \ No newline at end of file diff --git a/contracts/params/add_usk_collateral.json b/contracts/params/add_usk_collateral.json new file mode 100644 index 0000000..2659904 --- /dev/null +++ b/contracts/params/add_usk_collateral.json @@ -0,0 +1,15 @@ +{ + "owner": "kujira1knlrgd8l99sz7lyzsp4lkp5gaduak50rmhnp7s", + "stable_denom": "factory/kujira1knlrgd8l99sz7lyzsp4lkp5gaduak50rmhnp7s/uusk", + "stable_denom_admin": "kujira1qk00h5atutpsv900x202pxx42npjr9thg58dnqpa72f2p7m2luase444a7", + "collateral_denom": "ibc/A7A5C44AA67317F1B3FFB27BAFC89C9CC04F61306F6F834F89A74B8F82D252A1", + "collateral_denom_decimal_delta": 0, + "oracle_denom": "SOMM", + "max_ratio": "0.5", + "mint_fee": "0.001", + "interest_rate": "0.01", + "orca_address": "kujira1tsekaqv9vmem0zwskmf90gpf0twl6k57e8vdnq", + "max_debt": "250000000000", + "liquidation_threshold": "1000000000", + "liquidation_ratio": "0.1" +} \ No newline at end of file diff --git a/devbuild.sh b/devbuild.sh new file mode 100755 index 0000000..0c37623 --- /dev/null +++ b/devbuild.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +action=build +if [ $# -eq 1 ] && [ "$1" == "manifest" ]; then + action=manifest +fi + +if [ -n "$(which docker)" ]; then + cmd=docker +elif [ -n "$(which podman)" ]; then + cmd=podman +else + exit 1 +fi + +cmd=podman + +arch=$(arch) + +# contracts +kujira_version=v0.9.0 +tag=starsquid/contracts:${kujira_version} + +if [ "$action" == "build" ]; then + $cmd build \ + --tag ${tag}-${arch} \ + --build-arg kujira_version=${kujira_version} \ + contracts + + # $cmd push $tag-${arch} +fi + +if [ "$action" == "manifest" ]; then + $cmd manifest create ${tag} ${tag}-x86_64 ${tag}-arm64 + $cmd manifest push ${tag} +fi diff --git a/kujira.sh b/kujira.sh new file mode 100755 index 0000000..8cd8564 --- /dev/null +++ b/kujira.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +if [ "$1" == "tx" ]; then + extra="--from validator --keyring-backend test --gas auto --gas-adjustment 2" +fi + +kujirad-v0.8.8-43-gc5a82f3 \ + --node http://localhost:10157 $@ \ + --home /tmp/pond --chain-id pond-1 $extra From 05aaaba3082ff11fe74394431b6fe8e159e1468a Mon Sep 17 00:00:00 2001 From: starsquidnodes Date: Tue, 31 Oct 2023 18:02:38 +0100 Subject: [PATCH 02/10] Batch transactions, add instantiation for fin --- contracts/contracts.py | 221 ++++++++++++++++++++++++++++++++--------- 1 file changed, 173 insertions(+), 48 deletions(-) diff --git a/contracts/contracts.py b/contracts/contracts.py index 02e0930..3adb9d6 100755 --- a/contracts/contracts.py +++ b/contracts/contracts.py @@ -6,37 +6,34 @@ import subprocess import json import hashlib +import time +import logging +import sys class Chain: def __init__(self, binary, chain_id): self.binary = binary self.chain_id = chain_id - # self.mnemonic = mnemonic - # self.add_key() + self.accounts = {} + self.denoms = {} + self.contracts = {} # get address result = subprocess.run([ - binary, "keys", "show", "validator", "-a" + binary, "keys", "show", "validator", "-a", "--keyring-backend", "test", "--home", "/Users/christian/.pond/kujira01" ], text=True, capture_output=True) - self.address = result.stdout + self.address = result.stdout.strip() - def add_key(self): - cmd = [ - self.binary, "--home", "/Users/christian/.pond/kujira01", - "keys", "add", "validator", "--recover", "--keyring-backend", "test" - ] - - print(" ".join(cmd)) - - result = subprocess.run( - cmd, text=True, input=self.mnemonic, capture_output=True - ) + result = self.q("auth accounts") + for account in result["accounts"]: + name = account.get("name") + if not name: + continue - print(result.stderr) - print(result.stdout) + self.accounts[name] = account["base_account"]["address"] def q(self, args): cmd = [self.binary, "--home", "/Users/christian/.pond/kujira01", "q"] + args.split() + [ @@ -45,32 +42,98 @@ def q(self, args): ] result = subprocess.run(cmd, capture_output=True, text=True) - return result.stdout + if result.returncode == 0: + return json.loads(result.stdout) + else: + print(result.stderr) + return None def tx(self, args): + time.sleep(8) cmd = [self.binary, "--home", "/Users/christian/.pond/kujira01", "tx"] + args.split() + [ "--node", "http://127.0.0.1:10157", "--chain-id", self.chain_id, "--output", "json", "--from", "validator", "--keyring-backend", "test", - "--gas", "auto", "--gas-adjustment", "2", "--yes" + "--gas", "auto", "--gas-adjustment", "2", "--yes", + "-b", "async" ] - print(" ".join(cmd)) result = subprocess.run(cmd, capture_output=True, text=True) - print(result.stderr) - print(result.stdout) + if result.returncode != 0: + print(result.stderr) + print(result.stdout) + return None - return result.stdout + return json.loads(result.stdout) + + def wait_for(self, tx, timeout=10): + print(f"wait for tx: {tx}") + result = None + while result == None and timeout > 0: + print(timeout) + time.sleep(1) + timeout -= 1 + result = self.q(f"tx {tx}") + + # if result.returncode != 0: + # print(result) def create_denom(self, denom): - self.tx(f"denom create-denom {denom}") + logging.info(f"create {denom}") + + path = f"factory/{self.address}/u{denom}".lower() + self.denoms[path] = denom - def add_orca_queue(self, usk, denom): + return { + "@type": "/kujira.denom.MsgCreateDenom", + "sender": self.address, + "nonce": f"u{denom}".lower() + } + + def instantiate_fin_contract(self, denom1, denom2, precision=4, delta=0): + logging.info(f"Instantiate Fin pair {denom1}/{denom2}") + + path1 = "" + path2 = "" + for path, denom in self.denoms.items(): + if denom1 == denom: + path1 = path + if denom2 == denom: + path2 = path + + code_id = 2 + label = f"FIN pair {denom1}/{denom2}" + + return { + "@type": "/cosmwasm.wasm.v1.MsgInstantiateContract", + "sender": self.address, + "admin": self.address, + "code_id": f"{code_id}", + "label": label, + "msg": { + "owner": self.address, + "denoms": [ + {"native": path1}, + {"native": path2} + ], + "price_precision": { + "decimal_places": 4 + }, + "decimal_delta": 0, + "fee_taker": "0.0015", + "fee_maker": "0.00075" + }, + "funds": [] + } + + def instantiate_orca_queue(self, source, collateral, denom): params = { - "bid_denom": f"factory/{self.address}/uusk", + # "bid_denom": f"factory/{self.address}/uusk", + "bid_denom": denom, "bid_threshold": "10000000000", - "collateral_denom": "factory/{self.address}/usquid", - "fee_address": "kujira17xpfvakm2amg962yls6f84z3kell8c5lp3pcxh", + # "collateral_denom": f"factory/{self.address}/usquid", + "collateral_denom": collateral, + "fee_address": self.accounts["fee_collector"], "liquidation_fee": "0.01", "max_slot": 30, "owner": self.address, @@ -79,11 +142,49 @@ def add_orca_queue(self, usk, denom): "withdrawal_fee": "0.005" } + def send(self, messages): + tx = { + "body": { + "messages": messages, + "memo": "", + "timeout_height": "0", + "extension_options": [], + "non_critical_extension_options": [] + }, + "auth_info": { + "signer_infos": [], + "fee": { + "amount": [], + "gas_limit": "1000000000", + "payer": "", + "granter": "" + }, + "tip": None + }, + "signatures": [] + } + + tx_file = "/tmp/tx.json" + + open(tx_file, "w").write(json.dumps(tx)) + + result = self.tx(f"sign {tx_file}") + + if not result: + return + + open(f"{tx_file}.signed", "w").write(json.dumps(result)) + + result = self.tx(f"broadcast {tx_file}.signed") + + self.wait_for(result["txhash"]) + def parse_args(): parser = argparse.ArgumentParser() parser.add_argument( - "--rpc", default="https://rest.cosmos.directory/kujira") + "--rpc", default="https://api-kujira.starsquid.io") + # "--rpc", default="https://rest.cosmos.directory/kujira") return parser.parse_args() @@ -93,33 +194,57 @@ def main(): kujira = Chain( "kujirad-v0.8.8-43-gc5a82f3", "pond-1") - contracts = { - "usk_market": [73], - } + contracts = [{ + "name": "usk_market", + "id": 73 + }, { + "name": "fin", + "id": 134 + }] + + result = kujira.q("wasm list-codes") + if result["code_infos"]: + # contracts already deployed, exit + sys.exit(0) + + messages = [] + + for contract in contracts: + id = contract["id"] + url = f"{args.rpc}/cosmwasm/wasm/v1/code/{id}" + response = requests.get(url) + + print(url) + + if response.status_code != 200: + print(f"response status: {response.status_code}") + sys.exit(1) - # for name, ids in contracts.items(): - # for id in ids: - # url = f"{args.rpc}/cosmwasm/wasm/v1/code/{id}" - # print(url) - # response = requests.get(url) + data = response.json().get("data") + if not data: + raise "data is None" - # if response.status_code != 200: - # raise f"response status: {response.status_code}" + bz = base64.b64decode(data) - # data = response.json().get("data") - # if not data: - # raise "data is None" + messages.append({ + "@type": "/cosmwasm.wasm.v1.MsgStoreCode", + "sender": kujira.address, + "wasm_byte_code": data, + "instantiate_permission": None + }) - # bz = base64.b64decode(data) + for denom in ["USK", "SQUID"]: + messages.append(kujira.create_denom(denom)) - # open(f"{id}.wasm", "wb").write(bz) + print("Deploy contracts") + # kujira.send(messages) - # print(hashlib.sha256(bz).hexdigest()) + print(kujira.denoms) - # # print(kujira.tx(f"wasm stor1 {id}.wasm")) - # print(kujira.q(f"wasm code-info 1")) + messages = [kujira.instantiate_fin_contract("SQUID", "USK")] - kujira.create_denom("ufoo") + print("Instantiate contracts") + kujira.send(messages) if __name__ == "__main__": From 260beea666e74a3491bb28520d06b89bb498348a Mon Sep 17 00:00:00 2001 From: starsquidnodes Date: Fri, 10 Nov 2023 15:52:17 +0100 Subject: [PATCH 03/10] Move start/stop handling into pond --- prepare/prepare.py | 37 ++++++++++++--------------------- prepare/templates/start.sh.j2 | 39 ----------------------------------- prepare/templates/stop.sh.j2 | 21 ------------------- 3 files changed, 13 insertions(+), 84 deletions(-) delete mode 100644 prepare/templates/start.sh.j2 delete mode 100644 prepare/templates/stop.sh.j2 diff --git a/prepare/prepare.py b/prepare/prepare.py index 9c662d0..72737f0 100644 --- a/prepare/prepare.py +++ b/prepare/prepare.py @@ -39,6 +39,7 @@ def __init__(self, name, chain_id, denom, num_validators, port_prefix, podman): info, gentx = self.prepare_gentxs(chain_id, home) info["rpc_port"] = f"{self.port_prefix}{i:02}57" + info["api_port"] = f"{self.port_prefix}{i:02}17" self.validators.append(info) gentxs.append(gentx) @@ -227,30 +228,19 @@ def main(): if not os.path.isdir(WORKDIR): os.mkdir(WORKDIR) + config = { + "command": "docker", + "chains": {} + } + + if args.podman: + config["command"] = "podman" + chains = [ Chain("Kujira", "pond-1", "ukuji", args.nodes, 1, args.podman), # Chain("Faker", "faker-1", "ufake", 1, 2) ] - start = jinja2.Template(open("templates/start.sh.j2", "r").read()) - open(f"{WORKDIR}/start.sh", "w").write( - start.render({ - "podman": args.podman, - "chains": chains - }) - ) - - stop = jinja2.Template(open("templates/stop.sh.j2", "r").read()) - open(f"{WORKDIR}/stop.sh", "w").write( - stop.render({ - "podman": args.podman, - "chains": chains - }) - ) - - info = { - "chains": {} - } for chain in chains: chain_info = { "name": chain.name, @@ -259,17 +249,16 @@ def main(): for validator in chain.validators: validator["rpc_url"] = f"http://localhost:{validator['rpc_port']}" + validator["api_url"] = f"http://localhost:{validator['api_port']}" validator.pop("rpc_port") + validator.pop("api_port") validator.pop("amount") chain_info["validators"].append(validator) - - info["chains"][chain.chain_id] = chain_info - json.dump(info, open(f"{WORKDIR}/info.json", "w")) + config["chains"][chain.chain_id] = chain_info - os.chmod(f"{WORKDIR}/start.sh", 0o755) - os.chmod(f"{WORKDIR}/stop.sh", 0o755) + json.dump(config, open(f"{WORKDIR}/pond.json", "w")) if __name__ == "__main__": diff --git a/prepare/templates/start.sh.j2 b/prepare/templates/start.sh.j2 deleted file mode 100644 index 8707062..0000000 --- a/prepare/templates/start.sh.j2 +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash - -cd $(dirname $0) - -{% if podman -%} -podman pod rm --force pond -podman pod create --name pond{% for chain in chains %}{% for validator in chain.validators %} -p {{ validator.rpc_port }}:{{ validator.rpc_port }}{% endfor %}{% endfor %} -{% else -%} -docker network rm pond -docker network create pond -{% endif -%} -{% for chain in chains -%} -{% for validator in chain.validators -%} -{% set port = validator.rpc_port %} -{% set name = validator.moniker | lower -%} -{% if podman %} -podman run --name {{ name }} -d --pod pond -v ./{{ name }}:/kujira teamkujira/kujirad:v0.9.0 kujirad --home /kujira start -{% else %} -docker rm {{ name }} -docker run -e USER=$UID -dp 127.0.0.1:{{ port }}:{{ port }} --network pond --name {{ name }} --network-alias {{ name }} -v ./{{ name }}:/kujira teamkujira/kujirad:v0.9.0 kujirad --home /kujira start -{% endif %} -{% endfor -%} -{% endfor %} -echo "waiting for chain(s) to start" -sleep 5 - -{% for chain in chains -%} -{% if chain.name == "Kujira" -%} -{% for index in range(chain.validators | length) -%} -{% set name = "feeder%02d" % (index + 1) -%} -{% if podman %} -podman run --name {{ name }} -d --pod pond -v ./{{ name }}:/feeder -e "PRICE_FEEDER_MNEMONIC={{ chain.validators[index].mnemonic }}" teamkujira/feeder:next -{% else %} -docker rm {{ name }} -docker run -e USER=$UID -d --network pond --network-alias {{ name }} --name {{ name }} -v ./{{ name }}:/feeder -e "PRICE_FEEDER_MNEMONIC={{ chain.validators[index].mnemonic }}" teamkujira/feeder:next -{% endif %} -{% endfor -%} -{% endif -%} -{% endfor %} diff --git a/prepare/templates/stop.sh.j2 b/prepare/templates/stop.sh.j2 deleted file mode 100644 index 534c389..0000000 --- a/prepare/templates/stop.sh.j2 +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -cd $(dirname $0) - -{% for chain in chains -%} -{% for index in range(chain.validators | length) -%} -{% set name = chain.validators[index].moniker | lower -%} -{% if podman %} -{% set command = "podman" %} -{% else %} -{% set command = "docker" %} -{% endif %} -{{ command }} kill {{ name }} -{% if chain.name == "Kujira" -%} -{{ command }} kill {{ "feeder%02d" % (index + 1) }} -{% endif %} -{% endfor -%} -{% endfor %} -{% if podman %} -podman pod kill pond -{% endif %} \ No newline at end of file From 0de7a6ce502a8290158c29ba87b49d752b43a179 Mon Sep 17 00:00:00 2001 From: starsquidnodes Date: Fri, 10 Nov 2023 15:53:58 +0100 Subject: [PATCH 04/10] Print available contracts --- contracts/contracts.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/contracts/contracts.py b/contracts/contracts.py index 3adb9d6..2fb7268 100755 --- a/contracts/contracts.py +++ b/contracts/contracts.py @@ -179,6 +179,19 @@ def send(self, messages): self.wait_for(result["txhash"]) + def get_contracts(self): + contracts = {} + result = self.q("wasm list-codes") + for index in range(len(result["code_infos"])): + id = index + 1 + contracts[id] = {} + result = self.q(f"wasm list-contract-by-code {id}") + for contract in result["contracts"]: + result = self.q(f"wasm contract {contract}") + contracts[id][contract] = result["contract_info"]["label"] + + print(json.dumps(contracts, indent=2)) + def parse_args(): parser = argparse.ArgumentParser() @@ -202,6 +215,8 @@ def main(): "id": 134 }] + kujira.get_contracts() + result = kujira.q("wasm list-codes") if result["code_infos"]: # contracts already deployed, exit From 97891af78dec1369b2d8b049c58f4791257b4d4c Mon Sep 17 00:00:00 2001 From: starsquidnodes Date: Mon, 27 Nov 2023 13:43:58 +0100 Subject: [PATCH 05/10] Rework Dockerfiles, build script --- build.py | 136 ++++++++++++++++++ build.sh | 76 ---------- devbuild.sh | 36 ----- kujira.sh | 9 -- {kujirad => kujira}/Dockerfile | 0 {kujirad => kujira}/entrypoint.sh | 0 prepare-feeder/Dockerfile | 24 ++++ {prepare => prepare-feeder}/entrypoint.sh | 0 prepare-feeder/prepare.py | 79 ++++++++++ .../templates/config.toml.j2 | 2 +- prepare-kujira/Dockerfile | 22 +++ prepare-kujira/entrypoint.sh | 10 ++ {prepare => prepare-kujira}/prepare.py | 29 ++-- .../templates/app.toml.j2 | 0 prepare-kujira/templates/client.toml.j2 | 17 +++ .../templates/config.toml.j2 | 0 prepare/Dockerfile | 16 --- 17 files changed, 303 insertions(+), 153 deletions(-) create mode 100755 build.py delete mode 100755 build.sh delete mode 100755 devbuild.sh delete mode 100755 kujira.sh rename {kujirad => kujira}/Dockerfile (100%) rename {kujirad => kujira}/entrypoint.sh (100%) create mode 100644 prepare-feeder/Dockerfile rename {prepare => prepare-feeder}/entrypoint.sh (100%) create mode 100644 prepare-feeder/prepare.py rename prepare/templates/feeder.toml.j2 => prepare-feeder/templates/config.toml.j2 (94%) create mode 100644 prepare-kujira/Dockerfile create mode 100644 prepare-kujira/entrypoint.sh rename {prepare => prepare-kujira}/prepare.py (94%) rename {prepare => prepare-kujira}/templates/app.toml.j2 (100%) create mode 100644 prepare-kujira/templates/client.toml.j2 rename {prepare => prepare-kujira}/templates/config.toml.j2 (100%) delete mode 100644 prepare/Dockerfile diff --git a/build.py b/build.py new file mode 100755 index 0000000..7b987dc --- /dev/null +++ b/build.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python3 + +import argparse +import platform +import subprocess +import sys + +GO_VERSIONS = { + "kujira": { + "v0.9.0": "1.20.2", + "v0.9.1": "1.20.2", + "v0.9.2": "1.20.2", + "sdk-50": "1.21.3", + }, + "feeder": { + "v0.8.3": "1.20.2", + } +} + + +def parse_args(): + parser = argparse.ArgumentParser() + parser.add_argument("action", choices=["build", "manifest"]) + parser.add_argument("-n", "--namespace", default="teamkujira") + parser.add_argument("-a", "--app", required=True) + parser.add_argument("-t", "--tag", required=True) + parser.add_argument("--push", action="store_true") + parser.add_argument("--podman", action="store_true") + parser.add_argument("--mainnet", action="store_true") + parser.add_argument("--testnet", action="store_true") + return parser.parse_args() + + +def build(command, namespace, app, tag, push=False, extra_tags=[]): + arch = platform.machine() + fulltag = f"{namespace}/{app}:{tag}-{arch}" + baseapp = app.replace("prepare-", "") + + cmd = [command, "build", "--tag", fulltag] + + if baseapp in ["feeder", "kujira"]: + go_version = GO_VERSIONS.get(baseapp, {}).get(tag) + if not go_version: + print(f"no go version defined for {baseapp}:{tag}") + sys.exit(1) + + cmd += ["--build-arg", f"{baseapp}_version={tag}"] + cmd += ["--build-arg", f"go_version={go_version}"] + + if app.startswith("prepare-"): + cmd += ["--build-arg", f"namespace={namespace}"] + cmd += ["--build-arg", f"arch={arch}"] + + cmd.append(app) + + print(" ".join(cmd)) + subprocess.run(cmd) + + push_cmds = [ + [command, "push", fulltag] + ] + + for tag in extra_tags: + print(tag) + newtag = f"{namespace}/{app}:{tag}-{arch}" + subprocess.run([command, "tag", fulltag, newtag]) + push_cmds.append([command, "push", newtag]) + + print(push_cmds) + + if push: + for cmd in push_cmds: + print(cmd) + subprocess.run(cmd) + + +def manifest(command, namespace, app, tag, push=False, extra_tags=[]): + push_commands = [] + basetag = f"{namespace}/{app}" + + fulltag = f"{basetag}:{tag}" + print("------------------") + print(fulltag) + subprocess.run([ + command, "manifest", "create", f"{fulltag}", + # f"{basetag}-arm64", f"{basetag}-x86_64" + f"{fulltag}-arm64" + ]) + + push_commands.append( + [command, "manifest", "push", f"{fulltag}"] + ) + + for tag in extra_tags: + print(tag) + newtag = f"{basetag}:{tag}" + subprocess.run([command, "tag", fulltag, newtag]) + push_commands.append([command, "push", newtag]) + + if push: + for cmd in push_commands: + print(cmd) + subprocess.run(cmd) + + +def main(): + args = parse_args() + + command = "docker" + if args.podman: + command = "podman" + + apps = [args.app] + if args.app in ["feeder", "kujira"]: + apps.append(f"prepare-{args.app}") + + print(apps) + + for app in apps: + extra_tags = [] + if args.testnet: + extra_tags.append("testnet") + if args.mainnet: + extra_tags.append("mainnet") + + if args.action == "build": + + build(command, args.namespace, app, + args.tag, args.push, extra_tags) + elif args.action == "manifest": + manifest(command, args.namespace, app, + args.tag, args.push, extra_tags) + + +if __name__ == "__main__": + main() diff --git a/build.sh b/build.sh deleted file mode 100755 index b80bf28..0000000 --- a/build.sh +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/bash - -action=build -if [ $# -eq 1 ] && [ "$1" == "manifest" ]; then - action=manifest -fi - -if [ -n "$(which docker)" ]; then - cmd=docker -elif [ -n "$(which podman)" ]; then - cmd=podman -else - exit 1 -fi - -arch=$(arch) - -# kujirad -go_version=1.20.2 -kujira_version=v0.9.0 -tag=teamkujira/kujirad:${kujira_version} - -if [ "$action" == "build" ]; then - $cmd build \ - --tag ${tag}-${arch} \ - --build-arg go_version=${go_version} \ - --build-arg kujira_version=${kujira_version} \ - kujirad && \ - - $cmd push $tag-${arch} -fi - -if [ "$action" == "manifest" ]; then - $cmd manifest create ${tag} ${tag}-x86_64 ${tag}-arm64 - $cmd manifest push ${tag} -fi - -# feeder -go_version=1.20.2 -feeder_version=next -tag=teamkujira/feeder:${feeder_version} - -if [ "$action" == "build" ]; then - $cmd build \ - --tag ${tag}-${arch} \ - --build-arg go_version=${go_version} \ - --build-arg feeder_version=${feeder_version} \ - feeder && \ - - $cmd push $tag-${arch} -fi - - -if [ "$action" == "manifest" ]; then - $cmd manifest create ${tag} ${tag}-x86_64 ${tag}-arm64 - $cmd manifest push ${tag} -fi - -# prepare -prepare_version=latest -tag=teamkujira/prepare:${prepare_version} - -if [ "$action" == "build" ]; then - $cmd build \ - --tag ${tag}-${arch} \ - --build-arg kujira_version=${kujira_version} \ - --build-arg arch=${arch} \ - prepare && \ - - $cmd push $tag-${arch} -fi - -if [ "$action" == "manifest" ]; then - $cmd manifest create ${tag} ${tag}-x86_64 ${tag}-arm64 - $cmd manifest push ${tag} -fi \ No newline at end of file diff --git a/devbuild.sh b/devbuild.sh deleted file mode 100755 index 0c37623..0000000 --- a/devbuild.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -action=build -if [ $# -eq 1 ] && [ "$1" == "manifest" ]; then - action=manifest -fi - -if [ -n "$(which docker)" ]; then - cmd=docker -elif [ -n "$(which podman)" ]; then - cmd=podman -else - exit 1 -fi - -cmd=podman - -arch=$(arch) - -# contracts -kujira_version=v0.9.0 -tag=starsquid/contracts:${kujira_version} - -if [ "$action" == "build" ]; then - $cmd build \ - --tag ${tag}-${arch} \ - --build-arg kujira_version=${kujira_version} \ - contracts - - # $cmd push $tag-${arch} -fi - -if [ "$action" == "manifest" ]; then - $cmd manifest create ${tag} ${tag}-x86_64 ${tag}-arm64 - $cmd manifest push ${tag} -fi diff --git a/kujira.sh b/kujira.sh deleted file mode 100755 index 8cd8564..0000000 --- a/kujira.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -if [ "$1" == "tx" ]; then - extra="--from validator --keyring-backend test --gas auto --gas-adjustment 2" -fi - -kujirad-v0.8.8-43-gc5a82f3 \ - --node http://localhost:10157 $@ \ - --home /tmp/pond --chain-id pond-1 $extra diff --git a/kujirad/Dockerfile b/kujira/Dockerfile similarity index 100% rename from kujirad/Dockerfile rename to kujira/Dockerfile diff --git a/kujirad/entrypoint.sh b/kujira/entrypoint.sh similarity index 100% rename from kujirad/entrypoint.sh rename to kujira/entrypoint.sh diff --git a/prepare-feeder/Dockerfile b/prepare-feeder/Dockerfile new file mode 100644 index 0000000..0bad9dd --- /dev/null +++ b/prepare-feeder/Dockerfile @@ -0,0 +1,24 @@ +ARG namespace +ARG feeder_version +ARG arch +FROM ${namespace}/feeder:${feeder_version}-${arch} + +ARG feeder_version +ENV VERSION=${feeder_version} + +RUN echo "$VERSION" + +RUN apt-get update && \ + apt-get install -y --no-install-recommends python3 python3-jinja2 && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +COPY prepare.py entrypoint.sh /usr/local/bin/ +COPY templates /tmp/templates + +RUN chmod +x /usr/local/bin/* + +WORKDIR /tmp + +ENTRYPOINT ["entrypoint.sh"] + diff --git a/prepare/entrypoint.sh b/prepare-feeder/entrypoint.sh similarity index 100% rename from prepare/entrypoint.sh rename to prepare-feeder/entrypoint.sh diff --git a/prepare-feeder/prepare.py b/prepare-feeder/prepare.py new file mode 100644 index 0000000..fcc5bfe --- /dev/null +++ b/prepare-feeder/prepare.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 + +import json +import os +import jinja2 +import argparse +import sys + +WORKDIR = "pond" + + +def parse_args(): + parser = argparse.ArgumentParser() + parser.add_argument("--podman", action="store_true", + help="Generate start/stop scripts for podman") + + return parser.parse_args() + + +def main(): + args = parse_args() + + if not os.path.isdir(WORKDIR): + sys.exit(1) + + config = { + "command": "docker", + "chains": {} + } + + if args.podman: + config["command"] = "podman" + + config = json.load(open(f"{WORKDIR}/pond.json", "r")) + + chains = config.get("chains", {}) + chain = chains.get("pond-1") + if not chain: + print(f"chain 'pond-1' not found") + sys.exit(1) + + feeder_toml = jinja2.Template( + open("templates/config.toml.j2", "r").read() + ) + + for validator in chain["validators"]: + port_prefix = validator["rpc_url"][-5:-2] + params = { + "grpc_port": f"{port_prefix}{90}", + "rpc_port": f"{port_prefix}{57}", + "feeder_port": f"{port_prefix}{71}", + "moniker": validator["moniker"], + "address": validator["address"], + "valoper": validator["valoper"], + "chain_id": "pond-1", + "podman": args.podman + } + + name = validator["moniker"].lower().replace("kujira", "feeder") + home = f"{WORKDIR}/{name}" + if os.path.isdir(home): + continue + + os.mkdir(home) + + open(f"{home}/config.toml", "w").write( + feeder_toml.render(params) + ) + + # update version + version = config.get("version", {}) + version["feeder"] = os.environ.get("VERSION") + config["version"] = version + + json.dump(config, open(f"{WORKDIR}/pond.json", "w")) + + +if __name__ == "__main__": + main() diff --git a/prepare/templates/feeder.toml.j2 b/prepare-feeder/templates/config.toml.j2 similarity index 94% rename from prepare/templates/feeder.toml.j2 rename to prepare-feeder/templates/config.toml.j2 index be0e6fa..4cde77e 100644 --- a/prepare/templates/feeder.toml.j2 +++ b/prepare-feeder/templates/config.toml.j2 @@ -48,4 +48,4 @@ providers = ["binance", "bitget", "lbank", "mexc", "okx", "xt"] [[currency_pairs]] base = "USDT" quote = "USD" -providers = ["binanceus", "crypto", "gate", "kraken", "osmosis"] \ No newline at end of file +providers = ["binanceus", "crypto", "gate", "kraken"] \ No newline at end of file diff --git a/prepare-kujira/Dockerfile b/prepare-kujira/Dockerfile new file mode 100644 index 0000000..86c787d --- /dev/null +++ b/prepare-kujira/Dockerfile @@ -0,0 +1,22 @@ +ARG namespace +ARG kujira_version +ARG arch +FROM ${namespace}/kujira:${kujira_version}-${arch} + +ARG kujira_version +ENV VERSION=${kujira_version} + +RUN apt-get update && \ + apt-get install -y --no-install-recommends python3 python3-jinja2 && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* + +COPY prepare.py entrypoint.sh /usr/local/bin/ +COPY templates /tmp/templates + +RUN chmod +x /usr/local/bin/* + +WORKDIR /tmp + +ENTRYPOINT ["entrypoint.sh"] + diff --git a/prepare-kujira/entrypoint.sh b/prepare-kujira/entrypoint.sh new file mode 100644 index 0000000..b6d850f --- /dev/null +++ b/prepare-kujira/entrypoint.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +if [ -n "$USER" ]; then + useradd -u $USER prepare + chown -R prepare /tmp/pond + + exec runuser -u prepare -- "$@" +else + $@ +fi \ No newline at end of file diff --git a/prepare/prepare.py b/prepare-kujira/prepare.py similarity index 94% rename from prepare/prepare.py rename to prepare-kujira/prepare.py index 72737f0..13733e0 100644 --- a/prepare/prepare.py +++ b/prepare-kujira/prepare.py @@ -149,8 +149,8 @@ def prepare_config(self): config_toml = jinja2.Template( open("templates/config.toml.j2", "r").read() ) - feeder_toml = jinja2.Template( - open("templates/feeder.toml.j2", "r").read() + client_toml = jinja2.Template( + open("templates/client.toml.j2", "r").read() ) for index, info in enumerate(self.validators): @@ -176,7 +176,6 @@ def prepare_config(self): "rpc_port": f"{self.port_prefix}{num}{57}", "abci_port": f"{self.port_prefix}{num}{58}", "pprof_port": f"{self.port_prefix}{num}{60}", - "feeder_port": f"{self.port_prefix}{num}{71}", "persistent_peers": ",".join(persistent_peers), "moniker": info["moniker"], "address": info["address"], @@ -193,17 +192,8 @@ def prepare_config(self): config_toml.render(config) ) - if self.denom != "ukuji": - continue - - home = f"{WORKDIR}/feeder{num}" - if os.path.isdir(home): - continue - - os.mkdir(home) - - open(f"{home}/config.toml", "w").write( - feeder_toml.render(config) + open(f"{home}/config/client.toml", "w").write( + client_toml.render(config) ) @@ -230,7 +220,10 @@ def main(): config = { "command": "docker", - "chains": {} + "chains": {}, + "version": { + "kujira": os.environ.get("VERSION") + } } if args.podman: @@ -241,6 +234,8 @@ def main(): # Chain("Faker", "faker-1", "ufake", 1, 2) ] + print(config) + for chain in chains: chain_info = { "name": chain.name, @@ -258,6 +253,10 @@ def main(): config["chains"][chain.chain_id] = chain_info + print(config) + + print(config) + json.dump(config, open(f"{WORKDIR}/pond.json", "w")) diff --git a/prepare/templates/app.toml.j2 b/prepare-kujira/templates/app.toml.j2 similarity index 100% rename from prepare/templates/app.toml.j2 rename to prepare-kujira/templates/app.toml.j2 diff --git a/prepare-kujira/templates/client.toml.j2 b/prepare-kujira/templates/client.toml.j2 new file mode 100644 index 0000000..0485d17 --- /dev/null +++ b/prepare-kujira/templates/client.toml.j2 @@ -0,0 +1,17 @@ +# This is a TOML config file. +# For more information, see https://github.com/toml-lang/toml + +############################################################################### +### Client Configuration ### +############################################################################### + +# The network chain ID +chain-id = "{{ chain_id }}" +# The keyring's backend, where the keys are stored (os|file|kwallet|pass|test|memory) +keyring-backend = "os" +# CLI output format (text|json) +output = "text" +# : to Tendermint RPC interface for this chain +node = "tcp://localhost:{{ rpc_port }}" +# Transaction broadcasting mode (sync|async|block) +broadcast-mode = "sync" diff --git a/prepare/templates/config.toml.j2 b/prepare-kujira/templates/config.toml.j2 similarity index 100% rename from prepare/templates/config.toml.j2 rename to prepare-kujira/templates/config.toml.j2 diff --git a/prepare/Dockerfile b/prepare/Dockerfile deleted file mode 100644 index 18d201f..0000000 --- a/prepare/Dockerfile +++ /dev/null @@ -1,16 +0,0 @@ -ARG kujira_version -ARG arch -FROM teamkujira/kujirad:${kujira_version}-${arch} - -RUN apt-get update && apt-get install --yes python3 python3-jinja2 - -COPY prepare.py /usr/local/bin/ -COPY entrypoint.sh /usr/local/bin/ -COPY templates /tmp/templates - -RUN chmod +x /usr/local/bin/* - -WORKDIR /tmp - -ENTRYPOINT ["entrypoint.sh"] - From 7d54fe1359cbac019b2f9a997827a04944c501df Mon Sep 17 00:00:00 2001 From: starsquidnodes Date: Mon, 27 Nov 2023 16:46:39 +0100 Subject: [PATCH 06/10] Fix api --- prepare-kujira/templates/app.toml.j2 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prepare-kujira/templates/app.toml.j2 b/prepare-kujira/templates/app.toml.j2 index db2ef98..a489791 100644 --- a/prepare-kujira/templates/app.toml.j2 +++ b/prepare-kujira/templates/app.toml.j2 @@ -118,10 +118,10 @@ global-labels = [] enable = true # Swagger defines if swagger documentation should automatically be registered. -swagger = false +swagger = true # Address defines the API server to listen on. -address = "tcp://127.0.0.1:{{ api_port }}" +address = "tcp://0.0.0.0:{{ api_port }}" # MaxOpenConnections defines the number of maximum open connections. max-open-connections = 1000 From 8d6e23bc7f28605e25693e62a897702e0c0c0656 Mon Sep 17 00:00:00 2001 From: starsquidnodes Date: Mon, 27 Nov 2023 16:46:46 +0100 Subject: [PATCH 07/10] Fix build script --- build.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build.py b/build.py index 7b987dc..cb46dba 100755 --- a/build.py +++ b/build.py @@ -83,8 +83,7 @@ def manifest(command, namespace, app, tag, push=False, extra_tags=[]): print(fulltag) subprocess.run([ command, "manifest", "create", f"{fulltag}", - # f"{basetag}-arm64", f"{basetag}-x86_64" - f"{fulltag}-arm64" + f"{fulltag}-arm64", f"{fulltag}-x86_64" ]) push_commands.append( From 55daedfe98c65eb1082158f730fa7eb38efa92e1 Mon Sep 17 00:00:00 2001 From: starsquidnodes Date: Sat, 10 Feb 2024 13:14:10 +0100 Subject: [PATCH 08/10] Rework prepare, add kujira-2, relayer --- README.md | 10 + build.py | 123 +++--- prepare-feeder/Dockerfile | 24 -- prepare-feeder/prepare.py | 79 ---- prepare-kujira/entrypoint.sh | 10 - prepare-kujira/prepare.py | 264 ------------- {prepare-kujira => prepare}/Dockerfile | 8 +- {prepare-feeder => prepare}/entrypoint.sh | 0 ...bb595bc2e6e1a2fd66c262da3a220c0f85.address | 1 + .../keys/kujira-1/keyring-test/relayer.info | 1 + ...bb595bc2e6e1a2fd66c262da3a220c0f85.address | 1 + .../keys/kujira-2/keyring-test/relayer.info | 1 + prepare/mnemonics.json | 26 ++ prepare/prepare.py | 355 ++++++++++++++++++ .../templates/app.toml.j2 | 0 .../templates/client.toml.j2 | 0 .../templates/config.toml.j2 | 0 .../templates/feeder.toml.j2 | 0 prepare/templates/relayer.yaml.j2 | 45 +++ relayer/Dockerfile | 23 ++ relayer/entrypoint.sh | 10 + relayer/link-and-start-pond.sh | 6 + 22 files changed, 550 insertions(+), 437 deletions(-) create mode 100644 README.md delete mode 100644 prepare-feeder/Dockerfile delete mode 100644 prepare-feeder/prepare.py delete mode 100644 prepare-kujira/entrypoint.sh delete mode 100644 prepare-kujira/prepare.py rename {prepare-kujira => prepare}/Dockerfile (66%) rename {prepare-feeder => prepare}/entrypoint.sh (100%) create mode 100644 prepare/keys/kujira-1/keyring-test/ca2106bb595bc2e6e1a2fd66c262da3a220c0f85.address create mode 100644 prepare/keys/kujira-1/keyring-test/relayer.info create mode 100644 prepare/keys/kujira-2/keyring-test/ca2106bb595bc2e6e1a2fd66c262da3a220c0f85.address create mode 100644 prepare/keys/kujira-2/keyring-test/relayer.info create mode 100644 prepare/mnemonics.json create mode 100755 prepare/prepare.py rename {prepare-kujira => prepare}/templates/app.toml.j2 (100%) rename {prepare-kujira => prepare}/templates/client.toml.j2 (100%) rename {prepare-kujira => prepare}/templates/config.toml.j2 (100%) rename prepare-feeder/templates/config.toml.j2 => prepare/templates/feeder.toml.j2 (100%) create mode 100644 prepare/templates/relayer.yaml.j2 create mode 100644 relayer/Dockerfile create mode 100644 relayer/entrypoint.sh create mode 100644 relayer/link-and-start-pond.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..08ca41a --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# pond-images + +This repo provides the sources for all images needed to run the local Kujira development environment pond. + +## Build + +```sh +./build.py -n teamkujira -a kujira --push +./build.py --manifest --archs arm64,x86_64 +``` diff --git a/build.py b/build.py index cb46dba..46d9b0b 100755 --- a/build.py +++ b/build.py @@ -10,46 +10,68 @@ "v0.9.0": "1.20.2", "v0.9.1": "1.20.2", "v0.9.2": "1.20.2", + "v0.9.3-1": "1.20.2", "sdk-50": "1.21.3", }, "feeder": { "v0.8.3": "1.20.2", + "v0.11.0": "1.20.2", + }, + "relayer": { + "v2.5.0": "1.21.7", + } +} + +VERSIONS = { + "v0.1.0": { + "kujira": "v0.9.3-1", + "feeder": "v0.11.0", + "relayer": "v2.5.0" } } def parse_args(): parser = argparse.ArgumentParser() - parser.add_argument("action", choices=["build", "manifest"]) parser.add_argument("-n", "--namespace", default="teamkujira") - parser.add_argument("-a", "--app", required=True) - parser.add_argument("-t", "--tag", required=True) + parser.add_argument("-a", "--app") + parser.add_argument("-t", "--tag", default="v0.1.0") parser.add_argument("--push", action="store_true") parser.add_argument("--podman", action="store_true") - parser.add_argument("--mainnet", action="store_true") - parser.add_argument("--testnet", action="store_true") + parser.add_argument("--manifest", action="store_true") + parser.add_argument("--archs", default=platform.machine()) return parser.parse_args() -def build(command, namespace, app, tag, push=False, extra_tags=[]): +def build_arg(s): + return ["--build-arg", s] + + +def build(command, namespace, app, tag, push=False): arch = platform.machine() fulltag = f"{namespace}/{app}:{tag}-{arch}" - baseapp = app.replace("prepare-", "") cmd = [command, "build", "--tag", fulltag] - if baseapp in ["feeder", "kujira"]: - go_version = GO_VERSIONS.get(baseapp, {}).get(tag) + if app in ["feeder", "kujira", "relayer"]: + go_version = GO_VERSIONS.get(app, {}).get(tag) if not go_version: - print(f"no go version defined for {baseapp}:{tag}") + print(f"no go version defined for {app}:{tag}") sys.exit(1) - cmd += ["--build-arg", f"{baseapp}_version={tag}"] - cmd += ["--build-arg", f"go_version={go_version}"] + cmd += build_arg(f"{app}_version={tag}") + cmd += build_arg(f"go_version={go_version}") + + if app == "prepare": + kujira_version = VERSIONS[tag]["kujira"] + feeder_version = VERSIONS[tag]["feeder"] + relayer_version = VERSIONS[tag]["relayer"] - if app.startswith("prepare-"): - cmd += ["--build-arg", f"namespace={namespace}"] - cmd += ["--build-arg", f"arch={arch}"] + cmd += build_arg(f"kujira_version={kujira_version}") + cmd += build_arg(f"feeder_version={feeder_version}") + cmd += build_arg(f"relayer_version={relayer_version}") + cmd += build_arg(f"namespace={namespace}") + cmd += build_arg(f"arch={arch}") cmd.append(app) @@ -60,12 +82,6 @@ def build(command, namespace, app, tag, push=False, extra_tags=[]): [command, "push", fulltag] ] - for tag in extra_tags: - print(tag) - newtag = f"{namespace}/{app}:{tag}-{arch}" - subprocess.run([command, "tag", fulltag, newtag]) - push_cmds.append([command, "push", newtag]) - print(push_cmds) if push: @@ -74,32 +90,22 @@ def build(command, namespace, app, tag, push=False, extra_tags=[]): subprocess.run(cmd) -def manifest(command, namespace, app, tag, push=False, extra_tags=[]): - push_commands = [] - basetag = f"{namespace}/{app}" +def manifest(command, namespace, app, tag, archs, push=False): + fulltag = f"{namespace}/{app}:{tag}" + commands = [] - fulltag = f"{basetag}:{tag}" print("------------------") print(fulltag) - subprocess.run([ - command, "manifest", "create", f"{fulltag}", - f"{fulltag}-arm64", f"{fulltag}-x86_64" - ]) - - push_commands.append( - [command, "manifest", "push", f"{fulltag}"] - ) - for tag in extra_tags: - print(tag) - newtag = f"{basetag}:{tag}" - subprocess.run([command, "tag", fulltag, newtag]) - push_commands.append([command, "push", newtag]) + tags = [f"{fulltag}-{x}" for x in archs.split(",")] + commands.append([command, "manifest", "create", f"{fulltag}"] + tags) if push: - for cmd in push_commands: - print(cmd) - subprocess.run(cmd) + commands.append([command, "manifest", "push", f"{fulltag}"]) + + for cmd in commands: + print(cmd) + subprocess.run(cmd) def main(): @@ -109,26 +115,25 @@ def main(): if args.podman: command = "podman" - apps = [args.app] - if args.app in ["feeder", "kujira"]: - apps.append(f"prepare-{args.app}") - - print(apps) + apps = ["kujira", "feeder", "relayer", "prepare"] + if args.app: + apps = [args.app] for app in apps: - extra_tags = [] - if args.testnet: - extra_tags.append("testnet") - if args.mainnet: - extra_tags.append("mainnet") - - if args.action == "build": - - build(command, args.namespace, app, - args.tag, args.push, extra_tags) - elif args.action == "manifest": - manifest(command, args.namespace, app, - args.tag, args.push, extra_tags) + tag = VERSIONS[args.tag].get(app) + if app == "prepare": + tag = args.tag + + if not tag: + print(f"no tag defined for {app} ({args.tag})") + sys.exit(1) + + build(command, args.namespace, app, tag, args.push) + + if not args.manifest: + return + + manifest(command, args.namespace, app, tag, args.archs, args.push) if __name__ == "__main__": diff --git a/prepare-feeder/Dockerfile b/prepare-feeder/Dockerfile deleted file mode 100644 index 0bad9dd..0000000 --- a/prepare-feeder/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -ARG namespace -ARG feeder_version -ARG arch -FROM ${namespace}/feeder:${feeder_version}-${arch} - -ARG feeder_version -ENV VERSION=${feeder_version} - -RUN echo "$VERSION" - -RUN apt-get update && \ - apt-get install -y --no-install-recommends python3 python3-jinja2 && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* - -COPY prepare.py entrypoint.sh /usr/local/bin/ -COPY templates /tmp/templates - -RUN chmod +x /usr/local/bin/* - -WORKDIR /tmp - -ENTRYPOINT ["entrypoint.sh"] - diff --git a/prepare-feeder/prepare.py b/prepare-feeder/prepare.py deleted file mode 100644 index fcc5bfe..0000000 --- a/prepare-feeder/prepare.py +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env python3 - -import json -import os -import jinja2 -import argparse -import sys - -WORKDIR = "pond" - - -def parse_args(): - parser = argparse.ArgumentParser() - parser.add_argument("--podman", action="store_true", - help="Generate start/stop scripts for podman") - - return parser.parse_args() - - -def main(): - args = parse_args() - - if not os.path.isdir(WORKDIR): - sys.exit(1) - - config = { - "command": "docker", - "chains": {} - } - - if args.podman: - config["command"] = "podman" - - config = json.load(open(f"{WORKDIR}/pond.json", "r")) - - chains = config.get("chains", {}) - chain = chains.get("pond-1") - if not chain: - print(f"chain 'pond-1' not found") - sys.exit(1) - - feeder_toml = jinja2.Template( - open("templates/config.toml.j2", "r").read() - ) - - for validator in chain["validators"]: - port_prefix = validator["rpc_url"][-5:-2] - params = { - "grpc_port": f"{port_prefix}{90}", - "rpc_port": f"{port_prefix}{57}", - "feeder_port": f"{port_prefix}{71}", - "moniker": validator["moniker"], - "address": validator["address"], - "valoper": validator["valoper"], - "chain_id": "pond-1", - "podman": args.podman - } - - name = validator["moniker"].lower().replace("kujira", "feeder") - home = f"{WORKDIR}/{name}" - if os.path.isdir(home): - continue - - os.mkdir(home) - - open(f"{home}/config.toml", "w").write( - feeder_toml.render(params) - ) - - # update version - version = config.get("version", {}) - version["feeder"] = os.environ.get("VERSION") - config["version"] = version - - json.dump(config, open(f"{WORKDIR}/pond.json", "w")) - - -if __name__ == "__main__": - main() diff --git a/prepare-kujira/entrypoint.sh b/prepare-kujira/entrypoint.sh deleted file mode 100644 index b6d850f..0000000 --- a/prepare-kujira/entrypoint.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -if [ -n "$USER" ]; then - useradd -u $USER prepare - chown -R prepare /tmp/pond - - exec runuser -u prepare -- "$@" -else - $@ -fi \ No newline at end of file diff --git a/prepare-kujira/prepare.py b/prepare-kujira/prepare.py deleted file mode 100644 index 13733e0..0000000 --- a/prepare-kujira/prepare.py +++ /dev/null @@ -1,264 +0,0 @@ -#!/usr/bin/env python3 - -import json -import shutil -import subprocess -import os -import jinja2 -import argparse - -WORKDIR = "pond" - - -class Chain: - name = "" - denom = "stake" - chain_id = "" - validators = [] - port_prefix = 1 - podman = False - rpc_port = "" - - def __init__(self, name, chain_id, denom, num_validators, port_prefix, podman): - self.name = name - self.chain_id = chain_id - self.denom = denom - self.port_prefix = port_prefix - self.podman = podman - - gentxs = [] - self.validators = [] - - for i in range(1, num_validators + 1): - home = f"{WORKDIR}/{name.lower()}{i:02}" - - if os.path.isdir(home): - continue - - os.mkdir(home) - - info, gentx = self.prepare_gentxs(chain_id, home) - info["rpc_port"] = f"{self.port_prefix}{i:02}57" - info["api_port"] = f"{self.port_prefix}{i:02}17" - self.validators.append(info) - - gentxs.append(gentx) - - self.prepare_genesis(gentxs) - self.prepare_config() - - def prepare_gentxs(self, chain_id, home, amount=10**15): - moniker = home.split("/")[-1].title() - denom = self.denom - - kujirad = ["kujirad", "--home", home] - - result = subprocess.run(kujirad + [ - "init", moniker, "--chain-id", chain_id, - "--default-denom", self.denom - ], capture_output=True, text=True) - - output = json.loads(result.stderr) - node_id = output["node_id"] - - kujirad += ["--output", "json"] - - result = subprocess.run(kujirad + [ - "keys", "add", "validator", "--keyring-backend", "test", - ], capture_output=True, text=True) - - output = json.loads(result.stdout) - address = output["address"] - mnemonic = output["mnemonic"] - - subprocess.run(kujirad + [ - "genesis", "add-genesis-account", address, f"{amount}{denom}" - ]) - - staked = amount / 2 - result = subprocess.run(kujirad + [ - "genesis", "gentx", "validator", f"{staked}{denom}", - "--chain-id", chain_id, "--keyring-backend", "test" - ], capture_output=True, text=True) - - gentx_path = f"{home}/config/gentx" - gentx_file = os.listdir(gentx_path)[0] - gentx_data = json.load(open(f"{gentx_path}/{gentx_file}", "r")) - - info = { - "moniker": moniker, - "address": address, - "valoper": gentx_data["body"]["messages"][0]["validator_address"], - "node_id": node_id, - "mnemonic": mnemonic, - "amount": amount - } - - return info, gentx_data - - def prepare_genesis(self, gentxs): - name = self.name.lower() - home = f"{WORKDIR}/{name}01" - - kujirad = ["kujirad", "--home", home] - - for i in range(1, len(self.validators)): - info = self.validators[i] - address = info["address"] - amount = info["amount"] - subprocess.run(kujirad + [ - "genesis", "add-genesis-account", address, f"{amount}{self.denom}" - ]) - - json.dump( - gentxs[i], - open(f"{home}/config/gentx/gentx-{info['node_id']}.json", "w") - ) - - subprocess.run(kujirad + [ - "genesis", "collect-gentxs" - ]) - - genesis = json.load(open(f"{home}/config/genesis.json")) - - genesis["app_state"]["crisis"]["constant_fee"]["denom"] = self.denom - genesis["app_state"]["denom"]["params"]["creation_fee"][0]["denom"] = self.denom - genesis["app_state"]["gov"]["params"]["min_deposit"][0]["denom"] = self.denom - genesis["app_state"]["gov"]["params"]["max_deposit_period"] = "20s" - genesis["app_state"]["gov"]["params"]["voting_period"] = "20s" - genesis["app_state"]["mint"]["minter"]["inflation"] = "0" - genesis["app_state"]["mint"]["params"]["mint_denom"] = self.denom - if self.denom == "ukuji": - genesis["app_state"]["oracle"]["params"]["whitelist"] = [ - {"name": "BTC"}, - {"name": "ETH"} - ] - genesis["app_state"]["staking"]["params"]["unbonding_time"] = "120s" - genesis["app_state"]["staking"]["params"]["bond_denom"] = self.denom - - for i in range(len(self.validators)): - json.dump( - genesis, - open(f"{WORKDIR}/{name}{i+1:02}/config/genesis.json", "w"), - ) - - def prepare_config(self): - app_toml = jinja2.Template( - open("templates/app.toml.j2", "r").read() - ) - config_toml = jinja2.Template( - open("templates/config.toml.j2", "r").read() - ) - client_toml = jinja2.Template( - open("templates/client.toml.j2", "r").read() - ) - - for index, info in enumerate(self.validators): - num = f"{index+1:02}" - home = f"{WORKDIR}/{self.name.lower()}{num}" - - node_id = info["node_id"] - - persistent_peers = [] - for i, v in enumerate(self.validators): - if v["node_id"] == node_id: - continue - port = f"{self.port_prefix}{i+1:02}{56}" - host = v["moniker"].lower() - if self.podman: - host = "127.0.0.1" - persistent_peers.append(f"{v['node_id']}@{host}:{port}") - - config = { - "api_port": f"{self.port_prefix}{num}{17}", - "grpc_port": f"{self.port_prefix}{num}{90}", - "app_port": f"{self.port_prefix}{num}{56}", - "rpc_port": f"{self.port_prefix}{num}{57}", - "abci_port": f"{self.port_prefix}{num}{58}", - "pprof_port": f"{self.port_prefix}{num}{60}", - "persistent_peers": ",".join(persistent_peers), - "moniker": info["moniker"], - "address": info["address"], - "valoper": info["valoper"], - "chain_id": self.chain_id, - "podman": self.podman - } - - open(f"{home}/config/app.toml", "w").write( - app_toml.render(config) - ) - - open(f"{home}/config/config.toml", "w").write( - config_toml.render(config) - ) - - open(f"{home}/config/client.toml", "w").write( - client_toml.render(config) - ) - - -def parse_args(): - parser = argparse.ArgumentParser() - parser.add_argument("-n", "--nodes", type=int, default=1, - help="Set number of validator nodes") - parser.add_argument("--clear", action="store_true", - help="Remove all configs and create new chain") - parser.add_argument("--podman", action="store_true", - help="Generate start/stop scripts for podman") - - return parser.parse_args() - - -def main(): - args = parse_args() - - if args.clear: - shutil.rmtree(WORKDIR, ignore_errors=True) - - if not os.path.isdir(WORKDIR): - os.mkdir(WORKDIR) - - config = { - "command": "docker", - "chains": {}, - "version": { - "kujira": os.environ.get("VERSION") - } - } - - if args.podman: - config["command"] = "podman" - - chains = [ - Chain("Kujira", "pond-1", "ukuji", args.nodes, 1, args.podman), - # Chain("Faker", "faker-1", "ufake", 1, 2) - ] - - print(config) - - for chain in chains: - chain_info = { - "name": chain.name, - "validators": [] - } - - for validator in chain.validators: - validator["rpc_url"] = f"http://localhost:{validator['rpc_port']}" - validator["api_url"] = f"http://localhost:{validator['api_port']}" - validator.pop("rpc_port") - validator.pop("api_port") - validator.pop("amount") - - chain_info["validators"].append(validator) - - config["chains"][chain.chain_id] = chain_info - - print(config) - - print(config) - - json.dump(config, open(f"{WORKDIR}/pond.json", "w")) - - -if __name__ == "__main__": - main() diff --git a/prepare-kujira/Dockerfile b/prepare/Dockerfile similarity index 66% rename from prepare-kujira/Dockerfile rename to prepare/Dockerfile index 86c787d..b6931ff 100644 --- a/prepare-kujira/Dockerfile +++ b/prepare/Dockerfile @@ -4,7 +4,11 @@ ARG arch FROM ${namespace}/kujira:${kujira_version}-${arch} ARG kujira_version -ENV VERSION=${kujira_version} +ARG feeder_version +ARG relayer_version +ENV KUJIRA_VERSION=${kujira_version} +ENV FEEDER_VERSION=${feeder_version} +ENV RELAYER_VERSION=${relayer_version} RUN apt-get update && \ apt-get install -y --no-install-recommends python3 python3-jinja2 && \ @@ -13,6 +17,8 @@ RUN apt-get update && \ COPY prepare.py entrypoint.sh /usr/local/bin/ COPY templates /tmp/templates +COPY keys /tmp/keys +COPY mnemonics.json /tmp/mnemonics.json RUN chmod +x /usr/local/bin/* diff --git a/prepare-feeder/entrypoint.sh b/prepare/entrypoint.sh similarity index 100% rename from prepare-feeder/entrypoint.sh rename to prepare/entrypoint.sh diff --git a/prepare/keys/kujira-1/keyring-test/ca2106bb595bc2e6e1a2fd66c262da3a220c0f85.address b/prepare/keys/kujira-1/keyring-test/ca2106bb595bc2e6e1a2fd66c262da3a220c0f85.address new file mode 100644 index 0000000..98f9104 --- /dev/null +++ b/prepare/keys/kujira-1/keyring-test/ca2106bb595bc2e6e1a2fd66c262da3a220c0f85.address @@ -0,0 +1 @@ +eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyNC0wMi0wOCAxMTo1NDoyNS42MDg4MzMwNzcgKzAwMDAgVVRDIG09KzAuMDY4MzE0OTM3IiwiZW5jIjoiQTI1NkdDTSIsInAyYyI6ODE5MiwicDJzIjoiVjduNDROMUtrc3BVNVhaSSJ9.NHBK_57jyBFkaZ0LynMY4SIfYokUEe0F3hdDkeimO8q-2iqEJqOZyw.G-lHJYMIZfsKppPc.kATfxA_uaaBa0Sc8rgn4r3c8n1XwjA5yiSn3uNLYJOgzlCiziDYywLiPBr9SC64ljkH5V0sHeyNGD814DGUuLW02reJ0D9t0j8jiV6iV1kBmpLr16ic_FLKnon3Dc3_Rh3lZTA6DYGLzQAkzxOAI_Aqs4QO-LtSg1WzNFOuDmN2f38Lh9ykW4P5aXOjVFpfyXbQmRU-ykSoOXQryz2qGUhbJizP_CtX4rsKg_MmBQTVkc7O9Hg4.Zmgn1RaXOheUxnJGHd9gxA \ No newline at end of file diff --git a/prepare/keys/kujira-1/keyring-test/relayer.info b/prepare/keys/kujira-1/keyring-test/relayer.info new file mode 100644 index 0000000..6cce618 --- /dev/null +++ b/prepare/keys/kujira-1/keyring-test/relayer.info @@ -0,0 +1 @@ +eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyNC0wMi0wOCAxMTo1NDoyNS42MDEyODExMjEgKzAwMDAgVVRDIG09KzAuMDYwNzYyOTgxIiwiZW5jIjoiQTI1NkdDTSIsInAyYyI6ODE5MiwicDJzIjoiN0lDQUZteHN6eEZFMzA3bSJ9.c0D_PW-gtsQE9Wz-zRMYKSTFRN5SuhKqh68G4flPDeEKKrM9qJkaJA.o3GRRv5tM7wxeJh2.t1Ngp1m6aZqtJIQsy0jh5Pzak9eKelL8zstcYFbFbgMA5_fv0CRVQz1mIXeE57G8xy3rlAXwX24WpjchffNf2eOPwK1pmgzNYNsbudsN5i5_0UtzGBcuVaYDCCz4O_vYC7Te0L0efc2Nir9aKb7FY65fiTJW90zGU6SVxaAsOr5wuYyBohBq4iKxUf0jup3A8qhMB-3g7gO6_dEjVM9dtj0ZGDMjyg2JaN3MtmSuTvbiyTyAwYuUPZxscuVWnKrVKEWw91yHxQl8D9dhNRlUxa1I3ebS2joJ1Cz2u6CSRQQKI5a5rsarvpofJ3Puw_sQ2DcArpKuub3ojFZKuhyltX1Dql0YmkmGy-Wsay3A7vaFy13nXPCxTN-ptiyVYIhDAOKvbbcONkHMba_4hImSzFE7yBuXjeAlSRDJ5nHHbm4sLKB222INFY2Tdu35XCMde84.5KBIxMBkAAq1Cpuwr9aP3w \ No newline at end of file diff --git a/prepare/keys/kujira-2/keyring-test/ca2106bb595bc2e6e1a2fd66c262da3a220c0f85.address b/prepare/keys/kujira-2/keyring-test/ca2106bb595bc2e6e1a2fd66c262da3a220c0f85.address new file mode 100644 index 0000000..ba7a149 --- /dev/null +++ b/prepare/keys/kujira-2/keyring-test/ca2106bb595bc2e6e1a2fd66c262da3a220c0f85.address @@ -0,0 +1 @@ +eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyNC0wMi0wOCAxMTo1NDoyNy42NDMxMzQxODkgKzAwMDAgVVRDIG09KzAuMDY2NTEzODEyIiwiZW5jIjoiQTI1NkdDTSIsInAyYyI6ODE5MiwicDJzIjoiUDZLLXpia212TkdIN0hVeiJ9.O_EGYosIUOE9ojzT8Nii1QSfbPiTUyqrjCqwCgh1SYGNMBM7wA3z9g.tztcXKRX_iaWKtt4.85ITSo-dmxYo9fLSJpX-m6dTPI4BBBDUde4KMJSTha8-OmzlJLx15ocgNJWFZu-COSsoOt_dSbqQN3j8OBr7cZ3IvKgoTxGA1_74APznlx_bj44jITrzXRyilBcUiMMEwghE4yxd6nwRHD_4Xarm4AuIZha5jwobh6qvodvVMD_6pmmnyo8SRoHRPWCDAvw7_ryMQStIQrC5aHUY3NHuK9Z79PhJJ-NH1rOaFDdgz1wdt7CQv20.glJMxV_RZ-uPnh5VIn5PwQ \ No newline at end of file diff --git a/prepare/keys/kujira-2/keyring-test/relayer.info b/prepare/keys/kujira-2/keyring-test/relayer.info new file mode 100644 index 0000000..2e76248 --- /dev/null +++ b/prepare/keys/kujira-2/keyring-test/relayer.info @@ -0,0 +1 @@ +eyJhbGciOiJQQkVTMi1IUzI1NitBMTI4S1ciLCJjcmVhdGVkIjoiMjAyNC0wMi0wOCAxMTo1NDoyNy42Mzc2NTc2OTEgKzAwMDAgVVRDIG09KzAuMDYxMDM3MzE0IiwiZW5jIjoiQTI1NkdDTSIsInAyYyI6ODE5MiwicDJzIjoiQzROZk5Qa1Z1TE5hRHNEaCJ9.PbExSM5sFYkxOyCNFSBAf3cFrGccT3m6Xp5Y68TK5IlQm9qmLaKFXA.f41_LbTxPMcUIUDj.K1-1LrMElfkEZxI6tj4v94vwjXjEMPUCgs-KMYSURln4YlIiHkJISYvHgiOVBYe0GrDOiKaFTLNR-NXVFDrcFm2l6QpF4si7DnLpifyUSKjBJzMyfvdYwFqpZ_3yIIPRoajzRSv5WzSKYw8WJNvkGGyz5Bm9LEd5rXNE9YlXfpBeIRNG5_DUXK1AqEXjqDJx7LUkvhMzP36xL5KlVE2BngCNoY5_H9_Ho_T7E60HBc70ZsdbQOF_3dTKLF9Gy0vp5MQeclTAhP_D9tbwbeP_Ae5kKNWAKsNY0IOqTNNQq_Z69kL5l1fuWVAKBd2fd4REE08rxAScM5Nj_dtKl5yfbECi9DPSf8wc4SNUZ3bF46rR2ZwoaA-FgA-ztYAMwtIR-oIVcKUIFyBFlJm-M1FyXew_KHu-Dg-uVe-BbVslsC1F2fc1AxGKIrBBkCk-n3E-8EM.BTBNo3cdmWx8dyZBvCkhwA \ No newline at end of file diff --git a/prepare/mnemonics.json b/prepare/mnemonics.json new file mode 100644 index 0000000..f793ed4 --- /dev/null +++ b/prepare/mnemonics.json @@ -0,0 +1,26 @@ +{ + "validators": [ + "symbol rebuild hotel chief ensure hand coach veteran include feature paper flavor define wing hood valve field roast ridge rural advance suggest chunk eye", + "goddess build dragon recall orbit online try check athlete zero farm letter emerge midnight face forget rate swing mimic patient head game ill anger", + "kingdom another behind equip when miracle apart bulb rebuild square ensure witness dumb glue notable attitude dream inherit monitor desk famous wrong tired hat", + "grant tragic cream duty almost heart unveil crystal addict trim weekend lazy tragic segment beauty devote medal cement dirt coach flame hair say quality", + "brother tomato slogan pistol aware stamp govern spot shrimp prepare flag skate fever dance same wheel half student often divorce agent fine faint tunnel", + "erode island dragon twice retire sting tone giant treat mention language right tray spare virus grass chase lunar grant company strong unfair since ahead", + "desert oppose merit anxiety federal doll public oppose injury loop select ribbon devote wink exile frown fix safe into amount clinic food opera victory", + "leopard couch refuse cable quality glue bundle monster never output teach firm filter beef raise valid sting shrug mother puzzle attend squeeze segment aunt", + "upper ten air click easy jelly unique submit jewel follow siren live gadget oyster poverty sister course lemon mad cupboard enter nature reject idea" + ], + "accounts": [ + "notice oak worry limit wrap speak medal online prefer cluster roof addict wrist behave treat actual wasp year salad speed social layer crew genius", + "quality vacuum heart guard buzz spike sight swarm shove special gym robust assume sudden deposit grid alcohol choice devote leader tilt noodle tide penalty", + "symbol force gallery make bulk round subway violin worry mixture penalty kingdom boring survey tool fringe patrol sausage hard admit remember broken alien absorb", + "bounce success option birth apple portion aunt rural episode solution hockey pencil lend session cause hedgehog slender journey system canvas decorate razor catch empty", + "second render cat sing soup reward cluster island bench diet lumber grocery repeat balcony perfect diesel stumble piano distance caught occur example ozone loyal", + "spatial forest elevator battle also spoon fun skirt flight initial nasty transfer glory palm drama gossip remove fan joke shove label dune debate quick", + "noble width taxi input there patrol clown public spell aunt wish punch moment will misery eight excess arena pen turtle minimum grain vague inmate", + "cream sport mango believe inhale text fish rely elegant below earth april wall rug ritual blossom cherry detail length blind digital proof identify ride", + "index light average senior silent limit usual local involve delay update rack cause inmate wall render magnet common feature laundry exact casual resource hundred", + "prefer forget visit mistake mixture feel eyebrow autumn shop pair address airport diesel street pass vague innocent poem method awful require hurry unhappy shoulder" + ], + "relayer": "two detail rare vivid evil essence almost similar tattoo thing rabbit thought alert brick snap tumble dust sail eternal vapor aim finger paddle silver" +} \ No newline at end of file diff --git a/prepare/prepare.py b/prepare/prepare.py new file mode 100755 index 0000000..b67533f --- /dev/null +++ b/prepare/prepare.py @@ -0,0 +1,355 @@ +#!/usr/bin/env python3 + +import json +import shutil +import subprocess +import os +import jinja2 +import argparse + +WORKDIR = "pond" + + +class Node: + denom = "" + chain_id = "" + port_prefix = 0 + home = "" + binary = "" + + def __init__(self, name, chain_id, binary, denom, port_prefix): + self.name = name + self.home = f"{WORKDIR}/{name}" + self.chain_id = chain_id + self.binary = binary + self.port_prefix = port_prefix + self.denom = denom + + def init(self): + result = subprocess.run([ + self.binary, "--home", self.home, "init", self.name, + "--chain-id", self.chain_id, "--default-denom", self.denom + ], capture_output=True, text=True) + + output = json.loads(result.stderr) + + return output["node_id"] + + def add_key(self, mnemonic, dryrun=False): + extra = [] + if dryrun: + extra = ["--dry-run"] + + result = subprocess.run([ + self.binary, "--output", "json", + "--home", self.home, "keys", "add", "validator", + "--keyring-backend", "test", "--recover" + ] + extra, capture_output=True, text=True, input=mnemonic) + + output = json.loads(result.stdout) + address = output["address"] + + return address + + def add_genesis_account(self, address, amount): + subprocess.run([ + self.binary, "--output", "json", "--home", self.home, "genesis", + "add-genesis-account", address, f"{amount}{self.denom}" + ]) + + def create_gentx(self, amount): + subprocess.run([ + self.binary, "--output", "json", "--home", self.home, "genesis", + "gentx", "validator", f"{amount}{self.denom}", + "--chain-id", self.chain_id, "--keyring-backend", "test" + ], capture_output=True, text=True) + + gentx_path = f"{self.home}/config/gentx" + gentx_file = os.listdir(gentx_path)[0] + gentx_data = json.load(open(f"{gentx_path}/{gentx_file}", "r")) + valoper = gentx_data["body"]["messages"][0]["validator_address"] + + return valoper + + def collectd_gentxs(self): + subprocess.run([ + self.binary, "--home", self.home, "genesis", "collect-gentxs" + ], capture_output=False, text=True) + + +def parse_args(): + parser = argparse.ArgumentParser() + parser.add_argument("-n", "--nodes", type=int, default=1, + choices=range(1, 9), metavar="[1-9]", + help="Set number of validator nodes") + parser.add_argument("--clear", action="store_true", + help="Remove all configs and create new chain") + parser.add_argument("--podman", action="store_true", + help="Generate start/stop scripts for podman") + + return parser.parse_args() + + +def get_persistent_peers(validators, node_id, podman): + persistent_peers = [] + for validator in validators: + if validator["node_id"] == node_id: + continue + + port = validator["app_port"] + host = validator["moniker"].lower() + peer = validator["node_id"] + if podman: + host = "127.0.0.1" + persistent_peers.append(f"{peer}@{host}:{port}") + + return persistent_peers + + +def init_chain(name, chain_id, binary, denom, nodes, port_prefix, mnemonics, podman): + info = { + "validators": [], + "accounts": [] + } + + total = 0 + + main = Node(f"{name}1", id, binary, denom, port_prefix) + + for i in range(nodes): + moniker = f"{name}{i+1}" + mnemonic = mnemonics["validators"][i] + + amount = 300_000_000_000 + staked = 200_000_000_000 + + total += amount + + node = Node(moniker, chain_id, binary, denom, port_prefix) + node_id = node.init() + address = node.add_key(mnemonic) + node.add_genesis_account(address, amount) + valoper = node.create_gentx(staked) + + # add account to "main" node + if i > 0: + main.add_genesis_account(address, amount) + + info["validators"].append({ + "moniker": moniker, + "address": address, + "valoper": valoper, + "node_id": node_id, + "mnemonic": mnemonic, + "api_port": f"{port_prefix}{i+1:02}17", + "app_port": f"{port_prefix}{i+1:02}56", + "rpc_port": f"{port_prefix}{i+1:02}57" + }) + + if i == 0: + continue + + gentx_path = f"{WORKDIR}/{moniker}/config/gentx" + gentx_file = os.listdir(gentx_path)[0] + + shutil.copyfile( + f"{gentx_path}/{gentx_file}", + f"{WORKDIR}/{name}1/config/gentx/{gentx_file}" + ) + + for i in range(0, len(mnemonics.get("accounts", []))): + mnemonic = mnemonics["accounts"][i] + + amount = 10_000_000_000_000 + total += amount + + address = node.add_key(mnemonic, True) + node.add_genesis_account(address, amount) + + info["accounts"].append({ + "address": address, + "mnemonic": mnemonic + }) + + # add ibc account + + mnemonic = mnemonics["relayer"] + + amount = 1_000_000_000_000 + total += amount + + address = node.add_key(mnemonic, True) + node.add_genesis_account(address, amount) + + info["ibc"] = { + "address": address, + "mnemonic": mnemonic + } + + node.collectd_gentxs() + + genesis = json.load(open(f"{node.home}/config/genesis.json")) + + genesis["app_state"]["crisis"]["constant_fee"]["denom"] = denom + genesis["app_state"]["denom"]["params"]["creation_fee"][0]["denom"] = denom + genesis["app_state"]["gov"]["params"]["min_deposit"][0]["denom"] = denom + genesis["app_state"]["gov"]["params"]["max_deposit_period"] = "20s" + genesis["app_state"]["gov"]["params"]["voting_period"] = "20s" + genesis["app_state"]["mint"]["minter"]["inflation"] = "0" + genesis["app_state"]["mint"]["params"]["mint_denom"] = denom + genesis["app_state"]["staking"]["params"]["unbonding_time"] = "1209600s" + genesis["app_state"]["staking"]["params"]["bond_denom"] = denom + + if name == "kujira-1": + genesis["app_state"]["oracle"]["params"]["whitelist"] = [ + {"name": "BTC"}, + {"name": "ETH"} + ] + + for i in range(nodes): + filename = f"{WORKDIR}/{name}{i+1}/config/genesis.json" + json.dump(genesis, open(filename, "w")) + + app_toml = jinja2.Template( + open("templates/app.toml.j2", "r").read() + ) + config_toml = jinja2.Template( + open("templates/config.toml.j2", "r").read() + ) + client_toml = jinja2.Template( + open("templates/client.toml.j2", "r").read() + ) + feeder_toml = jinja2.Template( + open("templates/feeder.toml.j2", "r").read() + ) + + for i, validator in enumerate(info["validators"]): + # validator nodes + + home = f"{WORKDIR}/{name}{i+1}" + + node_id = validator["node_id"] + + persistent_peers = get_persistent_peers( + info["validators"], node_id, podman + ) + + config = { + "api_port": f"{port_prefix}0{i+1}{17}", + "grpc_port": f"{port_prefix}0{i+1}{90}", + "app_port": f"{port_prefix}0{i+1}{56}", + "rpc_port": f"{port_prefix}0{i+1}{57}", + "abci_port": f"{port_prefix}0{i+1}{58}", + "pprof_port": f"{port_prefix}0{i+1}{60}", + "feeder_port": f"{port_prefix}0{i+1}{71}", + "persistent_peers": ",".join(persistent_peers), + "moniker": validator["moniker"], + "address": validator["address"], + "valoper": validator["valoper"], + "chain_id": chain_id, + "podman": podman + } + + open(f"{home}/config/app.toml", "w").write( + app_toml.render(config) + ) + + open(f"{home}/config/config.toml", "w").write( + config_toml.render(config) + ) + + open(f"{home}/config/client.toml", "w").write( + client_toml.render(config) + ) + + # feeders + if chain_id != "kujira-1": + continue + + home = f"{WORKDIR}/feeder1-{i+1}" + + if not os.path.isdir(home): + os.mkdir(home) + + open(f"{home}/config.toml", "w").write( + feeder_toml.render(config) + ) + + # fix info + + for i in range(nodes): + validator = info["validators"][i] + + validator["rpc_url"] = f"http://localhost:{validator['rpc_port']}" + validator["api_url"] = f"http://localhost:{validator['api_port']}" + validator.pop("app_port") + validator.pop("api_port") + validator.pop("rpc_port") + + info["validators"][i] = validator + + return info + + +def main(): + args = parse_args() + + if args.clear: + shutil.rmtree(WORKDIR, ignore_errors=True) + + if not os.path.isdir(WORKDIR): + os.mkdir(WORKDIR) + + config = { + "command": "docker", + "wallets": {}, + "validators": {}, + "version": { + "kujira": os.environ.get("KUJIRA_VERSION"), + "feeder": os.environ.get("FEEDER_VERSION"), + "relayer": os.environ.get("RELAYER_VERSION") + } + } + + if args.podman: + config["command"] = "podman" + + mnemonics = json.load(open("mnemonics.json", "r")) + + info1 = init_chain( + "kujira1-", "kujira-1", "kujirad", "ukuji", + args.nodes, 1, mnemonics, args.podman + ) + + info2 = init_chain( + "kujira2-", "kujira-2", "kujirad", "ukuji", 1, 2, mnemonics, args.podman + ) + + config["validators"] = { + "kujira-1": info1["validators"], + "kujira-2": info2["validators"] + } + + config["wallets"] = info1["accounts"] + config["ibc"] = info1["ibc"] + + # init relayer + + home = f"{WORKDIR}/relayer" + os.makedirs(f"{home}/config", exist_ok=True) + + relayer_yaml = jinja2.Template( + open("templates/relayer.yaml.j2", "r").read() + ) + + open(f"{home}/config/config.yaml", "w").write( + relayer_yaml.render({"podman": args.podman}) + ) + + shutil.copytree("keys", f"{home}/keys", dirs_exist_ok=True) + + json.dump(config, open(f"{WORKDIR}/pond.json", "w")) + + +if __name__ == "__main__": + main() diff --git a/prepare-kujira/templates/app.toml.j2 b/prepare/templates/app.toml.j2 similarity index 100% rename from prepare-kujira/templates/app.toml.j2 rename to prepare/templates/app.toml.j2 diff --git a/prepare-kujira/templates/client.toml.j2 b/prepare/templates/client.toml.j2 similarity index 100% rename from prepare-kujira/templates/client.toml.j2 rename to prepare/templates/client.toml.j2 diff --git a/prepare-kujira/templates/config.toml.j2 b/prepare/templates/config.toml.j2 similarity index 100% rename from prepare-kujira/templates/config.toml.j2 rename to prepare/templates/config.toml.j2 diff --git a/prepare-feeder/templates/config.toml.j2 b/prepare/templates/feeder.toml.j2 similarity index 100% rename from prepare-feeder/templates/config.toml.j2 rename to prepare/templates/feeder.toml.j2 diff --git a/prepare/templates/relayer.yaml.j2 b/prepare/templates/relayer.yaml.j2 new file mode 100644 index 0000000..aed6ef3 --- /dev/null +++ b/prepare/templates/relayer.yaml.j2 @@ -0,0 +1,45 @@ +global: + api-listen-addr: :5183 + timeout: 10s + memo: "" + light-cache-size: 20 + log-level: info + ics20-memo-limit: 0 + max-receiver-size: 150 +chains: +{% for i in [1, 2] %} + kujira-{{ i }}: + type: cosmos + value: + key-directory: /relayer/keys/kujira-{{ i }} + key: relayer + chain-id: kujira-{{ i }} + rpc-addr: http://{{ "127.0.0.1" if podman else "kujira%s-1" % i }}:{{ i }}0157 + account-prefix: kujira + keyring-backend: test + gas-adjustment: 1.5 + gas-prices: 0.01ukuji + min-gas-amount: 0 + max-gas-amount: 0 + debug: false + timeout: 20s + block-timeout: "" + output-format: json + sign-mode: direct + extra-codecs: [] + coin-type: 118 + signing-algorithm: "" + broadcast-mode: batch + min-loop-duration: 0s + extension-options: [] + feegrants: null +{% endfor %} +paths: + pond: + src: + chain-id: kujira-1 + dst: + chain-id: kujira-2 + src-channel-filter: + rule: "" + channel-list: [] diff --git a/relayer/Dockerfile b/relayer/Dockerfile new file mode 100644 index 0000000..56ae577 --- /dev/null +++ b/relayer/Dockerfile @@ -0,0 +1,23 @@ +ARG go_version +FROM golang:${go_version} AS build + +ARG relayer_version + +WORKDIR /build +RUN git clone --depth 1 --branch ${relayer_version} https://github.com/cosmos/relayer.git && \ + cd relayer && \ + make install + +WORKDIR /dist +RUN mkdir bin && \ + mv /go/bin/rly bin/ + +FROM ubuntu:latest + +COPY --from=build /dist/bin/* /usr/local/bin/ + +COPY entrypoint.sh link-and-start-pond.sh /usr/local/bin/ + +RUN chmod +x /usr/local/bin/* + +ENTRYPOINT ["entrypoint.sh"] \ No newline at end of file diff --git a/relayer/entrypoint.sh b/relayer/entrypoint.sh new file mode 100644 index 0000000..175f4b8 --- /dev/null +++ b/relayer/entrypoint.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +if [ -n "$USER" ]; then + useradd -u $USER kujira -d /kujira -m + chown -R kujira /kujira + + exec runuser -u kujira -- "$@" +else + $@ +fi diff --git a/relayer/link-and-start-pond.sh b/relayer/link-and-start-pond.sh new file mode 100644 index 0000000..34f9b87 --- /dev/null +++ b/relayer/link-and-start-pond.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +rly --home /relayer paths show pond -j | grep -q '"connection":false' && \ +rly --home /relayer tx link pond + +rly --home /relayer start \ No newline at end of file From b7c683b792f2cc538b9840dd7ac531893aa77676 Mon Sep 17 00:00:00 2001 From: starsquidnodes Date: Sat, 10 Feb 2024 14:57:22 +0100 Subject: [PATCH 09/10] Rename arch x86_64 to amd64 --- README.md | 2 +- build.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 08ca41a..e5e33c6 100644 --- a/README.md +++ b/README.md @@ -6,5 +6,5 @@ This repo provides the sources for all images needed to run the local Kujira dev ```sh ./build.py -n teamkujira -a kujira --push -./build.py --manifest --archs arm64,x86_64 +./build.py --manifest --archs arm64,amd64 ``` diff --git a/build.py b/build.py index 46d9b0b..5933083 100755 --- a/build.py +++ b/build.py @@ -49,6 +49,10 @@ def build_arg(s): def build(command, namespace, app, tag, push=False): arch = platform.machine() + + if arch == "x86_64": + arch = "amd64" + fulltag = f"{namespace}/{app}:{tag}-{arch}" cmd = [command, "build", "--tag", fulltag] From 70d69f9c510381552e4aa8caa9c19ee204f8edd0 Mon Sep 17 00:00:00 2001 From: starsquidnodes Date: Sun, 11 Feb 2024 08:15:17 +0100 Subject: [PATCH 10/10] Rename pond chains --- .../ca2106bb595bc2e6e1a2fd66c262da3a220c0f85.address | 0 .../{kujira-1 => pond-1}/keyring-test/relayer.info | 0 .../ca2106bb595bc2e6e1a2fd66c262da3a220c0f85.address | 0 .../{kujira-2 => pond-2}/keyring-test/relayer.info | 0 prepare/prepare.py | 12 ++++++------ prepare/templates/relayer.yaml.j2 | 10 +++++----- 6 files changed, 11 insertions(+), 11 deletions(-) rename prepare/keys/{kujira-1 => pond-1}/keyring-test/ca2106bb595bc2e6e1a2fd66c262da3a220c0f85.address (100%) rename prepare/keys/{kujira-1 => pond-1}/keyring-test/relayer.info (100%) rename prepare/keys/{kujira-2 => pond-2}/keyring-test/ca2106bb595bc2e6e1a2fd66c262da3a220c0f85.address (100%) rename prepare/keys/{kujira-2 => pond-2}/keyring-test/relayer.info (100%) diff --git a/prepare/keys/kujira-1/keyring-test/ca2106bb595bc2e6e1a2fd66c262da3a220c0f85.address b/prepare/keys/pond-1/keyring-test/ca2106bb595bc2e6e1a2fd66c262da3a220c0f85.address similarity index 100% rename from prepare/keys/kujira-1/keyring-test/ca2106bb595bc2e6e1a2fd66c262da3a220c0f85.address rename to prepare/keys/pond-1/keyring-test/ca2106bb595bc2e6e1a2fd66c262da3a220c0f85.address diff --git a/prepare/keys/kujira-1/keyring-test/relayer.info b/prepare/keys/pond-1/keyring-test/relayer.info similarity index 100% rename from prepare/keys/kujira-1/keyring-test/relayer.info rename to prepare/keys/pond-1/keyring-test/relayer.info diff --git a/prepare/keys/kujira-2/keyring-test/ca2106bb595bc2e6e1a2fd66c262da3a220c0f85.address b/prepare/keys/pond-2/keyring-test/ca2106bb595bc2e6e1a2fd66c262da3a220c0f85.address similarity index 100% rename from prepare/keys/kujira-2/keyring-test/ca2106bb595bc2e6e1a2fd66c262da3a220c0f85.address rename to prepare/keys/pond-2/keyring-test/ca2106bb595bc2e6e1a2fd66c262da3a220c0f85.address diff --git a/prepare/keys/kujira-2/keyring-test/relayer.info b/prepare/keys/pond-2/keyring-test/relayer.info similarity index 100% rename from prepare/keys/kujira-2/keyring-test/relayer.info rename to prepare/keys/pond-2/keyring-test/relayer.info diff --git a/prepare/prepare.py b/prepare/prepare.py index b67533f..32d9b2b 100755 --- a/prepare/prepare.py +++ b/prepare/prepare.py @@ -200,7 +200,7 @@ def init_chain(name, chain_id, binary, denom, nodes, port_prefix, mnemonics, pod genesis["app_state"]["staking"]["params"]["unbonding_time"] = "1209600s" genesis["app_state"]["staking"]["params"]["bond_denom"] = denom - if name == "kujira-1": + if chain_id == "pond-1": genesis["app_state"]["oracle"]["params"]["whitelist"] = [ {"name": "BTC"}, {"name": "ETH"} @@ -263,7 +263,7 @@ def init_chain(name, chain_id, binary, denom, nodes, port_prefix, mnemonics, pod ) # feeders - if chain_id != "kujira-1": + if chain_id != "pond-1": continue home = f"{WORKDIR}/feeder1-{i+1}" @@ -317,17 +317,17 @@ def main(): mnemonics = json.load(open("mnemonics.json", "r")) info1 = init_chain( - "kujira1-", "kujira-1", "kujirad", "ukuji", + "kujira1-", "pond-1", "kujirad", "ukuji", args.nodes, 1, mnemonics, args.podman ) info2 = init_chain( - "kujira2-", "kujira-2", "kujirad", "ukuji", 1, 2, mnemonics, args.podman + "kujira2-", "pond-2", "kujirad", "ukuji", 1, 2, mnemonics, args.podman ) config["validators"] = { - "kujira-1": info1["validators"], - "kujira-2": info2["validators"] + "pond-1": info1["validators"], + "pond-2": info2["validators"] } config["wallets"] = info1["accounts"] diff --git a/prepare/templates/relayer.yaml.j2 b/prepare/templates/relayer.yaml.j2 index aed6ef3..82c7459 100644 --- a/prepare/templates/relayer.yaml.j2 +++ b/prepare/templates/relayer.yaml.j2 @@ -8,12 +8,12 @@ global: max-receiver-size: 150 chains: {% for i in [1, 2] %} - kujira-{{ i }}: + pond-{{ i }}: type: cosmos value: - key-directory: /relayer/keys/kujira-{{ i }} + key-directory: /relayer/keys/pond-{{ i }} key: relayer - chain-id: kujira-{{ i }} + chain-id: pond-{{ i }} rpc-addr: http://{{ "127.0.0.1" if podman else "kujira%s-1" % i }}:{{ i }}0157 account-prefix: kujira keyring-backend: test @@ -37,9 +37,9 @@ chains: paths: pond: src: - chain-id: kujira-1 + chain-id: pond-1 dst: - chain-id: kujira-2 + chain-id: pond-2 src-channel-filter: rule: "" channel-list: []