Skip to content

Commit

Permalink
Subaccounts for load tests (#552)
Browse files Browse the repository at this point in the history
* subaccounts for loadtests

* delete subaccount
  • Loading branch information
volovyks authored Apr 15, 2024
1 parent 96ec17f commit 919c638
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 49 deletions.
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions load-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ near-jsonrpc-client = "0.6.0"
near-fetch = "0.2.0"
web3 = "0.19.0"
borsh = "0.10.3"
near-workspaces = "0.10.0"
98 changes: 66 additions & 32 deletions load-tests/src/fastauth/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ pub mod primitives;
pub mod utils;

use core::panic;
use near_workspaces::{types::NearToken, Account};
use reqwest::{header::CONTENT_TYPE, Body};
use std::{time::Duration, vec};
use std::{str::FromStr, time::Duration, vec};

use constants::VALID_OIDC_PROVIDER_KEY;
use goose::prelude::*;
Expand All @@ -29,14 +30,35 @@ use near_primitives::{
types::AccountId,
};
use primitives::UserSession;
use rand::{distributions::Alphanumeric, Rng};
use utils::build_send_and_check_request;

pub async fn prepare_user_credentials(user: &mut GooseUser) -> TransactionResult {
tracing::info!("prepare_user_credentials");
// Generate 2 key pairs
let fa_sk = SecretKey::from_random(near_crypto::KeyType::ED25519);
let la_sk = SecretKey::from_random(near_crypto::KeyType::ED25519);

let worker = near_workspaces::testnet().await.unwrap();

let root_account = Account::from_secret_key(
near_workspaces::types::AccountId::try_from("dev-1660670387515-45063246810397".to_string()).unwrap(),
near_workspaces::types::SecretKey::from_str(
"ed25519:4hc3qA3nTE8M63DB8jEZx9ZbHVUPdkMjUAoa11m4xtET7F6w4bk51TwQ3RzEcFhBtXvF6NYzFdiJduaGdJUvynAi"
).unwrap(),
&worker
);

let subaccount = root_account
.create_subaccount(&format!("user-{}", rand::random::<u64>()))
.initial_balance(NearToken::from_yoctonear(200000000000000000000000u128))
.transact()
.await
.unwrap()
.into_result()
.unwrap();

tracing::info!(
"Created user accountId: {}, pk: {}",
subaccount.id(),
subaccount.secret_key().public_key()
);

// Create JWT with random sub (usually done by OIDC Provider)
let oidc_token = OidcToken::new(&utils::create_jwt_token(
Expand All @@ -46,22 +68,13 @@ pub async fn prepare_user_credentials(user: &mut GooseUser) -> TransactionResult
None,
));

// Generate random near account id
let account_id_rand: String = rand::thread_rng()
.sample_iter(&Alphanumeric)
.take(10)
.map(char::from)
.collect();

let near_account_id: AccountId = format!("acc-{}.near", account_id_rand.to_lowercase())
.try_into()
.expect("Failed to generate random account Id");

let session = UserSession {
jwt_token: oidc_token,
near_account_id,
fa_sk,
la_sk,
account: subaccount.clone(),
root_account,
near_account_id: AccountId::try_from(subaccount.id().to_string()).unwrap(),
fa_sk: SecretKey::from_str(&subaccount.secret_key().to_string()).unwrap(),
la_sk: SecretKey::from_random(near_crypto::KeyType::ED25519), // no need to actually add it ATM
recovery_pk: None,
};

Expand All @@ -70,17 +83,36 @@ pub async fn prepare_user_credentials(user: &mut GooseUser) -> TransactionResult
Ok(())
}

pub async fn delete_user_account(user: &mut GooseUser) -> TransactionResult {
tracing::info!("delete_user_accounts");

let session = user
.get_session_data::<UserSession>()
.expect("Session Data must be set");

let _ = session
.account
.clone()
.delete_account(session.root_account.id())
.await
.expect("Failed to delete subaccount");

Ok(())
}

pub async fn user_credentials(user: &mut GooseUser) -> TransactionResult {
tracing::info!("user_credentials");
let sesion = user
let session = user
.get_session_data::<UserSession>()
.expect("Session Data must be set");

let oidc_token = sesion.jwt_token.clone();
let fa_sk = sesion.fa_sk.clone();
let oidc_token = session.jwt_token.clone();
let fa_sk = session.fa_sk.clone();
let fa_pk = fa_sk.public_key();
let la_sk = sesion.la_sk.clone();
let near_account_id = sesion.near_account_id.clone();
let la_sk = session.la_sk.clone();
let near_account_id = session.near_account_id.clone();
let account = session.account.clone();
let root_account = session.root_account.clone();

let user_credentials_request_digest =
user_credentials_request_digest(&oidc_token, &fa_pk).expect("Failed to create digest");
Expand Down Expand Up @@ -121,6 +153,8 @@ pub async fn user_credentials(user: &mut GooseUser) -> TransactionResult {
tracing::info!("UserCredentialsResponce has Ok, setting session data");
let session = UserSession {
jwt_token: oidc_token,
account,
root_account,
near_account_id,
fa_sk,
la_sk,
Expand All @@ -145,11 +179,11 @@ pub async fn mpc_public_key(user: &mut GooseUser) -> TransactionResult {

pub async fn claim_oidc(user: &mut GooseUser) -> TransactionResult {
tracing::info!("claim_oidc");
let sesion = user
let session = user
.get_session_data::<UserSession>()
.expect("Session Data must be set");
let oidc_token_hash = sesion.jwt_token.digest_hash();
let frp_secret_key = sesion.fa_sk.clone();
let oidc_token_hash = session.jwt_token.digest_hash();
let frp_secret_key = session.fa_sk.clone();
let frp_public_key = frp_secret_key.public_key();

let request_digest = claim_oidc_request_digest(&oidc_token_hash, &frp_public_key)
Expand All @@ -169,13 +203,13 @@ pub async fn claim_oidc(user: &mut GooseUser) -> TransactionResult {
}

pub async fn new_account(user: &mut GooseUser) -> TransactionResult {
let sesion = user
let session = user
.get_session_data::<UserSession>()
.expect("Session Data must be set");
let oidc_token = sesion.jwt_token.clone();
let fa_secret_key = sesion.fa_sk.clone();
let oidc_token = session.jwt_token.clone();
let fa_secret_key = session.fa_sk.clone();
let fa_public_key = fa_secret_key.public_key();
let user_account_id = sesion.near_account_id.clone();
let user_account_id = session.near_account_id.clone();

let create_account_options = CreateAccountOptions {
full_access_keys: Some(vec![fa_public_key.clone()]),
Expand All @@ -194,7 +228,7 @@ pub async fn new_account(user: &mut GooseUser) -> TransactionResult {
let new_account_request = NewAccountRequest {
near_account_id: user_account_id,
create_account_options,
oidc_token: sesion.jwt_token.clone(),
oidc_token: session.jwt_token.clone(),
user_credentials_frp_signature,
frp_public_key: fa_public_key,
};
Expand Down
4 changes: 4 additions & 0 deletions load-tests/src/fastauth/primitives.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use mpc_recovery::sign_node::oidc::OidcToken;
use near_crypto::{PublicKey, SecretKey};
use near_primitives::types::AccountId;
use near_workspaces::Account;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
Expand All @@ -13,6 +14,9 @@ pub struct IdTokenClaims {

pub struct UserSession {
pub jwt_token: OidcToken,
pub account: Account,
// account to create other account
pub root_account: Account,
pub near_account_id: AccountId,
pub fa_sk: SecretKey,
pub la_sk: SecretKey,
Expand Down
16 changes: 14 additions & 2 deletions load-tests/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ pub mod fastauth;
pub mod multichain;

use fastauth::{
claim_oidc, mpc_public_key, new_account, prepare_user_credentials, sign, user_credentials,
claim_oidc, delete_user_account, mpc_public_key, new_account, prepare_user_credentials, sign,
user_credentials,
};
use goose::prelude::*;
use multichain::multichain_sign;
Expand All @@ -19,7 +20,18 @@ async fn main() -> Result<(), GooseError> {
GooseAttack::initialize()?
.register_scenario(
scenario!("multichainSign")
.register_transaction(transaction!(multichain_sign).set_sequence(2)),
.register_transaction(transaction!(prepare_user_credentials).set_sequence(1))
.register_transaction(transaction!(multichain_sign).set_sequence(2))
.register_transaction(transaction!(multichain_sign).set_sequence(3))
.register_transaction(transaction!(multichain_sign).set_sequence(4))
.register_transaction(transaction!(multichain_sign).set_sequence(5))
.register_transaction(transaction!(multichain_sign).set_sequence(6))
.register_transaction(transaction!(multichain_sign).set_sequence(7))
.register_transaction(transaction!(multichain_sign).set_sequence(8))
.register_transaction(transaction!(multichain_sign).set_sequence(9))
.register_transaction(transaction!(multichain_sign).set_sequence(10))
.register_transaction(transaction!(multichain_sign).set_sequence(11))
.register_transaction(transaction!(delete_user_account).set_sequence(12)),
)
.register_scenario(
scenario!("fastAuthRegistration")
Expand Down
30 changes: 18 additions & 12 deletions load-tests/src/multichain/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use std::{str::FromStr, time::Duration};
use std::time::Duration;

use goose::goose::{GooseMethod, GooseRequest, GooseUser, TransactionResult};
use goose_eggs::{validate_and_load_static_assets, Validate};
use near_crypto::{InMemorySigner, SecretKey};
use near_crypto::InMemorySigner;
use near_jsonrpc_client::JsonRpcClient;
use near_primitives::{
transaction::{Action, FunctionCallAction, Transaction},
Expand All @@ -11,20 +11,23 @@ use near_primitives::{
use rand::Rng;
use reqwest::header::CONTENT_TYPE;

use crate::fastauth::primitives::UserSession;

pub async fn multichain_sign(user: &mut GooseUser) -> TransactionResult {
tracing::info!("multichain_sign");

// TODO: for better experience we can create real account in prepare_user_credentials and then get it from session
let account_id = AccountId::try_from("dev-1660670387515-45063246810397".to_string()).unwrap();
let secret_key = SecretKey::from_str("ed25519:4hc3qA3nTE8M63DB8jEZx9ZbHVUPdkMjUAoa11m4xtET7F6w4bk51TwQ3RzEcFhBtXvF6NYzFdiJduaGdJUvynAi").unwrap();
let public_key = secret_key.public_key();
let multichain_contract_id = AccountId::try_from("multichain0.testnet".to_string()).unwrap(); // TODO: pass in parameters
let session = user
.get_session_data::<UserSession>()
.expect("Session Data must be set");

let multichain_contract_id =
AccountId::try_from("v2.multichain-mpc.testnet".to_string()).unwrap();
let testnet_rpc_url = "https://rpc.testnet.near.org".to_string();

let signer = InMemorySigner {
account_id: account_id.clone(),
public_key: public_key.clone(),
secret_key,
account_id: session.near_account_id.clone(),
public_key: session.fa_sk.public_key(),
secret_key: session.fa_sk.clone(),
};

let connector = JsonRpcClient::new_client();
Expand All @@ -40,8 +43,8 @@ pub async fn multichain_sign(user: &mut GooseUser) -> TransactionResult {
tracing::info!("requesting signature for: {:?}", payload_hashed);

let transaction = Transaction {
signer_id: account_id.clone(),
public_key,
signer_id: session.near_account_id.clone(),
public_key: session.fa_sk.public_key(),
nonce,
receiver_id: multichain_contract_id,
block_hash,
Expand Down Expand Up @@ -85,6 +88,9 @@ pub async fn multichain_sign(user: &mut GooseUser) -> TransactionResult {

let goose_response = user.request(goose_request).await?;

// let text = goose_response.response.unwrap().text().await.unwrap();
// tracing::info!("goose_response: {:?}", text);

let rsp = goose_response.response.as_ref().unwrap();

tracing::info!("goose_response: {:?}", rsp);
Expand Down
2 changes: 1 addition & 1 deletion load-tests/src/multichain/test_plans/short.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0,0s;1,120s;0,0s
0,0s;5,30s;5,20m;0,0s

0 comments on commit 919c638

Please sign in to comment.