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

Dynamic Retrieval Pricing #542

Merged
merged 16 commits into from
Jun 4, 2021
Merged

Dynamic Retrieval Pricing #542

merged 16 commits into from
Jun 4, 2021

Conversation

aarshkshah1992
Copy link
Collaborator

@aarshkshah1992 aarshkshah1992 commented Apr 22, 2021

Markets PR for the Dynamic Retrieval Pricing feature. Please see the corresponding Lotus PR for the motivation behind this work.

Here is an explanation of the changes made in the Markets module to support Dynamic Retrieval Pricing:

  • Instead of using the price configured in the Ask Store to blanket price all Retrieval deals, we now call the Pricing function configured by Lotus with the following parameters and use the output of the function to price a retrieval deal:
type PricingInput struct {
	// PayloadCID is the cid of the payload to retrieve.
	PayloadCID cid.Cid
	// PieceCID is the cid of the Piece from which the Payload will be retrieved.
	PieceCID cid.Cid
	// PieceSize is the size of the Piece from which the payload will be retrieved.
	PieceSize abi.UnpaddedPieceSize
	// Client is the peerID of the retrieval client.
	Client peer.ID
	// VerifiedDeal is true if there exists a verified storage deal for the PayloadCID.
	VerifiedDeal bool
	// Unsealed is true if there exists an unsealed sector from which we can retrieve the given payload.
	Unsealed bool
	// CurrentAsk is the current configured ask in the ask-store by using the lotus `set-ask` retrieval 
	// CLI command.
	CurrentAsk Ask
}
  • Introduces/Exports a "default pricing function" that Lotus can configure Markets to use for retrieval pricing. This pricing function:

    • Does NOT charge for Unsealing if we already have an Unsealed copy of a sector file containing the retrieval payload.
    • Does NOT charge for data-transfer if there exists a Verified storage deal containing the retrieval payload AND the user hasn't turned off this particular functionality in the Lotus config.
  • If the Miner has multiple Sector files containing the required retrieval payload AND the client hasn't mandated that we retrieve the payload from a specific Piece, we will ALWAYS read the payload from an Unsealed Sector file and also price deals accordingly.

  • If the client wants to retrieve the payload from a specific Piece, the above logic still applies but we will only consider Sector files that have the Piece mandated by the user.

@aarshkshah1992 aarshkshah1992 requested a review from dirkmc April 22, 2021 13:57
@codecov-commenter
Copy link

codecov-commenter commented Apr 23, 2021

Codecov Report

Merging #542 (dc16894) into master (5b6d12f) will decrease coverage by 0.15%.
The diff coverage is 72.26%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #542      +/-   ##
==========================================
- Coverage   65.77%   65.63%   -0.14%     
==========================================
  Files          56       56              
  Lines        3634     3750     +116     
==========================================
+ Hits         2390     2461      +71     
- Misses       1009     1039      +30     
- Partials      235      250      +15     
Impacted Files Coverage Δ
retrievalmarket/network/old_query_stream.go 75.87% <0.00%> (-2.70%) ⬇️
retrievalmarket/network/query_stream.go 50.00% <0.00%> (-3.84%) ⬇️
retrievalmarket/types.go 57.15% <ø> (ø)
retrievalmarket/impl/dtutils/dtutils.go 79.44% <50.00%> (ø)
storagemarket/impl/dtutils/dtutils.go 75.00% <50.00%> (ø)
retrievalmarket/impl/provider_environments.go 59.26% <69.50%> (+3.31%) ⬆️
...ievalmarket/impl/providerstates/provider_states.go 88.00% <71.43%> (-2.69%) ⬇️
retrievalmarket/impl/provider.go 65.65% <73.81%> (-2.41%) ⬇️
...market/impl/requestvalidation/requestvalidation.go 87.66% <81.82%> (-1.81%) ⬇️
retrievalmarket/impl/clientstates/client_states.go 94.34% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 672687c...dc16894. Read the comment docs.

@aarshkshah1992 aarshkshah1992 marked this pull request as draft May 6, 2021 09:39
@aarshkshah1992 aarshkshah1992 force-pushed the feat/dynamic-retreival-pricing branch from 4a61fc5 to 8bd6d00 Compare May 6, 2021 10:05
Copy link
Contributor

@dirkmc dirkmc left a comment

Choose a reason for hiding this comment

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

The test coverage is really nice 👍

retrievalmarket/impl/provider.go Outdated Show resolved Hide resolved
retrievalmarket/impl/provider.go Show resolved Hide resolved
retrievalmarket/impl/provider.go Outdated Show resolved Hide resolved
retrievalmarket/impl/provider_environments.go Show resolved Hide resolved
retrievalmarket/impl/provider_environments.go Show resolved Hide resolved
@@ -37,32 +37,522 @@ import (
tut "github.com/filecoin-project/go-fil-markets/shared_testutil"
)

func TestDynamicPricing(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I love how thorough this test is 👍 👍

expectedUnsealPrice: expectedUnsealPrice,
},

{name: "When PieceCID is not provided, prefer a piece for which an unsealed sector already exists and price it accordingly",
Copy link
Contributor

Choose a reason for hiding this comment

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

👍 👍

retrievalmarket/impl/providerstates/provider_states.go Outdated Show resolved Hide resolved
retrievalmarket/impl/provider.go Outdated Show resolved Hide resolved
retrievalmarket/impl/provider.go Outdated Show resolved Hide resolved
retrievalmarket/impl/provider.go Outdated Show resolved Hide resolved
retrievalmarket/impl/provider_environments.go Outdated Show resolved Hide resolved
retrievalmarket/impl/provider_environments.go Outdated Show resolved Hide resolved
retrievalmarket/impl/provider_environments.go Outdated Show resolved Hide resolved
retrievalmarket/impl/provider_environments.go Outdated Show resolved Hide resolved
@aarshkshah1992
Copy link
Collaborator Author

@dirkmc I've fixed a bug in commit 6c11597 wherein we were quoting the retrieval data transfer price based on the padded piece size instead of the unpadded piece size even though don't actually (obviously) transfer the padding across the wire.

@raulk
Copy link
Member

raulk commented Jun 2, 2021

@aarshkshah1992 Mind updating this PR's description with an explanation of what has been done concretely in this module (as part of the linked Lotus side PR) + what's left, so that the communityi can follow?

Do we need to add more test coverage here?

@aarshkshah1992
Copy link
Collaborator Author

aarshkshah1992 commented Jun 3, 2021

@raulk @dirkmc

I've updated the description of the PR to give more information about the changes introduced by this PR.

This PR is in pretty good shape and has solid tests. I just need @dirkmc to look at one last small commit that I recently introduced:
6c11597

If that looks good, we are good to go.

@aarshkshah1992 aarshkshah1992 marked this pull request as ready for review June 3, 2021 04:13
@dirkmc
Copy link
Contributor

dirkmc commented Jun 3, 2021

Looks good, thanks Aarsh 👍

Before we merge I'd like to do some real world testing, for correctness and also to make sure that it's performant.

@dirkmc dirkmc merged commit 32e5cce into master Jun 4, 2021
@dirkmc dirkmc deleted the feat/dynamic-retreival-pricing branch June 4, 2021 13:23
@dirkmc dirkmc mentioned this pull request Jun 4, 2021
Comment on lines +420 to +436
// PricingInput provides input parameters required to price a retrieval deal.
type PricingInput struct {
// PayloadCID is the cid of the payload to retrieve.
PayloadCID cid.Cid
// PieceCID is the cid of the Piece from which the Payload will be retrieved.
PieceCID cid.Cid
// PieceSize is the size of the Piece from which the payload will be retrieved.
PieceSize abi.UnpaddedPieceSize
// Client is the peerID of the retrieval client.
Client peer.ID
// VerifiedDeal is true if there exists a verified storage deal for the PayloadCID.
VerifiedDeal bool
// Unsealed is true if there exists an unsealed sector from which we can retrieve the given payload.
Unsealed bool
// CurrentAsk is the current configured ask in the ask-store.
CurrentAsk Ask
}
Copy link
Contributor

Choose a reason for hiding this comment

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

( I am well aware I am commenting on an old, merged PR )

@aarshkshah1992 @hannahhoward @willscott was it a deliberate decision to exclude the client-provided selector in this structure, or just an omission? Even if we do not have the tools for miners to interpret/decide on a selector-driven partial-retrieval, the structure is being exposed to 3rd party tools. It is probably prudent to provide all the information available from the get-go, instead of adding it later on.

Copy link
Contributor

Choose a reason for hiding this comment

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

An extra nit regarding the title-comment:

If the Miner has multiple Sector files containing the required retrieval payload AND the client hasn't mandated that we retrieve the payload from a specific Piece,

A specific deal PayloadCID (root-dag) + PieceSize will always invariably correspond to an identical PieceCID. That is - if a deal is stored in multiple sectors, some sealed and some unsealed, a PieceCID can not differentiate among them: it will be identical among them all.

Copy link
Member

@raulk raulk Jul 19, 2021

Choose a reason for hiding this comment

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

Never too late to provide useful feedback! ;-)

Re: including the selector in the pricing function input: how useful would this be? The function can't evaluate the selector against the data, and it can't really derive anything useful from it intrinsically AFAIK.

If it's to symbolise that a partial retrieval is being performed, for pricing purposes, the price-per-byte formulation of the quote already decouples the final price from the actual data being selected. We could pass a "partial retrieval = true/false" flag, but it's not possible to calculate it correctly because the selector could be selecting the entire deal.

Re: extensibility/completeness, it's non-invasive to add a JSON field in the future if we do decide we want this for some reason. But until there's a standardised, canonical text representation for selectors, I don't think it's practical to even consider.

Copy link
Member

Choose a reason for hiding this comment

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

A specific deal PayloadCID (root-dag) + PieceSize will always invariably correspond to an identical PieceCID. That is - if a deal is stored in multiple sectors, some sealed and some unsealed, a PieceCID can not differentiate among them: it will be identical among them all.

If there's an unsealed copy, we always select the unsealed copy as input to the pricing function, and as the source of the retrieval.

Copy link
Contributor

Choose a reason for hiding this comment

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

@raulk right, I was specifically questioning this part of the sentence:

the client hasn't mandated that we retrieve the payload from a specific Piece

There is no way for a client to signal "I want to retrieve from this physical piece" via the struct in question: they all have the same PieceCid

Copy link
Member

@raulk raulk Jul 19, 2021

Choose a reason for hiding this comment

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

Oh, what @aarshkshah1992 was trying to get to is that if "universal retrieval" is enabled (such that clients don't need to specify the PieceCID they want to retrieve a given PayloadCID from), and there are multiple PieceCIDs that contain that PayloadCID, we prefer the deal that's unsealed, should there be one. I don't think any of that implies that the client gets to choose the sector, or concrete physical piece within a sector.

Copy link
Contributor

Choose a reason for hiding this comment

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

But until there's a standardized, canonical text representation for selectors, I don't think it's practical to even consider.

The reason I brought this up is that the selector is already exposed in a standard-ish encoded-cbor representation via the RetrievalFilter codepath: https://github.com/filecoin-project/lotus/blob/v1.11.0-rc2/markets/dealfilter/cli.go#L28-L62

I do not have a preference either way. Rather am raising the inconsistency of having two sets of external tools, one being fed the structure in this pr, the other being fed this: https://github.com/Murmuration-Labs/bitscreen/blob/master/testdata/retrieval_proposal.json

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for the pointer. Note that this isn't a filtering function, but rather a pricing function. It runs when the retrieval provider is asked for a quote. At that time, the selector is not available. So in terms of the data interface, the deal filter and the pricing function can't be symmetrical.

Copy link
Contributor

Choose a reason for hiding this comment

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

It runs when the retrieval provider is asked for a quote. At that time, the selector is not available.

@raulk indeed you are correct: it is all commented out :cryingbear:
https://github.com/filecoin-project/go-fil-markets/blob/v1.6.0-rc1/retrievalmarket/types.go#L158-L167

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