Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parameterize CML Valid Range Calculation #147

Merged
merged 5 commits into from
Sep 2, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/ledger_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ pub enum LedgerClientError {
ConfigError(String),
#[error("While getting current time: {0:?}")]
CurrentTime(Box<dyn error::Error + Send + Sync>),
#[error("While setting validity range: {0:?}")]
ValidityRange(String),
}

pub type LedgerClientResult<T> = Result<T, LedgerClientError>;
1 change: 1 addition & 0 deletions src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ pub enum TransactionVersion {
V2,
}

/// Range of times in seconds since the Unix epoch
type Range = (Option<i64>, Option<i64>);

pub struct UnbuiltTransaction<Datum, Redeemer> {
Expand Down
30 changes: 23 additions & 7 deletions src/trireme_ledger_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,16 @@ pub enum KeySource {
#[serde(tag = "type")]
pub enum Network {
Preprod,
Preview,
Mainnet,
Testnet,
}

impl From<Network> for u8 {
fn from(network: Network) -> Self {
match network {
Network::Preprod => 0,
Network::Mainnet => 1,
Network::Preprod | Network::Preview | Network::Testnet => 0,
}
}
}
Expand Down Expand Up @@ -290,10 +292,9 @@ impl ClientConfig {
match self.variant {
ClientVariant::CML(inner) => {
let network = inner.network;
let network_index = network.clone().into();
let keys = match inner.key_source {
KeySource::RawSecretPhrase { phrase_file } => {
let keys = RawSecretPhraseKeys::new(phrase_file, network_index);
let keys = RawSecretPhraseKeys::new(phrase_file, network.clone().into());
SecretPhraseKeys::RawSecretPhraseKeys(keys)
}
KeySource::TerminalPasswordUpfrontSecretPhrase {
Expand All @@ -305,7 +306,7 @@ impl ClientConfig {
let keys = PasswordProtectedPhraseKeys::new(
password,
phrase_file,
network_index,
network.clone().into(),
encrpytion_nonce,
);
SecretPhraseKeys::PasswordProtectedPhraseKeys(keys)
Expand All @@ -323,12 +324,27 @@ impl ClientConfig {
)
})?;
let key: String = blockfrost_key.into();
let url = match network {
let url = match &network {
Network::Preprod => PREPROD_NETWORK_URL,
Network::Mainnet => MAINNET_URL,
Network::Preview => {
return Err(Error::Trireme(
"Preview network not supported yet".to_string(),
))
}
Network::Testnet => {
return Err(Error::Trireme(
"Testnet network is no longer supported".to_string(),
))
}
};
let ledger = BlockFrostLedger::new(url, &key);
InnerClient::BlockFrost(CMLLedgerCLient::new(ledger, keys, network_index))
let network_settings = network.clone().into();
InnerClient::BlockFrost(CMLLedgerCLient::new(
ledger,
keys,
network_settings,
))
}
LedgerSource::OgmiosAndScrolls {
scrolls_ip,
Expand All @@ -342,7 +358,7 @@ impl ClientConfig {
InnerClient::OgmiosScrolls(CMLLedgerCLient::new(
ledger,
keys,
network_index,
network.into(),
))
}
};
Expand Down
54 changes: 28 additions & 26 deletions src/trireme_ledger_client/cml_client.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::trireme_ledger_client::cml_client::network_settings::NetworkSettings;
use crate::{
ledger_client::{LedgerClient, LedgerClientError, LedgerClientResult},
output::{Output, UnbuiltOutput},
Expand Down Expand Up @@ -35,14 +36,15 @@ use cardano_multiplatform_lib::{
TransactionInput, TransactionOutput,
};
use error::*;
use pallas_addresses::{Address, Network};
use pallas_addresses::{Address, Network as CMLNetwork};
use std::time::UNIX_EPOCH;
use std::{collections::HashMap, fmt::Debug, marker::PhantomData, ops::Deref};

pub mod blockfrost_ledger;
pub mod error;
pub mod issuance_helpers;
pub mod key_manager;
pub mod network_settings;
pub mod ogmios_scrolls_ledger;
pub mod plutus_data_interop;

Expand All @@ -59,7 +61,7 @@ where
{
ledger: L,
keys: K,
network: u8,
network_settings: NetworkSettings,
_datum: PhantomData<Datum>,
_redeemer: PhantomData<Redeemer>,
}
Expand Down Expand Up @@ -195,11 +197,11 @@ where
D: PlutusDataInterop,
R: PlutusDataInterop,
{
pub fn new(ledger: L, keys: K, network: u8) -> Self {
pub fn new(ledger: L, keys: K, network_settings: NetworkSettings) -> Self {
CMLLedgerCLient {
ledger,
keys,
network,
network_settings,
_datum: Default::default(),
_redeemer: Default::default(),
}
Expand Down Expand Up @@ -242,7 +244,7 @@ where
async fn cml_script_address(&self, cml_script: &PlutusScript) -> CMLAddress {
let script_hash = cml_script.hash();
let stake_cred = StakeCredential::from_scripthash(&script_hash);
let enterprise_addr = EnterpriseAddress::new(self.network, &stake_cred);
let enterprise_addr = EnterpriseAddress::new(self.network_settings.network(), &stake_cred);
enterprise_addr.to_address()
}

Expand Down Expand Up @@ -513,33 +515,33 @@ where
Ok(tx_id)
}

// TODO: https://github.com/MitchTurner/naumachia/issues/79
async fn set_valid_range<Datum: PlutusDataInterop + Debug, Redeemer: PlutusDataInterop>(
&self,
tx_builder: &mut TransactionBuilder,
tx: &UnbuiltTransaction<Datum, Redeemer>,
) -> LedgerClientResult<()> {
// TODO: This only works on Testnet :(((((( and it's kinda hacky at that
// https://github.com/MitchTurner/naumachia/issues/78
fn slot_from_posix(posix: i64) -> BigNum {
// From this time onward, each slot is 1 second
const ARB_SLOT_POSIX: i64 = 1595967616;
const ARB_SLOT: i64 = 1598400;
if posix < ARB_SLOT_POSIX {
todo!("posix too low!")
} else {
let delta = posix - ARB_SLOT_POSIX;
((ARB_SLOT + delta) as u64).into()
}
}
let (lower, _upper) = tx.valid_range;
let (lower, upper) = tx.valid_range;
if let Some(posix) = lower {
let slot = slot_from_posix(posix);
let slot = self.slot_from_posix(posix)?;
tx_builder.set_validity_start_interval(&slot);
}
if let Some(posix) = upper {
let slot = self.slot_from_posix(posix)?;
tx_builder.set_ttl(&slot);
}
Ok(())
}

fn slot_from_posix(&self, posix: i64) -> LedgerClientResult<BigNum> {
let time_ms = posix
.checked_sub(self.network_settings.first_slot_time())
.ok_or(LedgerClientError::ValidityRange(
"Validity range must be after genesis".to_string(),
))?;
let slot = time_ms / self.network_settings.slot_length();
Ok((slot as u64).into())
}

async fn add_specific_inputs<Datum: PlutusDataInterop + Debug, Redeemer: PlutusDataInterop>(
&self,
tx_builder: &mut TransactionBuilder,
Expand Down Expand Up @@ -668,11 +670,11 @@ where
}
}

async fn network(&self) -> LedgerClientResult<Network> {
let network = match self.network {
0 => Network::Testnet,
1 => Network::Mainnet,
_ => Network::Other(self.network),
async fn network(&self) -> LedgerClientResult<CMLNetwork> {
let network = match self.network_settings.network() {
0 => CMLNetwork::Testnet,
1 => CMLNetwork::Mainnet,
_ => CMLNetwork::Other(self.network_settings.network()),
};
Ok(network)
}
Expand Down
3 changes: 0 additions & 3 deletions src/trireme_ledger_client/cml_client/key_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ use cardano_multiplatform_lib::{
use std::{fs, path::Path};
use thiserror::Error;

pub const TESTNET: u8 = 0;
pub const MAINNET: u8 = 1;

pub struct KeyManager {
config_path: String,
network: u8,
Expand Down
72 changes: 72 additions & 0 deletions src/trireme_ledger_client/cml_client/network_settings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use crate::trireme_ledger_client::Network;

pub struct NetworkSettings {
network: u8,
slot_length: i64,
first_slot_time: i64,
}

impl NetworkSettings {
pub fn new(network: u8, slot_length: i64, first_slot_time: i64) -> Self {
NetworkSettings {
network,
slot_length,
first_slot_time,
}
}

pub fn network(&self) -> u8 {
self.network
}

pub fn slot_length(&self) -> i64 {
self.slot_length
}

pub fn first_slot_time(&self) -> i64 {
self.first_slot_time
}
}

const MAINNET_NETWORK: u8 = 1;
const MAINNET_SLOT_LENGTH: i64 = 1;
const MAINNET_FIRST_SLOT_TIME: i64 = 1596059091;

const PRE_PROD_NETWORK: u8 = 0;
const PRE_PROD_SLOT_LENGTH: i64 = 1;
const PRE_PROD_FIRST_SLOT_TIME: i64 = 1654041600;

const PREVIEW_NETWORK: u8 = 0;
const PREVIEW_SLOT_LENGTH: i64 = 1;
const PREVIEW_FIRST_SLOT_TIME: i64 = 1660003200;

const TESTNET_NETWORK: u8 = 0;
const TESTNET_SLOT_LENGTH: i64 = 1;
const TESTNET_FIRST_SLOT_TIME: i64 = 1595967616;

impl From<Network> for NetworkSettings {
fn from(network: Network) -> Self {
match network {
Network::Preprod => NetworkSettings::new(
PRE_PROD_NETWORK,
PRE_PROD_SLOT_LENGTH,
PRE_PROD_FIRST_SLOT_TIME,
),
Network::Mainnet => NetworkSettings::new(
MAINNET_NETWORK,
MAINNET_SLOT_LENGTH,
MAINNET_FIRST_SLOT_TIME,
),
Network::Preview => NetworkSettings::new(
PREVIEW_NETWORK,
PREVIEW_SLOT_LENGTH,
PREVIEW_FIRST_SLOT_TIME,
),
Network::Testnet => NetworkSettings::new(
TESTNET_NETWORK,
TESTNET_SLOT_LENGTH,
TESTNET_FIRST_SLOT_TIME,
),
}
}
}
19 changes: 10 additions & 9 deletions src/trireme_ledger_client/cml_client/tests.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use super::*;
use crate::trireme_ledger_client::cml_client::{
blockfrost_ledger::BlockFrostLedger,
key_manager::{KeyManager, TESTNET},
blockfrost_ledger::BlockFrostLedger, key_manager::KeyManager,
};
use crate::trireme_ledger_client::Network;
use crate::PolicyId;
use blockfrost_http_client::load_key_from_file;
use blockfrost_http_client::{load_key_from_file, PREPROD_NETWORK_URL};
use cardano_multiplatform_lib::address::BaseAddress;
use std::time::Duration;
use test_helpers::{
Expand All @@ -15,8 +15,6 @@ use tokio::time::sleep;

mod test_helpers;

// const MAINNET_URL: &str = "https://cardano-mainnet.blockfrost.io/api/v0";
const TEST_URL: &str = "https://cardano-testnet.blockfrost.io/api/v0/";
// Must include a TOML file at your project root with the field:
// project_id = <INSERT API KEY HERE>
const CONFIG_PATH: &str = ".blockfrost.toml";
Expand All @@ -26,10 +24,13 @@ async fn get_test_client<Datum: PlutusDataInterop, Redeemer: PlutusDataInterop>(
BaseAddress,
) {
let api_key = load_key_from_file(CONFIG_PATH).unwrap();
let ledger = BlockFrostLedger::new(TEST_URL, &api_key);
let keys = KeyManager::new(CONFIG_PATH.to_string(), TESTNET);
let ledger = BlockFrostLedger::new(PREPROD_NETWORK_URL, &api_key);
let keys = KeyManager::new(CONFIG_PATH.to_string(), Network::Preprod.into());
let base_addr = keys.base_addr().await.unwrap();
(CMLLedgerCLient::new(ledger, keys, TESTNET), base_addr)
(
CMLLedgerCLient::new(ledger, keys, Network::Preprod.into()),
base_addr,
)
}

#[ignore]
Expand Down Expand Up @@ -94,7 +95,7 @@ async fn create_datum_wait_and_then_redeem_same_datum() {
let (client, _) = get_test_client::<(), ()>().await;
let tx_id = client.issue(unbuilt_tx).await.unwrap();
println!("{:?}", &tx_id);
let script_addr = always_succeeds_script_address(TESTNET);
let script_addr = always_succeeds_script_address(Network::Preprod.into());

let mut tries = 30;
println!("Attempting to find and spend datum from {:?}", &tx_id);
Expand Down
4 changes: 2 additions & 2 deletions src/trireme_ledger_client/cml_client/tests/test_helpers.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::scripts::raw_script::PlutusScriptFile;
use crate::scripts::raw_validator_script::RawPlutusValidator;
use crate::transaction::TransactionVersion;
use crate::trireme_ledger_client::cml_client::key_manager::TESTNET;
use crate::trireme_ledger_client::Network;
use crate::{
output::{Output, UnbuiltOutput},
scripts::ValidatorCode,
Expand Down Expand Up @@ -30,7 +30,7 @@ pub fn transfer_tx(recipient: Address, amount: u64) -> UnbuiltTransaction<(), ()
}

pub fn lock_at_always_succeeds_tx(amount: u64) -> UnbuiltTransaction<(), ()> {
let script_address = always_succeeds_script_address(TESTNET);
let script_address = always_succeeds_script_address(Network::Preprod.into());
let mut values = Values::default();
values.add_one_value(&PolicyId::Lovelace, amount);
let output = UnbuiltOutput::new_validator(script_address, values, ());
Expand Down