use sn_dbc::{
bls_ringct::{bls_bulletproofs::PedersenGens, group::Curve},
rng, Dbc, Hash, IndexedSignatureShare, MlsagMaterial, Owner, OwnerOnce, RevealedCommitment,
SpentProofContent, SpentProofShare, Token, TransactionBuilder, TrueInput,
};
use std::{fmt::Debug, result};
use thiserror::Error;
pub const GENESIS_DBC_AMOUNT: u64 = 4_525_524_120 * u64::pow(10, 9);
pub type Result<T> = result::Result<T, Error>;
#[derive(Error, Debug, Clone)]
#[non_exhaustive]
pub enum Error {
#[error("Genesis DBC error:: {0}")]
GenesisDbcError(String),
}
pub fn gen_genesis_dbc(
genesis_section_sk_set: &bls::SecretKeySet,
genesis_dbc_sk: &bls::SecretKey,
) -> Result<Dbc> {
let output_owner =
OwnerOnce::from_owner_base(Owner::from(genesis_dbc_sk.clone()), &mut rng::thread_rng());
let revealed_commitment =
RevealedCommitment::from_value(GENESIS_DBC_AMOUNT, &mut rng::thread_rng());
let true_input = TrueInput::new(genesis_dbc_sk.clone(), revealed_commitment);
let mlsag_material = MlsagMaterial {
true_input,
decoy_inputs: vec![],
pi_base: 0,
alpha: (1234.into(), 5678.into()),
r: vec![(9123.into(), 4567.into())],
};
let mut dbc_builder = TransactionBuilder::default()
.add_input(mlsag_material)
.add_output_by_amount(Token::from_nano(GENESIS_DBC_AMOUNT), output_owner)
.build(rng::thread_rng())
.map_err(|err| {
Error::GenesisDbcError(format!(
"Failed to build the ringct transaction for genesis DBC: {err}",
))
})?;
let (key_image, tx) = dbc_builder.inputs().into_iter().next().ok_or_else(|| {
Error::GenesisDbcError(
"DBC builder (unexpectedly) contains an empty set of inputs.".to_string(),
)
})?;
let content = SpentProofContent {
key_image,
transaction_hash: Hash::from(tx.hash()),
public_commitments: vec![revealed_commitment
.commit(&PedersenGens::default())
.to_affine()],
};
let sk_share_index = 0;
let sig_share = genesis_section_sk_set
.secret_key_share(sk_share_index)
.sign(content.hash().as_ref());
let spentbook_sig_share = IndexedSignatureShare::new(sk_share_index, sig_share);
let spent_proof_share = SpentProofShare {
content,
spentbook_pks: genesis_section_sk_set.public_keys(),
spentbook_sig_share,
};
dbc_builder = dbc_builder
.add_spent_proof_share(spent_proof_share)
.add_spent_transaction(tx);
let outputs = dbc_builder.build_without_verifying().map_err(|err| {
Error::GenesisDbcError(format!(
"DBC builder failed to create output genesis DBC: {err}",
))
})?;
let (genesis_dbc, _, _) = outputs.into_iter().next().ok_or_else(|| {
Error::GenesisDbcError(
"DBC builder (unexpectedly) contains an empty set of outputs.".to_string(),
)
})?;
Ok(genesis_dbc)
}