feat: generate genesis utxos from genesis file (#59)
Co-authored-by: rvcas <x@rvcas.dev> Co-authored-by: jmhrpr <harper.jme@gmail.com>
This commit is contained in:
parent
90b228492c
commit
a8df6dc666
10 changed files with 15080 additions and 42 deletions
|
|
@ -5,6 +5,7 @@ members = [
|
||||||
"pallas-addresses",
|
"pallas-addresses",
|
||||||
"pallas-network",
|
"pallas-network",
|
||||||
"pallas-crypto",
|
"pallas-crypto",
|
||||||
|
"pallas-configs",
|
||||||
"pallas-primitives",
|
"pallas-primitives",
|
||||||
"pallas-traverse",
|
"pallas-traverse",
|
||||||
"pallas-utxorpc",
|
"pallas-utxorpc",
|
||||||
|
|
|
||||||
|
|
@ -18,3 +18,4 @@ base58 = "0.2.0"
|
||||||
bech32 = "0.9.1"
|
bech32 = "0.9.1"
|
||||||
thiserror = "1.0.31"
|
thiserror = "1.0.31"
|
||||||
crc = "3.0.1"
|
crc = "3.0.1"
|
||||||
|
sha3 = "0.10.8"
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ pub enum AddrType {
|
||||||
PubKey,
|
PubKey,
|
||||||
Script,
|
Script,
|
||||||
Redeem,
|
Redeem,
|
||||||
Other(u64),
|
Other(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'b, C> minicbor::Decode<'b, C> for AddrType {
|
impl<'b, C> minicbor::Decode<'b, C> for AddrType {
|
||||||
|
|
@ -70,7 +70,7 @@ impl<'b, C> minicbor::Decode<'b, C> for AddrType {
|
||||||
d: &mut minicbor::Decoder<'b>,
|
d: &mut minicbor::Decoder<'b>,
|
||||||
_ctx: &mut C,
|
_ctx: &mut C,
|
||||||
) -> Result<Self, minicbor::decode::Error> {
|
) -> Result<Self, minicbor::decode::Error> {
|
||||||
let variant = d.u64()?;
|
let variant = d.u32()?;
|
||||||
|
|
||||||
match variant {
|
match variant {
|
||||||
0 => Ok(AddrType::PubKey),
|
0 => Ok(AddrType::PubKey),
|
||||||
|
|
@ -88,10 +88,10 @@ impl<C> minicbor::Encode<C> for AddrType {
|
||||||
_ctx: &mut C,
|
_ctx: &mut C,
|
||||||
) -> Result<(), minicbor::encode::Error<W::Error>> {
|
) -> Result<(), minicbor::encode::Error<W::Error>> {
|
||||||
match self {
|
match self {
|
||||||
AddrType::PubKey => e.u64(0)?,
|
AddrType::PubKey => e.u32(0)?,
|
||||||
AddrType::Script => e.u64(1)?,
|
AddrType::Script => e.u32(1)?,
|
||||||
AddrType::Redeem => e.u64(2)?,
|
AddrType::Redeem => e.u32(2)?,
|
||||||
AddrType::Other(x) => e.u64(*x)?,
|
AddrType::Other(x) => e.u32(*x)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -149,6 +149,60 @@ impl<C> minicbor::Encode<C> for AddrAttrProperty {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd)]
|
||||||
|
pub enum SpendingData {
|
||||||
|
PubKey(ByteVec),
|
||||||
|
Script(ByteVec),
|
||||||
|
Redeem(ByteVec),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'b, C> minicbor::Decode<'b, C> for SpendingData {
|
||||||
|
fn decode(d: &mut minicbor::Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
|
||||||
|
d.array()?;
|
||||||
|
let key = d.u8()?;
|
||||||
|
|
||||||
|
match key {
|
||||||
|
0 => Ok(Self::PubKey(d.decode_with(ctx)?)),
|
||||||
|
1 => Ok(Self::Script(d.decode_with(ctx)?)),
|
||||||
|
2 => Ok(Self::Redeem(d.decode_with(ctx)?)),
|
||||||
|
_ => Err(minicbor::decode::Error::message(
|
||||||
|
"unknown tag for spending data",
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C> minicbor::Encode<C> for SpendingData {
|
||||||
|
fn encode<W: minicbor::encode::Write>(
|
||||||
|
&self,
|
||||||
|
e: &mut minicbor::Encoder<W>,
|
||||||
|
_ctx: &mut C,
|
||||||
|
) -> Result<(), minicbor::encode::Error<W::Error>> {
|
||||||
|
e.array(2)?;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
Self::PubKey(x) => {
|
||||||
|
e.u8(0)?;
|
||||||
|
e.encode(x)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Self::Script(x) => {
|
||||||
|
e.u8(1)?;
|
||||||
|
e.encode(x)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Self::Redeem(b) => {
|
||||||
|
e.u8(2)?;
|
||||||
|
e.encode(b)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type AddrAttrs = OrderPreservingProperties<AddrAttrProperty>;
|
pub type AddrAttrs = OrderPreservingProperties<AddrAttrProperty>;
|
||||||
|
|
||||||
#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, PartialOrd)]
|
#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, PartialOrd)]
|
||||||
|
|
@ -163,6 +217,62 @@ pub struct AddressPayload {
|
||||||
pub addrtype: AddrType,
|
pub addrtype: AddrType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use sha3::{Digest, Sha3_256};
|
||||||
|
impl AddressPayload {
|
||||||
|
pub fn hash_address_id(
|
||||||
|
addrtype: &AddrType,
|
||||||
|
spending_data: &SpendingData,
|
||||||
|
attributes: &AddrAttrs,
|
||||||
|
) -> Hash<28> {
|
||||||
|
let parts = (addrtype, spending_data, attributes);
|
||||||
|
let buf = minicbor::to_vec(parts).unwrap();
|
||||||
|
|
||||||
|
let mut sha = Sha3_256::new();
|
||||||
|
sha.update(buf);
|
||||||
|
let sha = sha.finalize();
|
||||||
|
|
||||||
|
pallas_crypto::hash::Hasher::<224>::hash(&sha)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(addrtype: AddrType, spending_data: SpendingData, attributes: AddrAttrs) -> Self {
|
||||||
|
AddressPayload {
|
||||||
|
root: Self::hash_address_id(&addrtype, &spending_data, &attributes),
|
||||||
|
attributes,
|
||||||
|
addrtype,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// bootstrap era + no hdpayload address
|
||||||
|
pub fn new_redeem(
|
||||||
|
pubkey: pallas_crypto::key::ed25519::PublicKey,
|
||||||
|
network_tag: Option<Vec<u8>>,
|
||||||
|
) -> Self {
|
||||||
|
let spending_data = SpendingData::Redeem(ByteVec::from(Vec::from(pubkey.as_ref())));
|
||||||
|
|
||||||
|
let attributes = match network_tag {
|
||||||
|
Some(x) => vec![
|
||||||
|
//AddrAttrProperty::DerivationPath(ByteVec::from(vec![])),
|
||||||
|
//AddrAttrProperty::AddrDistr(AddrDistr::BootstrapEraDistribution),
|
||||||
|
AddrAttrProperty::NetworkTag(x.into()),
|
||||||
|
]
|
||||||
|
.into(),
|
||||||
|
None => vec![
|
||||||
|
//AddrAttrProperty::DerivationPath(ByteVec::from(vec![])),
|
||||||
|
//AddrAttrProperty::AddrDistr(AddrDistr::BootstrapEraDistribution),
|
||||||
|
]
|
||||||
|
.into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Self::new(AddrType::Redeem, spending_data, attributes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AddressPayload> for ByronAddress {
|
||||||
|
fn from(value: AddressPayload) -> Self {
|
||||||
|
ByronAddress::from_decoded(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// New type wrapping a Byron address primitive
|
/// New type wrapping a Byron address primitive
|
||||||
#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct ByronAddress {
|
pub struct ByronAddress {
|
||||||
|
|
@ -183,31 +293,9 @@ impl ByronAddress {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_bootstrap(
|
pub fn from_decoded(payload: AddressPayload) -> Self {
|
||||||
root: AddressId,
|
|
||||||
addrtype: AddrType,
|
|
||||||
network_tag: Option<Vec<u8>>,
|
|
||||||
) -> Self {
|
|
||||||
let payload = AddressPayload {
|
|
||||||
root,
|
|
||||||
attributes: match network_tag {
|
|
||||||
Some(x) => vec![
|
|
||||||
AddrAttrProperty::AddrDistr(AddrDistr::BootstrapEraDistribution),
|
|
||||||
AddrAttrProperty::NetworkTag(x.into()),
|
|
||||||
]
|
|
||||||
.into(),
|
|
||||||
None => vec![AddrAttrProperty::AddrDistr(
|
|
||||||
AddrDistr::BootstrapEraDistribution,
|
|
||||||
)]
|
|
||||||
.into(),
|
|
||||||
},
|
|
||||||
addrtype,
|
|
||||||
};
|
|
||||||
|
|
||||||
let payload = minicbor::to_vec(payload).unwrap();
|
let payload = minicbor::to_vec(payload).unwrap();
|
||||||
|
|
||||||
let c = CRC.checksum(&payload);
|
let c = CRC.checksum(&payload);
|
||||||
|
|
||||||
ByronAddress::new(&payload, c)
|
ByronAddress::new(&payload, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -249,25 +337,55 @@ impl ByronAddress {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
const TEST_VECTOR: &str = "37btjrVyb4KDXBNC4haBVPCrro8AQPHwvCMp3RFhhSVWwfFmZ6wwzSK6JK1hY6wHNmtrpTf1kdbva8TCneM2YsiXT7mrzT21EacHnPpz5YyUdj64na";
|
const TEST_VECTORS: [&str; 3] = [
|
||||||
|
"37btjrVyb4KDXBNC4haBVPCrro8AQPHwvCMp3RFhhSVWwfFmZ6wwzSK6JK1hY6wHNmtrpTf1kdbva8TCneM2YsiXT7mrzT21EacHnPpz5YyUdj64na",
|
||||||
|
"DdzFFzCqrht7PQiAhzrn6rNNoADJieTWBt8KeK9BZdUsGyX9ooYD9NpMCTGjQoUKcHN47g8JMXhvKogsGpQHtiQ65fZwiypjrC6d3a4Q",
|
||||||
|
"Ae2tdPwUPEZLs4HtbuNey7tK4hTKrwNwYtGqp7bDfCy2WdR3P6735W5Yfpe",
|
||||||
|
];
|
||||||
|
|
||||||
const ROOT_HASH: &str = "7e9ee4a9527dea9091e2d580edd6716888c42f75d96276290f98fe0b";
|
// const ROOT_HASH: &str = "7e9ee4a9527dea9091e2d580edd6716888c42f75d96276290f98fe0b";
|
||||||
|
|
||||||
|
//const NON_AVVM_BYRON_ADDRESS_FROM_PREVIEW_GENESIS =
|
||||||
|
// "FHnt4NL7yPXjpZtYj1YUiX9QYYUZGXDT9gA2PJXQFkTSMx3EgawXK5BUrCHdhe2";
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn roundtrip_base58() {
|
fn roundtrip_base58() {
|
||||||
let addr = ByronAddress::from_base58(TEST_VECTOR).unwrap();
|
for vector in TEST_VECTORS {
|
||||||
|
let addr = ByronAddress::from_base58(vector).unwrap();
|
||||||
let ours = addr.to_base58();
|
let ours = addr.to_base58();
|
||||||
assert_eq!(TEST_VECTOR, ours);
|
assert_eq!(vector, ours);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn payload_matches() {
|
fn roundtrip_cbor() {
|
||||||
let addr = ByronAddress::from_base58(TEST_VECTOR).unwrap();
|
for vector in TEST_VECTORS {
|
||||||
|
let addr = ByronAddress::from_base58(vector).unwrap();
|
||||||
|
let addr = addr.decode().unwrap();
|
||||||
|
let addr = ByronAddress::from_decoded(addr);
|
||||||
|
let ours = addr.to_base58();
|
||||||
|
assert_eq!(vector, ours);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn payload_crc_matches() {
|
||||||
|
for vector in TEST_VECTORS {
|
||||||
|
let addr = ByronAddress::from_base58(vector).unwrap();
|
||||||
let crc2 = CRC.checksum(addr.payload.as_ref());
|
let crc2 = CRC.checksum(addr.payload.as_ref());
|
||||||
assert_eq!(crc2, addr.crc);
|
assert_eq!(crc2, addr.crc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let payload = addr.decode().unwrap();
|
// #[test]
|
||||||
assert_eq!(payload.root.to_string(), ROOT_HASH);
|
// fn address_id_matches() {
|
||||||
}
|
// let addr = ByronAddress::from_base58(TEST_VECTOR).unwrap();
|
||||||
|
|
||||||
|
// let payload = addr.decode().unwrap();
|
||||||
|
// let computed =
|
||||||
|
// AddressPayload::hash_address_id(&payload.addrtype, spending_data,
|
||||||
|
// &payload.attributes);
|
||||||
|
|
||||||
|
// assert_eq!(payload.root.to_string(), ROOT_HASH);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
24
pallas-configs/Cargo.toml
Normal file
24
pallas-configs/Cargo.toml
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
[package]
|
||||||
|
name = "pallas-configs"
|
||||||
|
description = "Config structs and utilities matching the Haskell implementation"
|
||||||
|
version = "0.19.0-alpha.2"
|
||||||
|
edition = "2021"
|
||||||
|
repository = "https://github.com/txpipe/pallas"
|
||||||
|
homepage = "https://github.com/txpipe/pallas"
|
||||||
|
documentation = "https://docs.rs/pallas-configs"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
readme = "README.md"
|
||||||
|
authors = ["Santiago Carmuega <santiago@carmuega.me>"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
hex = "0.4.3"
|
||||||
|
pallas-addresses = { version = "0.19.0-alpha.0", path = "../pallas-addresses" }
|
||||||
|
pallas-crypto = { version = "0.19.0-alpha.0", path = "../pallas-crypto" }
|
||||||
|
pallas-codec = { version = "0.19.0-alpha.0", path = "../pallas-codec" }
|
||||||
|
serde = { version = "1.0.136", optional = true, features = ["derive"] }
|
||||||
|
serde_json = { version = "1.0.79", optional = true }
|
||||||
|
base64 = "0.21.2"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
json = ["serde", "serde_json"]
|
||||||
|
default = ["json"]
|
||||||
2
pallas-configs/README.md
Normal file
2
pallas-configs/README.md
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
# Pallas Configs
|
||||||
|
|
||||||
218
pallas-configs/src/byron.rs
Normal file
218
pallas-configs/src/byron.rs
Normal file
|
|
@ -0,0 +1,218 @@
|
||||||
|
//! Parsing of Byron configuration data
|
||||||
|
|
||||||
|
use pallas_addresses::ByronAddress;
|
||||||
|
use pallas_crypto::hash::Hash;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct GenesisFile {
|
||||||
|
pub avvm_distr: HashMap<String, String>,
|
||||||
|
pub block_version_data: BlockVersionData,
|
||||||
|
pub fts_seed: Option<String>,
|
||||||
|
pub protocol_consts: ProtocolConsts,
|
||||||
|
pub start_time: u64,
|
||||||
|
pub boot_stakeholders: HashMap<String, BootStakeWeight>,
|
||||||
|
pub heavy_delegation: HashMap<String, HeavyDelegation>,
|
||||||
|
pub non_avvm_balances: HashMap<String, String>,
|
||||||
|
pub vss_certs: Option<HashMap<String, VssCert>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct BlockVersionData {
|
||||||
|
pub heavy_del_thd: String,
|
||||||
|
pub max_block_size: String,
|
||||||
|
pub max_header_size: String,
|
||||||
|
pub max_proposal_size: String,
|
||||||
|
pub max_tx_size: String,
|
||||||
|
pub mpc_thd: String,
|
||||||
|
pub script_version: u32,
|
||||||
|
pub slot_duration: String,
|
||||||
|
pub softfork_rule: SoftForkRule,
|
||||||
|
pub tx_fee_policy: TxFeePolicy,
|
||||||
|
pub unlock_stake_epoch: String,
|
||||||
|
pub update_implicit: String,
|
||||||
|
pub update_proposal_thd: String,
|
||||||
|
pub update_vote_thd: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct ProtocolConsts {
|
||||||
|
pub k: usize,
|
||||||
|
pub protocol_magic: u32,
|
||||||
|
#[serde(rename = "vssMaxTTL")]
|
||||||
|
pub vss_max_ttl: Option<u32>,
|
||||||
|
#[serde(rename = "vssMinTTL")]
|
||||||
|
pub vss_min_ttl: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type BootStakeWeight = u16;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct HeavyDelegation {
|
||||||
|
pub issuer_pk: String,
|
||||||
|
pub delegate_pk: String,
|
||||||
|
pub cert: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct VssCert {
|
||||||
|
pub vss_key: String,
|
||||||
|
// TODO: is this size fine?
|
||||||
|
pub expiry_epoch: u32,
|
||||||
|
pub signature: String,
|
||||||
|
pub signing_key: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct SoftForkRule {
|
||||||
|
pub init_thd: String,
|
||||||
|
pub min_thd: String,
|
||||||
|
pub thd_decrement: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct TxFeePolicy {
|
||||||
|
pub multiplier: String,
|
||||||
|
pub summand: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_file(path: &std::path::Path) -> Result<GenesisFile, std::io::Error> {
|
||||||
|
let file = std::fs::File::open(path)?;
|
||||||
|
let reader = std::io::BufReader::new(file);
|
||||||
|
let parsed: GenesisFile = serde_json::from_reader(reader)?;
|
||||||
|
|
||||||
|
Ok(parsed)
|
||||||
|
}
|
||||||
|
|
||||||
|
use base64::Engine;
|
||||||
|
|
||||||
|
pub type GenesisUtxo = (Hash<32>, ByronAddress, u64);
|
||||||
|
|
||||||
|
pub fn genesis_avvm_utxos(config: &GenesisFile) -> Vec<GenesisUtxo> {
|
||||||
|
config
|
||||||
|
.avvm_distr
|
||||||
|
.iter()
|
||||||
|
.map(|(pubkey, amount)| {
|
||||||
|
let amount = amount.parse().unwrap();
|
||||||
|
let pubkey = base64::engine::general_purpose::URL_SAFE
|
||||||
|
.decode(pubkey)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let pubkey = pallas_crypto::key::ed25519::PublicKey::try_from(&pubkey[..]).unwrap();
|
||||||
|
|
||||||
|
// TODO: network tag
|
||||||
|
//let network_tag = Some(config.protocol_consts.protocol_magic);
|
||||||
|
let network_tag = None;
|
||||||
|
|
||||||
|
let addr = pallas_addresses::byron::AddressPayload::new_redeem(pubkey, network_tag);
|
||||||
|
|
||||||
|
let addr: pallas_addresses::ByronAddress = addr.into();
|
||||||
|
|
||||||
|
let txid = pallas_crypto::hash::Hasher::<256>::hash_cbor(&addr);
|
||||||
|
|
||||||
|
(txid, addr, amount)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn genesis_non_avvm_utxos(config: &GenesisFile) -> Vec<GenesisUtxo> {
|
||||||
|
config
|
||||||
|
.non_avvm_balances
|
||||||
|
.iter()
|
||||||
|
.map(|(addr, amount)| {
|
||||||
|
let amount = amount.parse().unwrap();
|
||||||
|
let addr = ByronAddress::from_base58(addr).unwrap();
|
||||||
|
|
||||||
|
let txid = pallas_crypto::hash::Hasher::<256>::hash_cbor(&addr);
|
||||||
|
|
||||||
|
(txid, addr, amount)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn load_test_data_config(network: &str) -> GenesisFile {
|
||||||
|
let path = std::path::PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap())
|
||||||
|
.join("..")
|
||||||
|
.join("test_data")
|
||||||
|
.join(format!("{network}-byron-genesis.json"));
|
||||||
|
|
||||||
|
from_file(&path).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_preview_json_loads() {
|
||||||
|
load_test_data_config("preview");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_mainnet_json_loads() {
|
||||||
|
load_test_data_config("mainnet");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn utxo_exists(set: &[GenesisUtxo], expected: GenesisUtxo) -> bool {
|
||||||
|
set.iter().any(|(hash, addr, amount)| {
|
||||||
|
hash.eq(&expected.0) && addr.eq(&expected.1) && amount.eq(&expected.2)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn genesis_utxo_from_raw(hash_hex: &str, addr_base58: &str, amount: u64) -> GenesisUtxo {
|
||||||
|
(
|
||||||
|
Hash::from_str(hash_hex).unwrap(),
|
||||||
|
ByronAddress::from_base58(addr_base58).unwrap(),
|
||||||
|
amount,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_preview_non_avvm_utxos() {
|
||||||
|
let f = load_test_data_config("preview");
|
||||||
|
|
||||||
|
let utxos = super::genesis_non_avvm_utxos(&f);
|
||||||
|
assert_eq!(utxos.len(), 8);
|
||||||
|
|
||||||
|
// check known tx as seen: https://preview.cexplorer.io/tx/4843cf2e582b2f9ce37600e5ab4cc678991f988f8780fed05407f9537f7712bd
|
||||||
|
let expected = genesis_utxo_from_raw(
|
||||||
|
"4843cf2e582b2f9ce37600e5ab4cc678991f988f8780fed05407f9537f7712bd",
|
||||||
|
"FHnt4NL7yPXvDWHa8bVs73UEUdJd64VxWXSFNqetECtYfTd9TtJguJ14Lu3feth",
|
||||||
|
30_000_000_000_000_000,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(utxo_exists(&utxos, expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn test_mainnet_avvm_utxos() {
|
||||||
|
let f = load_test_data_config("mainnet");
|
||||||
|
|
||||||
|
let utxos = super::genesis_non_avvm_utxos(&f);
|
||||||
|
|
||||||
|
// there aren't non-avvm utxos in mainnet
|
||||||
|
assert!(utxos.is_empty());
|
||||||
|
|
||||||
|
let utxos = super::genesis_avvm_utxos(&f);
|
||||||
|
|
||||||
|
assert_eq!(utxos.len(), 14505);
|
||||||
|
|
||||||
|
// check known tx as seen: https://cexplorer.io/tx/0ae3da29711600e94a33fb7441d2e76876a9a1e98b5ebdefbf2e3bc535617616
|
||||||
|
let expected = genesis_utxo_from_raw(
|
||||||
|
"0ae3da29711600e94a33fb7441d2e76876a9a1e98b5ebdefbf2e3bc535617616",
|
||||||
|
"Ae2tdPwUPEZKQuZh2UndEoTKEakMYHGNjJVYmNZgJk2qqgHouxDsA5oT83n",
|
||||||
|
2_463_071_701_000_000,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(utxo_exists(&utxos, expected));
|
||||||
|
}
|
||||||
|
}
|
||||||
3
pallas-configs/src/lib.rs
Normal file
3
pallas-configs/src/lib.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
//! Genesis data structs and utilities
|
||||||
|
|
||||||
|
pub mod byron;
|
||||||
|
|
@ -22,6 +22,14 @@ impl<const BYTES: usize> From<[u8; BYTES]> for Hash<BYTES> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<const BYTES: usize> From<&[u8]> for Hash<BYTES> {
|
||||||
|
fn from(value: &[u8]) -> Self {
|
||||||
|
let mut hash = [0; BYTES];
|
||||||
|
hash.copy_from_slice(value);
|
||||||
|
Self::new(hash)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<const BYTES: usize> AsRef<[u8]> for Hash<BYTES> {
|
impl<const BYTES: usize> AsRef<[u8]> for Hash<BYTES> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn as_ref(&self) -> &[u8] {
|
fn as_ref(&self) -> &[u8] {
|
||||||
|
|
|
||||||
14572
test_data/mainnet-byron-genesis.json
Normal file
14572
test_data/mainnet-byron-genesis.json
Normal file
File diff suppressed because it is too large
Load diff
91
test_data/preview-byron-genesis.json
Normal file
91
test_data/preview-byron-genesis.json
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
{
|
||||||
|
"bootStakeholders": {
|
||||||
|
"021e737009040bf7f1e7b1bcc148f29d748d4a6b561902c95e4a9f36": 1,
|
||||||
|
"0bc82ced9544980b9ffe7f64b1538bbda6804a5cc32c8035485e184b": 1,
|
||||||
|
"18ed9844deef98cf9ba8b39791dede0538d2d2fa79bf67ef37dcc826": 1,
|
||||||
|
"66cfa84ad0ee5ca8586244c8393007cf3d9622d77cfa03fd4f35065b": 1,
|
||||||
|
"76c4d6c68c0ef81ae364411a84e52ce66089ed006ca29adfc0227901": 1,
|
||||||
|
"8cc6b89fec65cc83d34b7bab2e6494db631d8476a86625767dd0c2a0": 1,
|
||||||
|
"e90060fdc085ac9f63cdb3b32ba1d84e0f7eb98561687b213b4c8770": 1
|
||||||
|
},
|
||||||
|
"heavyDelegation": {
|
||||||
|
"021e737009040bf7f1e7b1bcc148f29d748d4a6b561902c95e4a9f36": {
|
||||||
|
"omega": 0,
|
||||||
|
"issuerPk": "6hSFCotivD08t02n43RMiaF9LzwtYVrFMu/WX6ShfEsxfdXFL5Y6c+DwHSZOCywU0RJz5er2icIO03UytC9NTg==",
|
||||||
|
"delegatePk": "JEnSVQTPGriTx1+lAMkKhCNsMBDNPGw+NiEvNPh4ui6IdvxrO+WkQPTy5U865XB4VFvi/zb7d+H1bilnztQNBg==",
|
||||||
|
"cert": "558952d17442e8cc73f0c7dd606e329b38ed2ec0c1f83fe2567d28b21ef2223d2d23640cd0531f75832b50e519631c48643fcfaa7168851645dce07b90d87f0e"
|
||||||
|
},
|
||||||
|
"0bc82ced9544980b9ffe7f64b1538bbda6804a5cc32c8035485e184b": {
|
||||||
|
"omega": 0,
|
||||||
|
"issuerPk": "MJ7IskKU8GKk0Eeg3zhfSOK1DDVXOMHD2V/zhEpODUtL9YB0Y7sXnbZfg3+Df05hskP5Jz+dZvdC6DH/dP9jmQ==",
|
||||||
|
"delegatePk": "hwO7NJL7LfAk5e/QG61FKcdORoK60tvprE3063Muh4EQKrWA6l7t23B2GziK8D0hRO0j5W1Gzpn8WW69XLIlKA==",
|
||||||
|
"cert": "2bccf50d0c3cbb03dd29cfba817e8ba615db3d7722b41b264ad08722e548cfe83d069b29d13e490823d7519ecdd9940ea49573f6027056c4bd58da1adf75020e"
|
||||||
|
},
|
||||||
|
"18ed9844deef98cf9ba8b39791dede0538d2d2fa79bf67ef37dcc826": {
|
||||||
|
"omega": 0,
|
||||||
|
"issuerPk": "pXbW4Jak8maeuWiosvrurykKnqDSHswUjroonSDS3fTnWS+BKe+vjT4zZJNKhQ33KbagiHVJ5CJUNggfsCtG2g==",
|
||||||
|
"delegatePk": "rbJAZp3kWCUvp8dnLR6qsgpGU+qKAFow4NHYKWiKCkfm1qFCFONob50N1IbNWCGWAhg38ZPTvBazTasjsfj6yQ==",
|
||||||
|
"cert": "89e1638e31fd3d402cecb897ba773d8c2c11c2d3cff2462b266e21461539b1a4fe8fb528e159b9af473799b51e49aa5b5816a88f10c484aa7cef7ad12850830a"
|
||||||
|
},
|
||||||
|
"66cfa84ad0ee5ca8586244c8393007cf3d9622d77cfa03fd4f35065b": {
|
||||||
|
"omega": 0,
|
||||||
|
"issuerPk": "/LGZjmmcAMRisP7Rf454GM2QUKgj2aAyqE+iQo2PIEhcistFOlT+idtbLTceZAnQcwwPJDtTcNi+EnPQyscZOg==",
|
||||||
|
"delegatePk": "rinFUiKKCPPFY0ULEKn1SPRgLVmOS3jdTXDtrxK6VI1I11G3uBS1Olxi0mQSN3kf+B3hm/xHkuUDVNaSXNiBeQ==",
|
||||||
|
"cert": "3e7f30bb68c5bc4d23c2a730ac154a188a1fd45aac3f438efd380303171443d2ca4f50e5a1ff66b40ae3da64697f2599956ae06c21b73fa828b8c0dc9fb27302"
|
||||||
|
},
|
||||||
|
"76c4d6c68c0ef81ae364411a84e52ce66089ed006ca29adfc0227901": {
|
||||||
|
"omega": 0,
|
||||||
|
"issuerPk": "9EE85tTLdSSR4T1Xoy6n9wr6jlbavCdfp9oQKusskO3DSSyNqRYS7QzYQ96j/WnphUey63082YkKijMfF9A4eA==",
|
||||||
|
"delegatePk": "dvyHDkXg8LFtb0K6Sitl8OGSEZPvfCVQYLDR6Au6t6/ROvlerMKQ8uri4fG7hQQzbHKtdKWgv94t+zuFJTQ1fw==",
|
||||||
|
"cert": "5ec0ed46ae7e575bdb089f1bceca3b2689b13a7162fe08578fe60ba64607fffaa507412a97652c3c81cc0ef93ff404cf809a628ae19faba1a035fca0505c1d04"
|
||||||
|
},
|
||||||
|
"8cc6b89fec65cc83d34b7bab2e6494db631d8476a86625767dd0c2a0": {
|
||||||
|
"omega": 0,
|
||||||
|
"issuerPk": "Hr5S5PAxf9HSB4FzmtZzaFcXrNrctrI5XUrDrnCkOUTX6rhbtOMkXU3sWVDOvU6LNSSr3/Ws2+iCYZIr7LmTWg==",
|
||||||
|
"delegatePk": "FaLH2b5H/XS31YRnm98N6fP4Etx6m+GbniVAXMwOp8KhYXPKBJBsX/EjIy3pSkvRBhGCjsycB0yrDxWMi5ZsIQ==",
|
||||||
|
"cert": "10f06304cceb42071605ebba67b308c7568e5e6fe0d773c58f7e8c13bc8d8a340f70a4fd5e1b4a1c1db1de5c7646802bbc929d6c82d7adb8a77cb6ad77eac50a"
|
||||||
|
},
|
||||||
|
"e90060fdc085ac9f63cdb3b32ba1d84e0f7eb98561687b213b4c8770": {
|
||||||
|
"omega": 0,
|
||||||
|
"issuerPk": "B2R+VXzy3c8bxncdOpQ2Z/tblxRNQO8AXQ0OsJDQvZYnLeGQcLD78kyYLpi3nfuS4SfnLar23NV4yiEVwaw+Yw==",
|
||||||
|
"delegatePk": "nACHGIBacymrKwn07iW/a5ZKJCPZ2cKQqeXw3ivR7WOYVUuufWhZlCoUTZ7rtBqoDaexblUQwkC7hA7AmNA3FA==",
|
||||||
|
"cert": "b5440daa05f7fae557df46e4f1b7c5802b86f465daad1137e315abf6e72f1c877207276abb8dcba86e18e42d39b34c2f0fa82ba2919944cdc8e2e5264baa450b"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"startTime": 1666656000,
|
||||||
|
"nonAvvmBalances": {
|
||||||
|
"FHnt4NL7yPXjpZtYj1YUiX9QYYUZGXDT9gA2PJXQFkTSMx3EgawXK5BUrCHdhe2": "0",
|
||||||
|
"FHnt4NL7yPXk7D87qAWEmfnL7wSQ9AzBU2mjZt3eM48NSCbygxgzAU6vCGiRZEW": "0",
|
||||||
|
"FHnt4NL7yPXpazQsTdJ3Gp1twQUo4N5rrgGbRNSzchjchPiApc1k4CvqDMcdd7H": "0",
|
||||||
|
"FHnt4NL7yPXtNo1wLCLZyGTMfAvB14h8onafiYkM7B69ZwvGgXeUyQWfi7FPrif": "0",
|
||||||
|
"FHnt4NL7yPXtmi4mAjD43V3NB3shDs1gCuHNcMLPsRWjaw1b2yRV2xad8S8V6aq": "0",
|
||||||
|
"FHnt4NL7yPXvDWHa8bVs73UEUdJd64VxWXSFNqetECtYfTd9TtJguJ14Lu3feth": "30000000000000000",
|
||||||
|
"FHnt4NL7yPXvNSRpCYydjRr7koQCrsTtkovk5uYMimgqMJX2DyrEEBqiXaTd8rG": "0",
|
||||||
|
"FHnt4NL7yPY9rTvdsCeyRnsbzp4bN7XdmAZeU5PzA1qR2asYmN6CsdxJw4YoDjG": "0"
|
||||||
|
},
|
||||||
|
"blockVersionData": {
|
||||||
|
"scriptVersion": 0,
|
||||||
|
"slotDuration": "20000",
|
||||||
|
"maxBlockSize": "2000000",
|
||||||
|
"maxHeaderSize": "2000000",
|
||||||
|
"maxTxSize": "4096",
|
||||||
|
"maxProposalSize": "700",
|
||||||
|
"mpcThd": "20000000000000",
|
||||||
|
"heavyDelThd": "300000000000",
|
||||||
|
"updateVoteThd": "1000000000000",
|
||||||
|
"updateProposalThd": "100000000000000",
|
||||||
|
"updateImplicit": "10000",
|
||||||
|
"softforkRule": {
|
||||||
|
"initThd": "900000000000000",
|
||||||
|
"minThd": "600000000000000",
|
||||||
|
"thdDecrement": "50000000000000"
|
||||||
|
},
|
||||||
|
"txFeePolicy": {
|
||||||
|
"summand": "155381000000000",
|
||||||
|
"multiplier": "43946000000"
|
||||||
|
},
|
||||||
|
"unlockStakeEpoch": "18446744073709551615"
|
||||||
|
},
|
||||||
|
"protocolConsts": { "k": 432, "protocolMagic": 2 },
|
||||||
|
"avvmDistr": {}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue