github.com/0chain/gosdk@v1.17.11/zboxcore/sdk/blobber_operations_mobile.go (about) 1 //go:build mobile 2 // +build mobile 3 4 package sdk 5 6 import ( 7 "encoding/json" 8 "math" 9 "strconv" 10 "strings" 11 12 "github.com/0chain/errors" 13 "github.com/0chain/gosdk/core/transaction" 14 "github.com/0chain/gosdk/zboxcore/client" 15 ) 16 17 // CreateAllocationForOwner creates a new allocation with the given options (txn: `storagesc.new_allocation_request`). 18 // 19 // - owner is the client id of the owner of the allocation. 20 // - ownerpublickey is the public key of the owner of the allocation. 21 // - datashards is the number of data shards for the allocation. 22 // - parityshards is the number of parity shards for the allocation. 23 // - size is the size of the allocation. 24 // - readPrice is the read price range for the allocation (Reads in Züs are free!). 25 // - writePrice is the write price range for the allocation. 26 // - lock is the lock value for the transaction (how much tokens to lock to the allocation, in SAS). 27 // - preferredBlobberIds is a list of preferred blobber ids for the allocation. 28 // - thirdPartyExtendable is a flag indicating whether the allocation can be extended by a third party. 29 // - fileOptionsParams is the file options parameters for the allocation, which control the usage permissions of the files in the allocation. 30 // 31 // returns the hash of the transaction, the nonce of the transaction, the transaction object and an error if any. 32 func CreateAllocationForOwner( 33 owner, ownerpublickey string, 34 datashards, parityshards int, size int64, 35 readPrice, writePrice PriceRange, 36 lock uint64, preferredBlobberIds, blobberAuthTickets []string, thirdPartyExtendable, IsEnterprise, force bool, fileOptionsParams *FileOptionsParameters, 37 ) (hash string, nonce int64, txn *transaction.Transaction, err error) { 38 39 if lock > math.MaxInt64 { 40 return "", 0, nil, errors.New("invalid_lock", "int64 overflow on lock value") 41 } 42 43 if datashards < 1 || parityshards < 1 { 44 return "", 0, nil, errors.New("allocation_validation_failed", "atleast 1 data and 1 parity shards are required") 45 } 46 47 allocationRequest, err := getNewAllocationBlobbers( 48 datashards, parityshards, size, readPrice, writePrice, preferredBlobberIds, blobberAuthTickets, force) 49 if err != nil { 50 return "", 0, nil, errors.New("failed_get_allocation_blobbers", "failed to get blobbers for allocation: "+err.Error()) 51 } 52 53 if !sdkInitialized { 54 return "", 0, nil, sdkNotInitialized 55 } 56 57 allocationRequest["owner_id"] = owner 58 allocationRequest["owner_public_key"] = ownerpublickey 59 allocationRequest["third_party_extendable"] = thirdPartyExtendable 60 allocationRequest["file_options_changed"], allocationRequest["file_options"] = calculateAllocationFileOptions(63 /*0011 1111*/, fileOptionsParams) 61 allocationRequest["is_enterprise"] = IsEnterprise 62 63 var sn = transaction.SmartContractTxnData{ 64 Name: transaction.NEW_ALLOCATION_REQUEST, 65 InputArgs: allocationRequest, 66 } 67 hash, _, nonce, txn, err = storageSmartContractTxnValue(sn, strconv.FormatUint(lock, 10)) 68 return 69 } 70 71 // CreateFreeAllocation creates a new free allocation (txn: `storagesc.free_allocation_request`). 72 // - marker is the marker for the free allocation. 73 // - value is the value of the free allocation. 74 // 75 // returns the hash of the transaction, the nonce of the transaction and an error if any. 76 func CreateFreeAllocation(marker string, value string) (string, int64, error) { 77 if !sdkInitialized { 78 return "", 0, sdkNotInitialized 79 } 80 81 recipientPublicKey := client.GetClientPublicKey() 82 83 var input = map[string]interface{}{ 84 "recipient_public_key": recipientPublicKey, 85 "marker": marker, 86 } 87 88 blobbers, err := GetFreeAllocationBlobbers(input) 89 if err != nil { 90 return "", 0, err 91 } 92 93 input["blobbers"] = blobbers 94 95 var sn = transaction.SmartContractTxnData{ 96 Name: transaction.NEW_FREE_ALLOCATION, 97 InputArgs: input, 98 } 99 hash, _, n, _, err := storageSmartContractTxnValue(sn, value) 100 return hash, n, err 101 } 102 103 // UpdateAllocation sends an update request for an allocation (txn: `storagesc.update_allocation_request`) 104 // 105 // - size is the size of the allocation. 106 // - extend is a flag indicating whether to extend the allocation. 107 // - allocationID is the id of the allocation. 108 // - lock is the lock value for the transaction (how much tokens to lock to the allocation, in SAS). 109 // - addBlobberId is the id of the blobber to add to the allocation. 110 // - addBlobberAuthTicket is the auth ticket of the blobber to add to the allocation, in case the blobber is restricted. 111 // - removeBlobberId is the id of the blobber to remove from the allocation. 112 // - setThirdPartyExtendable is a flag indicating whether the allocation can be extended by a third party. 113 // - fileOptionsParams is the file options parameters for the allocation, which control the usage permissions of the files in the allocation. 114 // 115 // returns the hash of the transaction, the nonce of the transaction and an error if any. 116 func UpdateAllocation( 117 size int64, 118 extend bool, 119 allocationID string, 120 lock uint64, 121 addBlobberId, addBlobberAuthTicket, removeBlobberId string, 122 setThirdPartyExtendable bool, fileOptionsParams *FileOptionsParameters, 123 ) (hash string, nonce int64, err error) { 124 125 if lock > math.MaxInt64 { 126 return "", 0, errors.New("invalid_lock", "int64 overflow on lock value") 127 } 128 129 if !sdkInitialized { 130 return "", 0, sdkNotInitialized 131 } 132 133 alloc, err := GetAllocation(allocationID) 134 if err != nil { 135 return "", 0, allocationNotFound 136 } 137 138 updateAllocationRequest := make(map[string]interface{}) 139 updateAllocationRequest["owner_id"] = client.GetClientID() 140 updateAllocationRequest["owner_public_key"] = "" 141 updateAllocationRequest["id"] = allocationID 142 updateAllocationRequest["size"] = size 143 updateAllocationRequest["extend"] = extend 144 updateAllocationRequest["add_blobber_id"] = addBlobberId 145 updateAllocationRequest["add_blobber_auth_ticket"] = addBlobberAuthTicket 146 updateAllocationRequest["remove_blobber_id"] = removeBlobberId 147 updateAllocationRequest["set_third_party_extendable"] = setThirdPartyExtendable 148 updateAllocationRequest["file_options_changed"], updateAllocationRequest["file_options"] = calculateAllocationFileOptions(alloc.FileOptions, fileOptionsParams) 149 150 sn := transaction.SmartContractTxnData{ 151 Name: transaction.STORAGESC_UPDATE_ALLOCATION, 152 InputArgs: updateAllocationRequest, 153 } 154 hash, _, nonce, _, err = storageSmartContractTxnValue(sn, strconv.FormatUint(lock, 10)) 155 return 156 } 157 158 // StakePoolLock locks tokens in a stake pool. 159 // This function is the entry point for the staking operation. 160 // Provided the provider type and provider ID, the value is locked in the stake pool between the SDK client and the provider. 161 // Based on the locked amount, the client will get rewards as share of the provider's rewards. 162 // - providerType: provider type 163 // - providerID: provider ID 164 // - value: value to lock 165 // - fee: transaction fee 166 func StakePoolLock(providerType ProviderType, providerID string, value, fee string) (hash string, nonce int64, err error) { 167 if !sdkInitialized { 168 return "", 0, sdkNotInitialized 169 } 170 171 if providerType == 0 { 172 return "", 0, errors.New("stake_pool_lock", "provider is required") 173 } 174 175 if providerID == "" { 176 return "", 0, errors.New("stake_pool_lock", "provider_id is required") 177 } 178 179 spr := stakePoolRequest{ 180 ProviderType: providerType, 181 ProviderID: providerID, 182 } 183 184 var sn = transaction.SmartContractTxnData{ 185 InputArgs: &spr, 186 } 187 188 var scAddress string 189 switch providerType { 190 case ProviderBlobber, ProviderValidator: 191 scAddress = STORAGE_SCADDRESS 192 sn.Name = transaction.STORAGESC_STAKE_POOL_LOCK 193 case ProviderMiner, ProviderSharder: 194 scAddress = MINERSC_SCADDRESS 195 sn.Name = transaction.MINERSC_LOCK 196 case ProviderAuthorizer: 197 scAddress = ZCNSC_SCADDRESS 198 sn.Name = transaction.ZCNSC_LOCK 199 default: 200 return "", 0, errors.Newf("stake_pool_lock", "unsupported provider type: %v", providerType) 201 } 202 203 hash, _, nonce, _, err = smartContractTxnValueFeeWithRetry(scAddress, sn, value, fee) 204 return 205 } 206 207 // StakePoolUnlock unlocks a stake pool tokens. If tokens can't be unlocked due 208 // to opened offers, then it returns time where the tokens can be unlocked, 209 // marking the pool as 'want to unlock' to avoid its usage in offers in the 210 // future. The time is maximal time that can be lesser in some cases. To 211 // unlock tokens can't be unlocked now, wait the time and unlock them (call 212 // this function again). 213 // - providerType: provider type 214 // - providerID: provider ID 215 // - fee: transaction fee 216 func StakePoolUnlock(providerType ProviderType, providerID string, fee string) (unstake int64, nonce int64, err error) { 217 if !sdkInitialized { 218 return 0, 0, sdkNotInitialized 219 } 220 221 if providerType == 0 { 222 return 0, 0, errors.New("stake_pool_lock", "provider is required") 223 } 224 225 if providerID == "" { 226 return 0, 0, errors.New("stake_pool_lock", "provider_id is required") 227 } 228 229 spr := stakePoolRequest{ 230 ProviderType: providerType, 231 ProviderID: providerID, 232 } 233 234 var sn = transaction.SmartContractTxnData{ 235 InputArgs: &spr, 236 } 237 238 var scAddress string 239 switch providerType { 240 case ProviderBlobber, ProviderValidator: 241 scAddress = STORAGE_SCADDRESS 242 sn.Name = transaction.STORAGESC_STAKE_POOL_UNLOCK 243 case ProviderMiner, ProviderSharder: 244 scAddress = MINERSC_SCADDRESS 245 sn.Name = transaction.MINERSC_UNLOCK 246 case ProviderAuthorizer: 247 scAddress = ZCNSC_SCADDRESS 248 sn.Name = transaction.ZCNSC_UNLOCK 249 default: 250 return 0, 0, errors.Newf("stake_pool_unlock", "unsupported provider type: %v", providerType) 251 } 252 253 var out string 254 if _, out, nonce, _, err = smartContractTxnValueFeeWithRetry(scAddress, sn, "0", fee); err != nil { 255 return // an error 256 } 257 258 var spuu stakePoolLock 259 if err = json.Unmarshal([]byte(out), &spuu); err != nil { 260 return 261 } 262 263 return spuu.Amount, nonce, nil 264 } 265 266 // ReadPoolLock locks given number of tokes for given duration in read pool. 267 // - tokens: number of tokens to lock 268 // - fee: transaction fee 269 func ReadPoolLock(tokens, fee string) (hash string, nonce int64, err error) { 270 if !sdkInitialized { 271 return "", 0, sdkNotInitialized 272 } 273 274 var sn = transaction.SmartContractTxnData{ 275 Name: transaction.STORAGESC_READ_POOL_LOCK, 276 InputArgs: nil, 277 } 278 hash, _, nonce, _, err = smartContractTxnValueFeeWithRetry(STORAGE_SCADDRESS, sn, tokens, fee) 279 return 280 } 281 282 // ReadPoolUnlock unlocks tokens in expired read pool 283 // - fee: transaction fee 284 func ReadPoolUnlock(fee string) (hash string, nonce int64, err error) { 285 if !sdkInitialized { 286 return "", 0, sdkNotInitialized 287 } 288 289 var sn = transaction.SmartContractTxnData{ 290 Name: transaction.STORAGESC_READ_POOL_UNLOCK, 291 InputArgs: nil, 292 } 293 hash, _, nonce, _, err = smartContractTxnValueFeeWithRetry(STORAGE_SCADDRESS, sn, "0", fee) 294 return 295 } 296 297 // 298 // write pool 299 // 300 301 // WritePoolLock locks given number of tokes for given duration in read pool. 302 // - allocID: allocation ID 303 // - tokens: number of tokens to lock 304 // - fee: transaction fee 305 func WritePoolLock(allocID string, tokens, fee string) (hash string, nonce int64, err error) { 306 if !sdkInitialized { 307 return "", 0, sdkNotInitialized 308 } 309 310 type lockRequest struct { 311 AllocationID string `json:"allocation_id"` 312 } 313 314 var req lockRequest 315 req.AllocationID = allocID 316 317 var sn = transaction.SmartContractTxnData{ 318 Name: transaction.STORAGESC_WRITE_POOL_LOCK, 319 InputArgs: &req, 320 } 321 322 hash, _, nonce, _, err = smartContractTxnValueFeeWithRetry(STORAGE_SCADDRESS, sn, tokens, fee) 323 return 324 } 325 326 // WritePoolUnlock unlocks ALL tokens of a write pool. Needs to be cancelled first. 327 // - allocID: allocation ID 328 // - fee: transaction fee 329 func WritePoolUnlock(allocID string, fee string) (hash string, nonce int64, err error) { 330 if !sdkInitialized { 331 return "", 0, sdkNotInitialized 332 } 333 334 type unlockRequest struct { 335 AllocationID string `json:"allocation_id"` 336 } 337 338 var req unlockRequest 339 req.AllocationID = allocID 340 341 var sn = transaction.SmartContractTxnData{ 342 Name: transaction.STORAGESC_WRITE_POOL_UNLOCK, 343 InputArgs: &req, 344 } 345 hash, _, nonce, _, err = smartContractTxnValueFeeWithRetry(STORAGE_SCADDRESS, sn, "0", fee) 346 return 347 } 348 349 func smartContractTxn(scAddress string, sn transaction.SmartContractTxnData) ( 350 hash, out string, nonce int64, txn *transaction.Transaction, err error) { 351 return smartContractTxnValue(scAddress, sn, "0") 352 } 353 354 func StorageSmartContractTxn(sn transaction.SmartContractTxnData) ( 355 hash, out string, nonce int64, txn *transaction.Transaction, err error) { 356 357 return storageSmartContractTxnValue(sn, "0") 358 } 359 360 func storageSmartContractTxn(sn transaction.SmartContractTxnData) ( 361 hash, out string, nonce int64, txn *transaction.Transaction, err error) { 362 363 return storageSmartContractTxnValue(sn, "0") 364 } 365 366 func smartContractTxnValue(scAddress string, sn transaction.SmartContractTxnData, value string) ( 367 hash, out string, nonce int64, txn *transaction.Transaction, err error) { 368 369 return smartContractTxnValueFeeWithRetry(scAddress, sn, value, strconv.FormatUint(client.TxnFee(), 10)) 370 } 371 372 func storageSmartContractTxnValue(sn transaction.SmartContractTxnData, value string) ( 373 hash, out string, nonce int64, txn *transaction.Transaction, err error) { 374 375 // Fee is set during sdk initialization. 376 return smartContractTxnValueFeeWithRetry(STORAGE_SCADDRESS, sn, value, strconv.FormatUint(client.TxnFee(), 10)) 377 } 378 379 func smartContractTxnValueFeeWithRetry(scAddress string, sn transaction.SmartContractTxnData, 380 value, fee string) (hash, out string, nonce int64, t *transaction.Transaction, err error) { 381 hash, out, nonce, t, err = smartContractTxnValueFee(scAddress, sn, value, fee) 382 383 if err != nil && strings.Contains(err.Error(), "invalid transaction nonce") { 384 return smartContractTxnValueFee(scAddress, sn, value, fee) 385 } 386 387 return 388 } 389 390 func smartContractTxnValueFee(scAddress string, sn transaction.SmartContractTxnData, 391 value, fee string) (hash, out string, nonce int64, t *transaction.Transaction, err error) { 392 t, err = ExecuteSmartContract(scAddress, sn, value, fee) 393 if err != nil { 394 if t != nil { 395 return "", "", t.TransactionNonce, nil, err 396 } 397 398 return "", "", 0, nil, err 399 } 400 401 return t.Hash, t.TransactionOutput, t.TransactionNonce, t, nil 402 }