mirror of
https://github.com/mimblewimble/grin.git
synced 2025-01-20 19:11:08 +03:00
Get last bitcon block hash, setup genesis header without PoW (for now)
This commit is contained in:
parent
cd135c4dca
commit
3e7bc2888c
4 changed files with 157 additions and 0 deletions
|
@ -12,6 +12,7 @@ build = "src/build/build.rs"
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["api", "chain", "config", "core", "keychain", "p2p", "servers", "store", "util", "pool", "wallet"]
|
members = ["api", "chain", "config", "core", "keychain", "p2p", "servers", "store", "util", "pool", "wallet"]
|
||||||
|
exclude = ["etc/gen_gen"]
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "grin"
|
name = "grin"
|
||||||
|
|
24
etc/gen_gen/Cargo.toml
Normal file
24
etc/gen_gen/Cargo.toml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
[package]
|
||||||
|
name = "grin_gen_gen"
|
||||||
|
version = "0.0.1"
|
||||||
|
edition = "2018"
|
||||||
|
authors = ["Grin Developers <mimblewimble@lists.launchpad.net>"]
|
||||||
|
description = "Utility to automate the generation of Grin's genesis block"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
repository = "https://github.com/mimblewimble/grin"
|
||||||
|
keywords = [ "crypto", "grin", "mimblewimble" ]
|
||||||
|
readme = "README.md"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "gen_gen"
|
||||||
|
path = "src/bin/gen_gen.rs"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
chrono = "0.4.4"
|
||||||
|
curl = "0.4.19"
|
||||||
|
serde_json = "1"
|
||||||
|
grin_core = "0.4.2"
|
||||||
|
grin_chain = "0.4.2"
|
||||||
|
grin_keychain = "0.4.2"
|
||||||
|
grin_store = "0.4.2"
|
||||||
|
grin_util = "0.4.2"
|
18
etc/gen_gen/README.md
Normal file
18
etc/gen_gen/README.md
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Genesis Genesis
|
||||||
|
|
||||||
|
This crate isn't strictly part of grin but allows the generation and release of a new Grin Genesis in an automated fashion. The process is the following:
|
||||||
|
|
||||||
|
* Prepare a multisig output and kernel to use as coinbase. In the case of Grin mainnet, this is done and owned by the council treasurers. This can be down a few days prior.
|
||||||
|
* Grab the latest bitcoin block hash from publicly available APIs.
|
||||||
|
* Build a genesis block with the prepared coinbase and the bitcoin block hash as `prev_root`. The timestamp of the block is set to 30 min ahead to leave enough time to run a build and start a node.
|
||||||
|
* Mine the block so we have at least a valid Cuckatoo Cycle. We don't require a given difficulty for that solution.
|
||||||
|
* Finalize the block with the proof-of-work, setting a high-enough difficulty (to be agreed upon separately).
|
||||||
|
* Commit the block information to github.
|
||||||
|
* Tag version 1.0.0 (scary).
|
||||||
|
|
||||||
|
N.B. This was written while listening to Genesis. Unfortunately, I'm not rich enough to do it while driving a Genesis. And that'd be dangerous.
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
1. Build this crate.
|
||||||
|
2. From its root run `./target/release/gen-gen --coinbase <file> --difficulty <u64> --tag <version>`
|
114
etc/gen_gen/src/bin/gen_gen.rs
Normal file
114
etc/gen_gen/src/bin/gen_gen.rs
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
// Copyright 2018 The Grin Developers
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
//! Main for building the genesis generation utility.
|
||||||
|
|
||||||
|
use std::fs;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use chrono::Duration;
|
||||||
|
use chrono::prelude::Utc;
|
||||||
|
use curl;
|
||||||
|
use serde_json;
|
||||||
|
|
||||||
|
use grin_chain as chain;
|
||||||
|
use grin_core as core;
|
||||||
|
use grin_store as store;
|
||||||
|
use grin_util as util;
|
||||||
|
|
||||||
|
use grin_keychain::{ExtKeychain, Keychain};
|
||||||
|
|
||||||
|
static BCHAIN_INFO_URL: &str = "https://blockchain.info/latestblock";
|
||||||
|
static BCYPHER_URL: &str = "https://api.blockcypher.com/v1/btc/main";
|
||||||
|
static BCHAIR_URL: &str = "https://api.blockchair.com/bitcoin/blocks?limit=2";
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// get the latest bitcoin hash
|
||||||
|
let h1 = get_bchain_head();
|
||||||
|
let h2 = get_bcypher_head();
|
||||||
|
let h3 = get_bchair_head();
|
||||||
|
if h1 != h2 || h1 != h3 {
|
||||||
|
panic!("Bitcoin chain head is inconsistent, please retry.");
|
||||||
|
}
|
||||||
|
println!("Using bitcoin block hash {}", h1);
|
||||||
|
|
||||||
|
// build the basic parts of the genesis block header, perhaps some of this
|
||||||
|
// can be moved to core
|
||||||
|
let mut gen = core::genesis::genesis_main();
|
||||||
|
gen.header.timestamp = Utc::now() + Duration::minutes(30);
|
||||||
|
gen.header.prev_root = core::core::hash::Hash::from_hex(&h1).unwrap();
|
||||||
|
gen.header.pow.proof.edge_bits = 29;
|
||||||
|
println!("Built genesis:\n{:?}", gen);
|
||||||
|
|
||||||
|
// TODO get the proper keychain and/or raw coinbase
|
||||||
|
let keychain = ExtKeychain::from_random_seed().unwrap();
|
||||||
|
let key_id = ExtKeychain::derive_key_id(0, 1, 0, 0, 0);
|
||||||
|
let reward = core::libtx::reward::output(&keychain, &key_id, 0, 0).unwrap();
|
||||||
|
gen = gen.with_reward(reward.0, reward.1);
|
||||||
|
|
||||||
|
{
|
||||||
|
// setup a tmp chain to set block header roots
|
||||||
|
let tmp_chain = setup_chain(".grin.tmp", core::pow::mine_genesis_block().unwrap());
|
||||||
|
tmp_chain.set_txhashset_roots(&mut gen).unwrap();
|
||||||
|
gen.header.output_mmr_size = 1;
|
||||||
|
gen.header.kernel_mmr_size = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO mine a valid Cuckatoo29 solution
|
||||||
|
// TODO check again the bitcoin block to make sure it's not been orphaned
|
||||||
|
// TODO Commit genesis block info in git and tag
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_chain(dir_name: &str, genesis: core::core::Block) -> chain::Chain {
|
||||||
|
util::init_test_logger();
|
||||||
|
let _ = fs::remove_dir_all(dir_name);
|
||||||
|
let verifier_cache = Arc::new(util::RwLock::new(core::core::verifier_cache::LruVerifierCache::new()));
|
||||||
|
let db_env = Arc::new(store::new_env(dir_name.to_string()));
|
||||||
|
chain::Chain::init(
|
||||||
|
dir_name.to_string(),
|
||||||
|
db_env,
|
||||||
|
Arc::new(chain::types::NoopAdapter {}),
|
||||||
|
genesis,
|
||||||
|
core::pow::verify_size,
|
||||||
|
verifier_cache,
|
||||||
|
false,
|
||||||
|
).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_bchain_head() -> String {
|
||||||
|
get_json(BCHAIN_INFO_URL)["hash"].as_str().unwrap().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_bcypher_head() -> String {
|
||||||
|
get_json(BCYPHER_URL)["hash"].as_str().unwrap().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_bchair_head() -> String {
|
||||||
|
get_json(BCHAIR_URL)["data"][0]["hash"].as_str().unwrap().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_json(url: &str) -> serde_json::Value {
|
||||||
|
let mut body = Vec::new();
|
||||||
|
let mut easy = curl::easy::Easy::new();
|
||||||
|
easy.url(url).unwrap();
|
||||||
|
{
|
||||||
|
let mut transfer = easy.transfer();
|
||||||
|
transfer.write_function(|data| {
|
||||||
|
body.extend_from_slice(data);
|
||||||
|
Ok(data.len())
|
||||||
|
}).unwrap();
|
||||||
|
transfer.perform().unwrap();
|
||||||
|
}
|
||||||
|
serde_json::from_slice(&body).unwrap()
|
||||||
|
}
|
Loading…
Reference in a new issue