Skip to content

Commit

Permalink
Adding different prices for verified deals (#347)
Browse files Browse the repository at this point in the history
* adding different prices for verified deals

* Documentation improvements to verified deal ask

Co-authored-by: Sami Mäkelä <mrsmkl@gmail.com>
  • Loading branch information
arajasek and mrsmkl committed Jul 31, 2020
1 parent e72c40e commit 0511062
Show file tree
Hide file tree
Showing 11 changed files with 60 additions and 32 deletions.
4 changes: 2 additions & 2 deletions retrievalmarket/storage_retrieval_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func TestStorageRetrieval(t *testing.T) {
_ = sh.Client.SubscribeToEvents(clientSubscriber)

// set ask price where we'll accept any price
err := sh.Provider.SetAsk(big.NewInt(0), 50_000)
err := sh.Provider.SetAsk(big.NewInt(0), big.NewInt(0), 50_000)
assert.NoError(t, err)

result := sh.ProposeStorageDeal(t, &storagemarket.DataRef{TransferType: storagemarket.TTGraphsync, Root: sh.PayloadCid})
Expand Down Expand Up @@ -307,7 +307,7 @@ func newStorageHarness(ctx context.Context, t *testing.T) *storageHarness {
require.NoError(t, err)

// set ask price where we'll accept any price
require.NoError(t, provider.SetAsk(big.NewInt(0), 50_000))
require.NoError(t, provider.SetAsk(big.NewInt(0), big.NewInt(0), 50_000))
require.NoError(t, provider.Start(ctx))

// Closely follows the MinerInfo struct in the spec
Expand Down
1 change: 1 addition & 0 deletions shared_testutil/generators.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ func MakeTestMinerDeal(state storagemarket.StorageDealStatus, clientDealProposal
func MakeTestStorageAsk() *storagemarket.StorageAsk {
return &storagemarket.StorageAsk{
Price: MakeTestTokenAmount(),
VerifiedPrice: MakeTestTokenAmount(),
MinPieceSize: abi.PaddedPieceSize(rand.Uint64()),
Miner: address.TestAddress2,
Timestamp: abi.ChainEpoch(rand.Int63()),
Expand Down
6 changes: 3 additions & 3 deletions storagemarket/impl/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ var _ network.StorageReceiver = &Provider{}
// StoredAsk is an interface which provides access to a StorageAsk
type StoredAsk interface {
GetAsk() *storagemarket.SignedStorageAsk
SetAsk(price abi.TokenAmount, duration abi.ChainEpoch, options ...storagemarket.StorageAskOption) error
SetAsk(price abi.TokenAmount, verifiedPrice abi.TokenAmount, duration abi.ChainEpoch, options ...storagemarket.StorageAskOption) error
}

// Provider is the production implementation of the StorageProvider interface
Expand Down Expand Up @@ -367,8 +367,8 @@ func (p *Provider) ListLocalDeals() ([]storagemarket.MinerDeal, error) {

// SetAsk configures the storage miner's ask with the provided price,
// duration, and options. Any previously-existing ask is replaced.
func (p *Provider) SetAsk(price abi.TokenAmount, duration abi.ChainEpoch, options ...storagemarket.StorageAskOption) error {
return p.storedAsk.SetAsk(price, duration, options...)
func (p *Provider) SetAsk(price abi.TokenAmount, verifiedPrice abi.TokenAmount, duration abi.ChainEpoch, options ...storagemarket.StorageAskOption) error {
return p.storedAsk.SetAsk(price, verifiedPrice, duration, options...)
}

/*
Expand Down
7 changes: 6 additions & 1 deletion storagemarket/impl/providerstates/provider_states.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,12 @@ func ValidateDealProposal(ctx fsm.Context, environment ProviderDealEnvironment,
return ctx.Trigger(storagemarket.ProviderEventDealRejected, xerrors.Errorf("proposed provider collateral above maximum: %s > %s", proposal.ProviderCollateral, pcMax))
}

minPrice := big.Div(big.Mul(environment.Ask().Price, abi.NewTokenAmount(int64(proposal.PieceSize))), abi.NewTokenAmount(1<<30))
askPrice := environment.Ask().Price
if deal.Proposal.VerifiedDeal {
askPrice = environment.Ask().VerifiedPrice
}

minPrice := big.Div(big.Mul(askPrice, abi.NewTokenAmount(int64(proposal.PieceSize))), abi.NewTokenAmount(1<<30))
if proposal.StoragePricePerEpoch.LessThan(minPrice) {
return ctx.Trigger(storagemarket.ProviderEventDealRejected,
xerrors.Errorf("storage price per epoch less than asking price: %s < %s", proposal.StoragePricePerEpoch, minPrice))
Expand Down
7 changes: 4 additions & 3 deletions storagemarket/impl/providerstates/provider_states_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -887,9 +887,10 @@ var defaultDataRef = storagemarket.DataRef{
var defaultClientMarketBalance = abi.NewTokenAmount(200 * 10000)

var defaultAsk = storagemarket.StorageAsk{
Price: abi.NewTokenAmount(10000000),
MinPieceSize: abi.PaddedPieceSize(256),
MaxPieceSize: 1 << 20,
Price: abi.NewTokenAmount(10000000),
VerifiedPrice: abi.NewTokenAmount(1000000),
MinPieceSize: abi.PaddedPieceSize(256),
MaxPieceSize: 1 << 20,
}

var testData = tut.NewTestIPLDTree()
Expand Down
26 changes: 15 additions & 11 deletions storagemarket/impl/storedask/storedask.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ import (

var log = logging.Logger("storedask")

// DefaultPrice is the default price set for StorageAsk in Fil / GiB / Epoch
// DefaultPrice is the default price for unverified deals (in attoFil / GiB / Epoch)
var DefaultPrice = abi.NewTokenAmount(500000000)

// DefaultVerifiedPrice is the default price for verified deals (in attoFil / GiB / Epoch)
var DefaultVerifiedPrice = abi.NewTokenAmount(50000000)

// DefaultDuration is the default number of epochs a storage ask is in effect for
const DefaultDuration abi.ChainEpoch = 1000000

Expand Down Expand Up @@ -61,17 +64,17 @@ func NewStoredAsk(ds datastore.Batching, dsKey datastore.Key, spn storagemarket.
if s.ask == nil {
// TODO: we should be fine with this state, and just say it means 'not actively accepting deals'
// for now... lets just set a price
if err := s.SetAsk(DefaultPrice, DefaultDuration); err != nil {
if err := s.SetAsk(DefaultPrice, DefaultVerifiedPrice, DefaultDuration); err != nil {
return nil, xerrors.Errorf("failed setting a default price: %w", err)
}
}
return s, nil
}

// SetAsk writes a new ask to disk with the provided price,
// SetAsk configures the storage miner's ask with the provided prices (for unverified and verified deals),
// duration, and options. Any previously-existing ask is replaced.
// It also increments the sequence number on the ask
func (s *StoredAsk) SetAsk(price abi.TokenAmount, duration abi.ChainEpoch, options ...storagemarket.StorageAskOption) error {
func (s *StoredAsk) SetAsk(price abi.TokenAmount, verifiedPrice abi.TokenAmount, duration abi.ChainEpoch, options ...storagemarket.StorageAskOption) error {
s.askLk.Lock()
defer s.askLk.Unlock()
var seqno uint64
Expand All @@ -86,13 +89,14 @@ func (s *StoredAsk) SetAsk(price abi.TokenAmount, duration abi.ChainEpoch, optio
return err
}
ask := &storagemarket.StorageAsk{
Price: price,
Timestamp: height,
Expiry: height + duration,
Miner: s.actor,
SeqNo: seqno,
MinPieceSize: DefaultMinPieceSize,
MaxPieceSize: DefaultMaxPieceSize,
Price: price,
VerifiedPrice: verifiedPrice,
Timestamp: height,
Expiry: height + duration,
Miner: s.actor,
SeqNo: seqno,
MinPieceSize: DefaultMinPieceSize,
MaxPieceSize: DefaultMaxPieceSize,
}

for _, option := range options {
Expand Down
10 changes: 6 additions & 4 deletions storagemarket/impl/storedask/storedask_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,15 @@ func TestStoredAsk(t *testing.T) {
require.NoError(t, err)

testPrice := abi.NewTokenAmount(1000000000)
testVerifiedPrice := abi.NewTokenAmount(100000000)
testDuration := abi.ChainEpoch(200)
t.Run("auto initializing", func(t *testing.T) {
ask := storedAsk.GetAsk()
require.NotNil(t, ask)
})
t.Run("setting ask price", func(t *testing.T) {
minPieceSize := abi.PaddedPieceSize(1024)
err := storedAsk.SetAsk(testPrice, testDuration, storagemarket.MinPieceSize(minPieceSize))
err := storedAsk.SetAsk(testPrice, testVerifiedPrice, testDuration, storagemarket.MinPieceSize(minPieceSize))
require.NoError(t, err)
ask := storedAsk.GetAsk()
require.Equal(t, ask.Ask.Price, testPrice)
Expand All @@ -47,6 +48,7 @@ func TestStoredAsk(t *testing.T) {
require.NoError(t, err)
ask := storedAsk2.GetAsk()
require.Equal(t, ask.Ask.Price, testPrice)
require.Equal(t, ask.Ask.VerifiedPrice, testVerifiedPrice)
require.Equal(t, ask.Ask.Expiry-ask.Ask.Timestamp, testDuration)
})
t.Run("node errors", func(t *testing.T) {
Expand All @@ -59,7 +61,7 @@ func TestStoredAsk(t *testing.T) {
// should load cause ask is is still in data store
storedAskError, err := storedask.NewStoredAsk(ds, datastore.NewKey("latest-ask"), spnStateIDErr, actor)
require.NoError(t, err)
err = storedAskError.SetAsk(testPrice, testDuration)
err = storedAskError.SetAsk(testPrice, testVerifiedPrice, testDuration)
require.Error(t, err)

spnMinerWorkerErr := &testnodes.FakeProviderNode{
Expand All @@ -71,7 +73,7 @@ func TestStoredAsk(t *testing.T) {
// should load cause ask is is still in data store
storedAskError, err = storedask.NewStoredAsk(ds, datastore.NewKey("latest-ask"), spnMinerWorkerErr, actor)
require.NoError(t, err)
err = storedAskError.SetAsk(testPrice, testDuration)
err = storedAskError.SetAsk(testPrice, testVerifiedPrice, testDuration)
require.Error(t, err)

spnSignBytesErr := &testnodes.FakeProviderNode{
Expand All @@ -83,7 +85,7 @@ func TestStoredAsk(t *testing.T) {
// should load cause ask is is still in data store
storedAskError, err = storedask.NewStoredAsk(ds, datastore.NewKey("latest-ask"), spnSignBytesErr, actor)
require.NoError(t, err)
err = storedAskError.SetAsk(testPrice, testDuration)
err = storedAskError.SetAsk(testPrice, testVerifiedPrice, testDuration)
require.Error(t, err)
})
}
6 changes: 3 additions & 3 deletions storagemarket/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func TestMakeDeal(t *testing.T) {
_ = h.Client.SubscribeToEvents(clientSubscriber)

// set ask price where we'll accept any price
err := h.Provider.SetAsk(big.NewInt(0), 50_000)
err := h.Provider.SetAsk(big.NewInt(0), big.NewInt(0), 50_000)
assert.NoError(t, err)

result := h.ProposeStorageDeal(t, &storagemarket.DataRef{TransferType: storagemarket.TTGraphsync, Root: h.PayloadCid}, true, false)
Expand Down Expand Up @@ -291,7 +291,7 @@ func TestRestartClient(t *testing.T) {
require.NoError(t, h.Client.Start(ctx))

// set ask price where we'll accept any price
err := h.Provider.SetAsk(big.NewInt(0), 50_000)
err := h.Provider.SetAsk(big.NewInt(0), big.NewInt(0), 50_000)
assert.NoError(t, err)

wg := sync.WaitGroup{}
Expand Down Expand Up @@ -461,7 +461,7 @@ func newHarnessWithTestData(t *testing.T, ctx context.Context, td *shared_testut
assert.NoError(t, err)

// set ask price where we'll accept any price
err = provider.SetAsk(big.NewInt(0), 50_000)
err = provider.SetAsk(big.NewInt(0), big.NewInt(0), 50_000)
assert.NoError(t, err)

err = provider.Start(ctx)
Expand Down
4 changes: 2 additions & 2 deletions storagemarket/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ type StorageProvider interface {
// Stop terminates processing of deals on a StorageProvider
Stop() error

// SetAsk configures the storage miner's ask with the provided price,
// SetAsk configures the storage miner's ask with the provided prices (for unverified and verified deals),
// duration, and options. Any previously-existing ask is replaced.
SetAsk(price abi.TokenAmount, duration abi.ChainEpoch, options ...StorageAskOption) error
SetAsk(price abi.TokenAmount, verifiedPrice abi.TokenAmount, duration abi.ChainEpoch, options ...StorageAskOption) error

// GetAsk returns the storage miner's ask, or nil if one does not exist.
GetAsk() *SignedStorageAsk
Expand Down
3 changes: 2 additions & 1 deletion storagemarket/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ type Balance struct {
// storage provider may run its own decision logic).
type StorageAsk struct {
// Price per GiB / Epoch
Price abi.TokenAmount
Price abi.TokenAmount
VerifiedPrice abi.TokenAmount

MinPieceSize abi.PaddedPieceSize
MaxPieceSize abi.PaddedPieceSize
Expand Down
18 changes: 16 additions & 2 deletions storagemarket/types_cbor_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 0511062

Please sign in to comment.