Skip to content

Commit

Permalink
[faucet] revert recent changes to get to a known kinda clean state
Browse files Browse the repository at this point in the history
  • Loading branch information
davidiw authored and aptos-bot committed Mar 15, 2022
1 parent d1874e3 commit b0e6b3e
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 297 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

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

4 changes: 1 addition & 3 deletions crates/aptos-faucet/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
Faucet is a service for creating and funding accounts on the Aptos Network.
It is meant to be used for devnets and testnets.

During startup, by default, the Faucet will use the root key to create a new account, fund it, give it permissions to
mint, and use that new account to mint from. To avoid this behaviour, you can pass `--do-not-delgate`.

## Mint API

Expand All @@ -31,7 +29,7 @@ Notes:

### Response

If the query param `return_txns` is not provided, or it is not "true", the server returns a json-encoded list of transaction hash values. These can be used to monitor the status of submitted transactions.
If the query param `return_txns` is not provided, or it is not "true", the server returns a json-encoded list of transaction has values. These can be used to monitor the status of submitted transactions.

If the query param `return_txns` is set, the server will respond with the transactions for creating and funding your account.
The response HTTP body is hex encoded bytes of BCS encoded `Vec<aptos_types::transaction::SignedTransaction>`.
Expand Down
203 changes: 54 additions & 149 deletions crates/aptos-faucet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,20 @@ use aptos_sdk::{
};
use reqwest::StatusCode;
use serde::Deserialize;
use std::{convert::Infallible, fmt, ops::DerefMut, sync::Arc};
use tokio::sync::Mutex;

use std::{
convert::Infallible,
fmt,
sync::{Arc, Mutex},
};
use url::Url;
use warp::{Filter, Rejection, Reply};

pub mod mint;

pub struct Service {
pub faucet_account: Arc<Mutex<LocalAccount>>,
pub transaction_factory: TransactionFactory,
pub client: Client,
pub faucet_account: Mutex<LocalAccount>,
transaction_factory: TransactionFactory,
client: Client,
endpoint: String,
maximum_amount: Option<u64>,
}
Expand All @@ -59,14 +61,13 @@ impl Service {
chain_id: ChainId,
faucet_account: LocalAccount,
maximum_amount: Option<u64>,
transaction_timeout: u64,
) -> Self {
let client = Client::new(Url::parse(&endpoint).expect("Invalid rest endpoint"));
Service {
faucet_account: Arc::new(Mutex::new(faucet_account)),
faucet_account: Mutex::new(faucet_account),
transaction_factory: TransactionFactory::new(chain_id)
.with_gas_unit_price(1)
.with_transaction_expiration_time(transaction_timeout),
.with_transaction_expiration_time(30),
client,
endpoint,
maximum_amount,
Expand Down Expand Up @@ -114,7 +115,7 @@ fn health_route(
}

async fn handle_health(service: Arc<Service>) -> Result<Box<dyn warp::Reply>, Infallible> {
let faucet_address = service.faucet_account.lock().await.address();
let faucet_address = service.faucet_account.lock().unwrap().address();
let faucet_account = service.client.get_account(faucet_address).await;

match faucet_account {
Expand All @@ -132,95 +133,6 @@ fn accounts_routes(
create_account_route(service.clone()).or(fund_account_route(service))
}

pub async fn delegate_account(
service: Arc<Service>,
server_url: String,
chain_id: ChainId,
maximum_amount: Option<u64>,
transaction_timeout: u64,
) -> Arc<Service> {
// Create a new random account, then delegate to it
let delegated_account = LocalAccount::generate(&mut rand::rngs::OsRng);
// Create the account
service
.client
.wait_for_signed_transaction(
&create_account(
service.clone(),
CreateAccountParams {
pub_key: delegated_account.public_key().clone(),
},
)
.await
.unwrap(),
)
.await
.unwrap();

// Give the new account some moolah
service
.client
.wait_for_signed_transaction(
// we hold the world ransom for one... hundred... billion... dollars
&fund_account_unchecked(
service.clone(),
delegated_account.address(),
100_000_000_000,
)
.await
.unwrap(),
)
.await
.unwrap();

let service = {
let mut faucet_account = service.faucet_account.lock().await;
get_and_update_seq_no(&service, faucet_account.deref_mut())
.await
.unwrap();
// Delegate minting to the account
service
.client
.submit_and_wait(&faucet_account.sign_with_transaction_builder(
service.transaction_factory.payload(
aptos_stdlib::encode_delegate_mint_capability_script_function(
delegated_account.address(),
),
),
))
.await
.unwrap();

Arc::new(Service::new(
server_url,
chain_id,
delegated_account,
maximum_amount,
transaction_timeout,
))
};
{
let mut faucet_account = service.faucet_account.lock().await;
get_and_update_seq_no(&service, faucet_account.deref_mut())
.await
.unwrap();

// claim the capability!
service
.client
.submit_and_wait(
&faucet_account.sign_with_transaction_builder(
service
.transaction_factory
.payload(aptos_stdlib::encode_claim_mint_capability_script_function()),
),
)
.await
.unwrap();
}
service
}

#[derive(Deserialize)]
struct CreateAccountParams {
pub_key: Ed25519PublicKey,
Expand Down Expand Up @@ -266,21 +178,33 @@ async fn create_account(
if service.client.get_account(params.receiver()).await.is_ok() {
return Err(anyhow!("account already exists"));
}
let mut faucet_account = service.faucet_account.lock().await;
let faucet_seq = get_and_update_seq_no(&service, faucet_account.deref_mut()).await?;

let txn = faucet_account.sign_with_transaction_builder(service.transaction_factory.payload(
aptos_stdlib::encode_create_account_script_function(
params.receiver(),
params.pre_image().into_vec(),
),
));
let resp = service.client.submit(&txn).await;
// If there was an issue submitting a transaction we should just reset our sequence_numbers to what was on chain
if resp.is_err() {
*faucet_account.sequence_number_mut() = faucet_seq;
resp?;
}

let faucet_account_address = service.faucet_account.lock().unwrap().address();
let faucet_sequence_number = service
.client
.get_account(faucet_account_address)
.await
.map_err(|_| anyhow::format_err!("faucet account {} not found", faucet_account_address))?
.into_inner()
.sequence_number;

let txn = {
let mut faucet_account = service.faucet_account.lock().unwrap();
if faucet_sequence_number > faucet_account.sequence_number() {
*faucet_account.sequence_number_mut() = faucet_sequence_number;
}

let builder = service.transaction_factory.payload(
aptos_stdlib::encode_create_account_script_function(
params.receiver(),
params.pre_image().into_vec(),
),
);

faucet_account.sign_with_transaction_builder(builder)
};

service.client.submit(&txn).await?;
Ok(txn)
}

Expand Down Expand Up @@ -323,42 +247,13 @@ async fn fund_account(
.ok_or_else(|| anyhow::format_err!("Mint amount must be provided"))?;
let service_amount = service.maximum_amount.unwrap_or(asked_amount);
let amount = std::cmp::min(asked_amount, service_amount);
fund_account_unchecked(service, address, amount).await
}

pub(crate) async fn fund_account_unchecked(
service: Arc<Service>,
address: AccountAddress,
amount: u64,
) -> Result<SignedTransaction> {
// Check to ensure the account has already been created
if service.client.get_account(address).await.is_err() {
return Err(anyhow!("account doesn't exist"));
}

let mut faucet_account = service.faucet_account.lock().await;
let faucet_seq = get_and_update_seq_no(&service, faucet_account.deref_mut()).await?;

let txn = faucet_account.sign_with_transaction_builder(
service
.transaction_factory
.payload(aptos_stdlib::encode_mint_script_function(address, amount)),
);

let resp = service.client.submit(&txn).await;
// If there was an issue submitting a transaction we should just reset our sequence_numbers to what was on chain
if resp.is_err() {
*faucet_account.sequence_number_mut() = faucet_seq;
resp?;
}
Ok(txn)
}

pub(crate) async fn get_and_update_seq_no(
service: &Service,
faucet_account: &mut LocalAccount,
) -> Result<u64> {
let faucet_account_address = faucet_account.address();
let faucet_account_address = service.faucet_account.lock().unwrap().address();
let faucet_sequence_number = service
.client
.get_account(faucet_account_address)
Expand All @@ -367,11 +262,21 @@ pub(crate) async fn get_and_update_seq_no(
.into_inner()
.sequence_number;

// If the onchain sequence_number is greater than what we have, update our sequence_numbers
if faucet_sequence_number > faucet_account.sequence_number() {
*faucet_account.sequence_number_mut() = faucet_sequence_number;
}
Ok(faucet_sequence_number)
let txn = {
let mut faucet_account = service.faucet_account.lock().unwrap();
if faucet_sequence_number > faucet_account.sequence_number() {
*faucet_account.sequence_number_mut() = faucet_sequence_number;
}

faucet_account.sign_with_transaction_builder(
service
.transaction_factory
.payload(aptos_stdlib::encode_mint_script_function(address, amount)),
)
};

service.client.submit(&txn).await?;
Ok(txn)
}

//
Expand Down
45 changes: 8 additions & 37 deletions crates/aptos-faucet/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use aptos_faucet::delegate_account;
use aptos_logger::info;
use aptos_sdk::types::{
account_address::AccountAddress, account_config::aptos_root_address, chain_id::ChainId,
Expand Down Expand Up @@ -46,14 +45,6 @@ struct Args {
/// Maximum amount of coins to mint.
#[structopt(long)]
pub maximum_amount: Option<u64>,
/// If this is set, the faucet will use the root key to mint from,
/// instead of creating a new account, giving it permissions to mint,
/// and using that one.
#[structopt(short = "d", long)]
pub do_not_delegate: bool,
/// How long should faucet transactions wait in mempool before dying?
#[structopt(short = "o", long, default_value = "30")]
pub transaction_timeout: u64,
}

#[tokio::main]
Expand All @@ -77,36 +68,17 @@ async fn main() {
let faucet_address: AccountAddress =
args.mint_account_address.unwrap_or_else(aptos_root_address);
let faucet_account = LocalAccount::new(faucet_address, key, 0);

let mut service = Arc::new(aptos_faucet::Service::new(
args.server_url.clone(),
let service = Arc::new(aptos_faucet::Service::new(
args.server_url,
args.chain_id,
faucet_account,
args.maximum_amount,
args.transaction_timeout,
));

if !args.do_not_delegate {
service = delegate_account(
service,
args.server_url,
args.chain_id,
args.maximum_amount,
args.transaction_timeout,
)
.await;
let faucet_address = service.faucet_account.lock().await.address();
info!(
"[faucet]: running on: {}. Minting from {} via delegation",
address, faucet_address
);
} else {
info!(
"[faucet]: running on: {}. Minting from {}",
address, faucet_address
);
}

info!(
"[faucet]: running on: {}. Minting from {}",
address, faucet_address
);
warp::serve(aptos_faucet::routes(service))
.run(address)
.await;
Expand Down Expand Up @@ -206,7 +178,6 @@ mod tests {
chain_id,
faucet_account,
maximum_amount,
30,
);
(accounts, Arc::new(service))
}
Expand Down Expand Up @@ -411,17 +382,17 @@ mod tests {
#[tokio::test]
async fn test_mint_fullnode_error() {
let (accounts, service) = setup(None);
let address = service.faucet_account.lock().await.address();
let address = service.faucet_account.lock().unwrap().address();
accounts.write().remove(&address);
let filter = routes(service);
// assert_eq!("".to_string(), format!("{:?} - {}", &accounts, &address));

let pub_key = "459c77a38803bd53f3adee52703810e3a74fd7c46952c497e75afb0a7932586d";
let resp = warp::test::request()
.method("POST")
.path(format!("/mint?pub_key={}&amount=1000000", pub_key).as_str())
.reply(&filter)
.await;

assert_eq!(
resp.body(),
&format!("faucet account {:?} not found", address)
Expand Down
Loading

0 comments on commit b0e6b3e

Please sign in to comment.