1use std::net::SocketAddr;
3
4use crate::{
5 check_abi::CheckAbi, generate_devnet::GenerateDevnet, generate_genesis::GenerateGenesis,
6 generate_localnet::GenerateLocalnet, generate_state_bloat::GenerateStateBloat,
7 get_dkg_outcome::GetDkgOutcome,
8};
9
10use alloy::signers::{local::MnemonicBuilder, utils::secret_key_to_address};
11use clap::Parser as _;
12use commonware_codec::DecodeExt;
13use eyre::Context;
14
15mod check_abi;
16mod generate_devnet;
17mod generate_genesis;
18mod generate_localnet;
19mod generate_state_bloat;
20mod genesis_args;
21mod get_dkg_outcome;
22
23#[tokio::main]
24async fn main() -> eyre::Result<()> {
25 let args = Args::parse();
26 match args.action {
27 Action::CheckAbi(args) => args.run().wrap_err("failed ABI alignment check"),
28 Action::GetDkgOutcome(args) => args.run().await.wrap_err("failed to get DKG outcome"),
29 Action::GenerateGenesis(args) => args.run().await.wrap_err("failed generating genesis"),
30 Action::GenerateDevnet(args) => args
31 .run()
32 .await
33 .wrap_err("failed to generate devnet configs"),
34 Action::GenerateLocalnet(args) => args
35 .run()
36 .await
37 .wrap_err("failed to generate localnet configs"),
38 Action::GenerateAddPeer(cfg) => generate_config_to_add_peer(cfg),
39 Action::GenerateStateBloat(args) => args
40 .run()
41 .await
42 .wrap_err("failed to generate state bloat file"),
43 }
44}
45
46#[derive(Debug, clap::Parser)]
47#[command(author)]
48#[command(version)]
49#[command(about)]
50#[command(long_about = None)]
51struct Args {
52 #[command(subcommand)]
53 action: Action,
54}
55
56#[derive(Debug, clap::Subcommand)]
57enum Action {
58 CheckAbi(CheckAbi),
59 GetDkgOutcome(GetDkgOutcome),
60 GenerateGenesis(GenerateGenesis),
61 GenerateDevnet(GenerateDevnet),
62 GenerateLocalnet(GenerateLocalnet),
63 GenerateAddPeer(GenerateAddPeer),
64 GenerateStateBloat(GenerateStateBloat),
65}
66
67#[derive(Debug, clap::Args)]
68struct GenerateAddPeer {
69 #[arg(long)]
70 public_key: String,
71
72 #[arg(long)]
73 inbound_address: SocketAddr,
74
75 #[arg(long)]
76 rpc_endpoint: String,
77
78 #[arg(long, default_value_t = 0)]
79 admin_index: u32,
80
81 #[arg(long, default_value_t = 20)]
82 validator_index: u32,
83
84 #[arg(
85 short,
86 long,
87 default_value = "test test test test test test test test test test test junk"
88 )]
89 pub mnemonic: String,
90}
91
92fn generate_config_to_add_peer(
93 GenerateAddPeer {
94 public_key,
95 inbound_address,
96 admin_index,
97 validator_index,
98 rpc_endpoint,
99 mnemonic,
100 }: GenerateAddPeer,
101) -> eyre::Result<()> {
102 use tempo_precompiles::VALIDATOR_CONFIG_ADDRESS;
103 let public_key_bytes = const_hex::decode(&public_key)?;
104 let public_key = commonware_cryptography::ed25519::PublicKey::decode(&public_key_bytes[..])?;
105
106 let admin_key = const_hex::encode(
107 MnemonicBuilder::from_phrase_nth(&mnemonic, admin_index)
108 .credential()
109 .to_bytes(),
110 );
111
112 let validator_address = {
113 secret_key_to_address(
114 MnemonicBuilder::from_phrase_nth(mnemonic, validator_index).credential(),
115 )
116 };
117 let inbound = inbound_address.to_string();
118 let outbound = inbound_address.to_string();
119 println!(
120 "\
121 cast send {VALIDATOR_CONFIG_ADDRESS} \
122 \\\n\"addValidator(address newValidatorAddress, bytes32 publicKey, bool active, string calldata inboundAddress, string calldata outboundAddress)\" \
123 \\\n\"{validator_address}\" \
124 \\\n\"{public_key}\" \
125 \\\n\"true\" \
126 \\\n\"{inbound}\" \
127 \\\n\"{outbound}\" \
128 \\\n--private-key {admin_key} \
129 \\\n-r {rpc_endpoint}"
130 );
131 Ok(())
132}