Skip to content

Commit f9372fa

Browse files
authored
Deduct genesis deposits and accounts from zero address during persistence conversion (#1856)
1 parent b4a443b commit f9372fa

File tree

4 files changed

+102
-104
lines changed

4 files changed

+102
-104
lines changed

z2/docs/converter.md

+2-3
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@ session later. Use `screen`)
4848
```
4949
screen -a
5050
export Z2_CONVERTER=true
51-
z2 converter convert <--convert-accounts|--convert-blocks> /my/dir/persistences/zq1 /my/dir/persistences/zq2 config.toml <secret key>
51+
z2 converter convert /my/dir/persistences/zq1 /my/dir/persistences/zq2 config.toml <secret key>
5252
```
5353

54-
The secret key is for a single validator which will be assumed to have 64 ZIL staked, so that the network has a validator on startup.
55-
This tool requires plenty of ram to convert both accounts and blocks in a single run. Therefore, it's possible to convert either accounts or blocks at once.
54+
The secret key is for a single validator which will be assumed to have 64 ZIL staked, so that the network has a validator on startup.

z2/src/bin/z2.rs

-15
Original file line numberDiff line numberDiff line change
@@ -241,20 +241,7 @@ struct ConvertConfigStruct {
241241
zq2_config_file: String,
242242
#[arg(value_parser = SecretKey::from_hex)]
243243
secret_key: SecretKey,
244-
#[clap(flatten)]
245-
convert_type_group: ConvertTypeGroup,
246244
}
247-
#[derive(Args, Debug)]
248-
#[group(required = true, multiple = false)]
249-
pub struct ConvertTypeGroup {
250-
#[clap(long)]
251-
#[arg(default_value_t = false)]
252-
convert_accounts: bool,
253-
#[clap(long)]
254-
#[arg(default_value_t = false)]
255-
convert_blocks: bool,
256-
}
257-
258245
#[derive(Args, Debug)]
259246
struct ConverterPrintTransactionConfigStruct {
260247
zq1_persistence_directory: String,
@@ -925,8 +912,6 @@ async fn main() -> Result<()> {
925912
&arg.zq2_data_dir,
926913
&arg.zq2_config_file,
927914
arg.secret_key,
928-
arg.convert_type_group.convert_accounts,
929-
arg.convert_type_group.convert_blocks,
930915
)
931916
.await?;
932917
Ok(())

z2/src/converter.rs

+99-75
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use tokio::sync::mpsc;
3434
use tracing::{info, trace, warn};
3535
use zilliqa::{
3636
block_store::BlockStore,
37-
cfg::{scilla_ext_libs_path_default, Config},
37+
cfg::{scilla_ext_libs_path_default, Amount, Config, NodeConfig},
3838
consensus::Validator,
3939
constants::SCILLA_INVOKE_CHECKER,
4040
contracts,
@@ -324,13 +324,42 @@ fn stop_scilla_docker(child: &mut Child) -> Result<ExitStatus> {
324324
.or(Err(anyhow!("Unable to stop docker container!")))
325325
}
326326

327+
fn deduct_funds_from_zero_account(state: &mut State, config: &NodeConfig) -> Result<()> {
328+
let total_requested_amount = config
329+
.consensus
330+
.total_native_token_supply
331+
.0
332+
.checked_add(
333+
config
334+
.consensus
335+
.genesis_accounts
336+
.iter()
337+
.fold(0, |acc, item: &(Address, Amount)| acc + item.1 .0),
338+
)
339+
.expect("Genesis accounts sum to more than max value of u128")
340+
.checked_add(
341+
config
342+
.consensus
343+
.genesis_deposits
344+
.iter()
345+
.fold(0, |acc, item| acc + item.stake.0),
346+
)
347+
.expect("Genesis accounts + genesis deposits sum to more than max value of u128");
348+
state.mutate_account(Address::ZERO, |acc| {
349+
acc.balance = acc.balance.checked_sub(total_requested_amount).expect("Sum of funds in genesis.deposit and genesis.accounts exceeds funds in ZeroAccount from zq1!");
350+
Ok(())
351+
})?;
352+
353+
// Flush any pending changes to db
354+
let _ = state.root_hash()?;
355+
Ok(())
356+
}
357+
327358
pub async fn convert_persistence(
328359
zq1_db: zq1::Db,
329360
zq2_db: Db,
330361
zq2_config: Config,
331362
secret_key: SecretKey,
332-
convert_accounts: bool,
333-
convert_blocks: bool,
334363
) -> Result<()> {
335364
let style = ProgressStyle::with_template(
336365
"{msg} {wide_bar} [{per_sec}] {human_pos}/~{human_len} ({elapsed}/~{duration})",
@@ -359,88 +388,83 @@ pub async fn convert_persistence(
359388
block_store,
360389
)?;
361390

362-
if convert_accounts {
363-
let mut scilla_docker = run_scilla_docker()?;
364-
// Calculate an estimate for the number of accounts by taking the first 100 accounts, calculating the distance
365-
// between pairs of adjacent addresses, taking the average and extrapolating to the end of the key space.
366-
let distance_sum: u64 = zq1_db
367-
.accounts()
368-
.map(|(addr, _)| addr)
369-
.take(100)
370-
.tuple_windows()
371-
.map(|(a, b)| {
372-
// Downsample the addresses to 8 bytes, treating them as `u64`s, for ease of computation.
373-
let a = u64::from_be_bytes(a.as_slice()[..8].try_into().unwrap());
374-
let b = u64::from_be_bytes(b.as_slice()[..8].try_into().unwrap());
375-
376-
b - a
377-
})
378-
.sum();
379-
let average_distance = distance_sum as f64 / 99.;
380-
let address_count = ((u64::MAX as f64) / average_distance) as u64;
381-
382-
let progress = ProgressBar::new(address_count)
383-
.with_style(style.clone())
384-
.with_message("collect accounts")
385-
.with_finish(ProgressFinish::AndLeave);
391+
let mut scilla_docker = run_scilla_docker()?;
392+
// Calculate an estimate for the number of accounts by taking the first 100 accounts, calculating the distance
393+
// between pairs of adjacent addresses, taking the average and extrapolating to the end of the key space.
394+
let distance_sum: u64 = zq1_db
395+
.accounts()
396+
.map(|(addr, _)| addr)
397+
.take(100)
398+
.tuple_windows()
399+
.map(|(a, b)| {
400+
// Downsample the addresses to 8 bytes, treating them as `u64`s, for ease of computation.
401+
let a = u64::from_be_bytes(a.as_slice()[..8].try_into().unwrap());
402+
let b = u64::from_be_bytes(b.as_slice()[..8].try_into().unwrap());
403+
404+
b - a
405+
})
406+
.sum();
407+
let average_distance = distance_sum as f64 / 99.;
408+
let address_count = ((u64::MAX as f64) / average_distance) as u64;
386409

387-
let accounts: Vec<_> = zq1_db.accounts().progress_with(progress).collect();
410+
let progress = ProgressBar::new(address_count)
411+
.with_style(style.clone())
412+
.with_message("collect accounts")
413+
.with_finish(ProgressFinish::AndLeave);
388414

389-
let progress = ProgressBar::new(accounts.len() as u64)
390-
.with_style(style.clone())
391-
.with_message("convert accounts")
392-
.with_finish(ProgressFinish::AndLeave);
415+
let accounts: Vec<_> = zq1_db.accounts().progress_with(progress).collect();
393416

394-
for (address, zq1_account) in accounts.into_iter().progress_with(progress) {
395-
if address.is_zero() {
396-
continue;
397-
}
398-
let zq1_account = zq1::Account::from_proto(zq1_account)?;
417+
let progress = ProgressBar::new(accounts.len() as u64)
418+
.with_style(style.clone())
419+
.with_message("convert accounts")
420+
.with_finish(ProgressFinish::AndLeave);
399421

400-
let code = get_contract_code(&zq1_db, address)?;
422+
for (address, zq1_account) in accounts.into_iter().progress_with(progress) {
423+
if address.is_zero() {
424+
continue;
425+
}
426+
let zq1_account = zq1::Account::from_proto(zq1_account)?;
401427

402-
let (code, storage_root) = match code {
403-
Code::Evm(evm_code) if !evm_code.is_empty() => {
404-
let storage_root = convert_evm_state(&zq1_db, &zq2_db, address)?;
405-
(Code::Evm(evm_code), storage_root)
406-
}
407-
Code::Scilla {
408-
code, init_data, ..
409-
} => {
410-
let (storage_root, types, transitions) =
411-
convert_scilla_state(&zq1_db, &zq2_db, &state, &code, &init_data, address)?;
412-
(
413-
Code::Scilla {
414-
code,
415-
init_data,
416-
types,
417-
transitions,
418-
},
419-
storage_root,
420-
)
421-
}
422-
_ => (code, EMPTY_ROOT_HASH),
423-
};
428+
let code = get_contract_code(&zq1_db, address)?;
424429

425-
let account = Account {
426-
nonce: zq1_account.nonce,
427-
balance: zq1_account.balance * 10u128.pow(6),
428-
code,
429-
storage_root,
430-
};
430+
let (code, storage_root) = match code {
431+
Code::Evm(evm_code) if !evm_code.is_empty() => {
432+
let storage_root = convert_evm_state(&zq1_db, &zq2_db, address)?;
433+
(Code::Evm(evm_code), storage_root)
434+
}
435+
Code::Scilla {
436+
code, init_data, ..
437+
} => {
438+
let (storage_root, types, transitions) =
439+
convert_scilla_state(&zq1_db, &zq2_db, &state, &code, &init_data, address)?;
440+
(
441+
Code::Scilla {
442+
code,
443+
init_data,
444+
types,
445+
transitions,
446+
},
447+
storage_root,
448+
)
449+
}
450+
_ => (code, EMPTY_ROOT_HASH),
451+
};
431452

432-
state.save_account(address, account)?;
433-
// Flush any pending changes to db
434-
let _ = state.root_hash()?;
435-
}
453+
let account = Account {
454+
nonce: zq1_account.nonce,
455+
balance: zq1_account.balance * 10u128.pow(6),
456+
code,
457+
storage_root,
458+
};
436459

437-
stop_scilla_docker(&mut scilla_docker)?;
460+
state.save_account(address, account)?;
461+
// Flush any pending changes to db
462+
let _ = state.root_hash()?;
438463
}
439464

440-
if !convert_blocks {
441-
println!("Accounts converted. Skipping blocks.");
442-
return Ok(());
443-
}
465+
stop_scilla_docker(&mut scilla_docker)?;
466+
467+
deduct_funds_from_zero_account(&mut state, node_config)?;
444468

445469
let max_block = zq1_db
446470
.get_tx_blocks_aux("MaxTxBlockNumber")?

z2/src/plumbing.rs

+1-11
Original file line numberDiff line numberDiff line change
@@ -353,8 +353,6 @@ pub async fn run_persistence_converter(
353353
zq2_data_dir: &str,
354354
zq2_config: &str,
355355
secret_key: SecretKey,
356-
convert_accounts: bool,
357-
convert_blocks: bool,
358356
) -> Result<()> {
359357
println!("🐼 Converting {zq1_pers_dir} into {zq2_data_dir}.. ");
360358
let zq1_dir = PathBuf::from_str(zq1_pers_dir)?;
@@ -369,15 +367,7 @@ pub async fn run_persistence_converter(
369367
node_config.state_cache_size,
370368
)?;
371369
let zq1_db = zq1::Db::new(zq1_dir)?;
372-
converter::convert_persistence(
373-
zq1_db,
374-
zq2_db,
375-
zq2_config,
376-
secret_key,
377-
convert_accounts,
378-
convert_blocks,
379-
)
380-
.await?;
370+
converter::convert_persistence(zq1_db, zq2_db, zq2_config, secret_key).await?;
381371
Ok(())
382372
}
383373

0 commit comments

Comments
 (0)