github.com/0chain/gosdk@v1.17.11/zcncore/transaction.go (about) 1 //go:build !mobile 2 // +build !mobile 3 4 package zcncore 5 6 import ( 7 "context" 8 "encoding/json" 9 "fmt" 10 "math" 11 "net/http" 12 "sync" 13 "time" 14 15 "github.com/0chain/errors" 16 "github.com/0chain/gosdk/core/block" 17 "github.com/0chain/gosdk/core/common" 18 "github.com/0chain/gosdk/core/encryption" 19 "github.com/0chain/gosdk/core/node" 20 "github.com/0chain/gosdk/core/transaction" 21 "github.com/0chain/gosdk/core/util" 22 "github.com/0chain/gosdk/core/zcncrypto" 23 ) 24 25 // Provider represents the type of provider. 26 type Provider int 27 28 const ( 29 ProviderMiner Provider = iota + 1 30 ProviderSharder 31 ProviderBlobber 32 ProviderValidator 33 ProviderAuthorizer 34 ) 35 36 type TransactionVelocity = float64 37 38 // Transaction velocity vs cost factor 39 // TODO: Pass it to miner to calculate real time factor 40 const ( 41 RegularTransaction TransactionVelocity = 1.0 42 FastTransaction TransactionVelocity = 1.3 43 FasterTransaction TransactionVelocity = 1.6 44 ) 45 46 type ConfirmationStatus int 47 48 const ( 49 Undefined ConfirmationStatus = iota 50 Success 51 52 // ChargeableError is an error that still charges the user for the transaction. 53 ChargeableError 54 ) 55 56 type Miner struct { 57 ID string `json:"id"` 58 N2NHost string `json:"n2n_host"` 59 Host string `json:"host"` 60 Port int `json:"port"` 61 PublicKey string `json:"public_key"` 62 ShortName string `json:"short_name"` 63 BuildTag string `json:"build_tag"` 64 TotalStake int64 `json:"total_stake"` 65 Stat interface{} `json:"stat"` 66 } 67 68 // Node represents a node (miner or sharder) in the network. 69 type Node struct { 70 Miner Miner `json:"simple_miner"` 71 StakePool `json:"stake_pool"` 72 } 73 74 // MinerSCNodes list of nodes registered to the miner smart contract 75 type MinerSCNodes struct { 76 Nodes []Node `json:"Nodes"` 77 } 78 79 type VestingSCConfig struct { 80 MinLock common.Balance `json:"min_lock"` 81 MinDuration time.Duration `json:"min_duration"` 82 MaxDuration time.Duration `json:"max_duration"` 83 MaxDestinations int `json:"max_destinations"` 84 MaxDescriptionLength int `json:"max_description_length"` 85 } 86 87 type DelegatePool struct { 88 Balance int64 `json:"balance"` 89 Reward int64 `json:"reward"` 90 Status int `json:"status"` 91 RoundCreated int64 `json:"round_created"` // used for cool down 92 DelegateID string `json:"delegate_id"` 93 } 94 95 type StakePool struct { 96 Pools map[string]*DelegatePool `json:"pools"` 97 Reward int64 `json:"rewards"` 98 Settings StakePoolSettings `json:"settings"` 99 Minter int `json:"minter"` 100 } 101 102 type stakePoolRequest struct { 103 ProviderType Provider `json:"provider_type,omitempty"` 104 ProviderID string `json:"provider_id,omitempty"` 105 } 106 107 type MinerSCDelegatePoolInfo struct { 108 ID common.Key `json:"id"` 109 Balance common.Balance `json:"balance"` 110 Reward common.Balance `json:"reward"` // uncollected reread 111 RewardPaid common.Balance `json:"reward_paid"` // total reward all time 112 Status string `json:"status"` 113 } 114 115 // MinerSCUserPoolsInfo represents the user stake pools information 116 type MinerSCUserPoolsInfo struct { 117 Pools map[string][]*MinerSCDelegatePoolInfo `json:"pools"` 118 } 119 120 type TransactionCommon interface { 121 // ExecuteSmartContract implements wrapper for smart contract function 122 ExecuteSmartContract(address, methodName string, input interface{}, val uint64, feeOpts ...FeeOption) (*transaction.Transaction, error) 123 // Send implements sending token to a given clientid 124 Send(toClientID string, val uint64, desc string) error 125 126 //RegisterMultiSig registers a group wallet and subwallets with MultisigSC 127 RegisterMultiSig(walletstr, mswallet string) error 128 129 VestingAdd(ar *VestingAddRequest, value uint64) error 130 131 MinerSCLock(providerId string, providerType Provider, lock uint64) error 132 MinerSCUnlock(providerId string, providerType Provider) error 133 MinerSCCollectReward(providerID string, providerType Provider) error 134 MinerSCKill(providerID string, providerType Provider) error 135 136 StorageSCCollectReward(providerID string, providerType Provider) error 137 138 FinalizeAllocation(allocID string) error 139 CancelAllocation(allocID string) error 140 CreateAllocation(car *CreateAllocationRequest, lock uint64) error // 141 CreateReadPool() error 142 ReadPoolLock(allocID string, blobberID string, duration int64, lock uint64) error 143 ReadPoolUnlock() error 144 StakePoolLock(providerId string, providerType Provider, lock uint64) error 145 StakePoolUnlock(providerId string, providerType Provider) error 146 UpdateBlobberSettings(blobber *Blobber) error 147 UpdateValidatorSettings(validator *Validator) error 148 UpdateAllocation(allocID string, sizeDiff int64, expirationDiff int64, lock uint64) error 149 WritePoolLock(allocID string, blobberID string, duration int64, lock uint64) error 150 WritePoolUnlock(allocID string) error 151 152 VestingUpdateConfig(*InputMap) error 153 MinerScUpdateConfig(*InputMap) error 154 MinerScUpdateGlobals(*InputMap) error 155 StorageScUpdateConfig(*InputMap) error 156 AddHardfork(ip *InputMap) (err error) 157 FaucetUpdateConfig(*InputMap) error 158 ZCNSCUpdateGlobalConfig(*InputMap) error 159 160 MinerSCMinerSettings(*MinerSCMinerInfo) error 161 MinerSCSharderSettings(*MinerSCMinerInfo) error 162 MinerSCDeleteMiner(*MinerSCMinerInfo) error 163 MinerSCDeleteSharder(*MinerSCMinerInfo) error 164 165 // ZCNSCUpdateAuthorizerConfig updates authorizer config by ID 166 ZCNSCUpdateAuthorizerConfig(*AuthorizerNode) error 167 // ZCNSCAddAuthorizer adds authorizer 168 ZCNSCAddAuthorizer(*AddAuthorizerPayload) error 169 170 // ZCNSCAuthorizerHealthCheck provides health check for authorizer 171 ZCNSCAuthorizerHealthCheck(*AuthorizerHealthCheckPayload) error 172 173 // GetVerifyConfirmationStatus implements the verification status from sharders 174 GetVerifyConfirmationStatus() ConfirmationStatus 175 176 // ZCNSCDeleteAuthorizer deletes authorizer 177 ZCNSCDeleteAuthorizer(*DeleteAuthorizerPayload) error 178 179 ZCNSCCollectReward(providerID string, providerType Provider) error 180 } 181 182 // compiler time check 183 var ( 184 _ TransactionScheme = (*Transaction)(nil) 185 _ TransactionScheme = (*TransactionWithAuth)(nil) 186 ) 187 188 // TransactionScheme implements few methods for block chain. 189 // 190 // Note: to be buildable on MacOSX all arguments should have names. 191 type TransactionScheme interface { 192 TransactionCommon 193 // SetTransactionCallback implements storing the callback 194 // used to call after the transaction or verification is completed 195 SetTransactionCallback(cb TransactionCallback) error 196 // StoreData implements store the data to blockchain 197 StoreData(data string) error 198 // ExecuteFaucetSCWallet implements the `Faucet Smart contract` for a given wallet 199 ExecuteFaucetSCWallet(walletStr string, methodName string, input []byte) error 200 // GetTransactionHash implements retrieval of hash of the submitted transaction 201 GetTransactionHash() string 202 // SetTransactionHash implements verify a previous transaction status 203 SetTransactionHash(hash string) error 204 // SetTransactionNonce implements method to set the transaction nonce 205 SetTransactionNonce(txnNonce int64) error 206 // Verify implements verify the transaction 207 Verify() error 208 // GetVerifyOutput implements the verification output from sharders 209 GetVerifyOutput() string 210 // GetTransactionError implements error string in case of transaction failure 211 GetTransactionError() string 212 // GetVerifyError implements error string in case of verify failure error 213 GetVerifyError() string 214 // GetTransactionNonce returns nonce 215 GetTransactionNonce() int64 216 217 // Output of transaction. 218 Output() []byte 219 220 // Hash Transaction status regardless of status 221 Hash() string 222 223 // Vesting SC 224 225 VestingTrigger(poolID string) error 226 VestingStop(sr *VestingStopRequest) error 227 VestingUnlock(poolID string) error 228 VestingDelete(poolID string) error 229 230 // Miner SC 231 } 232 233 // PriceRange represents a price range allowed by user to filter blobbers. 234 type PriceRange struct { 235 Min common.Balance `json:"min"` 236 Max common.Balance `json:"max"` 237 } 238 239 // CreateAllocationRequest is information to create allocation. 240 type CreateAllocationRequest struct { 241 DataShards int `json:"data_shards"` 242 ParityShards int `json:"parity_shards"` 243 Size common.Size `json:"size"` 244 Expiration common.Timestamp `json:"expiration_date"` 245 Owner string `json:"owner_id"` 246 OwnerPublicKey string `json:"owner_public_key"` 247 Blobbers []string `json:"blobbers"` 248 ReadPriceRange PriceRange `json:"read_price_range"` 249 WritePriceRange PriceRange `json:"write_price_range"` 250 } 251 252 type StakePoolSettings struct { 253 DelegateWallet *string `json:"delegate_wallet,omitempty"` 254 NumDelegates *int `json:"num_delegates,omitempty"` 255 ServiceCharge *float64 `json:"service_charge,omitempty"` 256 } 257 258 type Terms struct { 259 ReadPrice common.Balance `json:"read_price"` // tokens / GB 260 WritePrice common.Balance `json:"write_price"` // tokens / GB ` 261 MaxOfferDuration time.Duration `json:"max_offer_duration"` 262 } 263 264 // Blobber represents a blobber node. 265 type Blobber struct { 266 // ID is the blobber ID. 267 ID common.Key `json:"id"` 268 // BaseURL is the blobber's base URL used to access the blobber 269 BaseURL string `json:"url"` 270 // Terms of storage service of the blobber (read/write price, max offer duration) 271 Terms Terms `json:"terms"` 272 // Capacity is the total capacity of the blobber 273 Capacity common.Size `json:"capacity"` 274 // Used is the capacity of the blobber used to create allocations 275 Allocated common.Size `json:"allocated"` 276 // LastHealthCheck is the last time the blobber was checked for health 277 LastHealthCheck common.Timestamp `json:"last_health_check"` 278 // StakePoolSettings is the settings of the blobber's stake pool 279 StakePoolSettings StakePoolSettings `json:"stake_pool_settings"` 280 // NotAvailable is true if the blobber is not available 281 NotAvailable bool `json:"not_available"` 282 // IsRestricted is true if the blobber is restricted. 283 // Restricted blobbers needs to be authenticated using AuthTickets in order to be used for allocation creation. 284 // Check Restricted Blobbers documentation for more details. 285 IsRestricted bool `json:"is_restricted"` 286 } 287 288 type Validator struct { 289 ID common.Key `json:"id"` 290 BaseURL string `json:"url"` 291 StakePoolSettings StakePoolSettings `json:"stake_pool_settings"` 292 } 293 294 // AddAuthorizerPayload represents the payload for adding an authorizer. 295 type AddAuthorizerPayload struct { 296 PublicKey string `json:"public_key"` 297 URL string `json:"url"` 298 StakePoolSettings AuthorizerStakePoolSettings `json:"stake_pool_settings"` // Used to initially create stake pool 299 } 300 301 // DeleteAuthorizerPayload represents the payload for deleting an authorizer. 302 type DeleteAuthorizerPayload struct { 303 ID string `json:"id"` // authorizer ID 304 } 305 306 // AuthorizerHealthCheckPayload represents the payload for authorizer health check. 307 type AuthorizerHealthCheckPayload struct { 308 ID string `json:"id"` // authorizer ID 309 } 310 311 // AuthorizerStakePoolSettings represents the settings for an authorizer's stake pool. 312 type AuthorizerStakePoolSettings struct { 313 DelegateWallet string `json:"delegate_wallet"` 314 NumDelegates int `json:"num_delegates"` 315 ServiceCharge float64 `json:"service_charge"` 316 } 317 318 type AuthorizerConfig struct { 319 Fee common.Balance `json:"fee"` 320 } 321 322 // InputMap represents a map of input fields. 323 type InputMap struct { 324 Fields map[string]string `json:"Fields"` 325 } 326 327 func newTransaction(cb TransactionCallback, txnFee uint64, nonce int64) (*Transaction, error) { 328 t := &Transaction{} 329 t.txn = transaction.NewTransactionEntity(_config.wallet.ClientID, _config.chain.ChainID, _config.wallet.ClientKey, nonce) 330 t.txnStatus, t.verifyStatus = StatusUnknown, StatusUnknown 331 t.txnCb = cb 332 t.txn.TransactionNonce = nonce 333 t.txn.TransactionFee = txnFee 334 return t, nil 335 } 336 337 // NewTransaction new generic transaction object for any operation 338 // - cb: callback for transaction state 339 // - txnFee: Transaction fees (in SAS tokens) 340 // - nonce: latest nonce of current wallet. please set it with 0 if you don't know the latest value 341 func NewTransaction(cb TransactionCallback, txnFee uint64, nonce int64) (TransactionScheme, error) { 342 err := CheckConfig() 343 if err != nil { 344 return nil, err 345 } 346 if _config.isSplitWallet { 347 logging.Info("New transaction interface with auth") 348 return newTransactionWithAuth(cb, txnFee, nonce) 349 } 350 351 logging.Info("New transaction interface") 352 return newTransaction(cb, txnFee, nonce) 353 } 354 355 func (t *Transaction) createSmartContractTxn(address, methodName string, input interface{}, value uint64, opts ...FeeOption) error { 356 sn := transaction.SmartContractTxnData{Name: methodName, InputArgs: input} 357 snBytes, err := json.Marshal(sn) 358 if err != nil { 359 return errors.Wrap(err, "create smart contract failed due to invalid data") 360 } 361 362 t.txn.TransactionType = transaction.TxnTypeSmartContract 363 t.txn.ToClientID = address 364 t.txn.TransactionData = string(snBytes) 365 t.txn.Value = value 366 367 if t.txn.TransactionFee > 0 { 368 return nil 369 } 370 371 tf := &TxnFeeOption{} 372 for _, opt := range opts { 373 opt(tf) 374 } 375 376 if tf.noEstimateFee { 377 return nil 378 } 379 380 // TODO: check if transaction is exempt to avoid unnecessary fee estimation 381 minFee, err := transaction.EstimateFee(t.txn, _config.chain.Miners, 0.2) 382 if err != nil { 383 return err 384 } 385 386 t.txn.TransactionFee = minFee 387 388 return nil 389 } 390 391 func (t *Transaction) createFaucetSCWallet(walletStr string, methodName string, input []byte) (*zcncrypto.Wallet, error) { 392 w, err := getWallet(walletStr) 393 if err != nil { 394 fmt.Printf("Error while parsing the wallet. %v\n", err) 395 return nil, err 396 } 397 err = t.createSmartContractTxn(FaucetSmartContractAddress, methodName, input, 0) 398 if err != nil { 399 return nil, err 400 } 401 return w, nil 402 } 403 404 func (t *Transaction) ExecuteSmartContract(address, methodName string, input interface{}, val uint64, opts ...FeeOption) (*transaction.Transaction, error) { 405 err := t.createSmartContractTxn(address, methodName, input, val, opts...) 406 if err != nil { 407 return nil, err 408 } 409 go func() { 410 t.setNonceAndSubmit() 411 }() 412 return t.txn, nil 413 } 414 415 func (t *Transaction) Send(toClientID string, val uint64, desc string) error { 416 txnData, err := json.Marshal(transaction.SmartContractTxnData{Name: "transfer", InputArgs: SendTxnData{Note: desc}}) 417 if err != nil { 418 return errors.New("", "Could not serialize description to transaction_data") 419 } 420 421 t.txn.TransactionType = transaction.TxnTypeSend 422 t.txn.ToClientID = toClientID 423 t.txn.Value = val 424 t.txn.TransactionData = string(txnData) 425 if t.txn.TransactionFee == 0 { 426 fee, err := transaction.EstimateFee(t.txn, _config.chain.Miners, 0.2) 427 if err != nil { 428 return err 429 } 430 t.txn.TransactionFee = fee 431 } 432 433 go func() { 434 t.setNonceAndSubmit() 435 }() 436 return nil 437 } 438 439 func (t *Transaction) SendWithSignatureHash(toClientID string, val uint64, desc string, sig string, CreationDate int64, hash string) error { 440 txnData, err := json.Marshal(SendTxnData{Note: desc}) 441 if err != nil { 442 return errors.New("", "Could not serialize description to transaction_data") 443 } 444 t.txn.TransactionType = transaction.TxnTypeSend 445 t.txn.ToClientID = toClientID 446 t.txn.Value = val 447 t.txn.Hash = hash 448 t.txn.TransactionData = string(txnData) 449 t.txn.Signature = sig 450 t.txn.CreationDate = CreationDate 451 if t.txn.TransactionFee == 0 { 452 fee, err := transaction.EstimateFee(t.txn, _config.chain.Miners, 0.2) 453 if err != nil { 454 return err 455 } 456 t.txn.TransactionFee = fee 457 } 458 459 go func() { 460 t.setNonceAndSubmit() 461 }() 462 return nil 463 } 464 465 type VestingDest struct { 466 ID string `json:"id"` // destination ID 467 Amount common.Balance `json:"amount"` // amount to vest for the destination 468 } 469 470 type VestingAddRequest struct { 471 Description string `json:"description"` // allow empty 472 StartTime common.Timestamp `json:"start_time"` // 473 Duration time.Duration `json:"duration"` // 474 Destinations []*VestingDest `json:"destinations"` // 475 } 476 477 func (t *Transaction) VestingAdd(ar *VestingAddRequest, value uint64) ( 478 err error) { 479 480 err = t.createSmartContractTxn(VestingSmartContractAddress, 481 transaction.VESTING_ADD, ar, value) 482 if err != nil { 483 logging.Error(err) 484 return 485 } 486 go func() { t.setNonceAndSubmit() }() 487 return 488 } 489 490 func (t *Transaction) VestingStop(sr *VestingStopRequest) (err error) { 491 err = t.createSmartContractTxn(VestingSmartContractAddress, 492 transaction.VESTING_STOP, sr, 0) 493 if err != nil { 494 logging.Error(err) 495 return 496 } 497 go func() { t.setNonceAndSubmit() }() 498 return 499 } 500 501 func (t *Transaction) vestingPoolTxn(function string, poolID string, 502 value uint64) error { 503 504 return t.createSmartContractTxn(VestingSmartContractAddress, 505 function, vestingRequest{PoolID: common.Key(poolID)}, value) 506 } 507 508 func (t *Transaction) VestingTrigger(poolID string) (err error) { 509 510 err = t.vestingPoolTxn(transaction.VESTING_TRIGGER, poolID, 0) 511 if err != nil { 512 logging.Error(err) 513 return 514 } 515 go func() { t.setNonceAndSubmit() }() 516 return 517 } 518 519 func (t *Transaction) VestingUnlock(poolID string) (err error) { 520 err = t.vestingPoolTxn(transaction.VESTING_UNLOCK, poolID, 0) 521 if err != nil { 522 logging.Error(err) 523 return 524 } 525 go func() { t.setNonceAndSubmit() }() 526 return 527 } 528 529 func (t *Transaction) VestingDelete(poolID string) (err error) { 530 err = t.vestingPoolTxn(transaction.VESTING_DELETE, poolID, 0) 531 if err != nil { 532 logging.Error(err) 533 return 534 } 535 go func() { t.setNonceAndSubmit() }() 536 return 537 } 538 539 func (t *Transaction) MinerSCLock(providerId string, providerType Provider, lock uint64) error { 540 if lock > math.MaxInt64 { 541 return errors.New("invalid_lock", "int64 overflow on lock value") 542 } 543 544 pr := &stakePoolRequest{ 545 ProviderID: providerId, 546 ProviderType: providerType, 547 } 548 err := t.createSmartContractTxn(MinerSmartContractAddress, 549 transaction.MINERSC_LOCK, pr, lock) 550 if err != nil { 551 logging.Error(err) 552 return err 553 } 554 go func() { t.setNonceAndSubmit() }() 555 return err 556 } 557 func (t *Transaction) MinerSCUnlock(providerId string, providerType Provider) error { 558 pr := &stakePoolRequest{ 559 ProviderID: providerId, 560 ProviderType: providerType, 561 } 562 err := t.createSmartContractTxn(MinerSmartContractAddress, 563 transaction.MINERSC_UNLOCK, pr, 0) 564 if err != nil { 565 logging.Error(err) 566 return err 567 } 568 go func() { t.setNonceAndSubmit() }() 569 return err 570 } 571 572 func (t *Transaction) MinerSCCollectReward(providerId string, providerType Provider) error { 573 pr := &scCollectReward{ 574 ProviderId: providerId, 575 ProviderType: int(providerType), 576 } 577 err := t.createSmartContractTxn(MinerSmartContractAddress, 578 transaction.MINERSC_COLLECT_REWARD, pr, 0) 579 if err != nil { 580 logging.Error(err) 581 return err 582 } 583 go func() { t.setNonceAndSubmit() }() 584 return err 585 } 586 587 func (t *Transaction) MinerSCKill(providerId string, providerType Provider) error { 588 pr := &scCollectReward{ 589 ProviderId: providerId, 590 ProviderType: int(providerType), 591 } 592 var name string 593 switch providerType { 594 case ProviderMiner: 595 name = transaction.MINERSC_KILL_MINER 596 case ProviderSharder: 597 name = transaction.MINERSC_KILL_SHARDER 598 default: 599 return fmt.Errorf("kill provider type %v not implimented", providerType) 600 } 601 602 err := t.createSmartContractTxn(MinerSmartContractAddress, name, pr, 0) 603 if err != nil { 604 logging.Error(err) 605 return err 606 } 607 go func() { t.setNonceAndSubmit() }() 608 return err 609 } 610 611 func (t *Transaction) StorageSCCollectReward(providerId string, providerType Provider) error { 612 pr := &scCollectReward{ 613 ProviderId: providerId, 614 ProviderType: int(providerType), 615 } 616 err := t.createSmartContractTxn(StorageSmartContractAddress, 617 transaction.STORAGESC_COLLECT_REWARD, pr, 0) 618 if err != nil { 619 logging.Error(err) 620 return err 621 } 622 go t.setNonceAndSubmit() 623 return err 624 } 625 626 // FinalizeAllocation transaction. 627 func (t *Transaction) FinalizeAllocation(allocID string) ( 628 err error) { 629 630 type finiRequest struct { 631 AllocationID string `json:"allocation_id"` 632 } 633 err = t.createSmartContractTxn(StorageSmartContractAddress, 634 transaction.STORAGESC_FINALIZE_ALLOCATION, &finiRequest{ 635 AllocationID: allocID, 636 }, 0) 637 if err != nil { 638 logging.Error(err) 639 return 640 } 641 642 go func() { t.setNonceAndSubmit() }() 643 return 644 } 645 646 // CancelAllocation transaction. 647 func (t *Transaction) CancelAllocation(allocID string) ( 648 err error) { 649 650 type cancelRequest struct { 651 AllocationID string `json:"allocation_id"` 652 } 653 err = t.createSmartContractTxn(StorageSmartContractAddress, 654 transaction.STORAGESC_CANCEL_ALLOCATION, &cancelRequest{ 655 AllocationID: allocID, 656 }, 0) 657 if err != nil { 658 logging.Error(err) 659 return 660 } 661 go func() { t.setNonceAndSubmit() }() 662 return 663 } 664 665 // CreateAllocation transaction. 666 func (t *Transaction) CreateAllocation(car *CreateAllocationRequest, 667 lock uint64) (err error) { 668 err = t.createSmartContractTxn(StorageSmartContractAddress, 669 transaction.STORAGESC_CREATE_ALLOCATION, car, lock) 670 if err != nil { 671 logging.Error(err) 672 return 673 } 674 675 go func() { t.setNonceAndSubmit() }() 676 return 677 } 678 679 // CreateReadPool for current user. 680 func (t *Transaction) CreateReadPool() (err error) { 681 err = t.createSmartContractTxn(StorageSmartContractAddress, 682 transaction.STORAGESC_CREATE_READ_POOL, nil, 0) 683 if err != nil { 684 logging.Error(err) 685 return 686 } 687 go func() { t.setNonceAndSubmit() }() 688 return 689 } 690 691 // ReadPoolLock locks tokens for current user and given allocation, using given 692 // duration. If blobberID is not empty, then tokens will be locked for given 693 // allocation->blobber only. 694 func (t *Transaction) ReadPoolLock(allocID, blobberID string, duration int64, lock uint64) (err error) { 695 if lock > math.MaxInt64 { 696 return errors.New("invalid_lock", "int64 overflow on lock value") 697 } 698 699 type lockRequest struct { 700 Duration time.Duration `json:"duration"` 701 AllocationID string `json:"allocation_id"` 702 BlobberID string `json:"blobber_id,omitempty"` 703 } 704 705 var lr lockRequest 706 lr.Duration = time.Duration(duration) 707 lr.AllocationID = allocID 708 lr.BlobberID = blobberID 709 710 err = t.createSmartContractTxn(StorageSmartContractAddress, 711 transaction.STORAGESC_READ_POOL_LOCK, &lr, lock) 712 if err != nil { 713 logging.Error(err) 714 return 715 } 716 go func() { t.setNonceAndSubmit() }() 717 return 718 } 719 720 // ReadPoolUnlock for current user and given pool. 721 func (t *Transaction) ReadPoolUnlock() (err error) { 722 err = t.createSmartContractTxn(StorageSmartContractAddress, 723 transaction.STORAGESC_READ_POOL_UNLOCK, nil, 0) 724 if err != nil { 725 logging.Error(err) 726 return 727 } 728 go func() { t.setNonceAndSubmit() }() 729 return 730 } 731 732 // StakePoolLock used to lock tokens in a stake pool of a blobber. 733 func (t *Transaction) StakePoolLock(providerId string, providerType Provider, lock uint64) error { 734 735 if lock > math.MaxInt64 { 736 return errors.New("invalid_lock", "int64 overflow on lock value") 737 } 738 739 type stakePoolRequest struct { 740 ProviderType Provider `json:"provider_type,omitempty"` 741 ProviderID string `json:"provider_id,omitempty"` 742 } 743 744 spr := stakePoolRequest{ 745 ProviderType: providerType, 746 ProviderID: providerId, 747 } 748 749 err := t.createSmartContractTxn(StorageSmartContractAddress, 750 transaction.STORAGESC_STAKE_POOL_LOCK, &spr, lock) 751 if err != nil { 752 logging.Error(err) 753 return err 754 } 755 go func() { t.setNonceAndSubmit() }() 756 return nil 757 } 758 759 // StakePoolUnlock by blobberID and poolID. 760 func (t *Transaction) StakePoolUnlock(providerId string, providerType Provider) error { 761 762 type stakePoolRequest struct { 763 ProviderType Provider `json:"provider_type,omitempty"` 764 ProviderID string `json:"provider_id,omitempty"` 765 } 766 767 spr := stakePoolRequest{ 768 ProviderType: providerType, 769 ProviderID: providerId, 770 } 771 772 err := t.createSmartContractTxn(StorageSmartContractAddress, transaction.STORAGESC_STAKE_POOL_UNLOCK, &spr, 0) 773 if err != nil { 774 logging.Error(err) 775 return err 776 } 777 go func() { t.setNonceAndSubmit() }() 778 return nil 779 } 780 781 // UpdateBlobberSettings update settings of a blobber. 782 func (t *Transaction) UpdateBlobberSettings(b *Blobber) (err error) { 783 784 err = t.createSmartContractTxn(StorageSmartContractAddress, 785 transaction.STORAGESC_UPDATE_BLOBBER_SETTINGS, b, 0) 786 if err != nil { 787 logging.Error(err) 788 return 789 } 790 go func() { t.setNonceAndSubmit() }() 791 return 792 } 793 794 // UpdateAllocation transaction. 795 func (t *Transaction) UpdateAllocation(allocID string, sizeDiff int64, 796 expirationDiff int64, lock uint64) (err error) { 797 798 if lock > math.MaxInt64 { 799 return errors.New("invalid_lock", "int64 overflow on lock value") 800 } 801 802 type updateAllocationRequest struct { 803 ID string `json:"id"` // allocation id 804 Size int64 `json:"size"` // difference 805 Expiration int64 `json:"expiration_date"` // difference 806 } 807 808 var uar updateAllocationRequest 809 uar.ID = allocID 810 uar.Size = sizeDiff 811 uar.Expiration = expirationDiff 812 813 err = t.createSmartContractTxn(StorageSmartContractAddress, 814 transaction.STORAGESC_UPDATE_ALLOCATION, &uar, lock) 815 if err != nil { 816 logging.Error(err) 817 return 818 } 819 go func() { t.setNonceAndSubmit() }() 820 return 821 } 822 823 // WritePoolLock locks tokens for current user and given allocation, using given 824 // duration. If blobberID is not empty, then tokens will be locked for given 825 // allocation->blobber only. 826 func (t *Transaction) WritePoolLock(allocID, blobberID string, duration int64, 827 lock uint64) (err error) { 828 829 if lock > math.MaxInt64 { 830 return errors.New("invalid_lock", "int64 overflow on lock value") 831 } 832 833 type lockRequest struct { 834 Duration time.Duration `json:"duration"` 835 AllocationID string `json:"allocation_id"` 836 BlobberID string `json:"blobber_id,omitempty"` 837 } 838 839 var lr lockRequest 840 lr.Duration = time.Duration(duration) 841 lr.AllocationID = allocID 842 lr.BlobberID = blobberID 843 844 err = t.createSmartContractTxn(StorageSmartContractAddress, 845 transaction.STORAGESC_WRITE_POOL_LOCK, &lr, lock) 846 if err != nil { 847 logging.Error(err) 848 return 849 } 850 go func() { t.setNonceAndSubmit() }() 851 return 852 } 853 854 // WritePoolUnlock for current user and given pool. 855 func (t *Transaction) WritePoolUnlock(allocID string) ( 856 err error) { 857 858 var ur = struct { 859 AllocationID string `json:"allocation_id"` 860 }{ 861 AllocationID: allocID, 862 } 863 864 err = t.createSmartContractTxn(StorageSmartContractAddress, 865 transaction.STORAGESC_WRITE_POOL_UNLOCK, &ur, 0) 866 if err != nil { 867 logging.Error(err) 868 return 869 } 870 go func() { t.setNonceAndSubmit() }() 871 return 872 } 873 874 func (t *Transaction) VestingUpdateConfig(vscc *InputMap) (err error) { 875 876 err = t.createSmartContractTxn(VestingSmartContractAddress, 877 transaction.VESTING_UPDATE_SETTINGS, vscc, 0) 878 if err != nil { 879 logging.Error(err) 880 return 881 } 882 go func() { t.setNonceAndSubmit() }() 883 return 884 } 885 886 // faucet smart contract 887 888 func (t *Transaction) FaucetUpdateConfig(ip *InputMap) (err error) { 889 890 err = t.createSmartContractTxn(FaucetSmartContractAddress, 891 transaction.FAUCETSC_UPDATE_SETTINGS, ip, 0) 892 if err != nil { 893 logging.Error(err) 894 return 895 } 896 go func() { t.setNonceAndSubmit() }() 897 return 898 } 899 900 // 901 // miner SC 902 // 903 904 func (t *Transaction) MinerScUpdateConfig(ip *InputMap) (err error) { 905 err = t.createSmartContractTxn(MinerSmartContractAddress, 906 transaction.MINERSC_UPDATE_SETTINGS, ip, 0) 907 if err != nil { 908 logging.Error(err) 909 return 910 } 911 go func() { t.setNonceAndSubmit() }() 912 return 913 } 914 915 func (t *Transaction) MinerScUpdateGlobals(ip *InputMap) (err error) { 916 err = t.createSmartContractTxn(MinerSmartContractAddress, 917 transaction.MINERSC_UPDATE_GLOBALS, ip, 0) 918 if err != nil { 919 logging.Error(err) 920 return 921 } 922 go func() { t.setNonceAndSubmit() }() 923 return 924 } 925 926 func (t *Transaction) StorageScUpdateConfig(ip *InputMap) (err error) { 927 err = t.createSmartContractTxn(StorageSmartContractAddress, 928 transaction.STORAGESC_UPDATE_SETTINGS, ip, 0) 929 if err != nil { 930 logging.Error(err) 931 return 932 } 933 go func() { t.setNonceAndSubmit() }() 934 return 935 } 936 func (t *Transaction) AddHardfork(ip *InputMap) (err error) { 937 err = t.createSmartContractTxn(MinerSmartContractAddress, 938 transaction.ADD_HARDFORK, ip, 0) 939 if err != nil { 940 logging.Error(err) 941 return 942 } 943 go func() { t.setNonceAndSubmit() }() 944 return 945 } 946 947 func (t *Transaction) ZCNSCUpdateGlobalConfig(ip *InputMap) (err error) { 948 err = t.createSmartContractTxn(ZCNSCSmartContractAddress, transaction.ZCNSC_UPDATE_GLOBAL_CONFIG, ip, 0) 949 if err != nil { 950 logging.Error(err) 951 return 952 } 953 go t.setNonceAndSubmit() 954 return 955 } 956 957 func (t *Transaction) GetVerifyConfirmationStatus() ConfirmationStatus { 958 return ConfirmationStatus(t.verifyConfirmationStatus) 959 } 960 961 // RegisterMultiSig register a multisig wallet with the SC. 962 func (t *Transaction) RegisterMultiSig(walletstr string, mswallet string) error { 963 w, err := GetWallet(walletstr) 964 if err != nil { 965 fmt.Printf("Error while parsing the wallet. %v\n", err) 966 return err 967 } 968 969 msw, err := GetMultisigPayload(mswallet) 970 if err != nil { 971 fmt.Printf("\nError in registering. %v\n", err) 972 return err 973 } 974 sn := transaction.SmartContractTxnData{Name: MultiSigRegisterFuncName, InputArgs: msw} 975 snBytes, err := json.Marshal(sn) 976 if err != nil { 977 return errors.Wrap(err, "execute multisig register failed due to invalid data.") 978 } 979 go func() { 980 t.txn.TransactionType = transaction.TxnTypeSmartContract 981 t.txn.ToClientID = MultiSigSmartContractAddress 982 t.txn.TransactionData = string(snBytes) 983 t.txn.Value = 0 984 nonce := t.txn.TransactionNonce 985 if nonce < 1 { 986 nonce = node.Cache.GetNextNonce(t.txn.ClientID) 987 } else { 988 node.Cache.Set(t.txn.ClientID, nonce) 989 } 990 t.txn.TransactionNonce = nonce 991 992 if t.txn.TransactionFee == 0 { 993 fee, err := transaction.EstimateFee(t.txn, _config.chain.Miners, 0.2) 994 if err != nil { 995 return 996 } 997 t.txn.TransactionFee = fee 998 } 999 1000 err = t.txn.ComputeHashAndSignWithWallet(signWithWallet, w) 1001 if err != nil { 1002 return 1003 } 1004 t.submitTxn() 1005 }() 1006 return nil 1007 } 1008 1009 // NewMSTransaction new transaction object for multisig operation 1010 func NewMSTransaction(walletstr string, cb TransactionCallback) (*Transaction, error) { 1011 w, err := GetWallet(walletstr) 1012 if err != nil { 1013 fmt.Printf("Error while parsing the wallet. %v", err) 1014 return nil, err 1015 } 1016 t := &Transaction{} 1017 t.txn = transaction.NewTransactionEntity(w.ClientID, _config.chain.ChainID, w.ClientKey, w.Nonce) 1018 t.txnStatus, t.verifyStatus = StatusUnknown, StatusUnknown 1019 t.txnCb = cb 1020 return t, nil 1021 } 1022 1023 // RegisterVote register a multisig wallet with the SC. 1024 func (t *Transaction) RegisterVote(signerwalletstr string, msvstr string) error { 1025 1026 w, err := GetWallet(signerwalletstr) 1027 if err != nil { 1028 fmt.Printf("Error while parsing the wallet. %v", err) 1029 return err 1030 } 1031 1032 msv, err := GetMultisigVotePayload(msvstr) 1033 1034 if err != nil { 1035 fmt.Printf("\nError in voting. %v\n", err) 1036 return err 1037 } 1038 sn := transaction.SmartContractTxnData{Name: MultiSigVoteFuncName, InputArgs: msv} 1039 snBytes, err := json.Marshal(sn) 1040 if err != nil { 1041 return errors.Wrap(err, "execute multisig vote failed due to invalid data.") 1042 } 1043 go func() { 1044 t.txn.TransactionType = transaction.TxnTypeSmartContract 1045 t.txn.ToClientID = MultiSigSmartContractAddress 1046 t.txn.TransactionData = string(snBytes) 1047 t.txn.Value = 0 1048 nonce := t.txn.TransactionNonce 1049 if nonce < 1 { 1050 nonce = node.Cache.GetNextNonce(t.txn.ClientID) 1051 } else { 1052 node.Cache.Set(t.txn.ClientID, nonce) 1053 } 1054 t.txn.TransactionNonce = nonce 1055 1056 if t.txn.TransactionFee == 0 { 1057 fee, err := transaction.EstimateFee(t.txn, _config.chain.Miners, 0.2) 1058 if err != nil { 1059 return 1060 } 1061 t.txn.TransactionFee = fee 1062 } 1063 1064 err = t.txn.ComputeHashAndSignWithWallet(signWithWallet, w) 1065 if err != nil { 1066 return 1067 } 1068 t.submitTxn() 1069 }() 1070 return nil 1071 } 1072 1073 type MinerSCDelegatePool struct { 1074 Settings StakePoolSettings `json:"settings"` 1075 } 1076 1077 // SimpleMiner represents a node in the network, miner or sharder. 1078 type SimpleMiner struct { 1079 ID string `json:"id"` 1080 } 1081 1082 // MinerSCMinerInfo interface for miner/sharder info functions on miner smart contract. 1083 type MinerSCMinerInfo struct { 1084 SimpleMiner `json:"simple_miner"` 1085 MinerSCDelegatePool `json:"stake_pool"` 1086 } 1087 1088 func (t *Transaction) MinerSCMinerSettings(info *MinerSCMinerInfo) (err error) { 1089 err = t.createSmartContractTxn(MinerSmartContractAddress, 1090 transaction.MINERSC_MINER_SETTINGS, info, 0) 1091 if err != nil { 1092 logging.Error(err) 1093 return 1094 } 1095 go func() { t.setNonceAndSubmit() }() 1096 return 1097 } 1098 1099 func (t *Transaction) MinerSCSharderSettings(info *MinerSCMinerInfo) (err error) { 1100 err = t.createSmartContractTxn(MinerSmartContractAddress, 1101 transaction.MINERSC_SHARDER_SETTINGS, info, 0) 1102 if err != nil { 1103 logging.Error(err) 1104 return 1105 } 1106 go func() { t.setNonceAndSubmit() }() 1107 return 1108 } 1109 1110 func (t *Transaction) MinerSCDeleteMiner(info *MinerSCMinerInfo) (err error) { 1111 err = t.createSmartContractTxn(MinerSmartContractAddress, 1112 transaction.MINERSC_MINER_DELETE, info, 0) 1113 if err != nil { 1114 logging.Error(err) 1115 return 1116 } 1117 go func() { t.setNonceAndSubmit() }() 1118 return 1119 } 1120 1121 func (t *Transaction) MinerSCDeleteSharder(info *MinerSCMinerInfo) (err error) { 1122 err = t.createSmartContractTxn(MinerSmartContractAddress, 1123 transaction.MINERSC_SHARDER_DELETE, info, 0) 1124 if err != nil { 1125 logging.Error(err) 1126 return 1127 } 1128 go func() { t.setNonceAndSubmit() }() 1129 return 1130 } 1131 1132 // AuthorizerNode represents an authorizer node in the network 1133 type AuthorizerNode struct { 1134 ID string `json:"id"` 1135 URL string `json:"url"` 1136 Config *AuthorizerConfig `json:"config"` 1137 } 1138 1139 func (t *Transaction) ZCNSCUpdateAuthorizerConfig(ip *AuthorizerNode) (err error) { 1140 err = t.createSmartContractTxn(ZCNSCSmartContractAddress, transaction.ZCNSC_UPDATE_AUTHORIZER_CONFIG, ip, 0) 1141 if err != nil { 1142 logging.Error(err) 1143 return 1144 } 1145 go t.setNonceAndSubmit() 1146 return 1147 } 1148 1149 func (t *Transaction) Verify() error { 1150 if t.txnHash == "" && t.txnStatus == StatusUnknown { 1151 return errors.New("", "invalid transaction. cannot be verified.") 1152 } 1153 if t.txnHash == "" && t.txnStatus == StatusSuccess { 1154 h := t.GetTransactionHash() 1155 if h == "" { 1156 node.Cache.Evict(t.txn.ClientID) 1157 return errors.New("", "invalid transaction. cannot be verified.") 1158 } 1159 } 1160 // If transaction is verify only start from current time 1161 if t.txn.CreationDate == 0 { 1162 t.txn.CreationDate = int64(common.Now()) 1163 } 1164 1165 tq, err := NewTransactionQuery(Sharders.Healthy(), _config.chain.Miners) 1166 if err != nil { 1167 logging.Error(err) 1168 return err 1169 } 1170 1171 go func() { 1172 1173 for { 1174 1175 tq.Reset() 1176 // Get transaction confirmationBlock from a random sharder 1177 confirmBlockHeader, confirmationBlock, lfbBlockHeader, err := tq.getFastConfirmation(context.TODO(), t.txnHash) 1178 if err != nil { 1179 now := int64(common.Now()) 1180 1181 // maybe it is a network or server error 1182 if lfbBlockHeader == nil { 1183 logging.Info(err, " now: ", now) 1184 } else { 1185 logging.Info(err, " now: ", now, ", LFB creation time:", lfbBlockHeader.CreationDate) 1186 } 1187 1188 // transaction is done or expired. it means random sharder might be outdated, try to query it from s/S sharders to confirm it 1189 if util.MaxInt64(lfbBlockHeader.getCreationDate(now), now) >= (t.txn.CreationDate + int64(defaultTxnExpirationSeconds)) { 1190 logging.Info("falling back to ", getMinShardersVerify(), " of ", len(_config.chain.Sharders), " Sharders") 1191 confirmBlockHeader, confirmationBlock, lfbBlockHeader, err = tq.getConsensusConfirmation(context.TODO(), getMinShardersVerify(), t.txnHash) 1192 } 1193 1194 // txn not found in fast confirmation/consensus confirmation 1195 if err != nil { 1196 1197 if lfbBlockHeader == nil { 1198 // no any valid lfb on all sharders. maybe they are network/server errors. try it again 1199 continue 1200 } 1201 1202 // it is expired 1203 if t.isTransactionExpired(lfbBlockHeader.getCreationDate(now), now) { 1204 t.completeVerify(StatusError, "", errors.New("", `{"error": "verify transaction failed"}`)) 1205 return 1206 } 1207 continue 1208 } 1209 } 1210 1211 valid := validateChain(confirmBlockHeader) 1212 if valid { 1213 output, err := json.Marshal(confirmationBlock) 1214 if err != nil { 1215 t.completeVerify(StatusError, "", errors.New("", `{"error": "transaction confirmation json marshal error"`)) 1216 return 1217 } 1218 confJson := confirmationBlock["confirmation"] 1219 1220 var conf map[string]json.RawMessage 1221 if err := json.Unmarshal(confJson, &conf); err != nil { 1222 return 1223 } 1224 txnJson := conf["txn"] 1225 1226 tt := transaction.Transaction{} 1227 if err := json.Unmarshal(txnJson, &tt); err != nil { 1228 return 1229 } 1230 1231 *t.txn = tt 1232 txStatus := tt.Status 1233 1234 switch txStatus { 1235 case 1: 1236 t.completeVerifyWithConStatus(StatusSuccess, int(Success), string(output), nil) 1237 case 2: 1238 t.completeVerifyWithConStatus(StatusSuccess, int(ChargeableError), tt.TransactionOutput, nil) 1239 default: 1240 t.completeVerify(StatusError, string(output), nil) 1241 } 1242 return 1243 } 1244 } 1245 }() 1246 return nil 1247 } 1248 1249 // ConvertToValue converts ZCN tokens to SAS tokens 1250 // # Inputs 1251 // - token: ZCN tokens 1252 func ConvertToValue(token float64) uint64 { 1253 return uint64(token * common.TokenUnit) 1254 } 1255 1256 func GetLatestFinalized(ctx context.Context, numSharders int) (b *block.Header, err error) { 1257 var result = make(chan *util.GetResponse, numSharders) 1258 defer close(result) 1259 1260 numSharders = len(Sharders.Healthy()) // overwrite, use all 1261 Sharders.QueryFromShardersContext(ctx, numSharders, GET_LATEST_FINALIZED, result) 1262 1263 var ( 1264 maxConsensus int 1265 roundConsensus = make(map[string]int) 1266 ) 1267 1268 for i := 0; i < numSharders; i++ { 1269 var rsp = <-result 1270 if rsp == nil { 1271 logging.Error("nil response") 1272 continue 1273 } 1274 1275 logging.Debug(rsp.Url, rsp.Status) 1276 1277 if rsp.StatusCode != http.StatusOK { 1278 logging.Error(rsp.Body) 1279 continue 1280 } 1281 1282 if err = json.Unmarshal([]byte(rsp.Body), &b); err != nil { 1283 logging.Error("block parse error: ", err) 1284 err = nil 1285 continue 1286 } 1287 1288 var h = encryption.FastHash([]byte(b.Hash)) 1289 if roundConsensus[h]++; roundConsensus[h] > maxConsensus { 1290 maxConsensus = roundConsensus[h] 1291 } 1292 } 1293 1294 if maxConsensus == 0 { 1295 return nil, errors.New("", "block info not found") 1296 } 1297 1298 return 1299 } 1300 1301 // GetLatestFinalizedMagicBlock gets latest finalized magic block 1302 // - numSharders: number of sharders 1303 // - timeout: request timeout 1304 func GetLatestFinalizedMagicBlock(ctx context.Context, numSharders int) (m *block.MagicBlock, err error) { 1305 var result = make(chan *util.GetResponse, numSharders) 1306 defer close(result) 1307 1308 numSharders = len(Sharders.Healthy()) // overwrite, use all 1309 Sharders.QueryFromShardersContext(ctx, numSharders, GET_LATEST_FINALIZED_MAGIC_BLOCK, result) 1310 1311 var ( 1312 maxConsensus int 1313 roundConsensus = make(map[string]int) 1314 ) 1315 1316 type respObj struct { 1317 MagicBlock *block.MagicBlock `json:"magic_block"` 1318 } 1319 1320 for i := 0; i < numSharders; i++ { 1321 var rsp = <-result 1322 if rsp == nil { 1323 logging.Error("nil response") 1324 continue 1325 } 1326 1327 logging.Debug(rsp.Url, rsp.Status) 1328 1329 if rsp.StatusCode != http.StatusOK { 1330 logging.Error(rsp.Body) 1331 continue 1332 } 1333 1334 var respo respObj 1335 if err = json.Unmarshal([]byte(rsp.Body), &respo); err != nil { 1336 logging.Error(" magic block parse error: ", err) 1337 err = nil 1338 continue 1339 } 1340 1341 m = respo.MagicBlock 1342 var h = encryption.FastHash([]byte(respo.MagicBlock.Hash)) 1343 if roundConsensus[h]++; roundConsensus[h] > maxConsensus { 1344 maxConsensus = roundConsensus[h] 1345 } 1346 } 1347 1348 if maxConsensus == 0 { 1349 return nil, errors.New("", "magic block info not found") 1350 } 1351 1352 return 1353 } 1354 1355 func GetChainStats(ctx context.Context) (b *block.ChainStats, err error) { 1356 var result = make(chan *util.GetResponse, 1) 1357 defer close(result) 1358 1359 var numSharders = len(Sharders.Healthy()) // overwrite, use all 1360 Sharders.QueryFromShardersContext(ctx, numSharders, GET_CHAIN_STATS, result) 1361 var rsp *util.GetResponse 1362 for i := 0; i < numSharders; i++ { 1363 var x = <-result 1364 if x == nil { 1365 logging.Error("nil response") 1366 continue 1367 } 1368 if x.StatusCode != http.StatusOK { 1369 continue 1370 } 1371 rsp = x 1372 } 1373 1374 if rsp == nil { 1375 return nil, errors.New("http_request_failed", "Request failed with status not 200") 1376 } 1377 1378 if err = json.Unmarshal([]byte(rsp.Body), &b); err != nil { 1379 return nil, err 1380 } 1381 return 1382 } 1383 1384 func GetFeeStats(ctx context.Context) (b *block.FeeStats, err error) { 1385 1386 var numMiners = 4 1387 1388 if numMiners > len(_config.chain.Miners) { 1389 numMiners = len(_config.chain.Miners) 1390 } 1391 1392 var result = make(chan *util.GetResponse, numMiners) 1393 1394 queryFromMinersContext(ctx, numMiners, GET_FEE_STATS, result) 1395 var rsp *util.GetResponse 1396 1397 loop: 1398 for i := 0; i < numMiners; i++ { 1399 select { 1400 case x := <-result: 1401 if x.StatusCode != http.StatusOK { 1402 continue 1403 } 1404 rsp = x 1405 if rsp != nil { 1406 break loop 1407 } 1408 case <-ctx.Done(): 1409 err = ctx.Err() 1410 return nil, err 1411 } 1412 } 1413 if rsp == nil { 1414 return nil, errors.New("http_request_failed", "Request failed with status not 200") 1415 } 1416 if err = json.Unmarshal([]byte(rsp.Body), &b); err != nil { 1417 return nil, err 1418 } 1419 return 1420 } 1421 1422 func GetBlockByRound(ctx context.Context, numSharders int, round int64) (b *block.Block, err error) { 1423 return Sharders.GetBlockByRound(ctx, numSharders, round) 1424 } 1425 1426 // GetRoundFromSharders returns the current round number from the sharders 1427 func GetRoundFromSharders() (int64, error) { 1428 return Sharders.GetRoundFromSharders() 1429 } 1430 1431 // GetHardForkRound returns the round number of the hard fork 1432 // - hardFork: hard fork name 1433 func GetHardForkRound(hardFork string) (int64, error) { 1434 return Sharders.GetHardForkRound(hardFork) 1435 } 1436 1437 func GetMagicBlockByNumber(ctx context.Context, numSharders int, number int64) (m *block.MagicBlock, err error) { 1438 1439 var result = make(chan *util.GetResponse, numSharders) 1440 defer close(result) 1441 1442 numSharders = len(Sharders.Healthy()) // overwrite, use all 1443 Sharders.QueryFromShardersContext(ctx, numSharders, 1444 fmt.Sprintf("%smagic_block_number=%d", GET_MAGIC_BLOCK_INFO, number), 1445 result) 1446 1447 var ( 1448 maxConsensus int 1449 roundConsensus = make(map[string]int) 1450 ) 1451 1452 type respObj struct { 1453 MagicBlock *block.MagicBlock `json:"magic_block"` 1454 } 1455 1456 for i := 0; i < numSharders; i++ { 1457 var rsp = <-result 1458 if rsp == nil { 1459 logging.Error("nil response") 1460 continue 1461 } 1462 logging.Debug(rsp.Url, rsp.Status) 1463 1464 if rsp.StatusCode != http.StatusOK { 1465 logging.Error(rsp.Body) 1466 continue 1467 } 1468 1469 var respo respObj 1470 if err = json.Unmarshal([]byte(rsp.Body), &respo); err != nil { 1471 logging.Error(" magic block parse error: ", err) 1472 err = nil 1473 continue 1474 } 1475 1476 m = respo.MagicBlock 1477 var h = encryption.FastHash([]byte(respo.MagicBlock.Hash)) 1478 if roundConsensus[h]++; roundConsensus[h] > maxConsensus { 1479 maxConsensus = roundConsensus[h] 1480 } 1481 } 1482 1483 if maxConsensus == 0 { 1484 return nil, errors.New("", "magic block info not found") 1485 } 1486 1487 return 1488 } 1489 1490 type NonceCache struct { 1491 cache map[string]int64 1492 guard sync.Mutex 1493 } 1494 1495 func NewNonceCache() *NonceCache { 1496 return &NonceCache{cache: make(map[string]int64)} 1497 } 1498 1499 func (nc *NonceCache) GetNextNonce(clientId string) int64 { 1500 nc.guard.Lock() 1501 defer nc.guard.Unlock() 1502 if _, ok := nc.cache[clientId]; !ok { 1503 back := &getNonceCallBack{ 1504 nonceCh: make(chan int64), 1505 err: nil, 1506 } 1507 if err := GetNonce(back); err != nil { 1508 return 0 1509 } 1510 1511 timeout, cancel := context.WithTimeout(context.Background(), time.Second) 1512 defer cancel() 1513 select { 1514 case n := <-back.nonceCh: 1515 if back.err != nil { 1516 return 0 1517 } 1518 nc.cache[clientId] = n 1519 case <-timeout.Done(): 1520 return 0 1521 } 1522 } 1523 1524 nc.cache[clientId] += 1 1525 return nc.cache[clientId] 1526 } 1527 1528 func (nc *NonceCache) Set(clientId string, nonce int64) { 1529 nc.guard.Lock() 1530 defer nc.guard.Unlock() 1531 nc.cache[clientId] = nonce 1532 } 1533 1534 func (nc *NonceCache) Evict(clientId string) { 1535 nc.guard.Lock() 1536 defer nc.guard.Unlock() 1537 delete(nc.cache, clientId) 1538 } 1539 1540 // WithEthereumNode set the ethereum node used for bridge operations. 1541 // - uri: ethereum node uri 1542 func WithEthereumNode(uri string) func(c *ChainConfig) error { 1543 return func(c *ChainConfig) error { 1544 c.EthNode = uri 1545 return nil 1546 } 1547 } 1548 1549 // WithChainID set the chain id. Chain ID is a unique identifier for the blockchain which is set at the time of its creation. 1550 // - id: chain id 1551 func WithChainID(id string) func(c *ChainConfig) error { 1552 return func(c *ChainConfig) error { 1553 c.ChainID = id 1554 return nil 1555 } 1556 } 1557 1558 // WithMinSubmit set the minimum submit, minimum number of miners that should receive the transaction submission. 1559 // - m: minimum submit 1560 func WithMinSubmit(m int) func(c *ChainConfig) error { 1561 return func(c *ChainConfig) error { 1562 c.MinSubmit = m 1563 return nil 1564 } 1565 } 1566 1567 // WithMinConfirmation set the minimum confirmation, minimum number of nodes that should confirm the transaction. 1568 // - m: minimum confirmation 1569 func WithMinConfirmation(m int) func(c *ChainConfig) error { 1570 return func(c *ChainConfig) error { 1571 c.MinConfirmation = m 1572 return nil 1573 } 1574 } 1575 1576 // WithConfirmationChainLength set the confirmation chain length, which is the number of blocks that need to be confirmed. 1577 // - m: confirmation chain length 1578 func WithConfirmationChainLength(m int) func(c *ChainConfig) error { 1579 return func(c *ChainConfig) error { 1580 c.ConfirmationChainLength = m 1581 return nil 1582 } 1583 } 1584 1585 func WithSharderConsensous(m int) func(c *ChainConfig) error { 1586 return func(c *ChainConfig) error { 1587 c.SharderConsensous = m 1588 return nil 1589 } 1590 } 1591 1592 func WithIsSplitWallet(v bool) func(c *ChainConfig) error { 1593 return func(c *ChainConfig) error { 1594 c.IsSplitWallet = v 1595 return nil 1596 } 1597 } 1598 1599 // UpdateValidatorSettings update settings of a validator. 1600 func (t *Transaction) UpdateValidatorSettings(v *Validator) (err error) { 1601 1602 err = t.createSmartContractTxn(StorageSmartContractAddress, 1603 transaction.STORAGESC_UPDATE_VALIDATOR_SETTINGS, v, 0) 1604 if err != nil { 1605 logging.Error(err) 1606 return 1607 } 1608 go func() { t.setNonceAndSubmit() }() 1609 return 1610 } 1611 1612 type VestingClientList struct { 1613 Pools []common.Key `json:"pools"` 1614 } 1615 1616 func GetVestingClientList(clientID string, cb GetInfoCallback) (err error) { 1617 if err = CheckConfig(); err != nil { 1618 return 1619 } 1620 if clientID == "" { 1621 clientID = _config.wallet.ClientID // if not blank 1622 } 1623 go GetInfoFromSharders(WithParams(GET_VESTING_CLIENT_POOLS, Params{ 1624 "client_id": clientID, 1625 }), 0, cb) 1626 return 1627 } 1628 1629 type VestingDestInfo struct { 1630 ID common.Key `json:"id"` // identifier 1631 Wanted common.Balance `json:"wanted"` // wanted amount for entire period 1632 Earned common.Balance `json:"earned"` // can unlock 1633 Vested common.Balance `json:"vested"` // already vested 1634 Last common.Timestamp `json:"last"` // last time unlocked 1635 } 1636 1637 type VestingPoolInfo struct { 1638 ID common.Key `json:"pool_id"` // pool ID 1639 Balance common.Balance `json:"balance"` // real pool balance 1640 Left common.Balance `json:"left"` // owner can unlock 1641 Description string `json:"description"` // description 1642 StartTime common.Timestamp `json:"start_time"` // from 1643 ExpireAt common.Timestamp `json:"expire_at"` // until 1644 Destinations []*VestingDestInfo `json:"destinations"` // receivers 1645 ClientID common.Key `json:"client_id"` // owner 1646 } 1647 1648 func GetVestingPoolInfo(poolID string, cb GetInfoCallback) (err error) { 1649 if err = CheckConfig(); err != nil { 1650 return 1651 } 1652 GetInfoFromSharders(WithParams(GET_VESTING_POOL_INFO, Params{ 1653 "pool_id": poolID, 1654 }), 0, cb) 1655 return 1656 } 1657 1658 func GetVestingSCConfig(cb GetInfoCallback) (err error) { 1659 if err = CheckConfig(); err != nil { 1660 return 1661 } 1662 go GetInfoFromSharders(GET_VESTING_CONFIG, 0, cb) 1663 return 1664 } 1665 1666 // faucet 1667 1668 func GetFaucetSCConfig(cb GetInfoCallback) (err error) { 1669 if err = CheckConfig(); err != nil { 1670 return 1671 } 1672 go GetInfoFromSharders(GET_FAUCETSC_CONFIG, 0, cb) 1673 return 1674 } 1675 1676 func (t *Transaction) ZCNSCAddAuthorizer(ip *AddAuthorizerPayload) (err error) { 1677 err = t.createSmartContractTxn(ZCNSCSmartContractAddress, transaction.ZCNSC_ADD_AUTHORIZER, ip, 0) 1678 if err != nil { 1679 logging.Error(err) 1680 return 1681 } 1682 go t.setNonceAndSubmit() 1683 return 1684 } 1685 1686 func (t *Transaction) ZCNSCAuthorizerHealthCheck(ip *AuthorizerHealthCheckPayload) (err error) { 1687 err = t.createSmartContractTxn(ZCNSCSmartContractAddress, transaction.ZCNSC_AUTHORIZER_HEALTH_CHECK, ip, 0) 1688 if err != nil { 1689 logging.Error(err) 1690 return 1691 } 1692 go t.setNonceAndSubmit() 1693 return 1694 } 1695 1696 func (t *Transaction) ZCNSCDeleteAuthorizer(ip *DeleteAuthorizerPayload) (err error) { 1697 err = t.createSmartContractTxn(ZCNSCSmartContractAddress, transaction.ZCNSC_DELETE_AUTHORIZER, ip, 0) 1698 if err != nil { 1699 logging.Error(err) 1700 return 1701 } 1702 go t.setNonceAndSubmit() 1703 return 1704 } 1705 1706 func (t *Transaction) ZCNSCCollectReward(providerId string, providerType Provider) error { 1707 pr := &scCollectReward{ 1708 ProviderId: providerId, 1709 ProviderType: int(providerType), 1710 } 1711 err := t.createSmartContractTxn(ZCNSCSmartContractAddress, 1712 transaction.ZCNSC_COLLECT_REWARD, pr, 0) 1713 if err != nil { 1714 logging.Error(err) 1715 return err 1716 } 1717 go func() { t.setNonceAndSubmit() }() 1718 return err 1719 }