Compare commits

..

6 Commits

Author SHA1 Message Date
Jędrzej Stuczyński 58b808602a I hate DKG 2025-10-22 09:24:58 +01:00
benedetta davico 85030069f1 comment out migration 2025-10-22 09:08:11 +01:00
Jędrzej Stuczyński df512d6d3a sandbox/canary inconsistent state fix 2025-10-22 09:08:11 +01:00
Jędrzej Stuczyński e30576eed3 bugfix: update internal owner address in transferred share 2025-10-22 08:58:01 +01:00
Jędrzej Stuczyński 9f9639950b feat: expose more explicit new_with_fronted_urls builder for http API client (#6136) 2025-10-21 14:47:58 +01:00
Jędrzej Stuczyński 111a0b20b6 bugfix: update stored epoch share when changing ownership (#6135) 2025-10-21 14:10:20 +01:00
8 changed files with 83 additions and 22 deletions
+1 -1
View File
@@ -151,7 +151,7 @@ pub async fn gateways_for_init(
}
let retry_count = retry_count.unwrap_or(DEFAULT_NYM_API_RETRIES);
let mut builder = nym_http_api_client::ClientBuilder::new_with_urls(nym_api_urls.clone())
let mut builder = nym_http_api_client::ClientBuilder::new_with_urls(nym_api_urls.clone())?
.with_retries(retry_count)
.with_bincode();
@@ -84,6 +84,10 @@ pub enum ExecuteMsg {
UpdateAnnounceAddress {
new_address: String,
},
FixOldShare {
old_owner: String,
},
}
#[cw_serde]
+32 -16
View File
@@ -296,6 +296,9 @@ impl std::error::Error for ReqwestErrorWrapper {}
#[derive(Debug, Error)]
#[allow(missing_docs)]
pub enum HttpClientError {
#[error("did not provide any valid client URLs")]
NoUrlsProvided,
#[error("failed to construct inner reqwest client: {source}")]
ReqwestBuildError {
#[source]
@@ -582,24 +585,29 @@ impl ClientBuilder {
Self::new(alt)
} else {
let url = url.to_url()?;
Ok(Self::new_with_urls(vec![url]))
Self::new_with_urls(vec![url])
}
}
/// Create a client builder from network details with sensible defaults
#[cfg(feature = "network-defaults")]
// deprecating function since it's not clear from its signature whether the client
// would be constructed using `nym_api_urls` or `nym_vpn_api_urls`
#[deprecated(note = "use explicit Self::new_with_fronted_urls instead")]
pub fn from_network(
network: &nym_network_defaults::NymNetworkDetails,
) -> Result<Self, HttpClientError> {
let urls = network
.nym_api_urls
.as_ref()
.ok_or_else(|| {
HttpClientError::GenericRequestFailure(
"No API URLs configured in network details".to_string(),
)
})?
.iter()
let urls = network.nym_api_urls.as_ref().cloned().unwrap_or_default();
Self::new_with_fronted_urls(urls.clone())
}
/// Create a client builder using the provided set of domain-fronted URLs
#[cfg(feature = "network-defaults")]
pub fn new_with_fronted_urls(
urls: Vec<nym_network_defaults::ApiUrl>,
) -> Result<Self, HttpClientError> {
let urls = urls
.into_iter()
.map(|api_url| {
// Convert ApiUrl to our Url type with fronting support
let mut url = Url::parse(&api_url.url)?;
@@ -611,15 +619,19 @@ impl ClientBuilder {
.iter()
.map(|host| format!("https://{}", host))
.collect();
url = Url::new(api_url.url.clone(), Some(fronts))
.map_err(|e| HttpClientError::GenericRequestFailure(e.to_string()))?;
url = Url::new(api_url.url.clone(), Some(fronts)).map_err(|source| {
HttpClientError::MalformedUrl {
raw: api_url.url.clone(),
source,
}
})?;
}
Ok(url)
})
.collect::<Result<Vec<_>, HttpClientError>>()?;
let mut builder = Self::new_with_urls(urls);
let mut builder = Self::new_with_urls(urls)?;
// Enable domain fronting by default (on retry)
#[cfg(feature = "tunneling")]
@@ -631,7 +643,11 @@ impl ClientBuilder {
}
/// Constructs a new http `ClientBuilder` from a valid url.
pub fn new_with_urls(urls: Vec<Url>) -> Self {
pub fn new_with_urls(urls: Vec<Url>) -> Result<Self, HttpClientError> {
if urls.is_empty() {
return Err(HttpClientError::NoUrlsProvided);
}
let urls = Self::check_urls(urls);
#[cfg(target_arch = "wasm32")]
@@ -640,7 +656,7 @@ impl ClientBuilder {
#[cfg(not(target_arch = "wasm32"))]
let reqwest_client_builder = default_builder();
ClientBuilder {
Ok(ClientBuilder {
urls,
timeout: None,
custom_user_agent: false,
@@ -651,7 +667,7 @@ impl ClientBuilder {
retry_limit: 0,
serialization: SerializationFormat::Json,
}
})
}
/// Add an additional URL to the set usable by this constructed `Client`
+9 -1
View File
@@ -21,6 +21,10 @@ inventory::collect!(ConfigRecord);
/// Returns the default builder with all registered configurations applied.
pub fn default_builder() -> ReqwestClientBuilder {
let mut b = ReqwestClientBuilder::new();
#[cfg(feature = "debug-inventory")]
let mut test_client = ReqwestClientBuilder::new();
let mut records: Vec<&'static ConfigRecord> =
inventory::iter::<ConfigRecord>.into_iter().collect();
records.sort_by_key(|r| r.priority); // lower runs first
@@ -35,6 +39,10 @@ pub fn default_builder() -> ReqwestClientBuilder {
for r in records {
b = (r.apply)(b);
#[cfg(feature = "debug-inventory")]
{
test_client = (r.apply)(test_client);
}
}
#[cfg(feature = "debug-inventory")]
@@ -47,7 +55,7 @@ pub fn default_builder() -> ReqwestClientBuilder {
eprintln!("[HTTP-INVENTORY] Building test client to verify configuration...");
// Try to build a client to see if it works
match b.try_clone().unwrap().build() {
match test_client.build() {
Ok(client) => {
eprintln!("[HTTP-INVENTORY] ✓ Client built successfully");
eprintln!("[HTTP-INVENTORY] Client debug info: {:#?}", client);
+1 -1
View File
@@ -93,7 +93,7 @@ async fn api_client_retry() -> Result<(), Box<dyn std::error::Error>> {
let client = ClientBuilder::new_with_urls(vec![
"http://broken.nym.badurl".parse()?,
"http://example.com/".parse()?,
])
])?
.with_retries(3)
.build()?;
+34 -1
View File
@@ -6,6 +6,7 @@ use crate::dealers::queries::{
query_epoch_dealers_addresses_paged, query_epoch_dealers_paged,
query_registered_dealer_details,
};
use crate::dealers::storage::{ensure_dealer, EPOCH_DEALERS_MAP};
use crate::dealers::transactions::{
try_add_dealer, try_transfer_ownership, try_update_announce_address,
};
@@ -18,14 +19,16 @@ use crate::epoch_state::queries::{
query_can_advance_state, query_current_epoch, query_current_epoch_threshold,
query_epoch_at_height, query_epoch_threshold,
};
use crate::epoch_state::storage::save_epoch;
use crate::epoch_state::storage::{load_current_epoch, save_epoch};
use crate::epoch_state::transactions::{
try_advance_epoch_state, try_initiate_dkg, try_trigger_reset, try_trigger_resharing,
};
use crate::epoch_state::utils::check_epoch_state;
use crate::error::ContractError;
use crate::state::queries::query_state;
use crate::state::storage::{DKG_ADMIN, MULTISIG, STATE};
use crate::verification_key_shares::queries::{query_vk_share, query_vk_shares_paged};
use crate::verification_key_shares::storage::vk_shares;
use crate::verification_key_shares::transactions::try_commit_verification_key_share;
use crate::verification_key_shares::transactions::try_verify_verification_key_share;
use cosmwasm_std::{
@@ -134,6 +137,36 @@ pub fn execute(
ExecuteMsg::UpdateAnnounceAddress { new_address } => {
try_update_announce_address(deps, info, new_address)
}
ExecuteMsg::FixOldShare { old_owner } => {
let old_owner = deps.api.addr_validate(&old_owner)?;
let epoch = load_current_epoch(deps.storage)?;
// make sure we're not mid-exchange
check_epoch_state(deps.storage, EpochState::InProgress)?;
// make sure the requester is actually a dealer for this epoch
ensure_dealer(deps.storage, &info.sender, epoch.epoch_id)?;
for epoch_id in 0..=epoch.epoch_id {
if let Some(mut vk_share) =
vk_shares().may_load(deps.storage, (&old_owner, epoch_id))?
{
vk_share.owner = info.sender.clone();
vk_shares().remove(deps.storage, (&old_owner, epoch_id))?;
vk_shares().save(deps.storage, (&info.sender, epoch_id), &vk_share)?;
}
if let Some(mut vk_share) =
vk_shares().may_load(deps.storage, (&info.sender, epoch_id))?
{
vk_share.owner = info.sender.clone();
vk_shares().save(deps.storage, (&info.sender, epoch_id), &vk_share)?;
}
}
Ok(Response::new())
}
}
}
@@ -57,7 +57,7 @@ async fn run(
.clone()
.expect("rust sdk mainnet default missing api_url");
let nym_api = nym_http_api_client::ClientBuilder::new_with_urls(vec![default_api_url.into()])
let nym_api = nym_http_api_client::ClientBuilder::new_with_urls(vec![default_api_url.into()])?
.no_hickory_dns()
.with_timeout(nym_api_client_timeout)
.build()?;
@@ -98,7 +98,7 @@ impl Monitor {
.expect("rust sdk mainnet default missing api_url");
let nym_api =
nym_http_api_client::ClientBuilder::new_with_urls(vec![default_api_url.into()])
nym_http_api_client::ClientBuilder::new_with_urls(vec![default_api_url.into()])?
.no_hickory_dns()
.with_timeout(self.nym_api_client_timeout)
.build()?;