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: msp check previous block #337

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

undercover-cactus
Copy link
Contributor

@undercover-cactus undercover-cactus commented Jan 22, 2025

In this PR, we add a check that allow msp to answer to NewStorageRequests when catching up to the block chain.

When closing up to the tip of the chain, a function will be called that will check for all the storage requests through a runtime api. If the storage request as the MSP id in it it will triggered a NewStorageRequest event. The MSP will then proceed the volunteer to it.

@undercover-cactus undercover-cactus force-pushed the feat/msp-check-previous-block branch from 3757114 to 74d4946 Compare January 23, 2025 11:24
@undercover-cactus undercover-cactus marked this pull request as ready for review January 23, 2025 12:39
// TODO: Send events to check that this node has a Forest Storage for each Bucket this MSP manages.
// TODO: Catch up to Forest root writes in the Bucket's Forests.

let storage_requests: Vec<(H256, StorageRequestMetadata)> = self
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though it is technically impossible for the storage_requests_by_msp to return duplicate storage requests, I would still make this a map instead to match runtime storage and have it be impossible on client side to emit more than a single event for the same file key

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with the above comment ⬆️. Making this a map instead of a vec would be ideal.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @undercover-cactus! Just a quick tip for PR comments in general: please don’t resolve comments if no action has been taken. If there’s nothing to do, it’s best to leave a reply explaining why instead of resolving it.
Ideally, the reviewer should be the one to resolve their own comments, unless it’s something simple and directly addressed. This helps a lot when re-reviewing to track what’s actually been handled. Thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep sorry.

I was going for it at first but I realize that HashMap need the key type to have the trait Hash which is in the std. And std is not allow in the runtime. In theory, having duplicate is not possible so it doesn't add much. I still convert it in the handler.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to use HashMap, you can use BTreeMap instead, which is available in the runtime, under the sp_std crate.

pallets/file-system/src/utils.rs Outdated Show resolved Hide resolved
client/blockchain-service/src/handler.rs Outdated Show resolved Hide resolved
Copy link
Contributor

@links234 links234 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some preliminary comments.

.unresponded_storage_requests_by_msp(block_hash, msp_id)
.unwrap();

for (file_key, sr) in storage_requests {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe ignore since it's personal preference

Can you rename sr to storage_request?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is hard to differentiate storage_requests and storage_request when browsing the code. I realize that sr is not a good name but we can quickly understand what it is by looking at the loop. It is a trade off and I guess linked to programming habits.

Maybe to improve readability I could add a comment ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a comment is fine by me, btw.

node/src/tasks/bsp_charge_fees.rs Outdated Show resolved Hide resolved
pallets/file-system/src/utils.rs Outdated Show resolved Hide resolved
// TODO: Send events to check that this node has a Forest Storage for each Bucket this MSP manages.
// TODO: Catch up to Forest root writes in the Bucket's Forests.

let storage_requests: Vec<(H256, StorageRequestMetadata)> = self
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with the above comment ⬆️. Making this a map instead of a vec would be ideal.

.client
.runtime_api()
.pending_storage_requests_by_msp(block_hash, msp_id)
.unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid unwrapping here, as it would panic the whole node. From what I see this runtime API call can fail if there is an internal error while calling the runtime API. So I'd handle the error logging that there was an internal error while trying to call the runtime API. Ideally, make it noticeable!

.unresponded_storage_requests_by_msp(block_hash, msp_id)
.unwrap();

for (file_key, sr) in storage_requests {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a comment is fine by me, btw.

@@ -45,19 +46,27 @@ pub enum QueryConfirmChunksToProveForFileError {
ChallengedChunkToChunkIdError,
}

/// Error type for the `pending_storage_requests_by_msp`.
#[derive(Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)]
pub enum StorageRequestsByMSPError {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub enum StorageRequestsByMSPError {
pub enum StorageRequestsByMspError {

pub fn pending_storage_requests_by_msp(
msp_id: ProviderIdFor<T>,
) -> Vec<(MerkleHash<T>, StorageRequestMetadata<T>)> {
// Get the storeage requests for a specific MSP
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Get the storeage requests for a specific MSP
// Get the storage requests for a specific MSP

node/src/tasks/bsp_charge_fees.rs Show resolved Hide resolved
Comment on lines +19 to +25
it("Network launches and can be queried", async () => {
const userNodePeerId = await userApi.rpc.system.localPeerId();
strictEqual(userNodePeerId.toString(), userApi.shConsts.NODE_INFOS.user.expectedPeerId);

const mspNodePeerId = await mspApi.rpc.system.localPeerId();
strictEqual(mspNodePeerId.toString(), userApi.shConsts.NODE_INFOS.msp1.expectedPeerId);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove this one, it's everywhere 😂

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can we remove it ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's testing the connections to the nodes, and we are testing this in pretty much every test. It doesn't hurt that it's there, but at this point it's not necessary really.

Comment on lines 47 to 48
// We need to wait so it won't try to answer the request storage
await sleep(5000);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need to wait here? It won't respond if it is paused.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had the behavior that if even if the container was paused I had a NewStorageRequest event from the MSP. So I added a delay to be sure it is paused before creating the new storage request.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could pause the container even before creating the bucket, or even add a check to see that it is not responding. But waiting 5s will unnecessarily slow down the integration test suite.

Comment on lines +75 to +95
// Advancing 10 blocks to see if MSP catchup
await userApi.block.skip(10);

await userApi.docker.restartBspContainer({ containerName: "docker-sh-msp-1" });

// need to wait for the container to be up again
// await sleep(5000);

// NOTE:
// We shouldn't have to recreate an API but any other attempt to reconnect failed
// Also had to guess for the port of MSP 1
// await using newMspApi = await createApi("ws://127.0.0.1:9777");

// Required to trigger out of sync mode
// await userApi.rpc.engine.createBlock(true, true);

// await waitFor({
// lambda: async () =>
// (await newMspApi.rpc.storagehubclient.isFileInFileStorage(event.data.fileKey)).isFileFound
// });

// await userApi.assert.eventPresent("fileSystem", "MspAcceptedStorageRequest");
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happened here? This is not really testing the right outcome 😂.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MSP being offline the user cannot send it the file and the MSP can never finish the task because it doesn't have the file.

#361 will solve this by downloading the file from a BSP in this particular case. The commented part in this test should then pass. It is commented so the CI would pass.

Copy link
Contributor

@ffarall ffarall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commenting and not approving due to the missing test. But good job.

@@ -0,0 +1,97 @@
import assert, { strictEqual } from "node:assert";
import { describeMspNet, shUser, type EnrichedBspApi, sleep } from "../../../util";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CI is complaining about this unused sleep import.

Comment on lines 28 to 29
use sp_std::collections::btree_map::BTreeMap;
use sp_std::prelude::Vec;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, merge these two use statements into one.

@undercover-cactus undercover-cactus marked this pull request as draft February 17, 2025 16:19
@undercover-cactus undercover-cactus force-pushed the feat/msp-check-previous-block branch from ca38439 to 6c17fb7 Compare February 19, 2025 12:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants