From 7a7f225f19e28d847098d4a905b57cbc8da1fff1 Mon Sep 17 00:00:00 2001 From: Jayash Satolia <73050737+Jayashsatolia403@users.noreply.github.com> Date: Fri, 17 Nov 2023 20:38:36 +0530 Subject: [PATCH] Feature/register blobber (#947) --- internal/api/model/api.go | 7 ++ internal/api/util/client/api_client.go | 52 ++++++++ tests/api_tests/register_blobber_test.go | 146 +++++++++++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 tests/api_tests/register_blobber_test.go diff --git a/internal/api/model/api.go b/internal/api/model/api.go index 74095ca5f5..ed67c7451a 100644 --- a/internal/api/model/api.go +++ b/internal/api/model/api.go @@ -168,6 +168,13 @@ func NewCreateAllocationTransactionData(scRestGetAllocationBlobbersResponse *SCR } } +func NewRegisterBlobberTransactionData(scRegisterBlobberRequest *StorageNode) TransactionData { + return TransactionData{ + Name: "add_blobber", + Input: *scRegisterBlobberRequest, + } +} + func NewCreateFreeAllocationTransactionData(scRestGetFreeAllocationBlobbersResponse *SCRestGetFreeAllocationBlobbersResponse) TransactionData { return TransactionData{ Name: "free_allocation_request", diff --git a/internal/api/util/client/api_client.go b/internal/api/util/client/api_client.go index d16ec24c12..70ecb9fa71 100644 --- a/internal/api/util/client/api_client.go +++ b/internal/api/util/client/api_client.go @@ -1049,6 +1049,58 @@ func (c *APIClient) CreateAllocationWithLockValue(t *test.SystemTest, return createAllocationTransactionPutResponse.Entity.Hash } +func (c *APIClient) RegisterBlobber(t *test.SystemTest, + wallet *model.Wallet, + storageNode *model.StorageNode, + requiredTransactionStatus int, + expectedResponse string) string { + t.Log("Registering blobber...") + + registerBlobberTransactionPutResponse, resp, err := c.V1TransactionPut( + t, + model.InternalTransactionPutRequest{ + Wallet: wallet, + ToClientID: StorageSmartContractAddress, + TransactionData: model.NewRegisterBlobberTransactionData(storageNode), + Value: tokenomics.IntToZCN(0), + TxnType: SCTxType, + }, + HttpOkStatus) + require.Nil(t, err) + require.NotNil(t, resp) + require.NotNil(t, registerBlobberTransactionPutResponse) + + var registerBlobberTransactionGetConfirmationResponse *model.TransactionGetConfirmationResponse + + wait.PoolImmediately(t, time.Minute*2, func() bool { + registerBlobberTransactionGetConfirmationResponse, resp, err = c.V1TransactionGetConfirmation( + t, + model.TransactionGetConfirmationRequest{ + Hash: registerBlobberTransactionPutResponse.Entity.Hash, + }, + HttpOkStatus) + + if err != nil { + t.Log("Error registering blobber : ", err) + return false + } + + if resp == nil { + return false + } + + if registerBlobberTransactionGetConfirmationResponse == nil { + return false + } + + return registerBlobberTransactionGetConfirmationResponse.Status == requiredTransactionStatus && registerBlobberTransactionGetConfirmationResponse.Transaction.TransactionOutput == expectedResponse + }) + + wallet.IncNonce() + + return registerBlobberTransactionPutResponse.Entity.Hash +} + func (c *APIClient) CreateFreeAllocation(t *test.SystemTest, wallet *model.Wallet, scRestGetFreeAllocationBlobbersResponse *model.SCRestGetFreeAllocationBlobbersResponse, diff --git a/tests/api_tests/register_blobber_test.go b/tests/api_tests/register_blobber_test.go new file mode 100644 index 0000000000..977bdcf5b3 --- /dev/null +++ b/tests/api_tests/register_blobber_test.go @@ -0,0 +1,146 @@ +package api_tests + +import ( + "crypto/rand" + "fmt" + "math/big" + "testing" + + "github.com/0chain/system_test/internal/api/model" + "github.com/0chain/system_test/internal/api/util/client" + "github.com/google/uuid" + + "github.com/0chain/system_test/internal/api/util/test" +) + +func TestRegisterBlobber(testSetup *testing.T) { + t := test.NewSystemTest(testSetup) + + t.RunSequentially("Write price lower than min_write_price should not allow register", func(t *test.SystemTest) { + sdkWalletBalance := apiClient.GetWalletBalance(t, sdkWallet, client.HttpOkStatus) + t.Logf("sdkWallet balance: %v", sdkWallet) + sdkWallet.Nonce = int(sdkWalletBalance.Nonce) + + apiClient.ExecuteFaucetWithTokens(t, sdkWallet, 9.0, client.TxSuccessfulStatus) + + sn := &model.StorageNode{} + sn.ID = uuid.New().String() + sn.BaseURL = generateRandomURL() + sn.Capacity = 10 * GB + + sn.Terms.ReadPrice = 1000000000 + sn.Terms.WritePrice = 1 + + sn.StakePoolSettings.DelegateWallet = "config.Configuration.DelegateWallet" + sn.StakePoolSettings.NumDelegates = 2 + sn.StakePoolSettings.ServiceCharge = 0.2 + + apiClient.RegisterBlobber(t, sdkWallet, sn, 2, "add_or_update_blobber_failed: invalid blobber params: write_price is less than min_write_price allowed") + }) + + t.RunSequentially("Write price higher than max_write_price should not allow register", func(t *test.SystemTest) { + sdkWalletBalance := apiClient.GetWalletBalance(t, sdkWallet, client.HttpOkStatus) + t.Logf("sdkWallet balance: %v", sdkWallet) + sdkWallet.Nonce = int(sdkWalletBalance.Nonce) + + apiClient.ExecuteFaucetWithTokens(t, sdkWallet, 9.0, client.TxSuccessfulStatus) + + sn := &model.StorageNode{} + sn.ID = uuid.New().String() + sn.BaseURL = generateRandomURL() + sn.Capacity = 10240 * GB + + sn.Terms.ReadPrice = 1000000000 + sn.Terms.WritePrice = 100000000000000000 + + sn.StakePoolSettings.DelegateWallet = "config.Configuration.DelegateWallet" + sn.StakePoolSettings.NumDelegates = 2 + sn.StakePoolSettings.ServiceCharge = 0.2 + + apiClient.RegisterBlobber(t, sdkWallet, sn, 2, "add_or_update_blobber_failed: invalid blobber params: write_price is greater than max_write_price allowed") + }) + + t.RunSequentially("Read price higher than max_read_price should not allow register", func(t *test.SystemTest) { + sdkWalletBalance := apiClient.GetWalletBalance(t, sdkWallet, client.HttpOkStatus) + t.Logf("sdkWallet balance: %v", sdkWallet) + sdkWallet.Nonce = int(sdkWalletBalance.Nonce) + + apiClient.ExecuteFaucetWithTokens(t, sdkWallet, 9.0, client.TxSuccessfulStatus) + + sn := &model.StorageNode{} + sn.ID = uuid.New().String() + sn.BaseURL = generateRandomURL() + sn.Capacity = 10240 * GB + + sn.Terms.ReadPrice = 100000000000000000 + sn.Terms.WritePrice = 1000000000 + + sn.StakePoolSettings.DelegateWallet = "config.Configuration.DelegateWallet" + sn.StakePoolSettings.NumDelegates = 2 + sn.StakePoolSettings.ServiceCharge = 0.2 + + apiClient.RegisterBlobber(t, sdkWallet, sn, 2, "add_or_update_blobber_failed: invalid blobber params: read_price is greater than max_read_price allowed") + }) + + t.RunSequentially("Service charge higher than max_service_charge should not allow register", func(t *test.SystemTest) { + sdkWalletBalance := apiClient.GetWalletBalance(t, sdkWallet, client.HttpOkStatus) + t.Logf("sdkWallet balance: %v", sdkWallet) + sdkWallet.Nonce = int(sdkWalletBalance.Nonce) + + apiClient.ExecuteFaucetWithTokens(t, sdkWallet, 9.0, client.TxSuccessfulStatus) + + sn := &model.StorageNode{} + sn.ID = uuid.New().String() + sn.BaseURL = generateRandomURL() + sn.Capacity = 10240 * GB + + sn.Terms.ReadPrice = 1000000000 + sn.Terms.WritePrice = 1000000000 + + sn.StakePoolSettings.DelegateWallet = "config.Configuration.DelegateWallet" + sn.StakePoolSettings.NumDelegates = 2 + sn.StakePoolSettings.ServiceCharge = 0.6 + + apiClient.RegisterBlobber(t, sdkWallet, sn, 2, "add_or_update_blobber_failed: creating stake pool: invalid stake_pool settings: service_charge (0.600000) is greater than max allowed by SC (0.500000)") + }) + + t.RunSequentially("Capacity lower than min_blobber_capacity should not allow register", func(t *test.SystemTest) { + sdkWalletBalance := apiClient.GetWalletBalance(t, sdkWallet, client.HttpOkStatus) + t.Logf("sdkWallet balance: %v", sdkWallet) + sdkWallet.Nonce = int(sdkWalletBalance.Nonce) + + apiClient.ExecuteFaucetWithTokens(t, sdkWallet, 9.0, client.TxSuccessfulStatus) + + sn := &model.StorageNode{} + sn.ID = uuid.New().String() + sn.BaseURL = generateRandomURL() + sn.Capacity = 1 * MB + + sn.Terms.ReadPrice = 1000000000 + sn.Terms.WritePrice = 1000000000 + + sn.StakePoolSettings.DelegateWallet = "config.Configuration.DelegateWallet" + sn.StakePoolSettings.NumDelegates = 2 + sn.StakePoolSettings.ServiceCharge = 0.2 + + apiClient.RegisterBlobber(t, sdkWallet, sn, 2, "add_or_update_blobber_failed: invalid blobber params: insufficient blobber capacity") + }) +} + +func generateRandomString(length int) string { + charset := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + + result := make([]byte, length) + for i := range result { + randomIndex, err := rand.Int(rand.Reader, big.NewInt(int64(len(charset)))) + if err != nil { + panic(err) + } + result[i] = charset[randomIndex.Int64()] + } + return string(result) +} + +func generateRandomURL() string { + return fmt.Sprintf("http://%s.com/%s", generateRandomString(10), generateRandomString(8)) +}