-
Notifications
You must be signed in to change notification settings - Fork 17
perf!(ServiceProviderRegistry): Bloom Schema #308
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
Conversation
…ing documentation
|
I'm changing the type of capabilities values to Also I have noticed that |
|
Remaining tasks:
Open questions:
|
|
I'm fine with bytes, my main concern with bytes has always been:
peerId is one case of wanting bytes |
…idersByProductType and getProvidersByProductType
| view | ||
| providerExists(providerId) | ||
| returns (bytes memory productData, string[] memory capabilityKeys, bool isActive) | ||
| returns (string[] memory capabilityKeys, bool isActive) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we just return the keys and values here and be done with it? this is one of the most awkward spots - if we don't use key-existence as a signal then we're always going to want the values too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
key existence is a signal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how about we just return ProviderWithProduct here? so this is the single version of getProvidersByProductType
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
key existence is a signal
you're the one arguing to make value necessary even for booleans; in that world I can't think of a case where just getting the keys is useful to me, I just want all of it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you still don't understand. If a capability is a boolean, its existence is sufficient. But that existence cannot be the signaled with the empty string because it is indistinguishable when doing a single key lookup in a solidity mapping.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a key's absence unambiguously signals the capability is not supported, then the key's presence can unambiguously signal the capability is supported. Any nonzero length is thus truthy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need many of these methods. I agree they aren't useful on or off chain. I will check how we are using them tomorrow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a key's absence unambiguously signals the capability is not supported, then the key's presence can unambiguously signal the capability is supported. Any nonzero length is thus truthy.
This is what I've been arguing for here and which is why I want an exists boolean return any time I want to ask for a specific key. I don't want to have to put a value in the value map, I just want to know the key exists and then not care about the value, and to work around the limitations of not having a null or non-zero sentinel in solidity. But we agree that the current implementation of doing that is broken - it should do it properly by iterating over keys that it has and figuring out whether it exists or not. But I also now think we can just do away with that entirely. There may be a case for "tell me the value for this key" or "tell me if you have this key", but with the way this is shaping up, I think all I really ever want out of this is be able to get the full product, keys and values, and deal with it on the client side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use case for querying a single key is for onchain lookup. It should not loop over all of the keys to do that.
|
|
I believe I suggested something similar in the original PR. Would you believe that synapse is fetching all of them and them filtering by isActive? |
Oh yes I would. This whole registry was done way too quick, on both sides. |
|
Trying out my own feedback as a PR: #328 |
|
I'm just coming to terms with the per-day here vs per-month before and per-month that we have in FWSS, it's a bit odd that we have two versions of this. Now an SP has to divide the per month charge that everyone talks about to figure out how many days. We have a standard for what a "month" is in epochs that we use everywhere, it's not abnormal to encode a month as 30 days. Anyway, just my 2c, not a big deal but it's jarring as I update Curio to work with this and think through what an SP has to deal with. The default I have to encode is 83333333333333333 to get close to the 2.5 USDFC we have in WarmStorage. Original thread is #297 (comment) |
|
Curio version on top of #328: filecoin-project/curio#736 |
Co-authored-by: Jakub Sztandera <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SGWM but needs a rebase
| } | ||
| } | ||
| // Enforce minimum schema | ||
| require(BloomSet16.mayContain(foundKeys, requiredKeys), Errors.InsufficientCapabilitiesForProduct(productType)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In theory, one can find a set of keys that match this bloom filter, but it is fine, since the final decision is on the client side and in the approval list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the Bloom filter is used only for that verification, the problem could be avoided by requiring keys to be provided in order. And then stepping through the list of required and provided in order, while allowing extra provided keys.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes we are ultimately validating these fields off-chain. The filter will help prevent accidental omissions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the problem could be avoided by requiring keys to be provided in order
That is a good idea, but this contract's codesize would then scale in the number of required keys rather than the number of products. It can be reduced by using a separate validation library per product. We could then have more specialized on-chain validation of known keys.
* feat(pdp): deal with new ServiceProviderRegistry changes Ref: FilOzone/filecoin-services#308 Ref: FilOzone/filecoin-services#328 * fixup! feat(pdp): deal with new ServiceProviderRegistry changes * fix: treat key presence as truthy for boolean options Co-authored-by: William Morriss <[email protected]> * feat(pdp): add IpniPeerID to PDPOfferingData Signed-off-by: Jakub Sztandera <[email protected]> * feat(pdp): show IpniPeerID in webui, use IpniPeerID in FSUpdatePDP Signed-off-by: Jakub Sztandera <[email protected]> --------- Signed-off-by: Jakub Sztandera <[email protected]> Co-authored-by: William Morriss <[email protected]> Co-authored-by: Jakub Sztandera <[email protected]>
* feat(pdp): deal with new ServiceProviderRegistry changes Ref: FilOzone/filecoin-services#308 Ref: FilOzone/filecoin-services#328 * fixup! feat(pdp): deal with new ServiceProviderRegistry changes * fix: treat key presence as truthy for boolean options Co-authored-by: William Morriss <[email protected]> * feat(pdp): add IpniPeerID to PDPOfferingData Signed-off-by: Jakub Sztandera <[email protected]> * feat(pdp): show IpniPeerID in webui, use IpniPeerID in FSUpdatePDP Signed-off-by: Jakub Sztandera <[email protected]> --------- Signed-off-by: Jakub Sztandera <[email protected]> Co-authored-by: William Morriss <[email protected]> Co-authored-by: Jakub Sztandera <[email protected]>
Reviewer @rvagg
Closes #307
This significantly reduces the size of ServiceProviderRegistry: 21,290 -> 17,751 (-3539)
Motivation
We want to allow all product attributes to be queryable on-chain. Therefore we are removing the encoded productData. Mandatory schema will be loosely enforced on-chain with a bloom filter.
Upgrade guide for synapse and curio
productInfopreviously abi-encoded is removed and everything is now capability key-value store. Keys arestring; values arebytes. This affectsregisterProvider,addProduct, andupdateProduct. Unsigned integers should be encoded big-endian. Addresses should be encoded asbytes[20]. Strings should be encoded utf-8. See the examples intest/PDPOffering.sol. We don't validate these values on-chain so if they don't look right, throw.getPDPOfferingis not how you get PDP product info anymore. Now usegetAllProductCapabilitieswhich will return all keys and values for a product.ProviderWithProductreturn type now containsproductCapabilityValuesso you don't have to fetch them separately.getProductCapabilitiesno longer returns theexistsboolarray. This array was misleading because it only indicated whether the bytes were empty.getProductCapabilityis removed. UseproductCapabilitiesinstead, which only differs in not havingexists.updatePDPServiceWithCapabilitiesis removed. UseupdateProduct.getProvidersByProductTypeandgetActiveProvidersByProductTypeare merged into one method,getProvidersByProductType, which now has a boolean flag parameteronlyActive.getProductis replaced bygetProviderWithProduct, which returnsProviderWithProductstoragePricePerTibPerMonthis nowstoragePricePerTibPerDayChanges
exists