mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-01-10 07:08:05 -05:00
script/research/gg: Genesis Generator cli util added
This commit is contained in:
4
script/research/gg/.gitignore
vendored
Normal file
4
script/research/gg/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
/target
|
||||
Cargo.lock
|
||||
rustfmt.toml
|
||||
/genesis_txs
|
||||
31
script/research/gg/Cargo.toml
Normal file
31
script/research/gg/Cargo.toml
Normal file
@@ -0,0 +1,31 @@
|
||||
[package]
|
||||
name = "gg"
|
||||
version = "0.4.1"
|
||||
description = """\
|
||||
Genesis Generator, a command-line utility to generate,\
|
||||
display and verify a bs58 encoded Darkfi genesis block\
|
||||
"""
|
||||
authors = ["Dyne.org foundation <foundation@dyne.org>"]
|
||||
repository = "https://github.com/darkrenaissance/darkfi"
|
||||
license = "AGPL-3.0-only"
|
||||
edition = "2021"
|
||||
|
||||
[workspace]
|
||||
|
||||
[dependencies]
|
||||
# Darkfi
|
||||
darkfi = {path = "../../../", features = ["validator"]}
|
||||
darkfi-contract-test-harness = {path = "../../../src/contract/test-harness"}
|
||||
darkfi-serial = {path = "../../../src/serial"}
|
||||
|
||||
# Misc
|
||||
anyhow = "1.0.75"
|
||||
async-std = {version = "1.12.0", features = ["attributes"]}
|
||||
bs58 = "0.5.0"
|
||||
clap = {version = "4.4.1", features = ["derive"]}
|
||||
sled = "0.34.7"
|
||||
|
||||
[patch.crates-io]
|
||||
halo2_proofs = {git="https://github.com/parazyd/halo2", branch="v4"}
|
||||
halo2_gadgets = {git="https://github.com/parazyd/halo2", branch="v4"}
|
||||
blake2b_simd = {git="https://github.com/parazyd/blake2_simd", branch="impl-common"}
|
||||
154
script/research/gg/src/main.rs
Normal file
154
script/research/gg/src/main.rs
Normal file
@@ -0,0 +1,154 @@
|
||||
/* This file is part of DarkFi (https://dark.fi)
|
||||
*
|
||||
* Copyright (C) 2020-2023 Dyne.org foundation
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use std::{
|
||||
fs::{read_dir, read_to_string},
|
||||
io::{stdin, Read},
|
||||
};
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::{Parser, Subcommand};
|
||||
use darkfi::{
|
||||
blockchain::{BlockInfo, Blockchain, BlockchainOverlay},
|
||||
cli_desc,
|
||||
tx::Transaction,
|
||||
util::{
|
||||
path::expand_path,
|
||||
time::{TimeKeeper, Timestamp},
|
||||
},
|
||||
validator::{utils::genesis_txs_total, verification::verify_genesis_block},
|
||||
};
|
||||
use darkfi_contract_test_harness::vks;
|
||||
use darkfi_serial::{deserialize, serialize};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(about = cli_desc!())]
|
||||
struct Args {
|
||||
#[command(subcommand)]
|
||||
command: Subcmd,
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum Subcmd {
|
||||
/// Read a Darkfi genesis block from stdin and display it
|
||||
Display,
|
||||
|
||||
/// Generate a Darkfi genesis block and write it to stdin
|
||||
Generate {
|
||||
#[arg(short, long, default_value = "genesis_txs")]
|
||||
/// Path to folder containing the genesis transactions
|
||||
txs_folder: String,
|
||||
|
||||
#[arg(short, long)]
|
||||
/// Genesis timestamp to use, instead of current one
|
||||
genesis_timestamp: Option<u64>,
|
||||
},
|
||||
|
||||
/// Read a Darkfi genesis block from stdin and verify it
|
||||
Verify,
|
||||
}
|
||||
|
||||
/// Auxiliary function to read a bs58 genesis block from stdin
|
||||
fn read_block() -> Result<BlockInfo> {
|
||||
eprintln!("Reading genesis block from stdin...");
|
||||
let mut buf = String::new();
|
||||
stdin().read_to_string(&mut buf)?;
|
||||
let bytes = bs58::decode(&buf.trim()).into_vec()?;
|
||||
let block = deserialize(&bytes)?;
|
||||
Ok(block)
|
||||
}
|
||||
|
||||
#[async_std::main]
|
||||
async fn main() -> Result<()> {
|
||||
// Parse arguments
|
||||
let args = Args::parse();
|
||||
|
||||
// Execute a subcommand
|
||||
match args.command {
|
||||
Subcmd::Display => {
|
||||
let genesis_block = read_block()?;
|
||||
println!("{genesis_block:#?}");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Subcmd::Generate { txs_folder, genesis_timestamp } => {
|
||||
// Grab genesis transactions from folder
|
||||
let txs_folder = expand_path(&txs_folder).unwrap();
|
||||
let mut genesis_txs: Vec<Transaction> = vec![];
|
||||
for file in read_dir(txs_folder)? {
|
||||
let bytes = bs58::decode(&read_to_string(file?.path())?.trim()).into_vec()?;
|
||||
let tx = deserialize(&bytes)?;
|
||||
genesis_txs.push(tx);
|
||||
}
|
||||
|
||||
// Generate the genesis block
|
||||
let mut genesis_block = BlockInfo::default();
|
||||
|
||||
// Update timestamp if one was provided
|
||||
if let Some(timestamp) = genesis_timestamp {
|
||||
genesis_block.header.timestamp = Timestamp(timestamp);
|
||||
}
|
||||
|
||||
// Append genesis transactions
|
||||
if !genesis_txs.is_empty() {
|
||||
// Retrieve genesis producer transaction
|
||||
let producer_tx = genesis_block.txs.pop().unwrap();
|
||||
|
||||
// Append genesis transactions and calculate their total
|
||||
genesis_block.txs.append(&mut genesis_txs);
|
||||
genesis_block.txs.push(producer_tx);
|
||||
let genesis_txs_total = genesis_txs_total(&genesis_block.txs)?;
|
||||
genesis_block.slots[0].total_tokens = genesis_txs_total;
|
||||
}
|
||||
|
||||
// Write generated genesis block to stdin
|
||||
let encoded = bs58::encode(&serialize(&genesis_block)).into_string();
|
||||
println!("{}", encoded);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Subcmd::Verify => {
|
||||
let genesis_block = read_block()?;
|
||||
let hash = genesis_block.hash()?;
|
||||
|
||||
println!("Verifying genesis block: {hash}");
|
||||
|
||||
// Initialize a temporary sled database
|
||||
let sled_db = sled::Config::new().temporary(true).open()?;
|
||||
let (_, vks) = vks::read_or_gen_vks_and_pks()?;
|
||||
vks::inject(&sled_db, &vks)?;
|
||||
|
||||
// Create an overlay over whole blockchain
|
||||
let blockchain = Blockchain::new(&sled_db)?;
|
||||
let overlay = BlockchainOverlay::new(&blockchain)?;
|
||||
|
||||
// Generate a dummy time keeper
|
||||
let time_keeper = TimeKeeper::new(genesis_block.header.timestamp, 10, 90, 0);
|
||||
|
||||
// Grab block txs total
|
||||
let genesis_txs_total = genesis_txs_total(&genesis_block.txs)?;
|
||||
|
||||
verify_genesis_block(&overlay, &time_keeper, &genesis_block, genesis_txs_total).await?;
|
||||
|
||||
println!("Genesis block {hash} verified successfully!");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user