mirror of
https://github.com/alexgo-io/stacks-puppet-node.git
synced 2026-01-12 16:53:21 +08:00
feat: embed name_zonefiles.txt and implement parser
This commit is contained in:
@@ -16,18 +16,25 @@ pub static CHAINSTATE_SHA256_FILE: &str = "chainstate.txt.sha256";
|
||||
pub static CHAINSTATE_TEST_FILE: &str = "chainstate-test.txt";
|
||||
pub static CHAINSTATE_TEST_SHA256_FILE: &str = "chainstate-test.txt.sha256";
|
||||
|
||||
pub static NAME_ZONEFILES_FILE: &str = "name_zonefiles.txt";
|
||||
pub static NAME_ZONEFILES_SHA256_FILE: &str = "name_zonefiles.txt.sha256";
|
||||
|
||||
fn main() {
|
||||
verify_name_zonefiles_integrity().expect("failed to verify and output name_zonefiles.txt.sha256 hash");
|
||||
verify_genesis_integrity(true)
|
||||
.expect("failed to verify and output chainstate-test.txt.sha256 hash");
|
||||
verify_genesis_integrity(false)
|
||||
.expect("failed to verify and output chainstate.txt.sha256 hash");
|
||||
write_archives(true).expect("failed to write chainstate test data archives");
|
||||
write_archives(false).expect("failed to write chainstate prod data archives");
|
||||
write_chainstate_archives(true).expect("failed to write chainstate test data archives");
|
||||
write_chainstate_archives(false).expect("failed to write chainstate prod data archives");
|
||||
write_name_zonefiles_archive().expect("failed to write name zonefiles data archive");
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
println!("cargo:rerun-if-changed=chainstate-test.txt.sha256");
|
||||
println!("cargo:rerun-if-changed=chainstate-test.txt");
|
||||
println!("cargo:rerun-if-changed=chainstate.txt.sha256");
|
||||
println!("cargo:rerun-if-changed=chainstate.txt");
|
||||
println!("cargo:rerun-if-changed=name_zonefiles.txt.sha256");
|
||||
println!("cargo:rerun-if-changed=name_zonefiles.txt");
|
||||
}
|
||||
|
||||
fn open_chainstate_file(test_data: bool) -> File {
|
||||
@@ -39,15 +46,15 @@ fn open_chainstate_file(test_data: bool) -> File {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn write_archives(test_data: bool) -> std::io::Result<()> {
|
||||
write_archive(test_data, "account_balances", "STX BALANCES")?;
|
||||
write_archive(test_data, "account_lockups", "STX VESTING")?;
|
||||
write_archive(test_data, "namespaces", "NAMESPACES")?;
|
||||
write_archive(test_data, "names", "NAMES")?;
|
||||
pub fn write_chainstate_archives(test_data: bool) -> std::io::Result<()> {
|
||||
write_chainstate_archive(test_data, "account_balances", "STX BALANCES")?;
|
||||
write_chainstate_archive(test_data, "account_lockups", "STX VESTING")?;
|
||||
write_chainstate_archive(test_data, "namespaces", "NAMESPACES")?;
|
||||
write_chainstate_archive(test_data, "names", "NAMES")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_archive(
|
||||
fn write_chainstate_archive(
|
||||
test_data: bool,
|
||||
output_file_name: &str,
|
||||
section_name: &str,
|
||||
@@ -83,6 +90,20 @@ fn write_archive(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_name_zonefiles_archive() -> std::io::Result<()> {
|
||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||
let zonefiles_file = File::open(NAME_ZONEFILES_FILE).unwrap();
|
||||
let mut reader = BufReader::new(zonefiles_file);
|
||||
let out_file_name = "name_zonefiles".to_owned();
|
||||
let out_file_path = Path::new(&out_dir).join(out_file_name + ".gz");
|
||||
let out_file = File::create(out_file_path)?;
|
||||
let mut encoder = deflate::Encoder::new(out_file);
|
||||
std::io::copy(&mut reader, &mut encoder).unwrap();
|
||||
let mut out_file = encoder.finish().into_result().unwrap();
|
||||
out_file.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn sha256_digest<R: Read>(mut reader: R) -> String {
|
||||
let mut hasher = Sha256::new();
|
||||
let mut buffer = [0; 1024];
|
||||
@@ -130,3 +151,20 @@ fn verify_genesis_integrity(test_data: bool) -> std::io::Result<()> {
|
||||
chainstate_hash_file.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn verify_name_zonefiles_integrity() -> std::io::Result<()> {
|
||||
let zonefiles_data_sha = sha256_digest(File::open(NAME_ZONEFILES_FILE).unwrap());
|
||||
let expected_zonefiles_sha = fs::read_to_string(NAME_ZONEFILES_SHA256_FILE).unwrap();
|
||||
if !zonefiles_data_sha.eq_ignore_ascii_case(&expected_zonefiles_sha) {
|
||||
panic!(
|
||||
"FATAL ERROR: name_zonefiles.txt hash mismatch, expected {}, got {}",
|
||||
expected_zonefiles_sha, zonefiles_data_sha
|
||||
);
|
||||
}
|
||||
let out_dir = env::var_os("OUT_DIR").unwrap();
|
||||
let zonefile_hash_file_path = Path::new(&out_dir).join(NAME_ZONEFILES_SHA256_FILE);
|
||||
let mut zonefile_hash_file = File::create(zonefile_hash_file_path)?;
|
||||
zonefile_hash_file.write_all(zonefiles_data_sha.as_bytes())?;
|
||||
zonefile_hash_file.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
3214
stx-genesis/name_zonefiles.txt
Normal file
3214
stx-genesis/name_zonefiles.txt
Normal file
File diff suppressed because one or more lines are too long
1
stx-genesis/name_zonefiles.txt.sha256
Normal file
1
stx-genesis/name_zonefiles.txt.sha256
Normal file
@@ -0,0 +1 @@
|
||||
e97a56561b44daeac8f808eb8becd3d8b765f58940c104438a7d2a2f8b87099d
|
||||
@@ -1,7 +1,7 @@
|
||||
use std::io::prelude::*;
|
||||
use std::io::{Cursor, Lines, prelude::*};
|
||||
use std::io::{self, BufReader};
|
||||
|
||||
use libflate::deflate;
|
||||
use libflate::deflate::{self, Decoder};
|
||||
|
||||
pub struct GenesisAccountBalance {
|
||||
/// A STX or BTC address (BTC addresses should be converted to STX when used).
|
||||
@@ -40,6 +40,11 @@ pub struct GenesisName {
|
||||
pub zonefile_hash: String,
|
||||
}
|
||||
|
||||
pub struct GenesisZonefile {
|
||||
pub zonefile_hash: String,
|
||||
pub zonefile_content: String,
|
||||
}
|
||||
|
||||
pub static GENESIS_CHAINSTATE_HASH: &str =
|
||||
include_str!(concat!(env!("OUT_DIR"), "/chainstate.txt.sha256"));
|
||||
|
||||
@@ -81,6 +86,41 @@ impl GenesisData {
|
||||
include_bytes!(concat!(env!("OUT_DIR"), "/names.gz"))
|
||||
})
|
||||
}
|
||||
pub fn read_name_zonefiles(&self) -> Box<dyn Iterator<Item = GenesisZonefile>> {
|
||||
let zonefiles_bytes: &'static [u8] = include_bytes!(concat!(env!("OUT_DIR"), "/name_zonefiles.gz"));
|
||||
read_deflated_zonefiles(zonefiles_bytes)
|
||||
}
|
||||
}
|
||||
|
||||
struct LinePairReader {
|
||||
val: Lines<BufReader<Decoder<Cursor<&'static [u8]>>>>
|
||||
}
|
||||
|
||||
impl Iterator for LinePairReader {
|
||||
type Item = [String; 2];
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let (Some(l1), Some(l2)) = (self.val.next(), self.val.next()) {
|
||||
Some([l1.unwrap(), l2.unwrap()])
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_deflated_zonefiles(deflate_bytes: &'static [u8]) -> Box<dyn Iterator<Item = GenesisZonefile>> {
|
||||
let cursor = io::Cursor::new(deflate_bytes);
|
||||
let deflate_decoder = deflate::Decoder::new(cursor);
|
||||
let buff_reader = BufReader::new(deflate_decoder);
|
||||
let pairs = LinePairReader {
|
||||
val: buff_reader.lines()
|
||||
};
|
||||
let pair_iter = pairs.into_iter().map(|pair| {
|
||||
GenesisZonefile {
|
||||
zonefile_hash: pair[0].to_owned(),
|
||||
zonefile_content: pair[1].replace("\\n", "\n"),
|
||||
}
|
||||
});
|
||||
return Box::new(pair_iter);
|
||||
}
|
||||
|
||||
fn iter_deflated_csv(deflate_bytes: &'static [u8]) -> Box<dyn Iterator<Item = Vec<String>>> {
|
||||
@@ -183,4 +223,11 @@ mod tests {
|
||||
assert!(name.registered_at > 0);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_name_zonefiles_read() {
|
||||
for zonefile in GenesisData::new(false).read_name_zonefiles() {
|
||||
assert_eq!(zonefile.zonefile_hash.len(), 40);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user