feat: embed name_zonefiles.txt and implement parser

This commit is contained in:
Matthew Little
2021-01-07 14:04:35 +01:00
parent 269e6623cd
commit 14e51dd357
4 changed files with 3310 additions and 10 deletions

View File

@@ -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(())
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
e97a56561b44daeac8f808eb8becd3d8b765f58940c104438a7d2a2f8b87099d

View File

@@ -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);
}
}
}