Skip to content
Open
14 changes: 7 additions & 7 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "witnet"
version = "1.6.7"
version = "2.0.0"
authors = ["Witnet Foundation <info@witnet.foundation>"]
publish = false
repository = "witnet/witnet-rust"
Expand Down
2 changes: 1 addition & 1 deletion bridges/centralized-ethereum/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "witnet-centralized-ethereum-bridge"
version = "1.6.7"
version = "2.0.0"
authors = ["Witnet Foundation <info@witnet.foundation>"]
edition = "2018"

Expand Down
2 changes: 1 addition & 1 deletion data_structures/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ authors = ["Witnet Foundation <info@witnet.foundation>"]
description = "data structures component"
edition = "2021"
name = "witnet_data_structures"
version = "1.6.7"
version = "2.0.0"
workspace = ".."

[features]
Expand Down
17 changes: 13 additions & 4 deletions data_structures/src/chain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1645,11 +1645,17 @@ pub enum RADType {
/// HTTP POST request
#[serde(rename = "HTTP-POST")]
HttpPost,
/// HTTP HEAD request
#[serde(rename = "HTTP-HEAD")]
HttpHead,
}

impl RADType {
pub fn is_http(&self) -> bool {
matches!(self, RADType::HttpGet | RADType::HttpPost)
matches!(
self,
RADType::HttpGet | RADType::HttpPost | RADType::HttpHead
)
}
}

Expand Down Expand Up @@ -1701,7 +1707,7 @@ pub struct RADRetrieve {
pub script: Vec<u8>,
/// Body of a HTTP-POST request
pub body: Vec<u8>,
/// Extra headers of a HTTP-GET or HTTP-POST request
/// Extra headers of a HTTP-GET, HTTP-POST or HTTP-HEAD request
pub headers: Vec<(String, String)>,
}

Expand Down Expand Up @@ -1810,6 +1816,9 @@ impl RADRetrieve {
&[Field::Body, Field::Headers],
)
}
RADType::HttpHead => {
check(&[Field::Kind, Field::Url, Field::Script], &[Field::Headers])
}
}
}

Expand Down Expand Up @@ -2681,7 +2690,7 @@ impl TransactionsPool {
for input in &vt_tx.body.inputs {
self.output_pointer_map
.entry(input.output_pointer)
.or_insert_with(Vec::new)
.or_default()
.push(vt_tx.hash());
}

Expand All @@ -2706,7 +2715,7 @@ impl TransactionsPool {
for input in &dr_tx.body.inputs {
self.output_pointer_map
.entry(input.output_pointer)
.or_insert_with(Vec::new)
.or_default()
.push(dr_tx.hash());
}

Expand Down
2 changes: 1 addition & 1 deletion data_structures/src/data_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ impl DataRequestPool {

self.data_requests_by_epoch
.entry(epoch)
.or_insert_with(HashSet::new)
.or_default()
.insert(dr_hash);
self.data_request_pool.insert(dr_hash, dr_state);

Expand Down
2 changes: 2 additions & 0 deletions data_structures/src/proto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ impl ProtobufConvert for chain::RADType {
chain::RADType::HttpGet => witnet::DataRequestOutput_RADRequest_RADType::HttpGet,
chain::RADType::Rng => witnet::DataRequestOutput_RADRequest_RADType::Rng,
chain::RADType::HttpPost => witnet::DataRequestOutput_RADRequest_RADType::HttpPost,
chain::RADType::HttpHead => witnet::DataRequestOutput_RADRequest_RADType::HttpHead,
}
}

Expand All @@ -60,6 +61,7 @@ impl ProtobufConvert for chain::RADType {
witnet::DataRequestOutput_RADRequest_RADType::HttpGet => chain::RADType::HttpGet,
witnet::DataRequestOutput_RADRequest_RADType::Rng => chain::RADType::Rng,
witnet::DataRequestOutput_RADRequest_RADType::HttpPost => chain::RADType::HttpPost,
witnet::DataRequestOutput_RADRequest_RADType::HttpHead => chain::RADType::HttpHead,
})
}
}
Expand Down
4 changes: 2 additions & 2 deletions data_structures/src/serialization_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ struct RADRetrieveSerializationHelperJson {
/// Body of a HTTP-POST request
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub body: Vec<u8>,
/// Extra headers of a HTTP-GET or HTTP-POST request
/// Extra headers of a HTTP-GET, HTTP-HEAD or HTTP-POST request
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub headers: Vec<(String, String)>,
}
Expand All @@ -377,7 +377,7 @@ struct RADRetrieveSerializationHelperBincode {
pub script: Vec<u8>,
/// Body of a HTTP-POST request
pub body: Vec<u8>,
/// Extra headers of a HTTP-GET or HTTP-POST request
/// Extra headers of a HTTP-GET, HTTP-HEAD or HTTP-POST request
pub headers: Vec<(String, String)>,
}

Expand Down
2 changes: 1 addition & 1 deletion net/src/client/http/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ pub struct WitnetHttpResponse {

impl WitnetHttpResponse {
#[inline]
/// Simple wrapper around `isahc::Response::status`.
/// Simple wrapper around `isahc::Response`.
pub fn inner(self) -> isahc::Response<isahc::AsyncBody> {
self.res
}
Expand Down
2 changes: 1 addition & 1 deletion node/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "witnet_node"
version = "1.6.7"
version = "2.0.0"
authors = ["Witnet Foundation <info@witnet.foundation>"]
workspace = ".."
description = "node component"
Expand Down
2 changes: 1 addition & 1 deletion rad/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "witnet_rad"
version = "0.3.2"
version = "0.3.3"
authors = ["Witnet Foundation <info@witnet.foundation>"]
edition = "2021"
workspace = ".."
Expand Down
123 changes: 110 additions & 13 deletions rad/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,11 +192,10 @@ pub fn run_retrieval_with_data_report(
settings: RadonScriptExecutionSettings,
) -> Result<RadonReport<RadonTypes>> {
match retrieve.kind {
RADType::HttpGet => string_response_with_data_report(retrieve, response, context, settings),
RADType::Rng => rng_response_with_data_report(response, context),
RADType::HttpPost => {
RADType::HttpGet | RADType::HttpPost | RADType::HttpHead => {
string_response_with_data_report(retrieve, response, context, settings)
}
RADType::Rng => rng_response_with_data_report(response, context),
_ => Err(RadError::UnknownRetrieval),
}
}
Expand All @@ -214,7 +213,7 @@ pub fn run_retrieval_with_data(
.map(RadonReport::into_inner)
}

/// Handle generic HTTP (GET/POST) response
/// Handle generic HTTP (GET/POST/HEAD) response
async fn http_response(
retrieve: &RADRetrieve,
context: &mut ReportContext<RadonTypes>,
Expand Down Expand Up @@ -259,6 +258,10 @@ async fn http_response(
WitnetHttpBody::from(retrieve.body.clone()),
)
}
RADType::HttpHead => (
builder.method("HEAD").uri(&retrieve.url),
WitnetHttpBody::empty(),
),
_ => panic!(
"Called http_response with invalid retrieval kind {:?}",
retrieve.kind
Expand Down Expand Up @@ -298,13 +301,21 @@ async fn http_response(

// If at some point we want to support the retrieval of non-UTF8 data (e.g. raw bytes), this is
// where we need to decide how to read the response body
let (_parts, mut body) = response.into_parts();
let mut response_string = String::default();
body.read_to_string(&mut response_string)
.await
.map_err(|x| RadError::HttpOther {
message: x.to_string(),
})?;

let (parts, mut body) = response.into_parts();
match retrieve.kind {
RADType::HttpHead => {
response_string = format!("{:?}", parts.headers);
}
_ => {
body.read_to_string(&mut response_string)
.await
.map_err(|x| RadError::HttpOther {
message: x.to_string(),
})?;
}
}

let result = run_retrieval_with_data_report(retrieve, &response_string, context, settings);

Expand Down Expand Up @@ -354,9 +365,10 @@ pub async fn run_retrieval_report(
context.set_active_wips(active_wips);

match retrieve.kind {
RADType::HttpGet => http_response(retrieve, context, settings, client).await,
RADType::HttpGet | RADType::HttpHead | RADType::HttpPost => {
http_response(retrieve, context, settings, client).await
}
RADType::Rng => rng_response(context, settings).await,
RADType::HttpPost => http_response(retrieve, context, settings, client).await,
_ => Err(RadError::UnknownRetrieval),
}
}
Expand Down Expand Up @@ -649,7 +661,7 @@ fn validate_header(name: &str, value: &str) -> Result<()> {
Err(RadError::InvalidHttpHeader {
name: name.to_string(),
value: value.to_string(),
error: error_message.to_string(),
error: error_message,
})
} else {
Ok(())
Expand Down Expand Up @@ -829,6 +841,39 @@ mod tests {

use super::*;

#[test]
fn test_run_http_head_retrieval() {
let script_r = Value::Array(vec![
Value::Integer(RadonOpCodes::StringParseJSONMap as i128),
Value::Array(vec![
Value::Integer(RadonOpCodes::MapGetString as i128),
Value::Text("etag".to_string()),
]),
]);
let packed_script_r = serde_cbor::to_vec(&script_r).unwrap();

let retrieve = RADRetrieve {
kind: RADType::HttpHead,
url: "https://en.wikipedia.org/static/images/icons/wikipedia.png".to_string(),
script: packed_script_r,
body: vec![],
headers: vec![],
};
let response = r#"{"date": "Wed, 11 Oct 2023 15:18:42 GMT", "content-type": "image/png", "content-length": "498219", "x-origin-cache": "HIT", "last-modified": "Mon, 28 Aug 2023 13:30:41 GMT", "access-control-allow-origin": "*", "etag": "\"64eca181-79a2b\"", "expires": "Wed, 11 Oct 2023 15:28:41 GMT", "cache-control": "max-age=1800", "x-proxy-cache": "MISS", "x-github-request-id": "6750:35DB:BF8211:FEFD2B:652602FA", "via": "1.1 varnish", "x-served-by": "cache-hnd18736-HND", "x-cache": "MISS", "x-cache-hits": "0", "x-timer": "S1696989946.496383,VS0,VE487", "vary": "Accept-Encoding", "x-fastly-request-id": "118bdfd8a926cbdc781bc23079c3dc07a22d2223", "cf-cache-status": "REVALIDATED", "accept-ranges": "bytes", "report-to": "{\"endpoints\":[{\"url\":\"https:\/\/a.nel.cloudflare.com\/report\/v3?s=FlzxKRCYYN4SL0x%2FraG7ugKCqdC%2BeQqVrucvsfeDWf%2F7A0Nv9fv7TYRgU0WL4k1kbZyxt%2B04VjOyv0XK55sF37GEPwXHE%2FdXnoFlWutID762k2ktcX6hUml6oNk%3D\"}],\"group\":\"cf-nel\",\"max_age\":604800}", "nel": "{\"success_fraction\":0,\"report_to\":\"cf-nel\",\"max_age\":604800}", "strict-transport-security": "max-age=0", "x-content-type-options": "nosniff", "server": "cloudflare", "cf-ray": "814813bf3a73f689-NRT", "alt-svc": "h3=\":443\"; ma=86400"}"#;
let result = run_retrieval_with_data(
&retrieve,
response,
RadonScriptExecutionSettings::disable_all(),
current_active_wips(),
)
.unwrap();

match result {
RadonTypes::String(_) => {}
err => panic!("Error in run_retrieval: {:?}", err),
}
}

#[test]
fn test_run_retrieval() {
let script_r = Value::Array(vec![
Expand Down Expand Up @@ -1526,6 +1571,58 @@ mod tests {
}
}

#[test]
fn test_try_data_request_http_get_non_ascii_header_key() {
let script_r = Value::Array(vec![]);
let packed_script_r = serde_cbor::to_vec(&script_r).unwrap();
let body = Vec::from(String::from(""));
let headers = vec![("ñ", "value")];
let headers = headers
.into_iter()
.map(|(a, b)| (a.to_string(), b.to_string()))
.collect();
let request = RADRequest {
time_lock: 0,
retrieve: vec![RADRetrieve {
kind: RADType::HttpGet,
url: String::from("http://127.0.0.1"),
script: packed_script_r,
body,
headers,
}],
aggregate: RADAggregate {
filters: vec![],
reducer: RadonReducers::Mode as u32,
},
tally: RADTally {
filters: vec![],
reducer: RadonReducers::Mode as u32,
},
};
let report = try_data_request(
&request,
RadonScriptExecutionSettings::enable_all(),
None,
None,
);
let tally_result = report.tally.into_inner();

assert_eq!(
tally_result,
RadonTypes::RadonError(
RadonError::try_from(RadError::UnhandledIntercept {
inner: Some(Box::new(RadError::InvalidHttpHeader {
name: "ñ".to_string(),
value: "value".to_string(),
error: "invalid HTTP header name".to_string()
})),
message: None
})
.unwrap()
)
);
}

#[test]
fn test_try_data_request_http_post_non_ascii_header_key() {
let script_r = Value::Array(vec![]);
Expand Down
Loading