Skip to content

Commit

Permalink
Merge pull request #122 from weaveVM/switch-to-non-tokio-for-async-calls
Browse files Browse the repository at this point in the history
Feat: Switch to non-tokio calls, improve I/O performance, Include struct versioning.
  • Loading branch information
andreespirela authored Dec 18, 2024
2 parents 744ed16 + 04b73f7 commit eefc1cd
Show file tree
Hide file tree
Showing 23 changed files with 914 additions and 413 deletions.
9 changes: 7 additions & 2 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions wvm-apps/wvm-exexed/crates/precompiles/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ reqwest-graphql = "1.0.0"
rbrotli = { path = "../brotli" }
wvm-borsh = { path = "../wvm-borsh", name = "wvm-borsh" }
wvm-static = { path = "../../../../crates/wvm-static" }
wvm-tx = { path = "../tx" }
borsh.workspace = true
alloy-primitives.workspace = true
ureq = { version = "2.10.1", features = ["json"] }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,37 +77,31 @@ fn arweave_read(input: &Bytes, gas_limit: u64) -> PrecompileResult {
let res = match id_str {
Ok(id) => {
let (gateway, tx_id) = parse_gateway_content(id.as_str());
internal_block(async {
let clean_gateway = clean_gateway_url(gateway.as_str());
let query = build_transaction_query(Some(&[tx_id.clone()]), None, None, None, true);
let now = Instant::now();
let data = send_graphql(clean_gateway.as_str(), query.as_str()).await;

let tx_size = if let Ok(data) = data {
let resp = data.data;
let tx = resp.transactions.edges.get(0);
if let Some(&ref tx) = tx {
let tx_size = tx.clone().node.data.unwrap().size;
let tx_size = tx_size.parse::<usize>().unwrap();
tx_size
} else {
0
}
} else {
0
};

if TX_MAX_SIZE >= tx_size {
download_tx(gas_used, clean_gateway, tx_id).await
} else {
Err(PrecompileErrors::Error(PrecompileError::Other(
"Arweave Transaction size is greater than allowed (18mb)".to_string(),
)))
}
})
.map_err(|_| {
let clean_gateway = clean_gateway_url(gateway.as_str());
let query = build_transaction_query(Some(&[tx_id.clone()]), None, None, None, true);

let data = send_graphql(clean_gateway.as_str(), query.as_str());
let tx_size = match data {
Ok(data) => data
.data
.transactions
.edges
.get(0)
.and_then(|edge| edge.node.data.as_ref())
.and_then(|data| data.size.parse::<usize>().ok())
.unwrap_or(0),
Err(_) => 0,
};

if tx_size > TX_MAX_SIZE {
return Err(PrecompileErrors::Error(PrecompileError::Other(
"Arweave Transaction size is greater than allowed (18mb)".to_string(),
)));
}

Ok(download_tx(gas_used, clean_gateway, tx_id).map_err(|_| {
PrecompileError::Other("Tokio runtime could not block_on for operation".to_string())
})?
})?)
}
Err(_) => Err(PrecompileErrors::Error(PrecompileError::Other(
"Transaction id could not be parsed".to_string(),
Expand All @@ -123,6 +117,8 @@ mod arweave_read_pc_tests {
use alloy_primitives::Bytes;
use reth::primitives::revm_primitives::PrecompileOutput;
use std::time::Instant;
use borsh::BorshDeserialize;
use wvm_borsh::block::BorshSealedBlockWithSenders;

#[test]
pub fn test_arweave_read_precompile() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ pub fn build_transaction_query(
query
}

pub async fn send_graphql(gateway: &str, query: &str) -> Result<Response, Error> {
pub fn send_graphql(gateway: &str, query: &str) -> Result<Response, Error> {
let res = ureq::post(format!("{}/{}", gateway, "graphql").as_str()).send_json(ureq::json!({
"variables": {},
"query": query
Expand Down
121 changes: 62 additions & 59 deletions wvm-apps/wvm-exexed/crates/precompiles/src/inner/kyve_precompile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,68 +60,71 @@ fn kyve_read(input: &Bytes, gas_limit: u64) -> PrecompileResult {

let field = field.unwrap();

internal_block(async {
println!(
"{}",
format!("{}/ethereum/beacon/blob_sidecars?block_height={}", KYVE_API_URL, blk_number)
);
let req = reqwest::get(
format!("{}/ethereum/beacon/blob_sidecars?block_height={}", KYVE_API_URL, blk_number)
.as_str(),
)
.await;

match req {
Ok(resp) => match resp.json::<serde_json::Value>().await {
Ok(json_val) => {
let main_val = json_val.get("value").unwrap();

let slot = main_val.get("slot").and_then(|s| s.as_u64()).unwrap().to_string();

let blobs = main_val.get("blobs").and_then(|b| b.as_array()).unwrap();

let (blob_indx, field) = field.split_once('.').unwrap();

if field.eq("slot") {
return Ok(PrecompileOutput::new(gas_used, slot.into_bytes().into()));
}

match blobs.get(blob_indx.parse::<usize>().unwrap()) {
Some(get_field) => {
if let Some(field_val) = get_field.get(field) {
Ok(PrecompileOutput::new(
gas_used,
field_val.as_str().unwrap().to_string().into_bytes().into(),
))
} else {
Err(PrecompileErrors::Error(PrecompileError::Other(
"Field does not exist".to_string(),
)))
}
}
None => Err(PrecompileErrors::Error(PrecompileError::Other(
"Blob index does not exist".to_string(),
))),
}
}
Err(_) => Err(PrecompileErrors::Error(PrecompileError::Other(
let req = ureq::get(
format!("{}/ethereum/beacon/blob_sidecars?block_height={}", KYVE_API_URL, blk_number)
.as_str(),
)
.call();

match req {
Ok(resp) => {
let json_val = resp.into_json::<serde_json::Value>().map_err(|_| {
PrecompileErrors::Error(PrecompileError::Other(
"Invalid Response from server".to_string(),
))),
},
Err(e) => {
println!("{:?}", e);
println!("{}", e.url().unwrap());
println!("{}", e.status().unwrap());
println!("{}", e.to_string());
Err(PrecompileErrors::Error(PrecompileError::Other(
"Could not connect with KYVE".to_string(),
)))
))
})?;

let main_val = json_val.get("value").ok_or_else(|| {
PrecompileErrors::Error(PrecompileError::Other("Missing 'value' field".to_string()))
})?;

let slot = main_val
.get("slot")
.and_then(|s| s.as_u64())
.ok_or_else(|| {
PrecompileErrors::Error(PrecompileError::Other(
"Missing or invalid 'slot' field".to_string(),
))
})?
.to_string();

let blobs = main_val.get("blobs").and_then(|b| b.as_array()).ok_or_else(|| {
PrecompileErrors::Error(PrecompileError::Other(
"Missing or invalid 'blobs' field".to_string(),
))
})?;

let (blob_indx, field) = field.split_once('.').ok_or_else(|| {
PrecompileErrors::Error(PrecompileError::Other("Invalid field format".to_string()))
})?;

if field == "slot" {
return Ok(PrecompileOutput::new(gas_used, slot.into_bytes().into()));
}

let blob_index = blob_indx.parse::<usize>().map_err(|_| {
PrecompileErrors::Error(PrecompileError::Other("Invalid blob index".to_string()))
})?;

let get_field = blobs.get(blob_index).ok_or_else(|| {
PrecompileErrors::Error(PrecompileError::Other(
"Blob index does not exist".to_string(),
))
})?;

let field_val = get_field.get(field).and_then(|val| val.as_str()).ok_or_else(|| {
PrecompileErrors::Error(PrecompileError::Other("Field does not exist".to_string()))
})?;

Ok(PrecompileOutput::new(gas_used, field_val.to_string().into_bytes().into()))
}
Err(e) => {
println!("{:?}", e);
Err(PrecompileErrors::Error(PrecompileError::Other(
"Could not connect with KYVE".to_string(),
)))
}
})
.map_err(|_| {
PrecompileError::Other("Tokio runtime could not block_on for operation".to_string())
})?
}
}

#[cfg(test)]
Expand Down
4 changes: 1 addition & 3 deletions wvm-apps/wvm-exexed/crates/precompiles/src/inner/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,8 @@ mod pc_inner_tests {
let pcs = wvm_precompiles();
let pcs: Vec<PrecompileWithAddress> = pcs.collect();
assert_eq!(pcs.len(), 4);
}

#[test]
pub fn wvm_precompiles_test() {
std::env::remove_var("BLOCKED_PC");
let mut get_pcs = wvm_precompiles();
let first = get_pcs.next().unwrap();
assert_eq!(first.0, u64_to_address(0x17));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use reth::primitives::SealedBlockWithSenders;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use wvm_borsh::block::BorshSealedBlockWithSenders;
use wvm_tx::wvm::WvmSealedBlockWithSenders;

#[derive(Debug, Deserialize, Serialize, PartialEq)]
#[serde(rename_all = "camelCase")]
Expand Down Expand Up @@ -125,7 +126,12 @@ pub fn from_sealed_block_senders_value(sealed_block: Value) -> Block {
impl From<BorshSealedBlockWithSenders> for Block {
fn from(value: BorshSealedBlockWithSenders) -> Self {
let sealed_block = value.0;
from_sealed_block_senders(sealed_block)
match sealed_block {
WvmSealedBlockWithSenders::V1(data) => {
from_sealed_block_senders(data.into())
}
}

}
}

Expand Down
13 changes: 12 additions & 1 deletion wvm-apps/wvm-exexed/crates/precompiles/src/inner/util.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use alloy_primitives::Bytes;
use revm_primitives::{PrecompileError, PrecompileErrors, PrecompileOutput};
use std::io::Read;
use wvm_static::internal_block;

pub const DEFAULT_ARWEAVE_TX_ENDPOINT: &str = "https://arweave.net/";

Expand All @@ -11,11 +12,21 @@ pub fn clean_gateway_url(gateway: &str) -> String {
clean_gateway.to_string()
}

pub async fn download_tx(
pub fn download_tx(
gas_used: u64,
clean_gateway: String,
tx_id: String,
) -> Result<PrecompileOutput, PrecompileErrors> {
// LEGACY
// internal_block(async {
// let download_tx = reqwest::get(format!("{}/{}", clean_gateway, tx_id.as_str())).await;
// match download_tx {
// Ok(tx) => Ok(PrecompileOutput::new(gas_used, tx.bytes().await.unwrap().into())),
// Err(_) => Err(PrecompileErrors::Error(PrecompileError::Other(
// "Arweave Transaction was not found".to_string(),
// ))),
// }
// }).unwrap()
let download_tx = ureq::get(format!("{}/{}", clean_gateway, tx_id.as_str()).as_str()).call();
match download_tx {
Ok(tx) => Ok(PrecompileOutput::new(gas_used, {
Expand Down
Loading

0 comments on commit eefc1cd

Please sign in to comment.