Skip to content

Commit

Permalink
Merge pull request #57 from near/serhii/meta
Browse files Browse the repository at this point in the history
  • Loading branch information
itegulov authored Apr 17, 2023
2 parents 8861171 + d3eff53 commit d18ee05
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 78 deletions.
18 changes: 10 additions & 8 deletions mpc-recovery/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use near_jsonrpc_client::{methods, JsonRpcClient, MethodCallResult};
use near_jsonrpc_primitives::types::query::QueryResponseKind;
use near_primitives::hash::CryptoHash;
use near_primitives::transaction::SignedTransaction;
use near_primitives::types::{AccountId, Finality};
use near_primitives::types::{AccountId, BlockHeight, Finality};
use near_primitives::views::{AccessKeyView, FinalExecutionOutcomeView, QueryRequest};

#[derive(Clone)]
Expand Down Expand Up @@ -42,7 +42,8 @@ impl NearRpcClient {
}
}

async fn query_broadcast_tx(
// TODO: delete this function if we will use reqest to communicate with the relayer
async fn _query_broadcast_tx(
&self,
method: &methods::broadcast_tx_commit::RpcBroadcastTxCommitRequest,
) -> MethodCallResult<
Expand Down Expand Up @@ -80,22 +81,23 @@ impl NearRpcClient {
Ok(key.0.nonce)
}

pub async fn latest_block_hash(&self) -> anyhow::Result<CryptoHash> {
pub async fn latest_block_height(&self) -> anyhow::Result<BlockHeight> {
let block_view = self
.rpc_client
.call(&methods::block::RpcBlockRequest {
block_reference: Finality::Final.into(),
})
.await?;
Ok(block_view.header.hash)
Ok(block_view.header.height)
}

pub async fn send_tx(
// TODO: delete this function if we will use reqest to communicate with the relayer
pub async fn _send_tx(
&self,
signed_transaction: SignedTransaction,
) -> anyhow::Result<FinalExecutionOutcomeView> {
let result = self
.query_broadcast_tx(&methods::broadcast_tx_commit::RpcBroadcastTxCommitRequest {
._query_broadcast_tx(&methods::broadcast_tx_commit::RpcBroadcastTxCommitRequest {
signed_transaction,
})
.await?;
Expand All @@ -111,9 +113,9 @@ mod tests {
#[tokio::test]
async fn test_latest_block() -> anyhow::Result<()> {
let testnet = NearRpcClient::testnet();
let block_hash = testnet.latest_block_hash().await?;
let block_height = testnet.latest_block_height().await?;

assert!(block_hash.0.len() == 32);
assert!(block_height > 0);
Ok(())
}

Expand Down
49 changes: 27 additions & 22 deletions mpc-recovery/src/leader_node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::msg::{
use crate::oauth::{OAuthTokenVerifier, UniversalTokenVerifier};
use crate::primitives::InternalAccountId;
use crate::transaction::{
new_add_fa_key_transaction, new_create_account_transaction, sign_transaction,
get_add_key_delegate_action, get_create_account_delegate_action, get_signed_delegated_action,
};
use crate::NodeId;
use axum::{http::StatusCode, routing::post, Extension, Json, Router};
Expand Down Expand Up @@ -109,26 +109,28 @@ async fn process_new_account(
.client
.access_key_nonce(account_creator_id.clone(), account_creator_pk.clone())
.await?;
let block_hash = state.client.latest_block_hash().await?;
let block_height = state.client.latest_block_height().await?;

// Create a transaction to create new NEAR account
let new_user_account_id: AccountId = request.account_id.clone().parse().unwrap();
let internal_user_id: InternalAccountId = "tmp".parse().unwrap(); // TODO:get real user id from ID token
let create_acc_tx = new_create_account_transaction(
new_user_account_id,
get_user_recovery_pk(internal_user_id),

let delegate_action = get_create_account_delegate_action(
account_creator_id.clone(),
account_creator_pk,
nonce,
block_hash,
new_user_account_id,
get_user_recovery_pk(internal_user_id),
crate::transaction::NetworkType::Testnet,
nonce,
block_height + 100,
);
let _signed_delegate_action =
get_signed_delegated_action(delegate_action, account_creator_id, account_creator_sk);

// Sign the transaction
let signed_create_acc_tx =
sign_transaction(create_acc_tx, account_creator_id, account_creator_sk);

state.client.send_tx(signed_create_acc_tx).await?;
// Send the transaction to the relayer
// TODO: currently client doesn't support sending delegated actions to the relayer,
// use request directly or add support to the client
// state.client.send_tx(signed_create_acc_tx).await?;

Ok((StatusCode::OK, Json(NewAccountResponse::Ok)))
}
Expand Down Expand Up @@ -186,26 +188,29 @@ async fn process_add_key(
get_user_recovery_pk(internal_user_id.clone()).clone(),
)
.await?;
let block_hash = state.client.latest_block_hash().await?;
let block_height = state.client.latest_block_height().await?;

// Create a transaction to create a new account
let new_user_pk: PublicKey = request.public_key.clone().parse().unwrap();
let add_key_tx = new_add_fa_key_transaction(

let max_block_height: u64 = block_height + 100;

let delegate_action = get_add_key_delegate_action(
user_account_id.clone(),
get_user_recovery_pk(internal_user_id.clone()),
new_user_pk,
nonce,
block_hash,
max_block_height,
);

// Sign the transaction
let signed_add_key_tx = sign_transaction(
add_key_tx,
let _signed_delegate_action = get_signed_delegated_action(
delegate_action,
user_account_id,
get_user_recovery_sk(internal_user_id),
get_user_recovery_sk(internal_user_id.clone()),
);

state.client.send_tx(signed_add_key_tx).await?;
// Send the transaction to the relayer
// TODO: currently client doesn't support sending delegated actions to the relayer,
// use request directly or add support to the client
// state.client.send_tx(signed_add_key_tx).await?;

Ok((StatusCode::OK, Json(AddKeyResponse::Ok)))
}
Expand Down
110 changes: 62 additions & 48 deletions mpc-recovery/src/transaction.rs
Original file line number Diff line number Diff line change
@@ -1,78 +1,92 @@
use near_crypto::{InMemorySigner, PublicKey, SecretKey};
use near_primitives::account::{AccessKey, AccessKeyPermission};
use near_primitives::hash::CryptoHash;
use near_primitives::transaction::{
Action, AddKeyAction, FunctionCallAction, SignedTransaction, Transaction,
};
use near_primitives::transaction::{Action, AddKeyAction, FunctionCallAction};
use near_primitives::types::{AccountId, Nonce};

use near_primitives::delegate_action::{DelegateAction, NonDelegateAction, SignedDelegateAction};
use near_primitives::signable_message::{SignableMessage, SignableMessageType};

use serde_json::json;

pub enum NetworkType {
_Mainnet,
Testnet,
}

pub fn new_create_account_transaction(
new_account_id: AccountId,
user_pk: PublicKey,
pub fn get_create_account_delegate_action(
signer_id: AccountId,
signer_pk: PublicKey,
nonce: Nonce,
block_hash: CryptoHash,
new_account_id: AccountId,
new_account_pk: PublicKey,
network_type: NetworkType,
) -> Transaction {
Transaction {
signer_id,
public_key: signer_pk,
nonce,
nonce: Nonce,
max_block_height: u64,
) -> DelegateAction {
let create_acc_action = Action::FunctionCall(FunctionCallAction {
method_name: "create_account".to_string(),
args: json!({
"new_account_id": new_account_id,
"new_public_key": new_account_pk.to_string(),
})
.to_string()
.into_bytes(),
gas: 300_000_000_000_000,
deposit: 0,
});

let delegate_create_acc_action = NonDelegateAction::try_from(create_acc_action).unwrap();

DelegateAction {
sender_id: signer_id,
receiver_id: match network_type {
NetworkType::_Mainnet => "near".parse().unwrap(),
NetworkType::Testnet => "testnet".parse().unwrap(),
},
block_hash,
actions: vec![Action::FunctionCall(FunctionCallAction {
method_name: "create_account".to_string(),
args: json!({
"new_account_id": new_account_id,
"new_public_key": user_pk.to_string(),
})
.to_string()
.into_bytes(),
gas: 300_000_000_000_000,
deposit: 0,
})],
actions: vec![delegate_create_acc_action],
nonce,
max_block_height,
public_key: signer_pk,
}
}

pub fn new_add_fa_key_transaction(
account_id: AccountId,
existing_pk: PublicKey,
new_pk: PublicKey,
pub fn get_add_key_delegate_action(
sender_id: AccountId,
public_key: PublicKey,
nonce: Nonce,
block_hash: CryptoHash,
) -> Transaction {
Transaction {
signer_id: account_id.clone(),
public_key: existing_pk,
max_block_height: u64,
) -> DelegateAction {
let add_key_action = Action::AddKey(AddKeyAction {
public_key: public_key.clone(),
access_key: AccessKey {
nonce: 0,
permission: AccessKeyPermission::FullAccess,
},
});

let delegate_add_key_action = NonDelegateAction::try_from(add_key_action).unwrap();

DelegateAction {
sender_id: sender_id.clone(),
receiver_id: sender_id,
actions: vec![delegate_add_key_action],
nonce,
receiver_id: account_id,
block_hash,
actions: vec![Action::AddKey(AddKeyAction {
public_key: new_pk,
access_key: AccessKey {
nonce: 0,
permission: AccessKeyPermission::FullAccess,
},
})],
max_block_height,
public_key,
}
}

pub fn sign_transaction(
transaction: Transaction,
pub fn get_signed_delegated_action(
delegate_action: DelegateAction,
signer_id: AccountId,
signer_sk: SecretKey,
) -> SignedTransaction {
) -> SignedDelegateAction {
let signer = InMemorySigner::from_secret_key(signer_id, signer_sk);
transaction.sign(&signer)
let signable_message =
SignableMessage::new(&delegate_action, SignableMessageType::DelegateAction);
let signature = signable_message.sign(&signer);

SignedDelegateAction {
delegate_action,
signature,
}
}

0 comments on commit d18ee05

Please sign in to comment.