Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(genesis-geremony): fix examine-genesis-checkpoint #4829

Merged
merged 14 commits into from
Jan 28, 2025
Merged
7 changes: 6 additions & 1 deletion crates/iota-genesis-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ impl Builder {
}
}

pub fn tx_migration_objects(self) -> Vec<Object> {
miker83z marked this conversation as resolved.
Show resolved Hide resolved
self.migration_tx_data.unwrap().get_objects().collect()
nonast marked this conversation as resolved.
Show resolved Hide resolved
}

pub fn with_delegator(mut self, delegator: IotaAddress) -> Self {
self.delegation = Some(GenesisDelegation::OneToAll(delegator));
self
Expand Down Expand Up @@ -259,8 +263,9 @@ impl Builder {
self.built_genesis.clone()
}

fn load_migration_sources(&mut self) -> anyhow::Result<()> {
pub fn load_migration_sources(&mut self) -> anyhow::Result<()> {
for source in &self.migration_sources {
println!("Adding migration objects from {:?}", source);
miker83z marked this conversation as resolved.
Show resolved Hide resolved
tracing::info!("Adding migration objects from {:?}", source);
self.migration_objects
.extend(bcs::from_reader::<Vec<_>>(source.to_reader()?)?);
Expand Down
25 changes: 25 additions & 0 deletions crates/iota-types/src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ use crate::{
is_system_package,
layout_resolver::LayoutResolver,
move_package::MovePackage,
stardust::output::{AliasOutput, BasicOutput, NftOutput},
timelock::timelock::TimeLock,
};

Expand Down Expand Up @@ -819,6 +820,30 @@ impl ObjectInner {
}
}

pub fn as_alias_output_maybe(&self) -> Option<AliasOutput> {
nonast marked this conversation as resolved.
Show resolved Hide resolved
if let Some(move_object) = self.data.try_as_move() {
Some(AliasOutput::from_bcs_bytes(move_object.contents()).ok()?)
} else {
None
}
}

pub fn as_basic_output_maybe(&self) -> Option<BasicOutput> {
if let Some(move_object) = self.data.try_as_move() {
Some(BasicOutput::from_bcs_bytes(move_object.contents()).ok()?)
} else {
None
}
}

pub fn as_nft_output_maybe(&self) -> Option<NftOutput> {
if let Some(move_object) = self.data.try_as_move() {
Some(NftOutput::from_bcs_bytes(move_object.contents()).ok()?)
} else {
None
}
}

pub fn coin_type_maybe(&self) -> Option<TypeTag> {
if let Some(move_object) = self.data.try_as_move() {
move_object.type_().coin_type_maybe()
Expand Down
10 changes: 10 additions & 0 deletions crates/iota-types/src/stardust/output/alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,14 @@ impl AliasOutput {

Ok(move_alias_output_object)
}

/// Create a `AliasOutput` from BCS bytes.
nonast marked this conversation as resolved.
Show resolved Hide resolved
pub fn from_bcs_bytes(content: &[u8]) -> Result<Self, bcs::Error> {
bcs::from_bytes(content)
}
nonast marked this conversation as resolved.
Show resolved Hide resolved

/// Serialize a `AliasOutput` as a `Vec<u8>` of BCS.
nonast marked this conversation as resolved.
Show resolved Hide resolved
pub fn to_bcs_bytes(&self) -> Vec<u8> {
bcs::to_bytes(&self).unwrap()
nonast marked this conversation as resolved.
Show resolved Hide resolved
}
}
10 changes: 10 additions & 0 deletions crates/iota-types/src/stardust/output/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,16 @@ impl BasicOutput {
coin_type,
)
}

/// Create a `BasicOutput` from BCS bytes.
pub fn from_bcs_bytes(content: &[u8]) -> std::result::Result<Self, bcs::Error> {
bcs::from_bytes(content)
}

/// Serialize a `BasicOutput` as a `Vec<u8>` of BCS.
pub fn to_bcs_bytes(&self) -> Vec<u8> {
bcs::to_bytes(&self).unwrap()
}
}

pub(crate) fn create_coin(
Expand Down
10 changes: 10 additions & 0 deletions crates/iota-types/src/stardust/output/nft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -469,4 +469,14 @@ impl NftOutput {

Ok(move_nft_output_object)
}

/// Create a `NftOutput` from BCS bytes.
miker83z marked this conversation as resolved.
Show resolved Hide resolved
pub fn from_bcs_bytes(content: &[u8]) -> std::result::Result<Self, bcs::Error> {
nonast marked this conversation as resolved.
Show resolved Hide resolved
bcs::from_bytes(content)
}

/// Serialize a `NftOutput` as a `Vec<u8>` of BCS.
pub fn to_bcs_bytes(&self) -> Vec<u8> {
bcs::to_bytes(&self).unwrap()
}
}
9 changes: 8 additions & 1 deletion crates/iota/src/genesis_ceremony.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,14 @@ pub async fn run(cmd: Ceremony) -> Result<()> {
));
};

examine_genesis_checkpoint(unsigned_genesis);
let migration_objects = builder.tx_migration_objects();

println!(
"Total number of migration objects: {}",
migration_objects.len()
);

examine_genesis_checkpoint(unsigned_genesis, migration_objects);
}

CeremonyCommand::VerifyAndSign { key_file } => {
Expand Down
124 changes: 119 additions & 5 deletions crates/iota/src/genesis_inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,35 @@ use std::collections::BTreeMap;
use inquire::Select;
use iota_config::genesis::UnsignedGenesis;
use iota_types::{
balance::Balance,
base_types::ObjectID,
coin::CoinMetadata,
gas_coin::{GasCoin, IotaTreasuryCap, NANOS_PER_IOTA},
governance::StakedIota,
iota_system_state::IotaValidatorGenesis,
move_package::MovePackage,
object::{MoveObject, Owner},
object::{MoveObject, Object, Owner},
stardust::output::{AliasOutput, BasicOutput, NftOutput},
timelock::{timelock::TimeLock, timelocked_staked_iota::TimelockedStakedIota},
};

const STR_ALL: &str = "All";
const STR_EXIT: &str = "Exit";
const STR_IOTA: &str = "Iota";
const STR_STAKED_IOTA: &str = "StakedIota";
const STR_TIMELOCKED_IOTA: &str = "TimelockedIota";
const STR_TIMELOCKED_STAKED_IOTA: &str = "TimelockedStakedIota";
const STR_ALIAS_OUTPUT_IOTA: &str = "AliasOutputIota";
const STR_BASIC_OUTPUT_IOTA: &str = "BasicOutputIota";
const STR_NFT_OUTPUT_IOTA: &str = "NftOutputIota";
const STR_PACKAGE: &str = "Package";
const STR_COIN_METADATA: &str = "CoinMetadata";
const STR_OTHER: &str = "Other";
const STR_IOTA_DISTRIBUTION: &str = "IOTA Distribution";
const STR_OBJECTS: &str = "Objects";
const STR_VALIDATORS: &str = "Validators";

pub(crate) fn examine_genesis_checkpoint(genesis: UnsignedGenesis) {
pub(crate) fn examine_genesis_checkpoint(genesis: UnsignedGenesis, migration_objects: Vec<Object>) {
let system_object = genesis
.iota_system_object()
.into_genesis_version_for_tooling();
Expand Down Expand Up @@ -65,10 +73,23 @@ pub(crate) fn examine_genesis_checkpoint(genesis: UnsignedGenesis) {
let mut package_map = BTreeMap::new();
let mut iota_map = BTreeMap::new();
let mut staked_iota_map = BTreeMap::new();
let mut timelocked_iota_map = BTreeMap::new();
let mut timelocked_staked_iota_map = BTreeMap::new();
let mut alias_output_iota_map = BTreeMap::new();
let mut basic_output_iota_map = BTreeMap::new();
let mut nft_output_iota_map = BTreeMap::new();
let mut coin_metadata_map = BTreeMap::new();
let mut other_object_map = BTreeMap::new();

for object in genesis.objects() {
// Combine migration objects with genesis objects.
let genesis_objects = genesis.objects().to_vec();
nonast marked this conversation as resolved.
Show resolved Hide resolved
let combined_objects = migration_objects
.iter()
.chain(genesis_objects.iter())
.cloned()
.collect::<Vec<Object>>();

for object in combined_objects.iter() {
let object_id = object.id();
let object_id_str = object_id.to_string();
assert_eq!(object.storage_rebate, 0);
Expand All @@ -94,6 +115,54 @@ pub(crate) fn examine_genesis_checkpoint(genesis: UnsignedGenesis) {
assert_eq!(validator.staking_pool.id, staked_iota.pool_id());

staked_iota_map.insert(object.id(), staked_iota);
} else if let Some(time_locked) = object.as_timelock_balance_maybe() {
nonast marked this conversation as resolved.
Show resolved Hide resolved
let entry = iota_distribution
.entry(object.owner.to_string())
.or_default();
entry.insert(
object_id_str,
(STR_TIMELOCKED_IOTA, time_locked.locked().value()),
);
timelocked_iota_map.insert(object.id(), time_locked);
} else if let Some(alias_output) = object.as_alias_output_maybe() {
let entry = iota_distribution
.entry(object.owner.to_string())
.or_default();
entry.insert(
object_id_str,
(STR_ALIAS_OUTPUT_IOTA, alias_output.balance.value()),
);
alias_output_iota_map.insert(object.id(), alias_output);
} else if let Some(basic_output) = object.as_basic_output_maybe() {
let entry = iota_distribution
.entry(object.owner.to_string())
.or_default();
entry.insert(
object_id_str,
(STR_BASIC_OUTPUT_IOTA, basic_output.balance.value()),
);
basic_output_iota_map.insert(object.id(), basic_output);
} else if let Some(nft_output) = object.as_nft_output_maybe() {
let entry = iota_distribution
.entry(object.owner.to_string())
.or_default();
entry.insert(
object_id_str,
(STR_NFT_OUTPUT_IOTA, nft_output.balance.value()),
);
nft_output_iota_map.insert(object.id(), nft_output);
} else if let Ok(timelocked_staked_iota) = TimelockedStakedIota::try_from(object) {
let entry = iota_distribution
.entry(object.owner.to_string())
.or_default();
entry.insert(
object_id_str,
(
STR_TIMELOCKED_STAKED_IOTA,
timelocked_staked_iota.principal(),
),
);
timelocked_staked_iota_map.insert(object.id(), timelocked_staked_iota);
} else {
other_object_map.insert(object.id(), move_object);
}
Expand All @@ -105,7 +174,7 @@ pub(crate) fn examine_genesis_checkpoint(genesis: UnsignedGenesis) {
}
println!(
"Total Number of Objects/Packages: {}",
genesis.objects().len()
combined_objects.len()
);

// Always check the Total Supply
Expand All @@ -128,13 +197,18 @@ pub(crate) fn examine_genesis_checkpoint(genesis: UnsignedGenesis) {
examine_validators(&validator_options, &validator_map);
}
Ok(name) if name == STR_OBJECTS => {
println!("Examine Objects (total: {})", genesis.objects().len());
println!("Examine Objects (total: {})", combined_objects.len());
examine_object(
&owner_map,
&validator_pool_id_map,
&package_map,
&iota_map,
&staked_iota_map,
&timelocked_iota_map,
&timelocked_staked_iota_map,
&alias_output_iota_map,
&basic_output_iota_map,
&nft_output_iota_map,
&coin_metadata_map,
&other_object_map,
);
Expand Down Expand Up @@ -182,12 +256,22 @@ fn examine_object(
package_map: &BTreeMap<ObjectID, &MovePackage>,
iota_map: &BTreeMap<ObjectID, GasCoin>,
staked_iota_map: &BTreeMap<ObjectID, StakedIota>,
timelocked_iota_map: &BTreeMap<ObjectID, TimeLock<Balance>>,
timelocked_staked_iota: &BTreeMap<ObjectID, TimelockedStakedIota>,
alias_output_iota_map: &BTreeMap<ObjectID, AliasOutput>,
basic_output_iota_map: &BTreeMap<ObjectID, BasicOutput>,
nft_output_iota_map: &BTreeMap<ObjectID, NftOutput>,
coin_metadata_map: &BTreeMap<ObjectID, CoinMetadata>,
other_object_map: &BTreeMap<ObjectID, &MoveObject>,
) {
let object_options: Vec<&str> = vec![
STR_IOTA,
STR_STAKED_IOTA,
STR_TIMELOCKED_IOTA,
STR_TIMELOCKED_STAKED_IOTA,
STR_ALIAS_OUTPUT_IOTA,
STR_BASIC_OUTPUT_IOTA,
STR_NFT_OUTPUT_IOTA,
STR_COIN_METADATA,
STR_PACKAGE,
STR_OTHER,
Expand All @@ -213,6 +297,36 @@ fn examine_object(
}
print_divider(STR_STAKED_IOTA);
}
Ok(name) if name == STR_TIMELOCKED_IOTA => {
for time_locked in timelocked_iota_map.values() {
nonast marked this conversation as resolved.
Show resolved Hide resolved
println!("{:#?}", time_locked);
}
print_divider(STR_TIMELOCKED_IOTA);
}
Ok(name) if name == STR_TIMELOCKED_STAKED_IOTA => {
for time_locked in timelocked_staked_iota.values() {
println!("{:#?}", time_locked);
}
print_divider(STR_TIMELOCKED_STAKED_IOTA);
}
Ok(name) if name == STR_ALIAS_OUTPUT_IOTA => {
for alias_output in alias_output_iota_map.values() {
println!("{:#?}", alias_output);
}
print_divider(STR_ALIAS_OUTPUT_IOTA);
}
Ok(name) if name == STR_BASIC_OUTPUT_IOTA => {
for basic_output in basic_output_iota_map.values() {
println!("{:#?}", basic_output);
}
print_divider(STR_BASIC_OUTPUT_IOTA);
}
Ok(name) if name == STR_NFT_OUTPUT_IOTA => {
for nft_output in nft_output_iota_map.values() {
println!("{:#?}", nft_output);
}
print_divider(STR_NFT_OUTPUT_IOTA);
}
Ok(name) if name == STR_PACKAGE => {
for package in package_map.values() {
println!("Package ID: {}", package.id());
Expand Down
Loading