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

Call ID Insertion and Resolution For #520 #533

Merged
merged 12 commits into from
Dec 9, 2024
4 changes: 2 additions & 2 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
Expand Up @@ -63,7 +63,7 @@ cargo-tangle = { path = "./cli", version = "0.3.2" }
cargo_metadata = { version = "0.18.1" }

# Tangle-related dependencies
tangle-subxt = { version = "0.7.0", default-features = false }
tangle-subxt = { git = "https://github.com/tangle-network/tangle", default-features = false }
subxt-signer = { version = "0.37.0", default-features = false }
subxt = { version = "0.37.0", default-features = false }
subxt-core = { version = "0.37.0", default-features = false }
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ passing `--clean` as an argument to reset the chain and any keys.
Then, you can run:

```bash
cargo test --package blueprint-test-utils tests_standard::test_externalities_gadget_starts -- --nocapture
cargo test --package blueprint-test-utils test_incredible_squaring -- --nocapture
```

Since testing is in beta stage, each time the blueprint is run, you
Expand Down
5 changes: 2 additions & 3 deletions blueprint-manager/src/executor/event_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,11 +266,10 @@ pub(crate) async fn handle_tangle_event(

// Ensure that we have a test fetcher if we are in test mode
if gadget_manager_opts.test_mode && test_fetcher_idx.is_none() {
warn!(
return Err(color_eyre::Report::msg(format!(
"No testing fetcher found for blueprint `{}` despite operating in TEST MODE",
blueprint.name,
);
continue;
)));
}

// Ensure that we have only one fetcher if we are in test mode
Expand Down
46 changes: 34 additions & 12 deletions blueprint-metadata/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,22 +316,44 @@ fn generate_gadget(package: &Package) -> Gadget<'static> {
let root = Path::new(&root)
.canonicalize()
.expect("Failed to canonicalize root dir");
let Some(gadget) = package.metadata.get("gadget") else {
let mut sources = vec![];
if let Some(gadget) = package.metadata.get("gadget") {
let gadget: Gadget<'static> =
serde_json::from_value(gadget.clone()).expect("Failed to deserialize gadget.");
if let Gadget::Native(NativeGadget { sources: fetchers }) = gadget {
sources.extend(fetchers);
} else {
panic!("Currently unsupported gadget type has been parsed")
}
} else {
eprintln!("No gadget metadata found in the Cargo.toml.");
eprintln!("For more information, see:");
eprintln!("<TODO>");
// For now, we just return an empty gadget
return Gadget::Native(NativeGadget {
sources: vec![GadgetSource {
fetcher: GadgetSourceFetcher::Testing(TestFetcher {
cargo_package: package.name.clone().into(),
cargo_bin: "main".into(),
base_path: format!("{}", root.display()).into(),
}),
}],
});
};
serde_json::from_value(gadget.clone()).expect("Failed to deserialize gadget.")

let has_test_fetcher = sources.iter().any(|fetcher| {
matches!(
fetcher,
GadgetSource {
fetcher: GadgetSourceFetcher::Testing(..)
}
)
});

if !has_test_fetcher {
println!("Adding test fetcher since none exists");
sources.push(GadgetSource {
fetcher: GadgetSourceFetcher::Testing(TestFetcher {
cargo_package: package.name.clone().into(),
cargo_bin: "main".into(),
base_path: format!("{}", root.display()).into(),
}),
})
}

assert_ne!(sources.len(), 0, "No sources found for the gadget");

Gadget::Native(NativeGadget { sources })
}

fn generate_rustdoc() -> Crate {
Expand Down
8 changes: 6 additions & 2 deletions blueprint-test-utils/src/tangle/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub fn run() -> Result<SubstrateNode, Error> {
&tangle_from_env,
"../tangle/target/release/tangle",
"../../tangle/target/release/tangle",
"../../../tangle/target/release/tangle",
])
.arg("validator")
.arg_val("rpc-cors", "all")
Expand Down Expand Up @@ -56,7 +57,8 @@ macro_rules! test_tangle_blueprint {
$T:tt,
$job_id:tt,
[$($inputs:expr),*],
[$($expected_output:expr),*]
[$($expected_output:expr),*],
$call_id:expr,
) => {
::blueprint_test_utils::tangle_blueprint_test_template!(
$N,
Expand All @@ -77,6 +79,7 @@ macro_rules! test_tangle_blueprint {
service_id,
$job_id as ::blueprint_test_utils::Job,
job_args,
$call_id,
)
.await
.expect("Failed to submit job");
Expand Down Expand Up @@ -113,7 +116,8 @@ macro_rules! test_tangle_blueprint {
$job_id:tt,
[$($input:expr),*],
[$($expected_output:expr),*]
$call_id:expr,
) => {
::blueprint_test_utils::test_tangle_blueprint!($N, $N, $job_id, [$($input),+], [$($expected_output),+]);
::blueprint_test_utils::test_tangle_blueprint!($N, $N, $job_id, [$($input),+], [$($expected_output),+], $call_id);
};
}
7 changes: 6 additions & 1 deletion blueprint-test-utils/src/tangle/transactions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use gadget_sdk::tangle_subxt::tangle_testnet_runtime::api::services::events::{Jo
use subxt::tx::TxProgress;
use gadget_sdk::clients::tangle::runtime::TangleConfig;
use gadget_sdk::subxt_core::tx::signer::Signer;
use gadget_sdk::tangle_subxt::tangle_testnet_runtime::api::runtime_types::tangle_primitives::services::Asset;
use gadget_sdk::tangle_subxt::tangle_testnet_runtime::api::services::calls::types::request::{Assets, PaymentAsset};
use crate::TestClient;

/// Deploy a new MBSM revision and returns the result.
Expand Down Expand Up @@ -138,6 +140,7 @@ pub async fn submit_job(
service_id: u64,
job_id: Job,
job_params: Args,
call_id: u64,
) -> Result<JobCalled, Box<dyn Error>> {
let call = api::tx().services().call(service_id, job_id, job_params);
let events = client
Expand All @@ -153,6 +156,7 @@ pub async fn submit_job(
if job_called.service_id == service_id
&& job_called.job == job_id
&& user.account_id() == job_called.caller
&& job_called.call_id == call_id
{
return Ok(job_called);
}
Expand All @@ -175,8 +179,9 @@ pub async fn request_service(
test_nodes.clone(),
test_nodes,
Default::default(),
vec![0],
Assets::from([0]),
1000,
PaymentAsset::from(Asset::Custom(0)),
value,
);
let res = client
Expand Down

Large diffs are not rendered by default.

22 changes: 17 additions & 5 deletions blueprints/examples/src/raw_tangle_events.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
use gadget_sdk::config::StdGadgetConfiguration;
use gadget_sdk::contexts::TangleClientContext;
use gadget_sdk::event_listener::tangle::{TangleEvent, TangleEventListener};
use gadget_sdk::event_utils::InitializableEventHandler;
use gadget_sdk::job;
use gadget_sdk::tangle_subxt::tangle_testnet_runtime::api;

#[derive(Clone)]
pub struct MyContext;
#[derive(Clone, TangleClientContext)]
pub struct MyContext {
#[config]
sdk_config: StdGadgetConfiguration,
#[call_id]
call_id: Option<u64>,
}

pub async fn constructor(
env: StdGadgetConfiguration,
Expand All @@ -17,9 +23,15 @@ pub async fn constructor(
.map_err(|e| color_eyre::eyre::eyre!(e))?;

gadget_sdk::info!("Starting the event watcher for {} ...", signer.account_id());
RawEventHandler::new(&env, MyContext)
.await
.map_err(|e| color_eyre::eyre::eyre!(e))
RawEventHandler::new(
&env,
MyContext {
sdk_config: env.clone(),
call_id: None,
},
)
.await
.map_err(|e| color_eyre::eyre::eyre!(e))
}

#[job(
Expand Down
16 changes: 12 additions & 4 deletions blueprints/examples/src/services_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ use gadget_sdk::tangle_subxt::tangle_testnet_runtime::api::services::events::Job
pub struct ExampleServiceContext {
#[config]
sdk_config: StdGadgetConfiguration,
#[call_id]
call_id: Option<u64>,
}

pub async fn constructor(
Expand All @@ -24,9 +26,15 @@ pub async fn constructor(
.map_err(|e| color_eyre::eyre::eyre!(e))?;

gadget_sdk::info!("Starting the event watcher for {} ...", signer.account_id());
HandleJobEventHandler::new(&env.clone(), ExampleServiceContext { sdk_config: env })
.await
.map_err(|e| color_eyre::eyre::eyre!(e))
HandleJobEventHandler::new(
&env.clone(),
ExampleServiceContext {
sdk_config: env,
call_id: None,
},
)
.await
.map_err(|e| color_eyre::eyre::eyre!(e))
}

#[job(
Expand All @@ -39,8 +47,8 @@ pub async fn constructor(
),
)]
pub async fn handle_job(
job_details: Vec<u8>,
context: ExampleServiceContext,
job_details: Vec<u8>,
) -> Result<u64, gadget_sdk::Error> {
let client = context.tangle_client().await.unwrap();
let blueprint_owner = context.current_blueprint_owner(&client).await.unwrap();
Expand Down
2 changes: 1 addition & 1 deletion blueprints/incredible-squaring/contracts/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
src = "src"
out = "out"
libs = ["lib"]
solc_version = "0.8.20"
solc_version = "0.8.20"
2 changes: 1 addition & 1 deletion blueprints/incredible-squaring/contracts/remappings.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ds-test/=lib/ds-test/src/
forge-std/=lib/forge-std/src/
incredible-squaring/=src/
tnt-core/=lib/tnt-core/src/
incredible-squaring/=src/
Original file line number Diff line number Diff line change
Expand Up @@ -23,46 +23,62 @@ contract IncredibleSquaringBlueprint is BlueprintServiceManagerBase {
mapping(uint64 => address) public serviceInstances;

/**
* @dev Hook for service instance requests. Called when a user requests a service
* instance from the blueprint.
* @param serviceId The ID of the requested service.
* @param operatorsOfService The operators involved in the service in bytes array format.
* @param requestInputs Inputs required for the service request in bytes format.
* @dev Hook for service initialization. Called when a service is initialized.
* This hook is called after the service is approved from all of the operators.
*
* @param requestId The ID of the request.
* @param serviceId The ID of the service.
* @param owner The owner of the service.
* @param permittedCallers The list of permitted callers for the service.
* @param ttl The time-to-live for the service.
*/
function onRequest(uint64 serviceId, bytes[] calldata operatorsOfService, bytes calldata requestInputs)
public
payable
virtual
override
onlyFromRootChain
function onServiceInitialized(
uint64 requestId,
uint64 serviceId,
address owner,
address[] calldata permittedCallers,
uint64 ttl
)
external
virtual
override
onlyFromMaster
{
IncredibleSquaringInstance deployed = new IncredibleSquaringInstance(serviceId);
serviceInstances[serviceId] = address(deployed);
}

/**
* @dev Verifies the result of a job call. This function is used to validate the
* outputs of a job execution against the expected results.
* @dev Hook for handling job result. Called when operators send the result
* of a job execution.
* @param serviceId The ID of the service related to the job.
* @param job The job identifier.
* @param jobCallId The unique ID for the job call.
* @param participant The participant (operator) whose result is being verified.
* @param inputs Inputs used for the job execution.
* @param outputs Outputs resulting from the job execution.
* @param operator The operator sending the result in bytes format.
* @param inputs Inputs used for the job execution in bytes format.
* @param outputs Outputs resulting from the job execution in bytes format.
*/
function onJobResult(
uint64 serviceId,
uint8 job,
uint64 jobCallId,
bytes calldata participant,
ServiceOperators.OperatorPreferences calldata operator,
bytes calldata inputs,
bytes calldata outputs
) public payable override {
Serial-ATA marked this conversation as resolved.
Show resolved Hide resolved
// Decode the inputs and outputs
uint256 input = abi.decode(inputs, (uint256));
uint256 output = abi.decode(outputs, (uint256));
// Check if the output is the square of the input
bool isValid = output == input * input;
require(isValid, "Invalid result");
)
external
payable
virtual
override
onlyFromMaster
{
if (jobCallId == 0) {
// Decode the inputs and outputs
uint256 input = abi.decode(inputs, (uint256));
uint256 output = abi.decode(outputs, (uint256));
// Check if the output is the square of the input
bool isValid = output == input * input;
require(isValid, "Invalid result");
}
}
}
Loading
Loading