Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Subaccounts for load tests #552

Merged
merged 3 commits into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
);
Comment on lines +40 to +46
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the issue with this is that somebody can easily disrupt the load test by getting this key. We wouldn't notice this either until we run it locally manually. We should be creating a dev account each time and delete the account at the end of the test

Copy link
Collaborator Author

@volovyks volovyks Apr 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I know. But dev_create_account does not work for me. And there is no Error handling. Maybe the faucet is broken.

Copy link
Collaborator Author

@volovyks volovyks Apr 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested, near-cli can create accounts using the faucet. Helper and URL parameters looks the same for me.


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
Loading