Skip to content

Refactor/client error handling and incorporate latest Sia consensus changes #10

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 28 commits into
base: release_candidate_1
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
36ea06c
move `impl Encodable for Hash256` to correct file
Alrighttt Nov 22, 2024
074e4ff
add general Hash256 todo dev comment
Alrighttt Nov 22, 2024
9e943d1
implement SatisfiedPolicy encoding changes from SiaFoundation/core/pu…
Alrighttt Nov 22, 2024
089b32f
fix hash.rs imports
Alrighttt Nov 22, 2024
876e0e3
update rust_port_test go port tests after implementing changes from S…
Alrighttt Nov 22, 2024
3956f53
begin refactor of ApiClient error handling - WIP WASM compilation broken
Alrighttt Dec 4, 2024
79fd59a
WIP partially integrate ApiClient refactor to ApiClientHelper
Alrighttt Dec 4, 2024
11c0238
refactor wasm client error handling - WIP
Alrighttt Dec 4, 2024
57a2ae9
standarize NativeClientError to fit error handling policy of siacoin …
Alrighttt Dec 4, 2024
8dc5c7d
remove ApiClient::to_data_request to simplify trait methods
Alrighttt Dec 4, 2024
289568b
fix NativeClientError to account for removal of ApiClient::to_data_re…
Alrighttt Dec 4, 2024
69b46fa
remove ApiClient::execute_request
Alrighttt Dec 4, 2024
e00aafc
fix NativeClientError formatting
Alrighttt Dec 4, 2024
81bf734
refactor wasm client error handling and incorporate ApiClient changes
Alrighttt Dec 4, 2024
f619a85
remove irrelevant dev comment
Alrighttt Dec 4, 2024
30a97ac
remove unused type, DynamicTransportError. Never used - was accidenta…
Alrighttt Dec 5, 2024
059c1fb
rename symbol client::native::NativeClient to client::native::Client
Alrighttt Jan 13, 2025
f192f23
Make all helpers error types agnostic towards ClientError type
Alrighttt Jan 14, 2025
5fa8577
add Error type trait bound to ApiClient::Error associated type
Alrighttt Jan 14, 2025
0d72a86
move all generic helpers errors to unique module
Alrighttt Jan 14, 2025
e2b0635
integrate generic error handling refactor to wasm client
Alrighttt Jan 14, 2025
aa472a3
Native client retry failed http requests up to 3 times
Alrighttt Feb 6, 2025
6cf471a
add ApiClientHelpers::mine_blocks for CI purposes
Alrighttt Feb 6, 2025
ba35c4a
add a temporary fix for newly added "basis" field in txpool/broadcast…
Alrighttt Feb 6, 2025
b4bedbd
add UtxoWithBasis struct
Alrighttt Feb 13, 2025
905bed3
add basis field to V2Transaction and V2TransactionBuilder
Alrighttt Feb 13, 2025
d7173e8
add new basis field to UTXO related endpoints and helpers
Alrighttt Feb 13, 2025
bd68559
use provided basis in broadcast_transaction
Alrighttt Feb 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions src/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,6 @@ pub trait Encodable {
fn encode(&self, encoder: &mut Encoder);
}

impl Encodable for Hash256 {
fn encode(&self, encoder: &mut Encoder) { encoder.write_slice(&self.0); }
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
24 changes: 10 additions & 14 deletions src/tests/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ mod test {
};

let hash = Encoder::encode_and_hash(&satisfied_policy);
let expected = Hash256::from_str("51832be911c7382502a2011cbddf1a9f689c4ca08c6a83ae3d021fb0dc781822").unwrap();
let expected = Hash256::from_str("92d9097978387a5da9d17435b796984dae6bd4342c88684d0949e406755c289c").unwrap();
assert_eq!(hash, expected);
}

Expand All @@ -194,11 +194,10 @@ mod test {
};

let hash = Encoder::encode_and_hash(&satisfied_policy);
let expected = Hash256::from_str("1e612d1ee36338b93a36bac0c52007a2d678cde0bd9b95c36a1f61166cf02b87").unwrap();
let expected = Hash256::from_str("abac830016d15871dfefad87ddfce263a6936b77e8ec18e7712870d6bf771376").unwrap();
assert_eq!(hash, expected);
}

// Adding a signature to SatisfiedPolicy of PolicyHash should have no effect
fn test_satisfied_policy_encode_hash_frivulous_signature() {
let policy = SpendPolicy::Hash(Hash256::default());

Expand All @@ -213,7 +212,7 @@ mod test {
};

let hash = Encoder::encode_and_hash(&satisfied_policy);
let expected = Hash256::from_str("80f3caa4507615945bc839c8505546decd91e9642120f26938b2fc370fa61992").unwrap();
let expected = Hash256::from_str("f6885827fb8a6d1a5751ce3f5a8580dc590f262f42e2dd9944052ec43ffc8d97").unwrap();
assert_eq!(hash, expected);
}

Expand All @@ -229,7 +228,7 @@ mod test {
};

let hash = Encoder::encode_and_hash(&satisfied_policy);
let expected = Hash256::from_str("80f3caa4507615945bc839c8505546decd91e9642120f26938b2fc370fa61992").unwrap();
let expected = Hash256::from_str("e3bbd67ade36322f3de8458b1daa80fd21bb74af88c779b768908e007611f36e").unwrap();
assert_eq!(hash, expected);
}

Expand All @@ -253,7 +252,7 @@ mod test {
};

let hash = Encoder::encode_and_hash(&satisfied_policy);
let expected = Hash256::from_str("c749f9ac53395ec557aed7e21d202f76a58e0de79222e5756b27077e9295931f").unwrap();
let expected = Hash256::from_str("0411ac20ae5472822bdc6c24c9ba2afdd828300ed3706cb1c07a8578276fd72d").unwrap();
assert_eq!(hash, expected);
}

Expand Down Expand Up @@ -289,7 +288,7 @@ mod test {
};

let hash = Encoder::encode_and_hash(&satisfied_policy);
let expected = Hash256::from_str("13806b6c13a97478e476e0e5a0469c9d0ad8bf286bec0ada992e363e9fc60901").unwrap();
let expected = Hash256::from_str("b4d658dbc32b3e147d2736f75b14ca881d5c04963663993b6448c86f4f1a2815").unwrap();
assert_eq!(hash, expected);
}

Expand All @@ -308,8 +307,7 @@ mod test {
};

let hash = Encoder::encode_and_hash(&satisfied_policy);
// FIXME update this in go equivalent. Preimage was changed from Vec<u8> to [u8; 32]
let expected = Hash256::from_str("2200a1464864cfaea8d312c1f16b5e00b816110896bea32ef7e1ccd43042d312").unwrap();
let expected = Hash256::from_str("5cd34ed67f2b2a55d016b4c485dfd1ca2eca75f6831cec9eed9494d6fa735315").unwrap();
assert_eq!(hash, expected);
}

Expand Down Expand Up @@ -338,8 +336,7 @@ mod test {
};

let hash = Encoder::encode_and_hash(&satisfied_policy);
// FIXME update this in go equivalent. Preimage was changed from Vec<u8> to [u8; 32]
let expected = Hash256::from_str("08852e4ad99f726120028ecd82925b5f55fa441952cfc034a5cf4f09159b9372").unwrap();
let expected = Hash256::from_str("30abac67d0017556ae69416f54663edbe2fb14c7bcef028f2d228aef500e8f51").unwrap();
assert_eq!(hash, expected);
}

Expand Down Expand Up @@ -368,7 +365,7 @@ mod test {
};

let hash = Encoder::encode_and_hash(&satisfied_policy);
let expected = Hash256::from_str("8975e8cf990d5a20d9ec3dae18ed3b3a0c92edf967a8d93fcdef6a1eb73bb348").unwrap();
let expected = Hash256::from_str("69b26bdb1114af01e4626d2a31184706e1dc83d83063c9019f9ee66381bd6923").unwrap();
assert_eq!(hash, expected);
}

Expand Down Expand Up @@ -404,8 +401,7 @@ mod test {
};

let hash = Encoder::encode_and_hash(&vin);
// FIXME update this in go equivalent. Preimage was changed from Vec<u8> to [u8; 32]
let expected = Hash256::from_str("d31a05b155113a5244f14ae833887fd8b30f555129be126ca4b90592290db24a").unwrap();
let expected = Hash256::from_str("102a2924e7427ee3654bfeea8fc055fd82c2a403598484dbb704da9cdaada3ba").unwrap();
assert_eq!(hash, expected);
}

Expand Down
57 changes: 14 additions & 43 deletions src/transport/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,8 @@ use url::Url;
#[cfg(not(target_arch = "wasm32"))] pub mod native;
#[cfg(target_arch = "wasm32")] pub mod wasm;

mod helpers;
pub use helpers::{ApiClientHelpers, HelperError};

// FIXME remove these client specific error types
#[cfg(not(target_arch = "wasm32"))]
use reqwest::Error as ReqwestError;

#[cfg(target_arch = "wasm32")] use wasm::wasm_fetch::FetchError;
pub(crate) mod helpers;
pub use helpers::ApiClientHelpers;

// Client implementation is generalized
// This allows for different client implementations (e.g., WebSocket, libp2p, etc.)
Expand All @@ -26,45 +20,16 @@ pub trait ApiClient: Clone {
type Request;
type Response;
type Conf;
type Error: std::error::Error + std::fmt::Debug;

async fn new(conf: Self::Conf) -> Result<Self, ApiClientError>
async fn new(conf: Self::Conf) -> Result<Self, Self::Error>
where
Self: Sized;

fn process_schema(&self, schema: EndpointSchema) -> Result<Self::Request, ApiClientError>;

fn to_data_request<R: SiaApiRequest>(&self, request: R) -> Result<Self::Request, ApiClientError> {
self.process_schema(request.to_endpoint_schema()?)
}

// TODO this can have a default implementation if an associated type can provide .execute()
// eg self.client().execute(request).await.map_err(Self::ClientError)
async fn execute_request(&self, request: Self::Request) -> Result<Self::Response, ApiClientError>;
fn process_schema(&self, schema: EndpointSchema) -> Result<Self::Request, Self::Error>;

// TODO default implementation should be possible if Execute::Response is a serde deserializable type
async fn dispatcher<R: SiaApiRequest>(&self, request: R) -> Result<R::Response, ApiClientError>;
}

#[derive(Debug, Error)]
pub enum ApiClientError {
#[error("BuildError error: {0}")]
BuildError(String),
#[error("FixmePlaceholder error: {0}")]
FixmePlaceholder(String), // FIXME this entire enum needs refactoring to not use client-specific error types
#[error("UrlParse error: {0}")]
UrlParse(#[from] url::ParseError),
#[error("UnexpectedHttpStatus error: status:{status} body:{body}")]
UnexpectedHttpStatus { status: http::StatusCode, body: String },
#[error("Serde error: {0}")]
Serde(#[from] serde_json::Error),
#[error("UnexpectedEmptyResponse error: {expected_type}")]
UnexpectedEmptyResponse { expected_type: String },
#[error("WasmFetchError error: {0}")]
#[cfg(target_arch = "wasm32")]
WasmFetchError(#[from] FetchError),
#[error("ReqwestError error: {0}")]
#[cfg(not(target_arch = "wasm32"))]
ReqwestError(#[from] ReqwestError), // FIXME remove this; it should be generalized enough to not need arch-specific error types
async fn dispatcher<R: SiaApiRequest>(&self, request: R) -> Result<R::Response, Self::Error>;
}

// Not all client implementations will have an exact equivalent of HTTP methods
Expand Down Expand Up @@ -150,9 +115,15 @@ pub enum Body {
None,
}

#[derive(Debug, Error)]
pub enum EndpointSchemaError {
#[error("EndpointSchema::build_url: failed to parse Url from constructed path: {0}")]
ParseUrl(#[from] url::ParseError),
}

impl EndpointSchema {
// Safely build the URL using percent-encoding for path params
pub fn build_url(&self, base_url: &Url) -> Result<Url, ApiClientError> {
pub fn build_url(&self, base_url: &Url) -> Result<Url, EndpointSchemaError> {
let mut path = self.path_schema.to_string();

// Replace placeholders in the path with encoded values if path_params are provided
Expand All @@ -164,7 +135,7 @@ impl EndpointSchema {
}

// Combine base_url with the constructed path
let mut url = base_url.join(&path).map_err(ApiClientError::UrlParse)?;
let mut url = base_url.join(&path)?;

// Add query parameters if any
if let Some(query_params) = &self.query_params {
Expand Down
Loading