diff --git a/integration-tests/tests/blockchain/contract_call.rs b/integration-tests/tests/blockchain/contract_call.rs index 3d2e18e..edafb9b 100644 --- a/integration-tests/tests/blockchain/contract_call.rs +++ b/integration-tests/tests/blockchain/contract_call.rs @@ -4,19 +4,17 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use dusk_wallet::{RuskHttpClient, WalletPath}; +use dusk_wallet::RuskHttpClient; use phoenix_core::transaction::ModuleId; -use std::path::PathBuf; -use toml_base_config::BaseConfig; -use zk_citadel_moat::wallet_accessor::BlockchainAccessConfig; -use zk_citadel_moat::wallet_accessor::Password::PwdHash; use zk_citadel_moat::{ Error, JsonLoader, PayloadSender, RequestJson, TxAwaiter, }; -const WALLET_PATH: &str = concat!(env!("HOME"), "/.dusk/rusk-wallet"); -const PWD_HASH: &str = - "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8"; +use zk_citadel_moat::api::MoatContext; + +const WALLET_PATH: &str = + concat!(env!("HOME"), "/.dusk/rusk-wallet/wallet.dat"); +const WALLET_PASS: &str = "password"; const GAS_LIMIT: u64 = 5_000_000_000; const GAS_PRICE: u64 = 1; @@ -35,9 +33,6 @@ async fn contract_call_with_payload() -> Result<(), Error> { let blockchain_config_path = concat!(env!("CARGO_MANIFEST_DIR"), "/config.toml"); - let blockchain_config = - BlockchainAccessConfig::load_path(blockchain_config_path)?; - let request_path = concat!( env!("CARGO_MANIFEST_DIR"), "/tests/request/test_request.json" @@ -45,24 +40,27 @@ async fn contract_call_with_payload() -> Result<(), Error> { let request_json: RequestJson = RequestJson::from_file(request_path)?; - let wallet_path = WalletPath::from( - PathBuf::from(WALLET_PATH).as_path().join("wallet.dat"), - ); + let moat_context = MoatContext::create( + blockchain_config_path, + WALLET_PATH, + WALLET_PASS, + GAS_LIMIT, + GAS_PRICE, + ) + .await?; let tx_id = PayloadSender::execute_contract_method( // any payload will do as long as the called method does not require // arguments request_json.provider_psk, - &blockchain_config, - &wallet_path, - &PwdHash(PWD_HASH.to_string()), - GAS_LIMIT, - GAS_PRICE, + &moat_context, LICENSE_CONTRACT_ID, CONTRACT_METHOD_NAME, ) .await?; - let client = RuskHttpClient::new(blockchain_config.rusk_address.clone()); + let client = RuskHttpClient::new( + moat_context.blockchain_access_config.rusk_address.clone(), + ); TxAwaiter::wait_for(&client, tx_id).await?; Ok(()) diff --git a/integration-tests/tests/citadel/int_test_user.rs b/integration-tests/tests/citadel/int_test_user.rs index 24b4e43..0cf1510 100644 --- a/integration-tests/tests/citadel/int_test_user.rs +++ b/integration-tests/tests/citadel/int_test_user.rs @@ -20,60 +20,42 @@ //! usage of the license) use dusk_bls12_381::BlsScalar; -use dusk_bytes::DeserializableSlice; -use dusk_pki::SecretSpendKey; use dusk_plonk::prelude::*; -use dusk_wallet::{RuskHttpClient, WalletPath}; +use dusk_wallet::RuskHttpClient; use rand::rngs::{OsRng, StdRng}; use rand::SeedableRng; -use std::path::PathBuf; -use toml_base_config::BaseConfig; use tracing::{info, Level}; use zk_citadel::license::Request; -use zk_citadel_moat::license_provider::{LicenseIssuer, ReferenceLP}; -use zk_citadel_moat::wallet_accessor::BlockchainAccessConfig; -use zk_citadel_moat::wallet_accessor::Password::PwdHash; +use zk_citadel_moat::license_provider::LicenseIssuer; use zk_citadel_moat::{ - BcInquirer, CitadelInquirer, CrsGetter, Error, JsonLoader, LicenseCircuit, - LicenseSessionId, LicenseUser, PayloadRetriever, RequestCreator, - RequestJson, RequestSender, TxAwaiter, + BcInquirer, CitadelInquirer, Error, LicenseSessionId, LicenseUser, + PayloadRetriever, TxAwaiter, }; -const WALLET_PATH: &str = concat!(env!("HOME"), "/.dusk/rusk-wallet"); -const PWD_HASH: &str = - "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8"; +use zk_citadel_moat::api::{MoatContext, MoatCore}; + +const WALLET_PATH: &str = + concat!(env!("HOME"), "/.dusk/rusk-wallet/wallet.dat"); +const WALLET_PASS: &str = "password"; const GAS_LIMIT: u64 = 5_000_000_000; const GAS_PRICE: u64 = 1; -static LABEL: &[u8] = b"dusk-network"; - /// Calls license contract's issue license method. /// Awaits for confirmation of the contract-calling transaction. async fn issue_license( - reference_lp: &ReferenceLP, - blockchain_config: &BlockchainAccessConfig, - wallet_path: &WalletPath, + moat_context: &MoatContext, request: &Request, rng: &mut StdRng, ) -> Result { - let license_issuer = LicenseIssuer::new( - blockchain_config.clone(), - wallet_path.clone(), - PwdHash(PWD_HASH.to_string()), - GAS_LIMIT, - GAS_PRICE, - ); - const ATTRIBUTE_DATA_EXAMPLE: u64 = 1234; - let (tx_id, _) = license_issuer - .issue_license( - rng, - &request, - &reference_lp.ssk_lp, - &JubJubScalar::from(ATTRIBUTE_DATA_EXAMPLE), - ) - .await?; + let (tx_id, _) = LicenseIssuer::issue_license( + rng, + &request, + &JubJubScalar::from(ATTRIBUTE_DATA_EXAMPLE), + &moat_context, + ) + .await?; Ok(tx_id) } @@ -131,78 +113,37 @@ async fn user_round_trip() -> Result<(), Error> { let blockchain_config_path = concat!(env!("CARGO_MANIFEST_DIR"), "/config.toml"); - let blockchain_config = - BlockchainAccessConfig::load_path(blockchain_config_path)?; - - let client = RuskHttpClient::new(blockchain_config.rusk_address.clone()); - - info!("obtaining CRS"); - let pp_vec = CrsGetter::get_crs(&client).await?; - let pp = - // SAFETY: CRS vector is checked by the hash check when it is received from the node - unsafe { PublicParameters::from_slice_unchecked(pp_vec.as_slice()) }; - - info!("compiling circuit"); - let (prover, verifier) = Compiler::compile::(&pp, LABEL) - .expect("Compiling circuit should succeed"); - - let request_path = concat!( - env!("CARGO_MANIFEST_DIR"), - "/tests/request/test_request.json" - ); - - let lp_config_path = concat!( - env!("CARGO_MANIFEST_DIR"), - "/tests/test_keys/test_keys_lp_2.json" - ); - - let reference_lp = ReferenceLP::create(&lp_config_path)?; + let moat_context = MoatContext::create( + blockchain_config_path, + WALLET_PATH, + WALLET_PASS, + GAS_LIMIT, + GAS_PRICE, + ) + .await?; - let wallet_path = WalletPath::from( - PathBuf::from(WALLET_PATH).as_path().join("wallet.dat"), + let client = RuskHttpClient::new( + moat_context.blockchain_access_config.rusk_address.clone(), ); - - // create request - let request_json: RequestJson = RequestJson::from_file(request_path)?; - let ssk_user_bytes = hex::decode(request_json.user_ssk.clone())?; - let ssk_user = SecretSpendKey::from_slice(ssk_user_bytes.as_slice())?; - - let request = RequestCreator::create_from_hex_args( - request_json.user_ssk, - request_json.provider_psk, - &mut rng, - )?; + let (psk_lp, _ssk_lp) = MoatCore::get_wallet_keypair(&moat_context)?; // as a User, submit request to blockchain info!("submitting request to blockchain (as a User)"); - let tx_id = RequestSender::send_request( - request, - &blockchain_config, - &wallet_path, - &PwdHash(PWD_HASH.to_string()), - GAS_LIMIT, - GAS_PRICE, - ) - .await?; - TxAwaiter::wait_for(&client, tx_id).await?; + let (_request_hash, request_tx_id) = + MoatCore::request_license(&psk_lp, &moat_context, &mut OsRng).await?; + TxAwaiter::wait_for(&client, request_tx_id).await?; // as a LP, retrieve request from blockchain info!("retrieving request from blockchain (as an LP)"); - let tx_id = hex::encode(tx_id.to_bytes()); + let tx_id = hex::encode(request_tx_id.to_bytes()); let request: Request = PayloadRetriever::retrieve_payload(tx_id, &client).await?; // as a LP, call issue license, wait for tx to confirm show_state(&client, "before issue_license").await?; info!("calling issue_license (as an LP)"); - let issue_license_txid = issue_license( - &reference_lp, - &blockchain_config, - &wallet_path, - &request, - &mut rng, - ) - .await?; + let issue_license_txid = + issue_license(&moat_context, &request, &mut rng).await?; show_state(&client, "after issue_license").await?; TxAwaiter::wait_for(&client, issue_license_txid).await?; let end_height = BcInquirer::block_height(&client).await?; @@ -223,8 +164,10 @@ async fn user_round_trip() -> Result<(), Error> { let mut licenses_stream = CitadelInquirer::get_licenses(&client, block_heights).await?; - let owned_licenses = - CitadelInquirer::find_owned_licenses(ssk_user, &mut licenses_stream)?; + let owned_licenses = CitadelInquirer::find_owned_licenses( + &moat_context, + &mut licenses_stream, + )?; let (pos, license) = owned_licenses.last().expect("owned license found"); // as a User, call get_merkle_opening, obtain opening @@ -241,20 +184,13 @@ async fn user_round_trip() -> Result<(), Error> { let challenge = JubJubScalar::from(num_sessions as u64 + 1); info!("proving license and calling use_license (as a user)"); let (tx_id, session_cookie) = LicenseUser::prove_and_use_license( - &blockchain_config, - &wallet_path, - &PwdHash(PWD_HASH.to_string()), - &ssk_user, - &reference_lp.psk_lp, - &reference_lp.psk_lp, - &prover, - &verifier, + &moat_context, + &psk_lp, + &psk_lp, &license, opening.expect("opening should be present"), &mut OsRng, &challenge, - GAS_LIMIT, - GAS_PRICE, ) .await?; TxAwaiter::wait_for(&client, tx_id).await?; diff --git a/integration-tests/tests/citadel/issue_license.rs b/integration-tests/tests/citadel/issue_license.rs index ba5a83c..4f0f6ed 100644 --- a/integration-tests/tests/citadel/issue_license.rs +++ b/integration-tests/tests/citadel/issue_license.rs @@ -5,73 +5,51 @@ // Copyright (c) DUSK NETWORK. All rights reserved. use dusk_jubjub::JubJubScalar; -use dusk_wallet::WalletPath; -use rand::rngs::StdRng; +use dusk_wallet::RuskHttpClient; +use rand::rngs::{OsRng, StdRng}; use rand::SeedableRng; -use std::path::PathBuf; -use toml_base_config::BaseConfig; -use zk_citadel_moat::license_provider::{LicenseIssuer, ReferenceLP}; -use zk_citadel_moat::wallet_accessor::BlockchainAccessConfig; -use zk_citadel_moat::wallet_accessor::Password::PwdHash; -use zk_citadel_moat::{Error, JsonLoader, RequestCreator, RequestJson}; +use zk_citadel::license::Request; +use zk_citadel_moat::{Error, PayloadRetriever}; -const WALLET_PATH: &str = concat!(env!("HOME"), "/.dusk/rusk-wallet"); -const PWD_HASH: &str = - "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8"; +use zk_citadel_moat::api::{MoatContext, MoatCore}; + +const WALLET_PATH: &str = + concat!(env!("HOME"), "/.dusk/rusk-wallet/wallet.dat"); +const WALLET_PASS: &str = "password"; const GAS_LIMIT: u64 = 5_000_000_000; const GAS_PRICE: u64 = 1; #[tokio::test(flavor = "multi_thread")] #[cfg_attr(not(feature = "int_tests"), ignore)] async fn issue_license() -> Result<(), Error> { - let request_path = concat!( - env!("CARGO_MANIFEST_DIR"), - "/tests/request/test_request.json" - ); let blockchain_config_path = concat!(env!("CARGO_MANIFEST_DIR"), "/config.toml"); - let lp_config_path = concat!( - env!("CARGO_MANIFEST_DIR"), - "/tests/test_keys/test_keys_lp_2.json" - ); - - let reference_lp = ReferenceLP::create(&lp_config_path)?; + let moat_context = MoatContext::create( + blockchain_config_path, + WALLET_PATH, + WALLET_PASS, + GAS_LIMIT, + GAS_PRICE, + ) + .await?; - let request_json: RequestJson = RequestJson::from_file(request_path)?; + let (psk_lp, _ssk_lp) = MoatCore::get_wallet_keypair(&moat_context)?; let rng = &mut StdRng::seed_from_u64(0xcafe); - let request = RequestCreator::create_from_hex_args( - request_json.user_ssk, - request_json.provider_psk, - rng, - )?; + let (_request_hash, request_tx_id) = + MoatCore::request_license(&psk_lp, &moat_context, &mut OsRng).await?; - let blockchain_config = - BlockchainAccessConfig::load_path(blockchain_config_path)?; + let attr_data = JubJubScalar::from(1233434334u64); - let wallet_path = WalletPath::from( - PathBuf::from(WALLET_PATH).as_path().join("wallet.dat"), + let tx_id = hex::encode(request_tx_id.to_bytes()); + let client = RuskHttpClient::new( + moat_context.blockchain_access_config.rusk_address.clone(), ); + let request: Request = + PayloadRetriever::retrieve_payload(tx_id, &client).await?; - let license_issuer = LicenseIssuer::new( - blockchain_config, - wallet_path, - PwdHash(PWD_HASH.to_string()), - GAS_LIMIT, - GAS_PRICE, - ); - - const ATTRIBUTE_DATA_EXAMPLE: u64 = 1234; - - license_issuer - .issue_license( - rng, - &request, - &reference_lp.ssk_lp, - &JubJubScalar::from(ATTRIBUTE_DATA_EXAMPLE), - ) - .await?; + MoatCore::issue_license(&request, &moat_context, &attr_data, rng).await?; Ok(()) } diff --git a/integration-tests/tests/citadel/send_request.rs b/integration-tests/tests/citadel/send_request.rs index 50d6a29..802dffd 100644 --- a/integration-tests/tests/citadel/send_request.rs +++ b/integration-tests/tests/citadel/send_request.rs @@ -4,27 +4,25 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use dusk_wallet::{RuskHttpClient, WalletPath}; +use dusk_wallet::RuskHttpClient; use rand::rngs::StdRng; use rand::SeedableRng; -use std::path::PathBuf; use std::time::Duration; use tokio::time::sleep; -use toml_base_config::BaseConfig; + use tracing::Level; use zk_citadel::license::Request; -use zk_citadel_moat::wallet_accessor::{ - BlockchainAccessConfig, Password::PwdHash, -}; use zk_citadel_moat::{ Error, PayloadExtractor, PayloadRetriever, RequestCreator, RequestJson, RequestSender, TxInquirer, MAX_REQUEST_SIZE, }; use zk_citadel_moat::{JsonLoader, TxAwaiter}; -const WALLET_PATH: &str = concat!(env!("HOME"), "/.dusk/rusk-wallet"); -const PWD_HASH: &str = - "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8"; +use zk_citadel_moat::api::MoatContext; + +const WALLET_PATH: &str = + concat!(env!("HOME"), "/.dusk/rusk-wallet/wallet.dat"); +const WALLET_PASS: &str = "password"; const GAS_LIMIT: u64 = 5_000_000_000; const GAS_PRICE: u64 = 1; @@ -55,22 +53,18 @@ async fn send_request() -> Result<(), Error> { .expect("Serializing should be infallible") .to_vec(); - let config = BlockchainAccessConfig::load_path(config_path)?; - - let wallet_path = WalletPath::from( - PathBuf::from(WALLET_PATH).as_path().join("wallet.dat"), - ); - - let tx_id = RequestSender::send_request( - request, - &config, - &wallet_path, - &PwdHash(PWD_HASH.to_string()), + let moat_context = MoatContext::create( + config_path, + WALLET_PATH, + WALLET_PASS, GAS_LIMIT, GAS_PRICE, ) .await?; - let client = RuskHttpClient::new(config.rusk_address); + + let tx_id = RequestSender::send_request(request, &moat_context).await?; + let client = + RuskHttpClient::new(moat_context.blockchain_access_config.rusk_address); TxAwaiter::wait_for(&client, tx_id).await?; let tx_id_hex = hex::encode(tx_id.to_bytes()); diff --git a/moat-cli/moat-cli-lp/src/args.rs b/moat-cli/moat-cli-lp/src/args.rs index 38a01aa..7ca19d0 100644 --- a/moat-cli/moat-cli-lp/src/args.rs +++ b/moat-cli/moat-cli-lp/src/args.rs @@ -4,8 +4,6 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use std::path::PathBuf; - use clap::Parser; #[derive(Parser, Debug)] @@ -13,12 +11,12 @@ use clap::Parser; #[command(propagate_version = true)] pub struct Args { /// Wallet directory [default: `$HOME/.dusk/rusk-wallet`] - #[clap(short, long, default_value = concat!(env!("HOME"), "/.dusk/rusk-wallet"))] - pub wallet_path: PathBuf, + #[clap(short, long, default_value = concat!(env!("HOME"), "/.dusk/rusk-wallet/wallet.dat"))] + pub wallet_path: String, /// Blockchain access config directory - #[clap(short, long, default_value = "moat-cli/config.toml")] - pub config_path: PathBuf, + #[clap(short, long, default_value = concat!(env!("CARGO_MANIFEST_DIR"), "/../config.toml"))] + pub config_path: String, /// Password for the wallet #[clap(long, default_value_t = String::from(""), env = "RUSK_WALLET_PWD")] diff --git a/moat-cli/moat-cli-lp/src/command.rs b/moat-cli/moat-cli-lp/src/command.rs index 0cfce28..063ed9e 100644 --- a/moat-cli/moat-cli-lp/src/command.rs +++ b/moat-cli/moat-cli-lp/src/command.rs @@ -9,12 +9,11 @@ use crate::run_result::{ }; use crate::SeedableRng; use dusk_jubjub::JubJubScalar; -use dusk_pki::SecretSpendKey; -use dusk_wallet::{RuskHttpClient, WalletPath}; +use dusk_wallet::RuskHttpClient; use moat_cli_common::Error; use rand::rngs::StdRng; +use zk_citadel_moat::api::{MoatContext, MoatCore}; use zk_citadel_moat::license_provider::{LicenseIssuer, ReferenceLP}; -use zk_citadel_moat::wallet_accessor::{BlockchainAccessConfig, Password}; use zk_citadel_moat::{BcInquirer, CitadelInquirer}; /// Commands that can be run against the Moat @@ -37,51 +36,38 @@ impl Command { #[allow(clippy::too_many_arguments)] pub async fn run( self, - wallet_path: &WalletPath, - psw: &Password, - blockchain_access_config: &BlockchainAccessConfig, - ssk: &SecretSpendKey, - gas_limit: u64, - gas_price: u64, + moat_context: &MoatContext, ) -> Result { let run_result = match self { Command::ListRequestsLP => { - Self::list_requests_lp(blockchain_access_config, ssk).await? + Self::list_requests_lp(moat_context).await? } Command::IssueLicenseLP { request_hash, attr_data_bytes, } => { Self::issue_license_lp( - wallet_path, - psw, - blockchain_access_config, - ssk, - gas_limit, - gas_price, + moat_context, request_hash, attr_data_bytes, ) .await? } - Command::ListLicenses => { - Self::list_licenses(blockchain_access_config).await? - } - Command::ShowState => { - Self::show_state(blockchain_access_config).await? - } + Command::ListLicenses => Self::list_licenses(moat_context).await?, + Command::ShowState => Self::show_state(moat_context).await?, }; Ok(run_result) } /// Command: List Requests LP async fn list_requests_lp( - blockchain_access_config: &BlockchainAccessConfig, - ssk: &SecretSpendKey, + moat_context: &MoatContext, ) -> Result { - let mut reference_lp = ReferenceLP::create_with_ssk(ssk)?; - let (found_total, found_owned) = - reference_lp.scan(blockchain_access_config).await?; + let (_psk, ssk) = MoatCore::get_wallet_keypair(moat_context)?; + let mut reference_lp = ReferenceLP::create_with_ssk(&ssk)?; + let (found_total, found_owned) = reference_lp + .scan(&moat_context.blockchain_access_config) + .await?; let summary = RequestsLPSummary { found_total, found_owned, @@ -95,40 +81,29 @@ impl Command { #[allow(clippy::too_many_arguments)] /// Command: Issue License LP async fn issue_license_lp( - wallet_path: &WalletPath, - psw: &Password, - blockchain_access_config: &BlockchainAccessConfig, - ssk: &SecretSpendKey, - gas_limit: u64, - gas_price: u64, + moat_context: &MoatContext, request_hash: String, attr_data_bytes: String, ) -> Result { let attr_data = JubJubScalar::from(attr_data_bytes.parse::()?); let mut rng = StdRng::from_entropy(); - let mut reference_lp = ReferenceLP::create_with_ssk(ssk)?; - let (_total_count, _this_lp_count) = - reference_lp.scan(blockchain_access_config).await?; + let (_psk, ssk) = MoatCore::get_wallet_keypair(moat_context)?; + let mut reference_lp = ReferenceLP::create_with_ssk(&ssk)?; + let (_total_count, _this_lp_count) = reference_lp + .scan(&moat_context.blockchain_access_config) + .await?; let request = reference_lp.get_request(&request_hash); Ok(match request { Some(request) => { - let license_issuer = LicenseIssuer::new( - blockchain_access_config.clone(), - wallet_path.clone(), - psw.clone(), - gas_limit, - gas_price, - ); - let (tx_id, license_blob) = license_issuer - .issue_license( - &mut rng, - &request, - &reference_lp.ssk_lp, - &attr_data, - ) - .await?; + let (tx_id, license_blob) = LicenseIssuer::issue_license( + &mut rng, + &request, + &attr_data, + moat_context, + ) + .await?; let summary = IssueLicenseSummary { request, tx_id: hex::encode(tx_id.to_bytes()), @@ -142,10 +117,11 @@ impl Command { /// Command: List Licenses async fn list_licenses( - blockchain_access_config: &BlockchainAccessConfig, + moat_context: &MoatContext, ) -> Result { - let client = - RuskHttpClient::new(blockchain_access_config.rusk_address.clone()); + let client = RuskHttpClient::new( + moat_context.blockchain_access_config.rusk_address.clone(), + ); let end_height = BcInquirer::block_height(&client).await?; let block_range = 0..(end_height + 1); @@ -161,10 +137,11 @@ impl Command { /// Command: Show State async fn show_state( - blockchain_access_config: &BlockchainAccessConfig, + moat_context: &MoatContext, ) -> Result { - let client = - RuskHttpClient::new(blockchain_access_config.rusk_address.clone()); + let client = RuskHttpClient::new( + moat_context.blockchain_access_config.rusk_address.clone(), + ); let (num_licenses, _, num_sessions) = CitadelInquirer::get_info(&client).await?; let summary = LicenseContractSummary { diff --git a/moat-cli/moat-cli-lp/src/interactor.rs b/moat-cli/moat-cli-lp/src/interactor.rs index a5eaed7..4a0f12a 100644 --- a/moat-cli/moat-cli-lp/src/interactor.rs +++ b/moat-cli/moat-cli-lp/src/interactor.rs @@ -6,11 +6,9 @@ use crate::prompt; use crate::{Command, Menu}; -use dusk_pki::SecretSpendKey; -use dusk_wallet::WalletPath; use moat_cli_common::Error; use requestty::{ErrorKind, Question}; -use zk_citadel_moat::wallet_accessor::{BlockchainAccessConfig, Password}; +use zk_citadel_moat::api::MoatContext; #[derive(PartialEq, Eq, Hash, Debug, Clone)] enum OpSelection { @@ -64,12 +62,7 @@ fn menu_operation() -> Result { } pub struct Interactor { - pub wallet_path: WalletPath, - pub psw: Password, - pub blockchain_access_config: BlockchainAccessConfig, - pub ssk: SecretSpendKey, - pub gas_limit: u64, - pub gas_price: u64, + pub moat_context: MoatContext, } impl Interactor { @@ -79,16 +72,7 @@ impl Interactor { match op { OpSelection::Exit => return Ok(()), OpSelection::Run(command) => { - let result = command - .run( - &self.wallet_path, - &self.psw, - &self.blockchain_access_config, - &self.ssk, - self.gas_limit, - self.gas_price, - ) - .await; + let result = command.run(&self.moat_context).await; match result { Ok(run_result) => { println!("{}", run_result); diff --git a/moat-cli/moat-cli-lp/src/main.rs b/moat-cli/moat-cli-lp/src/main.rs index 6c15fae..154c86a 100644 --- a/moat-cli/moat-cli-lp/src/main.rs +++ b/moat-cli/moat-cli-lp/src/main.rs @@ -17,62 +17,35 @@ mod run_result; use crate::args::Args; use crate::command::Command; use crate::menu::Menu; -use std::fs; use clap::Parser; -use crate::config::LPCliConfig; use crate::interactor::Interactor; -use dusk_wallet::{Wallet, WalletPath}; use moat_cli_common::Error; use rand::SeedableRng; -use toml_base_config::BaseConfig; -use zk_citadel_moat::wallet_accessor::Password::{Pwd, PwdHash}; -use zk_citadel_moat::wallet_accessor::{ - BlockchainAccessConfig, WalletAccessor, -}; + +use zk_citadel_moat::api::MoatContext; #[tokio::main] async fn main() -> Result<(), Error> { let cli = Args::parse(); - let config_path = cli.config_path.as_path(); - let wallet_path = cli.wallet_path.as_path(); + let config_path = cli.config_path; + let wallet_path = cli.wallet_path; let password = cli.wallet_pass; - let pwd_hash = cli.pwd_hash; let gas_limit = cli.gas_limit; let gas_price = cli.gas_price; - let _ = fs::metadata(config_path).map_err(|_| { - Error::NotFound(config_path.to_string_lossy().into_owned().into()) - })?; - let config = LPCliConfig::load_path(config_path)?; - let blockchain_access_config = BlockchainAccessConfig { - rusk_address: config.rusk_address.clone(), - prover_address: config.prover_address.clone(), - }; - - let wallet_path = WalletPath::from(wallet_path.join("wallet.dat")); - let psw = if pwd_hash.is_empty() { - Pwd(password) - } else { - PwdHash(pwd_hash) - }; - - let wallet_accessor = - WalletAccessor::create(wallet_path.clone(), psw.clone())?; - let wallet = Wallet::from_file(wallet_accessor)?; - - let (_psk, ssk) = wallet.spending_keys(wallet.default_address())?; - - let mut interactor = Interactor { + let moat_context = MoatContext::create( + config_path, wallet_path, - psw, - blockchain_access_config, - ssk, + password, gas_limit, gas_price, - }; + ) + .await?; + + let mut interactor = Interactor { moat_context }; interactor.run_loop().await?; diff --git a/moat-cli/moat-cli-sp/src/args.rs b/moat-cli/moat-cli-sp/src/args.rs index 38a01aa..7ca19d0 100644 --- a/moat-cli/moat-cli-sp/src/args.rs +++ b/moat-cli/moat-cli-sp/src/args.rs @@ -4,8 +4,6 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use std::path::PathBuf; - use clap::Parser; #[derive(Parser, Debug)] @@ -13,12 +11,12 @@ use clap::Parser; #[command(propagate_version = true)] pub struct Args { /// Wallet directory [default: `$HOME/.dusk/rusk-wallet`] - #[clap(short, long, default_value = concat!(env!("HOME"), "/.dusk/rusk-wallet"))] - pub wallet_path: PathBuf, + #[clap(short, long, default_value = concat!(env!("HOME"), "/.dusk/rusk-wallet/wallet.dat"))] + pub wallet_path: String, /// Blockchain access config directory - #[clap(short, long, default_value = "moat-cli/config.toml")] - pub config_path: PathBuf, + #[clap(short, long, default_value = concat!(env!("CARGO_MANIFEST_DIR"), "/../config.toml"))] + pub config_path: String, /// Password for the wallet #[clap(long, default_value_t = String::from(""), env = "RUSK_WALLET_PWD")] diff --git a/moat-cli/moat-cli-sp/src/command.rs b/moat-cli/moat-cli-sp/src/command.rs index 0900440..6bd3124 100644 --- a/moat-cli/moat-cli-sp/src/command.rs +++ b/moat-cli/moat-cli-sp/src/command.rs @@ -14,7 +14,7 @@ use dusk_jubjub::JubJubAffine; use dusk_pki::PublicSpendKey; use dusk_wallet::RuskHttpClient; use zk_citadel::license::{Session, SessionCookie}; -use zk_citadel_moat::wallet_accessor::BlockchainAccessConfig; +use zk_citadel_moat::api::{MoatContext, MoatCore}; use zk_citadel_moat::{CitadelInquirer, LicenseSessionId}; /// Commands that can be run against the Moat @@ -35,8 +35,7 @@ impl Command { #[allow(clippy::too_many_arguments)] pub async fn run( self, - blockchain_access_config: &BlockchainAccessConfig, - psk_sp: PublicSpendKey, + moat_context: &MoatContext, ) -> Result { let run_result = match self { Command::VerifyRequestedService { @@ -44,32 +43,29 @@ impl Command { psk_lp_bytes, } => { Self::verify_requested_service( - blockchain_access_config, + moat_context, &session_cookie, &psk_lp_bytes, - &psk_sp, ) .await? } Command::GetSession { session_id } => { - Self::get_session(blockchain_access_config, session_id).await? - } - Command::ShowState => { - Self::show_state(blockchain_access_config).await? + Self::get_session(moat_context, session_id).await? } + Command::ShowState => Self::show_state(moat_context).await?, }; Ok(run_result) } /// Command: Request Service async fn verify_requested_service( - blockchain_access_config: &BlockchainAccessConfig, + moat_context: &MoatContext, session_cookie: &str, psk_lp_bytes: &str, - psk_sp: &PublicSpendKey, ) -> Result { - let client = - RuskHttpClient::new(blockchain_access_config.rusk_address.clone()); + let client = RuskHttpClient::new( + moat_context.blockchain_access_config.rusk_address.clone(), + ); let bytes = hex::decode(session_cookie) .map_err(|_| Error::InvalidEntry("session cookie".into()))?; @@ -81,6 +77,8 @@ impl Command { let psk_lp = PublicSpendKey::from_slice(psk_lp_bytes_formatted.as_slice())?; let pk_lp = JubJubAffine::from(*psk_lp.A()); + + let (psk_sp, _ssk_sp) = MoatCore::get_wallet_keypair(moat_context)?; let pk_sp = JubJubAffine::from(*psk_sp.A()); let session_id = LicenseSessionId { id: sc.session_id }; @@ -98,11 +96,12 @@ impl Command { /// Command: Get Session async fn get_session( - blockchain_access_config: &BlockchainAccessConfig, + moat_context: &MoatContext, session_id: String, ) -> Result { - let client = - RuskHttpClient::new(blockchain_access_config.rusk_address.clone()); + let client = RuskHttpClient::new( + moat_context.blockchain_access_config.rusk_address.clone(), + ); let session_id_bytes = hex::decode(session_id.clone()) .map_err(|_| Error::InvalidEntry("session id".into()))?; let id = LicenseSessionId { @@ -126,10 +125,11 @@ impl Command { /// Command: Show State async fn show_state( - blockchain_access_config: &BlockchainAccessConfig, + moat_context: &MoatContext, ) -> Result { - let client = - RuskHttpClient::new(blockchain_access_config.rusk_address.clone()); + let client = RuskHttpClient::new( + moat_context.blockchain_access_config.rusk_address.clone(), + ); let (num_licenses, _, num_sessions) = CitadelInquirer::get_info(&client).await?; let summary = LicenseContractSummary { diff --git a/moat-cli/moat-cli-sp/src/interactor.rs b/moat-cli/moat-cli-sp/src/interactor.rs index b5ab6c6..ef6d52c 100644 --- a/moat-cli/moat-cli-sp/src/interactor.rs +++ b/moat-cli/moat-cli-sp/src/interactor.rs @@ -4,14 +4,11 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use crate::config::SPCliConfig; use crate::prompt; use crate::{Command, Menu}; -use dusk_pki::PublicSpendKey; -use dusk_wallet::WalletPath; use moat_cli_common::Error; use requestty::{ErrorKind, Question}; -use zk_citadel_moat::wallet_accessor::{BlockchainAccessConfig, Password}; +use zk_citadel_moat::api::MoatContext; #[derive(PartialEq, Eq, Hash, Debug, Clone)] enum OpSelection { @@ -65,13 +62,7 @@ fn menu_operation() -> Result { } pub struct Interactor { - pub wallet_path: WalletPath, - pub psw: Password, - pub blockchain_access_config: BlockchainAccessConfig, - pub config: SPCliConfig, - pub gas_limit: u64, - pub gas_price: u64, - pub psk_sp: PublicSpendKey, + pub moat_context: MoatContext, } impl Interactor { @@ -81,9 +72,7 @@ impl Interactor { match op { OpSelection::Exit => return Ok(()), OpSelection::Run(command) => { - let result = command - .run(&self.blockchain_access_config, self.psk_sp) - .await; + let result = command.run(&self.moat_context).await; match result { Ok(run_result) => { println!("{}", run_result); diff --git a/moat-cli/moat-cli-sp/src/main.rs b/moat-cli/moat-cli-sp/src/main.rs index 75fdcd5..7c0d096 100644 --- a/moat-cli/moat-cli-sp/src/main.rs +++ b/moat-cli/moat-cli-sp/src/main.rs @@ -20,53 +20,30 @@ use crate::menu::Menu; use clap::Parser; -use crate::config::SPCliConfig; use crate::interactor::Interactor; -use dusk_wallet::{Wallet, WalletPath}; use moat_cli_common::Error; -use toml_base_config::BaseConfig; -use zk_citadel_moat::wallet_accessor::Password::{Pwd, PwdHash}; -use zk_citadel_moat::wallet_accessor::{ - BlockchainAccessConfig, WalletAccessor, -}; +use zk_citadel_moat::api::MoatContext; #[tokio::main] async fn main() -> Result<(), Error> { let cli = Args::parse(); - let config_path = cli.config_path.as_path(); - let wallet_path = cli.wallet_path.as_path(); + let config_path = cli.config_path; + let wallet_path = cli.wallet_path; let password = cli.wallet_pass; - let pwd_hash = cli.pwd_hash; let gas_limit = cli.gas_limit; let gas_price = cli.gas_price; - let config = SPCliConfig::load_path(config_path)?; - let blockchain_access_config = - BlockchainAccessConfig::load_path(config_path)?; - - let wallet_path = WalletPath::from(wallet_path.join("wallet.dat")); - let psw = if pwd_hash.is_empty() { - Pwd(password) - } else { - PwdHash(pwd_hash) - }; - - let wallet_accessor = - WalletAccessor::create(wallet_path.clone(), psw.clone())?; - let wallet = Wallet::from_file(wallet_accessor)?; - - let (psk_sp, _ssk_sp) = wallet.spending_keys(wallet.default_address())?; - - let mut interactor = Interactor { + let moat_context = MoatContext::create( + config_path, wallet_path, - psw, - blockchain_access_config, - config, + password, gas_limit, gas_price, - psk_sp, - }; + ) + .await?; + + let mut interactor = Interactor { moat_context }; interactor.run_loop().await?; diff --git a/moat-cli/moat-cli-user/src/args.rs b/moat-cli/moat-cli-user/src/args.rs index 38a01aa..7ca19d0 100644 --- a/moat-cli/moat-cli-user/src/args.rs +++ b/moat-cli/moat-cli-user/src/args.rs @@ -4,8 +4,6 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use std::path::PathBuf; - use clap::Parser; #[derive(Parser, Debug)] @@ -13,12 +11,12 @@ use clap::Parser; #[command(propagate_version = true)] pub struct Args { /// Wallet directory [default: `$HOME/.dusk/rusk-wallet`] - #[clap(short, long, default_value = concat!(env!("HOME"), "/.dusk/rusk-wallet"))] - pub wallet_path: PathBuf, + #[clap(short, long, default_value = concat!(env!("HOME"), "/.dusk/rusk-wallet/wallet.dat"))] + pub wallet_path: String, /// Blockchain access config directory - #[clap(short, long, default_value = "moat-cli/config.toml")] - pub config_path: PathBuf, + #[clap(short, long, default_value = concat!(env!("CARGO_MANIFEST_DIR"), "/../config.toml"))] + pub config_path: String, /// Password for the wallet #[clap(long, default_value_t = String::from(""), env = "RUSK_WALLET_PWD")] diff --git a/moat-cli/moat-cli-user/src/command.rs b/moat-cli/moat-cli-user/src/command.rs index e72378a..f6ac5f6 100644 --- a/moat-cli/moat-cli-user/src/command.rs +++ b/moat-cli/moat-cli-user/src/command.rs @@ -4,27 +4,24 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use crate::interactor::SetupHolder; use crate::run_result::{ LicenseContractSummary, RunResult, SubmitRequestSummary, UseLicenseSummary, }; use crate::SeedableRng; use dusk_bls12_381::BlsScalar; use dusk_bytes::DeserializableSlice; -use dusk_pki::{PublicSpendKey, SecretSpendKey}; +use dusk_pki::PublicSpendKey; use dusk_plonk::prelude::*; -use dusk_wallet::{RuskHttpClient, WalletPath}; +use dusk_wallet::RuskHttpClient; use moat_cli_common::Error; use rand::rngs::{OsRng, StdRng}; use zk_citadel::license::{License, SessionCookie}; -use zk_citadel_moat::wallet_accessor::{BlockchainAccessConfig, Password}; use zk_citadel_moat::{ - BcInquirer, CitadelInquirer, CrsGetter, LicenseCircuit, LicenseUser, - MoatCoreUtils, RequestCreator, RequestSender, TxAwaiter, + BcInquirer, CitadelInquirer, LicenseUser, MoatCoreUtils, RequestCreator, + RequestSender, TxAwaiter, }; -use std::fs::File; -use std::io::prelude::*; +use zk_citadel_moat::api::{MoatContext, MoatCore}; /// Commands that can be run against the Moat #[derive(PartialEq, Eq, Hash, Clone, Debug)] @@ -46,36 +43,17 @@ pub(crate) enum Command { ShowState, } -static LABEL: &[u8] = b"dusk-network"; - impl Command { #[allow(clippy::too_many_arguments)] pub async fn run( self, - wallet_path: &WalletPath, - psw: &Password, - blockchain_access_config: &BlockchainAccessConfig, - gas_limit: u64, - gas_price: u64, - ssk: SecretSpendKey, - setup_holder: &mut Option, + moat_context: &MoatContext, ) -> Result { let run_result = match self { Command::SubmitRequest { psk_lp_bytes } => { - Self::submit_request( - wallet_path, - psw, - blockchain_access_config, - gas_limit, - gas_price, - ssk, - psk_lp_bytes, - ) - .await? - } - Command::ListLicenses => { - Self::list_licenses(blockchain_access_config, ssk).await? + Self::submit_request(moat_context, psk_lp_bytes).await? } + Command::ListLicenses => Self::list_licenses(moat_context).await?, Command::UseLicense { license_hash, psk_lp_bytes, @@ -83,16 +61,10 @@ impl Command { challenge_bytes, } => { Self::use_license( - wallet_path, - psw, - blockchain_access_config, - gas_limit, - gas_price, + moat_context, psk_lp_bytes, psk_sp_bytes, - ssk, challenge_bytes, - setup_holder, license_hash, ) .await? @@ -101,9 +73,7 @@ impl Command { println!("Off-chain request service to be placed here"); RunResult::Empty } - Command::ShowState => { - Self::show_state(blockchain_access_config).await? - } + Command::ShowState => Self::show_state(moat_context).await?, }; Ok(run_result) } @@ -111,12 +81,7 @@ impl Command { /// Command: Submit Request #[allow(non_snake_case)] async fn submit_request>( - wallet_path: &WalletPath, - psw: &Password, - blockchain_access_config: &BlockchainAccessConfig, - gas_limit: u64, - gas_price: u64, - ssk: SecretSpendKey, + moat_context: &MoatContext, psk_lp_bytes: T, ) -> Result { let psk_lp_bytes_formatted = @@ -125,19 +90,13 @@ impl Command { PublicSpendKey::from_slice(psk_lp_bytes_formatted.as_slice())?; let rng = &mut StdRng::from_entropy(); + let (_psk, ssk) = MoatCore::get_wallet_keypair(moat_context)?; let request = RequestCreator::create(&ssk, &psk_lp, rng)?; let request_hash = MoatCoreUtils::to_hash_hex(&request); - let tx_id = RequestSender::send_request( - request, - blockchain_access_config, - wallet_path, - psw, - gas_limit, - gas_price, - ) - .await?; - let client = - RuskHttpClient::new(blockchain_access_config.rusk_address.clone()); + let tx_id = RequestSender::send_request(request, moat_context).await?; + let client = RuskHttpClient::new( + moat_context.blockchain_access_config.rusk_address.clone(), + ); TxAwaiter::wait_for(&client, tx_id).await?; let summary = SubmitRequestSummary { @@ -150,18 +109,18 @@ impl Command { /// Command: List Licenses async fn list_licenses( - blockchain_access_config: &BlockchainAccessConfig, - ssk: SecretSpendKey, + moat_context: &MoatContext, ) -> Result { - let client = - RuskHttpClient::new(blockchain_access_config.rusk_address.clone()); + let client = RuskHttpClient::new( + moat_context.blockchain_access_config.rusk_address.clone(), + ); let end_height = BcInquirer::block_height(&client).await?; let block_range = 0..(end_height + 1); let mut licenses_stream = CitadelInquirer::get_licenses(&client, block_range.clone()).await?; - let ssk_user = ssk; + let (_psk_user, ssk_user) = MoatCore::get_wallet_keypair(moat_context)?; let pairs = CitadelInquirer::find_all_licenses(&mut licenses_stream)?; let vk = ssk_user.view_key(); @@ -177,24 +136,15 @@ impl Command { #[allow(non_snake_case)] /// Command: Use License async fn use_license( - wallet_path: &WalletPath, - psw: &Password, - blockchain_access_config: &BlockchainAccessConfig, - gas_limit: u64, - gas_price: u64, + moat_context: &MoatContext, psk_lp_bytes: String, psk_sp_bytes: String, - ssk: SecretSpendKey, challenge_bytes: String, - setup_holder: &mut Option, license_hash: String, ) -> Result { - let pos_license = Self::get_license_to_use( - blockchain_access_config, - ssk, - license_hash.clone(), - ) - .await?; + let pos_license = + Self::get_license_to_use(moat_context, license_hash.clone()) + .await?; Ok(match pos_license { Some((pos, license)) => { println!( @@ -213,18 +163,12 @@ impl Command { PublicSpendKey::from_slice(psk_sp_bytes.as_slice())?; let (tx_id, session_cookie) = Self::prove_and_send_use_license( - blockchain_access_config, - wallet_path, - psw, + moat_context, psk_lp, psk_sp, - ssk, challenge, &license, pos, - gas_limit, - gas_price, - setup_holder, ) .await?; let summary = UseLicenseSummary { @@ -244,10 +188,11 @@ impl Command { /// Command: Show State async fn show_state( - blockchain_access_config: &BlockchainAccessConfig, + moat_context: &MoatContext, ) -> Result { - let client = - RuskHttpClient::new(blockchain_access_config.rusk_address.clone()); + let client = RuskHttpClient::new( + moat_context.blockchain_access_config.rusk_address.clone(), + ); let (num_licenses, _, num_sessions) = CitadelInquirer::get_info(&client).await?; let summary = LicenseContractSummary { @@ -258,20 +203,22 @@ impl Command { } async fn get_license_to_use( - blockchain_access_config: &BlockchainAccessConfig, - ssk: SecretSpendKey, + moat_context: &MoatContext, license_hash: String, ) -> Result, Error> { - let client = - RuskHttpClient::new(blockchain_access_config.rusk_address.clone()); + let client = RuskHttpClient::new( + moat_context.blockchain_access_config.rusk_address.clone(), + ); let end_height = BcInquirer::block_height(&client).await?; let block_heights = 0..(end_height + 1); let mut licenses_stream = CitadelInquirer::get_licenses(&client, block_heights).await?; - let pairs = - CitadelInquirer::find_owned_licenses(ssk, &mut licenses_stream)?; + let pairs = CitadelInquirer::find_owned_licenses( + moat_context, + &mut licenses_stream, + )?; Ok(if pairs.is_empty() { None } else { @@ -286,73 +233,19 @@ impl Command { #[allow(clippy::too_many_arguments)] async fn prove_and_send_use_license( - blockchain_access_config: &BlockchainAccessConfig, - wallet_path: &WalletPath, - psw: &Password, + moat_context: &MoatContext, psk_lp: PublicSpendKey, psk_sp: PublicSpendKey, - ssk_user: SecretSpendKey, challenge: JubJubScalar, license: &License, pos: u64, - gas_limit: u64, - gas_price: u64, - sh_opt: &mut Option, ) -> Result<(BlsScalar, SessionCookie), Error> { - let client = - RuskHttpClient::new(blockchain_access_config.rusk_address.clone()); + let client = RuskHttpClient::new( + moat_context.blockchain_access_config.rusk_address.clone(), + ); // let (_, _, num_sessions) = CitadelInquirer::get_info(&client).await?; // let challenge = JubJubScalar::from(num_sessions as u64 + 1); - let setup_holder = match sh_opt { - Some(sh) => sh, - _ => { - let wallet_dir_path = match wallet_path.dir() { - Some(path) => path, - None => panic!(), - }; - - let prover_path = &wallet_dir_path.join("moat_prover.dat"); - let verifier_path = &wallet_dir_path.join("moat_verifier.dat"); - - if prover_path.exists() && verifier_path.exists() { - let mut file = File::open(prover_path)?; - let mut prover_bytes = vec![]; - file.read_to_end(&mut prover_bytes)?; - let prover = Prover::try_from_bytes(prover_bytes)?; - - file = File::open(verifier_path)?; - let mut verifier_bytes = vec![]; - file.read_to_end(&mut verifier_bytes)?; - let verifier = Verifier::try_from_bytes(verifier_bytes)?; - - let sh = SetupHolder { prover, verifier }; - *sh_opt = Some(sh); - sh_opt.as_ref().expect("setup holder is not empty") - } else { - println!("obtaining setup"); - let pp_vec = CrsGetter::get_crs(&client).await?; - let pp = - // SAFETY: CRS vector is checked by the hash check when it is received from the node - unsafe { PublicParameters::from_slice_unchecked(pp_vec.as_slice()) }; - println!("compiling circuit"); - let (prover, verifier) = - Compiler::compile::(&pp, LABEL) - .expect("Compiling circuit should succeed"); - - let mut file = File::create(prover_path)?; - file.write_all(prover.to_bytes().as_slice())?; - - file = File::create(verifier_path)?; - file.write_all(verifier.to_bytes().as_slice())?; - - let sh = SetupHolder { prover, verifier }; - *sh_opt = Some(sh); - sh_opt.as_ref().expect("setup holder is not empty") - } - } - }; - let opening = CitadelInquirer::get_merkle_opening(&client, pos) .await? .expect("Opening obtained successfully"); @@ -361,20 +254,13 @@ impl Command { "calculating proof and calling license contract's use_license" ); let (tx_id, session_cookie) = LicenseUser::prove_and_use_license( - blockchain_access_config, - wallet_path, - psw, - &ssk_user, + moat_context, &psk_lp, &psk_sp, - &setup_holder.prover, - &setup_holder.verifier, license, opening, &mut OsRng, &challenge, - gas_limit, - gas_price, ) .await?; TxAwaiter::wait_for(&client, tx_id).await?; diff --git a/moat-cli/moat-cli-user/src/interactor.rs b/moat-cli/moat-cli-user/src/interactor.rs index f8cc614..86a3a84 100644 --- a/moat-cli/moat-cli-user/src/interactor.rs +++ b/moat-cli/moat-cli-user/src/interactor.rs @@ -6,12 +6,9 @@ use crate::prompt; use crate::{Command, Menu}; -use dusk_pki::SecretSpendKey; -use dusk_plonk::prelude::{Prover, Verifier}; -use dusk_wallet::WalletPath; use moat_cli_common::Error; use requestty::{ErrorKind, Question}; -use zk_citadel_moat::wallet_accessor::{BlockchainAccessConfig, Password}; +use zk_citadel_moat::api::MoatContext; #[derive(PartialEq, Eq, Hash, Debug, Clone)] enum OpSelection { @@ -78,19 +75,8 @@ fn menu_operation() -> Result { }) } -pub struct SetupHolder { - pub prover: Prover, - pub verifier: Verifier, -} - pub struct Interactor { - pub wallet_path: WalletPath, - pub psw: Password, - pub blockchain_access_config: BlockchainAccessConfig, - pub gas_limit: u64, - pub gas_price: u64, - pub ssk: SecretSpendKey, - pub setup_holder: Option, + pub moat_context: MoatContext, } impl Interactor { @@ -100,17 +86,7 @@ impl Interactor { match op { OpSelection::Exit => return Ok(()), OpSelection::Run(command) => { - let result = command - .run( - &self.wallet_path, - &self.psw, - &self.blockchain_access_config, - self.gas_limit, - self.gas_price, - self.ssk, - &mut self.setup_holder, - ) - .await; + let result = command.run(&self.moat_context).await; match result { Ok(run_result) => { println!("{}", run_result); diff --git a/moat-cli/moat-cli-user/src/main.rs b/moat-cli/moat-cli-user/src/main.rs index d784c0b..e157952 100644 --- a/moat-cli/moat-cli-user/src/main.rs +++ b/moat-cli/moat-cli-user/src/main.rs @@ -16,59 +16,36 @@ mod run_result; use crate::args::Args; use crate::command::Command; use crate::menu::Menu; -use std::fs; use clap::Parser; use crate::interactor::Interactor; -use dusk_wallet::{Wallet, WalletPath}; use moat_cli_common::Error; use rand::SeedableRng; -use toml_base_config::BaseConfig; -use zk_citadel_moat::wallet_accessor::Password::{Pwd, PwdHash}; -use zk_citadel_moat::wallet_accessor::{ - BlockchainAccessConfig, WalletAccessor, -}; + +use zk_citadel_moat::api::MoatContext; #[tokio::main] #[allow(non_snake_case)] async fn main() -> Result<(), Error> { let cli = Args::parse(); - let config_path = cli.config_path.as_path(); - let wallet_path = cli.wallet_path.as_path(); + let config_path = cli.config_path; + let wallet_path = cli.wallet_path; let password = cli.wallet_pass; - let pwd_hash = cli.pwd_hash; let gas_limit = cli.gas_limit; let gas_price = cli.gas_price; - let wallet_path = WalletPath::from(wallet_path.join("wallet.dat")); - let _ = fs::metadata(config_path).map_err(|_| { - Error::NotFound(config_path.to_string_lossy().into_owned().into()) - })?; - let blockchain_access_config = - BlockchainAccessConfig::load_path(config_path)?; - let psw = if pwd_hash.is_empty() { - Pwd(password) - } else { - PwdHash(pwd_hash) - }; - - let wallet_accessor = - WalletAccessor::create(wallet_path.clone(), psw.clone())?; - let wallet = Wallet::from_file(wallet_accessor)?; - - let (_psk, ssk) = wallet.spending_keys(wallet.default_address())?; - - let mut interactor = Interactor { + let moat_context = MoatContext::create( + config_path, wallet_path, - psw, - blockchain_access_config, + password, gas_limit, gas_price, - ssk, - setup_holder: None, - }; + ) + .await?; + + let mut interactor = Interactor { moat_context }; interactor.run_loop().await?; diff --git a/moat-example/src/main.rs b/moat-example/src/main.rs index e95b175..e9cf212 100644 --- a/moat-example/src/main.rs +++ b/moat-example/src/main.rs @@ -30,20 +30,16 @@ async fn main() -> Result<(), Error> { wallet_password, gas_limit, gas_price, - )?; + ) + .await?; // Retrieve the keypair from the installed wallet let (psk_user, ssk_user) = MoatCore::get_wallet_keypair(&moat_context)?; // Submit a request to the Blockchain let psk_lp = psk_user; // we specify the same key just for testing - let request_hash = MoatCore::request_license( - &ssk_user, - &psk_lp, - &moat_context, - &mut OsRng, - ) - .await?; + let request_hash = + MoatCore::request_license(&psk_lp, &moat_context, &mut OsRng).await?; println!("Request transacted: {:?}", request_hash); // Get owned requests @@ -55,7 +51,6 @@ async fn main() -> Result<(), Error> { let rng = &mut OsRng; let license_hash = MoatCore::issue_license( requests.get(0).expect("A request was owned."), - &ssk_lp, &moat_context, &attr_data, rng, @@ -74,7 +69,6 @@ async fn main() -> Result<(), Error> { &moat_context, &psk_lp, &psk_sp, - &ssk_user, &challenge, licenses.get(0).expect("A license was owned."), rng, diff --git a/moat/Cargo.toml b/moat/Cargo.toml index c0ab846..c54c8c5 100644 --- a/moat/Cargo.toml +++ b/moat/Cargo.toml @@ -37,6 +37,7 @@ gql_client = "1" base64 = "0.21" hex = "0.4" rand = "0.8" +rand_core = {version="0.6", default-features=false} dusk-bytes = "0.1" blake3 = "1.4" tracing = "0.1" diff --git a/moat/src/api.rs b/moat/src/api.rs index de62612..3d4a2d0 100644 --- a/moat/src/api.rs +++ b/moat/src/api.rs @@ -6,25 +6,33 @@ use dusk_jubjub::{JubJubAffine, JubJubScalar}; use dusk_pki::{PublicSpendKey, SecretSpendKey}; +use dusk_plonk::composer::{Prover, Verifier}; use dusk_wallet::{RuskHttpClient, Wallet, WalletPath}; use zk_citadel::license::{License, Request, Session, SessionCookie}; use crate::license_provider::{LicenseIssuer, ReferenceLP}; use crate::utils::MoatCoreUtils; -use crate::wallet_accessor::Password::{self, Pwd}; +use crate::wallet_accessor::Password::Pwd; use crate::wallet_accessor::{BlockchainAccessConfig, WalletAccessor}; use crate::{ - BcInquirer, CitadelInquirer, LicenseSessionId, RequestCreator, - RequestSender, TxAwaiter, + BcInquirer, CitadelInquirer, CrsGetter, LicenseCircuit, LicenseSessionId, + RequestCreator, RequestSender, TxAwaiter, }; use rand::rngs::OsRng; +use rand_core::{CryptoRng, RngCore}; use std::path::Path; use std::sync::Arc; use toml_base_config::BaseConfig; +use dusk_plonk::prelude::*; + pub use crate::Error; +use std::fs::File; +use std::io::prelude::*; + +static LABEL: &[u8] = b"dusk-network"; pub struct MoatCore {} @@ -34,43 +42,31 @@ impl MoatCore { pub fn get_wallet_keypair( moat_context: &MoatContext, ) -> Result<(PublicSpendKey, SecretSpendKey), Error> { - let wallet_accessor = WalletAccessor::create( - moat_context.wallet_path.clone(), - moat_context.wallet_password.clone(), - )?; - let wallet = Wallet::from_file(wallet_accessor)?; - - wallet - .spending_keys(wallet.default_address()) + moat_context + .wallet + .spending_keys(moat_context.wallet.default_address()) .map_err(|e| Error::DuskWallet(Arc::from(e))) } /// Create and send a transaction containing a license request pub async fn request_license( - ssk_user: &SecretSpendKey, psk_lp: &PublicSpendKey, moat_context: &MoatContext, rng: &mut OsRng, - ) -> Result { - let request = RequestCreator::create(ssk_user, psk_lp, rng)?; + ) -> Result<(String, BlsScalar), Error> { + let (_psk_user, ssk_user) = MoatCore::get_wallet_keypair(moat_context)?; + + let request = RequestCreator::create(&ssk_user, psk_lp, rng)?; let request_hash = MoatCoreUtils::to_hash_hex(&request); - let tx_id = RequestSender::send_request( - request, - &moat_context.blockchain_access_config, - &moat_context.wallet_path, - &moat_context.wallet_password, - moat_context.gas_limit, - moat_context.gas_price, - ) - .await?; + let tx_id = RequestSender::send_request(request, moat_context).await?; let client = RuskHttpClient::new( moat_context.blockchain_access_config.rusk_address.clone(), ); TxAwaiter::wait_for(&client, tx_id).await?; - Ok(request_hash) + Ok((request_hash, tx_id)) } /// Retrieve a vector containing all the licenses owned by a given secret @@ -115,30 +111,22 @@ impl MoatCore { } /// Create and send a transaction containing a license for a given request - pub async fn issue_license( + pub async fn issue_license( request: &Request, - ssk_lp: &SecretSpendKey, moat_context: &MoatContext, attr_data: &JubJubScalar, - rng: &mut OsRng, + rng: &mut R, ) -> Result { - let mut reference_lp = ReferenceLP::create_with_ssk(ssk_lp)?; + let (_psk_lp, ssk_lp) = MoatCore::get_wallet_keypair(moat_context)?; + let mut reference_lp = ReferenceLP::create_with_ssk(&ssk_lp)?; let (_total_count, _this_lp_count) = reference_lp .scan(&moat_context.blockchain_access_config) .await?; - let license_issuer = LicenseIssuer::new( - moat_context.blockchain_access_config.clone(), - moat_context.wallet_path.clone(), - moat_context.wallet_password.clone(), - moat_context.gas_limit, - moat_context.gas_price, - ); - - let (_tx_id, license_blob) = license_issuer - .issue_license(rng, request, &reference_lp.ssk_lp, attr_data) - .await?; + let (_tx_id, license_blob) = + LicenseIssuer::issue_license(rng, request, attr_data, moat_context) + .await?; Ok(MoatCoreUtils::blob_to_hash_hex(&license_blob)) } @@ -148,15 +136,13 @@ impl MoatCore { moat_context: &MoatContext, psk_lp: &PublicSpendKey, psk_sp: &PublicSpendKey, - ssk: &SecretSpendKey, challenge: &JubJubScalar, license: &License, rng: &mut OsRng, ) -> Result, Error> { let license_hash = MoatCoreUtils::to_hash_hex(license); let pos_license = MoatCoreUtils::get_license_to_use( - &moat_context.blockchain_access_config, - ssk, + moat_context, license_hash.to_owned(), ) .await?; @@ -165,18 +151,12 @@ impl MoatCore { Some((pos, license)) => { let (_tx_id, session_cookie) = MoatCoreUtils::prove_and_send_use_license( - &moat_context.blockchain_access_config, - &moat_context.wallet_path, - &moat_context.wallet_password, + moat_context, psk_lp, psk_sp, - ssk, challenge, &license, pos, - moat_context.gas_limit, - moat_context.gas_price, - &mut None, rng, ) .await?; @@ -215,16 +195,17 @@ impl MoatCore { } pub struct MoatContext { - blockchain_access_config: BlockchainAccessConfig, - wallet_path: WalletPath, - wallet_password: Password, - gas_limit: u64, - gas_price: u64, + pub blockchain_access_config: BlockchainAccessConfig, + pub wallet: Wallet, + pub prover: Prover, + pub verifier: Verifier, + pub gas_limit: u64, + pub gas_price: u64, } impl MoatContext { /// Create a new Moat Context given the required configurations - pub fn create>( + pub async fn create>( config_path: T, wallet_path: T, wallet_password: T, @@ -234,15 +215,72 @@ impl MoatContext { let wallet_path = WalletPath::from(Path::new(wallet_path.as_ref())); let wallet_password = Pwd(wallet_password.as_ref().to_string()); + let wallet_accessor = WalletAccessor::create( + wallet_path.clone(), + wallet_password.clone(), + )?; + let blockchain_access_config = BlockchainAccessConfig::load_path(config_path.as_ref())?; - Ok(Self { - blockchain_access_config, - wallet_path, - wallet_password, - gas_limit, - gas_price, - }) + let wallet = wallet_accessor + .get_wallet(&blockchain_access_config) + .await?; + + let wallet_dir_path = match wallet_path.dir() { + Some(path) => path, + None => panic!(), + }; + + let prover_path = &wallet_dir_path.join("moat_prover.dat"); + let verifier_path = &wallet_dir_path.join("moat_verifier.dat"); + + if prover_path.exists() && verifier_path.exists() { + let mut file = File::open(prover_path)?; + let mut prover_bytes = vec![]; + file.read_to_end(&mut prover_bytes)?; + let prover = Prover::try_from_bytes(prover_bytes)?; + + file = File::open(verifier_path)?; + let mut verifier_bytes = vec![]; + file.read_to_end(&mut verifier_bytes)?; + let verifier = Verifier::try_from_bytes(verifier_bytes)?; + + Ok(Self { + blockchain_access_config, + wallet, + prover, + verifier, + gas_limit, + gas_price, + }) + } else { + let client = RuskHttpClient::new( + blockchain_access_config.rusk_address.clone(), + ); + + let pp_vec = CrsGetter::get_crs(&client).await?; + let pp = + // SAFETY: CRS vector is checked by the hash check when it is received from the node + unsafe { PublicParameters::from_slice_unchecked(pp_vec.as_slice()) }; + let (prover, verifier) = + Compiler::compile::(&pp, LABEL) + .expect("Compiling circuit should succeed"); + + let mut file = File::create(prover_path)?; + file.write_all(prover.to_bytes().as_slice())?; + + file = File::create(verifier_path)?; + file.write_all(verifier.to_bytes().as_slice())?; + + Ok(Self { + blockchain_access_config, + wallet, + prover, + verifier, + gas_limit, + gas_price, + }) + } } } diff --git a/moat/src/blockchain_payloads/payload_sender.rs b/moat/src/blockchain_payloads/payload_sender.rs index bbfbd8b..30ff361 100644 --- a/moat/src/blockchain_payloads/payload_sender.rs +++ b/moat/src/blockchain_payloads/payload_sender.rs @@ -4,13 +4,13 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. +use crate::api::MoatContext; use crate::error::Error; -use crate::wallet_accessor::{ - BlockchainAccessConfig, Password, WalletAccessor, -}; +use crate::wallet_accessor::accessor; + use crate::MAX_CALL_SIZE; + use dusk_bls12_381::BlsScalar; -use dusk_wallet::WalletPath; use phoenix_core::transaction::ModuleId; use rkyv::ser::serializers::AllocSerializer; @@ -21,11 +21,7 @@ impl PayloadSender { #[allow(clippy::too_many_arguments)] pub async fn execute_contract_method( payload: P, - cfg: &BlockchainAccessConfig, - wallet_path: &WalletPath, - password: &Password, - gas_limit: u64, - gas_price: u64, + moat_context: &MoatContext, contract_id: ModuleId, method: M, ) -> Result @@ -33,18 +29,13 @@ impl PayloadSender { P: rkyv::Serialize>, M: AsRef, { - let wallet_accessor = - WalletAccessor::create(wallet_path.clone(), password.clone())?; - let tx_id = wallet_accessor - .execute_contract_method( - payload, - contract_id, - method.as_ref().to_string(), - cfg, - gas_limit, - gas_price, - ) - .await?; + let tx_id = accessor::execute_contract_method( + moat_context, + payload, + contract_id, + method.as_ref().to_string(), + ) + .await?; Ok(tx_id) } } diff --git a/moat/src/citadel_licenses/license_user.rs b/moat/src/citadel_licenses/license_user.rs index ac3967a..439be1c 100644 --- a/moat/src/citadel_licenses/license_user.rs +++ b/moat/src/citadel_licenses/license_user.rs @@ -4,7 +4,7 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use crate::wallet_accessor::{BlockchainAccessConfig, Password}; +use crate::api::{MoatContext, MoatCore}; use crate::{ Error, LicenseCircuit, PayloadSender, LICENSE_CONTRACT_ID, USE_LICENSE_METHOD_NAME, @@ -13,9 +13,8 @@ use crate::{ARITY, DEPTH}; use bytecheck::CheckBytes; use dusk_bls12_381::BlsScalar; use dusk_jubjub::JubJubScalar; -use dusk_pki::{PublicSpendKey, SecretSpendKey}; -use dusk_plonk::prelude::{Proof, Prover, Verifier}; -use dusk_wallet::WalletPath; +use dusk_pki::PublicSpendKey; +use dusk_plonk::prelude::Proof; use poseidon_merkle::Opening; use rand::rngs::OsRng; use rkyv::{Archive, Deserialize, Serialize}; @@ -37,32 +36,29 @@ impl LicenseUser { /// as arguments to the license contract's use_license method. /// Returns transaction id and a session cookie. pub async fn prove_and_use_license( - blockchain_config: &BlockchainAccessConfig, - wallet_path: &WalletPath, - password: &Password, - ssk_user: &SecretSpendKey, + moat_context: &MoatContext, psk_lp: &PublicSpendKey, psk_sp: &PublicSpendKey, - prover: &Prover, - verifier: &Verifier, license: &License, opening: Opening<(), DEPTH, ARITY>, rng: &mut OsRng, challenge: &JubJubScalar, - gas_limit: u64, - gas_price: u64, ) -> Result<(BlsScalar, SessionCookie), Error> { + let (_psk_user, ssk_user) = MoatCore::get_wallet_keypair(moat_context)?; let (cpp, sc) = CitadelProverParameters::compute_parameters( - ssk_user, license, psk_lp, psk_sp, challenge, rng, opening, + &ssk_user, license, psk_lp, psk_sp, challenge, rng, opening, ); let circuit = LicenseCircuit::new(&cpp, &sc); - let (proof, public_inputs) = - prover.prove(rng, &circuit).expect("Proving should succeed"); + let (proof, public_inputs) = moat_context + .prover + .prove(rng, &circuit) + .expect("Proving should succeed"); assert!(!public_inputs.is_empty()); - verifier + moat_context + .verifier .verify(&proof, &public_inputs) .expect("Verifying the circuit should succeed"); @@ -73,11 +69,7 @@ impl LicenseUser { let tx_id = PayloadSender::execute_contract_method( use_license_arg, - blockchain_config, - wallet_path, - password, - gas_limit, - gas_price, + moat_context, LICENSE_CONTRACT_ID, USE_LICENSE_METHOD_NAME, ) diff --git a/moat/src/citadel_queries/citadel_inquirer.rs b/moat/src/citadel_queries/citadel_inquirer.rs index 59e6fe6..cc486ff 100644 --- a/moat/src/citadel_queries/citadel_inquirer.rs +++ b/moat/src/citadel_queries/citadel_inquirer.rs @@ -4,6 +4,7 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. +use crate::api::{MoatContext, MoatCore}; use crate::error::Error; use crate::Error::InvalidQueryResponse; use crate::{BlockInPlace, StreamAux}; @@ -14,7 +15,6 @@ use crate::{ LICENSE_CONTRACT_ID, }; use bytes::Bytes; -use dusk_pki::SecretSpendKey; use dusk_wallet::RuskHttpClient; use poseidon_merkle::Opening; use rkyv::{check_archived_root, Deserialize, Infallible}; @@ -105,7 +105,7 @@ impl CitadelInquirer { /// Finds owned license in a stream of licenses. /// It searches in a reverse order to return a newest license. pub fn find_owned_licenses( - ssk_user: SecretSpendKey, + moat_context: &MoatContext, stream: &mut (impl futures_core::Stream> + std::marker::Unpin), ) -> Result, Error> { @@ -114,6 +114,9 @@ impl CitadelInquirer { StreamAux::find_items::<(u64, Vec), ITEM_LEN>( |(pos, lic_vec)| { let license = Self::deserialise_license(lic_vec); + let (_psk, ssk_user) = + MoatCore::get_wallet_keypair(moat_context) + .expect("Keys returned."); if ssk_user.view_key().owns(&license.lsa) { pairs.push((*pos, license)); }; diff --git a/moat/src/citadel_requests/request_sender.rs b/moat/src/citadel_requests/request_sender.rs index efdc08c..1223ed3 100644 --- a/moat/src/citadel_requests/request_sender.rs +++ b/moat/src/citadel_requests/request_sender.rs @@ -4,12 +4,11 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use crate::wallet_accessor::{BlockchainAccessConfig, Password}; +use crate::api::MoatContext; use crate::{ Error, PayloadSender, LICENSE_CONTRACT_ID, REQUEST_LICENSE_METHOD_NAME, }; use dusk_bls12_381::BlsScalar; -use dusk_wallet::WalletPath; use zk_citadel::license::Request; pub struct RequestSender; @@ -18,19 +17,11 @@ impl RequestSender { /// Sends (submits) request into the blockchain. pub async fn send_request( request: Request, - config: &BlockchainAccessConfig, - wallet_path: &WalletPath, - password: &Password, - gas_limit: u64, - gas_price: u64, + moat_context: &MoatContext, ) -> Result { let tx_id = PayloadSender::execute_contract_method( request, - config, - wallet_path, - password, - gas_limit, - gas_price, + moat_context, LICENSE_CONTRACT_ID, REQUEST_LICENSE_METHOD_NAME, ) diff --git a/moat/src/license_provider/license_issuer.rs b/moat/src/license_provider/license_issuer.rs index 1b8b34f..2fec9cb 100644 --- a/moat/src/license_provider/license_issuer.rs +++ b/moat/src/license_provider/license_issuer.rs @@ -4,55 +4,32 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use crate::wallet_accessor::{BlockchainAccessConfig, Password}; +use crate::api::{MoatContext, MoatCore}; use crate::{ Error, PayloadSender, TxAwaiter, ISSUE_LICENSE_METHOD_NAME, LICENSE_CONTRACT_ID, MAX_LICENSE_SIZE, }; use dusk_bls12_381::BlsScalar; use dusk_jubjub::{JubJubAffine, JubJubScalar}; -use dusk_pki::SecretSpendKey; use dusk_poseidon::sponge; -use dusk_wallet::{RuskHttpClient, WalletPath}; +use dusk_wallet::RuskHttpClient; use rand::{CryptoRng, RngCore}; use tracing::trace; use zk_citadel::license::{License, Request}; -pub struct LicenseIssuer { - config: BlockchainAccessConfig, - wallet_path: WalletPath, - password: Password, - gas_limit: u64, - gas_price: u64, -} +pub struct LicenseIssuer {} impl LicenseIssuer { - pub fn new( - config: BlockchainAccessConfig, - wallet_path: WalletPath, - password: Password, - gas_limit: u64, - gas_price: u64, - ) -> Self { - Self { - config, - wallet_path, - password, - gas_limit, - gas_price, - } - } - /// Issue license for a given request, License Provider SSK, and attribute /// data. Returns a serialized license. pub async fn issue_license( - &self, rng: &mut R, request: &Request, - ssk_lp: &SecretSpendKey, attr_data: &JubJubScalar, + moat_context: &MoatContext, ) -> Result<(BlsScalar, Vec), Error> { - let license = License::new(attr_data, ssk_lp, request, rng); + let (_psk, ssk) = MoatCore::get_wallet_keypair(moat_context)?; + let license = License::new(attr_data, &ssk, request, rng); let license_blob = rkyv::to_bytes::<_, MAX_LICENSE_SIZE>(&license) .expect("Serializing should be infallible") .to_vec(); @@ -65,16 +42,14 @@ impl LicenseIssuer { ); let tx_id = PayloadSender::execute_contract_method( tuple, - &self.config, - &self.wallet_path, - &self.password, - self.gas_limit, - self.gas_price, + moat_context, LICENSE_CONTRACT_ID, ISSUE_LICENSE_METHOD_NAME, ) .await?; - let client = RuskHttpClient::new(self.config.rusk_address.clone()); + let client = RuskHttpClient::new( + moat_context.blockchain_access_config.rusk_address.clone(), + ); TxAwaiter::wait_for(&client, tx_id).await?; Ok((tx_id, license_blob)) } diff --git a/moat/src/utils.rs b/moat/src/utils.rs index 2284360..77d4c25 100644 --- a/moat/src/utils.rs +++ b/moat/src/utils.rs @@ -4,38 +4,21 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. -use crate::wallet_accessor::BlockchainAccessConfig; -use crate::wallet_accessor::Password; -use dusk_pki::{PublicSpendKey, SecretSpendKey}; -use dusk_wallet::WalletPath; +use crate::api::MoatContext; +use dusk_pki::PublicSpendKey; use rand::rngs::OsRng; use zk_citadel::license::{License, SessionCookie}; use dusk_jubjub::JubJubScalar; -use crate::{ - BcInquirer, CitadelInquirer, CrsGetter, Error, LicenseCircuit, LicenseUser, - TxAwaiter, -}; +use crate::{BcInquirer, CitadelInquirer, Error, LicenseUser, TxAwaiter}; use dusk_wallet::RuskHttpClient; use rkyv::ser::serializers::AllocSerializer; use sha3::{Digest, Sha3_256}; use dusk_bls12_381::BlsScalar; -use dusk_plonk::prelude::*; - -use std::fs::File; -use std::io::prelude::*; - -static LABEL: &[u8] = b"dusk-network"; - -pub struct SetupHolder { - pub prover: Prover, - pub verifier: Verifier, -} - pub struct MoatCoreUtils {} const MAX_OBJECT_SIZE: usize = 16384; @@ -76,20 +59,22 @@ impl MoatCoreUtils { } pub async fn get_license_to_use( - blockchain_access_config: &BlockchainAccessConfig, - ssk: &SecretSpendKey, + moat_context: &MoatContext, license_hash: String, ) -> Result, Error> { - let client = - RuskHttpClient::new(blockchain_access_config.rusk_address.clone()); + let client = RuskHttpClient::new( + moat_context.blockchain_access_config.rusk_address.clone(), + ); let end_height = BcInquirer::block_height(&client).await?; let block_heights = 0..(end_height + 1); let mut licenses_stream = CitadelInquirer::get_licenses(&client, block_heights).await?; - let pairs = - CitadelInquirer::find_owned_licenses(*ssk, &mut licenses_stream)?; + let pairs = CitadelInquirer::find_owned_licenses( + moat_context, + &mut licenses_stream, + )?; Ok(if pairs.is_empty() { None } else { @@ -104,89 +89,30 @@ impl MoatCoreUtils { #[allow(clippy::too_many_arguments)] pub async fn prove_and_send_use_license( - blockchain_access_config: &BlockchainAccessConfig, - wallet_path: &WalletPath, - psw: &Password, + moat_context: &MoatContext, psk_lp: &PublicSpendKey, psk_sp: &PublicSpendKey, - ssk_user: &SecretSpendKey, challenge: &JubJubScalar, license: &License, pos: u64, - gas_limit: u64, - gas_price: u64, - sh_opt: &mut Option, rng: &mut OsRng, ) -> Result<(BlsScalar, SessionCookie), Error> { - let client = - RuskHttpClient::new(blockchain_access_config.rusk_address.clone()); - - let setup_holder = match sh_opt { - Some(sh) => sh, - _ => { - let wallet_dir_path = match wallet_path.dir() { - Some(path) => path, - None => panic!(), - }; - - let prover_path = &wallet_dir_path.join("moat_prover.dat"); - let verifier_path = &wallet_dir_path.join("moat_verifier.dat"); - - if prover_path.exists() && verifier_path.exists() { - let mut file = File::open(prover_path)?; - let mut prover_bytes = vec![]; - file.read_to_end(&mut prover_bytes)?; - let prover = Prover::try_from_bytes(prover_bytes)?; - - file = File::open(verifier_path)?; - let mut verifier_bytes = vec![]; - file.read_to_end(&mut verifier_bytes)?; - let verifier = Verifier::try_from_bytes(verifier_bytes)?; - - let sh = SetupHolder { prover, verifier }; - *sh_opt = Some(sh); - sh_opt.as_ref().expect("setup holder is not empty") - } else { - let pp_vec = CrsGetter::get_crs(&client).await?; - let pp = - // SAFETY: CRS vector is checked by the hash check when it is received from the node - unsafe { PublicParameters::from_slice_unchecked(pp_vec.as_slice()) }; - let (prover, verifier) = - Compiler::compile::(&pp, LABEL) - .expect("Compiling circuit should succeed"); - - let mut file = File::create(prover_path)?; - file.write_all(prover.to_bytes().as_slice())?; - - file = File::create(verifier_path)?; - file.write_all(verifier.to_bytes().as_slice())?; - - let sh = SetupHolder { prover, verifier }; - *sh_opt = Some(sh); - sh_opt.as_ref().expect("setup holder is not empty") - } - } - }; + let client = RuskHttpClient::new( + moat_context.blockchain_access_config.rusk_address.clone(), + ); let opening = CitadelInquirer::get_merkle_opening(&client, pos) .await? .expect("Opening obtained successfully"); let (tx_id, session_cookie) = LicenseUser::prove_and_use_license( - blockchain_access_config, - wallet_path, - psw, - ssk_user, + moat_context, psk_lp, psk_sp, - &setup_holder.prover, - &setup_holder.verifier, license, opening, rng, challenge, - gas_limit, - gas_price, ) .await?; TxAwaiter::wait_for(&client, tx_id).await?; diff --git a/moat/src/wallet_accessor/accessor.rs b/moat/src/wallet_accessor/accessor.rs index c6487ce..b9acde6 100644 --- a/moat/src/wallet_accessor/accessor.rs +++ b/moat/src/wallet_accessor/accessor.rs @@ -4,6 +4,7 @@ // // Copyright (c) DUSK NETWORK. All rights reserved. +use crate::api::MoatContext; use crate::wallet_accessor::BlockchainAccessConfig; use crate::wallet_accessor::Password::{Pwd, PwdHash}; use dusk_bls12_381::BlsScalar; @@ -70,7 +71,7 @@ impl WalletAccessor { }) } - async fn get_wallet( + pub async fn get_wallet( &self, cfg: &BlockchainAccessConfig, ) -> Result, dusk_wallet::Error> { @@ -91,39 +92,6 @@ impl WalletAccessor { Ok(wallet) } - /// submits a transaction which will execute a given method - /// of a given contract - pub async fn execute_contract_method( - &self, - data: C, - contract_id: ModuleId, - call_name: String, - cfg: &BlockchainAccessConfig, - gas_limit: u64, - gas_price: u64, - ) -> Result - where - C: rkyv::Serialize>, - { - let wallet = self.get_wallet(cfg).await?; - - debug!( - "Sending tx with a call to method '{}' of contract='{}'", - call_name.clone(), - hex::encode(contract_id) - ); - - let sender = wallet.default_address(); - let mut gas = Gas::new(gas_limit); - gas.set_price(gas_price); - - let tx = wallet - .execute(sender, contract_id, call_name.clone(), data, gas) - .await?; - let tx_id = rusk_abi::hash::Hasher::digest(tx.to_hash_input_bytes()); - Ok(tx_id) - } - /// provides hashes of all notes belonging to the default address pub async fn get_notes( &self, @@ -133,3 +101,39 @@ impl WalletAccessor { wallet.get_all_notes(wallet.default_address()).await } } + +/// submits a transaction which will execute a given method +/// of a given contract +pub async fn execute_contract_method( + moat_context: &MoatContext, + data: C, + contract_id: ModuleId, + call_name: String, +) -> Result +where + C: rkyv::Serialize>, +{ + debug!( + "Sending tx with a call to method '{}' of contract='{}'", + call_name.clone(), + hex::encode(contract_id) + ); + + let sender = moat_context.wallet.default_address(); + let mut gas = Gas::new(moat_context.gas_limit); + gas.set_price(moat_context.gas_price); + + moat_context.wallet.sync().await?; + assert!( + moat_context.wallet.is_online().await, + "Wallet should be online" + ); + + let tx = moat_context + .wallet + .execute(sender, contract_id, call_name.clone(), data, gas) + .await?; + + let tx_id = rusk_abi::hash::Hasher::digest(tx.to_hash_input_bytes()); + Ok(tx_id) +}