Skip to content

Commit

Permalink
fix: examine genesis checkpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
nonast committed Jan 17, 2025
1 parent 62a0b7a commit aa286a5
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 12 deletions.
8 changes: 6 additions & 2 deletions crates/iota-genesis-builder/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use std::{
str::FromStr,
sync::Arc,
};

use anyhow::{Context, bail};
use camino::Utf8Path;
use fastcrypto::{hash::HashFunction, traits::KeyPair};
Expand Down Expand Up @@ -149,6 +148,10 @@ impl Builder {
}
}

pub fn tx_migration_objects(mut self) -> Vec<Object> {
self.migration_tx_data.unwrap().get_objects().collect()
}

pub fn with_delegator(mut self, delegator: IotaAddress) -> Self {
self.delegation = Some(GenesisDelegation::OneToAll(delegator));
self
Expand Down Expand Up @@ -259,8 +262,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);
tracing::info!("Adding migration objects from {:?}", source);
self.migration_objects
.extend(bcs::from_reader::<Vec<_>>(source.to_reader()?)?);
Expand Down
29 changes: 28 additions & 1 deletion crates/iota-types/src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ use std::{
mem::size_of,
sync::Arc,
};

use iota_stardust_sdk::types::block::output::dto::FoundryOutputDto;
use iota_stardust_sdk::types::block::output::FoundryOutput;
use iota_protocol_config::ProtocolConfig;
use move_binary_format::CompiledModule;
use move_bytecode_utils::{layout::TypeLayoutBuilder, module_cache::GetModule};
Expand Down Expand Up @@ -39,6 +40,7 @@ use crate::{
move_package::MovePackage,
timelock::timelock::TimeLock,
};
use crate::stardust::output::{AliasOutput, BasicOutput, NftOutput};

mod balance_traversal;
pub mod bounded_visitor;
Expand Down Expand Up @@ -712,6 +714,7 @@ impl std::ops::DerefMut for Object {
}
}


impl ObjectInner {
/// Returns true if the object is a system package.
pub fn is_system_package(&self) -> bool {
Expand Down Expand Up @@ -819,6 +822,30 @@ impl ObjectInner {
}
}

pub fn as_alias_output_maybe(&self) -> Option<AliasOutput> {
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
11 changes: 11 additions & 0 deletions crates/iota-types/src/stardust/output/alias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use crate::{
object::{Data, MoveObject, Object, Owner},
stardust::{coin_type::CoinType, stardust_to_iota_address},
};
use crate::timelock::timelock::TimeLock;

pub const ALIAS_MODULE_NAME: &IdentStr = ident_str!("alias");
pub const ALIAS_OUTPUT_MODULE_NAME: &IdentStr = ident_str!("alias_output");
Expand Down Expand Up @@ -201,4 +202,14 @@ impl AliasOutput {

Ok(move_alias_output_object)
}

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

/// Serialize a `AliasOutput` as a `Vec<u8>` of BCS.
pub fn to_bcs_bytes(&self) -> Vec<u8> {
bcs::to_bytes(&self).unwrap()
}
}
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.
pub fn from_bcs_bytes(content: &[u8]) -> std::result::Result<Self, bcs::Error> {
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()
}
}
12 changes: 8 additions & 4 deletions crates/iota/src/genesis_ceremony.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// SPDX-License-Identifier: Apache-2.0

use std::{fs::File, path::PathBuf};

use std::io::{BufReader, Read};
use anyhow::Result;
use camino::Utf8PathBuf;
use clap::Parser;
Expand All @@ -29,7 +29,7 @@ use iota_types::{
message_envelope::Message,
multiaddr::Multiaddr,
};

use iota_types::object::Object;
use crate::genesis_inspector::examine_genesis_checkpoint;

#[derive(Parser)]
Expand Down Expand Up @@ -298,15 +298,19 @@ pub async fn run(cmd: Ceremony) -> Result<()> {
}

CeremonyCommand::ExamineGenesisCheckpoint => {
let builder = Builder::load(&dir).await?;
let mut builder = Builder::load(&dir).await?;

let Some(unsigned_genesis) = builder.unsigned_genesis_checkpoint() else {
return Err(anyhow::anyhow!(
"Unable to examine genesis checkpoint; try running `build-unsigned-checkpoint`"
));
};

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
103 changes: 98 additions & 5 deletions crates/iota/src/genesis_inspector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// SPDX-License-Identifier: Apache-2.0

use std::collections::BTreeMap;

use inquire::Select;
use iota_config::genesis::UnsignedGenesis;
use iota_types::{
Expand All @@ -15,19 +14,29 @@ use iota_types::{
move_package::MovePackage,
object::{MoveObject, Owner},
};
use iota_types::balance::Balance;
use iota_types::object::Object;
use iota_types::stardust::output::{AliasOutput, BasicOutput, NftOutput};
use iota_types::timelock::timelock::TimeLock;
use iota_types::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 +74,19 @@ 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();
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 +112,36 @@ 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() {
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 +153,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 +176,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 +235,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 +276,36 @@ fn examine_object(
}
print_divider(STR_STAKED_IOTA);
}
Ok(name) if name == STR_TIMELOCKED_IOTA => {
for time_locked in timelocked_iota_map.values() {
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

0 comments on commit aa286a5

Please sign in to comment.