Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
circleci 0.1.31425
golang 1.24.5
circleci 0.1.31425
golang 1.26.3
golangci-lint 1.64.5
nodejs 18.17.0
postgres 14.2
pre-commit 4.1.0
protoc 29.3
shfmt 3.10.0
solidity 0.8.9
sqlc 1.28.0
nodejs 18.17.0
postgres 18.3
pre-commit 4.1.0
protoc 29.3
shfmt 3.10.0
solidity 0.8.9
sqlc latest
3 changes: 2 additions & 1 deletion mise-test-setup/mise-tasks/add-initial-keyper-set
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
#!/usr/bin/env -S uv run --script
# fmt: off
#MISE description="Add the initial keyper set on-chain"
#MISE depends=["gen-keyper-configs"]
# fmt: on

import json
import os
from pathlib import Path

import utils


deployment_type = utils.resolve_deployment_type(os.environ.get("DEPLOYMENT_TYPE", ""))
data_dir = Path(os.environ["DATA_DIR"])
run_path = (
Expand Down
11 changes: 8 additions & 3 deletions mise-test-setup/mise-tasks/add-keyper-set
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
#!/usr/bin/env -S uv run --script
# fmt: off
#MISE description="Add a keyper set on-chain"
#MISE depends=["gen-keyper-configs"]
#USAGE flag "--indices <indices>" help="Comma-separated keyper indices"
#USAGE flag "--threshold <threshold>" help="Keyper set threshold"
# fmt: on

import json
import os
from pathlib import Path

import utils


deployment_type = utils.resolve_deployment_type(os.environ.get("DEPLOYMENT_TYPE", ""))
data_dir = Path(os.environ["DATA_DIR"])
indices = utils.parse_indices(os.environ["usage_indices"])
Expand All @@ -24,8 +25,12 @@ run_path = (
/ "run-latest.json"
)
deployment_run = json.loads(run_path.read_text())
keyper_set_manager = utils.get_created_contract_address(deployment_run, "KeyperSetManager")
key_broadcast_contract = utils.get_created_contract_address(deployment_run, "KeyBroadcastContract")
keyper_set_manager = utils.get_created_contract_address(
deployment_run, "KeyperSetManager"
)
key_broadcast_contract = utils.get_created_contract_address(
deployment_run, "KeyBroadcastContract"
)
keyper_addresses = ",".join(
utils.keyper_address(data_dir / f"keyper-{index}.toml") for index in indices
)
Expand Down
2 changes: 2 additions & 0 deletions mise-test-setup/mise-tasks/build-image
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/usr/bin/env bash
# fmt: off
#MISE description="Build the rolling-shutter image"
# fmt: on

docker build \
-f ../docker/build-src/rolling-shutter/Dockerfile \
Expand Down
2 changes: 2 additions & 0 deletions mise-test-setup/mise-tasks/clean
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#!/usr/bin/env bash
# fmt: off
#MISE description="Delete all generated files"
#MISE depends=["down"]
# fmt: on

rm -rf "${DATA_DIR}"
rm -rf "${GENERATED_DIR}"
93 changes: 75 additions & 18 deletions mise-test-setup/mise-tasks/deploy
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
#!/usr/bin/env -S uv run --script
# fmt: off
#MISE description="Deploy contracts if not already deployed"
#MISE depends=["up-ethereum"]
# fmt: on

import os
import json
import os
from pathlib import Path

import utils

RPC = "http://127.0.0.1:8545"

REQUIRED_CONTRACTS: dict[str, list[str]] = {
"gnosis": [
"KeyBroadcastContract",
Expand All @@ -30,28 +35,80 @@ def deployment_is_complete(path: Path, deployment_type: str) -> bool:
return True


def deploy_test_helper(data_dir: Path) -> None:
addr_path = data_dir / "test-helper-addr.json"
if addr_path.exists():
addr = json.loads(addr_path.read_text())["address"]
print(f"EventTriggerTestHelper already deployed at {addr}")
return

artifact = json.loads(
(
data_dir
/ "contracts"
/ "out"
/ "EventTriggerTestHelper.sol"
/ "EventTriggerTestHelper.json"
).read_text()
)
bytecode_hex = artifact["bytecode"]["object"].removeprefix("0x")

result = utils.run(
[
"docker",
"compose",
"exec",
"-T",
"ethereum",
"cast",
"send",
"--json",
"--rpc-url",
RPC,
"--private-key",
os.environ["DEPLOY_KEY"],
"--create",
bytecode_hex,
],
capture_output=True,
)
receipt = json.loads(result.stdout.strip())
addr = receipt.get("contractAddress") or receipt.get("creates")
if not addr:
raise SystemExit(
f"Could not find contractAddress in receipt:\n{json.dumps(receipt, indent=2)}"
)

addr_path.write_text(json.dumps({"address": addr}))
print(f"EventTriggerTestHelper deployed at {addr}")


deployment_type = utils.resolve_deployment_type(os.environ.get("DEPLOYMENT_TYPE", ""))

deploy_script = utils.DEPLOYMENT_SCRIPTS[deployment_type]
data_dir = Path(os.environ["DATA_DIR"])
chain_id = os.environ["ETHEREUM_CHAIN_ID"]
run_path = data_dir / "contracts" / "broadcast" / deploy_script / chain_id / "run-latest.json"
run_path = (
data_dir / "contracts" / "broadcast" / deploy_script / chain_id / "run-latest.json"
)

if deployment_is_complete(run_path, deployment_type):
print(f"Deployment already present at {run_path}; skipping")
raise SystemExit(0)

utils.run(
[
"docker",
"compose",
"run",
"--rm",
"--env",
f"DEPLOY_KEY={os.environ['DEPLOY_KEY']}",
"contracts",
"script",
f"/app/script/{deploy_script}:Deploy",
"--broadcast",
]
)
else:
utils.run(
[
"docker",
"compose",
"run",
"--rm",
"--env",
f"DEPLOY_KEY={os.environ['DEPLOY_KEY']}",
"contracts",
"script",
f"/app/script/{deploy_script}:Deploy",
"--broadcast",
]
)

if deployment_type == "service":
deploy_test_helper(data_dir)
2 changes: 2 additions & 0 deletions mise-test-setup/mise-tasks/down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/usr/bin/env bash
# fmt: off
#MISE description="Stop the docker3 stack"
# fmt: on

if [ -f "${GENERATED_DIR}/compose.yml" ]; then
docker compose down || true
Expand Down
5 changes: 3 additions & 2 deletions mise-test-setup/mise-tasks/gen-compose
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
#!/usr/bin/env -S uv run --script
# fmt: off
#MISE description="Render docker compose files based on DEPLOYMENT_TYPE"
# /// script
# dependencies = ["jinja2"]
# ///
# fmt: on

import os
from pathlib import Path

from jinja2 import Environment, FileSystemLoader
import utils

from jinja2 import Environment, FileSystemLoader

deployment_type = utils.resolve_deployment_type(os.environ.get("DEPLOYMENT_TYPE", ""))
generated_dir = Path(os.environ["GENERATED_DIR"])
Expand Down
81 changes: 67 additions & 14 deletions mise-test-setup/mise-tasks/gen-keyper-configs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#!/usr/bin/env -S uv run --script
# fmt: off
#MISE description="Ensure config files for all keypers"
#MISE depends=["deploy"]
# /// script
# dependencies = ["tomlkit"]
# ///
# fmt: on

import os
import json
import os
from pathlib import Path

import tomlkit
Expand Down Expand Up @@ -52,22 +54,73 @@ for index in range(int(os.environ["NUM_KEYPERS"])):
)

document = tomlkit.parse(config_path.read_text())
utils.set_toml_path(document, ["DatabaseURL"], f"postgresql://postgres@db:5432/keyper-{index}")
utils.set_toml_path(document, ["Shuttermint", "ShuttermintURL"], f"http://chain-{index}:{os.environ['SHUTTERMINT_RPC_PORT']}")
utils.set_toml_path(document, ["Shuttermint", "DKGPhaseLength"], int(os.environ["SHUTTERMINT_DKG_PHASE_LENGTH"]))
utils.set_toml_path(document, ["Shuttermint", "StartBlockDelta"], int(os.environ["SHUTTERMINT_START_BLOCK_DELTA"]))
utils.set_toml_path(document, ["P2P", "CustomBootstrapAddresses"], bootstrap_addresses)
utils.set_toml_path(document, ["Chain", "Contracts", "KeyBroadcastContract"], utils.get_created_contract_address(deployment_run, "KeyBroadcastContract"))
utils.set_toml_path(document, ["Chain", "Contracts", "KeyperSetManager"], utils.get_created_contract_address(deployment_run, "KeyperSetManager"))
utils.set_toml_path(
document, ["DatabaseURL"], f"postgresql://postgres@db:5432/keyper-{index}"
)
utils.set_toml_path(
document,
["Shuttermint", "ShuttermintURL"],
f"http://chain-{index}:{os.environ['SHUTTERMINT_RPC_PORT']}",
)
utils.set_toml_path(
document,
["Shuttermint", "DKGPhaseLength"],
int(os.environ["SHUTTERMINT_DKG_PHASE_LENGTH"]),
)
utils.set_toml_path(
document,
["Shuttermint", "StartBlockDelta"],
int(os.environ["SHUTTERMINT_START_BLOCK_DELTA"]),
)
utils.set_toml_path(
document, ["P2P", "CustomBootstrapAddresses"], bootstrap_addresses
)
utils.set_toml_path(
document,
["Chain", "Contracts", "KeyBroadcastContract"],
utils.get_created_contract_address(deployment_run, "KeyBroadcastContract"),
)
utils.set_toml_path(
document,
["Chain", "Contracts", "KeyperSetManager"],
utils.get_created_contract_address(deployment_run, "KeyperSetManager"),
)

if deployment_type == "gnosis":
utils.set_toml_path(document, ["Gnosis", "Node", "EthereumURL"], "ws://ethereum:8545")
utils.set_toml_path(document, ["Chain", "Contracts", "Sequencer"], utils.get_created_contract_address(deployment_run, "Sequencer"))
utils.set_toml_path(document, ["Chain", "Contracts", "ValidatorRegistry"], utils.get_created_contract_address(deployment_run, "ValidatorRegistry"))
utils.set_toml_path(
document, ["Gnosis", "Node", "EthereumURL"], "ws://ethereum:8545"
)
utils.set_toml_path(
document,
["Chain", "Contracts", "Sequencer"],
utils.get_created_contract_address(deployment_run, "Sequencer"),
)
utils.set_toml_path(
document,
["Chain", "Contracts", "ValidatorRegistry"],
utils.get_created_contract_address(deployment_run, "ValidatorRegistry"),
)
elif deployment_type == "service":
utils.set_toml_path(document, ["Chain", "Node", "EthereumURL"], "ws://ethereum:8545")
utils.set_toml_path(document, ["Chain", "Contracts", "ShutterRegistry"], utils.get_created_contract_address(deployment_run, "ShutterRegistry"))
utils.set_toml_path(
document, ["Chain", "Node", "EthereumURL"], "ws://ethereum:8545"
)
utils.set_toml_path(
document,
["Chain", "Contracts", "ShutterRegistry"],
utils.get_created_contract_address(deployment_run, "ShutterRegistry"),
)
event_trigger_registry = utils.get_uups_proxy_address(
deployment_run, "ShutterEventTriggerRegistryV1"
)
if event_trigger_registry:
utils.set_toml_path(
document,
["Chain", "Contracts", "ShutterEventTriggerRegistry"],
event_trigger_registry,
)
else:
raise SystemExit(f"Unsupported DEPLOYMENT_TYPE for config generation: {deployment_type}")
raise SystemExit(
f"Unsupported DEPLOYMENT_TYPE for config generation: {deployment_type}"
)

config_path.write_text(tomlkit.dumps(document))
11 changes: 8 additions & 3 deletions mise-test-setup/mise-tasks/init-chain-nodes
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
#!/usr/bin/env -S uv run --script
# fmt: off
#MISE description="Initialize shuttermint chain nodes for all keypers"
#MISE depends=["init-chain-seed", "gen-keyper-configs"]
# /// script
# dependencies = ["tomlkit"]
# ///
# fmt: on

import os
from pathlib import Path

import tomlkit
import utils


data_dir = Path(os.environ["DATA_DIR"])
seed_node_id_path = data_dir / "chain-seed" / "config" / "node_key.json.id"
seed_node_id = seed_node_id_path.read_text().strip()

for index in range(int(os.environ["NUM_KEYPERS"])):
config_path = data_dir / f"chain-{index}" / "config" / "config.toml"
validator_pubkey_path = data_dir / f"chain-{index}" / "config" / "priv_validator_pubkey.hex"
validator_pubkey_path = (
data_dir / f"chain-{index}" / "config" / "priv_validator_pubkey.hex"
)
keyper_config_path = data_dir / f"keyper-{index}.toml"

if not config_path.exists():
Expand Down Expand Up @@ -56,5 +59,7 @@ for index in range(int(os.environ["NUM_KEYPERS"])):

validator_pubkey = validator_pubkey_path.read_text().strip()
keyper_document = tomlkit.parse(keyper_config_path.read_text())
utils.set_toml_path(keyper_document, ["Shuttermint", "ValidatorPublicKey"], validator_pubkey)
utils.set_toml_path(
keyper_document, ["Shuttermint", "ValidatorPublicKey"], validator_pubkey
)
keyper_config_path.write_text(tomlkit.dumps(keyper_document))
3 changes: 2 additions & 1 deletion mise-test-setup/mise-tasks/init-chain-seed
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
#!/usr/bin/env -S uv run --script
# fmt: off
#MISE description="Initialize the shuttermint seed node"
#MISE depends=["gen-compose"]
#MISE outputs=["{{env.DATA_DIR}}/chain-seed/config/config.toml"]
# /// script
# dependencies = ["tomlkit"]
# ///
# fmt: on

import os
from pathlib import Path

import tomlkit
import utils


data_dir = Path(os.environ["DATA_DIR"])
config_path = data_dir / "chain-seed" / "config" / "config.toml"

Expand Down
Loading