-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: 🐛 try fix for fullnet payment stream test
- Loading branch information
Showing
1 changed file
with
122 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,18 +28,38 @@ describeMspNet("Single MSP collecting debt", ({ before, createMspApi, it, create | |
const destination = ["test/whatsup.jpg", "test/adolphus.jpg", "test/smile.jpg"]; | ||
const bucketName = "nothingmuch-3"; | ||
|
||
// Get the value propositions from the MSP. It should have at least one | ||
const valueProps = await userApi.call.storageProvidersApi.queryValuePropositionsForMsp( | ||
userApi.shConsts.DUMMY_MSP_ID | ||
); | ||
|
||
// Get the ID of the first one. This is going to be used to access the price per giga-unit of data per tick | ||
const valuePropId = valueProps[0].id; | ||
|
||
// Create a bucket for the user in this MSP | ||
const newBucketEventEvent = await userApi.createBucket(bucketName, valuePropId); | ||
const newBucketEventDataBlob = | ||
userApi.events.fileSystem.NewBucket.is(newBucketEventEvent) && newBucketEventEvent.data; | ||
assert(newBucketEventDataBlob, "NewBucket event data does not match expected type"); | ||
|
||
// Check that the payment stream between the user and the MSP was created and has a rate equal | ||
// to the rate for a zero-sized bucket | ||
const maybePaymentStream = await userApi.query.paymentStreams.fixedRatePaymentStreams( | ||
userApi.shConsts.DUMMY_MSP_ID, | ||
userApi.shConsts.NODE_INFOS.user.AddressId | ||
); | ||
assert(maybePaymentStream.isSome, "Payment stream not found"); | ||
let paymentStream = maybePaymentStream.unwrap(); | ||
const zeroSizeBucketFixedRate = userApi.consts.providers.zeroSizeBucketFixedRate.toNumber(); | ||
strictEqual( | ||
paymentStream.rate.toNumber(), | ||
zeroSizeBucketFixedRate, | ||
"Payment stream rate does not match the expected value" | ||
); | ||
|
||
// Get the bucket ID from the event | ||
bucketId = newBucketEventDataBlob.bucketId; | ||
|
||
// Load each file in storage and issue the storage requests | ||
const txs = []; | ||
for (let i = 0; i < source.length; i++) { | ||
const { fingerprint, file_size, location } = | ||
|
@@ -61,24 +81,27 @@ describeMspNet("Single MSP collecting debt", ({ before, createMspApi, it, create | |
) | ||
); | ||
} | ||
|
||
await userApi.block.seal({ calls: txs, signer: shUser }); | ||
|
||
// Allow time for the MSP to receive and store the file from the user | ||
await sleep(3000); | ||
|
||
const events = await userApi.assert.eventMany("fileSystem", "NewStorageRequest"); | ||
// Allow time for the MSP to receive and store the files from the user | ||
await sleep(5000); | ||
|
||
const matchedEvents = events.filter((e) => | ||
// Check that the storage request submission events were emitted | ||
const newStorageRequestEvents = await userApi.assert.eventMany( | ||
"fileSystem", | ||
"NewStorageRequest" | ||
); | ||
const matchedStorageRequestEvents = newStorageRequestEvents.filter((e) => | ||
userApi.events.fileSystem.NewStorageRequest.is(e.event) | ||
); | ||
assert( | ||
matchedEvents.length === source.length, | ||
matchedStorageRequestEvents.length === source.length, | ||
`Expected ${source.length} NewStorageRequest events` | ||
); | ||
|
||
// For each issued storage request, check that the file is in the MSP's storage | ||
const issuedFileKeys = []; | ||
for (const e of matchedEvents) { | ||
for (const e of matchedStorageRequestEvents) { | ||
const newStorageRequestDataBlob = | ||
userApi.events.fileSystem.NewStorageRequest.is(e.event) && e.event.data; | ||
|
||
|
@@ -96,26 +119,31 @@ describeMspNet("Single MSP collecting debt", ({ before, createMspApi, it, create | |
issuedFileKeys.push(newStorageRequestDataBlob.fileKey); | ||
} | ||
|
||
// Seal block containing the MSP's transaction response to the storage request | ||
// Seal block containing the MSP's transaction response to the first received storage request | ||
await userApi.wait.mspResponseInTxPool(); | ||
await userApi.block.seal(); | ||
|
||
let mspAcceptedStorageRequestDataBlob: any = undefined; | ||
|
||
const eventsRecorded = await userApi.query.system.events(); | ||
const mspAcceptedStorageRequestEvent = eventsRecorded.find( | ||
(e) => e.event.section === "fileSystem" && e.event.method === "MspAcceptedStorageRequest" | ||
// Check that there's only one `MspAcceptedStorageRequest` event | ||
let mspAcceptedStorageRequestEvents = await userApi.assert.eventMany( | ||
"fileSystem", | ||
"MspAcceptedStorageRequest" | ||
); | ||
assert( | ||
mspAcceptedStorageRequestEvents.length === 1, | ||
"Expected a single MspAcceptedStorageRequest event" | ||
); | ||
|
||
// Get its file key | ||
const mspAcceptedStorageRequestEvent = mspAcceptedStorageRequestEvents[0]; | ||
if (mspAcceptedStorageRequestEvent) { | ||
mspAcceptedStorageRequestDataBlob = | ||
userApi.events.fileSystem.MspAcceptedStorageRequest.is( | ||
mspAcceptedStorageRequestEvent.event | ||
) && mspAcceptedStorageRequestEvent.event.data; | ||
} | ||
|
||
const acceptedFileKey = mspAcceptedStorageRequestDataBlob.fileKey.toString(); | ||
|
||
assert(acceptedFileKey, "MspAcceptedStorageRequest event were found"); | ||
|
||
// There is only a single key being accepted since it is the first file key to be processed and there is nothing to batch. | ||
|
@@ -127,10 +155,12 @@ describeMspNet("Single MSP collecting debt", ({ before, createMspApi, it, create | |
// Allow time for the MSP to update the local forest root | ||
await sleep(3000); | ||
|
||
// Get the root of the bucket now that the file has been stored | ||
const localBucketRoot = await mspApi.rpc.storagehubclient.getForestRoot( | ||
newBucketEventDataBlob.bucketId.toString() | ||
); | ||
|
||
// Ensure the `BucketRootChanged` event was emitted | ||
const { event: bucketRootChangedEvent } = await userApi.assert.eventPresent( | ||
"providers", | ||
"BucketRootChanged" | ||
|
@@ -145,22 +175,47 @@ describeMspNet("Single MSP collecting debt", ({ before, createMspApi, it, create | |
"Expected BucketRootChanged event but received event of different type" | ||
); | ||
|
||
// Ensure the new root of the bucket matches the one in the event | ||
strictEqual(bucketRootChangedDataBlob.newRoot.toString(), localBucketRoot.toString()); | ||
|
||
// Ensure that the file has been stored in the MSP's forest, in the bucket's trie | ||
const isFileInForest = await mspApi.rpc.storagehubclient.isFileInForest( | ||
newBucketEventDataBlob.bucketId.toString(), | ||
acceptedFileKey | ||
); | ||
|
||
assert(isFileInForest.isTrue, "File is not in forest"); | ||
|
||
// Check that the rate of the payment stream between the user and the MSP has been updated | ||
// to reflect the new size of the bucket | ||
paymentStream = ( | ||
await userApi.query.paymentStreams.fixedRatePaymentStreams( | ||
DUMMY_MSP_ID, | ||
userApi.shConsts.NODE_INFOS.user.AddressId | ||
) | ||
).unwrap(); | ||
const firstFileSize = ( | ||
await userApi.rpc.storagehubclient.getFileMetadata(bucketId, acceptedFileKey) | ||
) | ||
.unwrap() | ||
Check failure on line 200 in test/suites/integration/msp/debt-collection.test.ts GitHub Actions / Run FullNet Tests (1)MSP receives files from user after issued storage requests
Check failure on line 200 in test/suites/integration/msp/debt-collection.test.ts GitHub Actions / Run FullNet Tests (1)MSP receives files from user after issued storage requests
|
||
.file_size.toNumber(); | ||
const unitsInGigaUnit = 1024 * 1024 * 1024; | ||
let expectedPaymentStreamRate = Math.round( | ||
(valueProps[0].value_prop.price_per_giga_unit_of_data_per_block.toNumber() * firstFileSize) / | ||
unitsInGigaUnit + | ||
zeroSizeBucketFixedRate | ||
); | ||
strictEqual(paymentStream.rate.toNumber(), expectedPaymentStreamRate); | ||
|
||
// Seal block containing the MSP's transaction response to the storage request | ||
await userApi.wait.mspResponseInTxPool(); | ||
await userApi.block.seal(); | ||
|
||
const fileKeys2: string[] = []; | ||
|
||
const mspAcceptedStorageRequestEvents = await userApi.assert.eventMany( | ||
// Since we gave enough time to the MSP to receive both files before processing the response for the | ||
// first one, we should have two `MspAcceptedStorageRequest` events (because of the batching) | ||
mspAcceptedStorageRequestEvents = await userApi.assert.eventMany( | ||
"fileSystem", | ||
"MspAcceptedStorageRequest" | ||
); | ||
|
@@ -178,10 +233,12 @@ describeMspNet("Single MSP collecting debt", ({ before, createMspApi, it, create | |
// Allow time for the MSP to update the local forest root | ||
await sleep(3000); | ||
|
||
// Get the root of the bucket now that the files have been stored | ||
const localBucketRoot2 = await mspApi.rpc.storagehubclient.getForestRoot( | ||
newBucketEventDataBlob.bucketId.toString() | ||
); | ||
|
||
// Ensure the `BucketRootChanged` event was emitted | ||
const { event: bucketRootChangedEvent2 } = await userApi.assert.eventPresent( | ||
"providers", | ||
"BucketRootChanged" | ||
|
@@ -196,32 +253,75 @@ describeMspNet("Single MSP collecting debt", ({ before, createMspApi, it, create | |
"Expected BucketRootChanged event but received event of different type" | ||
); | ||
|
||
// Ensure the new root of the bucket matches the one in the event | ||
strictEqual(bucketRootChangedDataBlob2.newRoot.toString(), localBucketRoot2.toString()); | ||
|
||
// Ensure that the files have been stored in the MSP's forest, in the bucket's trie | ||
for (const fileKey of fileKeys2) { | ||
const isFileInForest = await mspApi.rpc.storagehubclient.isFileInForest( | ||
newBucketEventDataBlob.bucketId.toString(), | ||
fileKey | ||
); | ||
assert(isFileInForest.isTrue, "File is not in forest"); | ||
} | ||
|
||
// Check that the rate of the payment stream between the user and the MSP has been updated | ||
// to reflect the new size of the bucket | ||
paymentStream = ( | ||
await userApi.query.paymentStreams.fixedRatePaymentStreams( | ||
DUMMY_MSP_ID, | ||
userApi.shConsts.NODE_INFOS.user.AddressId | ||
) | ||
).unwrap(); | ||
const secondFileSize = ( | ||
await userApi.rpc.storagehubclient.getFileMetadata(bucketId, fileKeys2[0]) | ||
) | ||
.unwrap() | ||
.file_size.toNumber(); | ||
const thirdFileSize = ( | ||
await userApi.rpc.storagehubclient.getFileMetadata(bucketId, fileKeys2[1]) | ||
) | ||
.unwrap() | ||
.file_size.toNumber(); | ||
const sumOfSizeOfFiles = firstFileSize + secondFileSize + thirdFileSize; | ||
expectedPaymentStreamRate = Math.round( | ||
(valueProps[0].value_prop.price_per_giga_unit_of_data_per_block.toNumber() * | ||
sumOfSizeOfFiles) / | ||
unitsInGigaUnit + | ||
zeroSizeBucketFixedRate | ||
); | ||
strictEqual(paymentStream.rate.toNumber(), expectedPaymentStreamRate); | ||
}); | ||
|
||
it("MSP is charging user", async () => { | ||
// Get the current block | ||
let currentBlock = await userApi.rpc.chain.getHeader(); | ||
let currentBlockNumber = currentBlock.number.toNumber(); | ||
|
||
const blocksToAdvance = MSP_CHARGING_PERIOD - (currentBlockNumber % MSP_CHARGING_PERIOD) + 1; | ||
await userApi.block.skipTo(currentBlockNumber + blocksToAdvance - 1); | ||
// We want to advance to the next time the MSP is going to try to charge the user. | ||
const blocksToAdvance = MSP_CHARGING_PERIOD - (currentBlockNumber % MSP_CHARGING_PERIOD); | ||
await userApi.block.skipTo(currentBlockNumber + blocksToAdvance); | ||
|
||
// Wait for the MSP to try to charge the user and seal a block. | ||
await sleep(2000); | ||
await userApi.block.seal(); | ||
|
||
// Verify that the MSP charged the users after the notified. | ||
await userApi.assert.eventPresent("paymentStreams", "PaymentStreamCharged"); | ||
// Verify that the MSP was able to charge the user after the notify period. | ||
const firstPaymentStreamChargedEvent = await userApi.assert.eventPresent( | ||
"paymentStreams", | ||
"PaymentStreamCharged" | ||
); | ||
assert( | ||
userApi.events.paymentStreams.PaymentStreamCharged.is(firstPaymentStreamChargedEvent.event) | ||
); | ||
assert(firstPaymentStreamChargedEvent.event.data.providerId.eq(DUMMY_MSP_ID)); | ||
assert( | ||
firstPaymentStreamChargedEvent.event.data.userAccount.eq( | ||
userApi.shConsts.NODE_INFOS.user.AddressId | ||
) | ||
); | ||
|
||
// Advance many MSP charging periods, to charge again, but this time with a known number of | ||
// Advance many MSP charging periods to charge again, but this time with a known number of | ||
// blocks since last charged. That way, we can check for the exact amount charged. | ||
// Since the MSP is going to charge each period, the last charge should be for one period. | ||
currentBlock = await userApi.rpc.chain.getHeader(); | ||
|
@@ -237,7 +337,7 @@ describeMspNet("Single MSP collecting debt", ({ before, createMspApi, it, create | |
valueProps[0].value_prop.price_per_giga_unit_of_data_per_block.toNumber(); | ||
const unitsInGigaUnit = 1024 * 1024 * 1024; | ||
const expectedRateOfPaymentStream = | ||
Math.ceil((pricePerGigaUnitOfDataPerBlock * bucketSize) / unitsInGigaUnit) + | ||
Math.round((pricePerGigaUnitOfDataPerBlock * bucketSize) / unitsInGigaUnit) + | ||
userApi.consts.providers.zeroSizeBucketFixedRate.toNumber(); | ||
const paymentStream = ( | ||
await userApi.query.paymentStreams.fixedRatePaymentStreams( | ||
|