Skip to content

Commit

Permalink
Merge pull request #120 from cspr-rad/feature/contract-submit-batch
Browse files Browse the repository at this point in the history
Feature/contract submit batch
  • Loading branch information
Avi-D-coder authored Jun 24, 2024
2 parents 456cae1 + 870f849 commit 2dd3518
Show file tree
Hide file tree
Showing 57 changed files with 3,496 additions and 713 deletions.
1,087 changes: 831 additions & 256 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"


# Always optimize dependencies
[profile.dev.package."*"]
opt-level = 3

[workspace.dependencies]
casper-client = "2.0"
casper-types = "4.0"
Expand Down
13 changes: 9 additions & 4 deletions demo-contract-tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ edition.workspace = true
license.workspace = true

[dev-dependencies]
casper-engine-test-support = { version = "7.0.0", default-features = false }
casper-execution-engine = { version = "7.0.0", default-features = false }
casper-contract.workspace = true
casper-types = { workspace = true, default-features = false }
# using a custom branch because it contains modifications to the chainspec that is pulled for integration tests
casper-engine-test-support = { git = "https://github.com/cspr-rad/casper-node", branch = "kairos-testing-chainspec", default-features=false }
casper-execution-engine = { git = "https://github.com/cspr-rad/casper-node", branch = "kairos-testing-chainspec", default-features=false }
casper-contract = { git = "https://github.com/cspr-rad/casper-node", branch = "kairos-testing-chainspec", default-features=false }
casper-types = { git = "https://github.com/cspr-rad/casper-node", branch = "kairos-testing-chainspec", default-features=false }
serde = {version="1", default-features=false, features=["derive"]}
kairos-verifier-risc0-lib = {path="../kairos-prover/kairos-verifier-risc0-lib"}
serde-json-wasm = "1"
rand = "0.8"
wasm-opt = "0.116"
sha2 = {version = "0.10", default-features = false}
77 changes: 68 additions & 9 deletions demo-contract-tests/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ mod test_fixture;
mod tests {
use crate::test_fixture::TestContext;
use casper_types::U512;
use kairos_verifier_risc0_lib::verifier::verify_execution;

#[test]
fn should_install_contract() {
let _fixture = TestContext::new();
let _fixture = TestContext::new(None);
}

#[test]
fn test_deposit_succeeds() {
let mut fixture = TestContext::new();
let mut fixture = TestContext::new(None);

let user = fixture.create_funded_user();
let user_balance_before = fixture.get_user_balance(user);
Expand All @@ -34,7 +35,7 @@ mod tests {

#[test]
fn test_transfer_from_contract_purse_to_user_fails() {
let mut fixture = TestContext::new();
let mut fixture = TestContext::new(None);

let user = fixture.create_funded_user();
let amount = U512::from(100000000000u64);
Expand All @@ -45,7 +46,7 @@ mod tests {

#[test]
fn test_transfer_from_contract_purse_to_admin_fails() {
let mut fixture = TestContext::new();
let mut fixture = TestContext::new(None);

let user = fixture.create_funded_user();
let amount = U512::from(100000000000u64);
Expand All @@ -55,8 +56,8 @@ mod tests {
}

#[test]
fn test_transfer_from_contract_purse_by_uref_to_user_should_fails() {
let mut fixture = TestContext::new();
fn test_transfer_from_contract_purse_by_uref_to_user_fails() {
let mut fixture = TestContext::new(None);
let user = fixture.create_funded_user();
let amount = U512::from(100000000000u64);
fixture.deposit_succeeds(user, amount);
Expand All @@ -65,12 +66,70 @@ mod tests {
}

#[test]
fn test_transfer_from_contract_purse_by_uref_to_admin_should_fails() {
let mut fixture = TestContext::new();
fn test_transfer_from_contract_purse_by_uref_to_admin_fails() {
let mut fixture = TestContext::new(None);
let user = fixture.create_funded_user();
let amount = U512::from(100000000000u64);
fixture.deposit_succeeds(user, amount);

fixture.transfer_from_contract_purse_by_uref_to_user_fails(fixture.admin, amount)
}

#[test]
fn submit_batch_to_contract_simple() {
let receipt0 = include_bytes!("testdata/test_prove_simple_batches_0.json");
let receipt1 = include_bytes!("testdata/test_prove_simple_batches_1.json");

// precheck proofs before contract tests that are hard to debug
let proof_outputs =
verify_execution(&serde_json_wasm::from_slice(receipt0).unwrap()).unwrap();
assert_eq!(proof_outputs.pre_batch_trie_root, None);
verify_execution(&serde_json_wasm::from_slice(receipt1).unwrap()).unwrap();

let mut fixture = TestContext::new(None);
// submit proofs to contract
fixture.submit_proof_to_contract(fixture.admin, receipt0.to_vec());
fixture.submit_proof_to_contract(fixture.admin, receipt1.to_vec());
}

// TODO some more real larger batches fail with code unreachable in the contract.
// They verify fine outside the contract, so I suspect they use too much gas.
#[allow(dead_code)]
fn submit_batch_to_contract(receipt: &[u8]) {
// precheck proofs before contract tests that are hard to debug
let proof_outputs =
verify_execution(&serde_json_wasm::from_slice(receipt).unwrap()).unwrap();

eprintln!("{:?}", proof_outputs);

let mut fixture = TestContext::new(proof_outputs.pre_batch_trie_root);
fixture.submit_proof_to_contract(fixture.admin, receipt.to_vec())
}

#[test]
fn submit_batch_to_contract_1() {
let receipt =
include_bytes!("testdata/proptest_prove_batches-proof-journal-517453938a5b4f3e.json");
submit_batch_to_contract(receipt);
}

#[test]
fn submit_batch_to_contract_2() {
let receipt =
include_bytes!("testdata/proptest_prove_batches-proof-journal-9a85f9117f0bf3a8.json");
submit_batch_to_contract(receipt);
}

#[test]
fn submit_batch_to_contract_3() {
let receipt =
include_bytes!("testdata/proptest_prove_batches-proof-journal-52945c21c49e8ca6.json");
submit_batch_to_contract(receipt);
}

#[test]
fn submit_batch_to_contract_4() {
let receipt =
include_bytes!("testdata/proptest_prove_batches-proof-journal-a53b58a9cf37e50e.json");
submit_batch_to_contract(receipt);
}
}
41 changes: 34 additions & 7 deletions demo-contract-tests/tests/test_fixture/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use casper_engine_test_support::{
use casper_execution_engine::storage::global_state::in_memory::InMemoryGlobalState;
use casper_types::{
account::AccountHash,
bytesrepr::Bytes,
crypto::{PublicKey, SecretKey},
runtime_args,
system::{handle_payment::ARG_TARGET, mint::ARG_ID},
Expand All @@ -30,13 +31,18 @@ pub struct TestContext {
}

impl TestContext {
pub fn new() -> TestContext {
pub fn new(initial_trie_root: Option<[u8; 32]>) -> TestContext {
let mut builder = InMemoryWasmTestBuilder::default();
builder.run_genesis(&PRODUCTION_RUN_GENESIS_REQUEST);

let admin = create_funded_account_for_secret_key_bytes(&mut builder, ADMIN_SECRET_KEY);
let contract_path = get_wasm_directory().join("demo-contract-optimized.wasm");
run_session_with_args(&mut builder, &contract_path, admin, runtime_args! {});
let contract_path = get_wasm_directory().0.join("demo-contract-optimized.wasm");
run_session_with_args(
&mut builder,
&contract_path,
admin,
runtime_args! {"initial_trie_root" => initial_trie_root },
);

let contract_hash = builder
.get_expected_account(admin)
Expand Down Expand Up @@ -83,7 +89,9 @@ impl TestContext {
}

pub fn deposit_succeeds(&mut self, depositor: AccountHash, amount: U512) {
let deposit_session_path = get_wasm_directory().join("deposit-session-optimized.wasm");
let deposit_session_path = get_wasm_directory()
.1
.join("deposit-session-optimized.wasm");
let session_args = runtime_args! {
"amount" => amount,
"demo_contract" => self.contract_hash
Expand All @@ -106,7 +114,9 @@ impl TestContext {
"amount" => amount,
"demo_contract" => self.contract_hash
};
let malicious_session_path = get_wasm_directory().join("malicious-session-optimized.wasm");
let malicious_session_path = get_wasm_directory()
.1
.join("malicious-session-optimized.wasm");
run_session_with_args(
&mut self.builder,
malicious_session_path.as_path(),
Expand All @@ -125,8 +135,9 @@ impl TestContext {
"demo_contract" => self.contract_hash,
"purse_uref" => self.contract_purse
};
let malicious_reader_session_path =
get_wasm_directory().join("malicious-reader-optimized.wasm");
let malicious_reader_session_path = get_wasm_directory()
.1
.join("malicious-reader-optimized.wasm");
run_session_with_args(
&mut self.builder,
malicious_reader_session_path.as_path(),
Expand All @@ -135,6 +146,22 @@ impl TestContext {
);
self.builder.expect_failure();
}
pub fn submit_proof_to_contract(&mut self, sender: AccountHash, proof_serialized: Vec<u8>) {
let session_args = runtime_args! {
"risc0_receipt" => Bytes::from(proof_serialized),
};
let submit_batch_request = ExecuteRequestBuilder::contract_call_by_hash(
sender,
self.contract_hash,
"submit_batch",
session_args,
)
.build();
self.builder
.exec(submit_batch_request)
.commit()
.expect_success();
}
}

pub fn run_session_with_args(
Expand Down
35 changes: 20 additions & 15 deletions demo-contract-tests/tests/test_fixture/wasm_helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,38 @@ use std::fs;
use std::path::Path;
use std::path::PathBuf;

pub fn get_wasm_directory() -> PathBuf {
pub fn get_wasm_directory() -> (PathBuf, PathBuf) {
// Environment variable or default path.
let base_path = if let Ok(custom_path) = env::var("PATH_TO_WASM_BINARIES") {
PathBuf::from(custom_path)
} else {
let project_root = env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".to_string());
if cfg!(debug_assertions) {
PathBuf::from(project_root)
.join("../kairos-contracts/target/wasm32-unknown-unknown/debug/")
} else {
PathBuf::from(project_root)
.join("../kairos-contracts/target/wasm32-unknown-unknown/release/")
}
PathBuf::from(project_root)
.join("../kairos-contracts/target/wasm32-unknown-unknown/release/")
};

eprintln!("base_path: {:?}", base_path);

let base_path_session = if let Ok(custom_path) = env::var("PATH_TO_SESSION_BINARIES") {
PathBuf::from(custom_path)
} else {
let project_root = env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".to_string());
PathBuf::from(project_root)
.join("../kairos-session-code/target/wasm32-unknown-unknown/release/")
};

if !base_path.exists() {
let build_type = if cfg!(debug_assertions) {
"debug"
} else {
"release"
};
panic!("WASM directory does not exist: {}. Please build smart contracts at `./kairos-contracts` with `cargo build` for {}.", base_path.display(), build_type);
panic!("WASM directory does not exist: {}. Please build smart contracts at `./kairos-contracts` with `cargo build --release`.", base_path.display());
}

if !base_path_session.exists() {
panic!("WASM directory does not exist: {}. Please build session code at `./kairos-session-code` with `cargo build --release`", base_path_session.display());
}

// Ensure all WASM files are optimized.
optimize_files(&base_path).expect("Unable to optimize WASM files");

base_path
(base_path, base_path_session)
}

fn optimize_files(dir: &Path) -> Result<(), String> {
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Loading

0 comments on commit 2dd3518

Please sign in to comment.