fn decode_governance_stable_memory(gov_pb: PathBuf, output: &Path, rs: &Path) {
    // Decode
    // It's REALLY IMPORTANT to use `protoc` here, NOT the prost library.
    // The prost generated code silently drops all unknown fields when reading
    // serialized protobuf, hence it is NOT suitable for state auditing, or in
    // general for debugging.
    let mut cmd_base = std::process::Command::new("protoc");
    let cmd = cmd_base
        // -I: where to find included protos (transitively)
        .args(&["-I", "nns/governance/proto"])
        .args(&["-I", "rosetta-api/ledger_canister/proto"])
        .args(&["-I", "types/base_types/proto"])
        .args(&["-I", "nns/common/proto"])
        // Main arg: the main proto file
        .arg("nns/governance/proto/ic_nns_governance/pb/v1/governance.proto")
        // the actual command
        .args(&["--decode", "ic_nns_governance.pb.v1.Governance"])
        .current_dir(rs)
        .stdin(File::open(gov_pb.clone()).unwrap())
        .stdout(File::create(output.join("governance_stable_memory.textproto")).unwrap());
    let status = cmd.status().unwrap();
    match status.success() {
        true => eprintln!("Wrote governance_stable_memory.textproto"),
        false => eprintln!(
            "Something went wrong with parsing the governance proto. The command was: {:?}",
            cmd
        ),
    };

    // This time we use prost. This is fine: this is for an EXTRACT of the data.
    let mut bytes = Vec::<u8>::new();
    File::open(gov_pb).unwrap().read_to_end(&mut bytes).unwrap();
    match GovernanceProto::decode(bytes.as_slice()) {
        Err(e) => eprintln!("Can't prost-deserialize the governance proto: {}", e),
        Ok(proto) => {
            let mut csv_writer =
                csv::Writer::from_path(output.join("governance_neurons_EXTRACT.csv")).unwrap();
            let mut neurons: Vec<Neuron> = proto.neurons.values().cloned().collect();
            neurons.sort_by_key(|n| n.id.as_ref().map_or(0, |nid| nid.id));
            for n in neurons {
                let record = NeuronRecord {
                    id: n
                        .id
                        .map_or_else(|| "none".to_string(), |nid| nid.id.to_string()),
                    account_hex: hex::encode(n.account.as_slice()),
                    controller: n
                        .controller
                        .map_or_else(|| "none".to_string(), |c| c.to_string()),
                    hot_keys: n
                        .hot_keys
                        .iter()
                        .map(ToString::to_string)
                        .collect::<Vec<String>>()
                        .join(";"),
                    cached_neuron_stake_e8s: n.cached_neuron_stake_e8s,
                    neuron_fees_e8s: n.neuron_fees_e8s,
                    aging_since_timestamp_seconds: n.aging_since_timestamp_seconds,
                    kyc_verified: n.kyc_verified,
                    maturity_e8s_equivalent: n.maturity_e8s_equivalent,
                    not_for_profit: n.not_for_profit,
                    account_id: AccountIdentifier::new(
                        GOVERNANCE_CANISTER_ID.get(),
                        Some(Subaccount(n.account.as_slice().try_into().unwrap())),
                    )
                    .to_string(),
                };
                csv_writer.serialize(record).unwrap();
            }
            eprintln!("Wrote governance_neurons_EXTRACT.csv");
        }
    }
}
/// Decode stable memory for the governance canister.
///
/// gov_pb is expected to be a binary Governance proto. Extraction should have
/// already happened.
Decode stable memory for the governance canister.
gov_pb is expected to be a binary Governance proto. Extraction should have
already happened.
Decode stable memory for the governance canister . gov_pb is expected to be a binary Governance proto . Extraction should have already happened .
fn decode_governance_stable_memory(gov_pb: PathBuf, output: &Path, rs: &Path) {
    // Decode
    // It's REALLY IMPORTANT to use `protoc` here, NOT the prost library.
    // The prost generated code silently drops all unknown fields when reading
    // serialized protobuf, hence it is NOT suitable for state auditing, or in
    // general for debugging.
    let mut cmd_base = std::process::Command::new("protoc");
    let cmd = cmd_base
        // -I: where to find included protos (transitively)
        .args(&["-I", "nns/governance/proto"])
        .args(&["-I", "rosetta-api/ledger_canister/proto"])
        .args(&["-I", "types/base_types/proto"])
        .args(&["-I", "nns/common/proto"])
        // Main arg: the main proto file
        .arg("nns/governance/proto/ic_nns_governance/pb/v1/governance.proto")
        // the actual command
        .args(&["--decode", "ic_nns_governance.pb.v1.Governance"])
        .current_dir(rs)
        .stdin(File::open(gov_pb.clone()).unwrap())
        .stdout(File::create(output.join("governance_stable_memory.textproto")).unwrap());
    let status = cmd.status().unwrap();
    match status.success() {
        true => eprintln!("Wrote governance_stable_memory.textproto"),
        false => eprintln!(
            "Something went wrong with parsing the governance proto. The command was: {:?}",
            cmd
        ),
    };
    // This time we use prost. This is fine: this is for an EXTRACT of the data.
    let mut bytes = Vec::<u8>::new();
    File::open(gov_pb).unwrap().read_to_end(&mut bytes).unwrap();
    match GovernanceProto::decode(bytes.as_slice()) {
        Err(e) => eprintln!("Can't prost-deserialize the governance proto: {}", e),
        Ok(proto) => {
            let mut csv_writer =
                csv::Writer::from_path(output.join("governance_neurons_EXTRACT.csv")).unwrap();
            let mut neurons: Vec<Neuron> = proto.neurons.values().cloned().collect();
            neurons.sort_by_key(|n| n.id.as_ref().map_or(0, |nid| nid.id));
            for n in neurons {
                let record = NeuronRecord {
                    id: n
                        .id
                        .map_or_else(|| "none".to_string(), |nid| nid.id.to_string()),
                    account_hex: hex::encode(n.account.as_slice()),
                    controller: n
                        .controller
                        .map_or_else(|| "none".to_string(), |c| c.to_string()),
                    hot_keys: n
                        .hot_keys
                        .iter()
                        .map(ToString::to_string)
                        .collect::<Vec<String>>()
                        .join(";"),
                    cached_neuron_stake_e8s: n.cached_neuron_stake_e8s,
                    neuron_fees_e8s: n.neuron_fees_e8s,
                    aging_since_timestamp_seconds: n.aging_since_timestamp_seconds,
                    kyc_verified: n.kyc_verified,
                    maturity_e8s_equivalent: n.maturity_e8s_equivalent,
                    not_for_profit: n.not_for_profit,
                    account_id: AccountIdentifier::new(
                        GOVERNANCE_CANISTER_ID.get(),
                        Some(Subaccount(n.account.as_slice().try_into().unwrap())),
                    )
                    .to_string(),
                };
                csv_writer.serialize(record).unwrap();
            }
            eprintln!("Wrote governance_neurons_EXTRACT.csv");
        }
    }
}
fn decode_governance_stable_memory ( gov_pb : PathBuf , output : & Path , rs : & Path ) { // Decode // It's REALLY IMPORTANT to use `protoc` here, NOT the prost library. // The prost generated code silently drops all unknown fields when reading // serialized protobuf, hence it is NOT suitable for state auditing, or in // general for debugging. let mut cmd_base = std :: process :: Command :: new ( " " ) ; let cmd = cmd_base // -I: where to find included protos (transitively) . args ( & [ " " , " " ] ) . args ( & [ " " , " " ] ) . args ( & [ " " , " " ] ) . args ( & [ " " , " " ] ) // Main arg: the main proto file . arg ( " " ) // the actual command . args ( & [ " " , " " ] ) . current_dir ( rs ) . stdin ( File :: open ( gov_pb . clone ( ) ) . unwrap ( ) ) . stdout ( File :: create ( output . join ( " " ) ) . unwrap ( ) ) ; let status = cmd . status ( ) . unwrap ( ) ; match status . success ( ) { true => eprintln ! ( " " ) , false => eprintln ! ( " " cmd ) , } ; // This time we use prost. This is fine: this is for an EXTRACT of the data. let mut bytes = Vec :: < u8 > :: new ( ) ; File :: open ( gov_pb ) . unwrap ( ) . read_to_end ( & mut bytes ) . unwrap ( ) ; match GovernanceProto :: decode ( bytes . as_slice ( ) ) { Err ( e ) => eprintln ! ( " " e ) , Ok ( proto ) => { let mut csv_writer = csv :: Writer :: from_path ( output . join ( " " ) ) . unwrap ( ) ; let mut neurons : Vec < Neuron > = proto . neurons . values ( ) . cloned ( ) . collect ( ) ; neurons . sort_by_key ( | n | n . id . as_ref ( ) . map_or ( 0 , | nid | nid . id ) ) ; for n in neurons { let record = NeuronRecord { id : n . id . map_or_else ( | | " " . to_string ( ) , | nid | nid . id . to_string ( ) ) , account_hex : hex :: encode ( n . account . as_slice ( ) ) , controller : n . controller . map_or_else ( | | " " . to_string ( ) , | c | c . to_string ( ) ) , hot_keys : n . hot_keys . iter ( ) . map ( ToString :: to_string ) . collect :: < Vec < String > > ( ) . join ( " " ) , cached_neuron_stake_e8s : n . cached_neuron_stake_e8s , neuron_fees_e8s : n . neuron_fees_e8s , aging_since_timestamp_seconds : n . aging_since_timestamp_seconds , kyc_verified : n . kyc_verified , maturity_e8s_equivalent : n . maturity_e8s_equivalent , not_for_profit : n . not_for_profit , account_id : AccountIdentifier :: new ( GOVERNANCE_CANISTER_ID . get ( ) , Some ( Subaccount ( n . account . as_slice ( ) . try_into ( ) . unwrap ( ) ) ) , ) . to_string ( ) , } ; csv_writer . serialize ( record ) . unwrap ( ) ; } eprintln ! ( " " ) ; } } }
Decode stable memory for the governance canister.
Decode stable memory for the governance canister .
gov_pb
PathBuf
output
&Path
rs
&Path
gov_pb
PathBuf
output
&Path
rs
&Path