-
Notifications
You must be signed in to change notification settings - Fork 128
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
script/research/gg: Genesis Generator cli util added
- Loading branch information
Showing
3 changed files
with
189 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/target | ||
Cargo.lock | ||
rustfmt.toml | ||
/genesis_txs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <[email protected]>"] | ||
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"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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(()) | ||
} | ||
} | ||
} |