Skip to content

Commit

Permalink
compare fuel-indexer and forc-index versions
Browse files Browse the repository at this point in the history
  • Loading branch information
lostman committed Oct 9, 2023
1 parent d9e274c commit 6cc9d84
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 4 deletions.
1 change: 1 addition & 0 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 packages/fuel-indexer-api-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
tower = { version = "0.4", features = ["limit", "buffer"] }
tower-http = { version = "0.3", features = ["fs", "trace", "cors", "limit"] }
tracing = { workspace = true }
wasmer = "4"

[features]
default = ["metrics"]
Expand Down
8 changes: 8 additions & 0 deletions packages/fuel-indexer-api-server/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ pub enum ApiError {
SqlValidator(#[from] crate::sql::SqlValidatorError),
#[error("ParseError: {0:?}")]
ParseError(#[from] strum::ParseError),
#[error("The forc-index version {toolchain_version} does not match the fuel-indexer version {fuel_indexer_version}.")]
ToolchainVersionMismatch {
toolchain_version: String,
fuel_indexer_version: String,
},
#[error("Other error: {0}")]
OtherError(String),
}
Expand Down Expand Up @@ -168,6 +173,9 @@ impl IntoResponse for ApiError {
// This is currently the only type of ParseError on the web server
(StatusCode::BAD_REQUEST, format!("Invalid asset type: {e}"))
}
ApiError::ToolchainVersionMismatch{fuel_indexer_version, toolchain_version} => {
(StatusCode::METHOD_NOT_ALLOWED, format!("The toolchain version {toolchain_version} that the WASM module was compiled with does not match the fuel-indexer-versiion {fuel_indexer_version}"))
}
_ => (StatusCode::INTERNAL_SERVER_ERROR, generic_details),
};

Expand Down
48 changes: 48 additions & 0 deletions packages/fuel-indexer-api-server/src/ffi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use wasmer::{AsStoreMut, Instance, MemoryView, StoreMut, WasmPtr};

pub(crate) fn check_wasm_toolchain_version(data: Vec<u8>) -> anyhow::Result<String> {
let mut store = wasmer::Store::default();

let module = wasmer::Module::new(&store, data.clone())?;

let imports = wasmer::imports! {};

let instance = wasmer::Instance::new(&mut store, &module, &imports)?;

let version = get_toolchain_version(&mut store.as_store_mut(), &instance)?;

Ok(version)
}

/// Get the toolchain version stored in the WASM module.
pub fn get_toolchain_version(
store: &mut StoreMut,
instance: &Instance,
) -> anyhow::Result<String> {
let exports = &instance.exports;

let ptr = exports
.get_function("get_toolchain_version_ptr")?
.call(store, &[])?[0]
.i32()
.ok_or_else(|| anyhow::anyhow!("get_toolchain_version_ptr".to_string()))?
as u32;

let len = exports
.get_function("get_toolchain_version_len")?
.call(store, &[])?[0]
.i32()
.ok_or_else(|| anyhow::anyhow!("get_toolchain_version_len".to_string()))?
as u32;

let memory = exports.get_memory("memory")?.view(store);
let version = get_string(&memory, ptr, len)?;

Ok(version)
}

/// Fetch the string at the given pointer from memory.
fn get_string(mem: &MemoryView, ptr: u32, len: u32) -> anyhow::Result<String> {
let result = WasmPtr::<u8>::new(ptr).read_utf8_string(mem, len)?;
Ok(result)
}
1 change: 1 addition & 0 deletions packages/fuel-indexer-api-server/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
pub mod api;
pub mod cli;
pub(crate) mod commands;
pub(crate) mod ffi;
pub(crate) mod middleware;
pub(crate) mod models;
pub(crate) mod sql;
Expand Down
21 changes: 18 additions & 3 deletions packages/fuel-indexer-api-server/src/uses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,18 @@ pub(crate) async fn register_indexer_assets(

let multipart = multipart.ok_or_else(ApiError::default)?;

let (replace_indexer, asset_bytes) =
let (toolchain_version, replace_indexer, asset_bytes) =
parse_register_indexer_multipart(multipart).await?;

let fuel_indexer_version = env!("CARGO_PKG_VERSION").to_string();

if toolchain_version != fuel_indexer_version {
return Err(ApiError::ToolchainVersionMismatch {
toolchain_version,
fuel_indexer_version,
});
}

queries::start_transaction(&mut conn).await?;

let result = register_indexer_assets_transaction(
Expand Down Expand Up @@ -374,7 +383,8 @@ async fn register_indexer_assets_transaction(
// schema, and the WASM module.
async fn parse_register_indexer_multipart(
mut multipart: Multipart,
) -> ApiResult<(bool, Vec<(IndexerAssetType, Vec<u8>)>)> {
) -> ApiResult<(String, bool, Vec<(IndexerAssetType, Vec<u8>)>)> {
let mut toolchain_version: String = "unknown".to_string();
let mut replace_indexer: bool = false;
let mut assets: Vec<(IndexerAssetType, Vec<u8>)> = vec![];

Expand All @@ -390,12 +400,17 @@ async fn parse_register_indexer_multipart(
}
name => {
let asset_type = IndexerAssetType::from_str(name)?;
if asset_type == IndexerAssetType::Wasm {
toolchain_version =
crate::ffi::check_wasm_toolchain_version(data.clone().into())
.unwrap_or("none".to_string());
};
assets.push((asset_type, data.to_vec()));
}
};
}

Ok((replace_indexer, assets))
Ok((toolchain_version, replace_indexer, assets))
}

/// Return a `Nonce` to be used for authentication.
Expand Down
4 changes: 4 additions & 0 deletions packages/fuel-indexer-macros/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,14 @@ pub(crate) fn process_graphql_schema(

let version_tokens = const_item("VERSION", schema.version());

let toolchain_version_tokens =
const_item("TOOLCHAIN_VERSION", env!("CARGO_PKG_VERSION"));

let mut output = quote! {
#namespace_tokens
#identifer_tokens
#version_tokens
#toolchain_version_tokens
};

let schema =
Expand Down
Binary file not shown.
2 changes: 1 addition & 1 deletion packages/fuel-indexer/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub enum FFIError {
None(String),
}

/// Get the version of the indexer schema stored in the WASM instance.
/// Get the version of the indexer schema stored in the WASM module.
pub fn get_version(store: &mut StoreMut, instance: &Instance) -> FFIResult<String> {
let exports = &instance.exports;

Expand Down

0 comments on commit 6cc9d84

Please sign in to comment.