You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#![deny(unused_crate_dependencies)]//use rust_chainlink_ea_api::validate::*;pubmod validate;use anyhow::Result;use banyan_shared::{eth::EthClient, types::DealID};use ethers as _;use rand::Rng;use rocket::serde::{json::serde_json, json::Json,Deserialize,Serialize};use rocket::tokio::task::spawn;use rocket::{post,State};use std::sync::Arc;use tokio as _;pubstructWebserverState{pubprovider:Arc<EthClient>,pubshould_be_async:bool,}#[derive(Serialize,Deserialize,Debug)]pubstructChainlinkEARequest{pubid:String,pubdata: validate::ChainlinkRequestData,pubmeta:Option<serde_json::Value>,pubresponse_url:Option<String>,}fnformat_response(result:Result<validate::ChainlinkResponse, anyhow::Error>,) -> Json<serde_json::Value>{match result {Ok(data) => Json(serde_json::json!(data)),Err(e) => Json(serde_json::json!({"error": e.to_string()})),}}// TODO prefix all logs with ID from request#[post("/compute", format = "json", data = "<input_data>")]pubasyncfncompute(webserver_state:&State<WebserverState>,input_data:Json<ChainlinkEARequest>,) -> Json<serde_json::Value>{if webserver_state.should_be_async{let new_provider = webserver_state.provider.clone();spawn(asyncmove{let result =
validate::validate_deal_internal(new_provider, input_data.data.clone()).await;// send the result to the chainlink node
reqwest::Client::new().patch(input_data.into_inner().response_url.unwrap()).body(format_response(result).to_string()).send().await.unwrap();});Json(serde_json::json!({"pending":true}))// end of thread}else{format_response(
validate::validate_deal_internal(
webserver_state.provider.clone(),
input_data.data.clone(),).await,)}}#[rocket::main]asyncfnmain() -> Result<()>{
dotenv::dotenv().ok();let should_be_async = std::env::var("SHOULD_BE_ASYNC").map_or_else(|_| false, |n| n.parse::<bool>().unwrap_or(false));// create an ethers HTTP providerlet eth_client = Arc::new(EthClient::default());let _ = rocket::build().mount("/", rocket::routes![compute]).manage(WebserverState{provider: eth_client,
should_be_async,}).launch().await?;Ok(())}/// Helper function for testing inputs to Chainlink EA without having to run a node.pubasyncfnrust_chainlink_ea_api_call(deal_id:DealID,api_url:String,) -> Result<validate::ChainlinkResponse, anyhow::Error>{// Job id when chainlink calls is not random.letmut rng = rand::thread_rng();let random_job_id:u16 = rng.gen();let map = serde_json::json!({"id": random_job_id.to_string(),"data":{"deal_id": deal_id.0.to_string()}});let client = reqwest::Client::new();let res = client
.post(api_url).json(&map).send().await?
.json::<validate::ChainlinkResponse>().await?;dbg!("{:?}",&res);Ok(res)}/*#[cfg(test)]mod tests { use super::*; use banyan_shared::{ deals::DealProposalBuilder, eth::EthClient, types::{BlockNum, DealID, DealProposal}, }; use ethers::types::Bytes; use std::fs::File; #[tokio::test] /// This test will fail if no deal has ever been created on the contract, or if that deal has valid proofs in it. async fn api_call_test() -> Result<(), anyhow::Error> { let response_data: validate::ChainlinkResponse = rust_chainlink_ea_api_call(DealID(1), "http://127.0.0.1:8000/compute".to_string()) .await?; assert_eq!(response_data.data.success_count, 1); Ok(()) } #[tokio::test] /// This tests verifies that a deal with no logged proofs will have a success count of 0 async fn api_no_proofs_test() -> Result<(), anyhow::Error> { let file = File::open("test_files/ethereum.pdf").unwrap(); let deal_proposal = DealProposal::builder().with_file(file).build().unwrap(); let eth_client = EthClient::default(); let deal_id: DealID = eth_client .propose_deal(deal_proposal, None, None) .await .expect("Failed to send deal proposal"); dbg!("Offer Created for Deal ID: {:}", deal_id); let deal = eth_client.get_offer(deal_id).await.unwrap(); // Assert that the deal we read is the same as the one we sent dbg!("deal {:?}", deal.clone()); assert_eq!(deal.deal_length_in_blocks, BlockNum(10)); let response_data: validate::ChainlinkResponse = rust_chainlink_ea_api_call(deal_id, "http://127.0.0.1:8000/compute".to_string()) .await?; assert_eq!(response_data.data.success_count, 0); Ok(()) } #[tokio::test] /// This test verifies that an eth client can create multiple consecutive deals, which all have no logged proofs. async fn multiple_deals_same_file_no_proofs() -> Result<(), anyhow::Error> { let file = File::open("test_files/ethereum.pdf").unwrap(); let deal_proposal = DealProposal::builder().with_file(file).build().unwrap(); let eth_client = EthClient::default(); let deal_id: DealID = eth_client .propose_deal(deal_proposal.clone(), None, None) .await .expect("Failed to send deal proposal"); dbg!("Proof Created for Deal ID: {:}", &deal_id); let deal = eth_client.get_offer(deal_id).await.unwrap(); // Assert that the deal we read is the same as the one we sent assert_eq!(deal.deal_length_in_blocks, BlockNum(10)); let deal_id_2: DealID = eth_client .propose_deal(deal_proposal, None, None) .await .expect("Failed to send deal proposal"); dbg!("Proof Created for Deal ID: {:}", &deal_id_2); let deal = eth_client.get_offer(deal_id_2).await.unwrap(); assert_eq!(deal.deal_length_in_blocks, BlockNum(10)); let response_data_1: validate::ChainlinkResponse = rust_chainlink_ea_api_call(deal_id, "http://127.0.0.1:8000/compute".to_string()) .await?; assert_eq!(response_data_1.data.success_count, 0); let response_data_2: validate::ChainlinkResponse = rust_chainlink_ea_api_call(deal_id_2, "http://127.0.0.1:8000/compute".to_string()) .await?; assert_eq!(response_data_2.data.success_count, 0); Ok(()) } #[tokio::test] /// This test verifies that we can create a deal with one window, submit a proof, and verify it. async fn deal_and_proof_one_window() -> Result<(), anyhow::Error> { let mut file = File::open("test_files/ethereum.pdf").unwrap(); let deal_proposal: DealProposal = DealProposalBuilder::new( "0x0000000000000000000000000000000000000000".to_string(), 3, 3, 0.0, 0.0, "0x0000000000000000000000000000000000000000".to_string(), ) .with_file(file.try_clone()?) .build() .unwrap(); let eth_client = EthClient::default(); let deal_id: DealID = eth_client .propose_deal(deal_proposal.clone(), None, None) .await .expect("Failed to send deal proposal"); let deal = eth_client.get_offer(deal_id).await.unwrap(); // create a proof using the same file we used to create the deal let (_hash, proof) = eth_client .create_proof_helper( deal.deal_start_block, &mut file, deal.file_size.as_u64(), true, ) .await .expect("Failed to create proof"); // Wait one block until current block is no longer the deal start block let mut current_block_num = deal.deal_start_block; while current_block_num == deal.deal_start_block { current_block_num = eth_client .get_latest_block_num() .await .expect("Failed to get current block"); } let target_block = deal.deal_start_block; let _block_num: BlockNum = eth_client .post_proof(deal_id, proof, target_block, None, None) .await .expect("Failed to post proof"); let mut current_block_num_2 = BlockNum(0); while !EthClient::deal_over(current_block_num_2, deal.clone()) { current_block_num_2 = eth_client .get_latest_block_num() .await .expect("Failed to get current block"); } let response_data: validate::ChainlinkResponse = rust_chainlink_ea_api_call(deal_id, "http://127.0.0.1:8000/compute".to_string()) .await?; assert_eq!(response_data.data.success_count, 1); Ok(()) } #[tokio::test] /// This test verifies that we can create a deal with two window, post one proof and simply not post a second, and recieve /// A success count of 1. async fn one_proof_window_missing() -> Result<(), anyhow::Error> { let mut file = File::open("test_files/ethereum.pdf").unwrap(); let deal_proposal: DealProposal = DealProposalBuilder::new( "0x0000000000000000000000000000000000000000".to_string(), 6, 3, 0.0, 0.0, "0x0000000000000000000000000000000000000000".to_string(), ) .with_file(file.try_clone()?) .build() .unwrap(); let eth_client = EthClient::default(); let deal_id: DealID = eth_client .propose_deal(deal_proposal.clone(), None, None) .await .expect("Failed to send deal proposal"); let deal = eth_client.get_offer(deal_id).await.unwrap(); let target_window: usize = eth_client .compute_target_window(deal.deal_start_block, deal.proof_frequency_in_blocks) .await .expect("Failed to compute target window"); let target_block = EthClient::compute_target_block_start( deal.deal_start_block, deal.proof_frequency_in_blocks, target_window, ); // Wait one block until current block is no longer the deal start block let mut current_block_num = deal.deal_start_block; while current_block_num == deal.deal_start_block { current_block_num = eth_client .get_latest_block_num() .await .expect("Failed to get current block"); } // create a proof using the same file we used to create the deal let (_hash, proof) = eth_client .create_proof_helper(target_block, &mut file, deal.file_size.as_u64(), true) .await .expect("Failed to create proof"); let block_num: BlockNum = eth_client .post_proof(deal_id, proof, target_block, None, None) .await .expect("Failed to post proof"); // Wait for the second window to start // checking that deal is either finished or cancelled let mut current_block_num_2 = block_num; while !EthClient::deal_over(current_block_num_2, deal.clone()) { current_block_num_2 = eth_client .get_latest_block_num() .await .expect("Failed to get current block"); } let response_data: validate::ChainlinkResponse = rust_chainlink_ea_api_call(deal_id, "http://127.0.0.1:8000/compute".to_string()) .await?; assert_eq!(response_data.data.success_count, 1); assert_eq!(response_data.data.num_windows, 2); Ok(()) } #[tokio::test] /// This test verifies that we can submit two correct proofs and get two successes. async fn two_correct_proofs() -> Result<(), anyhow::Error> { let mut file = File::open("test_files/ethereum.pdf").unwrap(); let deal_proposal: DealProposal = DealProposalBuilder::new( "0x0000000000000000000000000000000000000000".to_string(), 4, 2, 0.0, 0.0, "0x0000000000000000000000000000000000000000".to_string(), ) .with_file(file.try_clone()?) .build() .unwrap(); let eth_client = EthClient::default(); let deal_id: DealID = eth_client .propose_deal(deal_proposal.clone(), None, None) .await .expect("Failed to send deal proposal"); let deal = eth_client.get_offer(deal_id).await.unwrap(); let target_window: usize = eth_client .compute_target_window(deal.deal_start_block, deal.proof_frequency_in_blocks) .await .expect("Failed to compute target window"); let target_block = EthClient::compute_target_block_start( deal.deal_start_block, deal.proof_frequency_in_blocks, target_window, ); dbg!("deal start block: {}", deal.deal_start_block); dbg!("target block start: {}", target_block); let (_hash, proof) = eth_client .create_proof_helper(target_block, &mut file, deal.file_size.as_u64(), true) .await .expect("Failed to create proof"); let block_num: BlockNum = eth_client .post_proof(deal_id, proof, target_block, None, None) .await .expect("Failed to post proof"); let target_block_2 = target_block + deal.proof_frequency_in_blocks; let mut current_block_num = block_num; while current_block_num != target_block_2 { current_block_num = eth_client .get_latest_block_num() .await .expect("Failed to get current block"); } let (_hash, bad_proof) = eth_client .create_proof_helper(target_block_2, &mut file, deal.file_size.as_u64(), true) .await .expect("Failed to create proof"); let block_num_2: BlockNum = eth_client .post_proof(deal_id, bad_proof, target_block_2, None, None) .await .expect("Failed to post proof"); current_block_num = block_num_2; while !EthClient::deal_over(current_block_num, deal.clone()) { current_block_num = eth_client .get_latest_block_num() .await .expect("Failed to get current block"); } let response_data: validate::ChainlinkResponse = rust_chainlink_ea_api_call(deal_id, "http://127.0.0.1:8000/compute".to_string()) .await?; assert_eq!(response_data.data.success_count, 2); assert_eq!(response_data.data.num_windows, 2); Ok(()) } #[tokio::test] /// This test verifies that we can get a success count of 1 when submitting one correct proof and one incorrect proof async fn one_proof_correct_one_incorrect() -> Result<(), anyhow::Error> { let mut file = File::open("test_files/ethereum.pdf").unwrap(); let deal_proposal: DealProposal = DealProposalBuilder::new( "0x0000000000000000000000000000000000000000".to_string(), 4, 2, 0.0, 0.0, "0x0000000000000000000000000000000000000000".to_string(), ) .with_file(file.try_clone()?) .build() .unwrap(); let eth_client = EthClient::default(); let deal_id: DealID = eth_client .propose_deal(deal_proposal.clone(), None, None) .await .expect("Failed to send deal proposal"); let deal = eth_client.get_offer(deal_id).await.unwrap(); let target_window: usize = eth_client .compute_target_window(deal.deal_start_block, deal.proof_frequency_in_blocks) .await .expect("Failed to compute target window"); let target_block = EthClient::compute_target_block_start( deal.deal_start_block, deal.proof_frequency_in_blocks, target_window, ); dbg!("deal start block: {}", deal.deal_start_block); dbg!("target block start: {}", target_block); let (_hash, proof) = eth_client .create_proof_helper(target_block, &mut file, deal.file_size.as_u64(), true) .await .expect("Failed to create proof"); let block_num: BlockNum = eth_client .post_proof(deal_id, proof, target_block, None, None) .await .expect("Failed to post proof"); let target_block_2 = target_block + deal.proof_frequency_in_blocks; let mut current_block_num = block_num; while current_block_num != target_block_2 { current_block_num = eth_client .get_latest_block_num() .await .expect("Failed to get current block"); } let (_hash, bad_proof) = eth_client .create_proof_helper(target_block_2, &mut file, deal.file_size.as_u64(), false) .await .expect("Failed to create proof"); let block_num_2: BlockNum = eth_client .post_proof(deal_id, bad_proof, target_block_2, None, None) .await .expect("Failed to post proof"); current_block_num = block_num_2; while !EthClient::deal_over(current_block_num, deal.clone()) { current_block_num = eth_client .get_latest_block_num() .await .expect("Failed to get current block"); } let response_data: validate::ChainlinkResponse = rust_chainlink_ea_api_call(deal_id, "http://127.0.0.1:8000/compute".to_string()) .await?; assert_eq!(response_data.data.success_count, 1); assert_eq!(response_data.data.num_windows, 2); Ok(()) } #[tokio::test] /// This test verifies that an empty proof will not be counted as a success. async fn empty_proof_unsuccessful() -> Result<(), anyhow::Error> { let file = File::open("test_files/ethereum.pdf").unwrap(); let deal_proposal: DealProposal = DealProposalBuilder::new( "0x0000000000000000000000000000000000000000".to_string(), 1, 1, 0.0, 0.0, "0x0000000000000000000000000000000000000000".to_string(), ) .with_file(file) .build() .unwrap(); let eth_client = EthClient::default(); let deal_id: DealID = eth_client .propose_deal(deal_proposal.clone(), None, None) .await .expect("Failed to send deal proposal"); let deal = eth_client.get_offer(deal_id).await.unwrap(); // create a proof using the same file we used to create the deal let proof = Bytes::from(Vec::new()); let block_num: BlockNum = eth_client .post_proof(deal_id, proof, deal.deal_start_block, None, None) .await .expect("Failed to post proof"); let mut current_block_num = block_num; while !EthClient::deal_over(current_block_num, deal.clone()) { current_block_num = eth_client .get_latest_block_num() .await .expect("Failed to get current block"); } let response_data: validate::ChainlinkResponse = rust_chainlink_ea_api_call(deal_id, "http://127.0.0.1:8000/compute".to_string()) .await?; assert_eq!(response_data.data.success_count, 0); Ok(()) }}*/
The text was updated successfully, but these errors were encountered:
/ A success count of 1.
checking that deal is either finished or cancelled
chainlink-proof-validator/src/main.rs
Line 38 in 85d3e4e
The text was updated successfully, but these errors were encountered: