diff --git a/bidengine/order.go b/bidengine/order.go index 0c21f2cb..2c28095e 100644 --- a/bidengine/order.go +++ b/bidengine/order.go @@ -372,11 +372,12 @@ loop: pricech = runner.Do(metricsutils.ObserveRunner(func() runner.Result { // Calculate price & bid priceReq := Request{ - Owner: group.GroupID.Owner, - GSpec: &group.GroupSpec, - PricePrecision: DefaultPricePrecision, + Owner: group.GroupID.Owner, + GSpec: &group.GroupSpec, + PricePrecision: DefaultPricePrecision, + AllocatedResources: reservation.GetAllocatedResources(), } - return runner.NewResult(o.cfg.PricingStrategy.CalculatePrice(ctx, priceReq, reservation)) + return runner.NewResult(o.cfg.PricingStrategy.CalculatePrice(ctx, priceReq)) }, pricingDuration)) case result := <-pricech: pricech = nil diff --git a/bidengine/order_test.go b/bidengine/order_test.go index cbb7c6c0..c33c26d7 100644 --- a/bidengine/order_test.go +++ b/bidengine/order_test.go @@ -31,7 +31,6 @@ import ( "github.com/akash-network/node/testutil" clustermocks "github.com/akash-network/provider/cluster/mocks" - ctypes "github.com/akash-network/provider/cluster/types/v1beta3" clmocks "github.com/akash-network/provider/cluster/types/v1beta3/mocks" "github.com/akash-network/provider/session" ) @@ -57,10 +56,8 @@ type alwaysFailsBidPricingStrategy struct { failure error } -var ( - _ BidPricingStrategy = (*testBidPricingStrategy)(nil) - _ BidPricingStrategy = (*alwaysFailsBidPricingStrategy)(nil) -) +var _ BidPricingStrategy = (*testBidPricingStrategy)(nil) +var _ BidPricingStrategy = (*alwaysFailsBidPricingStrategy)(nil) func makeMocks(s *orderTestScaffold) { groupResult := &dtypes.QueryGroupResponse{} @@ -320,6 +317,7 @@ func Test_BidOrderPriceTooHigh(t *testing.T) { // Should have called unreserve once, nothing happened after the bid scaffold.cluster.AssertCalled(t, "Unreserve", scaffold.orderID, mock.Anything) + } func Test_BidOrderAndThenClosedUnreserve(t *testing.T) { @@ -579,7 +577,6 @@ func Test_ShouldExitWhenAlreadySetAndLost(t *testing.T) { scaffold.txClient.AssertNotCalled(t, "Broadcast", mock.Anything, expMsgs, mock.Anything) } - func Test_ShouldCloseBidWhenAlreadySetAndThenTimeout(t *testing.T) { pricing, err := MakeRandomRangePricing() require.NoError(t, err) @@ -648,7 +645,7 @@ func Test_ShouldRecognizeLeaseCreatedIfBiddingIsSkipped(t *testing.T) { require.Nil(t, broadcast) } -func (tbps testBidPricingStrategy) CalculatePrice(_ context.Context, _ Request, _ ctypes.Reservation) (sdk.DecCoin, error) { +func (tbps testBidPricingStrategy) CalculatePrice(_ context.Context, _ Request) (sdk.DecCoin, error) { return sdk.NewInt64DecCoin(testutil.CoinDenom, int64(tbps)), nil } @@ -677,7 +674,7 @@ func Test_BidOrderUsesBidPricingStrategy(t *testing.T) { scaffold.cluster.AssertCalled(t, "Unreserve", scaffold.orderID, mock.Anything) } -func (afbps alwaysFailsBidPricingStrategy) CalculatePrice(_ context.Context, _ Request, _ ctypes.Reservation) (sdk.DecCoin, error) { +func (afbps alwaysFailsBidPricingStrategy) CalculatePrice(_ context.Context, _ Request) (sdk.DecCoin, error) { return sdk.DecCoin{}, afbps.failure } diff --git a/bidengine/pricing.go b/bidengine/pricing.go index 927da9c5..2323bf96 100644 --- a/bidengine/pricing.go +++ b/bidengine/pricing.go @@ -15,15 +15,14 @@ import ( atypes "github.com/akash-network/akash-api/go/node/types/v1beta3" "github.com/akash-network/node/sdl" - ctypes "github.com/akash-network/provider/cluster/types/v1beta3" - "github.com/akash-network/provider/cluster/util" ) type Request struct { - Owner string `json:"owner"` - GSpec *dtypes.GroupSpec - PricePrecision int + Owner string `json:"owner"` + GSpec *dtypes.GroupSpec + AllocatedResources dtypes.ResourceUnits + PricePrecision int } const ( @@ -31,7 +30,7 @@ const ( ) type BidPricingStrategy interface { - CalculatePrice(context.Context, Request, ctypes.Reservation) (sdk.DecCoin, error) + CalculatePrice(ctx context.Context, req Request) (sdk.DecCoin, error) } var ( @@ -130,7 +129,7 @@ func ceilBigRatToBigInt(v *big.Rat) *big.Int { return result } -func (fp scalePricing) CalculatePrice(_ context.Context, req Request, _ ctypes.Reservation) (sdk.DecCoin, error) { +func (fp scalePricing) CalculatePrice(_ context.Context, req Request) (sdk.DecCoin, error) { // Use unlimited precision math here. // Otherwise, a correctly crafted order could create a cost of '1' given // a possible configuration @@ -250,7 +249,7 @@ func MakeRandomRangePricing() (BidPricingStrategy, error) { return randomRangePricing(0), nil } -func (randomRangePricing) CalculatePrice(_ context.Context, req Request, _ ctypes.Reservation) (sdk.DecCoin, error) { +func (randomRangePricing) CalculatePrice(_ context.Context, req Request) (sdk.DecCoin, error) { min, max := calculatePriceRange(req.GSpec) if min.IsEqual(max) { return max, nil diff --git a/bidengine/pricing_test.go b/bidengine/pricing_test.go index bbc0518f..6729a9a2 100644 --- a/bidengine/pricing_test.go +++ b/bidengine/pricing_test.go @@ -22,13 +22,11 @@ import ( "github.com/stretchr/testify/require" dtypes "github.com/akash-network/akash-api/go/node/deployment/v1beta3" - mtypes "github.com/akash-network/akash-api/go/node/market/v1beta4" "github.com/akash-network/akash-api/go/node/types/unit" atypes "github.com/akash-network/akash-api/go/node/types/v1beta3" "github.com/akash-network/node/sdl" "github.com/akash-network/node/testutil" - ctypes "github.com/akash-network/provider/cluster/types/v1beta3" "github.com/akash-network/provider/cluster/util" ) @@ -138,7 +136,7 @@ func Test_ScalePricingFailsOnOverflow(t *testing.T) { GSpec: defaultGroupSpec(), } - price, err := pricing.CalculatePrice(context.Background(), req, nil) + price, err := pricing.CalculatePrice(context.Background(), req) require.Equal(t, sdk.DecCoin{}, price) require.Equal(t, err, ErrBidQuantityInvalid) @@ -160,7 +158,7 @@ func Test_ScalePricingOnCpu(t *testing.T) { GSpec: gspec, } - price, err := pricing.CalculatePrice(context.Background(), req, nil) + price, err := pricing.CalculatePrice(context.Background(), req) require.NoError(t, err) require.NotNil(t, pricing) @@ -184,7 +182,7 @@ func Test_ScalePricingOnMemory(t *testing.T) { GSpec: gspec, } - price, err := pricing.CalculatePrice(context.Background(), req, nil) + price, err := pricing.CalculatePrice(context.Background(), req) require.NoError(t, err) expectedPrice := testutil.AkashDecCoin(t, int64(memoryScale*memoryQuantity)) @@ -206,7 +204,7 @@ func Test_ScalePricingOnMemoryLessThanOne(t *testing.T) { Owner: testutil.AccAddress(t).String(), GSpec: gspec, } - price, err := pricing.CalculatePrice(context.Background(), req, nil) + price, err := pricing.CalculatePrice(context.Background(), req) require.NoError(t, err) expectedPrice, err := sdk.NewDecFromStr("0.0000009536743164") @@ -216,7 +214,7 @@ func Test_ScalePricingOnMemoryLessThanOne(t *testing.T) { // Make a resource exactly 1 less byte less than two megabytes memoryQuantity = uint64(2*unit.Mi - 1) gspec.Resources[0].Resources.Memory.Quantity = atypes.NewResourceValue(memoryQuantity) - price, err = pricing.CalculatePrice(context.Background(), req, nil) + price, err = pricing.CalculatePrice(context.Background(), req) require.NoError(t, err) require.NotNil(t, price) @@ -256,7 +254,7 @@ func Test_ScalePricingOnStorage(t *testing.T) { Owner: testutil.AccAddress(t).String(), GSpec: gspec, } - price, err := pricing.CalculatePrice(context.Background(), req, nil) + price, err := pricing.CalculatePrice(context.Background(), req) require.NoError(t, err) decNearly(t, price.Amount, int64(storageScale*storageQuantity)) @@ -279,14 +277,14 @@ func Test_ScalePricingByCountOfResources(t *testing.T) { Owner: testutil.AccAddress(t).String(), GSpec: gspec, } - firstPrice, err := pricing.CalculatePrice(context.Background(), req, nil) + firstPrice, err := pricing.CalculatePrice(context.Background(), req) require.NoError(t, err) require.NoError(t, err) decNearly(t, firstPrice.Amount, int64(storageScale*storageQuantity)) gspec.Resources[0].Count = 2 - secondPrice, err := pricing.CalculatePrice(context.Background(), req, nil) + secondPrice, err := pricing.CalculatePrice(context.Background(), req) require.NoError(t, err) decNearly(t, secondPrice.Amount, 2*int64(storageScale*storageQuantity)) } @@ -312,7 +310,7 @@ func Test_ScalePricingForIPs(t *testing.T) { Owner: testutil.AccAddress(t).String(), GSpec: gspec, } - price, err := pricing.CalculatePrice(context.Background(), req, nil) + price, err := pricing.CalculatePrice(context.Background(), req) require.NoError(t, err) require.NoError(t, err) @@ -323,14 +321,14 @@ func Test_ScalePricingForIPs(t *testing.T) { SequenceNumber: 1368, }) require.Equal(t, uint(2), util.GetEndpointQuantityOfResourceGroup(gspec, atypes.Endpoint_LEASED_IP)) - price, err = pricing.CalculatePrice(context.Background(), req, nil) + price, err = pricing.CalculatePrice(context.Background(), req) require.NoError(t, err) require.NoError(t, err) decNearly(t, price.Amount, 2*ipPriceInt) gspec.Resources[0].Count = 33 // any number greater than 1 works here - price, err = pricing.CalculatePrice(context.Background(), req, nil) + price, err = pricing.CalculatePrice(context.Background(), req) require.NoError(t, err) decNearly(t, price.Amount, 2*ipPriceInt) } @@ -367,7 +365,7 @@ func Test_ScriptPricingFailsWhenScriptDoesNotExist(t *testing.T) { Owner: testutil.AccAddress(t).String(), GSpec: defaultGroupSpec(), } - _, err = pricing.CalculatePrice(context.Background(), req, nil) + _, err = pricing.CalculatePrice(context.Background(), req) require.IsType(t, &os.PathError{}, errors.Unwrap(err)) } @@ -391,7 +389,7 @@ func Test_ScriptPricingFailsWhenScriptExitsNonZero(t *testing.T) { require.NoError(t, err) require.NotNil(t, pricing) - _, err = pricing.CalculatePrice(context.Background(), req, nil) + _, err = pricing.CalculatePrice(context.Background(), req) require.IsType(t, &exec.ExitError{}, errors.Unwrap(err)) } @@ -415,7 +413,7 @@ func Test_ScriptPricingFailsWhenScriptExitsWithoutWritingResultToStdout(t *testi GSpec: defaultGroupSpec(), } - _, err = pricing.CalculatePrice(context.Background(), req, nil) + _, err = pricing.CalculatePrice(context.Background(), req) require.ErrorIs(t, err, io.EOF) } @@ -439,7 +437,7 @@ func Test_ScriptPricingFailsWhenScriptWritesZeroResult(t *testing.T) { GSpec: defaultGroupSpec(), } - _, err = pricing.CalculatePrice(context.Background(), req, nil) + _, err = pricing.CalculatePrice(context.Background(), req) require.Equal(t, ErrBidZero, err) } @@ -463,7 +461,7 @@ func Test_ScriptPricingFailsWhenScriptWritesNegativeResult(t *testing.T) { GSpec: defaultGroupSpec(), } - _, err = pricing.CalculatePrice(context.Background(), req, nil) + _, err = pricing.CalculatePrice(context.Background(), req) require.Equal(t, ErrBidQuantityInvalid, err) } @@ -487,7 +485,7 @@ func Test_ScriptPricingWhenScriptWritesFractionalResult(t *testing.T) { GSpec: defaultGroupSpec(), } - result, err := pricing.CalculatePrice(context.Background(), req, nil) + result, err := pricing.CalculatePrice(context.Background(), req) require.NoError(t, err) expectedPrice, err := sdk.NewDecFromStr("1.5") require.NoError(t, err) @@ -515,7 +513,7 @@ func Test_ScriptPricingFailsWhenScriptWritesOverflowResult(t *testing.T) { GSpec: defaultGroupSpec(), } - _, err = pricing.CalculatePrice(context.Background(), req, nil) + _, err = pricing.CalculatePrice(context.Background(), req) require.ErrorIs(t, err, ErrBidQuantityInvalid) } @@ -540,7 +538,7 @@ func Test_ScriptPricingReturnsResultFromScript(t *testing.T) { GSpec: defaultGroupSpec(), } - price, err := pricing.CalculatePrice(context.Background(), req, nil) + price, err := pricing.CalculatePrice(context.Background(), req) require.NoError(t, err) require.Equal(t, "uakt", price.Denom) require.Equal(t, sdk.NewDec(132), price.Amount) @@ -569,7 +567,7 @@ func Test_ScriptPricingDoesNotExhaustSemaphore(t *testing.T) { GSpec: defaultGroupSpec(), } - _, err = pricing.CalculatePrice(context.Background(), req, nil) + _, err = pricing.CalculatePrice(context.Background(), req) require.NoError(t, err) } } @@ -595,7 +593,7 @@ func Test_ScriptPricingStopsByContext(t *testing.T) { Owner: testutil.AccAddress(t).String(), GSpec: defaultGroupSpec(), } - _, err = pricing.CalculatePrice(ctx, req, nil) + _, err = pricing.CalculatePrice(ctx, req) require.Error(t, err) require.Equal(t, context.Canceled, err) } @@ -626,7 +624,7 @@ func Test_ScriptPricingStopsByTimeout(t *testing.T) { GSpec: defaultGroupSpec(), } - _, err = pricing.CalculatePrice(ctx, req, nil) + _, err = pricing.CalculatePrice(ctx, req) require.Error(t, err) require.Equal(t, context.DeadlineExceeded, err) } @@ -654,7 +652,7 @@ func Test_ScriptPricingWritesJsonToStdin(t *testing.T) { GSpec: gspec, } - price, err := pricing.CalculatePrice(context.Background(), req, nil) + price, err := pricing.CalculatePrice(context.Background(), req) require.NoError(t, err) require.Equal(t, "uakt", price.Denom) require.Equal(t, sdk.NewDec(1), price.Amount) @@ -712,7 +710,7 @@ func Test_ScriptPricingFromScript(t *testing.T) { GSpec: gspec, } - price, err := pricing.CalculatePrice(context.Background(), req, nil) + price, err := pricing.CalculatePrice(context.Background(), req) require.NoError(t, err) amount, err := sdk.NewDecFromStr(expectedPrice) require.NoError(t, err) @@ -720,32 +718,6 @@ func Test_ScriptPricingFromScript(t *testing.T) { require.Equal(t, sdk.NewDecCoinFromDec("uakt", amount).String(), price.String()) } -var _ ctypes.Reservation = (*testReservation)(nil) - -type testReservation struct { - ru dtypes.ResourceUnits -} - -func (*testReservation) OrderID() mtypes.OrderID { - return mtypes.OrderID{} -} - -func (*testReservation) Resources() dtypes.ResourceGroup { - return nil -} - -func (r *testReservation) GetAllocatedResources() dtypes.ResourceUnits { - return r.ru -} - -func (r *testReservation) SetAllocatedResources(ru dtypes.ResourceUnits) { - r.ru = ru -} - -func (*testReservation) Allocated() bool { return false } -func (*testReservation) ClusterParams() any { return nil } -func (*testReservation) SetClusterParams(any) {} - func TestRationalToIntConversion(t *testing.T) { x := ceilBigRatToBigInt(big.NewRat(0, 1)) require.Equal(t, big.NewInt(0), x) diff --git a/bidengine/shellscript.go b/bidengine/shellscript.go index bd41d447..d086b27d 100644 --- a/bidengine/shellscript.go +++ b/bidengine/shellscript.go @@ -15,7 +15,6 @@ import ( "github.com/akash-network/node/sdl" sdk "github.com/cosmos/cosmos-sdk/types" - ctypes "github.com/akash-network/provider/cluster/types/v1beta3" "github.com/akash-network/provider/cluster/util" ) @@ -127,8 +126,8 @@ func parseStorage(resource atypes.Volumes) []storageElement { return res } -func (ssp shellScriptPricing) CalculatePrice(ctx context.Context, req Request, res ctypes.Reservation) (sdk.DecCoin, error) { - d := newDataForScript(req, res) +func (ssp shellScriptPricing) CalculatePrice(ctx context.Context, r Request) (sdk.DecCoin, error) { + d := newDataForScript(r) buf := &bytes.Buffer{} if err := json.NewEncoder(buf).Encode(&d); err != nil { @@ -151,10 +150,10 @@ func (ssp shellScriptPricing) CalculatePrice(ctx context.Context, req Request, r stderrBuf := &bytes.Buffer{} cmd.Stderr = stderrBuf - denom := req.GSpec.Price().Denom + denom := r.GSpec.Price().Denom subprocEnv := os.Environ() - subprocEnv = append(subprocEnv, fmt.Sprintf("AKASH_OWNER=%s", req.Owner)) + subprocEnv = append(subprocEnv, fmt.Sprintf("AKASH_OWNER=%s", r.Owner)) subprocEnv = append(subprocEnv, fmt.Sprintf("AKASH_DENOM=%s", denom)) cmd.Env = subprocEnv @@ -190,28 +189,23 @@ func (ssp shellScriptPricing) CalculatePrice(ctx context.Context, req Request, r return sdk.NewDecCoinFromDec(denom, price), nil } -func newDataForScript(req Request, res ctypes.Reservation) dataForScript { +func newDataForScript(r Request) dataForScript { d := dataForScript{ - Resources: make([]dataForScriptElement, len(req.GSpec.Resources)), - Price: req.GSpec.Price(), + Resources: make([]dataForScriptElement, len(r.GSpec.Resources)), + Price: r.GSpec.Price(), } - if req.PricePrecision > 0 { - d.PricePrecision = &req.PricePrecision + if r.PricePrecision > 0 { + d.PricePrecision = &r.PricePrecision } - vendorModels := make(map[string]string) - - if res != nil { - for _, g := range res.GetAllocatedResources() { - for v, a := range parseGPU(g.GPU).Attributes.Vendor { - vendorModels[v] = a.Model - } - } + resources := r.GSpec.Resources + if len(r.AllocatedResources) > 0 { + resources = r.AllocatedResources } // iterate over everything & sum it up - for i, group := range req.GSpec.Resources { + for i, group := range resources { groupCount := group.Count cpuQuantity := parseCPU(group.CPU) @@ -220,15 +214,6 @@ func newDataForScript(req Request, res ctypes.Reservation) dataForScript { storageQuantity := parseStorage(group.Storage) endpointQuantity := len(group.Endpoints) - for vendor, attrs := range gpuQuantity.Attributes.Vendor { - if attrs.Model == "*" { - m, ok := vendorModels[vendor] - if ok { - attrs.Model = m - } - } - } - d.Resources[i] = dataForScriptElement{ CPU: cpuQuantity, GPU: gpuQuantity, diff --git a/bidengine/shellscript_test.go b/bidengine/shellscript_test.go index b8216199..c628fc97 100644 --- a/bidengine/shellscript_test.go +++ b/bidengine/shellscript_test.go @@ -9,8 +9,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - - ctypes "github.com/akash-network/provider/cluster/types/v1beta3" ) func Test_parseGPU_LastAttribute(t *testing.T) { @@ -45,13 +43,12 @@ func Test_parseGPU_LastAttribute(t *testing.T) { func Test_newDataForScript_GPUWildcard(t *testing.T) { cases := []struct { desc string - req Request - res ctypes.Reservation + r Request gpu gpuElement }{ { - desc: "wildcard and reservation value", - req: Request{ + desc: "wildcard and allocated resources", + r: Request{ GSpec: &v1beta3.GroupSpec{ Resources: v1beta3.ResourceUnits{ { @@ -82,12 +79,20 @@ func Test_newDataForScript_GPUWildcard(t *testing.T) { }, }, }, - }, - res: &testReservation{ - ru: dtypes.ResourceUnits{ + AllocatedResources: dtypes.ResourceUnits{ { Resources: atypes.Resources{ ID: 111, + CPU: &atypes.CPU{ + Units: atypes.ResourceValue{ + Val: sdk.NewInt(111), + }, + }, + Memory: &atypes.Memory{ + Quantity: atypes.ResourceValue{ + Val: sdk.NewInt(111), + }, + }, GPU: &atypes.GPU{ Units: atypes.ResourceValue{ Val: sdk.NewInt(111), @@ -114,7 +119,7 @@ func Test_newDataForScript_GPUWildcard(t *testing.T) { }, { desc: "wildcard and no reservation value", - req: Request{ + r: Request{ GSpec: &v1beta3.GroupSpec{ Resources: v1beta3.ResourceUnits{ { @@ -146,20 +151,6 @@ func Test_newDataForScript_GPUWildcard(t *testing.T) { }, }, }, - res: &testReservation{ - ru: dtypes.ResourceUnits{ - { - Resources: atypes.Resources{ - ID: 111, - GPU: &atypes.GPU{ - Units: atypes.ResourceValue{ - Val: sdk.NewInt(111), - }, - }, - }, - }, - }, - }, gpu: gpuElement{ Units: 111, Attributes: gpuAttributes{ @@ -171,7 +162,7 @@ func Test_newDataForScript_GPUWildcard(t *testing.T) { }, { desc: "no wildcard and reservation value", - req: Request{ + r: Request{ GSpec: &v1beta3.GroupSpec{ Resources: v1beta3.ResourceUnits{ { @@ -202,12 +193,20 @@ func Test_newDataForScript_GPUWildcard(t *testing.T) { }, }, }, - }, - res: &testReservation{ - ru: dtypes.ResourceUnits{ + AllocatedResources: dtypes.ResourceUnits{ { Resources: atypes.Resources{ ID: 111, + CPU: &atypes.CPU{ + Units: atypes.ResourceValue{ + Val: sdk.NewInt(111), + }, + }, + Memory: &atypes.Memory{ + Quantity: atypes.ResourceValue{ + Val: sdk.NewInt(111), + }, + }, GPU: &atypes.GPU{ Units: atypes.ResourceValue{ Val: sdk.NewInt(111), @@ -238,7 +237,7 @@ func Test_newDataForScript_GPUWildcard(t *testing.T) { c := c t.Run(c.desc, func(t *testing.T) { - d := newDataForScript(c.req, c.res) + d := newDataForScript(c.r) assert.NotEmpty(t, d) }) }