From 645017fa56e5e2719c1692aa4da2315ea8d45b91 Mon Sep 17 00:00:00 2001 From: Jayash Satolia <73050737+Jayashsatolia403@users.noreply.github.com> Date: Sun, 26 Nov 2023 21:36:06 +0530 Subject: [PATCH] Feature/update lock amount (#952) * Debug * Added tests for min lock * Fix tests * Fix tests * Fix minLockRequiredInZcn * Fix * Fix lint * Fix --- go.mod | 2 +- go.sum | 4 +- internal/api/model/api.go | 2 +- internal/api/util/client/api_client.go | 3 +- .../allocation_update_lock_amount_test.go | 304 ++++++++++++++++++ 5 files changed, 310 insertions(+), 5 deletions(-) create mode 100644 tests/api_tests/allocation_update_lock_amount_test.go diff --git a/go.mod b/go.mod index 5a18780589..dda8bb81e4 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/0chain/errors v1.0.3 - github.com/0chain/gosdk v1.10.1-0.20231117130204-69a53a3c392a + github.com/0chain/gosdk v1.10.1-0.20231124141610-5a931d29f60a github.com/go-resty/resty/v2 v2.7.0 github.com/herumi/bls-go-binary v1.31.0 github.com/shopspring/decimal v1.3.1 diff --git a/go.sum b/go.sum index 3d61059bb7..455a3408df 100644 --- a/go.sum +++ b/go.sum @@ -40,8 +40,8 @@ github.com/0chain/common v0.0.6-0.20230127095721-8df4d1d72565 h1:z+DtCR8mBsjPnEs github.com/0chain/common v0.0.6-0.20230127095721-8df4d1d72565/go.mod h1:UyDC8Qyl5z9lGkCnf9RHJPMektnFX8XtCJZHXCCVj8E= github.com/0chain/errors v1.0.3 h1:QQZPFxTfnMcRdt32DXbzRQIfGWmBsKoEdszKQDb0rRM= github.com/0chain/errors v1.0.3/go.mod h1:xymD6nVgrbgttWwkpSCfLLEJbFO6iHGQwk/yeSuYkIc= -github.com/0chain/gosdk v1.10.1-0.20231117130204-69a53a3c392a h1:t7piyKuRVyY5mfFTFiAcTCvj9jgKW3mRSUZ6EvDhNao= -github.com/0chain/gosdk v1.10.1-0.20231117130204-69a53a3c392a/go.mod h1:l/c+X5v6RMyzWUib6FFPdK5bTAzAJ7PojhEvELp3LGk= +github.com/0chain/gosdk v1.10.1-0.20231124141610-5a931d29f60a h1:sY9uwb/Ujq5zr2e146WitR4lfdP7vNoyfVhq6b5OzGI= +github.com/0chain/gosdk v1.10.1-0.20231124141610-5a931d29f60a/go.mod h1:l/c+X5v6RMyzWUib6FFPdK5bTAzAJ7PojhEvELp3LGk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Luzifer/go-openssl/v3 v3.1.0 h1:QqKqo6kYXGGUsvtUoCpRZm8lHw+jDfhbzr36gVj+/gw= diff --git a/internal/api/model/api.go b/internal/api/model/api.go index b1c2c14adb..474a88e60c 100644 --- a/internal/api/model/api.go +++ b/internal/api/model/api.go @@ -551,7 +551,7 @@ type UpdateAllocationRequest struct { Name string `json:"name"` OwnerID string `json:"owner_id"` Size int64 `json:"size"` - Expiration int64 `json:"expiration_date"` + Extend bool `json:"extend"` SetImmutable bool `json:"set_immutable"` AddBlobberId string `json:"add_blobber_id"` RemoveBlobberId string `json:"remove_blobber_id"` diff --git a/internal/api/util/client/api_client.go b/internal/api/util/client/api_client.go index ab5bc316d5..588ba93f59 100644 --- a/internal/api/util/client/api_client.go +++ b/internal/api/util/client/api_client.go @@ -1177,6 +1177,7 @@ func (c *APIClient) UpdateAllocation( wallet *model.Wallet, allocationID string, uar *model.UpdateAllocationRequest, + lock float64, requiredTransactionStatus int) { t.Log("Update allocation...") uar.ID = allocationID @@ -1186,7 +1187,7 @@ func (c *APIClient) UpdateAllocation( Wallet: wallet, ToClientID: StorageSmartContractAddress, TransactionData: model.NewUpdateAllocationTransactionData(uar), - Value: tokenomics.IntToZCN(0.1), + Value: tokenomics.IntToZCN(lock), TxnType: SCTxType, }, HttpOkStatus) diff --git a/tests/api_tests/allocation_update_lock_amount_test.go b/tests/api_tests/allocation_update_lock_amount_test.go new file mode 100644 index 0000000000..4c28a13425 --- /dev/null +++ b/tests/api_tests/allocation_update_lock_amount_test.go @@ -0,0 +1,304 @@ +package api_tests + +import ( + "testing" + "time" + + "github.com/0chain/gosdk/zboxcore/sdk" + "github.com/0chain/system_test/internal/api/model" + "github.com/0chain/system_test/internal/api/util/client" + "github.com/0chain/system_test/internal/api/util/test" + "github.com/stretchr/testify/require" +) + +func TestAllocationUpdateLockAmount(testSetup *testing.T) { + t := test.NewSystemTest(testSetup) + + t.RunSequentiallyWithTimeout("Extend Allocation Size", 1*time.Minute, func(t *test.SystemTest) { + apiClient.ExecuteFaucetWithTokens(t, sdkWallet, 10, client.TxSuccessfulStatus) + + blobberRequirements := model.DefaultBlobberRequirements(sdkWallet.Id, sdkWallet.PublicKey) + blobberRequirements.Size = 1 * GB + blobberRequirements.DataShards = 1 + blobberRequirements.ParityShards = 1 + allocationBlobbers := apiClient.GetAllocationBlobbers(t, sdkWallet, &blobberRequirements, client.HttpOkStatus) + allocationID := apiClient.CreateAllocationWithLockValue(t, sdkWallet, allocationBlobbers, 0.2, client.TxSuccessfulStatus) + t.Log("Allocation ID: ", allocationID) + + uar := &model.UpdateAllocationRequest{ + ID: allocationID, + Size: 1 * GB, + } + + minLockRequired, err := sdk.GetUpdateAllocationMinLock(allocationID, 1*GB, false, "", "") + require.NoError(t, err) + + minLockRequiredInZcn := float64(minLockRequired) / 1e10 + + require.Equal(t, 0.21, minLockRequiredInZcn, "Min lock required is not correct") + + t.Logf("Min lock required: %v", minLockRequired) + + apiClient.UpdateAllocation(t, sdkWallet, allocationID, uar, minLockRequiredInZcn, client.TxSuccessfulStatus) + alloc := apiClient.GetAllocation(t, allocationID, client.HttpOkStatus) + + require.Equal(t, int64(2*GB), alloc.Size, "Allocation size is not updated") + }) + + t.RunSequentiallyWithTimeout("Extend Allocation Size with used size > 0", 5*time.Minute, func(t *test.SystemTest) { + apiClient.ExecuteFaucetWithTokens(t, sdkWallet, 10, client.TxSuccessfulStatus) + + blobberRequirements := model.DefaultBlobberRequirements(sdkWallet.Id, sdkWallet.PublicKey) + blobberRequirements.Size = 1 * GB + blobberRequirements.DataShards = 1 + blobberRequirements.ParityShards = 1 + allocationBlobbers := apiClient.GetAllocationBlobbers(t, sdkWallet, &blobberRequirements, client.HttpOkStatus) + allocationID := apiClient.CreateAllocationWithLockValue(t, sdkWallet, allocationBlobbers, 0.2, client.TxSuccessfulStatus) + t.Log("Allocation ID: ", allocationID) + + uploadOp := sdkClient.AddUploadOperation(t, "", 10*MB) + chimneySdkClient.MultiOperation(t, allocationID, []sdk.OperationRequest{uploadOp}) + + time.Sleep(2 * time.Minute) + + uar := &model.UpdateAllocationRequest{ + ID: allocationID, + Size: 1 * GB, + } + + minLockRequired, err := sdk.GetUpdateAllocationMinLock(allocationID, 1*GB, false, "", "") + require.NoError(t, err) + + minLockRequiredInZcn := float64(minLockRequired) / 1e10 + + require.Greater(t, minLockRequiredInZcn, 0.2, "Min lock required is not correct") + + t.Logf("Min lock required: %v", minLockRequired) + + apiClient.UpdateAllocation(t, sdkWallet, allocationID, uar, 0.2, client.TxSuccessfulStatus) + alloc := apiClient.GetAllocation(t, allocationID, client.HttpOkStatus) + + require.Equal(t, int64(2*GB), alloc.Size, "Allocation size is not updated") + }) + + t.RunSequentiallyWithTimeout("Extend Allocation Duration", 1*time.Minute, func(t *test.SystemTest) { + apiClient.ExecuteFaucetWithTokens(t, sdkWallet, 10, client.TxSuccessfulStatus) + + blobberRequirements := model.DefaultBlobberRequirements(sdkWallet.Id, sdkWallet.PublicKey) + blobberRequirements.Size = 1 * GB + blobberRequirements.DataShards = 1 + blobberRequirements.ParityShards = 1 + allocationBlobbers := apiClient.GetAllocationBlobbers(t, sdkWallet, &blobberRequirements, client.HttpOkStatus) + allocationID := apiClient.CreateAllocationWithLockValue(t, sdkWallet, allocationBlobbers, 0.2, client.TxSuccessfulStatus) + t.Log("Allocation ID: ", allocationID) + + uar := &model.UpdateAllocationRequest{ + ID: allocationID, + Extend: true, + } + + minLockRequired, err := sdk.GetUpdateAllocationMinLock(allocationID, 0, true, "", "") + require.NoError(t, err) + + t.Logf("Min lock required: %v", minLockRequired) + + minLockRequiredInZcn := float64(minLockRequired) / 1e10 + + require.Equal(t, float64(0), minLockRequiredInZcn, "Min lock required is not correct") + + apiClient.UpdateAllocation(t, sdkWallet, allocationID, uar, minLockRequiredInZcn, client.TxSuccessfulStatus) + alloc := apiClient.GetAllocation(t, allocationID, client.HttpOkStatus) + + require.Equal(t, int64(1*GB), alloc.Size, "Allocation size is not updated") + }) + + t.RunSequentiallyWithTimeout("Extend Allocation Duration with used size > 0", 5*time.Minute, func(t *test.SystemTest) { + apiClient.ExecuteFaucetWithTokens(t, sdkWallet, 10, client.TxSuccessfulStatus) + + blobberRequirements := model.DefaultBlobberRequirements(sdkWallet.Id, sdkWallet.PublicKey) + blobberRequirements.Size = 1 * GB + blobberRequirements.DataShards = 1 + blobberRequirements.ParityShards = 1 + allocationBlobbers := apiClient.GetAllocationBlobbers(t, sdkWallet, &blobberRequirements, client.HttpOkStatus) + allocationID := apiClient.CreateAllocationWithLockValue(t, sdkWallet, allocationBlobbers, 0.2, client.TxSuccessfulStatus) + t.Log("Allocation ID: ", allocationID) + + uploadOp := sdkClient.AddUploadOperation(t, "", 10*MB) + chimneySdkClient.MultiOperation(t, allocationID, []sdk.OperationRequest{uploadOp}) + + time.Sleep(2 * time.Minute) + + uar := &model.UpdateAllocationRequest{ + ID: allocationID, + Extend: true, + } + + minLockRequired, err := sdk.GetUpdateAllocationMinLock(allocationID, 0, true, "", "") + require.NoError(t, err) + + t.Logf("Min lock required: %v", minLockRequired) + + minLockRequiredInZcn := float64(minLockRequired) / 1e10 + + apiClient.UpdateAllocation(t, sdkWallet, allocationID, uar, minLockRequiredInZcn, client.TxSuccessfulStatus) + alloc := apiClient.GetAllocation(t, allocationID, client.HttpOkStatus) + + require.Equal(t, int64(1*GB), alloc.Size, "Allocation size is not updated") + }) + + t.RunSequentiallyWithTimeout("Add blobber to allocation", 1*time.Minute, func(t *test.SystemTest) { + apiClient.ExecuteFaucetWithTokens(t, sdkWallet, 10, client.TxSuccessfulStatus) + + blobberRequirements := model.DefaultBlobberRequirements(sdkWallet.Id, sdkWallet.PublicKey) + blobberRequirements.Size = 1 * GB + blobberRequirements.DataShards = 1 + blobberRequirements.ParityShards = 1 + allocationBlobbers := apiClient.GetAllocationBlobbers(t, sdkWallet, &blobberRequirements, client.HttpOkStatus) + allocationID := apiClient.CreateAllocationWithLockValue(t, sdkWallet, allocationBlobbers, 0.2, client.TxSuccessfulStatus) + t.Log("Allocation ID: ", allocationID) + + alloc := apiClient.GetAllocation(t, allocationID, client.HttpOkStatus) + + newBlobberID := getNotUsedStorageNodeID(allocationBlobbers.Blobbers, alloc.Blobbers) + require.NotZero(t, newBlobberID, "New blobber ID contains zero value") + + uar := &model.UpdateAllocationRequest{ + ID: allocationID, + AddBlobberId: newBlobberID, + } + + minLockRequired, err := sdk.GetUpdateAllocationMinLock(allocationID, 0, false, newBlobberID, "") + require.NoError(t, err) + + t.Logf("Min lock required: %v", minLockRequired) + + minLockRequiredInZcn := float64(minLockRequired) / 1e10 + + require.Equal(t, 0.105, minLockRequiredInZcn, "Min lock required is not correct") + + apiClient.UpdateAllocation(t, sdkWallet, allocationID, uar, minLockRequiredInZcn, client.TxSuccessfulStatus) + alloc = apiClient.GetAllocation(t, allocationID, client.HttpOkStatus) + + require.Equal(t, int64(1*GB), alloc.Size, "Allocation size is not updated") + }) + + t.RunSequentiallyWithTimeout("Add blobber to allocation with used size > 0", 5*time.Minute, func(t *test.SystemTest) { + apiClient.ExecuteFaucetWithTokens(t, sdkWallet, 10, client.TxSuccessfulStatus) + + blobberRequirements := model.DefaultBlobberRequirements(sdkWallet.Id, sdkWallet.PublicKey) + blobberRequirements.Size = 1 * GB + blobberRequirements.DataShards = 1 + blobberRequirements.ParityShards = 1 + allocationBlobbers := apiClient.GetAllocationBlobbers(t, sdkWallet, &blobberRequirements, client.HttpOkStatus) + allocationID := apiClient.CreateAllocationWithLockValue(t, sdkWallet, allocationBlobbers, 0.2, client.TxSuccessfulStatus) + t.Log("Allocation ID: ", allocationID) + + uploadOp := sdkClient.AddUploadOperation(t, "", 10*MB) + chimneySdkClient.MultiOperation(t, allocationID, []sdk.OperationRequest{uploadOp}) + + time.Sleep(2 * time.Minute) + + alloc := apiClient.GetAllocation(t, allocationID, client.HttpOkStatus) + + newBlobberID := getNotUsedStorageNodeID(allocationBlobbers.Blobbers, alloc.Blobbers) + require.NotZero(t, newBlobberID, "New blobber ID contains zero value") + + uar := &model.UpdateAllocationRequest{ + ID: allocationID, + AddBlobberId: newBlobberID, + } + + minLockRequired, err := sdk.GetUpdateAllocationMinLock(allocationID, 0, false, newBlobberID, "") + require.NoError(t, err) + + t.Logf("Min lock required: %v", minLockRequired) + + minLockRequiredInZcn := float64(minLockRequired) / 1e10 + + apiClient.UpdateAllocation(t, sdkWallet, allocationID, uar, minLockRequiredInZcn, client.TxSuccessfulStatus) + alloc = apiClient.GetAllocation(t, allocationID, client.HttpOkStatus) + + require.Equal(t, int64(1*GB), alloc.Size, "Allocation size is not updated") + }) + + t.RunSequentiallyWithTimeout("Replace blobber", 1*time.Minute, func(t *test.SystemTest) { + apiClient.ExecuteFaucetWithTokens(t, sdkWallet, 10, client.TxSuccessfulStatus) + + blobberRequirements := model.DefaultBlobberRequirements(sdkWallet.Id, sdkWallet.PublicKey) + blobberRequirements.Size = 1 * GB + blobberRequirements.DataShards = 1 + blobberRequirements.ParityShards = 2 + allocationBlobbers := apiClient.GetAllocationBlobbers(t, sdkWallet, &blobberRequirements, client.HttpOkStatus) + allocationID := apiClient.CreateAllocationWithLockValue(t, sdkWallet, allocationBlobbers, 0.3, client.TxSuccessfulStatus) + t.Log("Allocation ID: ", allocationID) + + alloc := apiClient.GetAllocation(t, allocationID, client.HttpOkStatus) + + newBlobberID := getNotUsedStorageNodeID(allocationBlobbers.Blobbers, alloc.Blobbers) + require.NotZero(t, newBlobberID, "New blobber ID contains zero value") + + removeBlobberID := alloc.Blobbers[0].ID + + uar := &model.UpdateAllocationRequest{ + ID: allocationID, + AddBlobberId: newBlobberID, + RemoveBlobberId: removeBlobberID, + } + + minLockRequired, err := sdk.GetUpdateAllocationMinLock(allocationID, 0, false, newBlobberID, removeBlobberID) + require.NoError(t, err) + + t.Logf("Min lock required: %v", minLockRequired) + + minLockRequiredInZcn := float64(minLockRequired) / 1e10 + + apiClient.UpdateAllocation(t, sdkWallet, allocationID, uar, minLockRequiredInZcn, client.TxSuccessfulStatus) + alloc = apiClient.GetAllocation(t, allocationID, client.HttpOkStatus) + + require.Equal(t, int64(1*GB), alloc.Size, "Allocation size is not updated") + }) + + t.RunSequentiallyWithTimeout("Replace blobber with used size > 0", 5*time.Minute, func(t *test.SystemTest) { + apiClient.ExecuteFaucetWithTokens(t, sdkWallet, 10, client.TxSuccessfulStatus) + + blobberRequirements := model.DefaultBlobberRequirements(sdkWallet.Id, sdkWallet.PublicKey) + blobberRequirements.Size = 1 * GB + blobberRequirements.DataShards = 1 + blobberRequirements.ParityShards = 2 + allocationBlobbers := apiClient.GetAllocationBlobbers(t, sdkWallet, &blobberRequirements, client.HttpOkStatus) + allocationID := apiClient.CreateAllocationWithLockValue(t, sdkWallet, allocationBlobbers, 0.3, client.TxSuccessfulStatus) + t.Log("Allocation ID: ", allocationID) + + uploadOp := sdkClient.AddUploadOperation(t, "", 10*MB) + chimneySdkClient.MultiOperation(t, allocationID, []sdk.OperationRequest{uploadOp}) + + time.Sleep(2 * time.Minute) + + alloc := apiClient.GetAllocation(t, allocationID, client.HttpOkStatus) + + newBlobberID := getNotUsedStorageNodeID(allocationBlobbers.Blobbers, alloc.Blobbers) + require.NotZero(t, newBlobberID, "New blobber ID contains zero value") + + removeBlobberID := alloc.Blobbers[0].ID + + uar := &model.UpdateAllocationRequest{ + ID: allocationID, + AddBlobberId: newBlobberID, + RemoveBlobberId: removeBlobberID, + } + + minLockRequired, err := sdk.GetUpdateAllocationMinLock(allocationID, 0, false, newBlobberID, removeBlobberID) + require.NoError(t, err) + + t.Logf("Min lock required: %v", minLockRequired) + + minLockRequiredInZcn := float64(minLockRequired) / 1e10 + + apiClient.UpdateAllocation(t, sdkWallet, allocationID, uar, minLockRequiredInZcn, client.TxSuccessfulStatus) + alloc = apiClient.GetAllocation(t, allocationID, client.HttpOkStatus) + + require.Equal(t, int64(1*GB), alloc.Size, "Allocation size is not updated") + }) +} + +//https://dev-1.devnet-0chain.net/sharder01/v1/screst/6dba10422e368813802877a85039d3985d96760ed844092319743fb3a76712d7/allocation-update-min-lock?data=%7B%22add_blobber_id%22%3A%22%22%2C%22extend%22%3Afalse%2C%22id%22%3A%22a50b5e9e0b24569b04b3f8c45a67730e11a0b9fe1840a88c130efa7ec34c6a73%22%2C%22owner_id%22%3A%226d02a02cb9cbddd76f7e3981eae473b86dc488e558cbaffbe0549b31926605b3%22%2C%22owner_public_key%22%3A%22%22%2C%22remove_blobber_id%22%3A%22%22%2C%22size%22%3A0%7D