feat(primitives): Improve ergonomics for Byron primitives (#47)
* feat(primitives): Improve ergonomics for Byron primitives * fix(ci): Fix tests
This commit is contained in:
parent
400aa9c5d2
commit
f4504a349d
9 changed files with 293 additions and 45 deletions
|
|
@ -19,3 +19,4 @@ minicbor-derive = "0.8.0"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
pallas-crypto = { version = "0.5.0-alpha.0", path = "../pallas-crypto" }
|
pallas-crypto = { version = "0.5.0-alpha.0", path = "../pallas-crypto" }
|
||||||
|
base58 = "0.2.0"
|
||||||
|
|
|
||||||
62
pallas-primitives/src/byron/address.rs
Normal file
62
pallas-primitives/src/byron/address.rs
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
use crate::Error;
|
||||||
|
|
||||||
|
use super::Address;
|
||||||
|
use base58::ToBase58;
|
||||||
|
use minicbor::to_vec;
|
||||||
|
|
||||||
|
impl Address {
|
||||||
|
pub fn to_addr_string(&self) -> Result<String, Error> {
|
||||||
|
let cbor = to_vec(self)?;
|
||||||
|
Ok(cbor.to_base58())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
use crate::byron::Block;
|
||||||
|
use crate::Fragment;
|
||||||
|
|
||||||
|
const KNOWN_ADDRESSES: &[&str] = &[
|
||||||
|
"DdzFFzCqrht8QHTQXbWy2qoyPaqTN8BjyfKygGmpy9dtot1tvkBfCaVTnR22XCaaDVn3M1U6aiMShoCLzw6VWSwzQKhhJrM3YjYp3wyy",
|
||||||
|
"DdzFFzCqrhsjUjMRukzoFx8sToHzCt4iidB17STXk9adAoVMNus5SvAjS1cXfPKbuNbPUZ5xQG25sMK85n9GdMkqo2ytqBnKWC68s8P3",
|
||||||
|
"Ae2tdPwUPEZFBnsqpm2RkDQfwJseUrBKrTECCDom4bAqNsxTNwbMPCZtbyJ",
|
||||||
|
"DdzFFzCqrhsvNcX48aHrYdcQhKhAwEdLebH7xPskKtQnZucNQmXXmEMJEU2NDqipuDTZKFec5UMCtm4vYoUgjixxULJexAzHGa3Bmctk",
|
||||||
|
"Ae2tdPwUPEZGEC75fV3vktzbwxhkD71JHxSYVgiNCgKB7Yo1rWamWVJDFsV",
|
||||||
|
"DdzFFzCqrht1K1sR9fQWEdcxhTxgqKQqwPHucez1McJy14uqbxu1UKnnq12EdHr9NxYs8RqKnSvswegh8wLvfC4fw6arB3nyqC5Wy4Ky",
|
||||||
|
"DdzFFzCqrhtC8HauYJMa59DzoAeTLnpDcdst1hFWmjkTdg5Xu55ougiBpAmwuo2Coe2DfAj26m52aF4e2yk8v5GQc4umZxsXUT2CuTB2",
|
||||||
|
"DdzFFzCqrht4Zsigv43q9LRHNsgu6TWdASuGe6tCYuv2B9H2wTggkvyuwHMb5WALqWDDiNQEHYq7BvnFJ65UDzKi6ThdZusVYmYLpJg9",
|
||||||
|
];
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn known_address_matches() {
|
||||||
|
// TODO: expand this test to include more test blocks
|
||||||
|
let block_idx = 1;
|
||||||
|
let block_str = include_str!("test_data/test2.block");
|
||||||
|
|
||||||
|
let block_bytes = hex::decode(block_str).expect(&format!("bad block file {}", block_idx));
|
||||||
|
let block = Block::decode_fragment(&block_bytes[..])
|
||||||
|
.expect(&format!("error decoding cbor for file {}", block_idx));
|
||||||
|
|
||||||
|
let block = match block {
|
||||||
|
Block::MainBlock(x) => x,
|
||||||
|
Block::EbBlock(_) => panic!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// don't want to pass if we don't have tx in the block
|
||||||
|
assert!(block.body.tx_payload.len() > 0);
|
||||||
|
|
||||||
|
for tx in block.body.tx_payload.iter() {
|
||||||
|
for output in tx.deref().transaction.outputs.iter() {
|
||||||
|
let addr_str = output.address.to_addr_string().unwrap();
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
KNOWN_ADDRESSES.contains(&addr_str.as_str()),
|
||||||
|
"address {} not in known list",
|
||||||
|
addr_str
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,26 +1,34 @@
|
||||||
use super::{Block, BlockHead, EbbHead};
|
use super::{Block, BlockHead, EbbHead, Tx};
|
||||||
use pallas_crypto::hash::{Hash, Hasher};
|
use pallas_crypto::hash::{Hash, Hasher};
|
||||||
|
|
||||||
pub fn hash_boundary_block_header(header: &EbbHead) -> Hash<32> {
|
impl EbbHead {
|
||||||
// hash expects to have a prefix for the type of block
|
pub fn to_hash(&self) -> Hash<32> {
|
||||||
Hasher::<256>::hash_cbor(&(0, header))
|
// hash expects to have a prefix for the type of block
|
||||||
}
|
Hasher::<256>::hash_cbor(&(0, self))
|
||||||
|
|
||||||
pub fn hash_main_block_header(header: &BlockHead) -> Hash<32> {
|
|
||||||
// hash expects to have a prefix for the type of block
|
|
||||||
Hasher::<256>::hash_cbor(&(1, header))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn hash_block_header(block: &Block) -> Hash<32> {
|
|
||||||
match block {
|
|
||||||
Block::EbBlock(x) => hash_boundary_block_header(&x.header),
|
|
||||||
Block::MainBlock(x) => hash_main_block_header(&x.header),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//pub fn hash_transaction(data: &TransactionBody) -> Hash<32> {
|
impl BlockHead {
|
||||||
// Hasher::<256>::hash_cbor(data)
|
pub fn to_hash(&self) -> Hash<32> {
|
||||||
//}
|
// hash expects to have a prefix for the type of block
|
||||||
|
Hasher::<256>::hash_cbor(&(1, self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Block {
|
||||||
|
pub fn to_hash(&self) -> Hash<32> {
|
||||||
|
match self {
|
||||||
|
Block::EbBlock(x) => x.header.to_hash(),
|
||||||
|
Block::MainBlock(x) => x.header.to_hash(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tx {
|
||||||
|
pub fn to_hash(&self) -> Hash<32> {
|
||||||
|
Hasher::<256>::hash_cbor(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
@ -40,7 +48,7 @@ mod tests {
|
||||||
let block_model = Block::decode_fragment(&block_bytes[..])
|
let block_model = Block::decode_fragment(&block_bytes[..])
|
||||||
.expect(&format!("error decoding cbor for file {}", block_idx));
|
.expect(&format!("error decoding cbor for file {}", block_idx));
|
||||||
|
|
||||||
let computed_hash = super::hash_block_header(&block_model);
|
let computed_hash = block_model.to_hash();
|
||||||
|
|
||||||
assert_eq!(hex::encode(computed_hash), KNOWN_HASH)
|
assert_eq!(hex::encode(computed_hash), KNOWN_HASH)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
76
pallas-primitives/src/byron/fees.rs
Normal file
76
pallas-primitives/src/byron/fees.rs
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
use crate::Error;
|
||||||
|
|
||||||
|
use super::TxPayload;
|
||||||
|
use minicbor::to_vec;
|
||||||
|
|
||||||
|
pub struct PolicyParams {
|
||||||
|
constant: u64,
|
||||||
|
size_coeficient: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for PolicyParams {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
constant: 155_381_000_000_000u64,
|
||||||
|
size_coeficient: 43_946_000_000u64,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compute_linear_fee_policy(tx_size: u64, params: &PolicyParams) -> u64 {
|
||||||
|
println!("tx size: {}", tx_size);
|
||||||
|
let nanos = params.constant + (tx_size * params.size_coeficient);
|
||||||
|
|
||||||
|
let loves = nanos / 1_000_000_000;
|
||||||
|
|
||||||
|
let rem = match nanos % 1_000_000_000 {
|
||||||
|
0 => 0u64,
|
||||||
|
_ => 1u64,
|
||||||
|
};
|
||||||
|
|
||||||
|
loves + rem
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TxPayload {
|
||||||
|
pub fn compute_fee(&self, params: &PolicyParams) -> Result<u64, Error> {
|
||||||
|
let tx_size = to_vec(&self)?.len();
|
||||||
|
let fee = compute_linear_fee_policy(tx_size as u64, params);
|
||||||
|
|
||||||
|
Ok(fee)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compute_fee_with_defaults(&self) -> Result<u64, Error> {
|
||||||
|
self.compute_fee(&PolicyParams::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::byron::Block;
|
||||||
|
use crate::Fragment;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn known_fee_matches() {
|
||||||
|
// TODO: expand this test to include more test blocks
|
||||||
|
let block_idx = 1;
|
||||||
|
let block_str = include_str!("test_data/test4.block");
|
||||||
|
|
||||||
|
let block_bytes = hex::decode(block_str).expect(&format!("bad block file {}", block_idx));
|
||||||
|
let block = Block::decode_fragment(&block_bytes[..])
|
||||||
|
.expect(&format!("error decoding cbor for file {}", block_idx));
|
||||||
|
|
||||||
|
let block = match block {
|
||||||
|
Block::MainBlock(x) => x,
|
||||||
|
Block::EbBlock(_) => panic!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// don't want to pass if we don't have tx in the block
|
||||||
|
assert!(block.body.tx_payload.len() > 0);
|
||||||
|
|
||||||
|
for tx in block.body.tx_payload.iter().take(1) {
|
||||||
|
println!("{}", tx.transaction.to_hash());
|
||||||
|
let fee = tx.compute_fee_with_defaults().unwrap();
|
||||||
|
assert_eq!(fee, 171070);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
//! Ledger primitives and cbor codec for the Byron era
|
//! Ledger primitives and cbor codec for the Byron era
|
||||||
|
|
||||||
|
mod address;
|
||||||
|
mod crypto;
|
||||||
|
mod fees;
|
||||||
mod model;
|
mod model;
|
||||||
|
mod time;
|
||||||
|
|
||||||
pub use model::*;
|
pub use model::*;
|
||||||
|
|
||||||
pub mod crypto;
|
|
||||||
|
|
|
||||||
|
|
@ -173,13 +173,39 @@ impl minicbor::Encode for AddrAttrProperty {
|
||||||
|
|
||||||
pub type AddrAttr = OrderPreservingProperties<AddrAttrProperty>;
|
pub type AddrAttr = OrderPreservingProperties<AddrAttrProperty>;
|
||||||
|
|
||||||
|
#[derive(Debug, Encode, Decode)]
|
||||||
|
pub struct AddressPayload {
|
||||||
|
#[n(0)]
|
||||||
|
pub root: AddressId,
|
||||||
|
|
||||||
|
#[n(1)]
|
||||||
|
pub attributes: AddrAttr,
|
||||||
|
|
||||||
|
#[n(2)]
|
||||||
|
pub addrtype: AddrType,
|
||||||
|
}
|
||||||
|
|
||||||
// address = [ #6.24(bytes .cbor ([addressid, addrattr, addrtype])), u64 ]
|
// address = [ #6.24(bytes .cbor ([addressid, addrattr, addrtype])), u64 ]
|
||||||
pub type Address = (CborWrap<(AddressId, AddrAttr, AddrType)>, u64);
|
#[derive(Debug, Encode, Decode)]
|
||||||
|
pub struct Address {
|
||||||
|
#[n(0)]
|
||||||
|
pub payload: CborWrap<AddressPayload>,
|
||||||
|
|
||||||
|
#[n(1)]
|
||||||
|
pub crc: u64,
|
||||||
|
}
|
||||||
|
|
||||||
// Transactions
|
// Transactions
|
||||||
|
|
||||||
// txout = [address, u64]
|
// txout = [address, u64]
|
||||||
pub type TxOut = (Address, u64);
|
#[derive(Debug, Encode, Decode)]
|
||||||
|
pub struct TxOut {
|
||||||
|
#[n(0)]
|
||||||
|
pub address: Address,
|
||||||
|
|
||||||
|
#[n(1)]
|
||||||
|
pub amount: u64,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum TxIn {
|
pub enum TxIn {
|
||||||
|
|
@ -228,21 +254,34 @@ impl minicbor::Encode for TxIn {
|
||||||
}
|
}
|
||||||
|
|
||||||
// tx = [[+ txin], [+ txout], attributes]
|
// tx = [[+ txin], [+ txout], attributes]
|
||||||
pub type Tx = (Vec<TxIn>, Vec<TxOut>, Attributes);
|
#[derive(Debug, Encode, Decode)]
|
||||||
|
pub struct Tx {
|
||||||
|
#[n(0)]
|
||||||
|
pub inputs: MaybeIndefArray<TxIn>,
|
||||||
|
|
||||||
|
#[n(1)]
|
||||||
|
pub outputs: MaybeIndefArray<TxOut>,
|
||||||
|
|
||||||
|
#[n(2)]
|
||||||
|
pub attributes: Attributes,
|
||||||
|
}
|
||||||
|
|
||||||
// txproof = [u32, hash, hash]
|
// txproof = [u32, hash, hash]
|
||||||
pub type TxProof = (u32, ByronHash, ByronHash);
|
pub type TxProof = (u32, ByronHash, ByronHash);
|
||||||
|
|
||||||
|
pub type ValidatorScript = (u16, ByteVec);
|
||||||
|
pub type RedeemerScript = (u16, ByteVec);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Twit {
|
pub enum Twit {
|
||||||
// [0, #6.24(bytes .cbor ([pubkey, signature]))]
|
// [0, #6.24(bytes .cbor ([pubkey, signature]))]
|
||||||
Variant0(CborWrap<(PubKey, Signature)>),
|
PkWitness(CborWrap<(PubKey, Signature)>),
|
||||||
|
|
||||||
// [1, #6.24(bytes .cbor ([[u16, bytes], [u16, bytes]]))]
|
// [1, #6.24(bytes .cbor ([[u16, bytes], [u16, bytes]]))]
|
||||||
Variant1(CborWrap<((u16, ByteVec), (u16, ByteVec))>),
|
ScriptWitness(CborWrap<(ValidatorScript, RedeemerScript)>),
|
||||||
|
|
||||||
// [2, #6.24(bytes .cbor ([pubkey, signature]))]
|
// [2, #6.24(bytes .cbor ([pubkey, signature]))]
|
||||||
Variant2(CborWrap<(PubKey, Signature)>),
|
RedeemWitness(CborWrap<(PubKey, Signature)>),
|
||||||
|
|
||||||
// [u8 .gt 2, encoded-cbor]
|
// [u8 .gt 2, encoded-cbor]
|
||||||
Other(u8, ByteVec),
|
Other(u8, ByteVec),
|
||||||
|
|
@ -255,9 +294,9 @@ impl<'b> minicbor::Decode<'b> for Twit {
|
||||||
let variant = d.u8()?;
|
let variant = d.u8()?;
|
||||||
|
|
||||||
match variant {
|
match variant {
|
||||||
0 => Ok(Twit::Variant0(d.decode()?)),
|
0 => Ok(Twit::PkWitness(d.decode()?)),
|
||||||
1 => Ok(Twit::Variant1(d.decode()?)),
|
1 => Ok(Twit::ScriptWitness(d.decode()?)),
|
||||||
2 => Ok(Twit::Variant2(d.decode()?)),
|
2 => Ok(Twit::RedeemWitness(d.decode()?)),
|
||||||
x => Ok(Twit::Other(x, d.decode()?)),
|
x => Ok(Twit::Other(x, d.decode()?)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -269,21 +308,21 @@ impl minicbor::Encode for Twit {
|
||||||
e: &mut minicbor::Encoder<W>,
|
e: &mut minicbor::Encoder<W>,
|
||||||
) -> Result<(), minicbor::encode::Error<W::Error>> {
|
) -> Result<(), minicbor::encode::Error<W::Error>> {
|
||||||
match self {
|
match self {
|
||||||
Twit::Variant0(x) => {
|
Twit::PkWitness(x) => {
|
||||||
e.array(2)?;
|
e.array(2)?;
|
||||||
e.u8(0)?;
|
e.u8(0)?;
|
||||||
e.encode(x)?;
|
e.encode(x)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Twit::Variant1(x) => {
|
Twit::ScriptWitness(x) => {
|
||||||
e.array(2)?;
|
e.array(2)?;
|
||||||
e.u8(1)?;
|
e.u8(1)?;
|
||||||
e.encode(x)?;
|
e.encode(x)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Twit::Variant2(x) => {
|
Twit::RedeemWitness(x) => {
|
||||||
e.array(2)?;
|
e.array(2)?;
|
||||||
e.u8(2)?;
|
e.u8(2)?;
|
||||||
e.encode(x)?;
|
e.encode(x)?;
|
||||||
|
|
@ -327,7 +366,7 @@ pub type VssDec = ByteVec;
|
||||||
// cddl note:
|
// cddl note:
|
||||||
// This is encoded using the
|
// This is encoded using the
|
||||||
// 'Binary' instance for Scrape.Proof
|
// 'Binary' instance for Scrape.Proof
|
||||||
pub type VssProof = (ByteVec, ByteVec, ByteVec, Vec<ByteVec>);
|
pub type VssProof = (ByteVec, ByteVec, ByteVec, MaybeIndefArray<ByteVec>);
|
||||||
|
|
||||||
//ssccomm = [pubkey, [{vsspubkey => vssenc},vssproof], signature]
|
//ssccomm = [pubkey, [{vsspubkey => vssenc},vssproof], signature]
|
||||||
pub type SscComm = (
|
pub type SscComm = (
|
||||||
|
|
@ -781,7 +820,14 @@ pub struct BlockHead {
|
||||||
}
|
}
|
||||||
|
|
||||||
// [tx, [* twit]]
|
// [tx, [* twit]]
|
||||||
pub type TxPayload = (Tx, Vec<Twit>);
|
#[derive(Debug, Encode, Decode)]
|
||||||
|
pub struct TxPayload {
|
||||||
|
#[n(0)]
|
||||||
|
pub transaction: Tx,
|
||||||
|
|
||||||
|
#[n(1)]
|
||||||
|
pub witness: MaybeIndefArray<Twit>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Encode, Decode, Debug)]
|
#[derive(Encode, Decode, Debug)]
|
||||||
pub struct BlockBody {
|
pub struct BlockBody {
|
||||||
|
|
@ -920,12 +966,10 @@ mod tests {
|
||||||
let block = Block::decode_fragment(&bytes[..])
|
let block = Block::decode_fragment(&bytes[..])
|
||||||
.expect(&format!("error decoding cbor for file {}", idx));
|
.expect(&format!("error decoding cbor for file {}", idx));
|
||||||
|
|
||||||
let _bytes2 =
|
let bytes2 =
|
||||||
to_vec(block).expect(&format!("error encoding block cbor for file {}", idx));
|
to_vec(block).expect(&format!("error encoding block cbor for file {}", idx));
|
||||||
|
|
||||||
// HACK: we ommit the ismorphic requirement until we find the
|
assert_eq!(hex::encode(bytes), hex::encode(bytes2));
|
||||||
// offending difference
|
|
||||||
// assert_eq!(bytes, bytes2);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -940,8 +984,6 @@ mod tests {
|
||||||
let block = BlockHead::decode_fragment(&bytes[..])
|
let block = BlockHead::decode_fragment(&bytes[..])
|
||||||
.expect(&format!("error decoding cbor for file {}", idx));
|
.expect(&format!("error decoding cbor for file {}", idx));
|
||||||
|
|
||||||
println!("{:?}", block);
|
|
||||||
|
|
||||||
let bytes2 =
|
let bytes2 =
|
||||||
to_vec(block).expect(&format!("error encoding header cbor for file {}", idx));
|
to_vec(block).expect(&format!("error encoding header cbor for file {}", idx));
|
||||||
|
|
||||||
|
|
|
||||||
1
pallas-primitives/src/byron/test_data/test4.block
Normal file
1
pallas-primitives/src/byron/test_data/test4.block
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
820183851a2d964a095820b5bdd15fbfbe7f618d2b7db0b20632658466b1b17654e9a8b865ec0e9fdccd4e8483015820c2c44f1f28599c08c6c1da0e375dc995d2b686c445b19110fa96ca68dfb2880e5820314b3c77650d6eba459864966dbcda18c438ee21bdd7e6b3272bf1e6b241d75d83025820d36a2619a672494604e11bb447cbcf5231e9f2ba25c2169177edc941bd50ad6c5820d36a2619a672494604e11bb447cbcf5231e9f2ba25c2169177edc941bd50ad6c5820afc0da64183bf2664f3d4eec7238d524ba607faeeab24fc100eb861dba69971b58204e66280cd94d591072349bec0a3090a53aa945562efb6d08d56e53654b0e4098848201195457584026566e86fc6b9b177c8480e275b2b112b573f6d073f9deea53b8d99c4ed976b335b2b3842f0e380001f090bc923caa9691ed9115e286da9421e2745c7acc87f18119a89f8202828400584026566e86fc6b9b177c8480e275b2b112b573f6d073f9deea53b8d99c4ed976b335b2b3842f0e380001f090bc923caa9691ed9115e286da9421e2745c7acc87f15840f14f712dc600d793052d4842d50cefa4e65884ea6cf83707079eb8ce302efc85dae922d5eb3838d2b91784f04824d26767bfb65bd36a36e74fec46d09d98858d58408ab43e904b06e799c1817c5ced4f3a7bbe15cdbf422dea9d2d5dc2c6105ce2f4d4c71e5d4779f6c44b770a133636109949e1f7786acb5a732bcdea0470fea4065840cfd641e91f908471af31762e7124147e8d3b27036d436f24d785de7330ebe33c03dae5ec27eb2944a82545fbcc30016737ba7696fb5e3fcaf8963ea12dbb87098483000000826a63617264616e6f2d736c01a058204ba92aa320c60acc9ad7b9a64f2eda55c4d2ec28e604faf186708b4f0c4e8edf849f82839f8200d81858248258200ca95f3bb516e3fa36b3c5ce18316a3d197b4faf2e36635baecae47e8a714b8d00ff9f8282d818584283581caca526063940ef762c899b92f20134264a43c5ab36d46cc6d36540d1a101581e581c2729cbfd641133bd0633ff422b246fa0d95cc2bef293d39adf3fd22b001aa25f5bd41b0000021a9f3ab0c28282d818584283581ce0751a974c40abdac7e71ee5b09d12b0591b1f4ecab73062ac8f96caa101581e581cca3e553c9c63c531002ff143535ea35088673bf86d25026baf12db3e001afdf29bac1a02625a00ffa0818200d81858858258408b9397dce473d3f296ad24e24e48795a495ad2f1602896e913fdc7e55e55e21f6fa53491a197e86428c86fadc0253ddec8d88bee623d474632603633643b26eb5840555e2f86fd803d1ed5bb3a3bc7f08dd82896744c4a0d99ce7b61f696ef632b12f6d8bd4787fcfe27de2bb7b1127fb1646d8d2f26755b4186f605210709016709ff8302a0d90102809fff82809fff81a0
|
||||||
47
pallas-primitives/src/byron/time.rs
Normal file
47
pallas-primitives/src/byron/time.rs
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
use super::{EbbHead, SlotId};
|
||||||
|
|
||||||
|
// TODO: is it safe to hardcode these values?
|
||||||
|
const WELLKNOWN_SLOT_LENGTH: u64 = 20; // 20 secs
|
||||||
|
const WELLKNOWN_EPOCH_LENGTH: u64 = 5 * 24 * 60 * 60; // 5 days
|
||||||
|
|
||||||
|
fn epoch_slot_to_absolute(epoch: u64, sub_epoch_slot: u64) -> u64 {
|
||||||
|
((epoch * WELLKNOWN_EPOCH_LENGTH) / WELLKNOWN_SLOT_LENGTH) + sub_epoch_slot
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SlotId {
|
||||||
|
pub fn to_abs_slot(&self) -> u64 {
|
||||||
|
epoch_slot_to_absolute(self.epoch, self.slot)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EbbHead {
|
||||||
|
pub fn to_abs_slot(&self) -> u64 {
|
||||||
|
epoch_slot_to_absolute(self.consensus_data.epoch_id, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::byron::Block;
|
||||||
|
use crate::Fragment;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn knwon_slot_matches() {
|
||||||
|
// TODO: expand this test to include more test blocks
|
||||||
|
let block_idx = 1;
|
||||||
|
let block_str = include_str!("test_data/test1.block");
|
||||||
|
|
||||||
|
let block_bytes = hex::decode(block_str).expect(&format!("bad block file {}", block_idx));
|
||||||
|
let block = Block::decode_fragment(&block_bytes[..])
|
||||||
|
.expect(&format!("error decoding cbor for file {}", block_idx));
|
||||||
|
|
||||||
|
let block = match block {
|
||||||
|
Block::MainBlock(x) => x,
|
||||||
|
Block::EbBlock(_) => panic!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let computed_slot = block.header.consensus_data.0.to_abs_slot();
|
||||||
|
|
||||||
|
assert_eq!(computed_slot, 4492794);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -153,9 +153,10 @@ where
|
||||||
MaybeIndefArray::Def(x) => {
|
MaybeIndefArray::Def(x) => {
|
||||||
e.encode(x)?;
|
e.encode(x)?;
|
||||||
}
|
}
|
||||||
MaybeIndefArray::Indef(x) if x.is_empty() => {
|
// TODO: this seemed necesary on alonzo, but breaks on byron. We need to double check.
|
||||||
e.encode(x)?;
|
//MaybeIndefArray::Indef(x) if x.is_empty() => {
|
||||||
}
|
// e.encode(x)?;
|
||||||
|
//}
|
||||||
MaybeIndefArray::Indef(x) => {
|
MaybeIndefArray::Indef(x) => {
|
||||||
e.begin_array()?;
|
e.begin_array()?;
|
||||||
|
|
||||||
|
|
@ -223,7 +224,7 @@ where
|
||||||
|
|
||||||
/// Wraps a struct so that it is encoded/decoded as a cbor bytes
|
/// Wraps a struct so that it is encoded/decoded as a cbor bytes
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct CborWrap<T>(T);
|
pub struct CborWrap<T>(pub T);
|
||||||
|
|
||||||
impl<'b, T> minicbor::Decode<'b> for CborWrap<T>
|
impl<'b, T> minicbor::Decode<'b> for CborWrap<T>
|
||||||
where
|
where
|
||||||
|
|
@ -257,6 +258,14 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Deref for CborWrap<T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TagWrap<I, const T: u64>(I);
|
pub struct TagWrap<I, const T: u64>(I);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue