Skip to content
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

feat: log/error on mismatch of client version and supported version #1166

Merged
merged 7 commits into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ proc-macro2 = "1.0.66"
quote = "1.0.33"
rand = { version = "0.8.5", default-features = false, features = ["std_rng", "getrandom"] }
regex = "1.10.0"
semver = "1.0.20"
serde = { version = "1.0.188", default-features = false }
serde_json = "1.0.107"
serde_with = { version = "3.3.0", default-features = false }
Expand All @@ -64,6 +65,7 @@ tai64 = { version = "4.0.0", default-features = false }
tempfile = { version = "3.8.0", default-features = false }
thiserror = { version = "1.0.49", default-features = false }
tokio = { version = "1.33.0", default-features = false }
tracing = "0.1.37"
trybuild = "1.0.85"
uint = { version = "0.9.5", default-features = false }
which = { version = "4.4.2", default-features = false }
Expand Down
2 changes: 2 additions & 0 deletions packages/fuels-accounts/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ fuel-vm = { workspace = true }
fuels-core = { workspace = true }
hex = { workspace = true, default-features = false, features = ["std"] }
rand = { workspace = true, default-features = false }
semver = { workspace = true }
tai64 = { workspace = true, features = ["serde"] }
thiserror = { workspace = true, default-features = false }
tokio = { workspace = true, features = ["full"] }
tracing = { workspace = true }
zeroize = { workspace = true, features = ["derive"] }

[dev-dependencies]
Expand Down
1 change: 1 addition & 0 deletions packages/fuels-accounts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use crate::{accounts_utils::extract_message_id, provider::Provider};
mod accounts_utils;
pub mod predicate;
pub mod provider;
mod supported_versions;
pub mod wallet;

/// Trait for signing transactions and messages
Expand Down
40 changes: 39 additions & 1 deletion packages/fuels-accounts/src/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ pub use retry_util::{Backoff, RetryConfig};
use tai64::Tai64;
use thiserror::Error;

use crate::provider::retryable_client::RetryableClient;
use crate::{
provider::retryable_client::RetryableClient,
supported_versions::{check_fuel_core_version_compatibility, VersionCompatibility},
};

type ProviderResult<T> = std::result::Result<T, ProviderError>;

#[derive(Debug)]
Expand Down Expand Up @@ -124,6 +128,13 @@ pub enum ProviderError {
ClientRequestError(#[from] io::Error),
#[error("Receipts have not yet been propagated. Retry the request later.")]
ReceiptsNotPropagatedYet,
#[error("Invalid Fuel client version: {0}")]
InvalidFuelClientVersion(#[from] semver::Error),
#[error("Unsupported Fuel client version. Current version: {current}, supported version: {supported}")]
UnsupportedFuelClientVersion {
current: semver::Version,
supported: semver::Version,
},
}

impl From<ProviderError> for Error {
Expand Down Expand Up @@ -269,9 +280,36 @@ impl Provider {
let node_info = self.node_info().await?;
let chain_info = self.chain_info().await?;

Self::ensure_client_version_is_supported(&node_info)?;

Ok(NetworkInfo::new(node_info, chain_info))
}

fn ensure_client_version_is_supported(node_info: &NodeInfo) -> ProviderResult<()> {
let node_version = node_info.node_version.parse::<semver::Version>()?;
let VersionCompatibility {
supported_version,
is_major_supported,
is_minor_supported,
is_patch_supported,
} = check_fuel_core_version_compatibility(&node_version);

if !is_major_supported || !is_minor_supported {
return Err(ProviderError::UnsupportedFuelClientVersion {
current: node_version,
supported: supported_version,
});
} else if !is_patch_supported {
tracing::warn!(
fuel_client_version = %node_version,
supported_version = %supported_version,
"The patch versions of the client and SDK differ.",
);
};

Ok(())
}

pub fn chain_id(&self) -> ChainId {
self.consensus_parameters.chain_id
}
Expand Down
116 changes: 116 additions & 0 deletions packages/fuels-accounts/src/supported_versions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use semver::Version;

fn get_supported_fuel_core_version() -> Version {
"0.20.6".parse().unwrap()
}

#[derive(Debug, PartialEq, Eq)]
pub(crate) struct VersionCompatibility {
pub(crate) supported_version: Version,
pub(crate) is_major_supported: bool,
pub(crate) is_minor_supported: bool,
pub(crate) is_patch_supported: bool,
}

pub(crate) fn check_fuel_core_version_compatibility(
network_version: &Version,
) -> VersionCompatibility {
let supported_version = get_supported_fuel_core_version();
check_version_compatibility(network_version, &supported_version)
}

fn check_version_compatibility(
actual_version: &Version,
Br1ght0ne marked this conversation as resolved.
Show resolved Hide resolved
expected_version: &Version,
) -> VersionCompatibility {
let is_major_supported = expected_version.major == actual_version.major;
let is_minor_supported = expected_version.minor == actual_version.minor;
let is_patch_supported = expected_version.patch == actual_version.patch;

VersionCompatibility {
supported_version: expected_version.clone(),
is_major_supported,
is_minor_supported,
is_patch_supported,
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn should_validate_all_possible_version_mismatches() {
let expected_version = "0.1.2".parse().unwrap();

assert_eq!(
check_version_compatibility(&"1.1.2".parse().unwrap(), &expected_version),
VersionCompatibility {
is_major_supported: false,
is_minor_supported: true,
is_patch_supported: true,
supported_version: expected_version.clone()
}
);

assert_eq!(
check_version_compatibility(&"1.2.2".parse().unwrap(), &expected_version),
VersionCompatibility {
is_major_supported: false,
is_minor_supported: false,
is_patch_supported: true,
supported_version: expected_version.clone()
}
);

assert_eq!(
check_version_compatibility(&"1.1.3".parse().unwrap(), &expected_version),
VersionCompatibility {
is_major_supported: false,
is_minor_supported: true,
is_patch_supported: false,
supported_version: expected_version.clone()
}
);

assert_eq!(
check_version_compatibility(&"0.2.2".parse().unwrap(), &expected_version),
VersionCompatibility {
is_major_supported: true,
is_minor_supported: false,
is_patch_supported: true,
supported_version: expected_version.clone()
}
);

assert_eq!(
check_version_compatibility(&"0.2.3".parse().unwrap(), &expected_version),
VersionCompatibility {
is_major_supported: true,
is_minor_supported: false,
is_patch_supported: false,
supported_version: expected_version.clone()
}
);

assert_eq!(
check_version_compatibility(&"0.1.3".parse().unwrap(), &expected_version),
VersionCompatibility {
is_major_supported: true,
is_minor_supported: true,
is_patch_supported: false,
supported_version: expected_version.clone()
}
);

assert_eq!(
check_version_compatibility(&"0.1.2".parse().unwrap(), &expected_version),
VersionCompatibility {
is_major_supported: true,
is_minor_supported: true,
is_patch_supported: true,
supported_version: expected_version.clone()
}
);
}
}