66#![ deny( clippy:: large_futures) ]
77
88use std:: {
9- collections:: { BTreeMap , BTreeSet , HashMap } ,
9+ collections:: { BTreeMap , BTreeSet } ,
1010 env,
1111 ops:: Deref ,
1212 path:: PathBuf ,
@@ -23,11 +23,11 @@ use command::{ClientCommand, DatabaseToolCommand, NetCommand, ProjectCommand, Wa
2323use futures:: { lock:: Mutex , FutureExt as _, StreamExt } ;
2424use linera_base:: {
2525 bcs,
26- crypto:: { CryptoHash , InMemorySigner , Signer } ,
26+ crypto:: { InMemorySigner , Signer } ,
2727 data_types:: {
2828 ApplicationPermissions , ChainDescription , ChainOrigin , Epoch , InitialChainConfig , Timestamp ,
2929 } ,
30- identifiers:: { AccountOwner , ChainId } ,
30+ identifiers:: AccountOwner ,
3131 listen_for_shutdown_signals,
3232 ownership:: ChainOwnership ,
3333} ;
@@ -1235,48 +1235,6 @@ impl Runnable for Job {
12351235 ) ;
12361236 }
12371237
1238- Wallet ( WalletCommand :: Init {
1239- faucet : Some ( faucet_url) ,
1240- with_new_chain : true ,
1241- with_other_chains,
1242- ..
1243- } ) => {
1244- let start_time = Instant :: now ( ) ;
1245- let public_key = signer. mutate ( |s| s. generate_new ( ) ) . await ?;
1246- let mut context = ClientContext :: new (
1247- storage. clone ( ) ,
1248- options. inner . clone ( ) ,
1249- wallet,
1250- Box :: new ( signer. into_value ( ) ) ,
1251- ) ;
1252- let owner: AccountOwner = public_key. into ( ) ;
1253- info ! (
1254- "Requesting a new chain for owner {owner} using the faucet at address \
1255- {faucet_url}",
1256- ) ;
1257- let faucet = cli_wrappers:: Faucet :: new ( faucet_url) ;
1258- let outcome = faucet. claim ( & owner) . await ?;
1259- println ! ( "{}" , outcome. chain_id) ;
1260- println ! ( "{}" , outcome. certificate_hash) ;
1261- println ! ( "{}" , owner) ;
1262- context
1263- . assign_new_chain_to_key ( outcome. chain_id , owner)
1264- . await ?;
1265- let admin_id = context. wallet ( ) . genesis_admin_chain ( ) ;
1266- let chains = with_other_chains
1267- . into_iter ( )
1268- . chain ( [ admin_id, outcome. chain_id ] ) ;
1269- Self :: print_peg_certificate_hash ( storage, chains, & context) . await ?;
1270- context
1271- . wallet_mut ( )
1272- . mutate ( |w| w. set_default_chain ( outcome. chain_id ) )
1273- . await ??;
1274- info ! (
1275- "Wallet initialized in {} ms" ,
1276- start_time. elapsed( ) . as_millis( )
1277- ) ;
1278- }
1279-
12801238 Wallet ( WalletCommand :: RequestChain {
12811239 faucet : faucet_url,
12821240 set_default,
@@ -1328,67 +1286,6 @@ impl Runnable for Job {
13281286 }
13291287}
13301288
1331- impl Job {
1332- /// Prints a warning message to explain that the wallet has been initialized using data from
1333- /// untrusted nodes, and gives instructions to verify that we are connected to the right
1334- /// network.
1335- async fn print_peg_certificate_hash < S > (
1336- storage : S ,
1337- chain_ids : impl IntoIterator < Item = ChainId > ,
1338- context : & ClientContext < impl linera_core:: Environment , impl Persist < Target = Wallet > > ,
1339- ) -> anyhow:: Result < ( ) >
1340- where
1341- S : Storage + Clone + Send + Sync + ' static ,
1342- {
1343- let mut chains = HashMap :: new ( ) ;
1344- for chain_id in chain_ids {
1345- if chains. contains_key ( & chain_id) {
1346- continue ;
1347- }
1348- chains. insert ( chain_id, storage. load_chain ( chain_id) . await ?) ;
1349- }
1350- // Find a chain with the latest known epoch, preferably the admin chain.
1351- let ( peg_chain_id, _) = chains
1352- . iter ( )
1353- . filter_map ( |( chain_id, chain) | {
1354- let epoch = ( * chain. execution_state . system . epoch . get ( ) ) ?;
1355- let is_admin = Some ( * chain_id) == * chain. execution_state . system . admin_id . get ( ) ;
1356- Some ( ( * chain_id, ( epoch, is_admin) ) )
1357- } )
1358- . max_by_key ( |( _, epoch) | * epoch)
1359- . context ( "no active chain found" ) ?;
1360- let peg_chain = chains. remove ( & peg_chain_id) . unwrap ( ) ;
1361- // These are the still-trusted committees. Every chain tip should be signed by one of them.
1362- let committees = peg_chain. execution_state . system . committees . get ( ) ;
1363- for ( chain_id, chain) in & chains {
1364- let Some ( hash) = chain. tip_state . get ( ) . block_hash else {
1365- continue ; // This chain was created based on the genesis config.
1366- } ;
1367- let certificate = storage. read_certificate ( hash) . await ?;
1368- let committee = committees
1369- . get ( & certificate. block ( ) . header . epoch )
1370- . ok_or_else ( || anyhow ! ( "tip of chain {chain_id} is outdated." ) ) ?;
1371- certificate. check ( committee) ?;
1372- }
1373- // This proves that once we have verified that the peg chain's tip is a block in the real
1374- // network, we can be confident that all downloaded chains are.
1375- let config_hash = CryptoHash :: new ( context. wallet . genesis_config ( ) ) ;
1376- let maybe_epoch = peg_chain. execution_state . system . epoch . get ( ) ;
1377- let epoch = maybe_epoch. context ( "missing epoch in peg chain" ) ?. 0 ;
1378- info ! (
1379- "Initialized wallet based on data provided by the faucet.\n \
1380- The current epoch is {epoch}.\n \
1381- The genesis config hash is {config_hash}{}",
1382- if let Some ( peg_hash) = peg_chain. tip_state. get( ) . block_hash {
1383- format!( "\n The latest certificate on chain {peg_chain_id} is {peg_hash}." )
1384- } else {
1385- "" . to_string( )
1386- }
1387- ) ;
1388- Ok ( ( ) )
1389- }
1390- }
1391-
13921289#[ derive( Clone , clap:: Parser ) ]
13931290#[ command(
13941291 name = "linera" ,
@@ -2188,8 +2085,6 @@ async fn run(options: &ClientOptions) -> Result<i32, Error> {
21882085 WalletCommand :: Init {
21892086 genesis_config_path,
21902087 faucet,
2191- with_new_chain,
2192- with_other_chains,
21932088 testing_prng_seed,
21942089 } => {
21952090 let start_time = Instant :: now ( ) ;
@@ -2222,27 +2117,10 @@ Make sure to use a Linera client compatible with this network.
22222117 }
22232118 ( _, _) => bail ! ( "Either --faucet or --genesis must be specified, but not both" ) ,
22242119 } ;
2225- let timestamp = genesis_config. timestamp ;
22262120 let mut keystore = options. create_keystore ( * testing_prng_seed) ?;
22272121 keystore. persist ( ) . await ?;
2228- options
2229- . create_wallet ( genesis_config) ?
2230- . mutate ( |wallet| {
2231- wallet. extend (
2232- with_other_chains
2233- . iter ( )
2234- . map ( |chain_id| UserChain :: make_other ( * chain_id, timestamp) ) ,
2235- )
2236- } )
2237- . await ?;
2122+ options. create_wallet ( genesis_config) ?. persist ( ) . await ?;
22382123 options. initialize_storage ( ) . boxed ( ) . await ?;
2239- if * with_new_chain {
2240- ensure ! (
2241- faucet. is_some( ) ,
2242- "Using --with-new-chain requires --faucet to be set"
2243- ) ;
2244- options. run_with_storage ( Job ( options. clone ( ) ) ) . await ??;
2245- }
22462124 info ! (
22472125 "Wallet initialized in {} ms" ,
22482126 start_time. elapsed( ) . as_millis( )
0 commit comments