Skip to content

Commit

Permalink
kairos-server: add deposit mock handler
Browse files Browse the repository at this point in the history
  • Loading branch information
marijanp committed May 23, 2024
1 parent d335a35 commit 541f23e
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 97 deletions.
3 changes: 2 additions & 1 deletion kairos-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ name = "kairos-server"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
all-tests = ["cctl-tests"]
all-tests = ["cctl-tests", "deposit-mock"]
cctl-tests = []
deposit-mock = []

[dependencies]
dotenvy = "0.15"
Expand Down
11 changes: 11 additions & 0 deletions kairos-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use crate::state::{BatchStateManager, ServerState, ServerStateInner};
type PublicKey = Vec<u8>;
type Signature = Vec<u8>;

#[cfg(not(feature = "deposit-mock"))]
pub fn app_router(state: ServerState) -> Router {
Router::new()
.typed_post(routes::deposit_handler)
Expand All @@ -26,6 +27,16 @@ pub fn app_router(state: ServerState) -> Router {
.with_state(state)
}

#[cfg(feature = "deposit-mock")]
pub fn app_router(state: ServerState) -> Router {
Router::new()
.typed_post(routes::deposit_handler)
.typed_post(routes::withdraw_handler)
.typed_post(routes::transfer_handler)
.typed_post(routes::deposit_mock_handler)
.with_state(state)
}

pub async fn run(config: ServerConfig) {
let listener = tokio::net::TcpListener::bind(config.socket_addr)
.await
Expand Down
51 changes: 51 additions & 0 deletions kairos-server/src/routes/deposit_mock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use anyhow::{anyhow, Context};
use axum::{extract::State, http::StatusCode, Json};
use axum_extra::routing::TypedPath;
use tracing::*;

use kairos_tx::asn::{SigningPayload, TransactionBody};

use crate::{
routes::PayloadBody,
state::{
transactions::{Signed, Transaction},
ServerState,
},
AppErr,
};

#[derive(TypedPath, Debug, Clone, Copy)]
#[typed_path("/api/v1/deposit-mock")]
pub struct MockDepositPath;

#[instrument(level = "trace", skip(state), ret)]
pub async fn deposit_mock_handler(
_: MockDepositPath,
state: State<ServerState>,
Json(body): Json<PayloadBody>,
) -> Result<(), AppErr> {
tracing::info!("parsing transaction data");
let signing_payload: SigningPayload =
body.payload.as_slice().try_into().context("payload err")?;
let deposit = match signing_payload.body {
TransactionBody::Deposit(deposit) => deposit.try_into().context("decoding deposit")?,
_ => {
return Err(AppErr::set_status(
anyhow!("invalid transaction type"),
StatusCode::BAD_REQUEST,
))
}
};

let public_key = body.public_key;
let nonce = signing_payload.nonce.try_into().context("decoding nonce")?;

state
.batch_state_manager
.enqueue_transaction(Signed {
public_key,
nonce,
transaction: Transaction::Deposit(deposit),
})
.await
}
4 changes: 4 additions & 0 deletions kairos-server/src/routes/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
pub mod deposit;
#[cfg(feature = "deposit-mock")]
pub mod deposit_mock;
pub mod transfer;
pub mod withdraw;

pub use deposit::deposit_handler;
#[cfg(feature = "deposit-mock")]
pub use deposit_mock::deposit_mock_handler;
pub use transfer::transfer_handler;
pub use withdraw::withdraw_handler;

Expand Down
146 changes: 50 additions & 96 deletions kairos-server/tests/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,26 @@ use casper_types::{
};
use kairos_server::{
config::ServerConfig,
routes::{deposit::DepositPath, transfer::TransferPath, withdraw::WithdrawPath, PayloadBody},
routes::deposit::DepositPath,
state::{BatchStateManager, ServerStateInner},
};
use kairos_test_utils::cctl::CCTLNetwork;
use kairos_tx::asn::{SigningPayload, Transfer, Withdrawal};
use reqwest::Url;
use tracing_subscriber::{prelude::*, EnvFilter};

#[cfg(feature = "deposit-mock")]
use kairos_tx::asn::{SigningPayload, Transfer, Withdrawal};
#[cfg(feature = "deposit-mock")]
use kairos_server::routes::{deposit_mock::MockDepositPath, transfer::TransferPath, withdraw::WithdrawPath, PayloadBody};

static TEST_ENVIRONMENT: OnceLock<()> = OnceLock::new();


#[cfg(feature = "deposit-mock")]
fn new_test_app() -> TestServer {
new_test_app_with_casper_node(&Url::parse("http://0.0.0.0:0").unwrap())
}

fn new_test_app_with_casper_node(casper_node_url: &Url) -> TestServer {
TEST_ENVIRONMENT.get_or_init(|| {
tracing_subscriber::registry()
Expand Down Expand Up @@ -84,50 +94,33 @@ async fn test_signed_deploy_is_forwarded_if_sender_in_approvals() {
}

#[tokio::test]
#[cfg_attr(not(feature = "cctl-tests"), ignore)]
#[cfg(feature = "deposit-mock")]
async fn test_deposit_withdraw() {
let network = CCTLNetwork::run().await.unwrap();
let node = network
.nodes
.first()
.expect("Expected at least one node after successful network run");
let casper_node_url =
Url::parse(&format!("http://localhost:{}/rpc", node.port.rpc_port)).unwrap();
let server = new_test_app();

let server = new_test_app_with_casper_node(&casper_node_url);

// DeployBuilder::build, calls Deploy::new, which calls Deploy::sign
let deposit_deploy = DeployBuilder::new_transfer(
"cspr-dev-cctl",
5_000_000_000u64,
// Option::None use the accounts main purse
Option::None,
TransferTarget::PublicKey(PublicKey::generate_ed25519().unwrap()),
Option::None,
&SecretKey::generate_ed25519().unwrap(),
)
.with_timestamp(Timestamp::now())
.with_standard_payment(5_000_000_000u64)
.build()
.unwrap();
let deposit = PayloadBody {
public_key: "alice_key".into(),
payload: SigningPayload::new_deposit(100).try_into().unwrap(),
signature: vec![],
};

// no arguments
server
.post(DepositPath.to_uri().path())
.post(MockDepositPath.to_uri().path())
.await
.assert_status_failure();

// deposit
server
.post(DepositPath.to_uri().path())
.json(&deposit_deploy)
.post(MockDepositPath.to_uri().path())
.json(&deposit)
.await
.assert_status_success();

// wrong arguments
server
.post(WithdrawPath.to_uri().path())
.json(&deposit_deploy)
.json(&deposit)
.await
.assert_status_failure();

Expand All @@ -136,7 +129,7 @@ async fn test_deposit_withdraw() {
.post(WithdrawPath.to_uri().path())
.json(&PayloadBody {
public_key: "alice_key".into(),
payload: SigningPayload::new(0, Withdrawal::new(2_500_000_000u64))
payload: SigningPayload::new(0, Withdrawal::new(50))
.try_into()
.unwrap(),
signature: vec![],
Expand All @@ -149,7 +142,7 @@ async fn test_deposit_withdraw() {
.post(WithdrawPath.to_uri().path())
.json(&PayloadBody {
public_key: "alice_key".into(),
payload: SigningPayload::new(1, Withdrawal::new(2_600_000_000u64))
payload: SigningPayload::new(1, Withdrawal::new(51))
.der_encode()
.unwrap(),
signature: vec![],
Expand All @@ -162,7 +155,7 @@ async fn test_deposit_withdraw() {
.post(WithdrawPath.to_uri().path())
.json(&PayloadBody {
public_key: "alice_key".into(),
payload: SigningPayload::new(1, Withdrawal::new(2_500_000_000u64))
payload: SigningPayload::new(1, Withdrawal::new(50))
.try_into()
.unwrap(),
signature: vec![],
Expand All @@ -184,37 +177,19 @@ async fn test_deposit_withdraw() {
}

#[tokio::test]
#[cfg_attr(not(feature = "cctl-tests"), ignore)]
#[cfg(feature = "deposit-mock")]
async fn test_deposit_transfer_withdraw() {
let network = CCTLNetwork::run().await.unwrap();
let node = network
.nodes
.first()
.expect("Expected at least one node after successful network run");
let casper_node_url =
Url::parse(&format!("http://localhost:{}/rpc", node.port.rpc_port)).unwrap();

let server = new_test_app_with_casper_node(&casper_node_url);

// DeployBuilder::build, calls Deploy::new, which calls Deploy::sign
let deposit_deploy = DeployBuilder::new_transfer(
"cspr-dev-cctl",
5_000_000_000u64,
// Option::None use the accounts main purse
Option::None,
TransferTarget::PublicKey(PublicKey::generate_ed25519().unwrap()),
Option::None,
&SecretKey::generate_ed25519().unwrap(),
)
.with_timestamp(Timestamp::now())
.with_standard_payment(5_000_000_000u64)
.build()
.unwrap();
let server = new_test_app();

// deposit
server
.post(DepositPath.to_uri().path())
.json(&deposit_deploy)
.post(MockDepositPath.to_uri().path())
.json(&PayloadBody {
public_key: "alice_key".into(),
// deposit's don't have a defined nonce
payload: SigningPayload::new_deposit(100).try_into().unwrap(),
signature: vec![],
})
.await
.assert_status_success();

Expand All @@ -223,7 +198,7 @@ async fn test_deposit_transfer_withdraw() {
.post(TransferPath.to_uri().path())
.json(&PayloadBody {
public_key: "alice_key".into(),
payload: SigningPayload::new(0, Transfer::new("bob_key".as_bytes(), 2_500_000_000u64))
payload: SigningPayload::new(0, Transfer::new("bob_key".as_bytes(), 50))
.try_into()
.unwrap(),
signature: vec![],
Expand All @@ -236,7 +211,7 @@ async fn test_deposit_transfer_withdraw() {
.post(WithdrawPath.to_uri().path())
.json(&PayloadBody {
public_key: "bob_key".into(),
payload: SigningPayload::new(0, Withdrawal::new(2_500_000_000u64))
payload: SigningPayload::new(0, Withdrawal::new(50))
.try_into()
.unwrap(),
signature: vec![],
Expand All @@ -246,37 +221,19 @@ async fn test_deposit_transfer_withdraw() {
}

#[tokio::test]
#[cfg_attr(not(feature = "cctl-tests"), ignore)]
#[cfg(feature = "deposit-mock")]
async fn test_deposit_transfer_to_self_withdraw() {
let network = CCTLNetwork::run().await.unwrap();
let node = network
.nodes
.first()
.expect("Expected at least one node after successful network run");
let casper_node_url =
Url::parse(&format!("http://localhost:{}/rpc", node.port.rpc_port)).unwrap();

let server = new_test_app_with_casper_node(&casper_node_url);

// DeployBuilder::build, calls Deploy::new, which calls Deploy::sign
let deposit_deploy = DeployBuilder::new_transfer(
"cspr-dev-cctl",
2_500_000_000u64,
// Option::None use the accounts main purse
Option::None,
TransferTarget::PublicKey(PublicKey::generate_ed25519().unwrap()),
Option::None,
&SecretKey::generate_ed25519().unwrap(),
)
.with_timestamp(Timestamp::now())
.with_standard_payment(2_500_000_000u64)
.build()
.unwrap();
let server = new_test_app();

// deposit
server
.post(DepositPath.to_uri().path())
.json(&deposit_deploy)
.post(MockDepositPath.to_uri().path())
.json(&PayloadBody {
public_key: "alice_key".into(),
// deposit's don't have a defined nonce
payload: SigningPayload::new_deposit(1000).try_into().unwrap(),
signature: vec![],
})
.await
.assert_status_success();

Expand All @@ -285,12 +242,9 @@ async fn test_deposit_transfer_to_self_withdraw() {
.post(TransferPath.to_uri().path())
.json(&PayloadBody {
public_key: "alice_key".into(),
payload: SigningPayload::new(
0,
Transfer::new("alice_key".as_bytes(), 2_500_000_000u64),
)
.try_into()
.unwrap(),
payload: SigningPayload::new(0, Transfer::new("alice_key".as_bytes(), 1000))
.try_into()
.unwrap(),
signature: vec![],
})
.await
Expand All @@ -301,7 +255,7 @@ async fn test_deposit_transfer_to_self_withdraw() {
.post(WithdrawPath.to_uri().path())
.json(&PayloadBody {
public_key: "alice_key".into(),
payload: SigningPayload::new(1, Withdrawal::new(2_500_000_000u64))
payload: SigningPayload::new(1, Withdrawal::new(1000))
.try_into()
.unwrap(),
signature: vec![],
Expand Down

0 comments on commit 541f23e

Please sign in to comment.