Skip to content

Commit

Permalink
Merge branch 'main' into feature/allow-unaccelerated-proving
Browse files Browse the repository at this point in the history
  • Loading branch information
koxu1996 authored Jul 25, 2024
2 parents b5d9165 + 0ec66d0 commit 154471a
Show file tree
Hide file tree
Showing 11 changed files with 182 additions and 125 deletions.
2 changes: 1 addition & 1 deletion kairos-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
default = ["demo"]
default = ["demo", "database"]
all-tests = ["cctl-tests", "database"]
cctl-tests = []
demo = ["dep:kairos-test-utils", "dep:tokio", "dep:dotenvy"]
Expand Down
2 changes: 1 addition & 1 deletion kairos-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ name = "kairos-server"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
default = ["cctl-tests", "deposit-mock"]
default = ["cctl-tests", "deposit-mock", "database"]
all-tests = ["cctl-tests", "deposit-mock", "database"]
cctl-tests = []
deposit-mock = []
Expand Down
2 changes: 1 addition & 1 deletion kairos-server/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl ServerConfig {
}
}
None => {
tracing::warn!("No secret key file provided. This server will not be able to sign or send depolys.");
tracing::warn!("No secret key file provided. This server will not be able to sign batch deploys.");
}
}
let kairos_demo_contract_hash = parse_env_as::<String>("KAIROS_SERVER_DEMO_CONTRACT_HASH")
Expand Down
12 changes: 12 additions & 0 deletions kairos-server/src/l1_sync/event_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use casper_event_toolkit::rpc::client::CasperClient;

use crate::state::ServerStateInner;
use kairos_circuit_logic::transactions::{KairosTransaction, L1Deposit};
#[cfg(feature = "database")]
use kairos_data::transaction as db;

use super::error::L1SyncError;

Expand Down Expand Up @@ -69,6 +71,16 @@ impl EventManager {
let recipient: Vec<u8> = deposit.recipient;
let txn = KairosTransaction::Deposit(L1Deposit { amount, recipient });

#[cfg(feature = "database")]
db::insert(&self.server_state.pool, txn.clone())
.await
.map_err(|e| {
L1SyncError::UnexpectedError(format!(
"Failed to add to database: {}",
e
))
})?;

// Push deposit to trie.
self.server_state
.batch_state_manager
Expand Down
25 changes: 11 additions & 14 deletions kairos-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,22 @@ use kairos_data::new as new_pool;
pub type PublicKey = Vec<u8>;
type Signature = Vec<u8>;

#[cfg(not(feature = "deposit-mock"))]
pub fn app_router(state: ServerState) -> Router {
Router::new()
let mut router = Router::new()
.typed_post(routes::deposit_handler)
.typed_post(routes::withdraw_handler)
.typed_post(routes::transfer_handler)
.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)
.typed_post(routes::get_nonce_handler)
.typed_get(routes::contract_hash_handler)
.with_state(state)
.typed_get(routes::contract_hash_handler);
#[cfg(feature = "deposit-mock")]
{
router = router.typed_post(routes::deposit_mock_handler)
}
#[cfg(feature = "database")]
{
router = router.typed_post(routes::query_transactions_handler);
}
router.with_state(state)
}

pub async fn run_l1_sync(server_state: Arc<ServerStateInner>) {
Expand Down
2 changes: 2 additions & 0 deletions kairos-server/src/routes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ pub use contract_hash::contract_hash_handler;
pub use deposit::deposit_handler;
#[cfg(feature = "deposit-mock")]
pub use deposit_mock::deposit_mock_handler;
#[cfg(feature = "database")]
pub use fetch::query_transactions_handler;
pub use get_nonce::get_nonce_handler;
pub use transfer::transfer_handler;
pub use withdraw::withdraw_handler;
Expand Down
1 change: 1 addition & 0 deletions kairos-test-utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ bench = false
[features]
# FIXME enable cctl-tests once this crate is factored out in a separate repository
#all-tests = ["cctl-tests"]
default = ["database"]
all-tests = ["database"]
cctl-tests = []
database = ["kairos-server/database"]
Expand Down
180 changes: 81 additions & 99 deletions kairos-test-utils/src/cctl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use casper_client::{
};
use casper_client_types::{ContractHash, ExecutionResult, Key, PublicKey, RuntimeArgs, SecretKey};
use hex::FromHex;
use rand::Rng;
use std::io::{self, Write};
use std::path::Path;
use std::path::PathBuf;
Expand Down Expand Up @@ -51,6 +50,16 @@ pub struct DeployableContract {
pub path: PathBuf,
}

pub fn casper_client_verbosity() -> Verbosity {
if tracing::enabled!(tracing::Level::TRACE) {
Verbosity::High
} else if tracing::enabled!(tracing::Level::DEBUG) {
Verbosity::Medium
} else {
Verbosity::Low
}
}

// max amount allowed to be used on gas fees
pub const MAX_GAS_FEE_PAYMENT_AMOUNT: u64 = 10_000_000_000_000;

Expand Down Expand Up @@ -137,34 +146,36 @@ impl CCTLNetwork {
tracing::info!("Waiting for network to pass genesis");
retry(ExponentialBackoff::default(), || async {
// This prevents retrying forever even after ctrl-c
let timed_out = start_time.elapsed().as_secs() > 60;

get_node_status(JsonRpcId::Number(1), &casper_node_rpc_url, Verbosity::Low)
.await
.map_err(|err| {
let elapsed = start_time.elapsed().as_secs();
tracing::info!("Running for {elapsed}s, Error: {err:?}");
err
})
.map_err(|err| match &err {
err if timed_out => {
backoff::Error::permanent(anyhow!("Timeout on error: {err:?}"))
}
Error::ResponseIsHttpError { .. } | Error::FailedToGetResponse { .. } => {
backoff::Error::transient(anyhow!(err))
}
_ => backoff::Error::permanent(anyhow!(err)),
})
.map(|success| match success.result.reactor_state {
ReactorState::Validate => Ok(()),
// _ if timed_out => Ok(()),
rs if timed_out => Err(backoff::Error::permanent(anyhow!(
"Node didn't reach the VALIDATE state before timeout: {rs:?}"
))),
_ => Err(backoff::Error::transient(anyhow!(
"Node didn't reach the VALIDATE state yet"
))),
})?
let timed_out = start_time.elapsed().as_secs() > 90;

get_node_status(
JsonRpcId::Number(1),
&casper_node_rpc_url,
casper_client_verbosity(),
)
.await
.map_err(|err| {
let elapsed = start_time.elapsed().as_secs();
tracing::info!("Running for {elapsed}s, Error: {err:?}");
err
})
.map_err(|err| match &err {
err if timed_out => backoff::Error::permanent(anyhow!("Timeout on error: {err:?}")),
Error::ResponseIsHttpError { .. } | Error::FailedToGetResponse { .. } => {
backoff::Error::transient(anyhow!(err))
}
_ => backoff::Error::permanent(anyhow!(err)),
})
.map(|success| match success.result.reactor_state {
ReactorState::Validate => Ok(()),
// _ if timed_out => Ok(()),
rs if timed_out => Err(backoff::Error::permanent(anyhow!(
"Node didn't reach the VALIDATE state before timeout: {rs:?}"
))),
_ => Err(backoff::Error::transient(anyhow!(
"Node didn't reach the VALIDATE state yet"
))),
})?
})
.await
.expect("Waiting for network to pass genesis failed");
Expand Down Expand Up @@ -243,6 +254,8 @@ async fn deploy_contract(
path.to_str().unwrap()
);

let casper_client_verbosity = casper_client_verbosity();

let contract_bytes = fs::read(path)?;
let contract =
ExecutableDeployItem::new_module_bytes(contract_bytes.into(), runtime_args.clone());
Expand All @@ -258,33 +271,25 @@ async fn deploy_contract(
.build()?;

tracing::info!("Submitting contract deploy");
let expected_rpc_id = JsonRpcId::Number(rand::thread_rng().gen::<i64>());
let deploy_hash = put_deploy(
expected_rpc_id.clone(),
JsonRpcId::Number(1),
casper_node_rpc_url,
Verbosity::High,
casper_client_verbosity,
deploy,
)
.await
.map_err(Into::<anyhow::Error>::into)
.and_then(|response| {
if response.id == expected_rpc_id {
Ok(response.result.deploy_hash)
} else {
Err(anyhow!("JSON RPC Id missmatch"))
}
})?;
.map(|response| response.result.deploy_hash)?;

tracing::info!("Waiting for successful contract initialization");
let start = Instant::now();
retry(ExponentialBackoff::default(), || async {
let timed_out = start.elapsed().as_secs() > 60;

let expected_rpc_id = JsonRpcId::Number(rand::thread_rng().gen::<i64>());
let response = get_deploy(
expected_rpc_id.clone(),
JsonRpcId::Number(1),
casper_node_rpc_url,
Verbosity::High,
casper_client_verbosity,
deploy_hash,
false,
)
Expand All @@ -302,96 +307,73 @@ async fn deploy_contract(
_ => backoff::Error::permanent(anyhow!(err)),
})?;

if response.id == expected_rpc_id {
match response.result.execution_results.first() {
Some(result) => match &result.result {
ExecutionResult::Failure { error_message, .. } => {
Err(backoff::Error::permanent(anyhow!(error_message.clone())))
}
ExecutionResult::Success { .. } => Ok(()),
},
None if timed_out => Err(backoff::Error::permanent(anyhow!(
"Timeout on error: No execution results"
))),
None => Err(backoff::Error::transient(anyhow!(
"No execution results there yet"
))),
}
} else {
Err(backoff::Error::permanent(anyhow!("JSON RPC Id missmatch")))
match response.result.execution_results.first() {
Some(result) => match &result.result {
ExecutionResult::Failure { error_message, .. } => {
Err(backoff::Error::permanent(anyhow!(error_message.clone())))
}
ExecutionResult::Success { .. } => Ok(()),
},
None if timed_out => Err(backoff::Error::permanent(anyhow!(
"Timeout on error: No execution results"
))),
None => Err(backoff::Error::transient(anyhow!(
"No execution results there yet"
))),
}
})
.await?;
tracing::info!("Contract was deployed successfully");

tracing::info!("Fetching deployed contract hash");
// Query global state
let expected_rpc_id = JsonRpcId::Number(rand::thread_rng().gen::<i64>());
let state_root_hash = get_state_root_hash(
expected_rpc_id.clone(),
JsonRpcId::Number(1),
casper_node_rpc_url,
Verbosity::High,
casper_client_verbosity,
Option::None,
)
.await
.map_err(Into::<anyhow::Error>::into)
.and_then(|response| {
if response.id == expected_rpc_id {
response
.result
.state_root_hash
.ok_or(anyhow!("No state root hash present in response"))
} else {
Err(anyhow!("JSON RPC Id missmatch"))
}
response
.result
.state_root_hash
.ok_or(anyhow!("No state root hash present in response"))
})?;

let expected_rpc_id = JsonRpcId::Number(rand::thread_rng().gen::<i64>());
let account = get_account(
expected_rpc_id.clone(),
JsonRpcId::Number(1),
casper_node_rpc_url,
Verbosity::High,
casper_client_verbosity,
Option::None,
contract_deployer_pkey.clone(),
)
.await
.map_err(Into::<anyhow::Error>::into)
.and_then(|response| {
if response.id == expected_rpc_id {
Ok(response.result.account)
} else {
Err(anyhow!("JSON RPC Id missmatch"))
}
})?;
.map(|response| response.result.account)?;

let expected_rpc_id = JsonRpcId::Number(rand::thread_rng().gen::<i64>());
let account_key = Key::Account(*account.account_hash());
let contract_hash: casper_client_types::ContractHash = query_global_state(
expected_rpc_id.clone(),
JsonRpcId::Number(1),
casper_node_rpc_url,
Verbosity::High,
casper_client_verbosity,
casper_client::rpcs::GlobalStateIdentifier::StateRootHash(state_root_hash), // fetches recent blocks state root hash
account_key,
vec![hash_name.clone()],
)
.await
.map_err(Into::<anyhow::Error>::into)
.and_then(|response| {
if response.id == expected_rpc_id {
match response.result.stored_value {
StoredValue::ContractPackage(contract_package) => Ok(*contract_package
.versions()
.next()
.expect("Expected at least one contract version")
.contract_hash()),
other => Err(anyhow!(
"Unexpected result type, type is not a CLValue: {:?}",
other
)),
}
} else {
Err(anyhow!("JSON RPC Id missmatch"))
}
.and_then(|response| match response.result.stored_value {
StoredValue::ContractPackage(contract_package) => Ok(*contract_package
.versions()
.next()
.expect("Expected at least one contract version")
.contract_hash()),
other => Err(anyhow!(
"Unexpected result type, type is not a CLValue: {:?}",
other
)),
})?;
tracing::info!(
"Successfully fetched the contract hash for {}: {}",
Expand Down
Loading

0 comments on commit 154471a

Please sign in to comment.