Skip to content

Commit

Permalink
Merge pull request #21 from dusk-network/refactorings
Browse files Browse the repository at this point in the history
Refactorings, enriching round trip test
  • Loading branch information
miloszm authored Oct 6, 2023
2 parents 2d4d5bd + c517536 commit 59037c2
Show file tree
Hide file tree
Showing 35 changed files with 288 additions and 84 deletions.
83 changes: 83 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,86 @@ This is a low-level crate which provides wallet (Blockchain) connectivity for fu
Users of moat-core do not need to be aware of this crate, yet for maintainers and extenders, the crate
provides a convenient low level interface between the higher-level moat-core library and the blockchain.
Note that this crate deals only with contract method calling, it does not deal with contract queries.

## moat-core

### citadel requests

Class: RequestCreator
Methods:
create,
create_from_hex_args
Both methods allow for creation of a request, given user's secret spend key and license provider's public spend key.
The request can then be sent to license provider, off-chain or on-chain.

Class: RequestSender
Methods: send_request
Submits the request into blockchain.
It does so by calling a dummy contract method with request as an argument.

Class: RequestScanner
Methods:
scan_transactions,
scan_last_blocks,
scan_block_range
Scan requests in a given collection of transactions,
contained in a given range of blocks or in a given number of most recent blocks.

### citadel queries

Class: CitadelInquirer
Methods:
get_licenses,
get_merkle_opening,
get_session,
get_info
Execute citadel-specific query methods of the license contract method.

### blockchain payloads

Class: PayloadExtractor
Methods: payload_from_tx
Extracts a payload from the given transaction,
errors if payload of a given type is not present or the transaction is not a contract calling transaction.

Class: PayloadRetriever
Methods: retrieve_payload
Retrieves payload of a given transaction id,
errors if transaction is not found, or it does not contain a payload
(for example, given transaction is not a contract calling transaction)

Class: PayloadSender
Methods: execute_contract_method
Executes given method of a given contract (identified by a contract id), passing to it the payload as an argument.

### contract queries

Class: ContractInquirer
Methods:
query_contract,
query_contract_with_feeder
query_contract - accepts a generic argument, contract id and contract query method name, returns a generic value result
query_contract_with_feeder - accepts a generic argument, contract id and method name, returns result as a Stream of bytes

### blockchain queries

Class: BcInquirer
Methods:
gql_query,
block_height
gql_query - executes a GQL query and returns result as a vector of bytes
block_height - returns the current block height as u64

Class: TxAwaiter
Methods:
wait_for,
wait_for_tx
Waits for a transaction identified by transaction id to be confirmed on the blockchain.

Class: TxInquirer
Methods:
txs_from_block,
txs_from_block_range,
txs_from_last_n_blocks,
retrieve_tx
Retrieve transaction identified by transaction id, or transactions contained in a given block, or a collection of blocks.
2 changes: 1 addition & 1 deletion integration-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ phoenix-core = { version = "0.20.0-rc.0", features = ["alloc"] }
poseidon-merkle = { version = "0.2.1-rc.0", features = ["rkyv-impl"] }
dusk-pki = { version = "0.12", default-features = false, features = ["rkyv-impl"] }
dusk-plonk = { version = "0.14", default-features = false, features = ["rkyv-impl", "alloc"] }
dusk-jubjub = { version = "0.12", default-features = false }
dusk-bls12_381 = "0.11"
wallet-accessor = { path = "../wallet-accessor" }
rkyv = { version = "=0.7.39" }
tokio = { version = "1.15", features = ["rt-multi-thread", "time", "fs", "macros"] }
Expand Down
8 changes: 8 additions & 0 deletions integration-tests/tests/blockchain/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) DUSK NETWORK. All rights reserved.

mod retrieve_txs;
mod stake_add_owner;
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Copyright (c) DUSK NETWORK. All rights reserved.

use dusk_wallet::RuskHttpClient;
use moat_core::{Error, TxRetriever};
use moat_core::{Error, TxInquirer};
use toml_base_config::BaseConfig;
use tracing::trace;
use wallet_accessor::BlockchainAccessConfig;
Expand All @@ -22,7 +22,7 @@ async fn retrieve_txs_from_block() -> Result<(), Error> {

const BLOCK_HEIGHT: u64 = 110;

let txs = TxRetriever::txs_from_block(&client, BLOCK_HEIGHT).await?;
let txs = TxInquirer::txs_from_block(&client, BLOCK_HEIGHT).await?;

trace!("transactions retrieved={}", txs.transactions.len());

Expand All @@ -42,7 +42,7 @@ async fn retrieve_txs_from_block_range() -> Result<(), Error> {
const BLOCK_HEIGHT_BEG: u64 = 1;
const BLOCK_HEIGHT_END: u64 = 1000;

let (txs, top_block) = TxRetriever::txs_from_block_range(
let (txs, top_block) = TxInquirer::txs_from_block_range(
&client,
BLOCK_HEIGHT_BEG,
BLOCK_HEIGHT_END,
Expand All @@ -66,7 +66,7 @@ async fn retrieve_txs_from_last_n_blocks() -> Result<(), Error> {
let client = RuskHttpClient::new(cfg.rusk_address);

const N: usize = 10000;
let txs = TxRetriever::txs_from_last_n_blocks(&client, N).await?;
let txs = TxInquirer::txs_from_last_n_blocks(&client, N).await?;

trace!("transactions={}", txs.transactions.len());

Expand All @@ -86,7 +86,7 @@ async fn retrieve_tx_by_id() -> Result<(), Error> {

let client = RuskHttpClient::new(config.rusk_address);

let (tx, height) = TxRetriever::retrieve_tx(TXID, &client).await?;
let (tx, height) = TxInquirer::retrieve_tx(TXID, &client).await?;

trace!("tx={:?}, block_height={}", tx, height);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ async fn stake_add_owner() -> Result<(), Error> {
PathBuf::from(WALLET_PATH).as_path().join("wallet.dat"),
);

let tx_id = PayloadSender::send_to_contract_method(
let tx_id = PayloadSender::execute_contract_method(
request_json.provider_psk,
&blockchain_config,
&wallet_path,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ async fn lp_scan() -> Result<(), Error> {
let blockchain_config =
BlockchainAccessConfig::load_path(blockchain_config_path)?;

let mut reference_lp = ReferenceLP::init(&lp_config_path)?;
let mut reference_lp = ReferenceLP::create(&lp_config_path)?;

reference_lp.scan(&blockchain_config).await?;
Ok(())
Expand All @@ -37,7 +37,7 @@ async fn lp_scan_last_blocks() -> Result<(), Error> {
let blockchain_config =
BlockchainAccessConfig::load_path(blockchain_config_path)?;

let mut reference_lp = ReferenceLP::init(&lp_config_path)?;
let mut reference_lp = ReferenceLP::create(&lp_config_path)?;

let (_total, _owned) = reference_lp
.scan_last_blocks(10000, &blockchain_config)
Expand All @@ -58,8 +58,8 @@ async fn lp_scan_2_lps() -> Result<(), Error> {
let blockchain_config =
BlockchainAccessConfig::load_path(blockchain_config_path)?;

let mut reference_lp1 = ReferenceLP::init(&lp1_config_path)?;
let mut reference_lp2 = ReferenceLP::init(&lp2_config_path)?;
let mut reference_lp1 = ReferenceLP::create(&lp1_config_path)?;
let mut reference_lp2 = ReferenceLP::create(&lp2_config_path)?;
let (_, _lp1_count) = reference_lp1.scan(&blockchain_config).await?;
let (_, _lp2_count) = reference_lp2.scan(&blockchain_config).await?;
Ok(())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,18 @@
use bytecheck::CheckBytes;
use bytes::Bytes;
use dusk_bls12_381::BlsScalar;
use dusk_bytes::{DeserializableSlice, Serializable};
use dusk_jubjub::BlsScalar;
use dusk_pki::{PublicSpendKey, SecretSpendKey};
use dusk_plonk::prelude::*;
use dusk_wallet::{RuskHttpClient, WalletPath};
use license_provider::{LicenseIssuer, ReferenceLP};
use moat_core::Error::InvalidQueryResponse;
use moat_core::{
BcInquirer, CitadelInquirer, Error, JsonLoader, LicenseCircuit,
LicenseSessionId, PayloadSender, RequestCreator, RequestJson, StreamAux,
TxAwaiter, ARITY, DEPTH, LICENSE_CONTRACT_ID, USE_LICENSE_METHOD_NAME,
LicenseSessionId, PayloadRetriever, PayloadSender, RequestCreator,
RequestJson, RequestSender, StreamAux, TxAwaiter, ARITY, DEPTH,
LICENSE_CONTRACT_ID, USE_LICENSE_METHOD_NAME,
};
use poseidon_merkle::Opening;
use rand::rngs::StdRng;
Expand Down Expand Up @@ -69,15 +70,14 @@ fn compute_citadel_parameters(
psk_lp: PublicSpendKey,
lic: &License,
merkle_proof: Opening<(), DEPTH, ARITY>,
challenge: &JubJubScalar,
) -> (CitadelProverParameters<DEPTH, ARITY>, SessionCookie) {
const CHALLENGE: u64 = 20221127u64;
let c = JubJubScalar::from(CHALLENGE);
let (cpp, sc) = CitadelProverParameters::compute_parameters(
&ssk,
&lic,
&psk_lp,
&psk_lp,
&c,
challenge,
rng,
merkle_proof,
);
Expand Down Expand Up @@ -120,13 +120,15 @@ async fn prove_and_send_use_license(
license: &License,
opening: Opening<(), DEPTH, ARITY>,
rng: &mut StdRng,
challenge: &JubJubScalar,
) -> Result<BlsScalar, Error> {
let (cpp, sc) = compute_citadel_parameters(
rng,
ssk_user,
reference_lp.psk_lp,
license,
opening,
&challenge,
);
let circuit = LicenseCircuit::new(&cpp, &sc);

Expand All @@ -146,7 +148,7 @@ async fn prove_and_send_use_license(
public_inputs,
};

let tx_id = PayloadSender::send_to_contract_method(
let tx_id = PayloadSender::execute_contract_method(
use_license_arg,
&blockchain_config,
&wallet_path,
Expand Down Expand Up @@ -258,7 +260,7 @@ async fn user_round_trip() -> Result<(), Error> {
let lp_config_path =
concat!(env!("CARGO_MANIFEST_DIR"), "/tests/config/lp2.json");

let reference_lp = ReferenceLP::init(&lp_config_path)?;
let reference_lp = ReferenceLP::create(&lp_config_path)?;

let blockchain_config =
BlockchainAccessConfig::load_path(blockchain_config_path)?;
Expand All @@ -270,20 +272,36 @@ async fn user_round_trip() -> Result<(), Error> {
let client = RuskHttpClient::new(blockchain_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.clone(),
request_json.user_ssk,
request_json.provider_psk,
rng,
)?;

let ssk_user_bytes = hex::decode(request_json.user_ssk)?;
let ssk_user = SecretSpendKey::from_slice(ssk_user_bytes.as_slice())?;
// 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?;

// as a LP, call issue license, wait for tx to confirm
// as a LP, retrieve request from blockchain
info!("retrieving request from blockchain (as an LP)");
let tx_id = format!("{:X}", tx_id);
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(
Expand All @@ -300,7 +318,6 @@ async fn user_round_trip() -> Result<(), Error> {
info!("end_height={}", end_height);

// as a User, call get_licenses, obtain license and pos

let start_height = if end_height > BLOCK_RANGE {
end_height - BLOCK_RANGE
} else {
Expand All @@ -319,14 +336,17 @@ async fn user_round_trip() -> Result<(), Error> {
.expect("owned license found");

// as a User, call get_merkle_opening, obtain opening

info!("calling get_merkle_opening (as a user)");
let opening = CitadelInquirer::get_merkle_opening(&client, pos).await?;
let opening =
CitadelInquirer::get_merkle_opening(&client, pos.clone()).await?;
assert!(opening.is_some());

// as a User, compute proof, call use_license, wait for tx to confirm

show_state(&client, "before use_license").await?;
// for test purposes we make challenge dependent on the number of sessions,
// so that it is different every time we run the test
let (_, _, num_sessions) = CitadelInquirer::get_info(&client).await?;
let challenge = JubJubScalar::from(num_sessions as u64 + 1);
info!("calling use_license (as a user)");
let session_id = prove_and_send_use_license(
&client,
Expand All @@ -339,13 +359,13 @@ async fn user_round_trip() -> Result<(), Error> {
&license,
opening.unwrap(),
rng,
&challenge,
)
.await?;
show_state(&client, "after use_license").await?;
let session_id = LicenseSessionId { id: session_id };

// as an SP, call get_session

info!("calling get_session (as an SP)");
let session = CitadelInquirer::get_session(&client, session_id).await?;
assert!(session.is_some());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ async fn issue_license() -> Result<(), Error> {
let lp_config_path =
concat!(env!("CARGO_MANIFEST_DIR"), "/tests/config/lp2.json");

let reference_lp = ReferenceLP::init(&lp_config_path)?;
let reference_lp = ReferenceLP::create(&lp_config_path)?;

let request_json: RequestJson = RequestJson::from_file(request_path)?;

Expand Down
Loading

0 comments on commit 59037c2

Please sign in to comment.