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