diff --git a/README.md b/README.md index 363c8f8..58e54a4 100755 --- a/README.md +++ b/README.md @@ -22,10 +22,11 @@ If you find any system errors or you have better suggestions, please submit an i wss://testnet-rpc0.cess.cloud/ws/ wss://testnet-rpc1.cess.cloud/ws/ wss://testnet-rpc2.cess.cloud/ws/ +wss://testnet-rpc3.cess.cloud/ws/ ``` **CESS test network bootstrap node** ``` -_dnsaddr.boot-bucket-testnet.cess.cloud +_dnsaddr.boot-miner-testnet.cess.cloud ``` ## 🚰 CESS test network faucet @@ -38,19 +39,16 @@ https://testnet-faucet.cess.cloud/ To get the package use the standard: ```sh -go get -u "github.com/CESSProject/cess-go-sdk" +go get "github.com/CESSProject/cess-go-sdk" ``` ## ✅ Testing To run test: -1. Run a [CESS node](https://github.com/CESSProject/cess) locally. -2. Run the command - - ```sh - go test -v - ``` +```sh +make check +``` ## 📖 Document diff --git a/cfg.go b/cfg.go new file mode 100644 index 0000000..56e2b73 --- /dev/null +++ b/cfg.go @@ -0,0 +1,54 @@ +/* + Copyright (C) CESS. All rights reserved. + Copyright (C) Cumulus Encrypted Storage System. All rights reserved. + + SPDX-License-Identifier: Apache-2.0 +*/ + +package sdkgo + +import ( + "context" + "time" + + "github.com/CESSProject/cess-go-sdk/chain" + "github.com/CESSProject/cess-go-sdk/config" +) + +// Config describes a set of settings for a client +type Config struct { + Rpc []string + Mnemonic string + Name string + Timeout time.Duration +} + +// Option is a client config option that can be given to the client constructor +type Option func(cfg *Config) error + +// // Option is a client config option that can be given to the client constructor +// type Option func(cfg *Config) error + +// NewSDK constructs a new client from the Config. +// +// This function consumes the config. Do not reuse it (really!). +func (cfg *Config) NewSDK(ctx context.Context) (*chain.ChainClient, error) { + if cfg.Name == "" { + cfg.Name = config.CharacterName_Default + } + return chain.NewChainClient(ctx, cfg.Name, cfg.Rpc, cfg.Mnemonic, cfg.Timeout) +} + +// Apply applies the given options to the config, returning the first error +// encountered (if any). +func (cfg *Config) Apply(opts ...Option) error { + for _, opt := range opts { + if opt == nil { + continue + } + if err := opt(cfg); err != nil { + return err + } + } + return nil +} diff --git a/chain/audit.go b/chain/audit.go index 3454ca1..9b31718 100755 --- a/chain/audit.go +++ b/chain/audit.go @@ -13,86 +13,173 @@ import ( "strings" "time" - "github.com/CESSProject/cess-go-sdk/core/pattern" "github.com/CESSProject/cess-go-sdk/utils" "github.com/centrifuge/go-substrate-rpc-client/v4/types" "github.com/pkg/errors" ) -func (c *ChainClient) QueryChallengeVerifyExpiration() (uint32, error) { +// QueryChallengeSnapShot query challenge snapshot data +// - accountID: signature account of the storage miner +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - bool: is there a value +// - ChallengeInfo: challenge snapshot data +// - error: error message +func (c *ChainClient) QueryChallengeSnapShot(accountID []byte, block int32) (bool, ChallengeInfo, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - var data types.U32 - if !c.GetChainState() { - return 0, pattern.ERR_RPC_CONNECTION + var data ChallengeInfo + + if !c.GetRpcState() { + return false, data, ERR_RPC_CONNECTION } - key, err := types.CreateStorageKey(c.metadata, pattern.AUDIT, pattern.CHALLENGEVERIFYDURATION) + key, err := types.CreateStorageKey(c.metadata, Audit, ChallengeSnapShot, accountID) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.AUDIT, pattern.CHALLENGEVERIFYDURATION, err) - c.SetChainState(false) - return 0, err + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), Audit, ChallengeSnapShot, err) + return false, data, err } - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Audit, ChallengeSnapShot, err) + c.SetRpcState(false) + return false, data, err + } + return ok, data, nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.AUDIT, pattern.CHALLENGEVERIFYDURATION, err) - c.SetChainState(false) - return 0, err + return false, data, err } - if !ok { - return 0, pattern.ERR_RPC_EMPTY_VALUE + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Audit, ChallengeSnapShot, err) + c.SetRpcState(false) + return false, data, err } - return uint32(data), nil + return ok, data, nil } -func (c *ChainClient) QueryChallengeInfo(accountID []byte, block int32) (bool, pattern.ChallengeInfo, error) { +// QueryCounterdClear query the number of times to clear the challenge failure count +// - accountID: signature account of the storage miner +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - uint8: cleanup count +// - error: error message +func (c *ChainClient) QueryCountedClear(accountID []byte, block int32) (uint8, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - var data pattern.ChallengeInfo + var data types.U8 - if !c.GetChainState() { - return false, data, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return uint8(data), ERR_RPC_CONNECTION } - key, err := types.CreateStorageKey(c.metadata, pattern.AUDIT, pattern.CHALLENGESNAPSHOT, accountID) + key, err := types.CreateStorageKey(c.metadata, Audit, CountedClear, accountID) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.AUDIT, pattern.CHALLENGESNAPSHOT, err) - c.SetChainState(false) - return false, data, err + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), Audit, CountedClear, err) + return uint8(data), err } if block < 0 { ok, err := c.api.RPC.State.GetStorageLatest(key, &data) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.AUDIT, pattern.CHALLENGESNAPSHOT, err) - c.SetChainState(false) - return false, data, err + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Audit, CountedClear, err) + c.SetRpcState(false) + return uint8(data), err } - return ok, data, nil + if !ok { + return uint8(data), ERR_RPC_EMPTY_VALUE + } + return uint8(data), nil } blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - return false, data, err + return uint8(data), err + } + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Audit, CountedClear, err) + c.SetRpcState(false) + return uint8(data), err + } + if !ok { + return uint8(data), ERR_RPC_EMPTY_VALUE } + return uint8(data), nil +} +// QueryCountedServiceFailed query the number of failed service data challenge +// - accountID: signature account of the storage miner +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - uint32: Is there a value +// - error: error message +func (c *ChainClient) QueryCountedServiceFailed(accountID []byte, block int32) (uint32, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + var data types.U32 + + if !c.GetRpcState() { + return uint32(data), ERR_RPC_CONNECTION + } + + key, err := types.CreateStorageKey(c.metadata, Audit, CountedServiceFailed, accountID) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), Audit, CountedServiceFailed, err) + return uint32(data), err + } + + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Audit, CountedServiceFailed, err) + c.SetRpcState(false) + return 0, err + } + if !ok { + return 0, ERR_RPC_EMPTY_VALUE + } + return uint32(data), nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + return uint32(data), err + } ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.AUDIT, pattern.CHALLENGESNAPSHOT, err) - c.SetChainState(false) - return false, data, err + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), Audit, CountedServiceFailed, err) + c.SetRpcState(false) + return uint32(data), err } - return ok, data, nil + if !ok { + return uint32(data), ERR_RPC_EMPTY_VALUE + } + return uint32(data), nil } +// SubmitIdleProof submit idle data proof to the chain +// - idleProof: idle data proof +// +// Return: +// - string: block hash +// - error: error message func (c *ChainClient) SubmitIdleProof(idleProof []types.U8) (string, error) { c.lock.Lock() defer func() { @@ -103,38 +190,40 @@ func (c *ChainClient) SubmitIdleProof(idleProof []types.U8) (string, error) { }() var ( - txhash string + blockhash string accountInfo types.AccountInfo ) - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION + if len(idleProof) == 0 { + return blockhash, ERR_IdleProofIsEmpty + } + + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION } - call, err := types.NewCall(c.metadata, pattern.TX_AUDIT_SUBMITIDLEPROOF, idleProof) + call, err := types.NewCall(c.metadata, TX_Audit_SubmitIdleProof, idleProof) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITIDLEPROOF, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitIdleProof, err) + return blockhash, err } ext := types.NewExtrinsic(call) - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITIDLEPROOF, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitIdleProof, err) + return blockhash, err } ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITIDLEPROOF, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitIdleProof, err) + c.SetRpcState(false) + return blockhash, err } if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE + return blockhash, ERR_RPC_EMPTY_VALUE } o := types.SignatureOptions{ @@ -150,30 +239,32 @@ func (c *ChainClient) SubmitIdleProof(idleProof []types.U8) (string, error) { // Sign the transaction err = ext.Sign(c.keyring, o) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITIDLEPROOF, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitIdleProof, err) + return blockhash, err } + <-c.txTicker.C + // Do the transfer and track the actual status sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) err = ext.Sign(c.keyring, o) if err != nil { - return txhash, errors.Wrap(err, "[Sign]") + return blockhash, errors.Wrap(err, "[Sign]") } + <-c.txTicker.C sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITIDLEPROOF, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitIdleProof, err) + c.SetRpcState(false) + return blockhash, err } } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITIDLEPROOF, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitIdleProof, err) + c.SetRpcState(false) + return blockhash, err } } defer sub.Unsubscribe() @@ -185,18 +276,24 @@ func (c *ChainClient) SubmitIdleProof(idleProof []types.U8) (string, error) { select { case status := <-sub.Chan(): if status.IsInBlock { - txhash = status.AsInBlock.Hex() + blockhash = status.AsInBlock.Hex() _, err = c.RetrieveEvent_Audit_SubmitIdleProof(status.AsInBlock) - return txhash, err + return blockhash, err } case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") + return blockhash, errors.Wrap(err, "[sub]") case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT + return blockhash, ERR_RPC_TIMEOUT } } } +// SubmitServiceProof submit service data proof to the chain +// - serviceProof: service data proof +// +// Return: +// - string: block hash +// - error: error message func (c *ChainClient) SubmitServiceProof(serviceProof []types.U8) (string, error) { c.lock.Lock() defer func() { @@ -207,38 +304,36 @@ func (c *ChainClient) SubmitServiceProof(serviceProof []types.U8) (string, error }() var ( - txhash string + blockhash string accountInfo types.AccountInfo ) - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION } - call, err := types.NewCall(c.metadata, pattern.TX_AUDIT_SUBMITSERVICEPROOF, serviceProof) + call, err := types.NewCall(c.metadata, TX_Audit_SubmitServiceProof, serviceProof) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITSERVICEPROOF, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitServiceProof, err) + return blockhash, err } ext := types.NewExtrinsic(call) - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITSERVICEPROOF, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitServiceProof, err) + return blockhash, err } ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITSERVICEPROOF, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitServiceProof, err) + c.SetRpcState(false) + return blockhash, err } if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE + return blockhash, ERR_RPC_EMPTY_VALUE } o := types.SignatureOptions{ @@ -254,30 +349,32 @@ func (c *ChainClient) SubmitServiceProof(serviceProof []types.U8) (string, error // Sign the transaction err = ext.Sign(c.keyring, o) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITSERVICEPROOF, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitServiceProof, err) + return blockhash, err } + <-c.txTicker.C + // Do the transfer and track the actual status sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) err = ext.Sign(c.keyring, o) if err != nil { - return txhash, errors.Wrap(err, "[Sign]") + return blockhash, errors.Wrap(err, "[Sign]") } + <-c.txTicker.C sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITSERVICEPROOF, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitServiceProof, err) + c.SetRpcState(false) + return blockhash, err } } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITSERVICEPROOF, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitServiceProof, err) + c.SetRpcState(false) + return blockhash, err } } defer sub.Unsubscribe() @@ -289,19 +386,31 @@ func (c *ChainClient) SubmitServiceProof(serviceProof []types.U8) (string, error select { case status := <-sub.Chan(): if status.IsInBlock { - txhash = status.AsInBlock.Hex() + blockhash = status.AsInBlock.Hex() _, err = c.RetrieveEvent_Audit_SubmitServiceProof(status.AsInBlock) - return txhash, err + return blockhash, err } case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") + return blockhash, errors.Wrap(err, "[sub]") case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT + return blockhash, ERR_RPC_TIMEOUT } } } -func (c *ChainClient) SubmitIdleProofResult(totalProofHash []types.U8, front, rear types.U64, accumulator pattern.Accumulator, result types.Bool, sig types.Bytes, teePuk pattern.WorkerPublicKey) (string, error) { +// SubmitVerifyIdleResult submit validation result of idle data proof to the chain +// - totalProofHash: total idle data proof hash value +// - front: idle data pre-offset +// - rear: back offset of idle data +// - accumulator: accumulator value +// - result: validation result of idle data proof +// - sig: signature from tee +// - teePuk: tee's work public key +// +// Return: +// - string: block hash +// - error: error message +func (c *ChainClient) SubmitVerifyIdleResult(totalProofHash []types.U8, front, rear types.U64, accumulator Accumulator, result types.Bool, sig types.Bytes, teePuk WorkerPublicKey) (string, error) { c.lock.Lock() defer func() { c.lock.Unlock() @@ -311,38 +420,36 @@ func (c *ChainClient) SubmitIdleProofResult(totalProofHash []types.U8, front, re }() var ( - txhash string + blockhash string accountInfo types.AccountInfo ) - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION } - call, err := types.NewCall(c.metadata, pattern.TX_AUDIT_SUBMITIDLEPROOFRESULT, totalProofHash, front, rear, accumulator, result, sig, teePuk) + call, err := types.NewCall(c.metadata, TX_Audit_SubmitVerifyIdleResult, totalProofHash, front, rear, accumulator, result, sig, teePuk) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITIDLEPROOFRESULT, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitVerifyIdleResult, err) + return blockhash, err } ext := types.NewExtrinsic(call) - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITIDLEPROOFRESULT, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitVerifyIdleResult, err) + return blockhash, err } ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITIDLEPROOFRESULT, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitVerifyIdleResult, err) + c.SetRpcState(false) + return blockhash, err } if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE + return blockhash, ERR_RPC_EMPTY_VALUE } o := types.SignatureOptions{ @@ -358,30 +465,32 @@ func (c *ChainClient) SubmitIdleProofResult(totalProofHash []types.U8, front, re // Sign the transaction err = ext.Sign(c.keyring, o) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITIDLEPROOFRESULT, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitVerifyIdleResult, err) + return blockhash, err } + <-c.txTicker.C + // Do the transfer and track the actual status sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) err = ext.Sign(c.keyring, o) if err != nil { - return txhash, errors.Wrap(err, "[Sign]") + return blockhash, errors.Wrap(err, "[Sign]") } + <-c.txTicker.C sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITIDLEPROOFRESULT, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitVerifyIdleResult, err) + c.SetRpcState(false) + return blockhash, err } } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITIDLEPROOFRESULT, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitVerifyIdleResult, err) + c.SetRpcState(false) + return blockhash, err } } defer sub.Unsubscribe() @@ -393,19 +502,28 @@ func (c *ChainClient) SubmitIdleProofResult(totalProofHash []types.U8, front, re select { case status := <-sub.Chan(): if status.IsInBlock { - txhash = status.AsInBlock.Hex() + blockhash = status.AsInBlock.Hex() _, err = c.RetrieveEvent_Audit_SubmitIdleVerifyResult(status.AsInBlock) - return txhash, err + return blockhash, err } case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") + return blockhash, errors.Wrap(err, "[sub]") case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT + return blockhash, ERR_RPC_TIMEOUT } } } -func (c *ChainClient) SubmitServiceProofResult(result types.Bool, sign types.Bytes, bloomFilter pattern.BloomFilter, teePuk pattern.WorkerPublicKey) (string, error) { +// SubmitVerifyServiceResult submit validation result of service data proof to the chain +// - result: validation result of idle data proof +// - sig: signature from tee +// - bloomFilter: bloom filter value +// - teePuk: tee's work public key +// +// Return: +// - string: block hash +// - error: error message +func (c *ChainClient) SubmitVerifyServiceResult(result types.Bool, sign types.Bytes, bloomFilter BloomFilter, teePuk WorkerPublicKey) (string, error) { c.lock.Lock() defer func() { c.lock.Unlock() @@ -415,38 +533,36 @@ func (c *ChainClient) SubmitServiceProofResult(result types.Bool, sign types.Byt }() var ( - txhash string + blockhash string accountInfo types.AccountInfo ) - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION } - call, err := types.NewCall(c.metadata, pattern.TX_AUDIT_SUBMITSERVICEPROOFRESULT, result, sign, bloomFilter, teePuk) + call, err := types.NewCall(c.metadata, TX_Audit_SubmitVerifyServiceResult, result, sign, bloomFilter, teePuk) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITSERVICEPROOFRESULT, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitVerifyServiceResult, err) + return blockhash, err } ext := types.NewExtrinsic(call) - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITSERVICEPROOFRESULT, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitVerifyServiceResult, err) + return blockhash, err } ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITSERVICEPROOFRESULT, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitVerifyServiceResult, err) + c.SetRpcState(false) + return blockhash, err } if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE + return blockhash, ERR_RPC_EMPTY_VALUE } o := types.SignatureOptions{ @@ -462,30 +578,32 @@ func (c *ChainClient) SubmitServiceProofResult(result types.Bool, sign types.Byt // Sign the transaction err = ext.Sign(c.keyring, o) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITSERVICEPROOFRESULT, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitVerifyServiceResult, err) + return blockhash, err } + <-c.txTicker.C + // Do the transfer and track the actual status sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) err = ext.Sign(c.keyring, o) if err != nil { - return txhash, errors.Wrap(err, "[Sign]") + return blockhash, errors.Wrap(err, "[Sign]") } + <-c.txTicker.C sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITSERVICEPROOFRESULT, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitVerifyServiceResult, err) + c.SetRpcState(false) + return blockhash, err } } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_AUDIT_SUBMITSERVICEPROOFRESULT, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Audit_SubmitVerifyServiceResult, err) + c.SetRpcState(false) + return blockhash, err } } defer sub.Unsubscribe() @@ -497,14 +615,14 @@ func (c *ChainClient) SubmitServiceProofResult(result types.Bool, sign types.Byt select { case status := <-sub.Chan(): if status.IsInBlock { - txhash = status.AsInBlock.Hex() + blockhash = status.AsInBlock.Hex() _, err = c.RetrieveEvent_Audit_SubmitServiceVerifyResult(status.AsInBlock) - return txhash, err + return blockhash, err } case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") + return blockhash, errors.Wrap(err, "[sub]") case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT + return blockhash, ERR_RPC_TIMEOUT } } } diff --git a/chain/balances.go b/chain/balances.go new file mode 100644 index 0000000..6ce74d2 --- /dev/null +++ b/chain/balances.go @@ -0,0 +1,241 @@ +/* + Copyright (C) CESS. All rights reserved. + Copyright (C) Cumulus Encrypted Storage System. All rights reserved. + + SPDX-License-Identifier: Apache-2.0 +*/ + +package chain + +import ( + "fmt" + "log" + "time" + + "github.com/CESSProject/cess-go-sdk/utils" + "github.com/centrifuge/go-substrate-rpc-client/v4/types" + "github.com/pkg/errors" +) + +// QueryTotalIssuance query the total amount of token issuance +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - string: the total amount of token issuance +// - error: error message +func (c *ChainClient) QueryTotalIssuance(block int) (string, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + var data types.U128 + + if !c.GetRpcState() { + return "", ERR_RPC_CONNECTION + } + + key, err := types.CreateStorageKey(c.metadata, Balances, TotalIssuance) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), Balances, TotalIssuance, err) + return "", err + } + + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Balances, TotalIssuance, err) + c.SetRpcState(false) + return "", err + } + if !ok { + return "", ERR_RPC_EMPTY_VALUE + } + return data.String(), nil + } + + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), Balances, TotalIssuance, err) + return "", err + } + + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), Balances, TotalIssuance, err) + c.SetRpcState(false) + return "", err + } + if !ok { + return "0", nil + } + if data.String() == "" { + return "0", nil + } + return data.String(), nil +} + +// QueryInactiveIssuance query the amount of inactive token issuance +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - string: the amount of inactive token issuance +// - error: error message +func (c *ChainClient) QueryInactiveIssuance(block int) (string, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + var data types.U128 + + if !c.GetRpcState() { + return "", ERR_RPC_CONNECTION + } + + key, err := types.CreateStorageKey(c.metadata, Balances, InactiveIssuance) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), Balances, InactiveIssuance, err) + return "", err + } + + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Balances, InactiveIssuance, err) + c.SetRpcState(false) + return "", err + } + if !ok { + return "", ERR_RPC_EMPTY_VALUE + } + return data.String(), nil + } + + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), Balances, InactiveIssuance, err) + return "", err + } + + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), Balances, InactiveIssuance, err) + c.SetRpcState(false) + return "", err + } + if !ok { + return "0", nil + } + if data.String() == "" { + return "0", nil + } + return data.String(), nil +} + +// TransferToken transfers to other accounts +// - dest: target account +// - amount: transfer amount +// +// Return: +// - string: block hash +// - string: target account +// - error: error message +func (c *ChainClient) TransferToken(dest string, amount uint64) (string, string, error) { + c.lock.Lock() + defer func() { + c.lock.Unlock() + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var ( + blockhash string + accountInfo types.AccountInfo + ) + + if !c.GetRpcState() { + return blockhash, "", ERR_RPC_CONNECTION + } + + pubkey, err := utils.ParsingPublickey(dest) + if err != nil { + return blockhash, "", errors.Wrapf(err, "[ParsingPublickey]") + } + + address, err := types.NewMultiAddressFromAccountID(pubkey) + if err != nil { + return blockhash, "", errors.Wrapf(err, "[NewMultiAddressFromAccountID]") + } + + call, err := types.NewCall(c.metadata, TX_Balances_Transfer, address, types.NewUCompactFromUInt(amount)) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_Balances_Transfer, err) + return blockhash, "", err + } + + ext := types.NewExtrinsic(call) + + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_Balances_Transfer, err) + return blockhash, "", err + } + + ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_Balances_Transfer, err) + c.SetRpcState(false) + return blockhash, "", err + } + if !ok { + return blockhash, "", ERR_RPC_EMPTY_VALUE + } + + o := types.SignatureOptions{ + BlockHash: c.genesisHash, + Era: types.ExtrinsicEra{IsMortalEra: false}, + GenesisHash: c.genesisHash, + Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), + SpecVersion: c.runtimeVersion.SpecVersion, + Tip: types.NewUCompactFromUInt(0), + TransactionVersion: c.runtimeVersion.TransactionVersion, + } + + // Sign the transaction + err = ext.Sign(c.keyring, o) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_Balances_Transfer, err) + return blockhash, "", err + } + + <-c.txTicker.C + + // Do the transfer and track the actual status + sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Balances_Transfer, err) + c.SetRpcState(false) + return blockhash, "", err + } + defer sub.Unsubscribe() + + timeout := time.NewTimer(c.packingTime) + defer timeout.Stop() + + for { + select { + case status := <-sub.Chan(): + if status.IsInBlock { + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_Balances_Transfer(status.AsInBlock) + return blockhash, dest, err + } + case err = <-sub.Err(): + return blockhash, "", errors.Wrap(err, "[sub]") + case <-timeout.C: + return blockhash, "", ERR_RPC_TIMEOUT + } + } +} diff --git a/chain/chain.go b/chain/chain.go index ba11e27..fb82a7e 100755 --- a/chain/chain.go +++ b/chain/chain.go @@ -9,18 +9,12 @@ package chain import ( "context" - "encoding/hex" - "fmt" "io" "log" - "net/http" "os" - "strings" "sync" "time" - "github.com/CESSProject/cess-go-sdk/core/pattern" - "github.com/CESSProject/cess-go-sdk/core/sdk" "github.com/CESSProject/cess-go-sdk/utils" gsrpc "github.com/centrifuge/go-substrate-rpc-client/v4" "github.com/centrifuge/go-substrate-rpc-client/v4/registry/retriever" @@ -28,9 +22,6 @@ import ( "github.com/centrifuge/go-substrate-rpc-client/v4/signature" "github.com/centrifuge/go-substrate-rpc-client/v4/types" "github.com/centrifuge/go-substrate-rpc-client/v4/xxhash" - "github.com/mr-tron/base58" - "github.com/pkg/errors" - "github.com/vedhavyas/go-subkey/sr25519" ) type ChainClient struct { @@ -41,7 +32,6 @@ type ChainClient struct { metadata *types.Metadata runtimeVersion *types.RuntimeVersion eventRetriever retriever.EventRetriever - keyEvents types.StorageKey genesisHash types.Hash keyring signature.KeyringPair rpcAddr []string @@ -50,37 +40,32 @@ type ChainClient struct { tokenSymbol string networkEnv string signatureAcc string - treasuryAcc string name string - chainState bool + rpcState bool } -var _ sdk.SDK = (*ChainClient)(nil) - -var globalTransport = &http.Transport{ - DisableKeepAlives: true, -} - -func NewEmptyChainClient() *ChainClient { - return &ChainClient{} -} - -func NewChainClient( - ctx context.Context, - serviceName string, - rpcs []string, - mnemonic string, - t time.Duration, -) (*ChainClient, error) { +var _ Chainer = (*ChainClient)(nil) + +// NewChainClient creates a chainclient +// - ctx: context +// - name: customised name, can be empty +// - rpcs: rpc addresses +// - mnemonic: account mnemonic, can be empty +// - t: waiting time for transaction packing, default is 30 seconds +// +// Return: +// - *ChainClient: chain client +// - error: error message +func NewChainClient(ctx context.Context, name string, rpcs []string, mnemonic string, t time.Duration) (*ChainClient, error) { var ( err error chainClient = &ChainClient{ lock: new(sync.Mutex), chainStLock: new(sync.Mutex), - txTicker: time.NewTicker(pattern.BlockInterval), + txTicker: time.NewTicker(BlockInterval), rpcAddr: rpcs, packingTime: t, - name: serviceName, + name: name, } ) @@ -98,10 +83,10 @@ func NewChainClient( } if chainClient.api == nil { - return nil, pattern.ERR_RPC_CONNECTION + return nil, ERR_RPC_CONNECTION } - chainClient.SetChainState(true) + chainClient.SetRpcState(true) chainClient.metadata, err = chainClient.api.RPC.State.GetMetadataLatest() if err != nil { @@ -115,10 +100,6 @@ func NewChainClient( if err != nil { return nil, err } - chainClient.keyEvents, err = types.CreateStorageKey(chainClient.metadata, pattern.SYSTEM, pattern.EVENTS, nil) - if err != nil { - return nil, err - } chainClient.eventRetriever, err = retriever.NewDefaultEventRetriever(state.NewEventProvider(chainClient.api.RPC.State), chainClient.api.RPC.State) if err != nil { return nil, err @@ -133,130 +114,132 @@ func NewChainClient( return nil, err } } - properties, err := chainClient.SysProperties() + properties, err := chainClient.SystemProperties() if err != nil { return nil, err } chainClient.tokenSymbol = string(properties.TokenSymbol) - chainClient.networkEnv, err = chainClient.SysChain() + chainClient.networkEnv, err = chainClient.SystemChain() if err != nil { return nil, err } - if strings.Contains(chainClient.networkEnv, "test") { - chainClient.treasuryAcc = "cXhT9Xh3DhrBMDmXcGeMPDmTzDm1J8vDxBtKvogV33pPshnWS" - } else if strings.Contains(chainClient.networkEnv, "main") { - chainClient.treasuryAcc = "cXhT9Xh3DhrBMDmXcGeMPDmTzDm1J8vDxBtKvogV33pPshnWS" - } else { - chainClient.treasuryAcc = "cXhT9Xh3DhrBMDmXcGeMPDmTzDm1J8vDxBtKvogV33pPshnWS" - } - return chainClient, nil } -func (c *ChainClient) ReconnectRPC() error { - var err error - c.lock.Lock() - defer c.lock.Unlock() - if c.GetChainState() { - return nil - } - if c.api != nil { - if c.api.Client != nil { - c.api.Client.Close() - c.api.Client = nil - } - c.api = nil - } - c.api, - c.metadata, - c.runtimeVersion, - c.keyEvents, - c.eventRetriever, - c.genesisHash, - c.currentRpcAddr, err = reconnectChainSDK(c.currentRpcAddr, c.rpcAddr) - if err != nil { - return err - } - c.SetChainState(true) - return nil -} - +// GetSDKName get sdk name func (c *ChainClient) GetSDKName() string { return c.name } +// GetCurrentRpcAddr get the current rpc address being used func (c *ChainClient) GetCurrentRpcAddr() string { return c.currentRpcAddr } -func (c *ChainClient) SetSDKName(name string) { - c.name = name -} - -func (c *ChainClient) SetChainState(state bool) { +// SetChainState set the rpc connection status flag, +// when the rpc connection is normal, set it to true, +// otherwise set it to false. +func (c *ChainClient) SetRpcState(state bool) { c.chainStLock.Lock() - c.chainState = state + c.rpcState = state c.chainStLock.Unlock() } -func (c *ChainClient) GetChainState() bool { +// GetRpcState get the rpc connection status flag +// - true: connection is normal +// - false: connection failed +func (c *ChainClient) GetRpcState() bool { c.chainStLock.Lock() - st := c.chainState + st := c.rpcState c.chainStLock.Unlock() return st } +// GetSignatureAcc get your current account address +// +// Note: +// - make sure you fill in mnemonic when you create the chain client func (c *ChainClient) GetSignatureAcc() string { return c.signatureAcc } -func (c *ChainClient) GetKeyEvents() types.StorageKey { - return c.keyEvents -} - +// GetSignatureAccPulickey get your current account public key +// +// Note: +// - make sure you fill in mnemonic when you create the chain client func (c *ChainClient) GetSignatureAccPulickey() []byte { return c.keyring.PublicKey } +// GetSubstrateAPI get substrate api func (c *ChainClient) GetSubstrateAPI() *gsrpc.SubstrateAPI { return c.api } +// GetMetadata get chain metadata func (c *ChainClient) GetMetadata() *types.Metadata { return c.metadata } +// GetTokenSymbol get token symbol func (c *ChainClient) GetTokenSymbol() string { return c.tokenSymbol } +// GetNetworkEnv get network env func (c *ChainClient) GetNetworkEnv() string { return c.networkEnv } +// GetURI get the mnemonic for your current account func (c *ChainClient) GetURI() string { return c.keyring.URI } -func (c *ChainClient) GetTreasuryAccount() string { - return c.treasuryAcc -} - +// Sign with the mnemonic of your current account func (c *ChainClient) Sign(msg []byte) ([]byte, error) { return signature.Sign(msg, c.keyring.URI) } +// Verify the signature with your current account's mnemonic func (c *ChainClient) Verify(msg []byte, sig []byte) (bool, error) { return signature.Verify(msg, sig, c.keyring.URI) } -func reconnectChainSDK(oldRpc string, rpcs []string) ( +// ReconnectRpc reconnect rpc +func (c *ChainClient) ReconnectRpc() error { + var err error + c.lock.Lock() + defer c.lock.Unlock() + if c.GetRpcState() { + return nil + } + if c.api != nil { + if c.api.Client != nil { + c.api.Client.Close() + c.api.Client = nil + } + c.api = nil + } + c.api, + c.metadata, + c.runtimeVersion, + c.eventRetriever, + c.genesisHash, + c.currentRpcAddr, err = reconnectRpc(c.currentRpcAddr, c.rpcAddr) + if err != nil { + return err + } + c.SetRpcState(true) + return nil +} + +func reconnectRpc(oldRpc string, rpcs []string) ( *gsrpc.SubstrateAPI, *types.Metadata, *types.RuntimeVersion, - types.StorageKey, retriever.EventRetriever, types.Hash, string, @@ -286,91 +269,42 @@ func reconnectChainSDK(oldRpc string, rpcs []string) ( rpcAddr = rpcaddrs[i] } if api == nil { - return nil, nil, nil, nil, nil, types.Hash{}, rpcAddr, pattern.ERR_RPC_CONNECTION + return nil, nil, nil, nil, types.Hash{}, rpcAddr, ERR_RPC_CONNECTION } var metadata *types.Metadata var runtimeVer *types.RuntimeVersion - var keyEvents types.StorageKey var genesisHash types.Hash var eventRetriever retriever.EventRetriever metadata, err = api.RPC.State.GetMetadataLatest() if err != nil { - return nil, nil, nil, nil, nil, types.Hash{}, rpcAddr, pattern.ERR_RPC_CONNECTION + return nil, nil, nil, nil, types.Hash{}, rpcAddr, ERR_RPC_CONNECTION } genesisHash, err = api.RPC.Chain.GetBlockHash(0) if err != nil { - return nil, nil, nil, nil, nil, types.Hash{}, rpcAddr, pattern.ERR_RPC_CONNECTION + return nil, nil, nil, nil, types.Hash{}, rpcAddr, ERR_RPC_CONNECTION } runtimeVer, err = api.RPC.State.GetRuntimeVersionLatest() if err != nil { - return nil, nil, nil, nil, nil, types.Hash{}, rpcAddr, pattern.ERR_RPC_CONNECTION - } - keyEvents, err = types.CreateStorageKey(metadata, pattern.SYSTEM, pattern.EVENTS, nil) - if err != nil { - return nil, nil, nil, nil, nil, types.Hash{}, rpcAddr, pattern.ERR_RPC_CONNECTION + return nil, nil, nil, nil, types.Hash{}, rpcAddr, ERR_RPC_CONNECTION } eventRetriever, err = retriever.NewDefaultEventRetriever(state.NewEventProvider(api.RPC.State), api.RPC.State) if err != nil { - return nil, nil, nil, nil, nil, types.Hash{}, rpcAddr, pattern.ERR_RPC_CONNECTION + return nil, nil, nil, nil, types.Hash{}, rpcAddr, ERR_RPC_CONNECTION } - return api, metadata, runtimeVer, keyEvents, eventRetriever, genesisHash, rpcAddr, err + return api, metadata, runtimeVer, eventRetriever, genesisHash, rpcAddr, err } -func createPrefixedKey(pallet, method string) []byte { +func CreatePrefixedKey(pallet, method string) []byte { return append(xxhash.New128([]byte(pallet)).Sum(nil), xxhash.New128([]byte(method)).Sum(nil)...) } -func (c *ChainClient) VerifyPolkaSignatureWithJS(account, msg, signature string) (bool, error) { - if len(msg) == 0 { - return false, errors.New("msg is empty") - } - - pkey, err := utils.ParsingPublickey(account) - if err != nil { - return false, err - } - - pub, err := sr25519.Scheme{}.FromPublicKey(pkey) - if err != nil { - return false, err - } - - sign_bytes, err := hex.DecodeString(strings.TrimPrefix(signature, "0x")) - if err != nil { - return false, err - } - message := fmt.Sprintf("%s", msg) - ok := pub.Verify([]byte(message), sign_bytes) - return ok, nil -} - -func (c *ChainClient) VerifyPolkaSignatureWithBase58(account, msg, signature string) (bool, error) { - if len(msg) == 0 { - return false, errors.New("msg is empty") - } - - pkey, err := utils.ParsingPublickey(account) - if err != nil { - return false, err - } - - pub, err := sr25519.Scheme{}.FromPublicKey(pkey) - if err != nil { - return false, err - } - - sign_bytes, err := base58.Decode(signature) - if err != nil { - return false, err - } - message := fmt.Sprintf("%s", msg) - ok := pub.Verify([]byte(message), sign_bytes) - return ok, nil -} - +// close chain client func (c *ChainClient) Close() { - if c.api.Client != nil { - c.api.Client.Close() + if c.api != nil { + if c.api.Client != nil { + c.api.Client.Close() + } + c.api = nil } } diff --git a/chain/chainer.go b/chain/chainer.go new file mode 100755 index 0000000..f813248 --- /dev/null +++ b/chain/chainer.go @@ -0,0 +1,197 @@ +/* + Copyright (C) CESS. All rights reserved. + Copyright (C) Cumulus Encrypted Storage System. All rights reserved. + + SPDX-License-Identifier: Apache-2.0 +*/ + +package chain + +import ( + gsrpc "github.com/centrifuge/go-substrate-rpc-client/v4" + "github.com/centrifuge/go-substrate-rpc-client/v4/types" +) + +// Chain client interface +type Chainer interface { + // Audit + QueryChallengeSnapShot(accountID []byte, block int32) (bool, ChallengeInfo, error) + QueryCountedClear(accountID []byte, block int32) (uint8, error) + QueryCountedServiceFailed(accountID []byte, block int32) (uint32, error) + SubmitIdleProof(idleProof []types.U8) (string, error) + SubmitServiceProof(serviceProof []types.U8) (string, error) + + // Balances + QueryTotalIssuance(block int) (string, error) + QueryInactiveIssuance(block int) (string, error) + TransferToken(dest string, amount uint64) (string, string, error) + + // Oss + QueryOss(accountID []byte, block int32) (OssInfo, error) + QueryAllOss(block int32) ([]OssInfo, error) + QueryAllOssPeerId(block int32) ([]string, error) + QueryAuthorityList(accountID []byte, block int32) ([]types.AccountID, error) + Authorize(accountID []byte) (string, error) + CancelAuthorize(accountID []byte) (string, error) + RegisterOss(peerId []byte, domain string) (string, error) + UpdateOss(peerId string, domain string) (string, error) + DestroyOss() (string, error) + + // EVM + SendEvmCall(source types.H160, target types.H160, input types.Bytes, value types.U256, gasLimit types.U64, maxFeePerGas types.U256, accessList []AccessInfo) (string, error) + + // FileBank + QueryBucket(accountID []byte, bucketName string, block int32) (BucketInfo, error) + QueryDealMap(fid string, block int32) (StorageOrder, error) + QueryFile(fid string, block int32) (FileMetadata, error) + QueryRestoralOrder(fragmentHash string, block int32) (RestoralOrderInfo, error) + QueryAllRestoralOrder(block int32) ([]RestoralOrderInfo, error) + QueryAllBucketName(accountID []byte, block int32) ([]string, error) + QueryAllUserFiles(accountID []byte, block int32) ([]string, error) + GenerateStorageOrder(fid string, segment []SegmentDataInfo, owner []byte, filename string, buckname string, filesize uint64) (string, error) + UploadDeclaration(fid string, segment []SegmentList, user UserBrief, filesize uint64) (string, error) + CreateBucket(owner []byte, bucketName string) (string, error) + DeleteBucket(owner []byte, bucketName string) (string, error) + DeleteFile(owner []byte, fid string) (string, error) + TransferReport(index uint8, fid string) (string, error) + GenerateRestoralOrder(fid, fragmentHash string) (string, error) + ClaimRestoralOrder(fragmentHash string) (string, error) + ClaimRestoralNoExistOrder(puk []byte, fid, fragmentHash string) (string, error) + RestoralOrderComplete(fragmentHash string) (string, error) + CertIdleSpace(spaceProofInfo SpaceProofInfo, teeSignWithAcc, teeSign types.Bytes, teePuk WorkerPublicKey) (string, error) + ReplaceIdleSpace(spaceProofInfo SpaceProofInfo, teeSignWithAcc, teeSign types.Bytes, teePuk WorkerPublicKey) (string, error) + CalculateReport(teeSig types.Bytes, tagSigInfo TagSigInfo) (string, error) + + // Sminer + QueryExpenders(block int32) (ExpendersInfo, error) + QueryMinerItems(accountID []byte, block int32) (MinerInfo, error) + QueryStakingStartBlock(accountID []byte, block int32) (uint32, error) + QueryAllMiner(block int32) ([]types.AccountID, error) + QueryCounterForMinerItems(block int32) (uint32, error) + QueryRewardMap(accountID []byte, block int32) (MinerReward, error) + QueryRestoralTarget(accountID []byte, block int32) (RestoralTargetInfo, error) + QueryAllRestoralTarget(block int32) ([]RestoralTargetInfo, error) + QueryPendingReplacements(accountID []byte, block int32) (types.U128, error) + QueryCompleteSnapShot(era uint32, block int32) (uint32, uint64, error) + IncreaseCollateral(accountID []byte, token string) (string, error) + IncreaseDeclarationSpace(tibCount uint32) (string, error) + MinerExitPrep() (string, error) + MinerWithdraw() (string, error) + ReceiveReward() (string, error) + RegisterPoisKey(poisKey PoISKeyInfo, teeSignWithAcc, teeSign types.Bytes, teePuk WorkerPublicKey) (string, error) + RegnstkSminer(earnings string, peerId []byte, staking uint64, tibCount uint32) (string, error) + RegnstkAssignStaking(earnings string, peerId []byte, stakingAcc string, tibCount uint32) (string, error) + UpdateBeneficiary(earnings string) (string, error) + UpdateSminerPeerId(peerid PeerId) (string, error) + + // Staking + QueryCounterForValidators(block int) (uint32, error) + QueryValidatorsCount(block int) (uint32, error) + QueryNominatorCount(block int) (uint32, error) + QueryErasTotalStake(era uint32, block int) (string, error) + QueryCurrentEra(block int) (uint32, error) + QueryErasRewardPoints(era uint32, block int32) (StakingEraRewardPoints, error) + QueryAllNominators(block int32) ([]StakingNominations, error) + QueryAllBonded(block int32) ([]types.AccountID, error) + QueryValidatorCommission(accountID []byte, block int) (uint8, error) + QueryEraValidatorReward(era uint32, block int) (string, error) + + // StorageHandler + QueryUnitPrice(block int32) (string, error) + QueryUserOwnedSpace(accountID []byte, block int32) (UserSpaceInfo, error) + QueryTotalIdleSpace(block int32) (uint64, error) + QueryTotalServiceSpace(block int32) (uint64, error) + QueryPurchasedSpace(block int32) (uint64, error) + BuySpace(count uint32) (string, error) + ExpansionSpace(count uint32) (string, error) + RenewalSpace(days uint32) (string, error) + + // System + QueryBlockNumber(blockhash string) (uint32, error) + QueryAccountInfo(account string, block int32) (types.AccountInfo, error) + QueryAccountInfoByAccountID(accountID []byte, block int32) (types.AccountInfo, error) + + // TeeWorker + QueryMasterPubKey(block int32) ([]byte, error) + QueryWorkers(puk WorkerPublicKey, block int32) (WorkerInfo, error) + QueryAllWorkers(block int32) ([]WorkerInfo, error) + QueryEndpoints(puk WorkerPublicKey, block int32) (string, error) + QueryWorkerAddedAt(puk WorkerPublicKey, block int32) (uint32, error) + + // CessTreasury + QueryCurrencyReward(block int32) (string, error) + QueryEraReward(block int32) (string, error) + QueryReserveReward(block int32) (string, error) + QueryRoundReward(era uint32, block int32) (string, error) + + // rpc_call + SystemProperties() (SysProperties, error) + SystemChain() (string, error) + SystemSyncState() (SysSyncState, error) + SystemVersion() (string, error) + NetListening() (bool, error) + + // chain_client + GetSDKName() string + GetCurrentRpcAddr() string + GetRpcState() bool + SetRpcState(state bool) + GetSignatureAcc() string + GetSignatureAccPulickey() []byte + GetSubstrateAPI() *gsrpc.SubstrateAPI + GetMetadata() *types.Metadata + GetTokenSymbol() string + GetNetworkEnv() string + GetURI() string + Sign(msg []byte) ([]byte, error) + Verify(msg []byte, sig []byte) (bool, error) + ReconnectRpc() error + Close() + + // Extrinsics + InitExtrinsicsName() error + + // event + DecodeEventNameFromBlock(block uint64) ([]string, error) + DecodeEventNameFromBlockhash(blockhash types.Hash) ([]string, error) + // retrieve event + RetrieveEvent_Audit_SubmitIdleProof(blockhash types.Hash) (Event_SubmitIdleProof, error) + RetrieveEvent_Audit_SubmitServiceProof(blockhash types.Hash) (Event_SubmitServiceProof, error) + RetrieveEvent_Audit_SubmitIdleVerifyResult(blockhash types.Hash) (Event_SubmitIdleVerifyResult, error) + RetrieveEvent_Audit_SubmitServiceVerifyResult(blockhash types.Hash) (Event_SubmitServiceVerifyResult, error) + RetrieveEvent_Oss_OssUpdate(blockhash types.Hash) (Event_OssUpdate, error) + RetrieveEvent_Oss_OssRegister(blockhash types.Hash) (Event_OssRegister, error) + RetrieveEvent_Oss_OssDestroy(blockhash types.Hash) (Event_OssDestroy, error) + RetrieveEvent_Oss_Authorize(blockhash types.Hash) (Event_Authorize, error) + RetrieveEvent_Oss_CancelAuthorize(blockhash types.Hash) (Event_CancelAuthorize, error) + RetrieveEvent_FileBank_UploadDeclaration(blockhash types.Hash) (Event_UploadDeclaration, error) + RetrieveEvent_FileBank_CreateBucket(blockhash types.Hash) (Event_CreateBucket, error) + RetrieveEvent_FileBank_DeleteFile(blockhash types.Hash) (Event_DeleteFile, error) + RetrieveEvent_FileBank_TransferReport(blockhash types.Hash) (Event_TransferReport, error) + RetrieveEvent_FileBank_ClaimRestoralOrder(blockhash types.Hash) (Event_ClaimRestoralOrder, error) + RetrieveEvent_FileBank_RecoveryCompleted(blockhash types.Hash) (Event_RecoveryCompleted, error) + RetrieveEvent_FileBank_IdleSpaceCert(blockhash types.Hash) (Event_IdleSpaceCert, error) + RetrieveEvent_FileBank_ReplaceIdleSpace(blockhash types.Hash) (Event_ReplaceIdleSpace, error) + RetrieveEvent_FileBank_CalculateReport(blockhash types.Hash) (Event_CalculateReport, error) + RetrieveEvent_Sminer_Registered(blockhash types.Hash) (Event_Registered, error) + RetrieveEvent_Sminer_RegisterPoisKey(blockhash types.Hash) (Event_RegisterPoisKey, error) + RetrieveEvent_Sminer_UpdataIp(blockhash types.Hash) (Event_UpdatePeerId, error) + RetrieveEvent_Sminer_UpdataBeneficiary(blockhash types.Hash) (Event_UpdateBeneficiary, error) + RetrieveEvent_Sminer_MinerExitPrep(blockhash types.Hash) (Event_MinerExitPrep, error) + RetrieveEvent_Sminer_IncreaseCollateral(blockhash types.Hash) (Event_IncreaseCollateral, error) + RetrieveEvent_Sminer_Receive(blockhash types.Hash) (Event_Receive, error) + RetrieveEvent_Sminer_Withdraw(blockhash types.Hash) (Event_Withdraw, error) + RetrieveEvent_Sminer_IncreaseDeclarationSpace(blockhash types.Hash) (Event_IncreaseDeclarationSpace, error) + RetrieveEvent_StorageHandler_BuySpace(blockhash types.Hash) (Event_BuySpace, error) + RetrieveEvent_StorageHandler_ExpansionSpace(blockhash types.Hash) (Event_ExpansionSpace, error) + RetrieveEvent_StorageHandler_RenewalSpace(blockhash types.Hash) (Event_RenewalSpace, error) + RetrieveEvent_Balances_Transfer(blockhash types.Hash) (types.EventBalancesTransfer, error) + RetrieveEvent_FileBank_GenRestoralOrder(blockhash types.Hash) (Event_GenerateRestoralOrder, error) + RetrieveAllEvent_FileBank_UploadDeclaration(blockhash types.Hash) ([]AllUploadDeclarationEvent, error) + RetrieveAllEvent_FileBank_StorageCompleted(blockhash types.Hash) ([]string, error) + RetrieveAllEvent_FileBank_DeleteFile(blockhash types.Hash) ([]AllDeleteFileEvent, error) + RetrieveAllEventFromBlock(blockhash types.Hash) ([]string, map[string][]string, error) + RetrieveBlock(blocknumber uint64) ([]string, []ExtrinsicsInfo, []TransferInfo, string, string, string, string, int64, error) + RetrieveBlockAndAll(blocknumber uint64) ([]string, []ExtrinsicsInfo, []TransferInfo, []string, []string, string, string, string, string, string, int64, error) + ParseBlockData(blocknumber uint64) (BlockData, error) +} diff --git a/chain/deoss.go b/chain/deoss.go index b86ff3d..b07ca34 100755 --- a/chain/deoss.go +++ b/chain/deoss.go @@ -13,7 +13,7 @@ import ( "strings" "time" - "github.com/CESSProject/cess-go-sdk/core/pattern" + "github.com/CESSProject/cess-go-sdk/config" "github.com/CESSProject/cess-go-sdk/utils" "github.com/centrifuge/go-substrate-rpc-client/v4/types" "github.com/centrifuge/go-substrate-rpc-client/v4/types/codec" @@ -21,67 +21,108 @@ import ( "github.com/pkg/errors" ) -func (c *ChainClient) QueryDeOSSInfo(accountID []byte) (pattern.OssInfo, error) { +// QueryOss query oss info +// - accountID: oss's account +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - OssInfo: oss info +// - error: error message +func (c *ChainClient) QueryOss(accountID []byte, block int32) (OssInfo, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - var data pattern.OssInfo + var data OssInfo - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return data, ERR_RPC_CONNECTION } - key, err := types.CreateStorageKey(c.metadata, pattern.OSS, pattern.OSS, accountID) + key, err := types.CreateStorageKey(c.metadata, Oss, Oss, accountID) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.OSS, pattern.OSS, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), Oss, Oss, err) return data, err } - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Oss, Oss, err) + c.SetRpcState(false) + return data, err + } + if !ok { + return data, ERR_RPC_EMPTY_VALUE + } + return data, nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.OSS, pattern.OSS, err) - c.SetChainState(false) + return data, err + } + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), Oss, Oss, err) + c.SetRpcState(false) return data, err } if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE + return data, ERR_RPC_EMPTY_VALUE } return data, nil } -func (c *ChainClient) QueryAllDeOSSInfo() ([]pattern.OssInfo, error) { +// QueryAllOss query all oss info +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - []OssInfo: all oss info +// - error: error message +func (c *ChainClient) QueryAllOss(block int32) ([]OssInfo, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - var result []pattern.OssInfo + var result []OssInfo - if !c.GetChainState() { - return nil, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return nil, ERR_RPC_CONNECTION } - key := createPrefixedKey(pattern.OSS, pattern.OSS) + key := CreatePrefixedKey(Oss, Oss) keys, err := c.api.RPC.State.GetKeysLatest(key) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetKeysLatest: %v", c.GetCurrentRpcAddr(), pattern.OSS, pattern.OSS, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetKeysLatest: %v", c.GetCurrentRpcAddr(), Oss, Oss, err) + c.SetRpcState(false) return nil, err } - set, err := c.api.RPC.State.QueryStorageAtLatest(keys) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAtLatest: %v", c.GetCurrentRpcAddr(), pattern.OSS, pattern.OSS, err) - c.SetChainState(false) - return nil, err + var set []types.StorageChangeSet + if block < 0 { + set, err = c.api.RPC.State.QueryStorageAtLatest(keys) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAtLatest: %v", c.GetCurrentRpcAddr(), Oss, Oss, err) + c.SetRpcState(false) + return nil, err + } + } else { + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + return nil, err + } + set, err = c.api.RPC.State.QueryStorageAt(keys, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAtLatest: %v", c.GetCurrentRpcAddr(), Oss, Oss, err) + c.SetRpcState(false) + return nil, err + } } - for _, elem := range set { for _, change := range elem.Changes { - var data pattern.OssInfo + var data OssInfo if err := codec.Decode(change.StorageData, &data); err != nil { continue } @@ -91,7 +132,13 @@ func (c *ChainClient) QueryAllDeOSSInfo() ([]pattern.OssInfo, error) { return result, nil } -func (c *ChainClient) QueryAllDeOSSPeerId() ([]string, error) { +// QueryAllOssPeerId query all oss's peer id +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - []string: all oss's peer id +// - error: error message +func (c *ChainClient) QueryAllOssPeerId(block int32) ([]string, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) @@ -99,28 +146,42 @@ func (c *ChainClient) QueryAllDeOSSPeerId() ([]string, error) { }() var result []string - if !c.GetChainState() { - return nil, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return nil, ERR_RPC_CONNECTION } - key := createPrefixedKey(pattern.OSS, pattern.OSS) + key := CreatePrefixedKey(Oss, Oss) keys, err := c.api.RPC.State.GetKeysLatest(key) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetKeysLatest: %v", c.GetCurrentRpcAddr(), pattern.OSS, pattern.OSS, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetKeysLatest: %v", c.GetCurrentRpcAddr(), Oss, Oss, err) + c.SetRpcState(false) return nil, err } - set, err := c.api.RPC.State.QueryStorageAtLatest(keys) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAtLatest: %v", c.GetCurrentRpcAddr(), pattern.OSS, pattern.OSS, err) - c.SetChainState(false) - return nil, err + var set []types.StorageChangeSet + if block < 0 { + set, err = c.api.RPC.State.QueryStorageAtLatest(keys) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAtLatest: %v", c.GetCurrentRpcAddr(), Oss, Oss, err) + c.SetRpcState(false) + return nil, err + } + } else { + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + return nil, err + } + set, err = c.api.RPC.State.QueryStorageAt(keys, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAtLatest: %v", c.GetCurrentRpcAddr(), Oss, Oss, err) + c.SetRpcState(false) + return nil, err + } } for _, elem := range set { for _, change := range elem.Changes { - var data pattern.OssInfo + var data OssInfo if err := codec.Decode(change.StorageData, &data); err != nil { continue } @@ -130,7 +191,14 @@ func (c *ChainClient) QueryAllDeOSSPeerId() ([]string, error) { return result, nil } -func (c *ChainClient) QueryAuthorizedAccountIDs(accountID []byte) ([]types.AccountID, error) { +// QueryAuthorityList query authorised all accounts +// - accountID: account to be queried +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - []types.AccountID: authorised all accounts +// - error: error message +func (c *ChainClient) QueryAuthorityList(accountID []byte, block int32) ([]types.AccountID, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) @@ -138,42 +206,54 @@ func (c *ChainClient) QueryAuthorizedAccountIDs(accountID []byte) ([]types.Accou }() var data []types.AccountID - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return data, ERR_RPC_CONNECTION } - key, err := types.CreateStorageKey(c.metadata, pattern.OSS, pattern.AUTHORITYLIST, accountID) + key, err := types.CreateStorageKey(c.metadata, Oss, AuthorityList, accountID) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.OSS, pattern.AUTHORITYLIST, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), Oss, AuthorityList, err) return data, err } - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Oss, AuthorityList, err) + c.SetRpcState(false) + return data, err + } + if !ok { + return data, ERR_RPC_EMPTY_VALUE + } + return data, nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.OSS, pattern.AUTHORITYLIST, err) - c.SetChainState(false) return data, err } - if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE - } - return data, nil -} - -func (c *ChainClient) QueryAuthorizedAccounts(accountID []byte) ([]string, error) { - acc, err := c.QueryAuthorizedAccountIDs(accountID) + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) if err != nil { - return nil, err + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), Oss, AuthorityList, err) + c.SetRpcState(false) + return data, err } - var result = make([]string, len(acc)) - for k, v := range acc { - result[k], _ = utils.EncodePublicKeyAsCessAccount(v[:]) + if !ok { + return data, ERR_RPC_EMPTY_VALUE } - return result, nil + return data, nil } -func (c *ChainClient) RegisterDeOSS(peerId []byte, domain string) (string, error) { +// Authorize to authorise space usage to another account +// - accountID: authorised account +// +// Return: +// - string: block hash +// - error: error message +// +// Node: +// - accountID should be oss account +func (c *ChainClient) Authorize(accountID []byte) (string, error) { c.lock.Lock() defer func() { c.lock.Unlock() @@ -183,63 +263,41 @@ func (c *ChainClient) RegisterDeOSS(peerId []byte, domain string) (string, error }() var ( - err error - txhash string - call types.Call + blockhash string accountInfo types.AccountInfo ) - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION } - var peerid pattern.PeerId - if len(peerid) != len(peerId) { - return txhash, errors.New("register deoss: invalid peerid") - } - for i := 0; i < len(peerid); i++ { - peerid[i] = types.U8(peerId[i]) - } - - if len(domain) > pattern.MaxDomainNameLength { - return txhash, fmt.Errorf("register deoss: Domain name length cannot exceed %v characters", pattern.MaxDomainNameLength) - } - - err = utils.CheckDomain(domain) + acc, err := types.NewAccountID(accountID) if err != nil { - return txhash, errors.New("register deoss: invalid domain") + return blockhash, errors.Wrap(err, "[NewAccountID]") } - call, err = types.NewCall(c.metadata, pattern.TX_OSS_REGISTER, peerid, types.NewBytes([]byte(domain))) + call, err := types.NewCall(c.metadata, TX_Oss_Authorize, *acc) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_REGISTER, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_Oss_Authorize, err) + return blockhash, err } ext := types.NewExtrinsic(call) - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_REGISTER, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_Oss_Authorize, err) + return blockhash, err } ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_REGISTER, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_Oss_Authorize, err) + c.SetRpcState(false) + return blockhash, err } - if !ok { - keyStr, _ := utils.NumsToByteStr(key, map[string]bool{}) - return txhash, fmt.Errorf( - "chain rpc.state.GetStorageLatest[%v]: %v", - keyStr, - pattern.ERR_RPC_EMPTY_VALUE, - ) + return blockhash, ERR_RPC_EMPTY_VALUE } o := types.SignatureOptions{ @@ -255,30 +313,32 @@ func (c *ChainClient) RegisterDeOSS(peerId []byte, domain string) (string, error // Sign the transaction err = ext.Sign(c.keyring, o) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_REGISTER, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_Oss_Authorize, err) + return blockhash, err } + <-c.txTicker.C + // Do the transfer and track the actual status sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) err = ext.Sign(c.keyring, o) if err != nil { - return txhash, errors.Wrap(err, "[Sign]") + return blockhash, errors.Wrap(err, "[Sign]") } + <-c.txTicker.C sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_REGISTER, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Oss_Authorize, err) + c.SetRpcState(false) + return blockhash, err } } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_REGISTER, err) - c.SetChainState(false) - return txhash, errors.Wrap(err, "[SubmitAndWatchExtrinsic]") + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Oss_Authorize, err) + c.SetRpcState(false) + return blockhash, err } } defer sub.Unsubscribe() @@ -290,19 +350,25 @@ func (c *ChainClient) RegisterDeOSS(peerId []byte, domain string) (string, error select { case status := <-sub.Chan(): if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_Oss_OssRegister(status.AsInBlock) - return txhash, err + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_Oss_Authorize(status.AsInBlock) + return blockhash, err } case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") + return blockhash, errors.Wrap(err, "[sub]") case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT + return blockhash, ERR_RPC_TIMEOUT } } } -func (c *ChainClient) UpdateDeOSS(peerId string, domain string) (string, error) { +// CancelAuthorize cancels authorisation for an account +// - accountID: account with cancelled authorisations +// +// Return: +// - string: block hash +// - error: error message +func (c *ChainClient) CancelAuthorize(accountID []byte) (string, error) { c.lock.Lock() defer func() { c.lock.Unlock() @@ -312,56 +378,36 @@ func (c *ChainClient) UpdateDeOSS(peerId string, domain string) (string, error) }() var ( - err error - txhash string - call types.Call + blockhash string accountInfo types.AccountInfo ) - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION } - var peerid pattern.PeerId - if len(peerid) != len(peerId) { - return txhash, errors.New("update deoss: invalid peerid") - } - for i := 0; i < len(peerid); i++ { - peerid[i] = types.U8(peerId[i]) - } - - if len(domain) > pattern.MaxSubmitedIdleFileMeta { - return txhash, fmt.Errorf("register deoss: domain name length cannot exceed %v", pattern.MaxSubmitedIdleFileMeta) - } - - err = utils.CheckDomain(domain) + call, err := types.NewCall(c.metadata, TX_Oss_CancelAuthorize, accountID) if err != nil { - return txhash, errors.New("register deoss: invalid domain name") - } - - call, err = types.NewCall(c.metadata, pattern.TX_OSS_UPDATE, peerid, types.NewBytes([]byte(domain))) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_UPDATE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_Oss_CancelAuthorize, err) + return blockhash, err } ext := types.NewExtrinsic(call) - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_UPDATE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_Oss_CancelAuthorize, err) + return blockhash, err } + ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_UPDATE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_Oss_CancelAuthorize, err) + c.SetRpcState(false) + return blockhash, err } if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE + return blockhash, ERR_RPC_EMPTY_VALUE } o := types.SignatureOptions{ @@ -377,9 +423,8 @@ func (c *ChainClient) UpdateDeOSS(peerId string, domain string) (string, error) // Sign the transaction err = ext.Sign(c.keyring, o) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_UPDATE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_Oss_CancelAuthorize, err) + return blockhash, err } <-c.txTicker.C @@ -387,44 +432,54 @@ func (c *ChainClient) UpdateDeOSS(peerId string, domain string) (string, error) // Do the transfer and track the actual status sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) err = ext.Sign(c.keyring, o) if err != nil { - return txhash, errors.Wrap(err, "[Sign]") + return blockhash, errors.Wrap(err, "[Sign]") } + <-c.txTicker.C sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_UPDATE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Oss_CancelAuthorize, err) + c.SetRpcState(false) + return blockhash, err } } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_UPDATE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Oss_CancelAuthorize, err) + c.SetRpcState(false) + return blockhash, err } } defer sub.Unsubscribe() + timeout := time.NewTimer(c.packingTime) defer timeout.Stop() + for { select { case status := <-sub.Chan(): if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_Oss_OssUpdate(status.AsInBlock) - return txhash, err + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_Oss_CancelAuthorize(status.AsInBlock) + return blockhash, err } case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") + return blockhash, errors.Wrap(err, "[sub]") case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT + return blockhash, ERR_RPC_TIMEOUT } } } -func (c *ChainClient) ExitDeOSS() (string, error) { +// RegisterOss registered as oss role +// - peerId: peer id +// - domain: domain name, can be empty +// +// Return: +// - string: block hash +// - error: error message +func (c *ChainClient) RegisterOss(peerId []byte, domain string) (string, error) { c.lock.Lock() defer func() { c.lock.Unlock() @@ -434,41 +489,59 @@ func (c *ChainClient) ExitDeOSS() (string, error) { }() var ( - err error - txhash string - call types.Call + blockhash string accountInfo types.AccountInfo ) - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION + } + + var peerid PeerId + if len(peerId) != PeerIdPublicKeyLen { + return blockhash, errors.New("register oss: invalid peerid") + } + for i := 0; i < len(peerid); i++ { + peerid[i] = types.U8(peerId[i]) + } + + if len(domain) > config.MaxDomainNameLength { + return blockhash, fmt.Errorf("register deoss: Domain name length cannot exceed %v characters", config.MaxDomainNameLength) + } + + err := utils.CheckDomain(domain) + if err != nil { + return blockhash, errors.New("register oss: invalid domain") } - call, err = types.NewCall(c.metadata, pattern.TX_OSS_DESTROY) + call, err := types.NewCall(c.metadata, TX_Oss_Register, peerid, types.NewBytes([]byte(domain))) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_DESTROY, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_Oss_Register, err) + return blockhash, err } ext := types.NewExtrinsic(call) - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_DESTROY, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_Oss_Register, err) + return blockhash, err } ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_DESTROY, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_Oss_Register, err) + c.SetRpcState(false) + return blockhash, err } if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE + keyStr, _ := utils.NumsToByteStr(key, map[string]bool{}) + return blockhash, fmt.Errorf( + "chain rpc.state.GetStorageLatest[%v]: %v", + keyStr, + ERR_RPC_EMPTY_VALUE, + ) } o := types.SignatureOptions{ @@ -484,9 +557,8 @@ func (c *ChainClient) ExitDeOSS() (string, error) { // Sign the transaction err = ext.Sign(c.keyring, o) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_DESTROY, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_Oss_Register, err) + return blockhash, err } <-c.txTicker.C @@ -494,22 +566,23 @@ func (c *ChainClient) ExitDeOSS() (string, error) { // Do the transfer and track the actual status sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) err = ext.Sign(c.keyring, o) if err != nil { - return txhash, errors.Wrap(err, "[Sign]") + return blockhash, errors.Wrap(err, "[Sign]") } + <-c.txTicker.C sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_DESTROY, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Oss_Register, err) + c.SetRpcState(false) + return blockhash, err } } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_DESTROY, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Oss_Register, err) + c.SetRpcState(false) + return blockhash, errors.Wrap(err, "[SubmitAndWatchExtrinsic]") } } defer sub.Unsubscribe() @@ -521,19 +594,26 @@ func (c *ChainClient) ExitDeOSS() (string, error) { select { case status := <-sub.Chan(): if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_Oss_OssDestroy(status.AsInBlock) - return txhash, err + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_Oss_OssRegister(status.AsInBlock) + return blockhash, err } case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") + return blockhash, errors.Wrap(err, "[sub]") case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT + return blockhash, ERR_RPC_TIMEOUT } } } -func (c *ChainClient) AuthorizeSpace(ossAccount string) (string, error) { +// UpdateOss update oss's peerId or domain +// - peerId: peer id +// - domain: domain name +// +// Return: +// - string: block hash +// - error: error message +func (c *ChainClient) UpdateOss(peerId string, domain string) (string, error) { c.lock.Lock() defer func() { c.lock.Unlock() @@ -543,61 +623,53 @@ func (c *ChainClient) AuthorizeSpace(ossAccount string) (string, error) { }() var ( - txhash string + blockhash string accountInfo types.AccountInfo ) - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION } - puk, err := utils.ParsingPublickey(ossAccount) - if err != nil { - return txhash, errors.Wrap(err, "[ParsingPublickey]") + var peerid PeerId + if len(peerid) != len(peerId) { + return blockhash, errors.New("update oss: invalid peerid") + } + for i := 0; i < len(peerid); i++ { + peerid[i] = types.U8(peerId[i]) } - acc, err := types.NewAccountID(puk) - if err != nil { - return txhash, errors.Wrap(err, "[NewAccountID]") + if len(domain) > config.MaxDomainNameLength { + return blockhash, fmt.Errorf("update oss: domain name length cannot exceed %v", config.MaxDomainNameLength) } - list, err := c.QueryAuthorizedAccounts(c.GetSignatureAccPulickey()) + err := utils.CheckDomain(domain) if err != nil { - if err.Error() != pattern.ERR_Empty { - return txhash, errors.Wrap(err, "[QueryAuthorizedAccounts]") - } - } else { - for _, v := range list { - if v == ossAccount { - return "", nil - } - } + return blockhash, errors.New("update oss: invalid domain name") } - call, err := types.NewCall(c.metadata, pattern.TX_OSS_AUTHORIZE, *acc) + call, err := types.NewCall(c.metadata, TX_Oss_Update, peerid, types.NewBytes([]byte(domain))) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_AUTHORIZE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_Oss_Update, err) + return blockhash, err } ext := types.NewExtrinsic(call) - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_AUTHORIZE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_Oss_Update, err) + return blockhash, err } ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_AUTHORIZE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_Oss_Update, err) + c.SetRpcState(false) + return blockhash, err } if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE + return blockhash, ERR_RPC_EMPTY_VALUE } o := types.SignatureOptions{ @@ -613,9 +685,8 @@ func (c *ChainClient) AuthorizeSpace(ossAccount string) (string, error) { // Sign the transaction err = ext.Sign(c.keyring, o) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_AUTHORIZE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_Oss_Update, err) + return blockhash, err } <-c.txTicker.C @@ -623,46 +694,50 @@ func (c *ChainClient) AuthorizeSpace(ossAccount string) (string, error) { // Do the transfer and track the actual status sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) err = ext.Sign(c.keyring, o) if err != nil { - return txhash, errors.Wrap(err, "[Sign]") + return blockhash, errors.Wrap(err, "[Sign]") } + <-c.txTicker.C sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_AUTHORIZE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Oss_Update, err) + c.SetRpcState(false) + return blockhash, err } } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_AUTHORIZE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Oss_Update, err) + c.SetRpcState(false) + return blockhash, err } } defer sub.Unsubscribe() - timeout := time.NewTimer(c.packingTime) defer timeout.Stop() - for { select { case status := <-sub.Chan(): if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_Oss_Authorize(status.AsInBlock) - return txhash, err + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_Oss_OssUpdate(status.AsInBlock) + return blockhash, err } case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") + return blockhash, errors.Wrap(err, "[sub]") case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT + return blockhash, ERR_RPC_TIMEOUT } } } -func (c *ChainClient) UnAuthorizeSpace(oss_acc string) (string, error) { +// DestroyOss destroys the oss role of the current account +// +// Return: +// - string: block hash +// - error: error message +func (c *ChainClient) DestroyOss() (string, error) { c.lock.Lock() defer func() { c.lock.Unlock() @@ -672,43 +747,37 @@ func (c *ChainClient) UnAuthorizeSpace(oss_acc string) (string, error) { }() var ( - txhash string + blockhash string accountInfo types.AccountInfo ) - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION } - pubkey, err := utils.ParsingPublickey(oss_acc) + call, err := types.NewCall(c.metadata, TX_Oss_Destroy) if err != nil { - return txhash, errors.Wrap(err, "[ParsingPublickey]") - } - - call, err := types.NewCall(c.metadata, pattern.TX_OSS_UNAUTHORIZE) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_AUTHORIZE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_Oss_Destroy, err) + return blockhash, err } ext := types.NewExtrinsic(call) - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, pubkey) + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_AUTHORIZE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_Oss_Destroy, err) + return blockhash, err } ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_AUTHORIZE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_Oss_Destroy, err) + c.SetRpcState(false) + return blockhash, err } + if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE + return blockhash, ERR_RPC_EMPTY_VALUE } o := types.SignatureOptions{ @@ -724,9 +793,8 @@ func (c *ChainClient) UnAuthorizeSpace(oss_acc string) (string, error) { // Sign the transaction err = ext.Sign(c.keyring, o) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_AUTHORIZE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_Oss_Destroy, err) + return blockhash, err } <-c.txTicker.C @@ -734,22 +802,23 @@ func (c *ChainClient) UnAuthorizeSpace(oss_acc string) (string, error) { // Do the transfer and track the actual status sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) err = ext.Sign(c.keyring, o) if err != nil { - return txhash, errors.Wrap(err, "[Sign]") + return blockhash, errors.Wrap(err, "[Sign]") } + <-c.txTicker.C sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_AUTHORIZE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Oss_Destroy, err) + c.SetRpcState(false) + return blockhash, err } } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_OSS_AUTHORIZE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Oss_Destroy, err) + c.SetRpcState(false) + return blockhash, err } } defer sub.Unsubscribe() @@ -761,14 +830,14 @@ func (c *ChainClient) UnAuthorizeSpace(oss_acc string) (string, error) { select { case status := <-sub.Chan(): if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_Oss_CancelAuthorize(status.AsInBlock) - return txhash, err + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_Oss_OssDestroy(status.AsInBlock) + return blockhash, err } case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") + return blockhash, errors.Wrap(err, "[sub]") case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT + return blockhash, ERR_RPC_TIMEOUT } } } diff --git a/chain/event.go b/chain/event.go index 188dd68..9680b4b 100755 --- a/chain/event.go +++ b/chain/event.go @@ -15,8 +15,6 @@ import ( "strconv" "strings" - "github.com/CESSProject/cess-go-sdk/core/event" - "github.com/CESSProject/cess-go-sdk/core/pattern" "github.com/CESSProject/cess-go-sdk/utils" "github.com/centrifuge/go-substrate-rpc-client/v4/registry/parser" "github.com/centrifuge/go-substrate-rpc-client/v4/types" @@ -57,14 +55,14 @@ func (c *ChainClient) DecodeEventNameFromBlockhash(blockhash types.Hash) ([]stri return result, nil } -func (c *ChainClient) RetrieveEvent_FileBank_ClaimRestoralOrder(blockhash types.Hash) (event.Event_ClaimRestoralOrder, error) { - var result event.Event_ClaimRestoralOrder +func (c *ChainClient) RetrieveEvent_FileBank_ClaimRestoralOrder(blockhash types.Hash) (Event_ClaimRestoralOrder, error) { + var result Event_ClaimRestoralOrder events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.FileBankClaimRestoralOrder { + if e.Name == FileBankClaimRestoralOrder { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -102,17 +100,17 @@ func (c *ChainClient) RetrieveEvent_FileBank_ClaimRestoralOrder(blockhash types. } } } - return result, errors.Errorf("failed: no %s event found", event.FileBankClaimRestoralOrder) + return result, errors.Errorf("failed: no %s event found", FileBankClaimRestoralOrder) } -func (c *ChainClient) RetrieveEvent_Audit_SubmitIdleProof(blockhash types.Hash) (event.Event_SubmitIdleProof, error) { - var result event.Event_SubmitIdleProof +func (c *ChainClient) RetrieveEvent_Audit_SubmitIdleProof(blockhash types.Hash) (Event_SubmitIdleProof, error) { + var result Event_SubmitIdleProof events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.AuditSubmitIdleProof { + if e.Name == AuditSubmitIdleProof { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -150,17 +148,17 @@ func (c *ChainClient) RetrieveEvent_Audit_SubmitIdleProof(blockhash types.Hash) } } } - return result, errors.Errorf("failed: no %s event found", event.AuditSubmitIdleProof) + return result, errors.Errorf("failed: no %s event found", AuditSubmitIdleProof) } -func (c *ChainClient) RetrieveEvent_Audit_SubmitServiceProof(blockhash types.Hash) (event.Event_SubmitServiceProof, error) { - var result event.Event_SubmitServiceProof +func (c *ChainClient) RetrieveEvent_Audit_SubmitServiceProof(blockhash types.Hash) (Event_SubmitServiceProof, error) { + var result Event_SubmitServiceProof events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.AuditSubmitServiceProof { + if e.Name == AuditSubmitServiceProof { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -198,17 +196,17 @@ func (c *ChainClient) RetrieveEvent_Audit_SubmitServiceProof(blockhash types.Has } } } - return result, errors.Errorf("failed: no %s event found", event.AuditSubmitServiceProof) + return result, errors.Errorf("failed: no %s event found", AuditSubmitServiceProof) } -func (c *ChainClient) RetrieveEvent_Audit_SubmitIdleVerifyResult(blockhash types.Hash) (event.Event_SubmitIdleVerifyResult, error) { - var result event.Event_SubmitIdleVerifyResult +func (c *ChainClient) RetrieveEvent_Audit_SubmitIdleVerifyResult(blockhash types.Hash) (Event_SubmitIdleVerifyResult, error) { + var result Event_SubmitIdleVerifyResult events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.AuditSubmitIdleVerifyResult { + if e.Name == AuditSubmitIdleVerifyResult { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -245,17 +243,17 @@ func (c *ChainClient) RetrieveEvent_Audit_SubmitIdleVerifyResult(blockhash types } } } - return result, errors.Errorf("failed: no %s event found", event.AuditSubmitIdleVerifyResult) + return result, errors.Errorf("failed: no %s event found", AuditSubmitIdleVerifyResult) } -func (c *ChainClient) RetrieveEvent_Audit_SubmitServiceVerifyResult(blockhash types.Hash) (event.Event_SubmitServiceVerifyResult, error) { - var result event.Event_SubmitServiceVerifyResult +func (c *ChainClient) RetrieveEvent_Audit_SubmitServiceVerifyResult(blockhash types.Hash) (Event_SubmitServiceVerifyResult, error) { + var result Event_SubmitServiceVerifyResult events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.AuditSubmitServiceVerifyResult { + if e.Name == AuditSubmitServiceVerifyResult { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -292,17 +290,17 @@ func (c *ChainClient) RetrieveEvent_Audit_SubmitServiceVerifyResult(blockhash ty } } } - return result, errors.Errorf("failed: no %s event found", event.AuditSubmitServiceVerifyResult) + return result, errors.Errorf("failed: no %s event found", AuditSubmitServiceVerifyResult) } -func (c *ChainClient) RetrieveEvent_Oss_OssUpdate(blockhash types.Hash) (event.Event_OssUpdate, error) { - var result event.Event_OssUpdate +func (c *ChainClient) RetrieveEvent_Oss_OssUpdate(blockhash types.Hash) (Event_OssUpdate, error) { + var result Event_OssUpdate events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.OssOssUpdate { + if e.Name == OssOssUpdate { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -339,17 +337,17 @@ func (c *ChainClient) RetrieveEvent_Oss_OssUpdate(blockhash types.Hash) (event.E } } } - return result, errors.Errorf("failed: no %s event found", event.OssOssUpdate) + return result, errors.Errorf("failed: no %s event found", OssOssUpdate) } -func (c *ChainClient) RetrieveEvent_Oss_OssRegister(blockhash types.Hash) (event.Event_OssRegister, error) { - var result event.Event_OssRegister +func (c *ChainClient) RetrieveEvent_Oss_OssRegister(blockhash types.Hash) (Event_OssRegister, error) { + var result Event_OssRegister events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.OssOssRegister { + if e.Name == OssOssRegister { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -386,17 +384,17 @@ func (c *ChainClient) RetrieveEvent_Oss_OssRegister(blockhash types.Hash) (event } } } - return result, errors.Errorf("failed: no %s event found", event.OssOssRegister) + return result, errors.Errorf("failed: no %s event found", OssOssRegister) } -func (c *ChainClient) RetrieveEvent_Oss_OssDestroy(blockhash types.Hash) (event.Event_OssDestroy, error) { - var result event.Event_OssDestroy +func (c *ChainClient) RetrieveEvent_Oss_OssDestroy(blockhash types.Hash) (Event_OssDestroy, error) { + var result Event_OssDestroy events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.OssOssDestroy { + if e.Name == OssOssDestroy { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -433,17 +431,17 @@ func (c *ChainClient) RetrieveEvent_Oss_OssDestroy(blockhash types.Hash) (event. } } } - return result, errors.Errorf("failed: no %s event found", event.OssOssDestroy) + return result, errors.Errorf("failed: no %s event found", OssOssDestroy) } -func (c *ChainClient) RetrieveEvent_Oss_Authorize(blockhash types.Hash) (event.Event_Authorize, error) { - var result event.Event_Authorize +func (c *ChainClient) RetrieveEvent_Oss_Authorize(blockhash types.Hash) (Event_Authorize, error) { + var result Event_Authorize events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.OssAuthorize { + if e.Name == OssAuthorize { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -480,17 +478,17 @@ func (c *ChainClient) RetrieveEvent_Oss_Authorize(blockhash types.Hash) (event.E } } } - return result, errors.Errorf("failed: no %s event found", event.OssAuthorize) + return result, errors.Errorf("failed: no %s event found", OssAuthorize) } -func (c *ChainClient) RetrieveEvent_Oss_CancelAuthorize(blockhash types.Hash) (event.Event_CancelAuthorize, error) { - var result event.Event_CancelAuthorize +func (c *ChainClient) RetrieveEvent_Oss_CancelAuthorize(blockhash types.Hash) (Event_CancelAuthorize, error) { + var result Event_CancelAuthorize events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.OssCancelAuthorize { + if e.Name == OssCancelAuthorize { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -527,17 +525,17 @@ func (c *ChainClient) RetrieveEvent_Oss_CancelAuthorize(blockhash types.Hash) (e } } } - return result, errors.Errorf("failed: no %s event found", event.OssCancelAuthorize) + return result, errors.Errorf("failed: no %s event found", OssCancelAuthorize) } -func (c *ChainClient) RetrieveEvent_FileBank_UploadDeclaration(blockhash types.Hash) (event.Event_UploadDeclaration, error) { - var result event.Event_UploadDeclaration +func (c *ChainClient) RetrieveEvent_FileBank_UploadDeclaration(blockhash types.Hash) (Event_UploadDeclaration, error) { + var result Event_UploadDeclaration events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.FileBankUploadDeclaration { + if e.Name == FileBankUploadDeclaration { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -574,17 +572,17 @@ func (c *ChainClient) RetrieveEvent_FileBank_UploadDeclaration(blockhash types.H } } } - return result, errors.Errorf("failed: no %s event found", event.FileBankUploadDeclaration) + return result, errors.Errorf("failed: no %s event found", FileBankUploadDeclaration) } -func (c *ChainClient) RetrieveEvent_FileBank_CreateBucket(blockhash types.Hash) (event.Event_CreateBucket, error) { - var result event.Event_CreateBucket +func (c *ChainClient) RetrieveEvent_FileBank_CreateBucket(blockhash types.Hash) (Event_CreateBucket, error) { + var result Event_CreateBucket events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.FileBankCreateBucket { + if e.Name == FileBankCreateBucket { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -621,17 +619,17 @@ func (c *ChainClient) RetrieveEvent_FileBank_CreateBucket(blockhash types.Hash) } } } - return result, errors.Errorf("failed: no %s event found", event.FileBankCreateBucket) + return result, errors.Errorf("failed: no %s event found", FileBankCreateBucket) } -func (c *ChainClient) RetrieveEvent_FileBank_DeleteBucket(blockhash types.Hash) (event.Event_DeleteBucket, error) { - var result event.Event_DeleteBucket +func (c *ChainClient) RetrieveEvent_FileBank_DeleteBucket(blockhash types.Hash) (Event_DeleteBucket, error) { + var result Event_DeleteBucket events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.FileBankDeleteBucket { + if e.Name == FileBankDeleteBucket { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -668,17 +666,17 @@ func (c *ChainClient) RetrieveEvent_FileBank_DeleteBucket(blockhash types.Hash) } } } - return result, errors.Errorf("failed: no %s event found", event.FileBankDeleteBucket) + return result, errors.Errorf("failed: no %s event found", FileBankDeleteBucket) } -func (c *ChainClient) RetrieveEvent_FileBank_DeleteFile(blockhash types.Hash) (event.Event_DeleteFile, error) { - var result event.Event_DeleteFile +func (c *ChainClient) RetrieveEvent_FileBank_DeleteFile(blockhash types.Hash) (Event_DeleteFile, error) { + var result Event_DeleteFile events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.FileBankDeleteFile { + if e.Name == FileBankDeleteFile { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -715,17 +713,17 @@ func (c *ChainClient) RetrieveEvent_FileBank_DeleteFile(blockhash types.Hash) (e } } } - return result, errors.Errorf("failed: no %s event found", event.FileBankDeleteFile) + return result, errors.Errorf("failed: no %s event found", FileBankDeleteFile) } -func (c *ChainClient) RetrieveEvent_FileBank_TransferReport(blockhash types.Hash) (event.Event_TransferReport, error) { - var result event.Event_TransferReport +func (c *ChainClient) RetrieveEvent_FileBank_TransferReport(blockhash types.Hash) (Event_TransferReport, error) { + var result Event_TransferReport events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.FileBankTransferReport { + if e.Name == FileBankTransferReport { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -762,17 +760,17 @@ func (c *ChainClient) RetrieveEvent_FileBank_TransferReport(blockhash types.Hash } } } - return result, errors.Errorf("failed: no %s event found", event.FileBankTransferReport) + return result, errors.Errorf("failed: no %s event found", FileBankTransferReport) } -func (c *ChainClient) RetrieveEvent_FileBank_RecoveryCompleted(blockhash types.Hash) (event.Event_RecoveryCompleted, error) { - var result event.Event_RecoveryCompleted +func (c *ChainClient) RetrieveEvent_FileBank_RecoveryCompleted(blockhash types.Hash) (Event_RecoveryCompleted, error) { + var result Event_RecoveryCompleted events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.FileBankRecoveryCompleted { + if e.Name == FileBankRecoveryCompleted { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -809,17 +807,17 @@ func (c *ChainClient) RetrieveEvent_FileBank_RecoveryCompleted(blockhash types.H } } } - return result, errors.Errorf("failed: no %s event found", event.FileBankRecoveryCompleted) + return result, errors.Errorf("failed: no %s event found", FileBankRecoveryCompleted) } -func (c *ChainClient) RetrieveEvent_FileBank_IdleSpaceCert(blockhash types.Hash) (event.Event_IdleSpaceCert, error) { - var result event.Event_IdleSpaceCert +func (c *ChainClient) RetrieveEvent_FileBank_IdleSpaceCert(blockhash types.Hash) (Event_IdleSpaceCert, error) { + var result Event_IdleSpaceCert events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.FileBankIdleSpaceCert { + if e.Name == FileBankIdleSpaceCert { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -856,17 +854,17 @@ func (c *ChainClient) RetrieveEvent_FileBank_IdleSpaceCert(blockhash types.Hash) } } } - return result, errors.Errorf("failed: no %s event found", event.FileBankIdleSpaceCert) + return result, errors.Errorf("failed: no %s event found", FileBankIdleSpaceCert) } -func (c *ChainClient) RetrieveEvent_FileBank_ReplaceIdleSpace(blockhash types.Hash) (event.Event_ReplaceIdleSpace, error) { - var result event.Event_ReplaceIdleSpace +func (c *ChainClient) RetrieveEvent_FileBank_ReplaceIdleSpace(blockhash types.Hash) (Event_ReplaceIdleSpace, error) { + var result Event_ReplaceIdleSpace events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.FileBankReplaceIdleSpace { + if e.Name == FileBankReplaceIdleSpace { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -903,17 +901,17 @@ func (c *ChainClient) RetrieveEvent_FileBank_ReplaceIdleSpace(blockhash types.Ha } } } - return result, errors.Errorf("failed: no %s event found", event.FileBankReplaceIdleSpace) + return result, errors.Errorf("failed: no %s event found", FileBankReplaceIdleSpace) } -func (c *ChainClient) RetrieveEvent_FileBank_CalculateReport(blockhash types.Hash) (event.Event_CalculateReport, error) { - var result event.Event_CalculateReport +func (c *ChainClient) RetrieveEvent_FileBank_CalculateReport(blockhash types.Hash) (Event_CalculateReport, error) { + var result Event_CalculateReport events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.FileBankCalculateReport { + if e.Name == FileBankCalculateReport { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -950,17 +948,17 @@ func (c *ChainClient) RetrieveEvent_FileBank_CalculateReport(blockhash types.Has } } } - return result, errors.Errorf("failed: no %s event found", event.FileBankCalculateReport) + return result, errors.Errorf("failed: no %s event found", FileBankCalculateReport) } -func (c *ChainClient) RetrieveEvent_Sminer_UpdataIp(blockhash types.Hash) (event.Event_UpdatePeerId, error) { - var result event.Event_UpdatePeerId +func (c *ChainClient) RetrieveEvent_Sminer_UpdataIp(blockhash types.Hash) (Event_UpdatePeerId, error) { + var result Event_UpdatePeerId events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.SminerUpdatePeerId { + if e.Name == SminerUpdatePeerId { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -997,17 +995,17 @@ func (c *ChainClient) RetrieveEvent_Sminer_UpdataIp(blockhash types.Hash) (event } } } - return result, errors.Errorf("failed: no %s event found", event.SminerUpdatePeerId) + return result, errors.Errorf("failed: no %s event found", SminerUpdatePeerId) } -func (c *ChainClient) RetrieveEvent_Sminer_UpdataBeneficiary(blockhash types.Hash) (event.Event_UpdateBeneficiary, error) { - var result event.Event_UpdateBeneficiary +func (c *ChainClient) RetrieveEvent_Sminer_UpdataBeneficiary(blockhash types.Hash) (Event_UpdateBeneficiary, error) { + var result Event_UpdateBeneficiary events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.SminerUpdateBeneficiary { + if e.Name == SminerUpdateBeneficiary { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -1044,17 +1042,17 @@ func (c *ChainClient) RetrieveEvent_Sminer_UpdataBeneficiary(blockhash types.Has } } } - return result, errors.Errorf("failed: no %s event found", event.SminerUpdateBeneficiary) + return result, errors.Errorf("failed: no %s event found", SminerUpdateBeneficiary) } -func (c *ChainClient) RetrieveEvent_Sminer_Registered(blockhash types.Hash) (event.Event_Registered, error) { - var result event.Event_Registered +func (c *ChainClient) RetrieveEvent_Sminer_Registered(blockhash types.Hash) (Event_Registered, error) { + var result Event_Registered events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.SminerRegistered { + if e.Name == SminerRegistered { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -1091,17 +1089,17 @@ func (c *ChainClient) RetrieveEvent_Sminer_Registered(blockhash types.Hash) (eve } } } - return result, errors.Errorf("failed: no %s event found", event.SminerRegistered) + return result, errors.Errorf("failed: no %s event found", SminerRegistered) } -func (c *ChainClient) RetrieveEvent_Sminer_RegisterPoisKey(blockhash types.Hash) (event.Event_RegisterPoisKey, error) { - var result event.Event_RegisterPoisKey +func (c *ChainClient) RetrieveEvent_Sminer_RegisterPoisKey(blockhash types.Hash) (Event_RegisterPoisKey, error) { + var result Event_RegisterPoisKey events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.SminerRegisterPoisKey { + if e.Name == SminerRegisterPoisKey { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -1138,17 +1136,17 @@ func (c *ChainClient) RetrieveEvent_Sminer_RegisterPoisKey(blockhash types.Hash) } } } - return result, errors.Errorf("failed: no %s event found", event.SminerRegisterPoisKey) + return result, errors.Errorf("failed: no %s event found", SminerRegisterPoisKey) } -func (c *ChainClient) RetrieveEvent_Sminer_MinerExitPrep(blockhash types.Hash) (event.Event_MinerExitPrep, error) { - var result event.Event_MinerExitPrep +func (c *ChainClient) RetrieveEvent_Sminer_MinerExitPrep(blockhash types.Hash) (Event_MinerExitPrep, error) { + var result Event_MinerExitPrep events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.SminerMinerExitPrep { + if e.Name == SminerMinerExitPrep { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -1185,17 +1183,17 @@ func (c *ChainClient) RetrieveEvent_Sminer_MinerExitPrep(blockhash types.Hash) ( } } } - return result, errors.Errorf("failed: no %s event found", event.SminerMinerExitPrep) + return result, errors.Errorf("failed: no %s event found", SminerMinerExitPrep) } -func (c *ChainClient) RetrieveEvent_Sminer_IncreaseCollateral(blockhash types.Hash) (event.Event_IncreaseCollateral, error) { - var result event.Event_IncreaseCollateral +func (c *ChainClient) RetrieveEvent_Sminer_IncreaseCollateral(blockhash types.Hash) (Event_IncreaseCollateral, error) { + var result Event_IncreaseCollateral events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.SminerIncreaseCollateral { + if e.Name == SminerIncreaseCollateral { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -1232,17 +1230,17 @@ func (c *ChainClient) RetrieveEvent_Sminer_IncreaseCollateral(blockhash types.Ha } } } - return result, errors.Errorf("failed: no %s event found", event.SminerIncreaseCollateral) + return result, errors.Errorf("failed: no %s event found", SminerIncreaseCollateral) } -func (c *ChainClient) RetrieveEvent_Sminer_IncreaseDeclarationSpace(blockhash types.Hash) (event.Event_IncreaseDeclarationSpace, error) { - var result event.Event_IncreaseDeclarationSpace +func (c *ChainClient) RetrieveEvent_Sminer_IncreaseDeclarationSpace(blockhash types.Hash) (Event_IncreaseDeclarationSpace, error) { + var result Event_IncreaseDeclarationSpace events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.SminerIncreaseDeclarationSpace { + if e.Name == SminerIncreaseDeclarationSpace { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -1279,17 +1277,17 @@ func (c *ChainClient) RetrieveEvent_Sminer_IncreaseDeclarationSpace(blockhash ty } } } - return result, errors.Errorf("failed: no %s event found", event.SminerIncreaseDeclarationSpace) + return result, errors.Errorf("failed: no %s event found", SminerIncreaseDeclarationSpace) } -func (c *ChainClient) RetrieveEvent_Sminer_Receive(blockhash types.Hash) (event.Event_Receive, error) { - var result event.Event_Receive +func (c *ChainClient) RetrieveEvent_Sminer_Receive(blockhash types.Hash) (Event_Receive, error) { + var result Event_Receive events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.SminerReceive { + if e.Name == SminerReceive { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -1326,17 +1324,17 @@ func (c *ChainClient) RetrieveEvent_Sminer_Receive(blockhash types.Hash) (event. } } } - return result, errors.Errorf("failed: no %s event found", event.SminerReceive) + return result, errors.Errorf("failed: no %s event found", SminerReceive) } -func (c *ChainClient) RetrieveEvent_Sminer_Withdraw(blockhash types.Hash) (event.Event_Withdraw, error) { - var result event.Event_Withdraw +func (c *ChainClient) RetrieveEvent_Sminer_Withdraw(blockhash types.Hash) (Event_Withdraw, error) { + var result Event_Withdraw events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.SminerWithdraw { + if e.Name == SminerWithdraw { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -1373,17 +1371,17 @@ func (c *ChainClient) RetrieveEvent_Sminer_Withdraw(blockhash types.Hash) (event } } } - return result, errors.Errorf("failed: no %s event found", event.SminerWithdraw) + return result, errors.Errorf("failed: no %s event found", SminerWithdraw) } -func (c *ChainClient) RetrieveEvent_StorageHandler_BuySpace(blockhash types.Hash) (event.Event_BuySpace, error) { - var result event.Event_BuySpace +func (c *ChainClient) RetrieveEvent_StorageHandler_BuySpace(blockhash types.Hash) (Event_BuySpace, error) { + var result Event_BuySpace events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.StorageHandlerBuySpace { + if e.Name == StorageHandlerBuySpace { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -1420,17 +1418,17 @@ func (c *ChainClient) RetrieveEvent_StorageHandler_BuySpace(blockhash types.Hash } } } - return result, errors.Errorf("failed: no %s event found", event.StorageHandlerBuySpace) + return result, errors.Errorf("failed: no %s event found", StorageHandlerBuySpace) } -func (c *ChainClient) RetrieveEvent_StorageHandler_ExpansionSpace(blockhash types.Hash) (event.Event_ExpansionSpace, error) { - var result event.Event_ExpansionSpace +func (c *ChainClient) RetrieveEvent_StorageHandler_ExpansionSpace(blockhash types.Hash) (Event_ExpansionSpace, error) { + var result Event_ExpansionSpace events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.StorageHandlerExpansionSpace { + if e.Name == StorageHandlerExpansionSpace { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -1467,17 +1465,17 @@ func (c *ChainClient) RetrieveEvent_StorageHandler_ExpansionSpace(blockhash type } } } - return result, errors.Errorf("failed: no %s event found", event.StorageHandlerExpansionSpace) + return result, errors.Errorf("failed: no %s event found", StorageHandlerExpansionSpace) } -func (c *ChainClient) RetrieveEvent_StorageHandler_RenewalSpace(blockhash types.Hash) (event.Event_RenewalSpace, error) { - var result event.Event_RenewalSpace +func (c *ChainClient) RetrieveEvent_StorageHandler_RenewalSpace(blockhash types.Hash) (Event_RenewalSpace, error) { + var result Event_RenewalSpace events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.StorageHandlerRenewalSpace { + if e.Name == StorageHandlerRenewalSpace { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -1514,7 +1512,7 @@ func (c *ChainClient) RetrieveEvent_StorageHandler_RenewalSpace(blockhash types. } } } - return result, errors.Errorf("failed: no %s event found", event.StorageHandlerRenewalSpace) + return result, errors.Errorf("failed: no %s event found", StorageHandlerRenewalSpace) } func (c *ChainClient) RetrieveEvent_Balances_Transfer(blockhash types.Hash) (types.EventBalancesTransfer, error) { @@ -1524,7 +1522,7 @@ func (c *ChainClient) RetrieveEvent_Balances_Transfer(blockhash types.Hash) (typ return result, err } for _, e := range events { - if e.Name == event.BalanceTransfer { + if e.Name == BalanceTransfer { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -1561,17 +1559,17 @@ func (c *ChainClient) RetrieveEvent_Balances_Transfer(blockhash types.Hash) (typ } } } - return result, errors.Errorf("failed: no %s event found", event.BalanceTransfer) + return result, errors.Errorf("failed: no %s event found", BalanceTransfer) } -func (c *ChainClient) RetrieveEvent_FileBank_GenRestoralOrder(blockhash types.Hash) (event.Event_GenerateRestoralOrder, error) { - var result event.Event_GenerateRestoralOrder +func (c *ChainClient) RetrieveEvent_FileBank_GenRestoralOrder(blockhash types.Hash) (Event_GenerateRestoralOrder, error) { + var result Event_GenerateRestoralOrder events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.FileBankGenerateRestoralOrder { + if e.Name == FileBankGenerateRestoralOrder { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -1608,19 +1606,19 @@ func (c *ChainClient) RetrieveEvent_FileBank_GenRestoralOrder(blockhash types.Ha } } } - return result, errors.Errorf("failed: no %s event found", event.FileBankGenerateRestoralOrder) + return result, errors.Errorf("failed: no %s event found", FileBankGenerateRestoralOrder) } -func (c *ChainClient) RetrieveAllEvent_FileBank_UploadDeclaration(blockhash types.Hash) ([]event.AllUploadDeclarationEvent, error) { - var result = make([]event.AllUploadDeclarationEvent, 0) +func (c *ChainClient) RetrieveAllEvent_FileBank_UploadDeclaration(blockhash types.Hash) ([]AllUploadDeclarationEvent, error) { + var result = make([]AllUploadDeclarationEvent, 0) events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.FileBankUploadDeclaration { - var ele event.AllUploadDeclarationEvent + if e.Name == FileBankUploadDeclaration { + var ele AllUploadDeclarationEvent for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -1663,13 +1661,13 @@ func (c *ChainClient) RetrieveAllEvent_FileBank_UploadDeclaration(blockhash type } else if strings.Contains(v.Name, "deal_hash") { temp := strings.Split(allValue, "] ") for _, v := range temp { - if strings.Count(v, " ") == (pattern.FileHashLen - 1) { + if strings.Count(v, " ") == (FileHashLen - 1) { subValue := strings.TrimPrefix(v, "[") ids := strings.Split(subValue, " ") - if len(ids) != pattern.FileHashLen { + if len(ids) != FileHashLen { continue } - var fhash pattern.FileHash + var fhash FileHash for kk, vv := range ids { intv, _ := strconv.Atoi(vv) fhash[kk] = types.U8(intv) @@ -1694,7 +1692,7 @@ func (c *ChainClient) RetrieveAllEvent_FileBank_StorageCompleted(blockhash types return result, err } for _, e := range events { - if e.Name == event.FileBankStorageCompleted { + if e.Name == FileBankStorageCompleted { for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -1703,13 +1701,13 @@ func (c *ChainClient) RetrieveAllEvent_FileBank_StorageCompleted(blockhash types if strings.Contains(v.Name, "file_hash") { temp := strings.Split(allValue, "] ") for _, v := range temp { - if strings.Count(v, " ") == (pattern.FileHashLen - 1) { + if strings.Count(v, " ") == (FileHashLen - 1) { subValue := strings.TrimPrefix(v, "[") ids := strings.Split(subValue, " ") - if len(ids) != pattern.FileHashLen { + if len(ids) != FileHashLen { continue } - var fhash pattern.FileHash + var fhash FileHash for kk, vv := range ids { intv, _ := strconv.Atoi(vv) fhash[kk] = types.U8(intv) @@ -1726,15 +1724,15 @@ func (c *ChainClient) RetrieveAllEvent_FileBank_StorageCompleted(blockhash types return result, nil } -func (c *ChainClient) RetrieveAllEvent_FileBank_DeleteFile(blockhash types.Hash) ([]event.AllDeleteFileEvent, error) { - var result = make([]event.AllDeleteFileEvent, 0) +func (c *ChainClient) RetrieveAllEvent_FileBank_DeleteFile(blockhash types.Hash) ([]AllDeleteFileEvent, error) { + var result = make([]AllDeleteFileEvent, 0) events, err := c.eventRetriever.GetEvents(blockhash) if err != nil { return result, err } for _, e := range events { - if e.Name == event.FileBankDeleteFile { - var ele event.AllDeleteFileEvent + if e.Name == FileBankDeleteFile { + var ele AllDeleteFileEvent for _, v := range e.Fields { if reflect.TypeOf(v.Value).Kind() == reflect.Slice { vf := reflect.ValueOf(v.Value) @@ -1779,13 +1777,13 @@ func (c *ChainClient) RetrieveAllEvent_FileBank_DeleteFile(blockhash types.Hash) allValue := fmt.Sprintf("%v", vf.Index(0)) temp := strings.Split(allValue, "] ") for _, v := range temp { - if strings.Count(v, " ") == (pattern.FileHashLen - 1) { + if strings.Count(v, " ") == (FileHashLen - 1) { subValue := strings.TrimPrefix(v, "[") ids := strings.Split(subValue, " ") - if len(ids) != pattern.FileHashLen { + if len(ids) != FileHashLen { continue } - var fhash pattern.FileHash + var fhash FileHash for kk, vv := range ids { intv, _ := strconv.Atoi(vv) fhash[kk] = types.U8(intv) @@ -1851,11 +1849,11 @@ func (c *ChainClient) RetrieveAllEventFromBlock(blockhash types.Hash) ([]string, return systemEvents, extrinsicsEvents, nil } -func (c *ChainClient) RetrieveBlock(blocknumber uint64) ([]string, []event.ExtrinsicsInfo, []event.TransferInfo, string, string, string, string, int64, error) { +func (c *ChainClient) RetrieveBlock(blocknumber uint64) ([]string, []ExtrinsicsInfo, []TransferInfo, string, string, string, string, int64, error) { var timeUnixMilli int64 var systemEvents = make([]string, 0) - var extrinsicsInfo = make([]event.ExtrinsicsInfo, 0) - var transferInfo = make([]event.TransferInfo, 0) + var extrinsicsInfo = make([]ExtrinsicsInfo, 0) + var transferInfo = make([]TransferInfo, 0) blockhash, err := c.GetSubstrateAPI().RPC.Chain.GetBlockHash(blocknumber) if err != nil { return systemEvents, extrinsicsInfo, transferInfo, "", "", "", "", 0, err @@ -1887,7 +1885,7 @@ func (c *ChainClient) RetrieveBlock(blocknumber uint64) ([]string, []event.Extri return systemEvents, extrinsicsInfo, transferInfo, "", "", "", "", 0, err } timeUnixMilli = timestamp.Int64() - extrinsicsInfo = append(extrinsicsInfo, event.ExtrinsicsInfo{ + extrinsicsInfo = append(extrinsicsInfo, ExtrinsicsInfo{ Name: name, Events: []string{e.Name}, Result: true, @@ -1895,28 +1893,21 @@ func (c *ChainClient) RetrieveBlock(blocknumber uint64) ([]string, []event.Extri continue } eventsBuf = append(eventsBuf, e.Name) - if e.Name == event.TransactionPaymentTransactionFeePaid || - e.Name == event.EvmAccountMappingTransactionFeePaid { + if e.Name == TransactionPaymentTransactionFeePaid || + e.Name == EvmAccountMappingTransactionFeePaid { signer, fee, _ = parseSignerAndFeePaidFromEvent(e) - } else if e.Name == event.BalancesTransfer { + } else if e.Name == BalancesTransfer { //parsedBalancesTransfer = false from, to, amount, _ := ParseTransferInfoFromEvent(e) - transferInfo = append(transferInfo, event.TransferInfo{ + transferInfo = append(transferInfo, TransferInfo{ From: from, To: to, Amount: amount, Result: true, }) - // transfers, err := c.parseTransferInfoFromBlock(blockhash) - // if err != nil { - // return systemEvents, extrinsicsInfo, transferInfo, "", "", "", "", 0, err - // } - // if len(transfers) > 0 { - // transferInfo = append(transferInfo, transfers...) - // } - } else if e.Name == event.SystemExtrinsicSuccess { + } else if e.Name == SystemExtrinsicSuccess { if len(eventsBuf) > 0 { - extrinsicsInfo = append(extrinsicsInfo, event.ExtrinsicsInfo{ + extrinsicsInfo = append(extrinsicsInfo, ExtrinsicsInfo{ Name: name, Signer: signer, FeePaid: fee, @@ -1925,9 +1916,9 @@ func (c *ChainClient) RetrieveBlock(blocknumber uint64) ([]string, []event.Extri }) eventsBuf = make([]string, 0) } - } else if e.Name == event.SystemExtrinsicFailed { + } else if e.Name == SystemExtrinsicFailed { if len(eventsBuf) > 0 { - extrinsicsInfo = append(extrinsicsInfo, event.ExtrinsicsInfo{ + extrinsicsInfo = append(extrinsicsInfo, ExtrinsicsInfo{ Name: name, Signer: signer, FeePaid: fee, @@ -1945,11 +1936,11 @@ func (c *ChainClient) RetrieveBlock(blocknumber uint64) ([]string, []event.Extri return systemEvents, extrinsicsInfo, transferInfo, blockhash.Hex(), block.Block.Header.ParentHash.Hex(), block.Block.Header.ExtrinsicsRoot.Hex(), block.Block.Header.StateRoot.Hex(), timeUnixMilli, nil } -func (c *ChainClient) RetrieveBlockAndAll(blocknumber uint64) ([]string, []event.ExtrinsicsInfo, []event.TransferInfo, []string, []string, string, string, string, string, string, int64, error) { +func (c *ChainClient) RetrieveBlockAndAll(blocknumber uint64) ([]string, []ExtrinsicsInfo, []TransferInfo, []string, []string, string, string, string, string, string, int64, error) { var timeUnixMilli int64 var systemEvents = make([]string, 0) - var extrinsicsInfo = make([]event.ExtrinsicsInfo, 0) - var transferInfo = make([]event.TransferInfo, 0) + var extrinsicsInfo = make([]ExtrinsicsInfo, 0) + var transferInfo = make([]TransferInfo, 0) var sminerRegInfo = make([]string, 0) var newAccounts = make([]string, 0) var allGasFee = new(big.Int) @@ -1982,19 +1973,19 @@ func (c *ChainClient) RetrieveBlockAndAll(blocknumber uint64) ([]string, []event var fee string var ok bool var name string - var extInfo event.ExtrinsicsInfo + var extInfo ExtrinsicsInfo for _, e := range events { if e.Phase.IsApplyExtrinsic { if name, ok = ExtrinsicsName[block.Block.Extrinsics[e.Phase.AsApplyExtrinsic].Method.CallIndex]; ok { if name == ExtName_Timestamp_set { - extInfo = event.ExtrinsicsInfo{} + extInfo = ExtrinsicsInfo{} timeDecoder := scale.NewDecoder(bytes.NewReader(block.Block.Extrinsics[e.Phase.AsApplyExtrinsic].Method.Args)) timestamp, err := timeDecoder.DecodeUintCompact() if err != nil { return systemEvents, extrinsicsInfo, transferInfo, sminerRegInfo, newAccounts, "", "", "", "", "", 0, err } timeUnixMilli = timestamp.Int64() - extrinsicsInfo = append(extrinsicsInfo, event.ExtrinsicsInfo{ + extrinsicsInfo = append(extrinsicsInfo, ExtrinsicsInfo{ Name: name, Events: []string{e.Name}, Result: true, @@ -2002,16 +1993,16 @@ func (c *ChainClient) RetrieveBlockAndAll(blocknumber uint64) ([]string, []event continue } eventsBuf = append(eventsBuf, e.Name) - if e.Name == event.TransactionPaymentTransactionFeePaid || - e.Name == event.EvmAccountMappingTransactionFeePaid { + if e.Name == TransactionPaymentTransactionFeePaid || + e.Name == EvmAccountMappingTransactionFeePaid { signer, fee, _ = parseSignerAndFeePaidFromEvent(e) tmp, ok := new(big.Int).SetString(fee, 10) if ok { allGasFee = allGasFee.Add(allGasFee, tmp) } - } else if e.Name == event.BalancesTransfer { + } else if e.Name == BalancesTransfer { from, to, amount, _ := ParseTransferInfoFromEvent(e) - transferInfo = append(transferInfo, event.TransferInfo{ + transferInfo = append(transferInfo, TransferInfo{ ExtrinsicName: name, From: from, To: to, @@ -2020,17 +2011,17 @@ func (c *ChainClient) RetrieveBlockAndAll(blocknumber uint64) ([]string, []event }) // extInfo.From = from // extInfo.To = to - } else if e.Name == event.SminerRegistered { + } else if e.Name == SminerRegistered { acc, err := ParseAccountFromEvent(e) if err == nil { sminerRegInfo = append(sminerRegInfo, acc) } - } else if e.Name == event.SystemNewAccount { + } else if e.Name == SystemNewAccount { acc, err := ParseAccountFromEvent(e) if err == nil { newAccounts = append(newAccounts, acc) } - } else if e.Name == event.SystemExtrinsicSuccess { + } else if e.Name == SystemExtrinsicSuccess { if len(eventsBuf) > 0 { extInfo.Name = name extInfo.Signer = signer @@ -2040,8 +2031,8 @@ func (c *ChainClient) RetrieveBlockAndAll(blocknumber uint64) ([]string, []event extrinsicsInfo = append(extrinsicsInfo, extInfo) eventsBuf = make([]string, 0) } - extInfo = event.ExtrinsicsInfo{} - } else if e.Name == event.SystemExtrinsicFailed { + extInfo = ExtrinsicsInfo{} + } else if e.Name == SystemExtrinsicFailed { if len(eventsBuf) > 0 { extInfo.Name = name extInfo.Signer = signer @@ -2051,7 +2042,7 @@ func (c *ChainClient) RetrieveBlockAndAll(blocknumber uint64) ([]string, []event extrinsicsInfo = append(extrinsicsInfo, extInfo) eventsBuf = make([]string, 0) } - extInfo = event.ExtrinsicsInfo{} + extInfo = ExtrinsicsInfo{} } } } else { @@ -2084,15 +2075,15 @@ func (c *ChainClient) RetrieveBlockAndAll(blocknumber uint64) ([]string, []event return systemEvents, extrinsicsInfo, transferInfo, sminerRegInfo, newAccounts, blockhash.Hex(), block.Block.Header.ParentHash.Hex(), block.Block.Header.ExtrinsicsRoot.Hex(), block.Block.Header.StateRoot.Hex(), allGasFee.String(), timeUnixMilli, nil } -func (c *ChainClient) ParseBlockData(blocknumber uint64) (event.BlockData, error) { +func (c *ChainClient) ParseBlockData(blocknumber uint64) (BlockData, error) { var ( ok bool name string err error extBytes []byte extrinsicIndex int - blockdata event.BlockData - extInfo event.ExtrinsicsInfo + blockdata BlockData + extInfo ExtrinsicsInfo allGasFee = new(big.Int) ) @@ -2112,7 +2103,7 @@ func (c *ChainClient) ParseBlockData(blocknumber uint64) (event.BlockData, error blockdata.ExtHash = block.Block.Header.ExtrinsicsRoot.Hex() blockdata.StHash = block.Block.Header.StateRoot.Hex() - blockdata.Extrinsics = make([]event.ExtrinsicsInfo, len(block.Block.Extrinsics)) + blockdata.Extrinsics = make([]ExtrinsicsInfo, len(block.Block.Extrinsics)) for k, v := range block.Block.Extrinsics { extBytes, err = codec.Encode(v) if err != nil { @@ -2142,7 +2133,7 @@ func (c *ChainClient) ParseBlockData(blocknumber uint64) (event.BlockData, error return blockdata, errors.New("The number of extrinsics hashes does not equal the number of extrinsics") } if name == ExtName_Timestamp_set { - extInfo = event.ExtrinsicsInfo{} + extInfo = ExtrinsicsInfo{} timestamp, err := scale.NewDecoder(bytes.NewReader(block.Block.Extrinsics[e.Phase.AsApplyExtrinsic].Method.Args)).DecodeUintCompact() if err != nil { return blockdata, err @@ -2155,8 +2146,8 @@ func (c *ChainClient) ParseBlockData(blocknumber uint64) (event.BlockData, error continue } eventsBuf = append(eventsBuf, e.Name) - if e.Name == event.TransactionPaymentTransactionFeePaid || - e.Name == event.EvmAccountMappingTransactionFeePaid { + if e.Name == TransactionPaymentTransactionFeePaid || + e.Name == EvmAccountMappingTransactionFeePaid { signer, fee, err = parseSignerAndFeePaidFromEvent(e) if err != nil { return blockdata, err @@ -2165,20 +2156,20 @@ func (c *ChainClient) ParseBlockData(blocknumber uint64) (event.BlockData, error if ok { allGasFee = allGasFee.Add(allGasFee, tmp) } - } else if e.Name == event.BalancesTransfer { + } else if e.Name == BalancesTransfer { from, to, amount, err := ParseTransferInfoFromEvent(e) if err != nil { return blockdata, err } - if to == c.treasuryAcc { - blockdata.Punishment = append(blockdata.Punishment, event.Punishment{ + if to == TreasuryAccount { + blockdata.Punishment = append(blockdata.Punishment, Punishment{ ExtrinsicHash: blockdata.Extrinsics[extrinsicIndex].Hash, From: from, To: to, Amount: amount, }) } - blockdata.TransferInfo = append(blockdata.TransferInfo, event.TransferInfo{ + blockdata.TransferInfo = append(blockdata.TransferInfo, TransferInfo{ ExtrinsicName: name, ExtrinsicHash: blockdata.Extrinsics[extrinsicIndex].Hash, From: from, @@ -2186,22 +2177,22 @@ func (c *ChainClient) ParseBlockData(blocknumber uint64) (event.BlockData, error Amount: amount, Result: true, }) - } else if e.Name == event.SminerRegistered { + } else if e.Name == SminerRegistered { acc, err := ParseAccountFromEvent(e) if err != nil { return blockdata, err } - blockdata.MinerReg = append(blockdata.MinerReg, event.MinerRegInfo{ + blockdata.MinerReg = append(blockdata.MinerReg, MinerRegInfo{ ExtrinsicHash: blockdata.Extrinsics[extrinsicIndex].Hash, Account: acc, }) - } else if e.Name == event.SystemNewAccount { + } else if e.Name == SystemNewAccount { acc, err := ParseAccountFromEvent(e) if err != nil { return blockdata, err } blockdata.NewAccounts = append(blockdata.NewAccounts, acc) - } else if e.Name == event.FileBankUploadDeclaration { + } else if e.Name == FileBankUploadDeclaration { acc, err := ParseAccountFromEvent(e) if err != nil { return blockdata, err @@ -2210,12 +2201,12 @@ func (c *ChainClient) ParseBlockData(blocknumber uint64) (event.BlockData, error if err != nil { return blockdata, err } - blockdata.UploadDecInfo = append(blockdata.UploadDecInfo, event.UploadDecInfo{ + blockdata.UploadDecInfo = append(blockdata.UploadDecInfo, UploadDecInfo{ ExtrinsicHash: blockdata.Extrinsics[extrinsicIndex].Hash, Owner: acc, Fid: fid, }) - } else if e.Name == event.FileBankDeleteFile { + } else if e.Name == FileBankDeleteFile { acc, err := ParseAccountFromEvent(e) if err != nil { return blockdata, err @@ -2224,12 +2215,12 @@ func (c *ChainClient) ParseBlockData(blocknumber uint64) (event.BlockData, error if err != nil { return blockdata, err } - blockdata.DeleteFileInfo = append(blockdata.DeleteFileInfo, event.DeleteFileInfo{ + blockdata.DeleteFileInfo = append(blockdata.DeleteFileInfo, DeleteFileInfo{ ExtrinsicHash: blockdata.Extrinsics[extrinsicIndex].Hash, Owner: acc, Fid: fid, }) - } else if e.Name == event.FileBankCreateBucket { + } else if e.Name == FileBankCreateBucket { acc, err := ParseAccountFromEvent(e) if err != nil { return blockdata, err @@ -2238,12 +2229,12 @@ func (c *ChainClient) ParseBlockData(blocknumber uint64) (event.BlockData, error if err != nil { return blockdata, err } - blockdata.CreateBucketInfo = append(blockdata.CreateBucketInfo, event.CreateBucketInfo{ + blockdata.CreateBucketInfo = append(blockdata.CreateBucketInfo, CreateBucketInfo{ ExtrinsicHash: blockdata.Extrinsics[extrinsicIndex].Hash, Owner: acc, BucketName: bucketname, }) - } else if e.Name == event.FileBankDeleteBucket { + } else if e.Name == FileBankDeleteBucket { acc, err := ParseAccountFromEvent(e) if err != nil { return blockdata, err @@ -2252,50 +2243,50 @@ func (c *ChainClient) ParseBlockData(blocknumber uint64) (event.BlockData, error if err != nil { return blockdata, err } - blockdata.DeleteBucketInfo = append(blockdata.DeleteBucketInfo, event.DeleteBucketInfo{ + blockdata.DeleteBucketInfo = append(blockdata.DeleteBucketInfo, DeleteBucketInfo{ ExtrinsicHash: blockdata.Extrinsics[extrinsicIndex].Hash, Owner: acc, BucketName: bucketname, }) - } else if e.Name == event.AuditSubmitIdleProof { + } else if e.Name == AuditSubmitIdleProof { acc, err := ParseAccountFromEvent(e) if err != nil { return blockdata, err } - blockdata.SubmitIdleProve = append(blockdata.SubmitIdleProve, event.SubmitIdleProve{ + blockdata.SubmitIdleProve = append(blockdata.SubmitIdleProve, SubmitIdleProve{ ExtrinsicHash: blockdata.Extrinsics[extrinsicIndex].Hash, Miner: acc, }) - } else if e.Name == event.AuditSubmitServiceProof { + } else if e.Name == AuditSubmitServiceProof { acc, err := ParseAccountFromEvent(e) if err != nil { return blockdata, err } - blockdata.SubmitServiceProve = append(blockdata.SubmitServiceProve, event.SubmitServiceProve{ + blockdata.SubmitServiceProve = append(blockdata.SubmitServiceProve, SubmitServiceProve{ ExtrinsicHash: blockdata.Extrinsics[extrinsicIndex].Hash, Miner: acc, }) - } else if e.Name == event.AuditSubmitIdleVerifyResult { + } else if e.Name == AuditSubmitIdleVerifyResult { acc, result, err := ParseChallResultFromEvent(e) if err != nil { return blockdata, err } - blockdata.SubmitIdleResult = append(blockdata.SubmitIdleResult, event.SubmitIdleResult{ + blockdata.SubmitIdleResult = append(blockdata.SubmitIdleResult, SubmitIdleResult{ ExtrinsicHash: blockdata.Extrinsics[extrinsicIndex].Hash, Miner: acc, Result: result, }) - } else if e.Name == event.AuditSubmitServiceVerifyResult { + } else if e.Name == AuditSubmitServiceVerifyResult { acc, result, err := ParseChallResultFromEvent(e) if err != nil { return blockdata, err } - blockdata.SubmitServiceResult = append(blockdata.SubmitServiceResult, event.SubmitServiceResult{ + blockdata.SubmitServiceResult = append(blockdata.SubmitServiceResult, SubmitServiceResult{ ExtrinsicHash: blockdata.Extrinsics[extrinsicIndex].Hash, Miner: acc, Result: result, }) - } else if e.Name == event.SystemExtrinsicSuccess { + } else if e.Name == SystemExtrinsicSuccess { extInfo.Events = append(make([]string, 0), eventsBuf...) extInfo.Name = name extInfo.Signer = signer @@ -2304,9 +2295,9 @@ func (c *ChainClient) ParseBlockData(blocknumber uint64) (event.BlockData, error extInfo.Hash = blockdata.Extrinsics[extrinsicIndex].Hash blockdata.Extrinsics[extrinsicIndex] = extInfo eventsBuf = make([]string, 0) - extInfo = event.ExtrinsicsInfo{} + extInfo = ExtrinsicsInfo{} extrinsicIndex++ - } else if e.Name == event.SystemExtrinsicFailed { + } else if e.Name == SystemExtrinsicFailed { for m := 0; m < len(blockdata.UploadDecInfo); m++ { if blockdata.UploadDecInfo[m].ExtrinsicHash == blockdata.Extrinsics[extrinsicIndex].Hash { if len(blockdata.UploadDecInfo) == 1 { @@ -2415,16 +2406,16 @@ func (c *ChainClient) ParseBlockData(blocknumber uint64) (event.BlockData, error extInfo.Hash = blockdata.Extrinsics[extrinsicIndex].Hash blockdata.Extrinsics[extrinsicIndex] = extInfo eventsBuf = make([]string, 0) - extInfo = event.ExtrinsicsInfo{} + extInfo = ExtrinsicsInfo{} extrinsicIndex++ } } } else { blockdata.SysEvents = append(blockdata.SysEvents, e.Name) - if e.Name == event.StakingStakersElected { + if e.Name == StakingStakersElected { blockdata.IsNewEra = true } - if e.Name == event.AuditGenerateChallenge { + if e.Name == AuditGenerateChallenge { acc, err := ParseAccountFromEvent(e) if err != nil { return blockdata, err @@ -2441,9 +2432,9 @@ func parseSignerAndFeePaidFromEvent(e *parser.Event) (string, string, error) { if e == nil { return "", "", errors.New("event is nil") } - if e.Name != event.TransactionPaymentTransactionFeePaid && - e.Name != event.EvmAccountMappingTransactionFeePaid { - return "", "", fmt.Errorf("event is not %s or %s", event.TransactionPaymentTransactionFeePaid, event.EvmAccountMappingTransactionFeePaid) + if e.Name != TransactionPaymentTransactionFeePaid && + e.Name != EvmAccountMappingTransactionFeePaid { + return "", "", fmt.Errorf("event is not %s or %s", TransactionPaymentTransactionFeePaid, EvmAccountMappingTransactionFeePaid) } var signAcc string var fee string @@ -2492,12 +2483,12 @@ func parseFidString(v reflect.Value) string { if v.Len() > 0 { allValue := fmt.Sprintf("%v", v.Index(0)) temp := strings.Split(allValue, "] ") - puk := make([]byte, pattern.FileHashLen) + puk := make([]byte, FileHashLen) for _, v := range temp { - if strings.Count(v, " ") == (pattern.FileHashLen - 1) { + if strings.Count(v, " ") == (FileHashLen - 1) { subValue := strings.TrimPrefix(v, "[") ids := strings.Split(subValue, " ") - if len(ids) != pattern.FileHashLen { + if len(ids) != FileHashLen { continue } for kk, vv := range ids { @@ -2561,41 +2552,12 @@ func ExplicitBigInt(v reflect.Value, depth int) string { return fee } -func (c *ChainClient) parseTransferInfoFromBlock(blockhash types.Hash) ([]event.TransferInfo, error) { - var transferEvents = make([]event.TransferInfo, 0) - var data types.StorageDataRaw - ok, err := c.GetSubstrateAPI().RPC.State.GetStorage(c.GetKeyEvents(), &data, blockhash) - if err != nil { - return transferEvents, err - } - var from string - var to string - if ok { - events := event.EventRecords{} - err = types.EventRecordsRaw(data).DecodeEventRecords(c.GetMetadata(), &events) - if err != nil { - return transferEvents, err - } - for _, e := range events.Balances_Transfer { - from, _ = utils.EncodePublicKeyAsCessAccount(e.From[:]) - to, _ = utils.EncodePublicKeyAsCessAccount(e.To[:]) - transferEvents = append(transferEvents, event.TransferInfo{ - From: from, - To: to, - Amount: e.Value.String(), - Result: true, - }) - } - } - return transferEvents, nil -} - func ParseTransferInfoFromEvent(e *parser.Event) (string, string, string, error) { if e == nil { return "", "", "", errors.New("event is nil") } - if e.Name != event.BalancesTransfer { - return "", "", "", fmt.Errorf("event is not %s", event.BalancesTransfer) + if e.Name != BalancesTransfer { + return "", "", "", fmt.Errorf("event is not %s", BalancesTransfer) } var from string var to string diff --git a/core/event/eventsName.go b/chain/event_name.go old mode 100755 new mode 100644 similarity index 99% rename from core/event/eventsName.go rename to chain/event_name.go index dba1358..874d50d --- a/core/event/eventsName.go +++ b/chain/event_name.go @@ -5,7 +5,7 @@ SPDX-License-Identifier: Apache-2.0 */ -package event +package chain const ( // AUDIT diff --git a/core/event/events.go b/chain/event_type.go old mode 100755 new mode 100644 similarity index 95% rename from core/event/events.go rename to chain/event_type.go index 01edcc9..aa921d4 --- a/core/event/events.go +++ b/chain/event_type.go @@ -5,10 +5,9 @@ SPDX-License-Identifier: Apache-2.0 */ -package event +package chain import ( - "github.com/CESSProject/cess-go-sdk/core/pattern" "github.com/centrifuge/go-substrate-rpc-client/v4/types" ) @@ -19,7 +18,7 @@ import ( // ------------------------Audit------------------- type Event_VerifyProof struct { Phase types.Phase - TeeWorker pattern.WorkerPublicKey + TeeWorker WorkerPublicKey Miner types.AccountID Topics []types.Hash } @@ -49,7 +48,7 @@ type Event_SubmitServiceProof struct { type Event_SubmitIdleVerifyResult struct { Phase types.Phase - Tee pattern.WorkerPublicKey + Tee WorkerPublicKey Miner types.AccountID Result types.Bool Topics []types.Hash @@ -57,7 +56,7 @@ type Event_SubmitIdleVerifyResult struct { type Event_SubmitServiceVerifyResult struct { Phase types.Phase - Tee pattern.WorkerPublicKey + Tee WorkerPublicKey Miner types.AccountID Result types.Bool Topics []types.Hash @@ -134,8 +133,8 @@ type Event_UpdateBeneficiary struct { type Event_UpdatePeerId struct { Phase types.Phase Acc types.AccountID - Old pattern.PeerId - New pattern.PeerId + Old PeerId + New PeerId Topics []types.Hash } @@ -157,14 +156,14 @@ type Event_DeleteFile struct { Phase types.Phase Operator types.AccountID Owner types.AccountID - Filehash []pattern.FileHash + Filehash []FileHash Topics []types.Hash } type Event_FillerDelete struct { Phase types.Phase Acc types.AccountID - FillerHash pattern.FileHash + FillerHash FileHash Topics []types.Hash } @@ -179,7 +178,7 @@ type Event_UploadDeclaration struct { Phase types.Phase Operator types.AccountID Owner types.AccountID - Deal_hash pattern.FileHash + Deal_hash FileHash Topics []types.Hash } @@ -202,47 +201,47 @@ type Event_DeleteBucket struct { type Event_TransferReport struct { Phase types.Phase Acc types.AccountID - DealHash pattern.FileHash + DealHash FileHash Topics []types.Hash } type Event_ReplaceFiller struct { Phase types.Phase Acc types.AccountID - Filler_list []pattern.FileHash + Filler_list []FileHash Topics []types.Hash } type Event_CalculateEnd struct { Phase types.Phase - File_hash pattern.FileHash + File_hash FileHash Topics []types.Hash } type Event_GenerateRestoralOrder struct { Phase types.Phase Miner types.AccountID - FragmentHash pattern.FileHash + FragmentHash FileHash Topics []types.Hash } type Event_ClaimRestoralOrder struct { Phase types.Phase Miner types.AccountID - OrderId pattern.FileHash + OrderId FileHash Topics []types.Hash } type Event_RecoveryCompleted struct { Phase types.Phase Miner types.AccountID - OrderId pattern.FileHash + OrderId FileHash Topics []types.Hash } type Event_StorageCompleted struct { Phase types.Phase - FileHash pattern.FileHash + FileHash FileHash Topics []types.Hash } @@ -276,7 +275,7 @@ type Event_ReplaceIdleSpace struct { type Event_CalculateReport struct { Phase types.Phase Miner types.AccountID - FileHash pattern.FileHash + FileHash FileHash Topics []types.Hash } @@ -333,7 +332,7 @@ type Event_MasterKeyLaunched struct { type Event_WorkerAdded struct { Phase types.Phase - Pubkey pattern.WorkerPublicKey + Pubkey WorkerPublicKey AttestationProvider types.Option[types.U8] ConfidenceLevel types.U8 Topics []types.Hash @@ -341,13 +340,13 @@ type Event_WorkerAdded struct { type Event_KeyfairyAdded struct { Phase types.Phase - Pubkey pattern.WorkerPublicKey + Pubkey WorkerPublicKey Topics []types.Hash } type Event_WorkerUpdated struct { Phase types.Phase - Pubkey pattern.WorkerPublicKey + Pubkey WorkerPublicKey AttestationProvider types.Option[types.U8] ConfidenceLevel types.U8 Topics []types.Hash @@ -356,7 +355,7 @@ type Event_WorkerUpdated struct { type Event_MasterKeyRotated struct { Phase types.Phase RotationId types.U64 - MasterPubkey pattern.WorkerPublicKey + MasterPubkey WorkerPublicKey Topics []types.Hash } @@ -379,14 +378,14 @@ type Event_MinimumCesealVersionChangedTo struct { type Event_OssRegister struct { Phase types.Phase Acc types.AccountID - Endpoint pattern.PeerId + Endpoint PeerId Topics []types.Hash } type Event_OssUpdate struct { Phase types.Phase Acc types.AccountID - NewEndpoint pattern.PeerId + NewEndpoint PeerId Topics []types.Hash } diff --git a/chain/evm.go b/chain/evm.go index 671b81d..bb63211 100644 --- a/chain/evm.go +++ b/chain/evm.go @@ -1,3 +1,10 @@ +/* + Copyright (C) CESS. All rights reserved. + Copyright (C) Cumulus Encrypted Storage System. All rights reserved. + + SPDX-License-Identifier: Apache-2.0 +*/ + package chain import ( @@ -6,13 +13,12 @@ import ( "strings" "time" - "github.com/CESSProject/cess-go-sdk/core/pattern" "github.com/CESSProject/cess-go-sdk/utils" "github.com/centrifuge/go-substrate-rpc-client/v4/types" "github.com/pkg/errors" ) -func (c *ChainClient) SendEvmCall(source types.H160, target types.H160, input types.Bytes, value types.U256, gasLimit types.U64, maxFeePerGas types.U256, accessList []pattern.AccessInfo) (string, error) { +func (c *ChainClient) SendEvmCall(source types.H160, target types.H160, input types.Bytes, value types.U256, gasLimit types.U64, maxFeePerGas types.U256, accessList []AccessInfo) (string, error) { c.lock.Lock() defer func() { c.lock.Unlock() @@ -22,12 +28,12 @@ func (c *ChainClient) SendEvmCall(source types.H160, target types.H160, input ty }() var ( - txhash string + blockhash string accountInfo types.AccountInfo ) - if !c.GetChainState() { - return txhash, fmt.Errorf("chainSDK.UploadDeclaration(): GetChainState(): %v", pattern.ERR_RPC_CONNECTION) + if !c.GetRpcState() { + return blockhash, fmt.Errorf("chainSDK.UploadDeclaration(): GetRpcState(): %v", ERR_RPC_CONNECTION) } var nonce types.Option[types.U256] @@ -36,35 +42,33 @@ func (c *ChainClient) SendEvmCall(source types.H160, target types.H160, input ty var maxPriorityFeePerGas types.Option[types.U256] maxPriorityFeePerGas.SetNone() - call, err := types.NewCall(c.metadata, pattern.TX_EVM_CALL, source, target, input, value, gasLimit, maxFeePerGas, maxPriorityFeePerGas, nonce, accessList) + call, err := types.NewCall(c.metadata, TX_EVM_Call, source, target, input, value, gasLimit, maxFeePerGas, maxPriorityFeePerGas, nonce, accessList) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.EVM, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_EVM_Call, err) + return blockhash, err } ext := types.NewExtrinsic(call) - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.EVM, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_EVM_Call, err) + return blockhash, err } ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.EVM, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_EVM_Call, err) + c.SetRpcState(false) + return blockhash, err } if !ok { keyStr, _ := utils.NumsToByteStr(key, map[string]bool{}) - return txhash, fmt.Errorf( + return blockhash, fmt.Errorf( "chain rpc.state.GetStorageLatest[%v]: %v", keyStr, - pattern.ERR_RPC_EMPTY_VALUE, + ERR_RPC_EMPTY_VALUE, ) } @@ -80,29 +84,28 @@ func (c *ChainClient) SendEvmCall(source types.H160, target types.H160, input ty err = ext.Sign(c.keyring, o) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.EVM, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_EVM_Call, err) + return blockhash, err } sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) err = ext.Sign(c.keyring, o) if err != nil { - return txhash, errors.Wrap(err, "[Sign]") + return blockhash, errors.Wrap(err, "[Sign]") } sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.EVM, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_EVM_Call, err) + c.SetRpcState(false) + return blockhash, err } } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.EVM, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_EVM_Call, err) + c.SetRpcState(false) + return blockhash, err } } defer sub.Unsubscribe() @@ -114,13 +117,13 @@ func (c *ChainClient) SendEvmCall(source types.H160, target types.H160, input ty select { case status := <-sub.Chan(): if status.IsInBlock { - txhash = status.AsInBlock.Hex() - return txhash, err + blockhash = status.AsInBlock.Hex() + return blockhash, err } case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") + return blockhash, errors.Wrap(err, "[sub]") case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT + return blockhash, ERR_RPC_TIMEOUT } } } diff --git a/chain/extrinsic_name.go b/chain/extrinsic_name.go index 01df6e1..299d0a9 100644 --- a/chain/extrinsic_name.go +++ b/chain/extrinsic_name.go @@ -219,6 +219,14 @@ const ( ExtName_Proxy_remove_proxies = "Proxy.remove_proxies" ExtName_Proxy_remove_proxy = "Proxy.remove_proxy" + // Reservoir + ExtName_Reservoir_attend_evnet = "Reservoir.attend_evnet" + ExtName_Reservoir_create_event = "Reservoir.create_event" + ExtName_Reservoir_event_withdraw = "Reservoir.event_withdraw" + ExtName_Reservoir_filling = "Reservoir.filling" + ExtName_Reservoir_store = "Reservoir.store" + ExtName_Reservoir_withdraw = "Reservoir.withdraw" + // Scheduler ExtName_Scheduler_cancel = "Scheduler.cancel" ExtName_Scheduler_cancel_named = "Scheduler.cancel_named" @@ -321,16 +329,21 @@ const ( ExtName_TechnicalMembership_swap_member = "TechnicalMembership.swap_member" // TeeWorker - ExtName_TeeWorker_add_ceseal = "TeeWorker.add_ceseal" - ExtName_TeeWorker_force_register_worker = "TeeWorker.force_register_worker" - ExtName_TeeWorker_register_keyfairy = "TeeWorker.register_keyfairy" - ExtName_TeeWorker_register_worker = "TeeWorker.register_worker" - ExtName_TeeWorker_register_worker_v2 = "TeeWorker.register_worker_v2" - ExtName_TeeWorker_remove_ceseal = "TeeWorker.remove_ceseal" - ExtName_TeeWorker_rotate_master_key = "TeeWorker.rotate_master_key" + ExtName_TeeWorker_add_ceseal = "TeeWorker.add_ceseal" + ExtName_TeeWorker_apply_master_key = "TeeWorker.apply_master_key" + ExtName_TeeWorker_force_register_worker = "TeeWorker.force_register_worker" + //ExtName_TeeWorker_register_keyfairy = "TeeWorker.register_keyfairy" + ExtName_TeeWorker_launch_master_key = "TeeWorker.launch_master_key" + ExtName_TeeWorker_migration_last_work = "TeeWorker.migration_last_work" + ExtName_TeeWorker_patch_clear_invalid_tee = "TeeWorker.patch_clear_invalid_tee" + ExtName_TeeWorker_patch_clear_not_work_tee = "TeeWorker.patch_clear_not_work_tee" + ExtName_TeeWorker_register_worker = "TeeWorker.register_worker" + ExtName_TeeWorker_register_worker_v2 = "TeeWorker.register_worker_v2" + ExtName_TeeWorker_remove_ceseal = "TeeWorker.remove_ceseal" + //ExtName_TeeWorker_rotate_master_key = "TeeWorker.rotate_master_key" ExtName_TeeWorker_set_minimum_ceseal_version = "TeeWorker.set_minimum_ceseal_version" - ExtName_TeeWorker_unregister_keyfairy = "TeeWorker.unregister_keyfairy" - ExtName_TeeWorker_update_worker_endpoint = "TeeWorker.update_worker_endpoint" + //ExtName_TeeWorker_unregister_keyfairy = "TeeWorker.unregister_keyfairy" + ExtName_TeeWorker_update_worker_endpoint = "TeeWorker.update_worker_endpoint" // Timestamp ExtName_Timestamp_set = "Timestamp.set" @@ -348,12 +361,17 @@ const ( ExtName_VoterList_rebag = "VoterList.rebag" ) +// InitExtrinsicsName initialises all transaction names +// +// Return: +// - error: error message +// +// Note: +// - if you need to make a transaction on the chain, you must call this method func (c *ChainClient) InitExtrinsicsName() error { ExtrinsicsName = make(map[types.CallIndex]string, 0) // Assets if callIndex, err := c.GetMetadata().FindCallIndex(ExtName_Assets_approve_transfer); err == nil { - //fmt.Println(ExtName_Timestamp_set, ".callIndex.MethodIndex:", callIndex.MethodIndex) - //fmt.Println(ExtName_Timestamp_set, ".callIndex.SectionIndex:", callIndex.SectionIndex) ExtrinsicsName[callIndex] = ExtName_Assets_approve_transfer } else { return err @@ -1188,6 +1206,38 @@ func (c *ChainClient) InitExtrinsicsName() error { return err } + // Reservoir + if callIndex, err := c.GetMetadata().FindCallIndex(ExtName_Reservoir_attend_evnet); err == nil { + ExtrinsicsName[callIndex] = ExtName_Reservoir_attend_evnet + } else { + return err + } + if callIndex, err := c.GetMetadata().FindCallIndex(ExtName_Reservoir_create_event); err == nil { + ExtrinsicsName[callIndex] = ExtName_Reservoir_create_event + } else { + return err + } + if callIndex, err := c.GetMetadata().FindCallIndex(ExtName_Reservoir_event_withdraw); err == nil { + ExtrinsicsName[callIndex] = ExtName_Reservoir_event_withdraw + } else { + return err + } + if callIndex, err := c.GetMetadata().FindCallIndex(ExtName_Reservoir_filling); err == nil { + ExtrinsicsName[callIndex] = ExtName_Reservoir_filling + } else { + return err + } + if callIndex, err := c.GetMetadata().FindCallIndex(ExtName_Reservoir_store); err == nil { + ExtrinsicsName[callIndex] = ExtName_Reservoir_store + } else { + return err + } + if callIndex, err := c.GetMetadata().FindCallIndex(ExtName_Reservoir_withdraw); err == nil { + ExtrinsicsName[callIndex] = ExtName_Reservoir_withdraw + } else { + return err + } + // Scheduler if callIndex, err := c.GetMetadata().FindCallIndex(ExtName_Scheduler_cancel); err == nil { ExtrinsicsName[callIndex] = ExtName_Scheduler_cancel @@ -1627,13 +1677,33 @@ func (c *ChainClient) InitExtrinsicsName() error { } else { return err } + if callIndex, err := c.GetMetadata().FindCallIndex(ExtName_TeeWorker_apply_master_key); err == nil { + ExtrinsicsName[callIndex] = ExtName_TeeWorker_apply_master_key + } else { + return err + } if callIndex, err := c.GetMetadata().FindCallIndex(ExtName_TeeWorker_force_register_worker); err == nil { ExtrinsicsName[callIndex] = ExtName_TeeWorker_force_register_worker } else { return err } - if callIndex, err := c.GetMetadata().FindCallIndex(ExtName_TeeWorker_register_keyfairy); err == nil { - ExtrinsicsName[callIndex] = ExtName_TeeWorker_register_keyfairy + if callIndex, err := c.GetMetadata().FindCallIndex(ExtName_TeeWorker_launch_master_key); err == nil { + ExtrinsicsName[callIndex] = ExtName_TeeWorker_launch_master_key + } else { + return err + } + if callIndex, err := c.GetMetadata().FindCallIndex(ExtName_TeeWorker_migration_last_work); err == nil { + ExtrinsicsName[callIndex] = ExtName_TeeWorker_migration_last_work + } else { + return err + } + if callIndex, err := c.GetMetadata().FindCallIndex(ExtName_TeeWorker_patch_clear_invalid_tee); err == nil { + ExtrinsicsName[callIndex] = ExtName_TeeWorker_patch_clear_invalid_tee + } else { + return err + } + if callIndex, err := c.GetMetadata().FindCallIndex(ExtName_TeeWorker_patch_clear_not_work_tee); err == nil { + ExtrinsicsName[callIndex] = ExtName_TeeWorker_patch_clear_not_work_tee } else { return err } @@ -1652,21 +1722,11 @@ func (c *ChainClient) InitExtrinsicsName() error { } else { return err } - if callIndex, err := c.GetMetadata().FindCallIndex(ExtName_TeeWorker_rotate_master_key); err == nil { - ExtrinsicsName[callIndex] = ExtName_TeeWorker_rotate_master_key - } else { - return err - } if callIndex, err := c.GetMetadata().FindCallIndex(ExtName_TeeWorker_set_minimum_ceseal_version); err == nil { ExtrinsicsName[callIndex] = ExtName_TeeWorker_set_minimum_ceseal_version } else { return err } - if callIndex, err := c.GetMetadata().FindCallIndex(ExtName_TeeWorker_unregister_keyfairy); err == nil { - ExtrinsicsName[callIndex] = ExtName_TeeWorker_unregister_keyfairy - } else { - return err - } if callIndex, err := c.GetMetadata().FindCallIndex(ExtName_TeeWorker_update_worker_endpoint); err == nil { ExtrinsicsName[callIndex] = ExtName_TeeWorker_update_worker_endpoint } else { diff --git a/chain/file.go b/chain/file.go deleted file mode 100755 index 6f5f26d..0000000 --- a/chain/file.go +++ /dev/null @@ -1,414 +0,0 @@ -/* - Copyright (C) CESS. All rights reserved. - Copyright (C) Cumulus Encrypted Storage System. All rights reserved. - - SPDX-License-Identifier: Apache-2.0 -*/ - -package chain - -import ( - "bufio" - "bytes" - "fmt" - "io" - "mime/multipart" - "net/http" - "os" - "path/filepath" - "strings" - - "github.com/CESSProject/cess-go-sdk/core/pattern" - "github.com/CESSProject/cess-go-sdk/utils" - keyring "github.com/CESSProject/go-keyring" - "github.com/btcsuite/btcutil/base58" - "github.com/pkg/errors" -) - -func (c *ChainClient) StoreFile(url, file, bucket string) (string, error) { - fstat, err := os.Stat(file) - if err != nil { - - return "", err - } - - if fstat.IsDir() { - return "", errors.New("not a file") - } - - if fstat.Size() == 0 { - return "", errors.New("empty file") - } - - if !utils.CheckBucketName(bucket) { - return "", errors.New("invalid bucket name") - } - - kr, _ := keyring.FromURI(c.GetURI(), keyring.NetSubstrate{}) - - // sign message - message := utils.GetRandomcode(16) - sig, _ := kr.Sign(kr.SigningContext([]byte(message))) - - body := new(bytes.Buffer) - writer := multipart.NewWriter(body) - // - formFile, err := writer.CreateFormFile("file", fstat.Name()) - if err != nil { - return "", err - } - - f, err := os.Open(file) - if err != nil { - return "", err - } - defer f.Close() - - _, err = io.Copy(formFile, f) - if err != nil { - return "", err - } - err = writer.Close() - if err != nil { - return "", err - } - - req, err := http.NewRequest(http.MethodPut, url, body) - if err != nil { - return "", err - } - - req.Header.Set("BucketName", bucket) - req.Header.Set("Account", c.GetSignatureAcc()) - req.Header.Set("Message", message) - req.Header.Set("Signature", base58.Encode(sig[:])) - req.Header.Set("Content-Type", writer.FormDataContentType()) - - client := &http.Client{} - client.Transport = globalTransport - resp, err := client.Do(req) - if err != nil { - return "", err - } - defer resp.Body.Close() - - respbody, err := io.ReadAll(resp.Body) - if err != nil { - return "", err - } - - if resp.StatusCode != http.StatusOK { - if len(respbody) > 0 { - return "", errors.New(string(respbody)) - } - return "", errors.New(fmt.Sprintf("upload failed, code: %d", resp.StatusCode)) - } - - return strings.TrimPrefix(strings.TrimSuffix(string(respbody), "\""), "\""), nil -} - -func (c *ChainClient) StoreObject(url string, reader io.Reader, bucket string) (string, error) { - if !utils.CheckBucketName(bucket) { - return "", errors.New("invalid bucket name") - } - - kr, _ := keyring.FromURI(c.GetURI(), keyring.NetSubstrate{}) - - // sign message - message := utils.GetRandomcode(16) - sig, _ := kr.Sign(kr.SigningContext([]byte(message))) - - req, err := http.NewRequest(http.MethodPut, url, reader) - if err != nil { - return "", err - } - - req.Header.Set("BucketName", bucket) - req.Header.Set("Account", c.GetSignatureAcc()) - req.Header.Set("Message", message) - req.Header.Set("Signature", base58.Encode(sig[:])) - req.Header.Set("Content-Type", "application/json") - - client := &http.Client{} - client.Transport = globalTransport - resp, err := client.Do(req) - if err != nil { - return "", err - } - defer resp.Body.Close() - - respbody, err := io.ReadAll(resp.Body) - if err != nil { - return "", err - } - - if resp.StatusCode != http.StatusOK { - if len(respbody) > 0 { - return "", errors.New(string(respbody)) - } - return "", errors.New(fmt.Sprintf("upload failed, code: %d", resp.StatusCode)) - } - - return strings.TrimPrefix(strings.TrimSuffix(string(respbody), "\""), "\""), nil -} - -func (c *ChainClient) RetrieveFile(url, fid, savepath string) error { - fstat, err := os.Stat(savepath) - if err == nil { - if fstat.IsDir() { - savepath = filepath.Join(savepath, fid) - } - if fstat.Size() > 0 { - return nil - } - } - - if url == "" { - return errors.New("empty url") - } - - if url[len(url)-1] != byte(47) { - url += "/" - } - - f, err := os.Create(savepath) - if err != nil { - return err - } - defer f.Close() - - req, err := http.NewRequest(http.MethodGet, url+fid, nil) - if err != nil { - return err - } - - kr, _ := keyring.FromURI(c.GetURI(), keyring.NetSubstrate{}) - - // sign message - message := utils.GetRandomcode(16) - sig, _ := kr.Sign(kr.SigningContext([]byte(message))) - req.Header.Set("Message", message) - req.Header.Set("Signature", base58.Encode(sig[:])) - req.Header.Set("Content-Type", "application/json") - req.Header.Set("Operation", "download") - req.Header.Set("Account", c.GetSignatureAcc()) - - client := &http.Client{} - client.Transport = globalTransport - resp, err := client.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - return errors.New("failed") - } - - _, err = io.Copy(f, resp.Body) - if err != nil { - return err - } - - return nil -} - -func (c *ChainClient) RetrieveObject(url, fid string) (io.ReadCloser, error) { - if url == "" { - return nil, errors.New("empty url") - } - - if url[len(url)-1] != byte(47) { - url += "/" - } - - req, err := http.NewRequest(http.MethodGet, url+fid, nil) - if err != nil { - return nil, err - } - kr, _ := keyring.FromURI(c.GetURI(), keyring.NetSubstrate{}) - - // sign message - message := utils.GetRandomcode(16) - sig, _ := kr.Sign(kr.SigningContext([]byte(message))) - req.Header.Set("Message", message) - req.Header.Set("Signature", base58.Encode(sig[:])) - req.Header.Set("Content-Type", "application/json") - req.Header.Set("Account", c.GetSignatureAcc()) - req.Header.Set("Operation", "download") - - client := &http.Client{} - client.Transport = globalTransport - resp, err := client.Do(req) - if err != nil { - return nil, err - } - - if resp.StatusCode != http.StatusOK { - return nil, errors.New(fmt.Sprintf("Retrieve failed, code: %d", resp.StatusCode)) - } - - return resp.Body, nil -} - -func (c *ChainClient) SplitFile(fpath, chunksDir string, chunkSize int64, filling bool) (int64, int, error) { - fstat, err := os.Stat(fpath) - if err != nil { - return 0, 0, err - } - if fstat.IsDir() { - return 0, 0, errors.New("not a file") - } - if fstat.Size() == 0 { - return 0, 0, errors.New("empty file") - } - if fstat.Size() < chunkSize { - chunkSize = fstat.Size() - } - count := fstat.Size() / chunkSize - if fstat.Size()%chunkSize != 0 { - count++ - } - buf := make([]byte, chunkSize) - f, err := os.Open(fpath) - if err != nil { - return 0, 0, err - } - defer f.Close() - reader := bufio.NewReader(f) - size := fstat.Size() - for i := int64(0); i < count; i++ { - n, err := reader.Read(buf) - if err != nil { - return 0, 0, err - } - if n <= 0 { - return 0, 0, errors.New("read a empty block") - } - if n < int(chunkSize) && filling { - if i+1 != count { - return 0, 0, errors.New("read file err") - } - copy(buf[n:], make([]byte, chunkSize-int64(n))) - size += chunkSize - int64(n) - n = int(chunkSize) - } - err = utils.WriteBufToFile(buf[:n], filepath.Join(chunksDir, fmt.Sprintf("chunk-%d", i))) - if err != nil { - return 0, 0, err - } - } - return size, int(count), nil -} - -func (c *ChainClient) SplitFileWithstandardSize(fpath, chunksDir string) (int64, int, error) { - return c.SplitFile(fpath, chunksDir, pattern.SegmentSize, true) -} - -func (c *ChainClient) UploadFileChunks(url, chunksDir, bucket, fname string, chunksNum int, totalSize int64) (string, error) { - entries, err := os.ReadDir(chunksDir) - if err != nil { - return "", errors.Wrap(err, "upload file chunk error") - } - if len(entries) == 0 { - return "", errors.Wrap(errors.New("empty dir"), "upload file chunk error") - } - if len(entries) > chunksNum { - return "", errors.Wrap(errors.New("bad chunks number"), "upload file chunk error") - } - var res string - for i := chunksNum - len(entries); i < chunksNum; i++ { - res, err = c.UploadFileChunk(url, chunksDir, bucket, fname, chunksNum, i, totalSize) - if err != nil { - return res, errors.Wrap(err, "upload file chunks error") - } - os.Remove(filepath.Join(chunksDir, fmt.Sprintf("chunk-%d", i))) - } - return res, nil -} - -func (c *ChainClient) UploadFileChunk(url, chunksDir, bucket, fname string, chunksNum, chunksId int, totalSize int64) (string, error) { - - file := filepath.Join(chunksDir, fmt.Sprintf("chunk-%d", chunksId)) - fstat, err := os.Stat(file) - if err != nil { - return "", errors.Wrap(err, "upload file chunk error") - } - - if fstat.IsDir() { - return "", errors.Wrap(errors.New("not a file"), "upload file chunk error") - } - - if fstat.Size() == 0 { - return "", errors.New("empty file") - } - - if !utils.CheckBucketName(bucket) { - return "", errors.New("invalid bucket name") - } - - kr, _ := keyring.FromURI(c.GetURI(), keyring.NetSubstrate{}) - - // sign message - message := utils.GetRandomcode(16) - sig, _ := kr.Sign(kr.SigningContext([]byte(message))) - - body := new(bytes.Buffer) - writer := multipart.NewWriter(body) - // - formFile, err := writer.CreateFormFile("file", fstat.Name()) - if err != nil { - return "", err - } - - f, err := os.Open(file) - if err != nil { - return "", err - } - defer f.Close() - - _, err = io.Copy(formFile, f) - if err != nil { - return "", err - } - err = writer.Close() - if err != nil { - return "", err - } - - req, err := http.NewRequest(http.MethodPut, url, body) - if err != nil { - return "", err - } - - req.Header.Set("BucketName", bucket) - req.Header.Set("Account", c.GetSignatureAcc()) - req.Header.Set("Message", message) - req.Header.Set("Signature", base58.Encode(sig[:])) - req.Header.Set("Content-Type", writer.FormDataContentType()) - req.Header.Set("FileName", fname) - req.Header.Set("BlockNumber", fmt.Sprint(chunksNum)) - req.Header.Set("BlockIndex", fmt.Sprint(chunksId)) - req.Header.Set("TotalSize", fmt.Sprint(totalSize)) - - client := &http.Client{} - client.Transport = globalTransport - resp, err := client.Do(req) - if err != nil { - return "", err - } - defer resp.Body.Close() - - respbody, err := io.ReadAll(resp.Body) - if err != nil { - return "", err - } - - if resp.StatusCode != http.StatusOK { - if len(respbody) > 0 { - return "", errors.New(string(respbody)) - } - return "", errors.New(fmt.Sprintf("upload failed, code: %d", resp.StatusCode)) - } - return strings.TrimPrefix(strings.TrimSuffix(string(respbody), "\""), "\""), nil -} diff --git a/chain/fileBank.go b/chain/fileBank.go deleted file mode 100755 index fd1e1ab..0000000 --- a/chain/fileBank.go +++ /dev/null @@ -1,1753 +0,0 @@ -/* - Copyright (C) CESS. All rights reserved. - Copyright (C) Cumulus Encrypted Storage System. All rights reserved. - - SPDX-License-Identifier: Apache-2.0 -*/ - -package chain - -import ( - "fmt" - "log" - "math/big" - "path/filepath" - "strings" - "time" - - "github.com/CESSProject/cess-go-sdk/core/pattern" - "github.com/CESSProject/cess-go-sdk/utils" - "github.com/centrifuge/go-substrate-rpc-client/v4/types" - "github.com/centrifuge/go-substrate-rpc-client/v4/types/codec" - "github.com/pkg/errors" -) - -func (c *ChainClient) QueryBucketInfo(accountID []byte, bucketname string) (pattern.BucketInfo, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var data pattern.BucketInfo - - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION - } - - acc, err := types.NewAccountID(accountID) - if err != nil { - return data, errors.Wrap(err, "[NewAccountID]") - } - - owner, err := codec.Encode(*acc) - if err != nil { - return data, errors.Wrap(err, "[EncodeToBytes]") - } - - name, err := codec.Encode(bucketname) - if err != nil { - return data, errors.Wrap(err, "[Encode]") - } - - key, err := types.CreateStorageKey(c.metadata, pattern.FILEBANK, pattern.BUCKET, owner, name) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.FILEBANK, pattern.BUCKET, err) - c.SetChainState(false) - return data, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.FILEBANK, pattern.BUCKET, err) - c.SetChainState(false) - return data, err - } - if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE - } - return data, nil -} - -func (c *ChainClient) QueryAllBucket(accountID []byte) ([]types.Bytes, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var data []types.Bytes - - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION - } - - acc, err := types.NewAccountID(accountID) - if err != nil { - return data, errors.Wrap(err, "[NewAccountID]") - } - - owner, err := codec.Encode(*acc) - if err != nil { - return data, errors.Wrap(err, "[EncodeToBytes]") - } - - key, err := types.CreateStorageKey(c.metadata, pattern.FILEBANK, pattern.BUCKETLIST, owner) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.FILEBANK, pattern.BUCKETLIST, err) - c.SetChainState(false) - return data, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.FILEBANK, pattern.BUCKETLIST, err) - c.SetChainState(false) - return data, err - } - if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE - } - return data, nil -} - -func (c *ChainClient) QueryAllBucketString(accountID []byte) ([]string, error) { - bucketlist, err := c.QueryAllBucket(accountID) - if err != nil { - if err.Error() != pattern.ERR_Empty { - return nil, err - } - } - var buckets = make([]string, len(bucketlist)) - for i := 0; i < len(bucketlist); i++ { - buckets[i] = string(bucketlist[i]) - } - return buckets, nil -} - -func (c *ChainClient) QueryFileMetadata(fid string) (pattern.FileMetadata, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var ( - data pattern.FileMetadata - hash pattern.FileHash - ) - - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION - } - - if len(hash) != len(fid) { - return data, errors.New("invalid filehash") - } - - for i := 0; i < len(hash); i++ { - hash[i] = types.U8(fid[i]) - } - - b, err := codec.Encode(hash) - if err != nil { - return data, errors.Wrap(err, "[Encode]") - } - - key, err := types.CreateStorageKey(c.metadata, pattern.FILEBANK, pattern.FILE, b) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.FILEBANK, pattern.FILE, err) - c.SetChainState(false) - return data, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.FILEBANK, pattern.FILE, err) - c.SetChainState(false) - return data, err - } - if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE - } - return data, nil -} - -func (c *ChainClient) QueryFileMetadataByBlock(fid string, block uint64) (pattern.FileMetadata, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var ( - data pattern.FileMetadata - hash pattern.FileHash - ) - - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION - } - - if len(hash) != len(fid) { - return data, errors.New("invalid filehash") - } - - for i := 0; i < len(hash); i++ { - hash[i] = types.U8(fid[i]) - } - - b, err := codec.Encode(hash) - if err != nil { - return data, errors.Wrap(err, "[Encode]") - } - - key, err := types.CreateStorageKey(c.metadata, pattern.FILEBANK, pattern.FILE, b) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.FILEBANK, pattern.FILE, err) - c.SetChainState(false) - return data, err - } - - blockhash, err := c.api.RPC.Chain.GetBlockHash(block) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), pattern.FILEBANK, pattern.FILE, err) - c.SetChainState(false) - return data, err - } - - ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), pattern.FILEBANK, pattern.FILE, err) - c.SetChainState(false) - return data, err - } - if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE - } - return data, nil -} - -func (c *ChainClient) QueryStorageOrder(fid string) (pattern.StorageOrder, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var ( - data pattern.StorageOrder - hash pattern.FileHash - ) - - if len(hash) != len(fid) { - return data, errors.New("invalid filehash") - } - - for i := 0; i < len(hash); i++ { - hash[i] = types.U8(fid[i]) - } - - b, err := codec.Encode(hash) - if err != nil { - return data, errors.Wrap(err, "[Encode]") - } - - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION - } - - key, err := types.CreateStorageKey(c.metadata, pattern.FILEBANK, pattern.DEALMAP, b) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.FILEBANK, pattern.DEALMAP, err) - c.SetChainState(false) - return data, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.FILEBANK, pattern.DEALMAP, err) - c.SetChainState(false) - return data, err - } - if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE - } - return data, nil -} - -func (c *ChainClient) QueryRestoralOrder(fragmentHash string) (pattern.RestoralOrderInfo, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var ( - data pattern.RestoralOrderInfo - hash pattern.FileHash - ) - - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION - } - - if len(hash) != len(fragmentHash) { - return data, errors.New("invalid root hash") - } - - for i := 0; i < len(hash); i++ { - hash[i] = types.U8(fragmentHash[i]) - } - - b, err := codec.Encode(hash) - if err != nil { - return data, errors.Wrap(err, "[Encode]") - } - - key, err := types.CreateStorageKey(c.metadata, pattern.FILEBANK, pattern.RESTORALORDER, b) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.FILEBANK, pattern.RESTORALORDER, err) - c.SetChainState(false) - return data, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.FILEBANK, pattern.RESTORALORDER, err) - c.SetChainState(false) - return data, err - } - if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE - } - return data, nil -} - -func (c *ChainClient) QueryRestoralOrderList() ([]pattern.RestoralOrderInfo, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - var result []pattern.RestoralOrderInfo - - if !c.GetChainState() { - return nil, pattern.ERR_RPC_CONNECTION - } - - key := createPrefixedKey(pattern.FILEBANK, pattern.RESTORALORDER) - keys, err := c.api.RPC.State.GetKeysLatest(key) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetKeysLatest: %v", c.GetCurrentRpcAddr(), pattern.FILEBANK, pattern.RESTORALORDER, err) - c.SetChainState(false) - return nil, err - } - - set, err := c.api.RPC.State.QueryStorageAtLatest(keys) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAtLatest: %v", c.GetCurrentRpcAddr(), pattern.FILEBANK, pattern.RESTORALORDER, err) - c.SetChainState(false) - return nil, err - } - - for _, elem := range set { - for _, change := range elem.Changes { - var data pattern.RestoralOrderInfo - if err := codec.Decode(change.StorageData, &data); err != nil { - continue - } - result = append(result, data) - } - } - return result, nil -} - -func (c *ChainClient) GenerateStorageOrder( - roothash string, - segment []pattern.SegmentDataInfo, - owner []byte, - filename string, - buckname string, - filesize uint64, -) (string, error) { - var err error - var segmentList = make([]pattern.SegmentList, len(segment)) - var user pattern.UserBrief - - for i := 0; i < len(segment); i++ { - hash := filepath.Base(segment[i].SegmentHash) - for k := 0; k < len(hash); k++ { - segmentList[i].SegmentHash[k] = types.U8(hash[k]) - } - segmentList[i].FragmentHash = make([]pattern.FileHash, len(segment[i].FragmentHash)) - for j := 0; j < len(segment[i].FragmentHash); j++ { - hash := filepath.Base(segment[i].FragmentHash[j]) - for k := 0; k < len(hash); k++ { - segmentList[i].FragmentHash[j][k] = types.U8(hash[k]) - } - } - } - - acc, err := types.NewAccountID(owner) - if err != nil { - return "", err - } - user.User = *acc - user.BucketName = types.NewBytes([]byte(buckname)) - user.FileName = types.NewBytes([]byte(filename)) - return c.UploadDeclaration(roothash, segmentList, user, filesize) -} - -func (c *ChainClient) UploadDeclaration(filehash string, dealinfo []pattern.SegmentList, user pattern.UserBrief, filesize uint64) (string, error) { - c.lock.Lock() - defer func() { - c.lock.Unlock() - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var ( - txhash string - hash pattern.FileHash - accountInfo types.AccountInfo - ) - if len(filehash) != len(hash) { - return txhash, errors.New("invalid filehash") - } - if filesize <= 0 { - return txhash, errors.New("invalid filesize") - } - for i := 0; i < len(hash); i++ { - hash[i] = types.U8(filehash[i]) - } - - if !c.GetChainState() { - return txhash, fmt.Errorf("chainSDK.UploadDeclaration(): GetChainState(): %v", pattern.ERR_RPC_CONNECTION) - } - - call, err := types.NewCall(c.metadata, pattern.TX_FILEBANK_UPLOADDEC, hash, dealinfo, user, types.NewU128(*new(big.Int).SetUint64(filesize))) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_UPLOADDEC, err) - c.SetChainState(false) - return txhash, err - } - - ext := types.NewExtrinsic(call) - - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_UPLOADDEC, err) - c.SetChainState(false) - return txhash, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_UPLOADDEC, err) - c.SetChainState(false) - return txhash, err - } - if !ok { - keyStr, _ := utils.NumsToByteStr(key, map[string]bool{}) - return txhash, fmt.Errorf( - "chain rpc.state.GetStorageLatest[%v]: %v", - keyStr, - pattern.ERR_RPC_EMPTY_VALUE, - ) - } - - o := types.SignatureOptions{ - BlockHash: c.genesisHash, - Era: types.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: c.genesisHash, - Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), - SpecVersion: c.runtimeVersion.SpecVersion, - Tip: types.NewUCompactFromUInt(0), - TransactionVersion: c.runtimeVersion.TransactionVersion, - } - - // Sign the transaction - err = ext.Sign(c.keyring, o) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_UPLOADDEC, err) - c.SetChainState(false) - return txhash, err - } - - <-c.txTicker.C - - // Do the transfer and track the actual status - sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { - o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) - err = ext.Sign(c.keyring, o) - if err != nil { - return txhash, errors.Wrap(err, "[Sign]") - } - sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_UPLOADDEC, err) - c.SetChainState(false) - return txhash, err - } - } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_UPLOADDEC, err) - c.SetChainState(false) - return txhash, err - } - } - defer sub.Unsubscribe() - - timeout := time.NewTimer(c.packingTime) - defer timeout.Stop() - - for { - select { - case status := <-sub.Chan(): - if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_FileBank_UploadDeclaration(status.AsInBlock) - return txhash, err - } - case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") - case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT - } - } -} - -func (c *ChainClient) CreateBucket(owner_pkey []byte, name string) (string, error) { - c.lock.Lock() - defer func() { - c.lock.Unlock() - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var ( - txhash string - accountInfo types.AccountInfo - ) - - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION - } - - buckets, err := c.QueryAllBucket(owner_pkey) - if err != nil { - if err.Error() != pattern.ERR_Empty { - return txhash, errors.Wrap(err, "[QueryBucketList]") - } - } else { - for _, v := range buckets { - if utils.CompareSlice(v, []byte(name)) { - return "", nil - } - } - } - - acc, err := types.NewAccountID(owner_pkey) - if err != nil { - return txhash, errors.Wrap(err, "[NewAccountID]") - } - - call, err := types.NewCall(c.metadata, pattern.TX_FILEBANK_PUTBUCKET, *acc, types.NewBytes([]byte(name))) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_PUTBUCKET, err) - c.SetChainState(false) - return txhash, err - } - - ext := types.NewExtrinsic(call) - - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_PUTBUCKET, err) - c.SetChainState(false) - return txhash, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_PUTBUCKET, err) - c.SetChainState(false) - return txhash, err - } - if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE - } - - o := types.SignatureOptions{ - BlockHash: c.genesisHash, - Era: types.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: c.genesisHash, - Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), - SpecVersion: c.runtimeVersion.SpecVersion, - Tip: types.NewUCompactFromUInt(0), - TransactionVersion: c.runtimeVersion.TransactionVersion, - } - - // Sign the transaction - err = ext.Sign(c.keyring, o) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_PUTBUCKET, err) - c.SetChainState(false) - return txhash, err - } - - <-c.txTicker.C - - // Do the transfer and track the actual status - sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_PUTBUCKET, err) - c.SetChainState(false) - return txhash, err - } - defer sub.Unsubscribe() - - timeout := time.NewTimer(c.packingTime) - defer timeout.Stop() - - for { - select { - case status := <-sub.Chan(): - if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_FileBank_CreateBucket(status.AsInBlock) - return txhash, err - } - case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") - case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT - } - } -} - -func (c *ChainClient) DeleteBucket(owner_pkey []byte, name string) (string, error) { - c.lock.Lock() - defer func() { - c.lock.Unlock() - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var ( - txhash string - accountInfo types.AccountInfo - ) - - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION - } - - acc, err := types.NewAccountID(owner_pkey) - if err != nil { - return txhash, errors.Wrap(err, "[NewAccountID]") - } - - call, err := types.NewCall(c.metadata, pattern.TX_FILEBANK_DELBUCKET, *acc, types.NewBytes([]byte(name))) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_DELBUCKET, err) - c.SetChainState(false) - return txhash, err - } - - ext := types.NewExtrinsic(call) - - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_DELBUCKET, err) - c.SetChainState(false) - return txhash, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_DELBUCKET, err) - c.SetChainState(false) - return txhash, err - } - if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE - } - - o := types.SignatureOptions{ - BlockHash: c.genesisHash, - Era: types.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: c.genesisHash, - Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), - SpecVersion: c.runtimeVersion.SpecVersion, - Tip: types.NewUCompactFromUInt(0), - TransactionVersion: c.runtimeVersion.TransactionVersion, - } - - // Sign the transaction - err = ext.Sign(c.keyring, o) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_DELBUCKET, err) - c.SetChainState(false) - return txhash, err - } - - <-c.txTicker.C - - // Do the transfer and track the actual status - sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_DELBUCKET, err) - c.SetChainState(false) - return txhash, err - } - defer sub.Unsubscribe() - - timeout := time.NewTimer(c.packingTime) - defer timeout.Stop() - - for { - select { - case status := <-sub.Chan(): - if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_FileBank_DeleteBucket(status.AsInBlock) - return txhash, err - } - case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") - case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT - } - } -} - -func (c *ChainClient) DeleteFile(puk []byte, filehash []string) (string, []pattern.FileHash, error) { - c.lock.Lock() - defer func() { - c.lock.Unlock() - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var ( - txhash string - accountInfo types.AccountInfo - hashs = make([]pattern.FileHash, len(filehash)) - ) - - if !c.GetChainState() { - return txhash, hashs, pattern.ERR_RPC_CONNECTION - } - - for j := 0; j < len(filehash); j++ { - if len(filehash[j]) != len(hashs[j]) { - return txhash, hashs, errors.New("invalid filehash") - } - for i := 0; i < len(hashs[j]); i++ { - hashs[j][i] = types.U8(filehash[j][i]) - } - } - - acc, err := types.NewAccountID(puk) - if err != nil { - return txhash, hashs, errors.Wrap(err, "[NewAccountID]") - } - - call, err := types.NewCall(c.metadata, pattern.TX_FILEBANK_DELFILE, *acc, hashs) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_DELFILE, err) - c.SetChainState(false) - return txhash, hashs, err - } - - ext := types.NewExtrinsic(call) - - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_DELFILE, err) - c.SetChainState(false) - return txhash, hashs, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_DELFILE, err) - c.SetChainState(false) - return txhash, hashs, err - } - if !ok { - return txhash, hashs, pattern.ERR_RPC_EMPTY_VALUE - } - - o := types.SignatureOptions{ - BlockHash: c.genesisHash, - Era: types.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: c.genesisHash, - Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), - SpecVersion: c.runtimeVersion.SpecVersion, - Tip: types.NewUCompactFromUInt(0), - TransactionVersion: c.runtimeVersion.TransactionVersion, - } - - // Sign the transaction - err = ext.Sign(c.keyring, o) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_DELFILE, err) - c.SetChainState(false) - return txhash, hashs, err - } - - <-c.txTicker.C - - // Do the transfer and track the actual status - sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { - o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) - err = ext.Sign(c.keyring, o) - if err != nil { - return txhash, hashs, errors.Wrap(err, "[Sign]") - } - sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_DELFILE, err) - c.SetChainState(false) - return txhash, hashs, err - } - } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_DELFILE, err) - c.SetChainState(false) - return txhash, hashs, err - } - } - - defer sub.Unsubscribe() - - timeout := time.NewTimer(c.packingTime) - defer timeout.Stop() - - for { - select { - case status := <-sub.Chan(): - if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_FileBank_DeleteFile(status.AsInBlock) - return txhash, nil, err - } - case err = <-sub.Err(): - return txhash, hashs, errors.Wrap(err, "[sub]") - case <-timeout.C: - return txhash, hashs, pattern.ERR_RPC_TIMEOUT - } - } -} - -func (c *ChainClient) ReportFile(index uint8, roothash string) (string, error) { - var hashs pattern.FileHash - - for j := 0; j < len(roothash); j++ { - hashs[j] = types.U8(roothash[j]) - } - return c.SubmitFileReport(types.U8(index), hashs) -} - -func (c *ChainClient) SubmitFileReport(index types.U8, roothash pattern.FileHash) (string, error) { - c.lock.Lock() - defer func() { - c.lock.Unlock() - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var ( - txhash string - accountInfo types.AccountInfo - ) - - if index == 0 || int(index) > (pattern.DataShards+pattern.ParShards) { - return "", errors.New("invalid index") - } - - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION - } - - call, err := types.NewCall(c.metadata, pattern.TX_FILEBANK_FILEREPORT, index, roothash) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_FILEREPORT, err) - c.SetChainState(false) - return txhash, err - } - - ext := types.NewExtrinsic(call) - - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_FILEREPORT, err) - c.SetChainState(false) - return txhash, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_FILEREPORT, err) - c.SetChainState(false) - return txhash, err - } - if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE - } - - o := types.SignatureOptions{ - BlockHash: c.genesisHash, - Era: types.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: c.genesisHash, - Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), - SpecVersion: c.runtimeVersion.SpecVersion, - Tip: types.NewUCompactFromUInt(0), - TransactionVersion: c.runtimeVersion.TransactionVersion, - } - - // Sign the transaction - err = ext.Sign(c.keyring, o) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_FILEREPORT, err) - c.SetChainState(false) - return txhash, err - } - - <-c.txTicker.C - - // Do the transfer and track the actual status - sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { - o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) - err = ext.Sign(c.keyring, o) - if err != nil { - return txhash, errors.Wrap(err, "[Sign]") - } - sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_FILEREPORT, err) - c.SetChainState(false) - return txhash, err - } - } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_FILEREPORT, err) - c.SetChainState(false) - return txhash, err - } - } - defer sub.Unsubscribe() - - timeout := time.NewTimer(c.packingTime) - defer timeout.Stop() - - for { - select { - case status := <-sub.Chan(): - if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_FileBank_TransferReport(status.AsInBlock) - return txhash, err - } - case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") - case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT - } - } -} - -func (c *ChainClient) GenerateRestoralOrder(rootHash, fragmentHash string) (string, error) { - c.lock.Lock() - defer func() { - c.lock.Unlock() - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var ( - txhash string - accountInfo types.AccountInfo - ) - - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION - } - - var rooth pattern.FileHash - var fragh pattern.FileHash - - if len(rootHash) != len(rooth) { - return txhash, errors.New("invalid root hash") - } - - if len(fragmentHash) != len(fragh) { - return txhash, errors.New("invalid fragment hash") - } - - for i := 0; i < len(rootHash); i++ { - rooth[i] = types.U8(rootHash[i]) - } - - for i := 0; i < len(fragmentHash); i++ { - fragh[i] = types.U8(fragmentHash[i]) - } - - call, err := types.NewCall(c.metadata, pattern.TX_FILEBANK_GENRESTOREORDER, rooth, fragh) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_GENRESTOREORDER, err) - c.SetChainState(false) - return txhash, err - } - - ext := types.NewExtrinsic(call) - - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_GENRESTOREORDER, err) - c.SetChainState(false) - return txhash, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_GENRESTOREORDER, err) - c.SetChainState(false) - return txhash, err - } - if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE - } - - o := types.SignatureOptions{ - BlockHash: c.genesisHash, - Era: types.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: c.genesisHash, - Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), - SpecVersion: c.runtimeVersion.SpecVersion, - Tip: types.NewUCompactFromUInt(0), - TransactionVersion: c.runtimeVersion.TransactionVersion, - } - - // Sign the transaction - err = ext.Sign(c.keyring, o) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_GENRESTOREORDER, err) - c.SetChainState(false) - return txhash, err - } - - <-c.txTicker.C - - // Do the transfer and track the actual status - sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_GENRESTOREORDER, err) - c.SetChainState(false) - return txhash, err - } - defer sub.Unsubscribe() - - timeout := time.NewTimer(c.packingTime) - defer timeout.Stop() - - for { - select { - case status := <-sub.Chan(): - if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_FileBank_GenRestoralOrder(status.AsInBlock) - return txhash, err - } - case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") - case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT - } - } -} - -func (c *ChainClient) ClaimRestoralOrder(fragmentHash string) (string, error) { - c.lock.Lock() - defer func() { - c.lock.Unlock() - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var ( - txhash string - accountInfo types.AccountInfo - ) - - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION - } - - var fragh pattern.FileHash - - if len(fragmentHash) != len(fragh) { - return txhash, errors.New("invalid fragment hash") - } - - for i := 0; i < len(fragmentHash); i++ { - fragh[i] = types.U8(fragmentHash[i]) - } - - call, err := types.NewCall(c.metadata, pattern.TX_FILEBANK_CLAIMRESTOREORDER, fragh) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CLAIMRESTOREORDER, err) - c.SetChainState(false) - return txhash, err - } - - ext := types.NewExtrinsic(call) - - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CLAIMRESTOREORDER, err) - c.SetChainState(false) - return txhash, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CLAIMRESTOREORDER, err) - c.SetChainState(false) - return txhash, err - } - if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE - } - - o := types.SignatureOptions{ - BlockHash: c.genesisHash, - Era: types.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: c.genesisHash, - Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), - SpecVersion: c.runtimeVersion.SpecVersion, - Tip: types.NewUCompactFromUInt(0), - TransactionVersion: c.runtimeVersion.TransactionVersion, - } - - // Sign the transaction - err = ext.Sign(c.keyring, o) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CLAIMRESTOREORDER, err) - c.SetChainState(false) - return txhash, err - } - - <-c.txTicker.C - - // Do the transfer and track the actual status - sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { - o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) - err = ext.Sign(c.keyring, o) - if err != nil { - return txhash, errors.Wrap(err, "[Sign]") - } - sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CLAIMRESTOREORDER, err) - c.SetChainState(false) - return txhash, err - } - } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CLAIMRESTOREORDER, err) - c.SetChainState(false) - return txhash, err - } - } - defer sub.Unsubscribe() - - timeout := time.NewTimer(c.packingTime) - defer timeout.Stop() - - for { - select { - case status := <-sub.Chan(): - if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_FileBank_ClaimRestoralOrder(status.AsInBlock) - return txhash, err - } - case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") - case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT - } - } -} - -func (c *ChainClient) ClaimRestoralNoExistOrder(puk []byte, rootHash, restoralFragmentHash string) (string, error) { - c.lock.Lock() - defer func() { - c.lock.Unlock() - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var ( - txhash string - accountInfo types.AccountInfo - ) - - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION - } - - acc, err := types.NewAccountID(puk) - if err != nil { - return txhash, errors.Wrap(err, "[NewAccountID]") - } - - var rooth pattern.FileHash - var fragh pattern.FileHash - - if len(rootHash) != len(rooth) { - return txhash, errors.New("invalid root hash") - } - - if len(restoralFragmentHash) != len(fragh) { - return txhash, errors.New("invalid fragment hash") - } - - for i := 0; i < len(rootHash); i++ { - rooth[i] = types.U8(rootHash[i]) - } - - for i := 0; i < len(restoralFragmentHash); i++ { - fragh[i] = types.U8(restoralFragmentHash[i]) - } - - call, err := types.NewCall(c.metadata, pattern.TX_FILEBANK_CLAIMNOEXISTORDER, *acc, rooth, fragh) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CLAIMNOEXISTORDER, err) - c.SetChainState(false) - return txhash, err - } - - ext := types.NewExtrinsic(call) - - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CLAIMNOEXISTORDER, err) - c.SetChainState(false) - return txhash, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CLAIMNOEXISTORDER, err) - c.SetChainState(false) - return txhash, err - } - if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE - } - - o := types.SignatureOptions{ - BlockHash: c.genesisHash, - Era: types.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: c.genesisHash, - Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), - SpecVersion: c.runtimeVersion.SpecVersion, - Tip: types.NewUCompactFromUInt(0), - TransactionVersion: c.runtimeVersion.TransactionVersion, - } - - // Sign the transaction - err = ext.Sign(c.keyring, o) - if err != nil { - return txhash, errors.Wrap(err, "[Sign]") - } - - <-c.txTicker.C - - // Do the transfer and track the actual status - sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { - o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) - err = ext.Sign(c.keyring, o) - if err != nil { - return txhash, errors.Wrap(err, "[Sign]") - } - sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CLAIMNOEXISTORDER, err) - c.SetChainState(false) - return txhash, err - } - } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CLAIMNOEXISTORDER, err) - c.SetChainState(false) - return txhash, err - } - } - defer sub.Unsubscribe() - - timeout := time.NewTimer(c.packingTime) - defer timeout.Stop() - - for { - select { - case status := <-sub.Chan(): - if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_FileBank_ClaimRestoralOrder(status.AsInBlock) - return txhash, err - } - case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") - case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT - } - } -} - -func (c *ChainClient) RestoralComplete(restoralFragmentHash string) (string, error) { - c.lock.Lock() - defer func() { - c.lock.Unlock() - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var ( - txhash string - accountInfo types.AccountInfo - ) - - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION - } - - var fragh pattern.FileHash - - if len(restoralFragmentHash) != len(fragh) { - return txhash, errors.New("invalid fragment hash") - } - - for i := 0; i < len(restoralFragmentHash); i++ { - fragh[i] = types.U8(restoralFragmentHash[i]) - } - - call, err := types.NewCall(c.metadata, pattern.TX_FILEBANK_RESTORALCOMPLETE, fragh) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_RESTORALCOMPLETE, err) - c.SetChainState(false) - return txhash, err - } - - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_RESTORALCOMPLETE, err) - c.SetChainState(false) - return txhash, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_RESTORALCOMPLETE, err) - c.SetChainState(false) - return txhash, err - } - if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE - } - - o := types.SignatureOptions{ - BlockHash: c.genesisHash, - Era: types.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: c.genesisHash, - Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), - SpecVersion: c.runtimeVersion.SpecVersion, - Tip: types.NewUCompactFromUInt(0), - TransactionVersion: c.runtimeVersion.TransactionVersion, - } - - ext := types.NewExtrinsic(call) - - // Sign the transaction - err = ext.Sign(c.keyring, o) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_RESTORALCOMPLETE, err) - c.SetChainState(false) - return txhash, err - } - - // Do the transfer and track the actual status - sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { - o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) - err = ext.Sign(c.keyring, o) - if err != nil { - return txhash, errors.Wrap(err, "[Sign]") - } - sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_RESTORALCOMPLETE, err) - c.SetChainState(false) - return txhash, err - } - } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_RESTORALCOMPLETE, err) - c.SetChainState(false) - return txhash, err - } - } - defer sub.Unsubscribe() - - timeout := time.NewTimer(c.packingTime) - defer timeout.Stop() - - for { - select { - case status := <-sub.Chan(): - if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_FileBank_RecoveryCompleted(status.AsInBlock) - return txhash, err - } - case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") - case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT - } - } -} - -func (c *ChainClient) CertIdleSpace(idleSignInfo pattern.SpaceProofInfo, teeSignWithAcc, teeSign types.Bytes, teePuk pattern.WorkerPublicKey) (string, error) { - c.lock.Lock() - defer func() { - c.lock.Unlock() - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var ( - txhash string - accountInfo types.AccountInfo - ) - - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION - } - - call, err := types.NewCall(c.metadata, pattern.TX_FILEBANK_CERTIDLESPACE, idleSignInfo, teeSignWithAcc, teeSign, teePuk) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CERTIDLESPACE, err) - c.SetChainState(false) - return txhash, err - } - - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CERTIDLESPACE, err) - c.SetChainState(false) - return txhash, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CERTIDLESPACE, err) - c.SetChainState(false) - return txhash, err - } - if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE - } - - o := types.SignatureOptions{ - BlockHash: c.genesisHash, - Era: types.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: c.genesisHash, - Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), - SpecVersion: c.runtimeVersion.SpecVersion, - Tip: types.NewUCompactFromUInt(0), - TransactionVersion: c.runtimeVersion.TransactionVersion, - } - - ext := types.NewExtrinsic(call) - - // Sign the transaction - err = ext.Sign(c.keyring, o) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CERTIDLESPACE, err) - c.SetChainState(false) - return txhash, err - } - - // Do the transfer and track the actual status - sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { - o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) - err = ext.Sign(c.keyring, o) - if err != nil { - return txhash, errors.Wrap(err, "[Sign]") - } - sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CERTIDLESPACE, err) - c.SetChainState(false) - return txhash, err - } - } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CERTIDLESPACE, err) - c.SetChainState(false) - return txhash, err - } - } - defer sub.Unsubscribe() - - timeout := time.NewTimer(c.packingTime) - defer timeout.Stop() - - for { - select { - case status := <-sub.Chan(): - if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_FileBank_IdleSpaceCert(status.AsInBlock) - return txhash, err - } - case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") - case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT - } - } -} - -func (c *ChainClient) ReplaceIdleSpace(idleSignInfo pattern.SpaceProofInfo, teeSignWithAcc, teeSign types.Bytes, teePuk pattern.WorkerPublicKey) (string, error) { - c.lock.Lock() - defer func() { - c.lock.Unlock() - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var ( - txhash string - accountInfo types.AccountInfo - ) - - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION - } - - call, err := types.NewCall(c.metadata, pattern.TX_FILEBANK_REPLACEIDLESPACE, idleSignInfo, teeSignWithAcc, teeSign, teePuk) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_REPLACEIDLESPACE, err) - c.SetChainState(false) - return txhash, err - } - - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_REPLACEIDLESPACE, err) - c.SetChainState(false) - return txhash, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_REPLACEIDLESPACE, err) - c.SetChainState(false) - return txhash, err - } - if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE - } - - o := types.SignatureOptions{ - BlockHash: c.genesisHash, - Era: types.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: c.genesisHash, - Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), - SpecVersion: c.runtimeVersion.SpecVersion, - Tip: types.NewUCompactFromUInt(0), - TransactionVersion: c.runtimeVersion.TransactionVersion, - } - - ext := types.NewExtrinsic(call) - - // Sign the transaction - err = ext.Sign(c.keyring, o) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_REPLACEIDLESPACE, err) - c.SetChainState(false) - return txhash, err - } - - // Do the transfer and track the actual status - sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { - o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) - err = ext.Sign(c.keyring, o) - if err != nil { - return txhash, errors.Wrap(err, "[Sign]") - } - sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_REPLACEIDLESPACE, err) - c.SetChainState(false) - return txhash, err - } - } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_REPLACEIDLESPACE, err) - c.SetChainState(false) - return txhash, err - } - } - defer sub.Unsubscribe() - - timeout := time.NewTimer(c.packingTime) - defer timeout.Stop() - - for { - select { - case status := <-sub.Chan(): - if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_FileBank_ReplaceIdleSpace(status.AsInBlock) - return txhash, err - } - case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") - case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT - } - } -} - -func (c *ChainClient) ReportTagCalculated(teeSig types.Bytes, tagSigInfo pattern.TagSigInfo) (string, error) { - c.lock.Lock() - defer func() { - c.lock.Unlock() - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var ( - txhash string - accountInfo types.AccountInfo - ) - - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION - } - - call, err := types.NewCall(c.metadata, pattern.TX_FILEBANK_CALCULATEREPORT, teeSig, tagSigInfo) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CALCULATEREPORT, err) - c.SetChainState(false) - return txhash, err - } - - ext := types.NewExtrinsic(call) - - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CALCULATEREPORT, err) - c.SetChainState(false) - return txhash, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CALCULATEREPORT, err) - c.SetChainState(false) - return txhash, err - } - if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE - } - - o := types.SignatureOptions{ - BlockHash: c.genesisHash, - Era: types.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: c.genesisHash, - Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), - SpecVersion: c.runtimeVersion.SpecVersion, - Tip: types.NewUCompactFromUInt(0), - TransactionVersion: c.runtimeVersion.TransactionVersion, - } - - // Sign the transaction - err = ext.Sign(c.keyring, o) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CALCULATEREPORT, err) - c.SetChainState(false) - return txhash, err - } - - <-c.txTicker.C - - // Do the transfer and track the actual status - sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { - o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) - err = ext.Sign(c.keyring, o) - if err != nil { - return txhash, errors.Wrap(err, "[Sign]") - } - sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CALCULATEREPORT, err) - c.SetChainState(false) - return txhash, err - } - } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_FILEBANK_CALCULATEREPORT, err) - c.SetChainState(false) - return txhash, err - } - } - defer sub.Unsubscribe() - - timeout := time.NewTimer(c.packingTime) - defer timeout.Stop() - - for { - select { - case status := <-sub.Chan(): - if status.IsInBlock { - txhash = status.AsInBlock.Hex() - blockhash := status.AsInBlock - _, err = c.RetrieveEvent_FileBank_CalculateReport(blockhash) - return txhash, err - } - case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") - case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT - } - } -} diff --git a/chain/file_bank.go b/chain/file_bank.go new file mode 100755 index 0000000..b707fca --- /dev/null +++ b/chain/file_bank.go @@ -0,0 +1,1980 @@ +/* + Copyright (C) CESS. All rights reserved. + Copyright (C) Cumulus Encrypted Storage System. All rights reserved. + + SPDX-License-Identifier: Apache-2.0 +*/ + +package chain + +import ( + "fmt" + "log" + "math/big" + "path/filepath" + "strings" + "time" + + "github.com/CESSProject/cess-go-sdk/config" + "github.com/CESSProject/cess-go-sdk/utils" + "github.com/centrifuge/go-substrate-rpc-client/v4/types" + "github.com/centrifuge/go-substrate-rpc-client/v4/types/codec" + "github.com/pkg/errors" +) + +// QueryBucket query user's bucket information +// - accountID: user account +// - bucketName: bucket name +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - BucketInfo: bucket info +// - error: error message +func (c *ChainClient) QueryBucket(accountID []byte, bucketName string, block int32) (BucketInfo, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var data BucketInfo + + if !c.GetRpcState() { + return data, ERR_RPC_CONNECTION + } + + acc, err := types.NewAccountID(accountID) + if err != nil { + return data, errors.Wrap(err, "[NewAccountID]") + } + + owner, err := codec.Encode(*acc) + if err != nil { + return data, errors.Wrap(err, "[EncodeToBytes]") + } + + name, err := codec.Encode(bucketName) + if err != nil { + return data, errors.Wrap(err, "[Encode]") + } + + key, err := types.CreateStorageKey(c.metadata, FileBank, Bucket, owner, name) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), FileBank, Bucket, err) + return data, err + } + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), FileBank, Bucket, err) + c.SetRpcState(false) + return data, err + } + if !ok { + return data, ERR_RPC_EMPTY_VALUE + } + return data, nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + return data, err + } + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), FileBank, Bucket, err) + c.SetRpcState(false) + return data, err + } + if !ok { + return data, ERR_RPC_EMPTY_VALUE + } + return data, nil +} + +// QueryDealMap query file storage order +// - fid: file identification +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - StorageOrder: file storage order +// - error: error message +func (c *ChainClient) QueryDealMap(fid string, block int32) (StorageOrder, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var ( + data StorageOrder + hash FileHash + ) + + if len(fid) != FileHashLen { + return data, errors.New("invalid filehash") + } + + for i := 0; i < len(hash); i++ { + hash[i] = types.U8(fid[i]) + } + + param_hash, err := codec.Encode(hash) + if err != nil { + return data, errors.Wrap(err, "[Encode]") + } + + if !c.GetRpcState() { + return data, ERR_RPC_CONNECTION + } + + key, err := types.CreateStorageKey(c.metadata, FileBank, DealMap, param_hash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), FileBank, DealMap, err) + return data, err + } + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), FileBank, DealMap, err) + c.SetRpcState(false) + return data, err + } + if !ok { + return data, ERR_RPC_EMPTY_VALUE + } + return data, nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), FileBank, DealMap, err) + return data, err + } + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), FileBank, DealMap, err) + c.SetRpcState(false) + return data, err + } + if !ok { + return data, ERR_RPC_EMPTY_VALUE + } + return data, nil +} + +// QueryFile query file metadata +// - fid: file identification +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - FileMetadata: file metadata +// - error: error message +func (c *ChainClient) QueryFile(fid string, block int32) (FileMetadata, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var ( + data FileMetadata + hash FileHash + ) + + if !c.GetRpcState() { + return data, ERR_RPC_CONNECTION + } + + if len(fid) != FileHashLen { + return data, errors.New("invalid filehash") + } + + for i := 0; i < len(hash); i++ { + hash[i] = types.U8(fid[i]) + } + + param_hash, err := codec.Encode(hash) + if err != nil { + return data, errors.Wrap(err, "[Encode]") + } + + key, err := types.CreateStorageKey(c.metadata, FileBank, File, param_hash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), FileBank, File, err) + return data, err + } + + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), FileBank, File, err) + c.SetRpcState(false) + return data, err + } + if !ok { + return data, ERR_RPC_EMPTY_VALUE + } + return data, nil + } + + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), FileBank, File, err) + return data, err + } + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), FileBank, File, err) + c.SetRpcState(false) + return data, err + } + if !ok { + return data, ERR_RPC_EMPTY_VALUE + } + return data, nil +} + +// QueryRestoralOrder query file restoral order +// - fragmentHash: fragment hash +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - RestoralOrderInfo: restoral order info +// - error: error message +func (c *ChainClient) QueryRestoralOrder(fragmentHash string, block int32) (RestoralOrderInfo, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var ( + data RestoralOrderInfo + hash FileHash + ) + + if !c.GetRpcState() { + return data, ERR_RPC_CONNECTION + } + + if len(fragmentHash) != FileHashLen { + return data, errors.New("invalid fragment hash") + } + + for i := 0; i < len(hash); i++ { + hash[i] = types.U8(fragmentHash[i]) + } + + param_hash, err := codec.Encode(hash) + if err != nil { + return data, errors.Wrap(err, "[Encode]") + } + + key, err := types.CreateStorageKey(c.metadata, FileBank, RestoralOrder, param_hash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), FileBank, RestoralOrder, err) + return data, err + } + + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), FileBank, RestoralOrder, err) + c.SetRpcState(false) + return data, err + } + if !ok { + return data, ERR_RPC_EMPTY_VALUE + } + return data, nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + return data, err + } + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), FileBank, RestoralOrder, err) + c.SetRpcState(false) + return data, err + } + if !ok { + return data, ERR_RPC_EMPTY_VALUE + } + return data, nil +} + +// QueryAllRestoralOrder query all file restoral order +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - []RestoralOrderInfo: all restoral order info +// - error: error message +func (c *ChainClient) QueryAllRestoralOrder(block int32) ([]RestoralOrderInfo, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + var result []RestoralOrderInfo + + if !c.GetRpcState() { + return nil, ERR_RPC_CONNECTION + } + + key := CreatePrefixedKey(FileBank, RestoralOrder) + keys, err := c.api.RPC.State.GetKeysLatest(key) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetKeysLatest: %v", c.GetCurrentRpcAddr(), FileBank, RestoralOrder, err) + c.SetRpcState(false) + return nil, err + } + var set []types.StorageChangeSet + if block < 0 { + set, err = c.api.RPC.State.QueryStorageAtLatest(keys) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAtLatest: %v", c.GetCurrentRpcAddr(), FileBank, RestoralOrder, err) + c.SetRpcState(false) + return nil, err + } + } else { + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + return nil, err + } + set, err = c.api.RPC.State.QueryStorageAt(keys, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAt: %v", c.GetCurrentRpcAddr(), FileBank, RestoralOrder, err) + c.SetRpcState(false) + return nil, err + } + } + + for _, elem := range set { + for _, change := range elem.Changes { + var data RestoralOrderInfo + if err := codec.Decode(change.StorageData, &data); err != nil { + continue + } + result = append(result, data) + } + } + return result, nil +} + +// QueryAllBucketName query user's all bucket names +// - accountID: user account +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - []string: all bucket names +// - error: error message +func (c *ChainClient) QueryAllBucketName(accountID []byte, block int32) ([]string, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var data []types.Bytes + var value []string + + if !c.GetRpcState() { + return nil, ERR_RPC_CONNECTION + } + + acc, err := types.NewAccountID(accountID) + if err != nil { + return nil, errors.Wrap(err, "[NewAccountID]") + } + + owner, err := codec.Encode(*acc) + if err != nil { + return nil, errors.Wrap(err, "[EncodeToBytes]") + } + + key, err := types.CreateStorageKey(c.metadata, FileBank, UserBucketList, owner) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), FileBank, UserBucketList, err) + return nil, err + } + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), FileBank, UserBucketList, err) + c.SetRpcState(false) + return nil, err + } + if !ok { + return []string{}, ERR_RPC_EMPTY_VALUE + } + for i := 0; i < len(data); i++ { + value[i] = string(data[i]) + } + return value, nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + return nil, err + } + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), FileBank, UserBucketList, err) + c.SetRpcState(false) + return nil, err + } + if !ok { + return []string{}, ERR_RPC_EMPTY_VALUE + } + for i := 0; i < len(data); i++ { + value[i] = string(data[i]) + } + return value, nil +} + +// QueryAllUserFiles query user's all files +// - accountID: user account +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - []string: all file identification +// - error: error message +func (c *ChainClient) QueryAllUserFiles(accountID []byte, block int32) ([]string, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var data []UserFileSliceInfo + var value []string + + if !c.GetRpcState() { + return nil, ERR_RPC_CONNECTION + } + + acc, err := types.NewAccountID(accountID) + if err != nil { + return nil, errors.Wrap(err, "[NewAccountID]") + } + + owner, err := codec.Encode(*acc) + if err != nil { + return nil, errors.Wrap(err, "[EncodeToBytes]") + } + + key, err := types.CreateStorageKey(c.metadata, FileBank, UserHoldFileList, owner) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), FileBank, UserHoldFileList, err) + return nil, err + } + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), FileBank, UserHoldFileList, err) + c.SetRpcState(false) + return nil, err + } + if !ok { + return []string{}, ERR_RPC_EMPTY_VALUE + } + for i := 0; i < len(data); i++ { + value[i] = string(data[i].Filehash[:]) + } + return value, nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + return nil, err + } + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), FileBank, UserHoldFileList, err) + c.SetRpcState(false) + return nil, err + } + if !ok { + return []string{}, ERR_RPC_EMPTY_VALUE + } + for i := 0; i < len(data); i++ { + value[i] = string(data[i].Filehash[:]) + } + return value, nil +} + +// GenerateStorageOrder generate a file storage order +// - fid: file identification +// - segment: segment info +// - owner: account of the file owner +// - filename: file name +// - buckname: bucket to store the file +// - filesize: file size +// +// Return: +// - string: block hash +// - error: error message +func (c *ChainClient) GenerateStorageOrder(fid string, segment []SegmentDataInfo, owner []byte, filename string, buckname string, filesize uint64) (string, error) { + var err error + var segmentList = make([]SegmentList, len(segment)) + var user UserBrief + + for i := 0; i < len(segment); i++ { + hash := filepath.Base(segment[i].SegmentHash) + for k := 0; k < len(hash); k++ { + segmentList[i].SegmentHash[k] = types.U8(hash[k]) + } + segmentList[i].FragmentHash = make([]FileHash, len(segment[i].FragmentHash)) + for j := 0; j < len(segment[i].FragmentHash); j++ { + hash := filepath.Base(segment[i].FragmentHash[j]) + for k := 0; k < len(hash); k++ { + segmentList[i].FragmentHash[j][k] = types.U8(hash[k]) + } + } + } + + acc, err := types.NewAccountID(owner) + if err != nil { + return "", err + } + user.User = *acc + user.BucketName = types.NewBytes([]byte(buckname)) + user.FileName = types.NewBytes([]byte(filename)) + return c.UploadDeclaration(fid, segmentList, user, filesize) +} + +// GenerateStorageOrder generate a file storage order +// - fid: file identification +// - segment: segment info +// - user: UserBrief +// - filename: file name +// - filesize: file size +// +// Return: +// - string: block hash +// - error: error message +func (c *ChainClient) UploadDeclaration(fid string, segment []SegmentList, user UserBrief, filesize uint64) (string, error) { + c.lock.Lock() + defer func() { + c.lock.Unlock() + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var ( + blockhash string + hash FileHash + accountInfo types.AccountInfo + ) + if len(fid) != FileHashLen { + return blockhash, errors.New("invalid filehash") + } + if filesize <= 0 { + return blockhash, errors.New("invalid filesize") + } + for i := 0; i < len(hash); i++ { + hash[i] = types.U8(fid[i]) + } + + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION + } + + call, err := types.NewCall(c.metadata, TX_FileBank_UploadDeclaration, hash, segment, user, types.NewU128(*new(big.Int).SetUint64(filesize))) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_FileBank_UploadDeclaration, err) + return blockhash, err + } + + ext := types.NewExtrinsic(call) + + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_FileBank_UploadDeclaration, err) + return blockhash, err + } + + ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_FileBank_UploadDeclaration, err) + c.SetRpcState(false) + return blockhash, err + } + if !ok { + keyStr, _ := utils.NumsToByteStr(key, map[string]bool{}) + return blockhash, fmt.Errorf( + "chain rpc.state.GetStorageLatest[%v]: %v", + keyStr, + ERR_RPC_EMPTY_VALUE, + ) + } + + o := types.SignatureOptions{ + BlockHash: c.genesisHash, + Era: types.ExtrinsicEra{IsMortalEra: false}, + GenesisHash: c.genesisHash, + Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), + SpecVersion: c.runtimeVersion.SpecVersion, + Tip: types.NewUCompactFromUInt(0), + TransactionVersion: c.runtimeVersion.TransactionVersion, + } + + // Sign the transaction + err = ext.Sign(c.keyring, o) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_FileBank_UploadDeclaration, err) + return blockhash, err + } + + <-c.txTicker.C + + // Do the transfer and track the actual status + sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { + o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) + err = ext.Sign(c.keyring, o) + if err != nil { + return blockhash, errors.Wrap(err, "[Sign]") + } + <-c.txTicker.C + sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_UploadDeclaration, err) + c.SetRpcState(false) + return blockhash, err + } + } else { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_UploadDeclaration, err) + c.SetRpcState(false) + return blockhash, err + } + } + defer sub.Unsubscribe() + + timeout := time.NewTimer(c.packingTime) + defer timeout.Stop() + + for { + select { + case status := <-sub.Chan(): + if status.IsInBlock { + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_FileBank_UploadDeclaration(status.AsInBlock) + return blockhash, err + } + case err = <-sub.Err(): + return blockhash, errors.Wrap(err, "[sub]") + case <-timeout.C: + return blockhash, ERR_RPC_TIMEOUT + } + } +} + +// CreateBucket create a bucket for owner +// - owner: bucket owner account +// - bucketName: bucket name +// +// Return: +// - string: block hash +// - error: error message +// +// Note: +// - cannot create a bucket that already exists +// - if you are not the owner, the owner account must be authorised to you +// +// For details on bucket naming rules, see: +// - https://docs.cess.cloud/deoss/get-started/deoss-gateway/step-1-create-a-bucket#naming-conventions-for-a-bucket +func (c *ChainClient) CreateBucket(owner []byte, bucketName string) (string, error) { + c.lock.Lock() + defer func() { + c.lock.Unlock() + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var ( + blockhash string + accountInfo types.AccountInfo + ) + + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION + } + + acc, err := types.NewAccountID(owner) + if err != nil { + return blockhash, errors.Wrap(err, "[NewAccountID]") + } + + call, err := types.NewCall(c.metadata, TX_FileBank_CreateBucket, *acc, types.NewBytes([]byte(bucketName))) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_FileBank_CreateBucket, err) + return blockhash, err + } + + ext := types.NewExtrinsic(call) + + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_FileBank_CreateBucket, err) + return blockhash, err + } + + ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_FileBank_CreateBucket, err) + c.SetRpcState(false) + return blockhash, err + } + if !ok { + return blockhash, ERR_RPC_EMPTY_VALUE + } + + o := types.SignatureOptions{ + BlockHash: c.genesisHash, + Era: types.ExtrinsicEra{IsMortalEra: false}, + GenesisHash: c.genesisHash, + Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), + SpecVersion: c.runtimeVersion.SpecVersion, + Tip: types.NewUCompactFromUInt(0), + TransactionVersion: c.runtimeVersion.TransactionVersion, + } + + // Sign the transaction + err = ext.Sign(c.keyring, o) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_FileBank_CreateBucket, err) + return blockhash, err + } + + <-c.txTicker.C + + // Do the transfer and track the actual status + sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_CreateBucket, err) + c.SetRpcState(false) + return blockhash, err + } + defer sub.Unsubscribe() + + timeout := time.NewTimer(c.packingTime) + defer timeout.Stop() + + for { + select { + case status := <-sub.Chan(): + if status.IsInBlock { + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_FileBank_CreateBucket(status.AsInBlock) + return blockhash, err + } + case err = <-sub.Err(): + return blockhash, errors.Wrap(err, "[sub]") + case <-timeout.C: + return blockhash, ERR_RPC_TIMEOUT + } + } +} + +// DeleteBucket delete a bucket for owner +// - owner: bucket owner account +// - bucketName: bucket name +// +// Return: +// - string: block hash +// - error: error message +// +// Note: +// - if you are not the owner, the owner account must be authorised to you +func (c *ChainClient) DeleteBucket(owner []byte, bucketName string) (string, error) { + c.lock.Lock() + defer func() { + c.lock.Unlock() + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var ( + blockhash string + accountInfo types.AccountInfo + ) + + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION + } + + acc, err := types.NewAccountID(owner) + if err != nil { + return blockhash, errors.Wrap(err, "[NewAccountID]") + } + + call, err := types.NewCall(c.metadata, TX_FileBank_DeleteBucket, *acc, types.NewBytes([]byte(bucketName))) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_FileBank_DeleteBucket, err) + return blockhash, err + } + + ext := types.NewExtrinsic(call) + + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_FileBank_DeleteBucket, err) + return blockhash, err + } + + ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_FileBank_DeleteBucket, err) + c.SetRpcState(false) + return blockhash, err + } + if !ok { + return blockhash, ERR_RPC_EMPTY_VALUE + } + + o := types.SignatureOptions{ + BlockHash: c.genesisHash, + Era: types.ExtrinsicEra{IsMortalEra: false}, + GenesisHash: c.genesisHash, + Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), + SpecVersion: c.runtimeVersion.SpecVersion, + Tip: types.NewUCompactFromUInt(0), + TransactionVersion: c.runtimeVersion.TransactionVersion, + } + + // Sign the transaction + err = ext.Sign(c.keyring, o) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_FileBank_DeleteBucket, err) + return blockhash, err + } + + <-c.txTicker.C + + // Do the transfer and track the actual status + sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_DeleteBucket, err) + c.SetRpcState(false) + return blockhash, err + } + defer sub.Unsubscribe() + + timeout := time.NewTimer(c.packingTime) + defer timeout.Stop() + + for { + select { + case status := <-sub.Chan(): + if status.IsInBlock { + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_FileBank_DeleteBucket(status.AsInBlock) + return blockhash, err + } + case err = <-sub.Err(): + return blockhash, errors.Wrap(err, "[sub]") + case <-timeout.C: + return blockhash, ERR_RPC_TIMEOUT + } + } +} + +// DeleteFile delete a bucket for owner +// - owner: file owner account +// - fid: file identification +// +// Return: +// - string: block hash +// - error: error message +// +// Note: +// - if you are not the owner, the owner account must be authorised to you +func (c *ChainClient) DeleteFile(owner []byte, fid string) (string, error) { + c.lock.Lock() + defer func() { + c.lock.Unlock() + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var ( + blockhash string + accountInfo types.AccountInfo + ) + + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION + } + + if len(fid) != FileHashLen { + return "", errors.New("invalid fid") + } + + acc, err := types.NewAccountID(owner) + if err != nil { + return blockhash, errors.Wrap(err, "[NewAccountID]") + } + + var fhash FileHash + for i := 0; i < len(fid); i++ { + fhash[i] = types.U8(fid[i]) + } + + call, err := types.NewCall(c.metadata, TX_FileBank_DeleteFile, *acc, fhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_FileBank_DeleteFile, err) + return blockhash, err + } + + ext := types.NewExtrinsic(call) + + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_FileBank_DeleteFile, err) + return blockhash, err + } + + ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_FileBank_DeleteFile, err) + c.SetRpcState(false) + return blockhash, err + } + if !ok { + return blockhash, ERR_RPC_EMPTY_VALUE + } + + o := types.SignatureOptions{ + BlockHash: c.genesisHash, + Era: types.ExtrinsicEra{IsMortalEra: false}, + GenesisHash: c.genesisHash, + Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), + SpecVersion: c.runtimeVersion.SpecVersion, + Tip: types.NewUCompactFromUInt(0), + TransactionVersion: c.runtimeVersion.TransactionVersion, + } + + // Sign the transaction + err = ext.Sign(c.keyring, o) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_FileBank_DeleteFile, err) + return blockhash, err + } + + <-c.txTicker.C + + // Do the transfer and track the actual status + sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { + o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) + err = ext.Sign(c.keyring, o) + if err != nil { + return blockhash, errors.Wrap(err, "[Sign]") + } + <-c.txTicker.C + sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_DeleteFile, err) + c.SetRpcState(false) + return blockhash, err + } + } else { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_DeleteFile, err) + c.SetRpcState(false) + return blockhash, err + } + } + + defer sub.Unsubscribe() + + timeout := time.NewTimer(c.packingTime) + defer timeout.Stop() + + for { + select { + case status := <-sub.Chan(): + if status.IsInBlock { + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_FileBank_DeleteFile(status.AsInBlock) + return blockhash, err + } + case err = <-sub.Err(): + return blockhash, errors.Wrap(err, "[sub]") + case <-timeout.C: + return blockhash, ERR_RPC_TIMEOUT + } + } +} + +// TransferReport is used by miners to report that a file has been transferred +// - index: index of the file fragment +// - fid: file identification +// +// Return: +// - string: block hash +// - error: error message +// +// Note: +// - for storage miner use only +func (c *ChainClient) TransferReport(index uint8, fid string) (string, error) { + c.lock.Lock() + defer func() { + c.lock.Unlock() + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var ( + blockhash string + accountInfo types.AccountInfo + ) + + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION + } + + if index <= 0 || int(index) > (config.DataShards+config.ParShards) { + return "", errors.New("invalid index") + } + + var fhash FileHash + + for j := 0; j < len(fid); j++ { + fhash[j] = types.U8(fid[j]) + } + + call, err := types.NewCall(c.metadata, TX_FileBank_TransferReport, types.NewU8(index), fhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_FileBank_TransferReport, err) + return blockhash, err + } + + ext := types.NewExtrinsic(call) + + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_FileBank_TransferReport, err) + return blockhash, err + } + + ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_FileBank_TransferReport, err) + c.SetRpcState(false) + return blockhash, err + } + if !ok { + return blockhash, ERR_RPC_EMPTY_VALUE + } + + o := types.SignatureOptions{ + BlockHash: c.genesisHash, + Era: types.ExtrinsicEra{IsMortalEra: false}, + GenesisHash: c.genesisHash, + Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), + SpecVersion: c.runtimeVersion.SpecVersion, + Tip: types.NewUCompactFromUInt(0), + TransactionVersion: c.runtimeVersion.TransactionVersion, + } + + // Sign the transaction + err = ext.Sign(c.keyring, o) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_FileBank_TransferReport, err) + return blockhash, err + } + + <-c.txTicker.C + + // Do the transfer and track the actual status + sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { + o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) + err = ext.Sign(c.keyring, o) + if err != nil { + return blockhash, errors.Wrap(err, "[Sign]") + } + <-c.txTicker.C + sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_TransferReport, err) + c.SetRpcState(false) + return blockhash, err + } + } else { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_TransferReport, err) + c.SetRpcState(false) + return blockhash, err + } + } + defer sub.Unsubscribe() + + timeout := time.NewTimer(c.packingTime) + defer timeout.Stop() + + for { + select { + case status := <-sub.Chan(): + if status.IsInBlock { + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_FileBank_TransferReport(status.AsInBlock) + return blockhash, err + } + case err = <-sub.Err(): + return blockhash, errors.Wrap(err, "[sub]") + case <-timeout.C: + return blockhash, ERR_RPC_TIMEOUT + } + } +} + +// GenerateRestoralOrder generate restoral orders for file fragment +// - fid: file identification +// - fragmentHash: fragment hash +// +// Return: +// - string: block hash +// - error: error message +// +// Note: +// - for storage miner use only +func (c *ChainClient) GenerateRestoralOrder(fid, fragmentHash string) (string, error) { + c.lock.Lock() + defer func() { + c.lock.Unlock() + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var ( + blockhash string + accountInfo types.AccountInfo + ) + + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION + } + + var rooth FileHash + var fragh FileHash + + if len(fid) != FileHashLen { + return blockhash, errors.New("invalid file hash") + } + + if len(fragmentHash) != FileHashLen { + return blockhash, errors.New("invalid fragment hash") + } + + for i := 0; i < len(fid); i++ { + rooth[i] = types.U8(fid[i]) + } + + for i := 0; i < len(fragmentHash); i++ { + fragh[i] = types.U8(fragmentHash[i]) + } + + call, err := types.NewCall(c.metadata, TX_FileBank_GenerateRestoralOrder, rooth, fragh) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_FileBank_GenerateRestoralOrder, err) + return blockhash, err + } + + ext := types.NewExtrinsic(call) + + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_FileBank_GenerateRestoralOrder, err) + return blockhash, err + } + + ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_FileBank_GenerateRestoralOrder, err) + c.SetRpcState(false) + return blockhash, err + } + if !ok { + return blockhash, ERR_RPC_EMPTY_VALUE + } + + o := types.SignatureOptions{ + BlockHash: c.genesisHash, + Era: types.ExtrinsicEra{IsMortalEra: false}, + GenesisHash: c.genesisHash, + Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), + SpecVersion: c.runtimeVersion.SpecVersion, + Tip: types.NewUCompactFromUInt(0), + TransactionVersion: c.runtimeVersion.TransactionVersion, + } + + // Sign the transaction + err = ext.Sign(c.keyring, o) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_FileBank_GenerateRestoralOrder, err) + return blockhash, err + } + + <-c.txTicker.C + + // Do the transfer and track the actual status + sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_GenerateRestoralOrder, err) + c.SetRpcState(false) + return blockhash, err + } + defer sub.Unsubscribe() + + timeout := time.NewTimer(c.packingTime) + defer timeout.Stop() + + for { + select { + case status := <-sub.Chan(): + if status.IsInBlock { + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_FileBank_GenRestoralOrder(status.AsInBlock) + return blockhash, err + } + case err = <-sub.Err(): + return blockhash, errors.Wrap(err, "[sub]") + case <-timeout.C: + return blockhash, ERR_RPC_TIMEOUT + } + } +} + +// ClaimRestoralOrder claim a restoral order +// - fragmentHash: fragment hash +// +// Return: +// - string: block hash +// - error: error message +// +// Note: +// - for storage miner use only +func (c *ChainClient) ClaimRestoralOrder(fragmentHash string) (string, error) { + c.lock.Lock() + defer func() { + c.lock.Unlock() + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var ( + blockhash string + accountInfo types.AccountInfo + ) + + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION + } + + if len(fragmentHash) != FileHashLen { + return blockhash, errors.New("invalid fragment hash") + } + + var fragh FileHash + for i := 0; i < len(fragmentHash); i++ { + fragh[i] = types.U8(fragmentHash[i]) + } + + call, err := types.NewCall(c.metadata, TX_FileBank_ClaimRestoralOrder, fragh) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_FileBank_ClaimRestoralOrder, err) + return blockhash, err + } + + ext := types.NewExtrinsic(call) + + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_FileBank_ClaimRestoralOrder, err) + return blockhash, err + } + + ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_FileBank_ClaimRestoralOrder, err) + c.SetRpcState(false) + return blockhash, err + } + if !ok { + return blockhash, ERR_RPC_EMPTY_VALUE + } + + o := types.SignatureOptions{ + BlockHash: c.genesisHash, + Era: types.ExtrinsicEra{IsMortalEra: false}, + GenesisHash: c.genesisHash, + Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), + SpecVersion: c.runtimeVersion.SpecVersion, + Tip: types.NewUCompactFromUInt(0), + TransactionVersion: c.runtimeVersion.TransactionVersion, + } + + // Sign the transaction + err = ext.Sign(c.keyring, o) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_FileBank_ClaimRestoralOrder, err) + return blockhash, err + } + + <-c.txTicker.C + + // Do the transfer and track the actual status + sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { + o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) + err = ext.Sign(c.keyring, o) + if err != nil { + return blockhash, errors.Wrap(err, "[Sign]") + } + <-c.txTicker.C + sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_ClaimRestoralOrder, err) + c.SetRpcState(false) + return blockhash, err + } + } else { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_ClaimRestoralOrder, err) + c.SetRpcState(false) + return blockhash, err + } + } + defer sub.Unsubscribe() + + timeout := time.NewTimer(c.packingTime) + defer timeout.Stop() + + for { + select { + case status := <-sub.Chan(): + if status.IsInBlock { + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_FileBank_ClaimRestoralOrder(status.AsInBlock) + return blockhash, err + } + case err = <-sub.Err(): + return blockhash, errors.Wrap(err, "[sub]") + case <-timeout.C: + return blockhash, ERR_RPC_TIMEOUT + } + } +} + +// ClaimRestoralNoExistOrder claim the restoral order of an exited storage miner +// - puk: storage miner account +// - fid: file identification +// - fragmentHash: fragment hash +// +// Return: +// - string: block hash +// - error: error message +// +// Note: +// - for storage miner use only +func (c *ChainClient) ClaimRestoralNoExistOrder(puk []byte, fid, fragmentHash string) (string, error) { + c.lock.Lock() + defer func() { + c.lock.Unlock() + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var ( + blockhash string + accountInfo types.AccountInfo + ) + + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION + } + + acc, err := types.NewAccountID(puk) + if err != nil { + return blockhash, errors.Wrap(err, "[NewAccountID]") + } + + var rooth FileHash + var fragh FileHash + + if len(fid) != FileHashLen { + return blockhash, errors.New("invalid file hash") + } + + if len(fragmentHash) != FileHashLen { + return blockhash, errors.New("invalid fragment hash") + } + + for i := 0; i < len(fid); i++ { + rooth[i] = types.U8(fid[i]) + } + + for i := 0; i < len(fragmentHash); i++ { + fragh[i] = types.U8(fragmentHash[i]) + } + + call, err := types.NewCall(c.metadata, TX_FileBank_ClaimRestoralNoexistOrder, *acc, rooth, fragh) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_FileBank_ClaimRestoralNoexistOrder, err) + return blockhash, err + } + + ext := types.NewExtrinsic(call) + + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_FileBank_ClaimRestoralNoexistOrder, err) + return blockhash, err + } + + ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_FileBank_ClaimRestoralNoexistOrder, err) + c.SetRpcState(false) + return blockhash, err + } + if !ok { + return blockhash, ERR_RPC_EMPTY_VALUE + } + + o := types.SignatureOptions{ + BlockHash: c.genesisHash, + Era: types.ExtrinsicEra{IsMortalEra: false}, + GenesisHash: c.genesisHash, + Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), + SpecVersion: c.runtimeVersion.SpecVersion, + Tip: types.NewUCompactFromUInt(0), + TransactionVersion: c.runtimeVersion.TransactionVersion, + } + + // Sign the transaction + err = ext.Sign(c.keyring, o) + if err != nil { + return blockhash, errors.Wrap(err, "[Sign]") + } + + <-c.txTicker.C + + // Do the transfer and track the actual status + sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { + o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) + err = ext.Sign(c.keyring, o) + if err != nil { + return blockhash, errors.Wrap(err, "[Sign]") + } + <-c.txTicker.C + sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_ClaimRestoralNoexistOrder, err) + c.SetRpcState(false) + return blockhash, err + } + } else { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_ClaimRestoralNoexistOrder, err) + c.SetRpcState(false) + return blockhash, err + } + } + defer sub.Unsubscribe() + + timeout := time.NewTimer(c.packingTime) + defer timeout.Stop() + + for { + select { + case status := <-sub.Chan(): + if status.IsInBlock { + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_FileBank_ClaimRestoralOrder(status.AsInBlock) + return blockhash, err + } + case err = <-sub.Err(): + return blockhash, errors.Wrap(err, "[sub]") + case <-timeout.C: + return blockhash, ERR_RPC_TIMEOUT + } + } +} + +// RestoralOrderComplete submits the restored completed order +// - fragmentHash: fragment hash +// +// Return: +// - string: block hash +// - error: error message +// +// Note: +// - for storage miner use only +func (c *ChainClient) RestoralOrderComplete(fragmentHash string) (string, error) { + c.lock.Lock() + defer func() { + c.lock.Unlock() + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var ( + blockhash string + accountInfo types.AccountInfo + ) + + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION + } + + var fragh FileHash + + if len(fragmentHash) != FileHashLen { + return blockhash, errors.New("invalid fragment hash") + } + + for i := 0; i < len(fragmentHash); i++ { + fragh[i] = types.U8(fragmentHash[i]) + } + + call, err := types.NewCall(c.metadata, TX_FileBank_RestoralOrderComplete, fragh) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_FileBank_RestoralOrderComplete, err) + return blockhash, err + } + + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_FileBank_RestoralOrderComplete, err) + return blockhash, err + } + + ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_FileBank_RestoralOrderComplete, err) + c.SetRpcState(false) + return blockhash, err + } + if !ok { + return blockhash, ERR_RPC_EMPTY_VALUE + } + + o := types.SignatureOptions{ + BlockHash: c.genesisHash, + Era: types.ExtrinsicEra{IsMortalEra: false}, + GenesisHash: c.genesisHash, + Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), + SpecVersion: c.runtimeVersion.SpecVersion, + Tip: types.NewUCompactFromUInt(0), + TransactionVersion: c.runtimeVersion.TransactionVersion, + } + + ext := types.NewExtrinsic(call) + + // Sign the transaction + err = ext.Sign(c.keyring, o) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_FileBank_RestoralOrderComplete, err) + return blockhash, err + } + + // Do the transfer and track the actual status + sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { + o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) + err = ext.Sign(c.keyring, o) + if err != nil { + return blockhash, errors.Wrap(err, "[Sign]") + } + sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_RestoralOrderComplete, err) + c.SetRpcState(false) + return blockhash, err + } + } else { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_RestoralOrderComplete, err) + c.SetRpcState(false) + return blockhash, err + } + } + defer sub.Unsubscribe() + + timeout := time.NewTimer(c.packingTime) + defer timeout.Stop() + + for { + select { + case status := <-sub.Chan(): + if status.IsInBlock { + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_FileBank_RecoveryCompleted(status.AsInBlock) + return blockhash, err + } + case err = <-sub.Err(): + return blockhash, errors.Wrap(err, "[sub]") + case <-timeout.C: + return blockhash, ERR_RPC_TIMEOUT + } + } +} + +// CertIdleSpace authenticates idle file to the chain +// - spaceProofInfo: space proof info +// - teeSignWithAcc: tee sign with account +// - teeSign: tee sign +// - teePuk: tee work public key +// +// Return: +// - string: block hash +// - error: error message +// +// Note: +// - for storage miner use only +func (c *ChainClient) CertIdleSpace(spaceProofInfo SpaceProofInfo, teeSignWithAcc, teeSign types.Bytes, teePuk WorkerPublicKey) (string, error) { + c.lock.Lock() + defer func() { + c.lock.Unlock() + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var ( + blockhash string + accountInfo types.AccountInfo + ) + + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION + } + + call, err := types.NewCall(c.metadata, TX_FileBank_CertIdleSpace, spaceProofInfo, teeSignWithAcc, teeSign, teePuk) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_FileBank_CertIdleSpace, err) + return blockhash, err + } + + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_FileBank_CertIdleSpace, err) + return blockhash, err + } + + ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_FileBank_CertIdleSpace, err) + c.SetRpcState(false) + return blockhash, err + } + if !ok { + return blockhash, ERR_RPC_EMPTY_VALUE + } + + o := types.SignatureOptions{ + BlockHash: c.genesisHash, + Era: types.ExtrinsicEra{IsMortalEra: false}, + GenesisHash: c.genesisHash, + Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), + SpecVersion: c.runtimeVersion.SpecVersion, + Tip: types.NewUCompactFromUInt(0), + TransactionVersion: c.runtimeVersion.TransactionVersion, + } + + ext := types.NewExtrinsic(call) + + // Sign the transaction + err = ext.Sign(c.keyring, o) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_FileBank_CertIdleSpace, err) + return blockhash, err + } + + <-c.txTicker.C + + // Do the transfer and track the actual status + sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { + o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) + err = ext.Sign(c.keyring, o) + if err != nil { + return blockhash, errors.Wrap(err, "[Sign]") + } + <-c.txTicker.C + sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_CertIdleSpace, err) + c.SetRpcState(false) + return blockhash, err + } + } else { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_CertIdleSpace, err) + c.SetRpcState(false) + return blockhash, err + } + } + defer sub.Unsubscribe() + + timeout := time.NewTimer(c.packingTime) + defer timeout.Stop() + + for { + select { + case status := <-sub.Chan(): + if status.IsInBlock { + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_FileBank_IdleSpaceCert(status.AsInBlock) + return blockhash, err + } + case err = <-sub.Err(): + return blockhash, errors.Wrap(err, "[sub]") + case <-timeout.C: + return blockhash, ERR_RPC_TIMEOUT + } + } +} + +// ReplaceIdleSpace replaces idle files with service files +// - spaceProofInfo: space proof info +// - teeSignWithAcc: tee sign with account +// - teeSign: tee sign +// - teePuk: tee work public key +// +// Return: +// - string: block hash +// - error: error message +// +// Note: +// - for storage miner use only +func (c *ChainClient) ReplaceIdleSpace(spaceProofInfo SpaceProofInfo, teeSignWithAcc, teeSign types.Bytes, teePuk WorkerPublicKey) (string, error) { + c.lock.Lock() + defer func() { + c.lock.Unlock() + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var ( + blockhash string + accountInfo types.AccountInfo + ) + + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION + } + + call, err := types.NewCall(c.metadata, TX_FileBank_ReplaceIdleSpace, spaceProofInfo, teeSignWithAcc, teeSign, teePuk) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_FileBank_ReplaceIdleSpace, err) + return blockhash, err + } + + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_FileBank_ReplaceIdleSpace, err) + return blockhash, err + } + + ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_FileBank_ReplaceIdleSpace, err) + c.SetRpcState(false) + return blockhash, err + } + if !ok { + return blockhash, ERR_RPC_EMPTY_VALUE + } + + o := types.SignatureOptions{ + BlockHash: c.genesisHash, + Era: types.ExtrinsicEra{IsMortalEra: false}, + GenesisHash: c.genesisHash, + Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), + SpecVersion: c.runtimeVersion.SpecVersion, + Tip: types.NewUCompactFromUInt(0), + TransactionVersion: c.runtimeVersion.TransactionVersion, + } + + ext := types.NewExtrinsic(call) + + // Sign the transaction + err = ext.Sign(c.keyring, o) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_FileBank_ReplaceIdleSpace, err) + return blockhash, err + } + + <-c.txTicker.C + + // Do the transfer and track the actual status + sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { + o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) + err = ext.Sign(c.keyring, o) + if err != nil { + return blockhash, errors.Wrap(err, "[Sign]") + } + <-c.txTicker.C + sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_ReplaceIdleSpace, err) + c.SetRpcState(false) + return blockhash, err + } + } else { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_ReplaceIdleSpace, err) + c.SetRpcState(false) + return blockhash, err + } + } + defer sub.Unsubscribe() + + timeout := time.NewTimer(c.packingTime) + defer timeout.Stop() + + for { + select { + case status := <-sub.Chan(): + if status.IsInBlock { + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_FileBank_ReplaceIdleSpace(status.AsInBlock) + return blockhash, err + } + case err = <-sub.Err(): + return blockhash, errors.Wrap(err, "[sub]") + case <-timeout.C: + return blockhash, ERR_RPC_TIMEOUT + } + } +} + +// CalculateReport report file tag calculation completed +// - teeSig: tee sign +// - tagSigInfo: tag sig info +// +// Return: +// - string: block hash +// - error: error message +// +// Note: +// - for storage miner use only +func (c *ChainClient) CalculateReport(teeSig types.Bytes, tagSigInfo TagSigInfo) (string, error) { + c.lock.Lock() + defer func() { + c.lock.Unlock() + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var ( + blockhash string + accountInfo types.AccountInfo + ) + + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION + } + + call, err := types.NewCall(c.metadata, TX_FileBank_CalculateReport, teeSig, tagSigInfo) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_FileBank_CalculateReport, err) + return blockhash, err + } + + ext := types.NewExtrinsic(call) + + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_FileBank_CalculateReport, err) + return blockhash, err + } + + ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_FileBank_CalculateReport, err) + c.SetRpcState(false) + return blockhash, err + } + if !ok { + return blockhash, ERR_RPC_EMPTY_VALUE + } + + o := types.SignatureOptions{ + BlockHash: c.genesisHash, + Era: types.ExtrinsicEra{IsMortalEra: false}, + GenesisHash: c.genesisHash, + Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), + SpecVersion: c.runtimeVersion.SpecVersion, + Tip: types.NewUCompactFromUInt(0), + TransactionVersion: c.runtimeVersion.TransactionVersion, + } + + // Sign the transaction + err = ext.Sign(c.keyring, o) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_FileBank_CalculateReport, err) + return blockhash, err + } + + <-c.txTicker.C + + // Do the transfer and track the actual status + sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { + o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) + err = ext.Sign(c.keyring, o) + if err != nil { + return blockhash, errors.Wrap(err, "[Sign]") + } + <-c.txTicker.C + sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_CalculateReport, err) + c.SetRpcState(false) + return blockhash, err + } + } else { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_FileBank_CalculateReport, err) + c.SetRpcState(false) + return blockhash, err + } + } + defer sub.Unsubscribe() + + timeout := time.NewTimer(c.packingTime) + defer timeout.Stop() + + for { + select { + case status := <-sub.Chan(): + if status.IsInBlock { + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_FileBank_CalculateReport(status.AsInBlock) + return blockhash, err + } + case err = <-sub.Err(): + return blockhash, errors.Wrap(err, "[sub]") + case <-timeout.C: + return blockhash, ERR_RPC_TIMEOUT + } + } +} diff --git a/core/pattern/pattern.go b/chain/pattern.go old mode 100755 new mode 100644 similarity index 67% rename from core/pattern/pattern.go rename to chain/pattern.go index e88ea17..1a7e9eb --- a/core/pattern/pattern.go +++ b/chain/pattern.go @@ -5,7 +5,7 @@ SPDX-License-Identifier: Apache-2.0 */ -package pattern +package chain import ( "time" @@ -32,72 +32,75 @@ const MaxSubmitedIdleFileMeta = 30 const PublicDeoss = "http://deoss-pub-gateway.cess.cloud/" const PublicDeossAccount = "cXhwBytXqrZLr1qM5NHJhCzEMckSTzNKw17ci2aHft6ETSQm9" -// Pallets +const TreasuryAccount = "cXhT9Xh3DhrBMDmXcGeMPDmTzDm1J8vDxBtKvogV33pPshnWS" + +// pallet names const ( - // - AUDIT = "Audit" + // Audit + Audit = "Audit" // OSS is a module about DeOSS - OSS = "Oss" + Oss = "Oss" // FILEBANK is a module about data metadata, bucket info, etc. - FILEBANK = "FileBank" + FileBank = "FileBank" // TEEWOEKER is a module about TEE - TEEWORKER = "TeeWorker" + TeeWorker = "TeeWorker" // SMINER is a module about storage miners - SMINER = "Sminer" + Sminer = "Sminer" // STAKING is a module about staking - STAKING = "Staking" + Staking = "Staking" // SMINER is a module about storage miners - STORAGEHANDLER = "StorageHandler" + StorageHandler = "StorageHandler" // BALANCES is a module about the balances - BALANCES = "Balances" + Balances = "Balances" // SYSTEM is a module about the system - SYSTEM = "System" + System = "System" // EVM is a module about the evm contract EVM = "EVM" // CessTreasury = "CessTreasury" ) -// Chain state +// chain state const ( - //AUDIT - UNVERIFYPROOF = "UnverifyProof" - CHALLENGEDURATION = "ChallengeDuration" - CHALLENGEVERIFYDURATION = "VerifyDuration" - CHALLENGESNAPSHOT = "ChallengeSnapShot" - UNVERIFYIDLEPROOF = "UnverifyIdleProof" - UNVERIFYSERVICEPROOF = "UnverifyServiceProof" - - // OSS - // OSS - AUTHORITYLIST = "AuthorityList" - - // SMINER - ALLMINER = "AllMiner" - MINERITEMS = "MinerItems" - REWARDMAP = "RewardMap" - EXPENDERS = "Expenders" - RESTORALTARGETINFO = "RestoralTarget" - STAKINGSTARTBLOCK = "StakingStartBlock" - CompleteSnapShot = "CompleteSnapShot" - - // TEEWORKER - TEEWorkers = "Workers" - TEEMasterPubkey = "MasterPubkey" - TEEEndpoints = "Endpoints" - TEEWorkerAddedAt = "WorkerAddedAt" - - // FILEBANK - FILE = "File" - BUCKET = "Bucket" - BUCKETLIST = "UserBucketList" - DEALMAP = "DealMap" - FILLERMAP = "FillerMap" - PENDINGREPLACE = "PendingReplacements" - RESTORALORDER = "RestoralOrder" - - // STAKING - COUNTERFORVALIDATORS = "CounterForValidators" + // Audit + ChallengeSlip = "ChallengeSlip" + ChallengeSnapShot = "ChallengeSnapShot" + CountedClear = "CountedClear" + CountedServiceFailed = "CountedServiceFailed" + VerifySlip = "VerifySlip" + + // Oss + // Oss + AuthorityList = "AuthorityList" + + // Sminer + AllMiner = "AllMiner" + CounterForMinerItems = "CounterForMinerItems" + MinerItems = "MinerItems" + RewardMap = "RewardMap" + Expenders = "Expenders" + RestoralTarget = "RestoralTarget" + StakingStartBlock = "StakingStartBlock" + CompleteSnapShot = "CompleteSnapShot" + + // TeeWorker + Workers = "Workers" + MasterPubkey = "MasterPubkey" + Endpoints = "Endpoints" + WorkerAddedAt = "WorkerAddedAt" + + // FileBank + File = "File" + Bucket = "Bucket" + DealMap = "DealMap" + FillerMap = "FillerMap" + PendingReplacements = "PendingReplacements" + RestoralOrder = "RestoralOrder" + UserBucketList = "UserBucketList" + UserHoldFileList = "UserHoldFileList" + + // Staking + CounterForValidators = "CounterForValidators" CounterForNominators = "CounterForNominators" ErasTotalStake = "ErasTotalStake" CurrentEra = "CurrentEra" @@ -109,76 +112,79 @@ const ( ErasValidatorReward = "ErasValidatorReward" ValidatorCount = "ValidatorCount" - // STORAGE_HANDLER - USERSPACEINFO = "UserOwnedSpace" - UNITPRICE = "UnitPrice" - TOTALIDLESPACE = "TotalIdleSpace" - TOTALSERVICESPACE = "TotalServiceSpace" - PURCHASEDSPACE = "PurchasedSpace" + // StorageHandler + UserOwnedSpace = "UserOwnedSpace" + UnitPrice = "UnitPrice" + TotalIdleSpace = "TotalIdleSpace" + TotalServiceSpace = "TotalServiceSpace" + PurchasedSpace = "PurchasedSpace" - // BALANCES - TOTALISSUANCE = "TotalIssuance" + // Balances + TotalIssuance = "TotalIssuance" + InactiveIssuance = "InactiveIssuance" - // SYSTEM - ACCOUNT = "Account" - EVENTS = "Events" + // System + Account = "Account" + Events = "Events" // CessTreasury - RoundReward = "RoundReward" + CurrencyReward = "CurrencyReward" + EraReward = "EraReward" + ReserveReward = "ReserveReward" + RoundReward = "RoundReward" ) // Extrinsics const ( - //AUDIT - TX_AUDIT_SUBMITPROOF = AUDIT + DOT + "submit_proof" - TX_AUDIT_SUBMITIDLEPROOF = AUDIT + DOT + "submit_idle_proof" - TX_AUDIT_SUBMITSERVICEPROOF = AUDIT + DOT + "submit_service_proof" - TX_AUDIT_SUBMITIDLEPROOFRESULT = AUDIT + DOT + "submit_verify_idle_result" - TX_AUDIT_SUBMITSERVICEPROOFRESULT = AUDIT + DOT + "submit_verify_service_result" - - // OSS - TX_OSS_REGISTER = OSS + DOT + "register" - TX_OSS_UPDATE = OSS + DOT + "update" - TX_OSS_DESTROY = OSS + DOT + "destroy" - TX_OSS_AUTHORIZE = OSS + DOT + "authorize" - TX_OSS_UNAUTHORIZE = OSS + DOT + "cancel_authorize" - - // SMINER - TX_SMINER_REGISTER = SMINER + DOT + "regnstk" - TX_SMINER_REGISTERASSIGNSTAKING = SMINER + DOT + "regnstk_assign_staking" - TX_SMINER_INCREASESTAKES = SMINER + DOT + "increase_collateral" - TX_SMINER_UPDATEPEERID = SMINER + DOT + "update_peer_id" - TX_SMINER_UPDATEINCOME = SMINER + DOT + "update_beneficiary" - TX_SMINER_CLAIMREWARD = SMINER + DOT + "receive_reward" - TX_SMINER_MINEREXITPREP = SMINER + DOT + "miner_exit_prep" - TX_SMINER_WITHDRAW = SMINER + DOT + "miner_withdraw" - TX_SMINER_REGISTERPOISKEY = SMINER + DOT + "register_pois_key" - TX_SMINER_INCREASEDECSPACE = SMINER + DOT + "increase_declaration_space" - - // FILEBANK - TX_FILEBANK_PUTBUCKET = FILEBANK + DOT + "create_bucket" - TX_FILEBANK_DELBUCKET = FILEBANK + DOT + "delete_bucket" - TX_FILEBANK_DELFILE = FILEBANK + DOT + "delete_file" - TX_FILEBANK_UPLOADDEC = FILEBANK + DOT + "upload_declaration" - TX_FILEBANK_FILEREPORT = FILEBANK + DOT + "transfer_report" - TX_FILEBANK_GENRESTOREORDER = FILEBANK + DOT + "generate_restoral_order" - TX_FILEBANK_CLAIMRESTOREORDER = FILEBANK + DOT + "claim_restoral_order" - TX_FILEBANK_CLAIMNOEXISTORDER = FILEBANK + DOT + "claim_restoral_noexist_order" - TX_FILEBANK_RESTORALCOMPLETE = FILEBANK + DOT + "restoral_order_complete" - TX_FILEBANK_CERTIDLESPACE = FILEBANK + DOT + "cert_idle_space" - TX_FILEBANK_REPLACEIDLESPACE = FILEBANK + DOT + "replace_idle_space" - TX_FILEBANK_CALCULATEREPORT = FILEBANK + DOT + "calculate_report" - - // STORAGE_HANDLER - TX_STORAGE_BUYSPACE = STORAGEHANDLER + DOT + "buy_space" - TX_STORAGE_EXPANSIONSPACE = STORAGEHANDLER + DOT + "expansion_space" - TX_STORAGE_RENEWALSPACE = STORAGEHANDLER + DOT + "renewal_space" + // Audit + TX_Audit_SubmitIdleProof = Audit + DOT + "submit_idle_proof" + TX_Audit_SubmitServiceProof = Audit + DOT + "submit_service_proof" + TX_Audit_SubmitVerifyIdleResult = Audit + DOT + "submit_verify_idle_result" + TX_Audit_SubmitVerifyServiceResult = Audit + DOT + "submit_verify_service_result" + + // Oss + TX_Oss_Register = Oss + DOT + "register" + TX_Oss_Update = Oss + DOT + "update" + TX_Oss_Destroy = Oss + DOT + "destroy" + TX_Oss_Authorize = Oss + DOT + "authorize" + TX_Oss_CancelAuthorize = Oss + DOT + "cancel_authorize" + + // Sminer + TX_Sminer_Regnstk = Sminer + DOT + "regnstk" + TX_Sminer_RegnstkAssignStaking = Sminer + DOT + "regnstk_assign_staking" + TX_Sminer_IncreaseCollateral = Sminer + DOT + "increase_collateral" + TX_Sminer_UpdatePeerId = Sminer + DOT + "update_peer_id" + TX_Sminer_UpdateBeneficiary = Sminer + DOT + "update_beneficiary" + TX_Sminer_ReceiveReward = Sminer + DOT + "receive_reward" + TX_Sminer_MinerExitPrep = Sminer + DOT + "miner_exit_prep" + TX_Sminer_MinerWithdraw = Sminer + DOT + "miner_withdraw" + TX_Sminer_RegisterPoisKey = Sminer + DOT + "register_pois_key" + TX_Sminer_IncreaseDeclarationSpace = Sminer + DOT + "increase_declaration_space" + + // FileBank + TX_FileBank_CreateBucket = FileBank + DOT + "create_bucket" + TX_FileBank_DeleteBucket = FileBank + DOT + "delete_bucket" + TX_FileBank_DeleteFile = FileBank + DOT + "delete_file" + TX_FileBank_UploadDeclaration = FileBank + DOT + "upload_declaration" + TX_FileBank_TransferReport = FileBank + DOT + "transfer_report" + TX_FileBank_GenerateRestoralOrder = FileBank + DOT + "generate_restoral_order" + TX_FileBank_ClaimRestoralOrder = FileBank + DOT + "claim_restoral_order" + TX_FileBank_ClaimRestoralNoexistOrder = FileBank + DOT + "claim_restoral_noexist_order" + TX_FileBank_RestoralOrderComplete = FileBank + DOT + "restoral_order_complete" + TX_FileBank_CertIdleSpace = FileBank + DOT + "cert_idle_space" + TX_FileBank_ReplaceIdleSpace = FileBank + DOT + "replace_idle_space" + TX_FileBank_CalculateReport = FileBank + DOT + "calculate_report" + + // StorageHandler + TX_StorageHandler_BuySpace = StorageHandler + DOT + "buy_space" + TX_StorageHandler_ExpansionSpace = StorageHandler + DOT + "expansion_space" + TX_StorageHandler_RenewalSpace = StorageHandler + DOT + "renewal_space" // BALANCES - TX_BALANCES_FORCETRANSFER = "Balances" + DOT + "transfer" + TX_Balances_Transfer = "Balances" + DOT + "transfer" // EVM - TX_EVM_CALL = EVM + DOT + "call" + TX_EVM_Call = EVM + DOT + "call" ) // RPC Call @@ -221,33 +227,13 @@ const ( ERR_Empty = "empty" ) -const ( - MinBucketNameLength = 3 - MaxBucketNameLength = 63 - MaxDomainNameLength = 50 -) - -// byte size -const ( - SIZE_1KiB = 1024 - SIZE_1MiB = 1024 * SIZE_1KiB - SIZE_1GiB = 1024 * SIZE_1MiB - SIZE_1TiB = 1024 * SIZE_1GiB -) - -const ( - SegmentSize = 32 * SIZE_1MiB - FragmentSize = 8 * SIZE_1MiB - DataShards = 4 - ParShards = 8 -) - var ( ERR_RPC_CONNECTION = errors.New("rpc err: connection failed") ERR_RPC_IP_FORMAT = errors.New("unsupported ip format") ERR_RPC_TIMEOUT = errors.New("timeout") ERR_RPC_EMPTY_VALUE = errors.New("empty") ERR_RPC_PRIORITYTOOLOW = "Priority is too low" + ERR_IdleProofIsEmpty = errors.New("idle data proof is empty") ) const ( @@ -280,6 +266,65 @@ type MasterPublicKey [MasterPublicKeyLen]types.U8 type EcdhPublicKey [EcdhPublicKeyLen]types.U8 type TeeSig [TeeSigLen]types.U8 +// Audit +type ChallengeInfo struct { + MinerSnapshot MinerSnapShot + ChallengeElement ChallengeElement + ProveInfo ProveInfo +} + +// Oss +type BucketInfo struct { + FileList []FileHash + Authority []types.AccountID +} + +// FileBank +type StorageOrder struct { + FileSize types.U128 + SegmentList []SegmentList + User UserBrief + CompleteList []CompleteInfo +} + +type FileMetadata struct { + SegmentList []SegmentInfo + Owner []UserBrief + FileSize types.U128 + Completion types.U32 + State types.U8 +} + +type RestoralOrderInfo struct { + Count types.U32 + Miner types.AccountID + OriginMiner types.AccountID + FragmentHash FileHash + FileHash FileHash + GenBlock types.U32 + Deadline types.U32 +} + +type RestoralTargetInfo struct { + Miner types.AccountID + ServiceSpace types.U128 + RestoredSpace types.U128 + CoolingBlock types.U32 +} + +type UserFileSliceInfo struct { + Filehash FileHash + Filesize types.U128 +} + +type SpaceProofInfo struct { + Miner types.AccountID + Front types.U64 + Rear types.U64 + PoisKey PoISKeyInfo + Accumulator Accumulator +} + type SysProperties struct { Ss58Format types.Bytes TokenDecimals types.U8 @@ -298,11 +343,7 @@ type OssInfo struct { Domain types.Bytes } -type BucketInfo struct { - ObjectsList []FileHash - Authority []types.AccountID -} - +// Sminer type MinerInfo struct { BeneficiaryAccount types.AccountID StakingAccount types.AccountID @@ -319,14 +360,6 @@ type MinerInfo struct { TeeSig TeeSig } -type SpaceProofInfo struct { - Miner types.AccountID - Front types.U64 - Rear types.U64 - PoisKey PoISKeyInfo - Accumulator Accumulator -} - type MinerReward struct { TotalReward types.U128 RewardIssued types.U128 @@ -342,12 +375,39 @@ type RewardOrder struct { LastReceiveBlock types.U32 } -type FileMetadata struct { - SegmentList []SegmentInfo - Owner []UserBrief - FileSize types.U128 - Completion types.U32 - State types.U8 +// StorageHandler +type UserSpaceInfo struct { + TotalSpace types.U128 + UsedSpace types.U128 + LockedSpace types.U128 + RemainingSpace types.U128 + Start types.U32 + Deadline types.U32 + State types.Bytes +} + +// Staking +type StakingEraRewardPoints struct { + Total types.U32 + Individual []Individual +} + +type Individual struct { + Acc types.AccountID + Reward types.U32 +} + +// TeeWorker +type WorkerInfo struct { + Pubkey WorkerPublicKey + EcdhPubkey EcdhPublicKey + Version types.U32 + LastUpdated types.U64 + StashAccount types.Option[types.AccountID] + AttestationProvider types.Option[types.U8] + ConfidenceLevel types.U8 + Features []types.U32 + Role types.U8 // 0:Full 1:Verifier 2:Marker } type SegmentInfo struct { @@ -368,13 +428,6 @@ type FragmentInfo struct { Miner types.AccountID } -type StorageOrder struct { - FileSize types.U128 - SegmentList []SegmentList - User UserBrief - CompleteList []CompleteInfo -} - type SegmentList struct { SegmentHash FileHash FragmentHash []FileHash @@ -385,22 +438,6 @@ type CompleteInfo struct { Miner types.AccountID } -type UserSpaceInfo struct { - TotalSpace types.U128 - UsedSpace types.U128 - LockedSpace types.U128 - RemainingSpace types.U128 - Start types.U32 - Deadline types.U32 - State types.Bytes -} - -type ChallengeInfo struct { - MinerSnapshot MinerSnapShot - ChallengeElement ChallengeElement - ProveInfo ProveInfo -} - type ProveInfo struct { Assign types.U8 IdleProve types.Option[IdleProveInfo] @@ -441,35 +478,6 @@ type ServiceProveInfo struct { VerifyResult types.Option[bool] } -type TeeWorkerInfo struct { - Pubkey WorkerPublicKey - EcdhPubkey EcdhPublicKey - Version types.U32 - LastUpdated types.U64 - StashAccount types.Option[types.AccountID] - AttestationProvider types.Option[types.U8] - ConfidenceLevel types.U8 - Features []types.U32 - Role types.U8 // 0:Full 1:Verifier 2:Marker -} - -type RestoralOrderInfo struct { - Count types.U32 - Miner types.AccountID - OriginMiner types.AccountID - FragmentHash FileHash - FileHash FileHash - GenBlock types.U32 - Deadline types.U32 -} - -type RestoralTargetInfo struct { - Miner types.AccountID - ServiceSpace types.U128 - RestoredSpace types.U128 - CoolingBlock types.U32 -} - type ExpendersInfo struct { K types.U64 N types.U64 @@ -511,16 +519,6 @@ type OtherStakingExposure struct { Value types.U128 } -type StakingEraRewardPoints struct { - Total types.U32 - Individual []Individual -} - -type Individual struct { - Acc types.AccountID - Reward types.U32 -} - type StakingNominations struct { Targets []types.AccountID SubmittedIn types.U32 diff --git a/chain/rpc_call.go b/chain/rpc_call.go new file mode 100644 index 0000000..2ece41f --- /dev/null +++ b/chain/rpc_call.go @@ -0,0 +1,110 @@ +/* + Copyright (C) CESS. All rights reserved. + Copyright (C) Cumulus Encrypted Storage System. All rights reserved. + + SPDX-License-Identifier: Apache-2.0 +*/ + +package chain + +import ( + "log" + + "github.com/CESSProject/cess-go-sdk/utils" + "github.com/centrifuge/go-substrate-rpc-client/v4/types" +) + +// SystemProperties query system properties +// +// Return: +// - SysProperties: system properties +// - error: error message +func (c *ChainClient) SystemProperties() (SysProperties, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + var data SysProperties + if !c.GetRpcState() { + return data, ERR_RPC_CONNECTION + } + err := c.api.Client.Call(&data, RPC_SYS_Properties) + return data, err +} + +// SystemProperties query system properties +// +// Return: +// - string: system chain +// - error: error message +func (c *ChainClient) SystemChain() (string, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + var data types.Text + if !c.GetRpcState() { + return "", ERR_RPC_CONNECTION + } + err := c.api.Client.Call(&data, RPC_SYS_Chain) + return string(data), err +} + +// SystemSyncState query system sync state +// +// Return: +// - SysSyncState: system sync state +// - error: error message +func (c *ChainClient) SystemSyncState() (SysSyncState, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + var data SysSyncState + if !c.GetRpcState() { + return data, ERR_RPC_CONNECTION + } + err := c.api.Client.Call(&data, RPC_SYS_SyncState) + return data, err +} + +// SystemVersion query system version +// +// Return: +// - string: system version +// - error: error message +func (c *ChainClient) SystemVersion() (string, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + var data types.Text + if !c.GetRpcState() { + return "", ERR_RPC_CONNECTION + } + err := c.api.Client.Call(&data, RPC_SYS_Version) + return string(data), err +} + +// NetListening query net listenning +// +// Return: +// - bool: net listenning +// - error: error message +func (c *ChainClient) NetListening() (bool, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + var data types.Bool + if !c.GetRpcState() { + return false, ERR_RPC_CONNECTION + } + err := c.api.Client.Call(&data, RPC_NET_Listening) + return bool(data), err +} diff --git a/chain/sminer.go b/chain/sminer.go index e2dd214..b1e8dd8 100755 --- a/chain/sminer.go +++ b/chain/sminer.go @@ -15,328 +15,445 @@ import ( "strings" "time" - "github.com/CESSProject/cess-go-sdk/core/pattern" "github.com/CESSProject/cess-go-sdk/utils" "github.com/centrifuge/go-substrate-rpc-client/v4/types" "github.com/centrifuge/go-substrate-rpc-client/v4/types/codec" "github.com/pkg/errors" ) -func (c *ChainClient) QueryExpenders() (pattern.ExpendersInfo, error) { +// QueryExpenders query expenders (idle data specification) +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - ExpendersInfo: idle data specification +// - error: error message +func (c *ChainClient) QueryExpenders(block int32) (ExpendersInfo, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - var data pattern.ExpendersInfo + var data ExpendersInfo - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return data, ERR_RPC_CONNECTION } - key, err := types.CreateStorageKey(c.metadata, pattern.SMINER, pattern.EXPENDERS) + key, err := types.CreateStorageKey(c.metadata, Sminer, Expenders) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.EXPENDERS, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), Sminer, Expenders, err) return data, err } - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Sminer, Expenders, err) + c.SetRpcState(false) + return data, err + } + if !ok { + return data, ERR_RPC_EMPTY_VALUE + } + return data, nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + return data, err + } + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.EXPENDERS, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), Sminer, Expenders, err) + c.SetRpcState(false) return data, err } if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE + return data, ERR_RPC_EMPTY_VALUE } return data, nil } -func (c *ChainClient) QueryStorageMinerByAccount(account string) (pattern.MinerInfo, error) { - publickey, err := utils.ParsingPublickey(account) - if err != nil { - return pattern.MinerInfo{}, err - } - return c.QueryStorageMiner(publickey) -} -func (c *ChainClient) QueryStorageMiner(puk []byte) (pattern.MinerInfo, error) { +// QueryMinerItems query storage miner info +// - accountID: storage miner account +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - MinerInfo: storage miner info +// - error: error message +func (c *ChainClient) QueryMinerItems(accountID []byte, block int32) (MinerInfo, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - var data pattern.MinerInfo + var data MinerInfo - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return data, ERR_RPC_CONNECTION } - key, err := types.CreateStorageKey(c.metadata, pattern.SMINER, pattern.MINERITEMS, puk) + key, err := types.CreateStorageKey(c.metadata, Sminer, MinerItems, accountID) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.MINERITEMS, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), Sminer, MinerItems, err) return data, err } - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Sminer, MinerItems, err) + c.SetRpcState(false) + return data, err + } + if !ok { + return data, ERR_RPC_EMPTY_VALUE + } + return data, nil + } + + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.MINERITEMS, err) - c.SetChainState(false) + return data, err + } + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), Sminer, MinerItems, err) + c.SetRpcState(false) return data, err } if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE + return data, ERR_RPC_EMPTY_VALUE } return data, nil } -func (c *ChainClient) QueryStorageMinerByBlock(puk []byte, block int32) (pattern.MinerInfo, error) { +// QueryStakingStartBlock query storage miner's starting staking block +// - accountID: storage miner account +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - uint32: starting staking block +// - error: error message +func (c *ChainClient) QueryStakingStartBlock(accountID []byte, block int32) (uint32, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - var data pattern.MinerInfo + var data types.U32 - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return 0, ERR_RPC_CONNECTION } - key, err := types.CreateStorageKey(c.metadata, pattern.SMINER, pattern.MINERITEMS, puk) + key, err := types.CreateStorageKey(c.metadata, Sminer, StakingStartBlock, accountID) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.MINERITEMS, err) - c.SetChainState(false) - return data, err + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), Sminer, StakingStartBlock, err) + return 0, err } if block < 0 { ok, err := c.api.RPC.State.GetStorageLatest(key, &data) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.MINERITEMS, err) - c.SetChainState(false) - return data, err + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Sminer, StakingStartBlock, err) + c.SetRpcState(false) + return 0, err } if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE + return 0, ERR_RPC_EMPTY_VALUE } - return data, nil + return uint32(data), nil } - blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.MINERITEMS, err) - c.SetChainState(false) - return data, err + return 0, err } - ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.MINERITEMS, err) - c.SetChainState(false) - return data, err + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Sminer, StakingStartBlock, err) + c.SetRpcState(false) + return 0, err } if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE + return 0, ERR_RPC_EMPTY_VALUE } - - return data, nil + return uint32(data), nil } -func (c *ChainClient) QueryStorageMinerStakingStartBlock(puk []byte) (types.U32, error) { +// QueryAllMiner query all storage miner accounts +// - accountID: storage miner account +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - []types.AccountID: all storage miner accounts +// - error: error message +func (c *ChainClient) QueryAllMiner(block int32) ([]types.AccountID, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - var data types.U32 + var data []types.AccountID - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return data, ERR_RPC_CONNECTION } - key, err := types.CreateStorageKey(c.metadata, pattern.SMINER, pattern.STAKINGSTARTBLOCK, puk) + key, err := types.CreateStorageKey(c.metadata, Sminer, AllMiner) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.STAKINGSTARTBLOCK, err) - c.SetChainState(false) - return data, err + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), Sminer, AllMiner, err) + return nil, err } - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Sminer, AllMiner, err) + c.SetRpcState(false) + return nil, err + } + if !ok { + return nil, ERR_RPC_EMPTY_VALUE + } + return data, nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.STAKINGSTARTBLOCK, err) - c.SetChainState(false) return data, err } + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), Sminer, AllMiner, err) + c.SetRpcState(false) + return nil, err + } if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE + return nil, ERR_RPC_EMPTY_VALUE } return data, nil } -func (c *ChainClient) QueryAllSminerAccount() ([]types.AccountID, error) { +// QueryCounterForMinerItems query all storage miner count +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - uint32: all storage miner count +// - error: error message +func (c *ChainClient) QueryCounterForMinerItems(block int32) (uint32, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - var data []types.AccountID + var data types.U32 - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return 0, ERR_RPC_CONNECTION } - key, err := types.CreateStorageKey(c.metadata, pattern.SMINER, pattern.ALLMINER) + key, err := types.CreateStorageKey(c.metadata, Sminer, CounterForMinerItems) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.ALLMINER, err) - c.SetChainState(false) - return nil, err + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), Sminer, CounterForMinerItems, err) + return 0, err } - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Sminer, CounterForMinerItems, err) + c.SetRpcState(false) + return 0, err + } + if !ok { + return 0, ERR_RPC_EMPTY_VALUE + } + return uint32(data), nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.ALLMINER, err) - c.SetChainState(false) - return nil, err + return 0, err + } + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), Sminer, CounterForMinerItems, err) + c.SetRpcState(false) + return 0, err } if !ok { - return nil, pattern.ERR_RPC_EMPTY_VALUE + return 0, ERR_RPC_EMPTY_VALUE } - return data, nil + return uint32(data), nil } -func (c *ChainClient) QueryAllSminerAccountByBlock(block int32) ([]types.AccountID, error) { +// QueryRewardMap query all reward information for storage miner +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - MinerReward: all reward information +// - error: error message +func (c *ChainClient) QueryRewardMap(accountID []byte, block int32) (MinerReward, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - var data []types.AccountID + var data MinerReward - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return data, ERR_RPC_CONNECTION } - key, err := types.CreateStorageKey(c.metadata, pattern.SMINER, pattern.ALLMINER) + key, err := types.CreateStorageKey(c.metadata, Sminer, RewardMap, accountID) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.ALLMINER, err) - c.SetChainState(false) - return nil, err + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), Sminer, RewardMap, err) + return data, err } if block < 0 { ok, err := c.api.RPC.State.GetStorageLatest(key, &data) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.ALLMINER, err) - c.SetChainState(false) - return nil, err + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Sminer, RewardMap, err) + c.SetRpcState(false) + return data, err } if !ok { - return nil, pattern.ERR_RPC_EMPTY_VALUE + return data, ERR_RPC_EMPTY_VALUE } + return data, nil } - blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.ALLMINER, err) - c.SetChainState(false) return data, err } - ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.ALLMINER, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), Sminer, RewardMap, err) + c.SetRpcState(false) return data, err } if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE + return data, ERR_RPC_EMPTY_VALUE } - return data, nil } -func (c *ChainClient) QueryRewardsMap(puk []byte) (pattern.MinerReward, error) { +// QueryRestoralTarget query the data recovery information of exited storage miner +// - accountID: storage miner account +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - RestoralTargetInfo: the data recovery information +// - error: error message +func (c *ChainClient) QueryRestoralTarget(accountID []byte, block int32) (RestoralTargetInfo, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - var data pattern.MinerReward + var data RestoralTargetInfo - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return data, ERR_RPC_CONNECTION } - key, err := types.CreateStorageKey(c.metadata, pattern.SMINER, pattern.REWARDMAP, puk) + acc, err := types.NewAccountID(accountID) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.REWARDMAP, err) - c.SetChainState(false) - return data, err + return data, errors.Wrap(err, "[NewAccountID]") + } + + account, err := codec.Encode(*acc) + if err != nil { + return data, errors.Wrap(err, "[EncodeToBytes]") } - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + key, err := types.CreateStorageKey(c.metadata, Sminer, RestoralTarget, account) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.REWARDMAP, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), Sminer, RestoralTarget, err) return data, err } - if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Sminer, RestoralTarget, err) + c.SetRpcState(false) + return data, err + } + if !ok { + return data, ERR_RPC_EMPTY_VALUE + } + return data, nil } - return data, nil -} - -func (c *ChainClient) QueryRewards(puk []byte) (pattern.RewardsType, error) { - var reward pattern.RewardsType - rewards, err := c.QueryRewardsMap(puk) + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - return reward, err + return data, err } - - reward.Total = rewards.TotalReward.String() - reward.Claimed = rewards.RewardIssued.String() - - return reward, nil + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), Sminer, RestoralTarget, err) + c.SetRpcState(false) + return data, err + } + if !ok { + return data, ERR_RPC_EMPTY_VALUE + } + return data, nil } -func (c *ChainClient) QueryRestoralTargetList() ([]pattern.RestoralTargetInfo, error) { +// QueryAllRestoralTarget query the data recovery information of all exited storage miner +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - []RestoralTargetInfo: all the data recovery information +// - error: error message +func (c *ChainClient) QueryAllRestoralTarget(block int32) ([]RestoralTargetInfo, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - var result []pattern.RestoralTargetInfo + var result []RestoralTargetInfo - if !c.GetChainState() { - return nil, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return nil, ERR_RPC_CONNECTION } - key := createPrefixedKey(pattern.SMINER, pattern.RESTORALTARGETINFO) + key := CreatePrefixedKey(Sminer, RestoralTarget) keys, err := c.api.RPC.State.GetKeysLatest(key) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetKeysLatest: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.RESTORALTARGETINFO, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetKeysLatest: %v", c.GetCurrentRpcAddr(), Sminer, RestoralTarget, err) + c.SetRpcState(false) return nil, err } - - set, err := c.api.RPC.State.QueryStorageAtLatest(keys) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAtLatest: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.RESTORALTARGETINFO, err) - c.SetChainState(false) - return nil, err + var set []types.StorageChangeSet + if block < 0 { + set, err = c.api.RPC.State.QueryStorageAtLatest(keys) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAtLatest: %v", c.GetCurrentRpcAddr(), Sminer, RestoralTarget, err) + c.SetRpcState(false) + return nil, err + } + } else { + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + return nil, err + } + set, err = c.api.RPC.State.QueryStorageAt(keys, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAt: %v", c.GetCurrentRpcAddr(), Sminer, RestoralTarget, err) + c.SetRpcState(false) + return nil, err + } } - for _, elem := range set { for _, change := range elem.Changes { - var data pattern.RestoralTargetInfo + var data RestoralTargetInfo if err := codec.Decode(change.StorageData, &data); err != nil { continue } @@ -346,90 +463,78 @@ func (c *ChainClient) QueryRestoralTargetList() ([]pattern.RestoralTargetInfo, e return result, nil } -func (c *ChainClient) QueryRestoralTarget(puk []byte) (pattern.RestoralTargetInfo, error) { +// QueryPendingReplacements query the size of the storage miner's replaceable idle data +// - accountID: storage miner account +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - types.U128: the size of replaceable idle data +// - error: error message +func (c *ChainClient) QueryPendingReplacements(accountID []byte, block int32) (types.U128, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - var data pattern.RestoralTargetInfo - - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION - } + var data types.U128 - acc, err := types.NewAccountID(puk) + acc, err := types.NewAccountID(accountID) if err != nil { return data, errors.Wrap(err, "[NewAccountID]") } - owner, err := codec.Encode(*acc) + account, err := codec.Encode(*acc) if err != nil { return data, errors.Wrap(err, "[EncodeToBytes]") } - key, err := types.CreateStorageKey(c.metadata, pattern.SMINER, pattern.RESTORALTARGETINFO, owner) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.RESTORALTARGETINFO, err) - c.SetChainState(false) - return data, err + if !c.GetRpcState() { + return data, ERR_RPC_CONNECTION } - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + key, err := types.CreateStorageKey(c.metadata, Sminer, PendingReplacements, account) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.RESTORALTARGETINFO, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), Sminer, PendingReplacements, err) return data, err } - if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE - } - return data, nil -} -func (c *ChainClient) QueryPendingReplacements(puk []byte) (types.U128, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Sminer, PendingReplacements, err) + c.SetRpcState(false) + return data, err } - }() - - var data types.U128 - - acc, err := types.NewAccountID(puk) - if err != nil { - return data, errors.Wrap(err, "[NewAccountID]") - } - - owner, err := codec.Encode(*acc) - if err != nil { - return data, errors.Wrap(err, "[EncodeToBytes]") - } - - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION + if !ok { + return data, ERR_RPC_EMPTY_VALUE + } + return data, nil } - - key, err := types.CreateStorageKey(c.metadata, pattern.SMINER, pattern.PENDINGREPLACE, owner) + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.PENDINGREPLACE, err) - c.SetChainState(false) return data, err } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.PENDINGREPLACE, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), Sminer, PendingReplacements, err) + c.SetRpcState(false) return data, err } if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE + return data, ERR_RPC_EMPTY_VALUE } return data, nil } +// QueryCompleteSnapShot query the number of storage miners and storage miner power in each era +// - era: era id +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - uint32: the number of storage miners in current era +// - uint64: all storage miners power in current era +// - error: error message func (c *ChainClient) QueryCompleteSnapShot(era uint32, block int32) (uint32, uint64, error) { defer func() { if err := recover(); err != nil { @@ -437,10 +542,10 @@ func (c *ChainClient) QueryCompleteSnapShot(era uint32, block int32) (uint32, ui } }() - var data pattern.CompleteSnapShotType + var data CompleteSnapShotType - if !c.GetChainState() { - return 0, 0, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return 0, 0, ERR_RPC_CONNECTION } param, err := codec.Encode(era) @@ -448,47 +553,56 @@ func (c *ChainClient) QueryCompleteSnapShot(era uint32, block int32) (uint32, ui return 0, 0, err } - key, err := types.CreateStorageKey(c.metadata, pattern.SMINER, pattern.CompleteSnapShot, param) + key, err := types.CreateStorageKey(c.metadata, Sminer, CompleteSnapShot, param) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.CompleteSnapShot, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), Sminer, CompleteSnapShot, err) return 0, 0, err } if block < 0 { ok, err := c.api.RPC.State.GetStorageLatest(key, &data) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.CompleteSnapShot, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Sminer, CompleteSnapShot, err) + c.SetRpcState(false) return 0, 0, err } if !ok { - return 0, 0, pattern.ERR_RPC_EMPTY_VALUE + return 0, 0, ERR_RPC_EMPTY_VALUE } return uint32(data.MinerCount), data.TotalPower.Uint64(), nil } blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.CompleteSnapShot, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), Sminer, CompleteSnapShot, err) return 0, 0, err } ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), pattern.SMINER, pattern.CompleteSnapShot, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), Sminer, CompleteSnapShot, err) + c.SetRpcState(false) return 0, 0, err } if !ok { - return 0, 0, pattern.ERR_RPC_EMPTY_VALUE + return 0, 0, ERR_RPC_EMPTY_VALUE } return uint32(data.MinerCount), data.TotalPower.Uint64(), nil } -func (c *ChainClient) UpdateSminerPeerId(peerid pattern.PeerId) (string, error) { +// IncreaseCollateral increases the number of staking for storage miner +// - accountID: storage miner account +// - token: number of staking +// +// Return: +// - string: block hash +// - error: error message +// +// Note: +// - The number of staking to be added is calculated in the smallest unit, +// if you want to add 1CESS staking, you need to fill in "1000000000000000000" +func (c *ChainClient) IncreaseCollateral(accountID []byte, token string) (string, error) { c.lock.Lock() defer func() { c.lock.Unlock() @@ -498,38 +612,46 @@ func (c *ChainClient) UpdateSminerPeerId(peerid pattern.PeerId) (string, error) }() var ( - txhash string + blockhash string accountInfo types.AccountInfo ) - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION + } + + tokens, ok := new(big.Int).SetString(token, 10) + if !ok { + return "", fmt.Errorf("[IncreaseCollateral] invalid token: %s", token) } - call, err := types.NewCall(c.metadata, pattern.TX_SMINER_UPDATEPEERID, peerid) + acc, err := types.NewAccountID(accountID) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_UPDATEPEERID, err) - c.SetChainState(false) - return txhash, err + return blockhash, errors.Wrap(err, "[NewAccountID]") + } + + call, err := types.NewCall(c.metadata, TX_Sminer_IncreaseCollateral, *acc, types.NewUCompact(tokens)) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_Sminer_IncreaseCollateral, err) + return blockhash, err } ext := types.NewExtrinsic(call) - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_UPDATEPEERID, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_Sminer_IncreaseCollateral, err) + return blockhash, err } - ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) + ok, err = c.api.RPC.State.GetStorageLatest(key, &accountInfo) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_UPDATEPEERID, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_Sminer_IncreaseCollateral, err) + c.SetRpcState(false) + return blockhash, err } if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE + return blockhash, ERR_RPC_EMPTY_VALUE } o := types.SignatureOptions{ @@ -545,9 +667,8 @@ func (c *ChainClient) UpdateSminerPeerId(peerid pattern.PeerId) (string, error) // Sign the transaction err = ext.Sign(c.keyring, o) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_UPDATEPEERID, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_Sminer_IncreaseCollateral, err) + return blockhash, err } <-c.txTicker.C @@ -555,44 +676,57 @@ func (c *ChainClient) UpdateSminerPeerId(peerid pattern.PeerId) (string, error) // Do the transfer and track the actual status sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) err = ext.Sign(c.keyring, o) if err != nil { - return txhash, errors.Wrap(err, "[Sign]") + return blockhash, errors.Wrap(err, "[Sign]") } + <-c.txTicker.C sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_UPDATEPEERID, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Sminer_IncreaseCollateral, err) + c.SetRpcState(false) + return blockhash, err } } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_UPDATEPEERID, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Sminer_IncreaseCollateral, err) + c.SetRpcState(false) + return blockhash, err } } defer sub.Unsubscribe() + timeout := time.NewTimer(c.packingTime) defer timeout.Stop() + for { select { case status := <-sub.Chan(): if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_Sminer_UpdataIp(status.AsInBlock) - return txhash, err + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_Sminer_IncreaseCollateral(status.AsInBlock) + return blockhash, err } case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") + return blockhash, errors.Wrap(err, "[sub]") case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT + return blockhash, ERR_RPC_TIMEOUT } } } -func (c *ChainClient) ExitSminer(miner string) (string, error) { +// IncreaseDeclarationSpace increases the size of space declared on the chain +// - tibCount: the size of the declaration space increased, in TiB +// +// Return: +// - string: block hash +// - error: error message +// +// Note: +// - the size of the declared space cannot be reduced +// - when the staking does not meet the declared space size, you will be frozen +func (c *ChainClient) IncreaseDeclarationSpace(tibCount uint32) (string, error) { c.lock.Lock() defer func() { c.lock.Unlock() @@ -602,50 +736,36 @@ func (c *ChainClient) ExitSminer(miner string) (string, error) { }() var ( - err error - txhash string - call types.Call + blockhash string accountInfo types.AccountInfo ) - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION } - pubkey, err := utils.ParsingPublickey(miner) + call, err := types.NewCall(c.metadata, TX_Sminer_IncreaseDeclarationSpace, types.NewU32(tibCount)) if err != nil { - return txhash, errors.Wrap(err, "[ParsingPublickey]") - } - acc, err := types.NewAccountID(pubkey) - if err != nil { - return txhash, errors.Wrap(err, "[NewAccountID]") - } - - call, err = types.NewCall(c.metadata, pattern.TX_SMINER_MINEREXITPREP, *acc) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_MINEREXITPREP, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_Sminer_IncreaseDeclarationSpace, err) + return blockhash, err } ext := types.NewExtrinsic(call) - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_MINEREXITPREP, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_Sminer_IncreaseDeclarationSpace, err) + return blockhash, err } ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_MINEREXITPREP, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_Sminer_IncreaseDeclarationSpace, err) + c.SetRpcState(false) + return blockhash, err } - if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE + return blockhash, ERR_RPC_EMPTY_VALUE } o := types.SignatureOptions{ @@ -661,9 +781,8 @@ func (c *ChainClient) ExitSminer(miner string) (string, error) { // Sign the transaction err = ext.Sign(c.keyring, o) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_MINEREXITPREP, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_Sminer_IncreaseDeclarationSpace, err) + return blockhash, err } <-c.txTicker.C @@ -671,22 +790,23 @@ func (c *ChainClient) ExitSminer(miner string) (string, error) { // Do the transfer and track the actual status sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) err = ext.Sign(c.keyring, o) if err != nil { - return txhash, errors.Wrap(err, "[Sign]") + return blockhash, errors.Wrap(err, "[Sign]") } + <-c.txTicker.C sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_MINEREXITPREP, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Sminer_IncreaseDeclarationSpace, err) + c.SetRpcState(false) + return blockhash, err } } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_MINEREXITPREP, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Sminer_IncreaseDeclarationSpace, err) + c.SetRpcState(false) + return blockhash, err } } defer sub.Unsubscribe() @@ -698,27 +818,28 @@ func (c *ChainClient) ExitSminer(miner string) (string, error) { select { case status := <-sub.Chan(): if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_Sminer_MinerExitPrep(status.AsInBlock) - return txhash, err + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_Sminer_IncreaseDeclarationSpace(status.AsInBlock) + return blockhash, err } case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") + return blockhash, errors.Wrap(err, "[sub]") case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT + return blockhash, ERR_RPC_TIMEOUT } } } -func (c *ChainClient) UpdateEarningsAccount(earnings string) (string, error) { - puk, err := utils.ParsingPublickey(earnings) - if err != nil { - return "", err - } - return c.UpdateEarningsAcc(puk) -} - -func (c *ChainClient) UpdateEarningsAcc(puk []byte) (string, error) { +// MinerExitPrep pre-exit storage miner +// +// Return: +// - string: block hash +// - error: error message +// +// Note: +// - after pre-exit, you need to wait for one day before it will automatically exit +// - cannot register as a storage miner again after pre-exit +func (c *ChainClient) MinerExitPrep() (string, error) { c.lock.Lock() defer func() { c.lock.Unlock() @@ -728,43 +849,44 @@ func (c *ChainClient) UpdateEarningsAcc(puk []byte) (string, error) { }() var ( + err error txhash string + call types.Call accountInfo types.AccountInfo ) - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return txhash, ERR_RPC_CONNECTION } - acc, err := types.NewAccountID(puk) + acc, err := types.NewAccountID(c.GetSignatureAccPulickey()) if err != nil { return txhash, errors.Wrap(err, "[NewAccountID]") } - call, err := types.NewCall(c.metadata, pattern.TX_SMINER_UPDATEINCOME, *acc) + call, err = types.NewCall(c.metadata, TX_Sminer_MinerExitPrep, *acc) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_UPDATEINCOME, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_Sminer_MinerExitPrep, err) return txhash, err } ext := types.NewExtrinsic(call) - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_UPDATEINCOME, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_Sminer_MinerExitPrep, err) return txhash, err } ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_UPDATEINCOME, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_Sminer_MinerExitPrep, err) + c.SetRpcState(false) return txhash, err } + if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE + return txhash, ERR_RPC_EMPTY_VALUE } o := types.SignatureOptions{ @@ -780,8 +902,7 @@ func (c *ChainClient) UpdateEarningsAcc(puk []byte) (string, error) { // Sign the transaction err = ext.Sign(c.keyring, o) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_UPDATEINCOME, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_Sminer_MinerExitPrep, err) return txhash, err } @@ -790,21 +911,22 @@ func (c *ChainClient) UpdateEarningsAcc(puk []byte) (string, error) { // Do the transfer and track the actual status sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) err = ext.Sign(c.keyring, o) if err != nil { return txhash, errors.Wrap(err, "[Sign]") } + <-c.txTicker.C sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_UPDATEINCOME, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Sminer_MinerExitPrep, err) + c.SetRpcState(false) return txhash, err } } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_UPDATEINCOME, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Sminer_MinerExitPrep, err) + c.SetRpcState(false) return txhash, err } } @@ -818,26 +940,27 @@ func (c *ChainClient) UpdateEarningsAcc(puk []byte) (string, error) { case status := <-sub.Chan(): if status.IsInBlock { txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_Sminer_UpdataBeneficiary(status.AsInBlock) + _, err = c.RetrieveEvent_Sminer_MinerExitPrep(status.AsInBlock) return txhash, err } case err = <-sub.Err(): return txhash, errors.Wrap(err, "[sub]") case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT + return txhash, ERR_RPC_TIMEOUT } } } -func (c *ChainClient) IncreaseStorageNodeStakingAmount(miner string, token string) (string, error) { - tokens, ok := new(big.Int).SetString(token+pattern.TokenPrecision_CESS, 10) - if !ok { - return "", fmt.Errorf("invalid tokens: %s", token) - } - return c.IncreaseStakingAmount(miner, tokens) -} - -func (c *ChainClient) IncreaseStakingAmount(miner string, tokens *big.Int) (string, error) { +// MinerWithdraw withdraws all staking +// +// Return: +// - string: block hash +// - error: error message +// +// Note: +// - must be an exited miner to withdraw +// - wait a day to withdraw after pre-exit +func (c *ChainClient) MinerWithdraw() (string, error) { c.lock.Lock() defer func() { c.lock.Unlock() @@ -851,43 +974,32 @@ func (c *ChainClient) IncreaseStakingAmount(miner string, tokens *big.Int) (stri accountInfo types.AccountInfo ) - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return txhash, ERR_RPC_CONNECTION } - pubkey, err := utils.ParsingPublickey(miner) - if err != nil { - return txhash, errors.Wrap(err, "[ParsingPublickey]") - } - acc, err := types.NewAccountID(pubkey) + call, err := types.NewCall(c.metadata, TX_Sminer_MinerWithdraw) if err != nil { - return txhash, errors.Wrap(err, "[NewAccountID]") - } - - call, err := types.NewCall(c.metadata, pattern.TX_SMINER_INCREASESTAKES, *acc, types.NewUCompact(tokens)) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_INCREASESTAKES, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_Sminer_MinerWithdraw, err) return txhash, err } ext := types.NewExtrinsic(call) - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_INCREASESTAKES, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_Sminer_MinerWithdraw, err) return txhash, err } ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_INCREASESTAKES, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_Sminer_MinerWithdraw, err) + c.SetRpcState(false) return txhash, err } if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE + return txhash, ERR_RPC_EMPTY_VALUE } o := types.SignatureOptions{ @@ -903,8 +1015,7 @@ func (c *ChainClient) IncreaseStakingAmount(miner string, tokens *big.Int) (stri // Sign the transaction err = ext.Sign(c.keyring, o) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_INCREASESTAKES, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_Sminer_MinerWithdraw, err) return txhash, err } @@ -913,22 +1024,23 @@ func (c *ChainClient) IncreaseStakingAmount(miner string, tokens *big.Int) (stri // Do the transfer and track the actual status sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) err = ext.Sign(c.keyring, o) if err != nil { return txhash, errors.Wrap(err, "[Sign]") } + <-c.txTicker.C sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_INCREASESTAKES, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Sminer_MinerWithdraw, err) + c.SetRpcState(false) return txhash, err } } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_INCREASESTAKES, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Sminer_MinerWithdraw, err) + c.SetRpcState(false) + return txhash, errors.Wrap(err, "[SubmitAndWatchExtrinsic]") } } defer sub.Unsubscribe() @@ -941,18 +1053,27 @@ func (c *ChainClient) IncreaseStakingAmount(miner string, tokens *big.Int) (stri case status := <-sub.Chan(): if status.IsInBlock { txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_Sminer_IncreaseCollateral(status.AsInBlock) + _, err = c.RetrieveEvent_Sminer_Withdraw(status.AsInBlock) return txhash, err } case err = <-sub.Err(): return txhash, errors.Wrap(err, "[sub]") case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT + return txhash, ERR_RPC_TIMEOUT } } } -func (c *ChainClient) ClaimRewards() (string, error) { +// ReceiveReward to receive rewards +// +// Return: +// - string: block hash +// - error: error message +// +// Note: +// - for storage miner only +// - pass at least one idle and service challenge at the same time to get the reward +func (c *ChainClient) ReceiveReward() (string, error) { c.lock.Lock() defer func() { c.lock.Unlock() @@ -962,38 +1083,36 @@ func (c *ChainClient) ClaimRewards() (string, error) { }() var ( - txhash string + blockhash string accountInfo types.AccountInfo ) - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION } - call, err := types.NewCall(c.metadata, pattern.TX_SMINER_CLAIMREWARD) + call, err := types.NewCall(c.metadata, TX_Sminer_ReceiveReward) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_CLAIMREWARD, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_Sminer_ReceiveReward, err) + return blockhash, err } ext := types.NewExtrinsic(call) - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_CLAIMREWARD, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_Sminer_ReceiveReward, err) + return blockhash, err } ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_CLAIMREWARD, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_Sminer_ReceiveReward, err) + c.SetRpcState(false) + return blockhash, err } if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE + return blockhash, ERR_RPC_EMPTY_VALUE } o := types.SignatureOptions{ @@ -1009,9 +1128,8 @@ func (c *ChainClient) ClaimRewards() (string, error) { // Sign the transaction err = ext.Sign(c.keyring, o) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_CLAIMREWARD, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_Sminer_ReceiveReward, err) + return blockhash, err } <-c.txTicker.C @@ -1019,22 +1137,22 @@ func (c *ChainClient) ClaimRewards() (string, error) { // Do the transfer and track the actual status sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) err = ext.Sign(c.keyring, o) if err != nil { - return txhash, errors.Wrap(err, "[Sign]") + return blockhash, errors.Wrap(err, "[Sign]") } sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_CLAIMREWARD, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Sminer_ReceiveReward, err) + c.SetRpcState(false) + return blockhash, err } } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_CLAIMREWARD, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Sminer_ReceiveReward, err) + c.SetRpcState(false) + return blockhash, err } } defer sub.Unsubscribe() @@ -1046,19 +1164,33 @@ func (c *ChainClient) ClaimRewards() (string, error) { select { case status := <-sub.Chan(): if status.IsInBlock { - txhash = status.AsInBlock.Hex() + blockhash = status.AsInBlock.Hex() _, err = c.RetrieveEvent_Sminer_Receive(status.AsInBlock) - return txhash, err + return blockhash, err } case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") + return blockhash, errors.Wrap(err, "[sub]") case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT + return blockhash, ERR_RPC_TIMEOUT } } } -func (c *ChainClient) Withdraw() (string, error) { +// RegisterPoisKey register pois key, storage miner registration +// requires two stages, this is the second one. +// +// - poisKey: pois key +// - teeSignWithAcc: tee's sign with account +// - teeSign: tee's sign +// - teePuk: tee's work public key +// +// Return: +// - string: block hash +// - error: error message +// +// Note: +// - storage miners must complete the first stage to register for the second stage +func (c *ChainClient) RegisterPoisKey(poisKey PoISKeyInfo, teeSignWithAcc, teeSign types.Bytes, teePuk WorkerPublicKey) (string, error) { c.lock.Lock() defer func() { c.lock.Unlock() @@ -1068,38 +1200,42 @@ func (c *ChainClient) Withdraw() (string, error) { }() var ( - txhash string + blockhash string accountInfo types.AccountInfo ) - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION } - call, err := types.NewCall(c.metadata, pattern.TX_SMINER_WITHDRAW) + call, err := types.NewCall(c.metadata, TX_Sminer_RegisterPoisKey, poisKey, teeSignWithAcc, teeSign, teePuk) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_WITHDRAW, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_Sminer_RegisterPoisKey, err) + return blockhash, err } ext := types.NewExtrinsic(call) - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_WITHDRAW, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_Sminer_RegisterPoisKey, err) + return blockhash, err } ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_WITHDRAW, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_Sminer_RegisterPoisKey, err) + c.SetRpcState(false) + return blockhash, err } + if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE + keyStr, _ := utils.NumsToByteStr(key, map[string]bool{}) + return blockhash, fmt.Errorf( + "chain rpc.state.GetStorageLatest[%v]: %v", + keyStr, + ERR_RPC_EMPTY_VALUE, + ) } o := types.SignatureOptions{ @@ -1115,9 +1251,8 @@ func (c *ChainClient) Withdraw() (string, error) { // Sign the transaction err = ext.Sign(c.keyring, o) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_WITHDRAW, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_Sminer_RegisterPoisKey, err) + return blockhash, err } <-c.txTicker.C @@ -1125,22 +1260,23 @@ func (c *ChainClient) Withdraw() (string, error) { // Do the transfer and track the actual status sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) err = ext.Sign(c.keyring, o) if err != nil { - return txhash, errors.Wrap(err, "[Sign]") + return blockhash, errors.Wrap(err, "[Sign]") } + <-c.txTicker.C sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_WITHDRAW, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Sminer_RegisterPoisKey, err) + c.SetRpcState(false) + return blockhash, err } } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_WITHDRAW, err) - c.SetChainState(false) - return txhash, errors.Wrap(err, "[SubmitAndWatchExtrinsic]") + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Sminer_RegisterPoisKey, err) + c.SetRpcState(false) + return blockhash, err } } defer sub.Unsubscribe() @@ -1152,19 +1288,30 @@ func (c *ChainClient) Withdraw() (string, error) { select { case status := <-sub.Chan(): if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_Sminer_Withdraw(status.AsInBlock) - return txhash, err + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_Sminer_RegisterPoisKey(status.AsInBlock) + return blockhash, err } case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") + return blockhash, errors.Wrap(err, "[sub]") case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT + return blockhash, ERR_RPC_TIMEOUT } } } -func (c *ChainClient) RegisterSminer(earnings string, peerId []byte, pledge uint64, tib_count uint32) (string, error) { +// RegnstkSminer registers as a storage miner, +// which is the first stage of storage miner registration. +// +// - earnings: earnings account +// - peerId: peer id +// - staking: number of staking, the unit is CESS +// - tibCount: the size of declaration space, in TiB +// +// Return: +// - string: block hash +// - error: error message +func (c *ChainClient) RegnstkSminer(earnings string, peerId []byte, staking uint64, tibCount uint32) (string, error) { c.lock.Lock() defer func() { c.lock.Unlock() @@ -1174,68 +1321,62 @@ func (c *ChainClient) RegisterSminer(earnings string, peerId []byte, pledge uint }() var ( - err error - txhash string - pubkey []byte - acc *types.AccountID - call types.Call + blockhash string accountInfo types.AccountInfo ) - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION } - var peerid pattern.PeerId - if len(peerid) != len(peerId) { - return txhash, fmt.Errorf("invalid peerid: %v", peerId) + var peerid PeerId + if len(peerId) != PeerIdPublicKeyLen { + return blockhash, fmt.Errorf("[RegnstkSminer] invalid peerid: %v", peerId) } for i := 0; i < len(peerid); i++ { peerid[i] = types.U8(peerId[i]) } - pubkey, err = utils.ParsingPublickey(earnings) + pubkey, err := utils.ParsingPublickey(earnings) if err != nil { - return txhash, errors.Wrap(err, "[DecodeToPub]") + return blockhash, errors.Wrap(err, "[DecodeToPub]") } - acc, err = types.NewAccountID(pubkey) + acc, err := types.NewAccountID(pubkey) if err != nil { - return txhash, errors.Wrap(err, "[NewAccountID]") + return blockhash, errors.Wrap(err, "[NewAccountID]") } - realTokens, ok := new(big.Int).SetString(strconv.FormatUint(pledge, 10)+pattern.TokenPrecision_CESS, 10) + realTokens, ok := new(big.Int).SetString(strconv.FormatUint(staking, 10)+TokenPrecision_CESS, 10) if !ok { - return txhash, errors.New("[big.Int.SetString]") + return blockhash, errors.New("[big.Int.SetString]") } - call, err = types.NewCall(c.metadata, pattern.TX_SMINER_REGISTER, *acc, peerid, types.NewU128(*realTokens), types.U32(tib_count)) + call, err := types.NewCall(c.metadata, TX_Sminer_Regnstk, *acc, peerid, types.NewU128(*realTokens), types.U32(tibCount)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_REGISTER, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_Sminer_Regnstk, err) + return blockhash, err } ext := types.NewExtrinsic(call) - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_REGISTER, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_Sminer_Regnstk, err) + return blockhash, err } ok, err = c.api.RPC.State.GetStorageLatest(key, &accountInfo) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_REGISTER, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_Sminer_Regnstk, err) + c.SetRpcState(false) + return blockhash, err } if !ok { keyStr, _ := utils.NumsToByteStr(key, map[string]bool{}) - return txhash, fmt.Errorf( + return blockhash, fmt.Errorf( "chain rpc.state.GetStorageLatest[%v]: %v", keyStr, - pattern.ERR_RPC_EMPTY_VALUE, + ERR_RPC_EMPTY_VALUE, ) } @@ -1252,9 +1393,8 @@ func (c *ChainClient) RegisterSminer(earnings string, peerId []byte, pledge uint // Sign the transaction err = ext.Sign(c.keyring, o) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_REGISTER, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_Sminer_Regnstk, err) + return blockhash, err } <-c.txTicker.C @@ -1262,22 +1402,23 @@ func (c *ChainClient) RegisterSminer(earnings string, peerId []byte, pledge uint // Do the transfer and track the actual status sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) err = ext.Sign(c.keyring, o) if err != nil { - return txhash, errors.Wrap(err, "[Sign]") + return blockhash, errors.Wrap(err, "[Sign]") } + <-c.txTicker.C sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_REGISTER, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Sminer_Regnstk, err) + c.SetRpcState(false) + return blockhash, err } } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_REGISTER, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Sminer_Regnstk, err) + c.SetRpcState(false) + return blockhash, err } } defer sub.Unsubscribe() @@ -1289,19 +1430,31 @@ func (c *ChainClient) RegisterSminer(earnings string, peerId []byte, pledge uint select { case status := <-sub.Chan(): if status.IsInBlock { - txhash = status.AsInBlock.Hex() + blockhash = status.AsInBlock.Hex() _, err = c.RetrieveEvent_Sminer_Registered(status.AsInBlock) - return txhash, err + return blockhash, err } case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") + return blockhash, errors.Wrap(err, "[sub]") case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT + return blockhash, ERR_RPC_TIMEOUT } } } -func (c *ChainClient) RegisterSminerAssignStaking(beneficiaryAcc string, peerId []byte, stakingAcc string, tib_count uint32) (string, error) { +// RegnstkAssignStaking is registered as a storage miner, unlike RegnstkSminer, +// needs to be actively staking by the staking account, which is the first stage +// of storage miner registration. +// +// - earnings: earnings account +// - peerId: peer id +// - stakingAcc: staking account +// - tibCount: the size of declaration space, in TiB +// +// Return: +// - string: block hash +// - error: error message +func (c *ChainClient) RegnstkAssignStaking(earnings string, peerId []byte, stakingAcc string, tibCount uint32) (string, error) { c.lock.Lock() defer func() { c.lock.Unlock() @@ -1311,78 +1464,73 @@ func (c *ChainClient) RegisterSminerAssignStaking(beneficiaryAcc string, peerId }() var ( - err error - txhash string - pubkey []byte - call types.Call + blockhash string accountInfo types.AccountInfo ) - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION } - var peerid pattern.PeerId - if len(peerid) != len(peerId) { - return txhash, fmt.Errorf("invalid peerid: %v", peerId) + var peerid PeerId + if len(peerId) != PeerIdPublicKeyLen { + return blockhash, fmt.Errorf("invalid peerid: %v", peerId) } for i := 0; i < len(peerid); i++ { peerid[i] = types.U8(peerId[i]) } - pubkey, err = utils.ParsingPublickey(beneficiaryAcc) + pubkey, err := utils.ParsingPublickey(earnings) if err != nil { - return txhash, errors.Wrap(err, "[DecodeToPub]") + return blockhash, errors.Wrap(err, "[DecodeToPub]") } beneficiaryacc, err := types.NewAccountID(pubkey) if err != nil { - return txhash, errors.Wrap(err, "[NewAccountID]") + return blockhash, errors.Wrap(err, "[NewAccountID]") } pubkey, err = utils.ParsingPublickey(stakingAcc) if err != nil { - return txhash, errors.Wrap(err, "[DecodeToPub]") + return blockhash, errors.Wrap(err, "[DecodeToPub]") } stakingacc, err := types.NewAccountID(pubkey) if err != nil { - return txhash, errors.Wrap(err, "[NewAccountID]") + return blockhash, errors.Wrap(err, "[NewAccountID]") } - call, err = types.NewCall( + call, err := types.NewCall( c.metadata, - pattern.TX_SMINER_REGISTERASSIGNSTAKING, + TX_Sminer_RegnstkAssignStaking, *beneficiaryacc, peerid, *stakingacc, - types.U32(tib_count), + types.U32(tibCount), ) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_REGISTERASSIGNSTAKING, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_Sminer_RegnstkAssignStaking, err) + return blockhash, err } ext := types.NewExtrinsic(call) - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_REGISTERASSIGNSTAKING, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_Sminer_RegnstkAssignStaking, err) + return blockhash, err } ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_REGISTERASSIGNSTAKING, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_Sminer_RegnstkAssignStaking, err) + c.SetRpcState(false) + return blockhash, err } if !ok { keyStr, _ := utils.NumsToByteStr(key, map[string]bool{}) - return txhash, fmt.Errorf( + return blockhash, fmt.Errorf( "chain rpc.state.GetStorageLatest[%v]: %v", keyStr, - pattern.ERR_RPC_EMPTY_VALUE, + ERR_RPC_EMPTY_VALUE, ) } @@ -1399,9 +1547,8 @@ func (c *ChainClient) RegisterSminerAssignStaking(beneficiaryAcc string, peerId // Sign the transaction err = ext.Sign(c.keyring, o) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_REGISTERASSIGNSTAKING, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_Sminer_RegnstkAssignStaking, err) + return blockhash, err } <-c.txTicker.C @@ -1409,22 +1556,23 @@ func (c *ChainClient) RegisterSminerAssignStaking(beneficiaryAcc string, peerId // Do the transfer and track the actual status sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) err = ext.Sign(c.keyring, o) if err != nil { - return txhash, errors.Wrap(err, "[Sign]") + return blockhash, errors.Wrap(err, "[Sign]") } + <-c.txTicker.C sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_REGISTERASSIGNSTAKING, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Sminer_RegnstkAssignStaking, err) + c.SetRpcState(false) + return blockhash, err } } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_REGISTERASSIGNSTAKING, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Sminer_RegnstkAssignStaking, err) + c.SetRpcState(false) + return blockhash, err } } defer sub.Unsubscribe() @@ -1436,19 +1584,26 @@ func (c *ChainClient) RegisterSminerAssignStaking(beneficiaryAcc string, peerId select { case status := <-sub.Chan(): if status.IsInBlock { - txhash = status.AsInBlock.Hex() + blockhash = status.AsInBlock.Hex() _, err = c.RetrieveEvent_Sminer_Registered(status.AsInBlock) - return txhash, err + return blockhash, err } case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") + return blockhash, errors.Wrap(err, "[sub]") case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT + return blockhash, ERR_RPC_TIMEOUT } } } -func (c *ChainClient) RegisterSminerPOISKey(poisKey pattern.PoISKeyInfo, teeSignWithAcc, teeSign types.Bytes, teePuk pattern.WorkerPublicKey) (string, error) { +// UpdateBeneficiary updates earnings account for storage miner +// +// - earnings: earnings account +// +// Return: +// - string: block hash +// - error: error message +func (c *ChainClient) UpdateBeneficiary(earnings string) (string, error) { c.lock.Lock() defer func() { c.lock.Unlock() @@ -1458,46 +1613,46 @@ func (c *ChainClient) RegisterSminerPOISKey(poisKey pattern.PoISKeyInfo, teeSign }() var ( - err error - txhash string - call types.Call + blockhash string accountInfo types.AccountInfo ) - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION } - call, err = types.NewCall(c.metadata, pattern.TX_SMINER_REGISTERPOISKEY, poisKey, teeSignWithAcc, teeSign, teePuk) + puk, err := utils.ParsingPublickey(earnings) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_REGISTERPOISKEY, err) - c.SetChainState(false) - return txhash, err + return "", err + } + + acc, err := types.NewAccountID(puk) + if err != nil { + return blockhash, errors.Wrap(err, "[NewAccountID]") + } + + call, err := types.NewCall(c.metadata, TX_Sminer_UpdateBeneficiary, *acc) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_Sminer_UpdateBeneficiary, err) + return blockhash, err } ext := types.NewExtrinsic(call) - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_REGISTERPOISKEY, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_Sminer_UpdateBeneficiary, err) + return blockhash, err } ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_REGISTERPOISKEY, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_Sminer_UpdateBeneficiary, err) + c.SetRpcState(false) + return blockhash, err } - if !ok { - keyStr, _ := utils.NumsToByteStr(key, map[string]bool{}) - return txhash, fmt.Errorf( - "chain rpc.state.GetStorageLatest[%v]: %v", - keyStr, - pattern.ERR_RPC_EMPTY_VALUE, - ) + return blockhash, ERR_RPC_EMPTY_VALUE } o := types.SignatureOptions{ @@ -1513,9 +1668,8 @@ func (c *ChainClient) RegisterSminerPOISKey(poisKey pattern.PoISKeyInfo, teeSign // Sign the transaction err = ext.Sign(c.keyring, o) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_REGISTERPOISKEY, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_Sminer_UpdateBeneficiary, err) + return blockhash, err } <-c.txTicker.C @@ -1523,22 +1677,23 @@ func (c *ChainClient) RegisterSminerPOISKey(poisKey pattern.PoISKeyInfo, teeSign // Do the transfer and track the actual status sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) err = ext.Sign(c.keyring, o) if err != nil { - return txhash, errors.Wrap(err, "[Sign]") + return blockhash, errors.Wrap(err, "[Sign]") } + <-c.txTicker.C sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_REGISTERPOISKEY, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Sminer_UpdateBeneficiary, err) + c.SetRpcState(false) + return blockhash, err } } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_REGISTERPOISKEY, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Sminer_UpdateBeneficiary, err) + c.SetRpcState(false) + return blockhash, err } } defer sub.Unsubscribe() @@ -1550,19 +1705,26 @@ func (c *ChainClient) RegisterSminerPOISKey(poisKey pattern.PoISKeyInfo, teeSign select { case status := <-sub.Chan(): if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_Sminer_RegisterPoisKey(status.AsInBlock) - return txhash, err + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_Sminer_UpdataBeneficiary(status.AsInBlock) + return blockhash, err } case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") + return blockhash, errors.Wrap(err, "[sub]") case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT + return blockhash, ERR_RPC_TIMEOUT } } } -func (c *ChainClient) IncreaseDeclarationSpace(tibCount uint32) (string, error) { +// UpdateSminerPeerId update peer id for storage miner +// +// - peerid: peer id +// +// Return: +// - string: block hash +// - error: error message +func (c *ChainClient) UpdateSminerPeerId(peerid PeerId) (string, error) { c.lock.Lock() defer func() { c.lock.Unlock() @@ -1572,38 +1734,36 @@ func (c *ChainClient) IncreaseDeclarationSpace(tibCount uint32) (string, error) }() var ( - txhash string + blockhash string accountInfo types.AccountInfo ) - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION } - call, err := types.NewCall(c.metadata, pattern.TX_SMINER_INCREASEDECSPACE, types.NewU32(tibCount)) + call, err := types.NewCall(c.metadata, TX_Sminer_UpdatePeerId, peerid) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_INCREASEDECSPACE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_Sminer_UpdatePeerId, err) + return blockhash, err } ext := types.NewExtrinsic(call) - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_INCREASEDECSPACE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_Sminer_UpdatePeerId, err) + return blockhash, err } ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_INCREASEDECSPACE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_Sminer_UpdatePeerId, err) + c.SetRpcState(false) + return blockhash, err } if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE + return blockhash, ERR_RPC_EMPTY_VALUE } o := types.SignatureOptions{ @@ -1619,9 +1779,8 @@ func (c *ChainClient) IncreaseDeclarationSpace(tibCount uint32) (string, error) // Sign the transaction err = ext.Sign(c.keyring, o) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_INCREASEDECSPACE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_Sminer_UpdatePeerId, err) + return blockhash, err } <-c.txTicker.C @@ -1629,41 +1788,40 @@ func (c *ChainClient) IncreaseDeclarationSpace(tibCount uint32) (string, error) // Do the transfer and track the actual status sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) err = ext.Sign(c.keyring, o) if err != nil { - return txhash, errors.Wrap(err, "[Sign]") + return blockhash, errors.Wrap(err, "[Sign]") } + <-c.txTicker.C sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_INCREASEDECSPACE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Sminer_UpdatePeerId, err) + c.SetRpcState(false) + return blockhash, err } } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_SMINER_INCREASEDECSPACE, err) - c.SetChainState(false) - return txhash, err + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_Sminer_UpdatePeerId, err) + c.SetRpcState(false) + return blockhash, err } } defer sub.Unsubscribe() - timeout := time.NewTimer(c.packingTime) defer timeout.Stop() - for { select { case status := <-sub.Chan(): if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_Sminer_IncreaseDeclarationSpace(status.AsInBlock) - return txhash, err + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_Sminer_UpdataIp(status.AsInBlock) + return blockhash, err } case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") + return blockhash, errors.Wrap(err, "[sub]") case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT + return blockhash, ERR_RPC_TIMEOUT } } } diff --git a/chain/staking.go b/chain/staking.go index 03906c1..53abc44 100755 --- a/chain/staking.go +++ b/chain/staking.go @@ -11,14 +11,19 @@ import ( "fmt" "log" - "github.com/CESSProject/cess-go-sdk/core/pattern" "github.com/CESSProject/cess-go-sdk/utils" "github.com/centrifuge/go-substrate-rpc-client/v4/types" "github.com/centrifuge/go-substrate-rpc-client/v4/types/codec" "github.com/pkg/errors" ) -func (c *ChainClient) QueryAllValidatorCount(block int) (uint32, error) { +// QueryCounterForValidators query validator number (waiting nodes included) +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - uint32: validator number +// - error: error message +func (c *ChainClient) QueryCounterForValidators(block int) (uint32, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) @@ -27,11 +32,11 @@ func (c *ChainClient) QueryAllValidatorCount(block int) (uint32, error) { var data types.U32 - if !c.GetChainState() { - return uint32(data), pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return uint32(data), ERR_RPC_CONNECTION } - key, err := types.CreateStorageKey(c.metadata, pattern.STAKING, pattern.COUNTERFORVALIDATORS) + key, err := types.CreateStorageKey(c.metadata, Staking, CounterForValidators) if err != nil { return uint32(data), errors.Wrap(err, "[CreateStorageKey]") } @@ -39,31 +44,38 @@ func (c *ChainClient) QueryAllValidatorCount(block int) (uint32, error) { if block < 0 { ok, err := c.api.RPC.State.GetStorageLatest(key, &data) if err != nil { + c.SetRpcState(false) return uint32(data), errors.Wrap(err, "[GetStorageLatest]") } if !ok { - return uint32(data), pattern.ERR_RPC_EMPTY_VALUE + return uint32(data), ERR_RPC_EMPTY_VALUE } return uint32(data), nil } blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), pattern.STAKING, pattern.COUNTERFORVALIDATORS, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), Staking, CounterForValidators, err) return uint32(data), err } ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) if err != nil { + c.SetRpcState(false) return uint32(data), errors.Wrap(err, "[GetStorage]") } if !ok { - return uint32(data), pattern.ERR_RPC_EMPTY_VALUE + return uint32(data), ERR_RPC_EMPTY_VALUE } return uint32(data), nil } +// QueryValidatorsCount query validator number (waiting nodes not included) +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - uint32: validator number +// - error: error message func (c *ChainClient) QueryValidatorsCount(block int) (uint32, error) { defer func() { if err := recover(); err != nil { @@ -73,11 +85,11 @@ func (c *ChainClient) QueryValidatorsCount(block int) (uint32, error) { var data types.U32 - if !c.GetChainState() { - return uint32(data), pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return uint32(data), ERR_RPC_CONNECTION } - key, err := types.CreateStorageKey(c.metadata, pattern.STAKING, pattern.ValidatorCount) + key, err := types.CreateStorageKey(c.metadata, Staking, ValidatorCount) if err != nil { return uint32(data), errors.Wrap(err, "[CreateStorageKey]") } @@ -85,31 +97,38 @@ func (c *ChainClient) QueryValidatorsCount(block int) (uint32, error) { if block < 0 { ok, err := c.api.RPC.State.GetStorageLatest(key, &data) if err != nil { + c.SetRpcState(false) return uint32(data), errors.Wrap(err, "[GetStorageLatest]") } if !ok { - return uint32(data), pattern.ERR_RPC_EMPTY_VALUE + return uint32(data), ERR_RPC_EMPTY_VALUE } return uint32(data), nil } blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), pattern.STAKING, pattern.ValidatorCount, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), Staking, ValidatorCount, err) return uint32(data), err } ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) if err != nil { + c.SetRpcState(false) return uint32(data), errors.Wrap(err, "[GetStorage]") } if !ok { - return uint32(data), pattern.ERR_RPC_EMPTY_VALUE + return uint32(data), ERR_RPC_EMPTY_VALUE } return uint32(data), nil } +// QueryNominatorCount query nominator number +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - uint32: nominator number +// - error: error message func (c *ChainClient) QueryNominatorCount(block int) (uint32, error) { defer func() { if err := recover(); err != nil { @@ -119,11 +138,11 @@ func (c *ChainClient) QueryNominatorCount(block int) (uint32, error) { var data types.U32 - if !c.GetChainState() { - return uint32(data), pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return uint32(data), ERR_RPC_CONNECTION } - key, err := types.CreateStorageKey(c.metadata, pattern.STAKING, pattern.CounterForNominators) + key, err := types.CreateStorageKey(c.metadata, Staking, CounterForNominators) if err != nil { return uint32(data), errors.Wrap(err, "[CreateStorageKey]") } @@ -131,31 +150,39 @@ func (c *ChainClient) QueryNominatorCount(block int) (uint32, error) { if block < 0 { ok, err := c.api.RPC.State.GetStorageLatest(key, &data) if err != nil { + c.SetRpcState(false) return uint32(data), errors.Wrap(err, "[GetStorageLatest]") } if !ok { - return uint32(data), pattern.ERR_RPC_EMPTY_VALUE + return uint32(data), ERR_RPC_EMPTY_VALUE } return uint32(data), nil } blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), pattern.STAKING, pattern.CounterForNominators, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), Staking, CounterForNominators, err) return uint32(data), err } ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) if err != nil { + c.SetRpcState(false) return uint32(data), errors.Wrap(err, "[GetStorage]") } if !ok { - return uint32(data), pattern.ERR_RPC_EMPTY_VALUE + return uint32(data), ERR_RPC_EMPTY_VALUE } return uint32(data), nil } +// QueryErasTotalStake query the total number of staking for each era +// - era: era id +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - string: the total number of staking +// - error: error message func (c *ChainClient) QueryErasTotalStake(era uint32, block int) (string, error) { defer func() { if err := recover(); err != nil { @@ -165,8 +192,8 @@ func (c *ChainClient) QueryErasTotalStake(era uint32, block int) (string, error) var data types.U128 - if !c.GetChainState() { - return "", pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return "", ERR_RPC_CONNECTION } param, err := codec.Encode(era) @@ -174,43 +201,47 @@ func (c *ChainClient) QueryErasTotalStake(era uint32, block int) (string, error) return "", err } - key, err := types.CreateStorageKey(c.metadata, pattern.STAKING, pattern.ErasTotalStake, param) + key, err := types.CreateStorageKey(c.metadata, Staking, ErasTotalStake, param) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.STAKING, pattern.ErasTotalStake, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), Staking, ErasTotalStake, err) return "", err } if block < 0 { ok, err := c.api.RPC.State.GetStorageLatest(key, &data) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.STAKING, pattern.ErasTotalStake, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Staking, ErasTotalStake, err) + c.SetRpcState(false) return "", err } if !ok { - return "", pattern.ERR_RPC_EMPTY_VALUE + return "", ERR_RPC_EMPTY_VALUE } return data.String(), nil } blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), pattern.STAKING, pattern.ErasTotalStake, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), Staking, ErasTotalStake, err) return data.String(), err } ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), pattern.STAKING, pattern.ErasTotalStake, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), Staking, ErasTotalStake, err) + c.SetRpcState(false) return "", err } if !ok { - return "", pattern.ERR_RPC_EMPTY_VALUE + return "", ERR_RPC_EMPTY_VALUE } return data.String(), nil } +// QueryCurrentEra query the current era id +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - uint32: era id +// - error: error message func (c *ChainClient) QueryCurrentEra(block int) (uint32, error) { defer func() { if err := recover(); err != nil { @@ -220,140 +251,62 @@ func (c *ChainClient) QueryCurrentEra(block int) (uint32, error) { var data types.U32 - if !c.GetChainState() { - return 0, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return 0, ERR_RPC_CONNECTION } - key, err := types.CreateStorageKey(c.metadata, pattern.STAKING, pattern.CurrentEra) + key, err := types.CreateStorageKey(c.metadata, Staking, CurrentEra) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.STAKING, pattern.CurrentEra, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), Staking, CurrentEra, err) return 0, err } if block < 0 { ok, err := c.api.RPC.State.GetStorageLatest(key, &data) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.STAKING, pattern.CurrentEra, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Staking, CurrentEra, err) + c.SetRpcState(false) return 0, err } if !ok { - return 0, pattern.ERR_RPC_EMPTY_VALUE + return 0, ERR_RPC_EMPTY_VALUE } return uint32(data), nil } blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), pattern.STAKING, pattern.CurrentEra, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), Staking, CurrentEra, err) return uint32(data), err } ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.STAKING, pattern.CurrentEra, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Staking, CurrentEra, err) + c.SetRpcState(false) return 0, err } if !ok { - return 0, pattern.ERR_RPC_EMPTY_VALUE + return 0, ERR_RPC_EMPTY_VALUE } return uint32(data), nil } -// func (c *ChainClient) QueryeErasStakers(era uint32) ([]pattern.StakingExposure, error) { -// defer func() { -// if err := recover(); err != nil { -// log.Println(utils.RecoverError(err)) -// } -// }() -// var result []pattern.StakingExposure - -// if !c.GetChainState() { -// return result, pattern.ERR_RPC_CONNECTION -// } - -// // key := createPrefixedKey(pattern.STAKING, pattern.ErasStakers) -// param1, err := codec.Encode(types.NewU32(era)) -// if err != nil { -// return result, err -// } - -// var p2 types.OptionAccountID - -// pk, err := utils.ParsingPublickey("cXjGzUnWJcNXBzKBEJKvs3ZBJ5f1aEEca38abpuNxvwGNZ5Gy") -// if err != nil { -// return result, err -// } - -// accid, err := types.NewAccountID(pk) -// if err != nil { -// return result, err -// } -// p2.SetSome(*accid) -// b := bytes.NewBuffer(make([]byte, 0)) - -// err = p2.Encode(*scale.NewEncoder(b)) -// if err != nil { -// return result, err -// } -// param2, err := codec.Encode(p2) -// if err != nil { -// return result, err -// } -// _ = param2 -// //fmt.Println(p2.HasValue()) -// key, err := types.CreateStorageKey(c.metadata, pattern.STAKING, "ErasStakersClipped", param1, param2) -// if err != nil { -// return result, err -// } -// _ = key -// kkey := createPrefixedKey(pattern.STAKING, pattern.ErasStakers) -// //kkey = append(kkey, []byte(" ")...) -// //kkey = append(kkey, param1...) //xxhash.New128(param1).Sum(nil)...) - -// entryMeta, err := c.GetMetadata().FindStorageEntryMetadata(pattern.STAKING, pattern.ErasStakers) -// if err != nil { -// return nil, err -// } -// hashers, err := entryMeta.Hashers() -// if err != nil { -// return nil, err -// } -// _, err = hashers[0].Write(param1) -// if err != nil { -// return nil, err -// } -// kkey = append(kkey, hashers[0].Sum(nil)...) -// _, err = hashers[1].Write(param2) -// if err != nil { -// return nil, err -// } -// kkey = append(kkey, hashers[1].Sum(nil)...) -// var result1 pattern.StakingExposure -// ok, err := c.api.RPC.State.GetStorageLatest(kkey, &result1) -// if err != nil { -// err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.STAKING, pattern.ErasStakers, err) -// c.SetChainState(false) -// return result, err -// } -// fmt.Println(result1) -// if !ok { -// return result, pattern.ERR_RPC_EMPTY_VALUE -// } -// return result, nil -// } - -func (c *ChainClient) QueryStakingEraRewardPoints(era uint32) (pattern.StakingEraRewardPoints, error) { +// QueryErasRewardPoints query the rewards of consensus nodes in each era +// - era: era id +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - StakingEraRewardPoints: the rewards of consensus nodes +// - error: error message +func (c *ChainClient) QueryErasRewardPoints(era uint32, block int32) (StakingEraRewardPoints, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - var result pattern.StakingEraRewardPoints + var result StakingEraRewardPoints - if !c.GetChainState() { - return result, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return result, ERR_RPC_CONNECTION } param1, err := codec.Encode(types.NewU32(era)) @@ -361,55 +314,89 @@ func (c *ChainClient) QueryStakingEraRewardPoints(era uint32) (pattern.StakingEr return result, err } - key, err := types.CreateStorageKey(c.metadata, pattern.STAKING, pattern.ErasRewardPoints, param1) + key, err := types.CreateStorageKey(c.metadata, Staking, ErasRewardPoints, param1) if err != nil { return result, err } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &result) + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &result) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Staking, ErasRewardPoints, err) + c.SetRpcState(false) + return result, err + } + if !ok { + return result, ERR_RPC_EMPTY_VALUE + } + return result, nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.STAKING, pattern.ErasRewardPoints, err) - c.SetChainState(false) + return result, err + } + ok, err := c.api.RPC.State.GetStorage(key, &result, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), Staking, ErasRewardPoints, err) + c.SetRpcState(false) return result, err } if !ok { - return result, pattern.ERR_RPC_EMPTY_VALUE + return result, ERR_RPC_EMPTY_VALUE } return result, nil } -func (c *ChainClient) QueryNominatorsLatest() ([]pattern.StakingNominations, error) { +// QueryAllNominators query all nominators info +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - []StakingNominations: all nominators info +// - error: error message +func (c *ChainClient) QueryAllNominators(block int32) ([]StakingNominations, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - //var keyList []string - var result []pattern.StakingNominations - if !c.GetChainState() { - return nil, pattern.ERR_RPC_CONNECTION + var result []StakingNominations + + if !c.GetRpcState() { + return nil, ERR_RPC_CONNECTION } - key := createPrefixedKey(pattern.STAKING, pattern.Nominators) + key := CreatePrefixedKey(Staking, Nominators) keys, err := c.api.RPC.State.GetKeysLatest(key) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetKeysLatest: %v", c.GetCurrentRpcAddr(), pattern.STAKING, pattern.Nominators, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetKeysLatest: %v", c.GetCurrentRpcAddr(), Staking, Nominators, err) + c.SetRpcState(false) return nil, err } - - set, err := c.api.RPC.State.QueryStorageAtLatest(keys) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAtLatest: %v", c.GetCurrentRpcAddr(), pattern.STAKING, pattern.Nominators, err) - c.SetChainState(false) - return nil, err + var set []types.StorageChangeSet + if block < 0 { + set, err = c.api.RPC.State.QueryStorageAtLatest(keys) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAtLatest: %v", c.GetCurrentRpcAddr(), Staking, Nominators, err) + c.SetRpcState(false) + return nil, err + } + } else { + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + return nil, err + } + set, err = c.api.RPC.State.QueryStorageAt(keys, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAt: %v", c.GetCurrentRpcAddr(), Staking, Nominators, err) + c.SetRpcState(false) + return nil, err + } } for _, elem := range set { for _, change := range elem.Changes { if change.HasStorageData { - var data pattern.StakingNominations + var data StakingNominations if err := codec.Decode(change.StorageData, &data); err != nil { continue } @@ -421,62 +408,54 @@ func (c *ChainClient) QueryNominatorsLatest() ([]pattern.StakingNominations, err return result, nil } -func (c *ChainClient) QueryBondedList(block int32) ([]types.AccountID, error) { +// QueryAllBonded query all consensus and nominators accounts +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - []types.AccountID: all consensus and nominators accounts +// - error: error message +func (c *ChainClient) QueryAllBonded(block int32) ([]types.AccountID, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - //var keyList []string + var result []types.AccountID - if !c.GetChainState() { - return nil, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return nil, ERR_RPC_CONNECTION } - key := createPrefixedKey(pattern.STAKING, pattern.Bonded) + key := CreatePrefixedKey(Staking, Bonded) keys, err := c.api.RPC.State.GetKeysLatest(key) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetKeysLatest: %v", c.GetCurrentRpcAddr(), pattern.STAKING, pattern.Bonded, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetKeysLatest: %v", c.GetCurrentRpcAddr(), Staking, Bonded, err) + c.SetRpcState(false) return nil, err } + var set []types.StorageChangeSet if block < 0 { - set, err := c.api.RPC.State.QueryStorageAtLatest(keys) + set, err = c.api.RPC.State.QueryStorageAtLatest(keys) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAtLatest: %v", c.GetCurrentRpcAddr(), pattern.STAKING, pattern.Bonded, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAtLatest: %v", c.GetCurrentRpcAddr(), Staking, Bonded, err) + c.SetRpcState(false) return nil, err } - - for _, elem := range set { - for _, change := range elem.Changes { - if change.HasStorageData { - var data types.AccountID - if err := codec.Decode(change.StorageData, &data); err != nil { - continue - } - result = append(result, data) - } - - } + } else { + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), Staking, Bonded, err) + return result, err } - return result, nil - } - blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), pattern.STAKING, pattern.Bonded, err) - c.SetChainState(false) - return result, err - } - - set, err := c.api.RPC.State.QueryStorageAt(keys, blockhash) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAtLatest: %v", c.GetCurrentRpcAddr(), pattern.STAKING, pattern.Bonded, err) - c.SetChainState(false) - return nil, err + set, err = c.api.RPC.State.QueryStorageAt(keys, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAt: %v", c.GetCurrentRpcAddr(), Staking, Bonded, err) + c.SetRpcState(false) + return nil, err + } } for _, elem := range set { @@ -494,28 +473,27 @@ func (c *ChainClient) QueryBondedList(block int32) ([]types.AccountID, error) { return result, nil } -func (c *ChainClient) QueryValidatorCommission(account string, block int) (uint8, error) { +// QueryValidatorCommission query validator commission +// - accountID: validator account +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - uint8: validator commission +// - error: error message +func (c *ChainClient) QueryValidatorCommission(accountID []byte, block int) (uint8, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - //var keyList []string - var result pattern.StakingValidatorPrefs - if !c.GetChainState() { - return 0, pattern.ERR_RPC_CONNECTION - } + var result StakingValidatorPrefs - pk, _ := utils.ParsingPublickey(account) - acc, _ := types.NewAccountID(pk) - // key := createPrefixedKey(pattern.STAKING, pattern.ErasStakers) - param1, err := codec.Encode(*acc) - if err != nil { - return 0, err + if !c.GetRpcState() { + return 0, ERR_RPC_CONNECTION } - key, err := types.CreateStorageKey(c.metadata, pattern.STAKING, pattern.Validators, param1) + key, err := types.CreateStorageKey(c.metadata, Staking, Validators, accountID) if err != nil { return 0, err } @@ -526,14 +504,13 @@ func (c *ChainClient) QueryValidatorCommission(account string, block int) (uint8 return 0, nil } if !ok { - return 0, pattern.ERR_RPC_EMPTY_VALUE + return 0, ERR_RPC_EMPTY_VALUE } return uint8(uint32(result.Commission-2) / uint32(40000000)), nil } blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), pattern.STAKING, pattern.Validators, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), Staking, Validators, err) return 0, err } ok, err := c.api.RPC.State.GetStorage(key, &result, blockhash) @@ -541,22 +518,29 @@ func (c *ChainClient) QueryValidatorCommission(account string, block int) (uint8 return 0, nil } if !ok { - return 0, pattern.ERR_RPC_EMPTY_VALUE + return 0, ERR_RPC_EMPTY_VALUE } return uint8(uint32(result.Commission-2) / uint32(40000000)), nil } -func (c *ChainClient) QueryEraValidatorReward(era uint32) (string, error) { +// QueryEraValidatorReward query the total rewards for each era +// - era: era id +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - string: total rewards +// - error: error message +func (c *ChainClient) QueryEraValidatorReward(era uint32, block int) (string, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - //var keyList []string + var result types.U128 - if !c.GetChainState() { - return "", pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return "", ERR_RPC_CONNECTION } param, err := codec.Encode(types.NewU32(era)) @@ -564,17 +548,114 @@ func (c *ChainClient) QueryEraValidatorReward(era uint32) (string, error) { return "", err } - key, err := types.CreateStorageKey(c.metadata, pattern.STAKING, pattern.ErasValidatorReward, param) + key, err := types.CreateStorageKey(c.metadata, Staking, ErasValidatorReward, param) if err != nil { return "", err } - ok, err := c.api.RPC.State.GetStorageLatest(key, &result) + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &result) + if err != nil { + return "", nil + } + if !ok { + return "", ERR_RPC_EMPTY_VALUE + } + return result.String(), nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + return "", err + } + ok, err := c.api.RPC.State.GetStorage(key, &result, blockhash) if err != nil { return "", nil } if !ok { - return "", pattern.ERR_RPC_EMPTY_VALUE + return "", ERR_RPC_EMPTY_VALUE } return result.String(), nil } + +// func (c *ChainClient) QueryeErasStakers(era uint32) ([]StakingExposure, error) { +// defer func() { +// if err := recover(); err != nil { +// log.Println(utils.RecoverError(err)) +// } +// }() +// var result []StakingExposure + +// if !c.GetRpcState() { +// return result, ERR_RPC_CONNECTION +// } + +// // key := CreatePrefixedKey(Staking, ErasStakers) +// param1, err := codec.Encode(types.NewU32(era)) +// if err != nil { +// return result, err +// } + +// var p2 types.OptionAccountID + +// pk, err := utils.ParsingPublickey("cXjGzUnWJcNXBzKBEJKvs3ZBJ5f1aEEca38abpuNxvwGNZ5Gy") +// if err != nil { +// return result, err +// } + +// accid, err := types.NewAccountID(pk) +// if err != nil { +// return result, err +// } +// p2.SetSome(*accid) +// b := bytes.NewBuffer(make([]byte, 0)) + +// err = p2.Encode(*scale.NewEncoder(b)) +// if err != nil { +// return result, err +// } +// param2, err := codec.Encode(p2) +// if err != nil { +// return result, err +// } +// _ = param2 +// //fmt.Println(p2.HasValue()) +// key, err := types.CreateStorageKey(c.metadata, Staking, "ErasStakersClipped", param1, param2) +// if err != nil { +// return result, err +// } +// _ = key +// kkey := CreatePrefixedKey(Staking, ErasStakers) +// //kkey = append(kkey, []byte(" ")...) +// //kkey = append(kkey, param1...) //xxhash.New128(param1).Sum(nil)...) + +// entryMeta, err := c.GetMetadata().FindStorageEntryMetadata(Staking, ErasStakers) +// if err != nil { +// return nil, err +// } +// hashers, err := entryMeta.Hashers() +// if err != nil { +// return nil, err +// } +// _, err = hashers[0].Write(param1) +// if err != nil { +// return nil, err +// } +// kkey = append(kkey, hashers[0].Sum(nil)...) +// _, err = hashers[1].Write(param2) +// if err != nil { +// return nil, err +// } +// kkey = append(kkey, hashers[1].Sum(nil)...) +// var result1 StakingExposure +// ok, err := c.api.RPC.State.GetStorageLatest(kkey, &result1) +// if err != nil { +// err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), Staking, ErasStakers, err) +// c.SetRpcState(false) +// return result, err +// } +// fmt.Println(result1) +// if !ok { +// return result, ERR_RPC_EMPTY_VALUE +// } +// return result, nil +// } diff --git a/chain/storage.go b/chain/storage.go deleted file mode 100755 index ab157e6..0000000 --- a/chain/storage.go +++ /dev/null @@ -1,538 +0,0 @@ -/* - Copyright (C) CESS. All rights reserved. - Copyright (C) Cumulus Encrypted Storage System. All rights reserved. - - SPDX-License-Identifier: Apache-2.0 -*/ - -package chain - -import ( - "fmt" - "log" - "strings" - "time" - - "github.com/CESSProject/cess-go-sdk/core/pattern" - "github.com/CESSProject/cess-go-sdk/utils" - "github.com/centrifuge/go-substrate-rpc-client/v4/types" - "github.com/centrifuge/go-substrate-rpc-client/v4/types/codec" - "github.com/pkg/errors" -) - -func (c *ChainClient) QuerySpacePricePerGib() (string, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var data types.U128 - - if !c.GetChainState() { - return "", pattern.ERR_RPC_CONNECTION - } - - key, err := types.CreateStorageKey(c.metadata, pattern.STORAGEHANDLER, pattern.UNITPRICE) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.STORAGEHANDLER, pattern.UNITPRICE, err) - c.SetChainState(false) - return "", err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.STORAGEHANDLER, pattern.UNITPRICE, err) - c.SetChainState(false) - return "", err - } - if !ok { - return "", pattern.ERR_RPC_EMPTY_VALUE - } - - return fmt.Sprintf("%v", data), nil -} - -func (c *ChainClient) QueryUserSpaceInfo(puk []byte) (pattern.UserSpaceInfo, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var data pattern.UserSpaceInfo - - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION - } - - acc, err := types.NewAccountID(puk) - if err != nil { - return data, errors.Wrap(err, "[NewAccountID]") - } - - owner, err := codec.Encode(*acc) - if err != nil { - return data, errors.Wrap(err, "[EncodeToBytes]") - } - - key, err := types.CreateStorageKey(c.metadata, pattern.STORAGEHANDLER, pattern.USERSPACEINFO, owner) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.STORAGEHANDLER, pattern.USERSPACEINFO, err) - c.SetChainState(false) - return data, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.STORAGEHANDLER, pattern.USERSPACEINFO, err) - c.SetChainState(false) - return data, err - } - if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE - } - return data, nil -} - -func (c *ChainClient) QueryUserSpaceSt(puk []byte) (pattern.UserSpaceSt, error) { - var userSpaceSt pattern.UserSpaceSt - spaceinfo, err := c.QueryUserSpaceInfo(puk) - if err != nil { - return userSpaceSt, err - } - userSpaceSt.Start = uint32(spaceinfo.Start) - userSpaceSt.Deadline = uint32(spaceinfo.Deadline) - userSpaceSt.TotalSpace = spaceinfo.TotalSpace.String() - userSpaceSt.UsedSpace = spaceinfo.UsedSpace.String() - userSpaceSt.RemainingSpace = spaceinfo.RemainingSpace.String() - userSpaceSt.LockedSpace = spaceinfo.LockedSpace.String() - userSpaceSt.State = string(spaceinfo.State) - return userSpaceSt, nil -} - -func (c *ChainClient) QueryTotalIdleSpace() (uint64, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var data types.U128 - - if !c.GetChainState() { - return 0, pattern.ERR_RPC_CONNECTION - } - - key, err := types.CreateStorageKey(c.metadata, pattern.STORAGEHANDLER, pattern.TOTALIDLESPACE) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.STORAGEHANDLER, pattern.TOTALIDLESPACE, err) - c.SetChainState(false) - return 0, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.STORAGEHANDLER, pattern.TOTALIDLESPACE, err) - c.SetChainState(false) - return 0, err - } - if !ok { - return 0, pattern.ERR_RPC_EMPTY_VALUE - } - return data.Uint64(), nil -} - -func (c *ChainClient) QueryTotalServiceSpace() (uint64, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var data types.U128 - - if !c.GetChainState() { - return 0, pattern.ERR_RPC_CONNECTION - } - - key, err := types.CreateStorageKey(c.metadata, pattern.STORAGEHANDLER, pattern.TOTALSERVICESPACE) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.STORAGEHANDLER, pattern.TOTALSERVICESPACE, err) - c.SetChainState(false) - return 0, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.STORAGEHANDLER, pattern.TOTALSERVICESPACE, err) - c.SetChainState(false) - return 0, err - } - if !ok { - return 0, pattern.ERR_RPC_EMPTY_VALUE - } - return data.Uint64(), nil -} - -func (c *ChainClient) QueryPurchasedSpace() (uint64, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var data types.U128 - - if !c.GetChainState() { - return 0, pattern.ERR_RPC_CONNECTION - } - - key, err := types.CreateStorageKey(c.metadata, pattern.STORAGEHANDLER, pattern.PURCHASEDSPACE) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.STORAGEHANDLER, pattern.PURCHASEDSPACE, err) - c.SetChainState(false) - return 0, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.STORAGEHANDLER, pattern.PURCHASEDSPACE, err) - c.SetChainState(false) - return 0, err - } - if !ok { - return 0, pattern.ERR_RPC_EMPTY_VALUE - } - return data.Uint64(), nil -} - -func (c *ChainClient) BuySpace(count uint32) (string, error) { - c.lock.Lock() - defer func() { - c.lock.Unlock() - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var ( - txhash string - accountInfo types.AccountInfo - ) - - if count == 0 { - return "", errors.New("[BuySpace] invalid count") - } - - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION - } - - call, err := types.NewCall(c.metadata, pattern.TX_STORAGE_BUYSPACE, types.NewU32(count)) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_STORAGE_BUYSPACE, err) - c.SetChainState(false) - return txhash, err - } - - ext := types.NewExtrinsic(call) - - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_STORAGE_BUYSPACE, err) - c.SetChainState(false) - return txhash, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_STORAGE_BUYSPACE, err) - c.SetChainState(false) - return txhash, err - } - if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE - } - - o := types.SignatureOptions{ - BlockHash: c.genesisHash, - Era: types.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: c.genesisHash, - Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), - SpecVersion: c.runtimeVersion.SpecVersion, - Tip: types.NewUCompactFromUInt(0), - TransactionVersion: c.runtimeVersion.TransactionVersion, - } - - // Sign the transaction - err = ext.Sign(c.keyring, o) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_STORAGE_BUYSPACE, err) - c.SetChainState(false) - return txhash, err - } - - <-c.txTicker.C - - // Do the transfer and track the actual status - sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { - o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) - err = ext.Sign(c.keyring, o) - if err != nil { - return txhash, errors.Wrap(err, "[Sign]") - } - sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_STORAGE_BUYSPACE, err) - c.SetChainState(false) - return txhash, err - } - } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_STORAGE_BUYSPACE, err) - c.SetChainState(false) - return txhash, err - } - } - defer sub.Unsubscribe() - - timeout := time.NewTimer(c.packingTime) - defer timeout.Stop() - - for { - select { - case status := <-sub.Chan(): - if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_StorageHandler_BuySpace(status.AsInBlock) - return txhash, err - } - case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") - case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT - } - } -} - -func (c *ChainClient) ExpansionSpace(count uint32) (string, error) { - c.lock.Lock() - defer func() { - c.lock.Unlock() - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var ( - txhash string - accountInfo types.AccountInfo - ) - - if count == 0 { - return "", errors.New("[ExpansionSpace] invalid count") - } - - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION - } - - call, err := types.NewCall(c.metadata, pattern.TX_STORAGE_EXPANSIONSPACE, types.NewU32(count)) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_STORAGE_EXPANSIONSPACE, err) - c.SetChainState(false) - return txhash, err - } - - ext := types.NewExtrinsic(call) - - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_STORAGE_EXPANSIONSPACE, err) - c.SetChainState(false) - return txhash, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_STORAGE_EXPANSIONSPACE, err) - c.SetChainState(false) - return txhash, err - } - if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE - } - - o := types.SignatureOptions{ - BlockHash: c.genesisHash, - Era: types.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: c.genesisHash, - Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), - SpecVersion: c.runtimeVersion.SpecVersion, - Tip: types.NewUCompactFromUInt(0), - TransactionVersion: c.runtimeVersion.TransactionVersion, - } - - // Sign the transaction - err = ext.Sign(c.keyring, o) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_STORAGE_EXPANSIONSPACE, err) - c.SetChainState(false) - return txhash, err - } - - <-c.txTicker.C - - // Do the transfer and track the actual status - sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { - o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) - err = ext.Sign(c.keyring, o) - if err != nil { - return txhash, errors.Wrap(err, "[Sign]") - } - sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_STORAGE_EXPANSIONSPACE, err) - c.SetChainState(false) - return txhash, err - } - } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_STORAGE_EXPANSIONSPACE, err) - c.SetChainState(false) - return txhash, err - } - } - defer sub.Unsubscribe() - - timeout := time.NewTimer(c.packingTime) - defer timeout.Stop() - - for { - select { - case status := <-sub.Chan(): - if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_StorageHandler_ExpansionSpace(status.AsInBlock) - return txhash, err - } - case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") - case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT - } - } -} - -func (c *ChainClient) RenewalSpace(days uint32) (string, error) { - c.lock.Lock() - defer func() { - c.lock.Unlock() - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var ( - txhash string - accountInfo types.AccountInfo - ) - - if days == 0 { - return "", errors.New("[RenewalSpace] invalid days") - } - - if !c.GetChainState() { - return txhash, pattern.ERR_RPC_CONNECTION - } - - call, err := types.NewCall(c.metadata, pattern.TX_STORAGE_RENEWALSPACE, types.NewU32(days)) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), pattern.TX_STORAGE_RENEWALSPACE, err) - c.SetChainState(false) - return txhash, err - } - - ext := types.NewExtrinsic(call) - - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TX_STORAGE_RENEWALSPACE, err) - c.SetChainState(false) - return txhash, err - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TX_STORAGE_RENEWALSPACE, err) - c.SetChainState(false) - return txhash, err - } - if !ok { - return txhash, pattern.ERR_RPC_EMPTY_VALUE - } - - o := types.SignatureOptions{ - BlockHash: c.genesisHash, - Era: types.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: c.genesisHash, - Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), - SpecVersion: c.runtimeVersion.SpecVersion, - Tip: types.NewUCompactFromUInt(0), - TransactionVersion: c.runtimeVersion.TransactionVersion, - } - - // Sign the transaction - err = ext.Sign(c.keyring, o) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), pattern.TX_STORAGE_RENEWALSPACE, err) - c.SetChainState(false) - return txhash, err - } - - <-c.txTicker.C - - // Do the transfer and track the actual status - sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - if strings.Contains(err.Error(), pattern.ERR_RPC_PRIORITYTOOLOW) { - o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) - err = ext.Sign(c.keyring, o) - if err != nil { - return txhash, errors.Wrap(err, "[Sign]") - } - sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_STORAGE_RENEWALSPACE, err) - c.SetChainState(false) - return txhash, err - } - } else { - err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), pattern.TX_STORAGE_RENEWALSPACE, err) - c.SetChainState(false) - return txhash, err - } - } - defer sub.Unsubscribe() - - timeout := time.NewTimer(c.packingTime) - defer timeout.Stop() - - for { - select { - case status := <-sub.Chan(): - if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_StorageHandler_RenewalSpace(status.AsInBlock) - return txhash, err - } - case err = <-sub.Err(): - return txhash, errors.Wrap(err, "[sub]") - case <-timeout.C: - return txhash, pattern.ERR_RPC_TIMEOUT - } - } -} diff --git a/chain/storage_handler.go b/chain/storage_handler.go new file mode 100755 index 0000000..17044b6 --- /dev/null +++ b/chain/storage_handler.go @@ -0,0 +1,646 @@ +/* + Copyright (C) CESS. All rights reserved. + Copyright (C) Cumulus Encrypted Storage System. All rights reserved. + + SPDX-License-Identifier: Apache-2.0 +*/ + +package chain + +import ( + "fmt" + "log" + "strings" + "time" + + "github.com/CESSProject/cess-go-sdk/utils" + "github.com/centrifuge/go-substrate-rpc-client/v4/types" + "github.com/centrifuge/go-substrate-rpc-client/v4/types/codec" + "github.com/pkg/errors" +) + +// QueryUnitPrice query price per GiB space +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - string: price per GiB space +// - error: error message +func (c *ChainClient) QueryUnitPrice(block int32) (string, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var data types.U128 + + if !c.GetRpcState() { + return "", ERR_RPC_CONNECTION + } + + key, err := types.CreateStorageKey(c.metadata, StorageHandler, UnitPrice) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), StorageHandler, UnitPrice, err) + c.SetRpcState(false) + return "", err + } + + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), StorageHandler, UnitPrice, err) + c.SetRpcState(false) + return "", err + } + if !ok { + return "", ERR_RPC_EMPTY_VALUE + } + + return fmt.Sprintf("%v", data), nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + return "", err + } + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), StorageHandler, UnitPrice, err) + c.SetRpcState(false) + return "", err + } + if !ok { + return "", ERR_RPC_EMPTY_VALUE + } + + return fmt.Sprintf("%v", data), nil +} + +// QueryUserOwnedSpace to query user purchased space information +// - accountID: user account +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - UserSpaceInfo: space information +// - error: error message +func (c *ChainClient) QueryUserOwnedSpace(accountID []byte, block int32) (UserSpaceInfo, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var data UserSpaceInfo + + if !c.GetRpcState() { + return data, ERR_RPC_CONNECTION + } + + acc, err := types.NewAccountID(accountID) + if err != nil { + return data, errors.Wrap(err, "[NewAccountID]") + } + + user, err := codec.Encode(*acc) + if err != nil { + return data, errors.Wrap(err, "[EncodeToBytes]") + } + + key, err := types.CreateStorageKey(c.metadata, StorageHandler, UserOwnedSpace, user) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), StorageHandler, UserOwnedSpace, err) + return data, err + } + + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), StorageHandler, UserOwnedSpace, err) + c.SetRpcState(false) + return data, err + } + if !ok { + return data, ERR_RPC_EMPTY_VALUE + } + return data, nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + return data, err + } + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), StorageHandler, UserOwnedSpace, err) + c.SetRpcState(false) + return data, err + } + if !ok { + return data, ERR_RPC_EMPTY_VALUE + } + return data, nil +} + +// QueryTotalIdleSpace query the size of all idle space +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - uint64: the size of all idle space +// - error: error message +func (c *ChainClient) QueryTotalIdleSpace(block int32) (uint64, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var data types.U128 + + if !c.GetRpcState() { + return 0, ERR_RPC_CONNECTION + } + + key, err := types.CreateStorageKey(c.metadata, StorageHandler, TotalIdleSpace) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), StorageHandler, TotalIdleSpace, err) + c.SetRpcState(false) + return 0, err + } + + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), StorageHandler, TotalIdleSpace, err) + c.SetRpcState(false) + return 0, err + } + if !ok { + return 0, ERR_RPC_EMPTY_VALUE + } + return data.Uint64(), nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + return 0, err + } + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), StorageHandler, TotalIdleSpace, err) + c.SetRpcState(false) + return 0, err + } + if !ok { + return 0, ERR_RPC_EMPTY_VALUE + } + return data.Uint64(), nil +} + +// QueryTotalServiceSpace query the size of all service space +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - uint64: the size of all service space +// - error: error message +func (c *ChainClient) QueryTotalServiceSpace(block int32) (uint64, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var data types.U128 + + if !c.GetRpcState() { + return 0, ERR_RPC_CONNECTION + } + + key, err := types.CreateStorageKey(c.metadata, StorageHandler, TotalServiceSpace) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), StorageHandler, TotalServiceSpace, err) + return 0, err + } + + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), StorageHandler, TotalServiceSpace, err) + c.SetRpcState(false) + return 0, err + } + if !ok { + return 0, ERR_RPC_EMPTY_VALUE + } + return data.Uint64(), nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + return 0, err + } + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), StorageHandler, TotalServiceSpace, err) + c.SetRpcState(false) + return 0, err + } + if !ok { + return 0, ERR_RPC_EMPTY_VALUE + } + return data.Uint64(), nil +} + +// QueryPurchasedSpace query all purchased space size +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - uint64: all purchased space size +// - error: error message +func (c *ChainClient) QueryPurchasedSpace(block int32) (uint64, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var data types.U128 + + if !c.GetRpcState() { + return 0, ERR_RPC_CONNECTION + } + + key, err := types.CreateStorageKey(c.metadata, StorageHandler, PurchasedSpace) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), StorageHandler, PurchasedSpace, err) + return 0, err + } + + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), StorageHandler, PurchasedSpace, err) + c.SetRpcState(false) + return 0, err + } + if !ok { + return 0, ERR_RPC_EMPTY_VALUE + } + return data.Uint64(), nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + return 0, err + } + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), StorageHandler, PurchasedSpace, err) + c.SetRpcState(false) + return 0, err + } + if !ok { + return 0, ERR_RPC_EMPTY_VALUE + } + return data.Uint64(), nil +} + +// BuySpace purchase space for current account +// - count: size of space purchased in gib +// +// Return: +// - string: block hash +// - error: error message +// +// Note: +// - if you have already purchased space and you are unable to purchase it again, +// you have the option to expand your space. +func (c *ChainClient) BuySpace(count uint32) (string, error) { + c.lock.Lock() + defer func() { + c.lock.Unlock() + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var ( + blockhash string + accountInfo types.AccountInfo + ) + + if count == 0 { + return "", errors.New("[BuySpace] invalid count") + } + + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION + } + + call, err := types.NewCall(c.metadata, TX_StorageHandler_BuySpace, types.NewU32(count)) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_StorageHandler_BuySpace, err) + return blockhash, err + } + + ext := types.NewExtrinsic(call) + + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_StorageHandler_BuySpace, err) + return blockhash, err + } + + ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_StorageHandler_BuySpace, err) + c.SetRpcState(false) + return blockhash, err + } + if !ok { + return blockhash, ERR_RPC_EMPTY_VALUE + } + + o := types.SignatureOptions{ + BlockHash: c.genesisHash, + Era: types.ExtrinsicEra{IsMortalEra: false}, + GenesisHash: c.genesisHash, + Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), + SpecVersion: c.runtimeVersion.SpecVersion, + Tip: types.NewUCompactFromUInt(0), + TransactionVersion: c.runtimeVersion.TransactionVersion, + } + + // Sign the transaction + err = ext.Sign(c.keyring, o) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_StorageHandler_BuySpace, err) + return blockhash, err + } + + <-c.txTicker.C + + // Do the transfer and track the actual status + sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { + o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) + err = ext.Sign(c.keyring, o) + if err != nil { + return blockhash, errors.Wrap(err, "[Sign]") + } + <-c.txTicker.C + sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_StorageHandler_BuySpace, err) + c.SetRpcState(false) + return blockhash, err + } + } else { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_StorageHandler_BuySpace, err) + c.SetRpcState(false) + return blockhash, err + } + } + defer sub.Unsubscribe() + + timeout := time.NewTimer(c.packingTime) + defer timeout.Stop() + + for { + select { + case status := <-sub.Chan(): + if status.IsInBlock { + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_StorageHandler_BuySpace(status.AsInBlock) + return blockhash, err + } + case err = <-sub.Err(): + return blockhash, errors.Wrap(err, "[sub]") + case <-timeout.C: + return blockhash, ERR_RPC_TIMEOUT + } + } +} + +// ExpansionSpace expands the size of your space +// - count: size of space expands in gib +// +// Return: +// - string: block hash +// - error: error message +func (c *ChainClient) ExpansionSpace(count uint32) (string, error) { + c.lock.Lock() + defer func() { + c.lock.Unlock() + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var ( + blockhash string + accountInfo types.AccountInfo + ) + + if count == 0 { + return "", errors.New("[ExpansionSpace] space is 0") + } + + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION + } + + call, err := types.NewCall(c.metadata, TX_StorageHandler_ExpansionSpace, types.NewU32(count)) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_StorageHandler_ExpansionSpace, err) + return blockhash, err + } + + ext := types.NewExtrinsic(call) + + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_StorageHandler_ExpansionSpace, err) + return blockhash, err + } + + ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_StorageHandler_ExpansionSpace, err) + c.SetRpcState(false) + return blockhash, err + } + if !ok { + return blockhash, ERR_RPC_EMPTY_VALUE + } + + o := types.SignatureOptions{ + BlockHash: c.genesisHash, + Era: types.ExtrinsicEra{IsMortalEra: false}, + GenesisHash: c.genesisHash, + Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), + SpecVersion: c.runtimeVersion.SpecVersion, + Tip: types.NewUCompactFromUInt(0), + TransactionVersion: c.runtimeVersion.TransactionVersion, + } + + // Sign the transaction + err = ext.Sign(c.keyring, o) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_StorageHandler_ExpansionSpace, err) + return blockhash, err + } + + <-c.txTicker.C + + // Do the transfer and track the actual status + sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { + o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) + err = ext.Sign(c.keyring, o) + if err != nil { + return blockhash, errors.Wrap(err, "[Sign]") + } + <-c.txTicker.C + sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_StorageHandler_ExpansionSpace, err) + c.SetRpcState(false) + return blockhash, err + } + } else { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_StorageHandler_ExpansionSpace, err) + c.SetRpcState(false) + return blockhash, err + } + } + defer sub.Unsubscribe() + + timeout := time.NewTimer(c.packingTime) + defer timeout.Stop() + + for { + select { + case status := <-sub.Chan(): + if status.IsInBlock { + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_StorageHandler_ExpansionSpace(status.AsInBlock) + return blockhash, err + } + case err = <-sub.Err(): + return blockhash, errors.Wrap(err, "[sub]") + case <-timeout.C: + return blockhash, ERR_RPC_TIMEOUT + } + } +} + +// RenewalSpace renew your space +// - days: renewal time, in days +// +// Return: +// - string: block hash +// - error: error message +func (c *ChainClient) RenewalSpace(days uint32) (string, error) { + c.lock.Lock() + defer func() { + c.lock.Unlock() + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var ( + blockhash string + accountInfo types.AccountInfo + ) + + if days == 0 { + return "", errors.New("[RenewalSpace] invalid days") + } + + if !c.GetRpcState() { + return blockhash, ERR_RPC_CONNECTION + } + + call, err := types.NewCall(c.metadata, TX_StorageHandler_RenewalSpace, types.NewU32(days)) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] NewCall: %v", c.GetCurrentRpcAddr(), TX_StorageHandler_RenewalSpace, err) + return blockhash, err + } + + ext := types.NewExtrinsic(call) + + key, err := types.CreateStorageKey(c.metadata, System, Account, c.keyring.PublicKey) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TX_StorageHandler_RenewalSpace, err) + return blockhash, err + } + + ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TX_StorageHandler_RenewalSpace, err) + c.SetRpcState(false) + return blockhash, err + } + if !ok { + return blockhash, ERR_RPC_EMPTY_VALUE + } + + o := types.SignatureOptions{ + BlockHash: c.genesisHash, + Era: types.ExtrinsicEra{IsMortalEra: false}, + GenesisHash: c.genesisHash, + Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), + SpecVersion: c.runtimeVersion.SpecVersion, + Tip: types.NewUCompactFromUInt(0), + TransactionVersion: c.runtimeVersion.TransactionVersion, + } + + // Sign the transaction + err = ext.Sign(c.keyring, o) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] Sign: %v", c.GetCurrentRpcAddr(), TX_StorageHandler_RenewalSpace, err) + return blockhash, err + } + + <-c.txTicker.C + + // Do the transfer and track the actual status + sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + if strings.Contains(err.Error(), ERR_RPC_PRIORITYTOOLOW) { + o.Nonce = types.NewUCompactFromUInt(uint64(accountInfo.Nonce + 1)) + err = ext.Sign(c.keyring, o) + if err != nil { + return blockhash, errors.Wrap(err, "[Sign]") + } + <-c.txTicker.C + sub, err = c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_StorageHandler_RenewalSpace, err) + c.SetRpcState(false) + return blockhash, err + } + } else { + err = fmt.Errorf("rpc err: [%s] [tx] [%s] SubmitAndWatchExtrinsic: %v", c.GetCurrentRpcAddr(), TX_StorageHandler_RenewalSpace, err) + c.SetRpcState(false) + return blockhash, err + } + } + defer sub.Unsubscribe() + + timeout := time.NewTimer(c.packingTime) + defer timeout.Stop() + + for { + select { + case status := <-sub.Chan(): + if status.IsInBlock { + blockhash = status.AsInBlock.Hex() + _, err = c.RetrieveEvent_StorageHandler_RenewalSpace(status.AsInBlock) + return blockhash, err + } + case err = <-sub.Err(): + return blockhash, errors.Wrap(err, "[sub]") + case <-timeout.C: + return blockhash, ERR_RPC_TIMEOUT + } + } +} diff --git a/chain/system.go b/chain/system.go index 97755fc..f3a830c 100755 --- a/chain/system.go +++ b/chain/system.go @@ -8,46 +8,30 @@ package chain import ( - "fmt" "log" - "time" - "github.com/CESSProject/cess-go-sdk/core/pattern" "github.com/CESSProject/cess-go-sdk/utils" "github.com/centrifuge/go-substrate-rpc-client/v4/types" "github.com/centrifuge/go-substrate-rpc-client/v4/types/codec" "github.com/pkg/errors" ) -// QueryNodeSynchronizationSt -func (c *ChainClient) QueryNodeSynchronizationSt() (bool, error) { +// QueryBlockNumber query the block number based on the block hash +// - blockhash: hex-encoded block hash, if empty query the latest block number +// +// Return: +// - uint32: block number +// - error: error message +func (c *ChainClient) QueryBlockNumber(blockhash string) (uint32, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - if !c.GetChainState() { - return false, pattern.ERR_RPC_CONNECTION - } - h, err := c.api.RPC.System.Health() - if err != nil { - return false, err - } - return h.IsSyncing, nil -} - -// QueryBlockHeight -func (c *ChainClient) QueryBlockHeight(hash string) (uint32, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - if hash != "" { + if blockhash != "" { var h types.Hash - err := codec.DecodeFromHex(hash, &h) + err := codec.DecodeFromHex(blockhash, &h) if err != nil { return 0, err } @@ -65,17 +49,29 @@ func (c *ChainClient) QueryBlockHeight(hash string) (uint32, error) { return uint32(block.Block.Header.Number), nil } -// QueryAccountInfo -func (c *ChainClient) QueryAccountInfoByAccount(acc string) (types.AccountInfo, error) { - puk, err := utils.ParsingPublickey(acc) +// QueryAccountInfo query account info +// - account: account +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - types.AccountInfo: account info +// - error: error message +func (c *ChainClient) QueryAccountInfo(account string, block int32) (types.AccountInfo, error) { + puk, err := utils.ParsingPublickey(account) if err != nil { return types.AccountInfo{}, err } - return c.QueryAccountInfo(puk) + return c.QueryAccountInfoByAccountID(puk, block) } -// QueryAccountInfo -func (c *ChainClient) QueryAccountInfo(puk []byte) (types.AccountInfo, error) { +// QueryAccountInfoByAccountID query account info +// - accountID: account id +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - types.AccountInfo: account info +// - error: error message +func (c *ChainClient) QueryAccountInfoByAccountID(accountID []byte, block int32) (types.AccountInfo, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) @@ -83,11 +79,11 @@ func (c *ChainClient) QueryAccountInfo(puk []byte) (types.AccountInfo, error) { }() var data types.AccountInfo - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return data, ERR_RPC_CONNECTION } - acc, err := types.NewAccountID(puk) + acc, err := types.NewAccountID(accountID) if err != nil { return data, errors.Wrap(err, "[NewAccountID]") } @@ -97,320 +93,31 @@ func (c *ChainClient) QueryAccountInfo(puk []byte) (types.AccountInfo, error) { return data, errors.Wrap(err, "[EncodeToBytes]") } - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, b) + key, err := types.CreateStorageKey(c.metadata, System, Account, b) if err != nil { return data, errors.Wrap(err, "[CreateStorageKey]") } - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) - if err != nil { - return data, errors.Wrap(err, "[GetStorageLatest]") - } - if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE - } - return data, nil -} - -// QueryAllAccountInfoFromBlock -func (c *ChainClient) QueryAllAccountInfoFromBlock(block int) ([]types.AccountInfo, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - var data []types.AccountInfo - - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION - } - - key := createPrefixedKey(pattern.SYSTEM, pattern.ACCOUNT) - - if block < 0 { - keys, err := c.api.RPC.State.GetKeysLatest(key) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetKeysLatest: %v", c.GetCurrentRpcAddr(), pattern.SYSTEM, pattern.ACCOUNT, err) - c.SetChainState(false) - return nil, err - } - set, err := c.api.RPC.State.QueryStorageAtLatest(keys) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAtLatest: %v", c.GetCurrentRpcAddr(), pattern.SYSTEM, pattern.ACCOUNT, err) - c.SetChainState(false) - return nil, err - } - for _, elem := range set { - for _, change := range elem.Changes { - var val types.AccountInfo - if err := codec.Decode(change.StorageData, &val); err != nil { - fmt.Println("Decode StorageData:", err) - continue - } - var kkey types.AccountID - if err := codec.Decode(change.StorageKey, &kkey); err != nil { - fmt.Println("Decode StorageKey:", err) - continue - } - fmt.Println(utils.EncodePublicKeyAsCessAccount(kkey[:])) - data = append(data, val) - } - } - return data, nil - } - - blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), pattern.SYSTEM, pattern.ACCOUNT, err) - c.SetChainState(false) - return data, err - } - - fmt.Println(">>>>>") - keys, err := c.api.RPC.State.GetKeys(key, blockhash) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetKeys: %v", c.GetCurrentRpcAddr(), pattern.SYSTEM, pattern.ACCOUNT, err) - c.SetChainState(false) - return nil, err - } - set, err := c.api.RPC.State.QueryStorageAt(keys, blockhash) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAt: %v", c.GetCurrentRpcAddr(), pattern.SYSTEM, pattern.ACCOUNT, err) - c.SetChainState(false) - return nil, err - } - for _, elem := range set { - for _, change := range elem.Changes { - if change.HasStorageData { - var val types.AccountInfo - - var kkey types.AccountID - if err := codec.Decode(change.StorageKey, &kkey); err != nil { - fmt.Println("Decode StorageKey:", err) - continue - } - if err := codec.Decode(change.StorageData, &val); err != nil { - fmt.Println("Decode StorageData:", err) - continue - } - fmt.Println(utils.EncodePublicKeyAsCessAccount(kkey[:])) - data = append(data, val) - } - } - } - - return data, nil -} - -// QueryTotalIssuance -func (c *ChainClient) QueryTotalIssuance(block int) (string, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - var data types.U128 - - if !c.GetChainState() { - return "", pattern.ERR_RPC_CONNECTION - } - - key, err := types.CreateStorageKey(c.metadata, pattern.BALANCES, pattern.TOTALISSUANCE) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.BALANCES, pattern.TOTALISSUANCE, err) - c.SetChainState(false) - return "", err - } - if block < 0 { ok, err := c.api.RPC.State.GetStorageLatest(key, &data) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.BALANCES, pattern.TOTALISSUANCE, err) - c.SetChainState(false) - return "", err + return data, errors.Wrap(err, "[GetStorageLatest]") } if !ok { - return "", pattern.ERR_RPC_EMPTY_VALUE + return data, ERR_RPC_EMPTY_VALUE } - return data.String(), nil + return data, nil } - blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), pattern.BALANCES, pattern.TOTALISSUANCE, err) - c.SetChainState(false) - return "", err + return data, err } - ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), pattern.BALANCES, pattern.TOTALISSUANCE, err) - c.SetChainState(false) - return "", err - } - if !ok { - return "", pattern.ERR_RPC_EMPTY_VALUE - } - return data.String(), nil -} - -func (c *ChainClient) SysProperties() (pattern.SysProperties, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - var data pattern.SysProperties - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION - } - err := c.api.Client.Call(&data, pattern.RPC_SYS_Properties) - return data, err -} - -func (c *ChainClient) SysChain() (string, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - var data types.Text - if !c.GetChainState() { - return "", pattern.ERR_RPC_CONNECTION - } - err := c.api.Client.Call(&data, pattern.RPC_SYS_Chain) - return string(data), err -} - -func (c *ChainClient) SyncState() (pattern.SysSyncState, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - var data pattern.SysSyncState - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION - } - err := c.api.Client.Call(&data, pattern.RPC_SYS_SyncState) - return data, err -} - -func (c *ChainClient) ChainVersion() (string, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - var data types.Text - if !c.GetChainState() { - return "", pattern.ERR_RPC_CONNECTION - } - err := c.api.Client.Call(&data, pattern.RPC_SYS_Version) - return string(data), err -} - -func (c *ChainClient) NetListening() (bool, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - var data types.Bool - if !c.GetChainState() { - return false, pattern.ERR_RPC_CONNECTION - } - err := c.api.Client.Call(&data, pattern.RPC_NET_Listening) - return bool(data), err -} - -func (c *ChainClient) TransferToken(dest string, amount uint64) (string, string, error) { - c.lock.Lock() - defer func() { - c.lock.Unlock() - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) - } - }() - - var ( - txhash string - accountInfo types.AccountInfo - ) - - if !c.GetChainState() { - return txhash, "", pattern.ERR_RPC_CONNECTION - } - - pubkey, err := utils.ParsingPublickey(dest) - if err != nil { - return "", "", errors.Wrapf(err, "[ParsingPublickey]") - } - - address, err := types.NewMultiAddressFromAccountID(pubkey) - if err != nil { - return "", "", errors.Wrapf(err, "[NewAddressFromAccountID]") - } - - call, err := types.NewCall(c.metadata, pattern.TX_BALANCES_FORCETRANSFER, address, types.NewUCompactFromUInt(amount)) - if err != nil { - return txhash, "", errors.Wrap(err, "[NewCall]") - } - - key, err := types.CreateStorageKey(c.metadata, pattern.SYSTEM, pattern.ACCOUNT, c.keyring.PublicKey) - if err != nil { - return txhash, "", errors.Wrap(err, "[CreateStorageKey]") - } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &accountInfo) - if err != nil { - return txhash, "", errors.Wrap(err, "[GetStorageLatest]") + return data, errors.Wrap(err, "[GetStorage]") } if !ok { - return txhash, "", pattern.ERR_RPC_EMPTY_VALUE - } - - o := types.SignatureOptions{ - BlockHash: c.genesisHash, - Era: types.ExtrinsicEra{IsMortalEra: false}, - GenesisHash: c.genesisHash, - Nonce: types.NewUCompactFromUInt(uint64(accountInfo.Nonce)), - SpecVersion: c.runtimeVersion.SpecVersion, - Tip: types.NewUCompactFromUInt(0), - TransactionVersion: c.runtimeVersion.TransactionVersion, - } - - ext := types.NewExtrinsic(call) - - // Sign the transaction - err = ext.Sign(c.keyring, o) - if err != nil { - return txhash, "", errors.Wrap(err, "[Sign]") - } - - // Do the transfer and track the actual status - sub, err := c.api.RPC.Author.SubmitAndWatchExtrinsic(ext) - if err != nil { - c.SetChainState(false) - return txhash, "", errors.Wrap(err, "[SubmitAndWatchExtrinsic]") - } - defer sub.Unsubscribe() - - timeout := time.NewTimer(c.packingTime) - defer timeout.Stop() - - for { - select { - case status := <-sub.Chan(): - if status.IsInBlock { - txhash = status.AsInBlock.Hex() - _, err = c.RetrieveEvent_Balances_Transfer(status.AsInBlock) - return txhash, dest, err - } - case err = <-sub.Err(): - return txhash, "", errors.Wrap(err, "[sub]") - case <-timeout.C: - return txhash, "", pattern.ERR_RPC_TIMEOUT - } + return data, ERR_RPC_EMPTY_VALUE } + return data, nil } diff --git a/chain/tee.go b/chain/tee.go index 831cc28..7104b6f 100755 --- a/chain/tee.go +++ b/chain/tee.go @@ -11,147 +11,173 @@ import ( "fmt" "log" - "github.com/CESSProject/cess-go-sdk/core/pattern" "github.com/CESSProject/cess-go-sdk/utils" "github.com/centrifuge/go-substrate-rpc-client/v4/types" "github.com/centrifuge/go-substrate-rpc-client/v4/types/codec" "github.com/pkg/errors" ) -func (c *ChainClient) QueryTeeWorker(puk pattern.WorkerPublicKey) (pattern.TeeWorkerInfo, error) { +// QueryMasterPubKey query master public key +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - []byte: master public key +// - error: error message +func (c *ChainClient) QueryMasterPubKey(block int32) ([]byte, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - var data pattern.TeeWorkerInfo + var data MasterPublicKey - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return nil, ERR_RPC_CONNECTION } - publickey, err := codec.Encode(puk) + key, err := types.CreateStorageKey(c.metadata, TeeWorker, MasterPubkey) if err != nil { - return data, errors.Wrap(err, "[EncodeToBytes]") + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TeeWorker, MasterPubkey, err) + return nil, err } - key, err := types.CreateStorageKey(c.metadata, pattern.TEEWORKER, pattern.TEEWorkers, publickey) + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + c.SetRpcState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TeeWorker, MasterPubkey, err) + return nil, err + } + if !ok { + return nil, ERR_RPC_EMPTY_VALUE + } + return []byte(string(data[:])), nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TEEWORKER, pattern.TEEWorkers, err) - return data, errors.Wrap(err, "[CreateStorageKey]") + return nil, err } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TEEWORKER, pattern.TEEWorkers, err) - return data, errors.Wrap(err, "[GetStorageLatest]") + c.SetRpcState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), TeeWorker, MasterPubkey, err) + return nil, err } if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE + return nil, ERR_RPC_EMPTY_VALUE } - - return data, nil + return []byte(string(data[:])), nil } -func (c *ChainClient) QueryTeeInfo(puk pattern.WorkerPublicKey) (pattern.TeeInfo, error) { +// QueryWorkers query tee work info +// - puk: tee's work public key +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - WorkerInfo: tee worker info +// - error: error message +func (c *ChainClient) QueryWorkers(puk WorkerPublicKey, block int32) (WorkerInfo, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - var data pattern.TeeInfo + var data WorkerInfo - teeWorkerInfo, err := c.QueryTeeWorker(puk) - if err != nil { - return data, err - } - data.Pubkey = string(teeWorkerInfo.Pubkey[:]) - data.EcdhPubkey = string(teeWorkerInfo.EcdhPubkey[:]) - data.Version = uint32(teeWorkerInfo.Version) - data.LastUpdated = uint64(teeWorkerInfo.LastUpdated) - if teeWorkerInfo.StashAccount.HasValue() { - if ok, puk := teeWorkerInfo.StashAccount.Unwrap(); ok { - data.StashAccount, _ = utils.EncodePublicKeyAsCessAccount(puk[:]) - } + if !c.GetRpcState() { + return data, ERR_RPC_CONNECTION } - if teeWorkerInfo.AttestationProvider.HasValue() { - if ok, val := teeWorkerInfo.AttestationProvider.Unwrap(); ok { - data.AttestationProvider = uint8(val) - } + + publickey, err := codec.Encode(puk) + if err != nil { + return data, errors.Wrap(err, "[EncodeToBytes]") } - data.ConfidenceLevel = uint8(teeWorkerInfo.ConfidenceLevel) - data.Features = make([]uint32, len(teeWorkerInfo.Features)) - for i := 0; i < len(teeWorkerInfo.Features); i++ { - data.Features[i] = uint32(teeWorkerInfo.Features[i]) + + key, err := types.CreateStorageKey(c.metadata, TeeWorker, Workers, publickey) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TeeWorker, Workers, err) + return data, errors.Wrap(err, "[CreateStorageKey]") } - data.WorkerRole = uint8(teeWorkerInfo.Role) - return data, nil -} -func (c *ChainClient) QueryMasterPublicKey() ([]byte, error) { - defer func() { - if err := recover(); err != nil { - log.Println(utils.RecoverError(err)) + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + c.SetRpcState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TeeWorker, Workers, err) + return data, errors.Wrap(err, "[GetStorageLatest]") } - }() - - var data pattern.MasterPublicKey - - if !c.GetChainState() { - return nil, pattern.ERR_RPC_CONNECTION + if !ok { + return data, ERR_RPC_EMPTY_VALUE + } + return data, nil } - - key, err := types.CreateStorageKey(c.metadata, pattern.TEEWORKER, pattern.TEEMasterPubkey) + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TEEWORKER, pattern.TEEMasterPubkey, err) - return nil, errors.Wrap(err, "[CreateStorageKey]") + return data, err } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TEEWORKER, pattern.TEEMasterPubkey, err) - return nil, errors.Wrap(err, "[GetStorageLatest]") + c.SetRpcState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TeeWorker, Workers, err) + return data, errors.Wrap(err, "[GetStorageLatest]") } if !ok { - return nil, pattern.ERR_RPC_EMPTY_VALUE + return data, ERR_RPC_EMPTY_VALUE } - - return []byte(string(data[:])), nil + return data, nil } -func (c *ChainClient) QueryAllTeeWorkerMap() ([]pattern.TeeWorkerInfo, error) { +// QueryAllWorkers query all tee work info +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - []WorkerInfo: all tee worker info +// - error: error message +func (c *ChainClient) QueryAllWorkers(block int32) ([]WorkerInfo, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) } }() - var list []pattern.TeeWorkerInfo + var list []WorkerInfo - if !c.GetChainState() { - return list, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return list, ERR_RPC_CONNECTION } - key := createPrefixedKey(pattern.TEEWORKER, pattern.TEEWorkers) + key := CreatePrefixedKey(TeeWorker, Workers) keys, err := c.api.RPC.State.GetKeysLatest(key) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetKeysLatest: %v", c.GetCurrentRpcAddr(), pattern.TEEWORKER, pattern.TEEWorkers, err) - return list, errors.Wrap(err, "[GetKeysLatest]") + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetKeysLatest: %v", c.GetCurrentRpcAddr(), TeeWorker, Workers, err) + return list, err } - - set, err := c.api.RPC.State.QueryStorageAtLatest(keys) - if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAtLatest: %v", c.GetCurrentRpcAddr(), pattern.TEEWORKER, pattern.TEEWorkers, err) - return list, errors.Wrap(err, "[QueryStorageAtLatest]") + var set []types.StorageChangeSet + if block < 0 { + set, err = c.api.RPC.State.QueryStorageAtLatest(keys) + if err != nil { + c.SetRpcState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAtLatest: %v", c.GetCurrentRpcAddr(), TeeWorker, Workers, err) + return list, err + } + } else { + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + return list, err + } + set, err = c.api.RPC.State.QueryStorageAt(keys, blockhash) + if err != nil { + c.SetRpcState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] QueryStorageAt: %v", c.GetCurrentRpcAddr(), TeeWorker, Workers, err) + return list, err + } } - for _, elem := range set { for _, change := range elem.Changes { - var teeWorker pattern.TeeWorkerInfo + var teeWorker WorkerInfo if err := codec.Decode(change.StorageData, &teeWorker); err != nil { - log.Println(err) continue } list = append(list, teeWorker) @@ -160,38 +186,14 @@ func (c *ChainClient) QueryAllTeeWorkerMap() ([]pattern.TeeWorkerInfo, error) { return list, nil } -func (c *ChainClient) QueryAllTeeInfo() ([]pattern.TeeInfo, error) { - teelist, err := c.QueryAllTeeWorkerMap() - if err != nil { - return nil, err - } - var results = make([]pattern.TeeInfo, len(teelist)) - for k, v := range teelist { - results[k].Pubkey = string(v.Pubkey[:]) - results[k].EcdhPubkey = string(v.EcdhPubkey[:]) - results[k].Version = uint32(v.Version) - results[k].LastUpdated = uint64(v.LastUpdated) - if v.StashAccount.HasValue() { - if ok, puk := v.StashAccount.Unwrap(); ok { - results[k].StashAccount, _ = utils.EncodePublicKeyAsCessAccount(puk[:]) - } - } - if v.AttestationProvider.HasValue() { - if ok, val := v.AttestationProvider.Unwrap(); ok { - results[k].AttestationProvider = uint8(val) - } - } - results[k].ConfidenceLevel = uint8(v.ConfidenceLevel) - results[k].Features = make([]uint32, len(v.Features)) - for i := 0; i < len(v.Features); i++ { - results[k].Features[i] = uint32(v.Features[i]) - } - results[k].WorkerRole = uint8(v.Role) - } - return results, nil -} - -func (c *ChainClient) QueryTeeWorkEndpoint(workPuk pattern.WorkerPublicKey) (string, error) { +// QueryEndpoints query tee's endpoint +// - puk: tee's work public key +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - string: tee's endpoint +// - error: error message +func (c *ChainClient) QueryEndpoints(puk WorkerPublicKey, block int32) (string, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) @@ -200,33 +202,55 @@ func (c *ChainClient) QueryTeeWorkEndpoint(workPuk pattern.WorkerPublicKey) (str var data types.Text - if !c.GetChainState() { - return "", pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return "", ERR_RPC_CONNECTION } - val, err := codec.Encode(workPuk) + val, err := codec.Encode(puk) if err != nil { return "", errors.Wrap(err, "[Encode]") } - key, err := types.CreateStorageKey(c.metadata, pattern.TEEWORKER, pattern.TEEEndpoints, val) + key, err := types.CreateStorageKey(c.metadata, TeeWorker, Endpoints, val) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TEEWORKER, pattern.TEEEndpoints, err) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TeeWorker, Endpoints, err) return "", errors.Wrap(err, "[CreateStorageKey]") } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + c.SetRpcState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TeeWorker, Endpoints, err) + return "", errors.Wrap(err, "[GetStorageLatest]") + } + if !ok { + return "", ERR_RPC_EMPTY_VALUE + } + return string(data), nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + return string(data), err + } + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TEEWORKER, pattern.TEEEndpoints, err) - return "", errors.Wrap(err, "[GetStorageLatest]") + c.SetRpcState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), TeeWorker, Endpoints, err) + return "", errors.Wrap(err, "[GetStorage]") } if !ok { - return "", pattern.ERR_RPC_EMPTY_VALUE + return "", ERR_RPC_EMPTY_VALUE } - return string(data), nil } -func (c *ChainClient) QueryWorkerAddedAt(workPuk pattern.WorkerPublicKey) (types.U32, error) { +// QueryWorkerAddedAt query tee work registered block +// - puk: tee's work public key +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - uint32: tee work registered block +// - error: error message +func (c *ChainClient) QueryWorkerAddedAt(puk WorkerPublicKey, block int32) (uint32, error) { defer func() { if err := recover(); err != nil { log.Println(utils.RecoverError(err)) @@ -235,28 +259,43 @@ func (c *ChainClient) QueryWorkerAddedAt(workPuk pattern.WorkerPublicKey) (types var data types.U32 - if !c.GetChainState() { - return data, pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return uint32(data), ERR_RPC_CONNECTION } - val, err := codec.Encode(workPuk) + val, err := codec.Encode(puk) if err != nil { - return data, errors.Wrap(err, "[Encode]") + return uint32(data), errors.Wrap(err, "[Encode]") } - key, err := types.CreateStorageKey(c.metadata, pattern.TEEWORKER, pattern.TEEWorkerAddedAt, val) + key, err := types.CreateStorageKey(c.metadata, TeeWorker, WorkerAddedAt, val) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.TEEWORKER, pattern.TEEWorkerAddedAt, err) - return data, errors.Wrap(err, "[CreateStorageKey]") + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), TeeWorker, WorkerAddedAt, err) + return uint32(data), err } - - ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + c.SetRpcState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), TeeWorker, WorkerAddedAt, err) + return uint32(data), err + } + if !ok { + return uint32(data), ERR_RPC_EMPTY_VALUE + } + return uint32(data), nil + } + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.TEEWORKER, pattern.TEEWorkerAddedAt, err) - return data, errors.Wrap(err, "[GetStorageLatest]") + return uint32(data), err + } + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + c.SetRpcState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), TeeWorker, WorkerAddedAt, err) + return uint32(data), err } if !ok { - return data, pattern.ERR_RPC_EMPTY_VALUE + return uint32(data), ERR_RPC_EMPTY_VALUE } - - return data, nil + return uint32(data), nil } diff --git a/chain/treasury.go b/chain/treasury.go index 1391614..eb98766 100644 --- a/chain/treasury.go +++ b/chain/treasury.go @@ -11,12 +11,207 @@ import ( "fmt" "log" - "github.com/CESSProject/cess-go-sdk/core/pattern" "github.com/CESSProject/cess-go-sdk/utils" "github.com/centrifuge/go-substrate-rpc-client/v4/types" "github.com/centrifuge/go-substrate-rpc-client/v4/types/codec" ) +// QueryCurrencyReward query the currency rewards +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - string: currency rewards +// - error: error message +func (c *ChainClient) QueryCurrencyReward(block int32) (string, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var data types.U128 + + if !c.GetRpcState() { + return "", ERR_RPC_CONNECTION + } + + key, err := types.CreateStorageKey(c.metadata, CessTreasury, CurrencyReward) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), CessTreasury, CurrencyReward, err) + return "", err + } + + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), CessTreasury, CurrencyReward, err) + c.SetRpcState(false) + return "", err + } + if !ok { + return "0", ERR_RPC_EMPTY_VALUE + } + if data.String() == "" { + return "0", nil + } + return data.String(), nil + } + + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), CessTreasury, CurrencyReward, err) + return "", err + } + + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), CessTreasury, CurrencyReward, err) + c.SetRpcState(false) + return "", err + } + if !ok { + return "0", ERR_RPC_EMPTY_VALUE + } + + if data.String() == "" { + return "0", nil + } + return data.String(), nil +} + +// QueryEraReward query the rewards in era +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - string: rewards in era +// - error: error message +func (c *ChainClient) QueryEraReward(block int32) (string, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var data types.U128 + + if !c.GetRpcState() { + return "", ERR_RPC_CONNECTION + } + + key, err := types.CreateStorageKey(c.metadata, CessTreasury, EraReward) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), CessTreasury, EraReward, err) + return "", err + } + + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), CessTreasury, EraReward, err) + c.SetRpcState(false) + return "", err + } + if !ok { + return "0", ERR_RPC_EMPTY_VALUE + } + if data.String() == "" { + return "0", nil + } + return data.String(), nil + } + + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), CessTreasury, EraReward, err) + return "", err + } + + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), CessTreasury, EraReward, err) + c.SetRpcState(false) + return "", err + } + if !ok { + return "0", ERR_RPC_EMPTY_VALUE + } + + if data.String() == "" { + return "0", nil + } + return data.String(), nil +} + +// QueryReserveReward query the reserve rewards +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - string: reserve rewards +// - error: error message +func (c *ChainClient) QueryReserveReward(block int32) (string, error) { + defer func() { + if err := recover(); err != nil { + log.Println(utils.RecoverError(err)) + } + }() + + var data types.U128 + + if !c.GetRpcState() { + return "", ERR_RPC_CONNECTION + } + + key, err := types.CreateStorageKey(c.metadata, CessTreasury, ReserveReward) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), CessTreasury, ReserveReward, err) + return "", err + } + + if block < 0 { + ok, err := c.api.RPC.State.GetStorageLatest(key, &data) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), CessTreasury, ReserveReward, err) + c.SetRpcState(false) + return "", err + } + if !ok { + return "0", ERR_RPC_EMPTY_VALUE + } + if data.String() == "" { + return "0", nil + } + return data.String(), nil + } + + blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), CessTreasury, ReserveReward, err) + return "", err + } + + ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) + if err != nil { + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), CessTreasury, ReserveReward, err) + c.SetRpcState(false) + return "", err + } + if !ok { + return "0", ERR_RPC_EMPTY_VALUE + } + + if data.String() == "" { + return "0", nil + } + return data.String(), nil +} + +// QueryRoundReward querie the rewards in each era +// - era: era id +// - block: block number, less than 0 indicates the latest block +// +// Return: +// - string: rewards in an era +// - error: error message func (c *ChainClient) QueryRoundReward(era uint32, block int32) (string, error) { defer func() { if err := recover(); err != nil { @@ -24,10 +219,10 @@ func (c *ChainClient) QueryRoundReward(era uint32, block int32) (string, error) } }() - var data pattern.RoundRewardType + var data RoundRewardType - if !c.GetChainState() { - return "", pattern.ERR_RPC_CONNECTION + if !c.GetRpcState() { + return "", ERR_RPC_CONNECTION } param, err := codec.Encode(era) @@ -35,42 +230,46 @@ func (c *ChainClient) QueryRoundReward(era uint32, block int32) (string, error) return "", err } - key, err := types.CreateStorageKey(c.metadata, pattern.CessTreasury, pattern.RoundReward, param) + key, err := types.CreateStorageKey(c.metadata, CessTreasury, RoundReward, param) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), pattern.CessTreasury, pattern.RoundReward, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] CreateStorageKey: %v", c.GetCurrentRpcAddr(), CessTreasury, RoundReward, err) return "", err } if block < 0 { ok, err := c.api.RPC.State.GetStorageLatest(key, &data) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), pattern.CessTreasury, pattern.RoundReward, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorageLatest: %v", c.GetCurrentRpcAddr(), CessTreasury, RoundReward, err) + c.SetRpcState(false) return "", err } if !ok { - return "", pattern.ERR_RPC_EMPTY_VALUE + return "0", ERR_RPC_EMPTY_VALUE + } + if data.TotalReward.String() == "" { + return "0", nil } return data.TotalReward.String(), nil } blockhash, err := c.api.RPC.Chain.GetBlockHash(uint64(block)) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), pattern.CessTreasury, pattern.RoundReward, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetBlockHash: %v", c.GetCurrentRpcAddr(), CessTreasury, RoundReward, err) return "", err } ok, err := c.api.RPC.State.GetStorage(key, &data, blockhash) if err != nil { - err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), pattern.CessTreasury, pattern.RoundReward, err) - c.SetChainState(false) + err = fmt.Errorf("rpc err: [%s] [st] [%s.%s] GetStorage: %v", c.GetCurrentRpcAddr(), CessTreasury, RoundReward, err) + c.SetRpcState(false) return "", err } if !ok { - return "", pattern.ERR_RPC_EMPTY_VALUE + return "0", ERR_RPC_EMPTY_VALUE } + if data.TotalReward.String() == "" { + return "0", nil + } return data.TotalReward.String(), nil } diff --git a/chain/util.go b/chain/util.go new file mode 100644 index 0000000..00f050c --- /dev/null +++ b/chain/util.go @@ -0,0 +1,66 @@ +/* + Copyright (C) CESS. All rights reserved. + Copyright (C) Cumulus Encrypted Storage System. All rights reserved. + + SPDX-License-Identifier: Apache-2.0 +*/ + +package chain + +import ( + "github.com/centrifuge/go-substrate-rpc-client/v4/types" + "github.com/pkg/errors" +) + +func BytesToFileHash(val []byte) (FileHash, error) { + if len(val) != FileHashLen { + return FileHash{}, errors.New("[BytesToFileHash] invalid length") + } + var filehash FileHash + for k, v := range val { + filehash[k] = types.U8(v) + } + return filehash, nil +} + +func BytesToWorkPublickey(val []byte) (WorkerPublicKey, error) { + if len(val) != WorkerPublicKeyLen { + return WorkerPublicKey{}, errors.New("[BytesToWorkPublickey] invalid length") + } + var pubkey WorkerPublicKey + for k, v := range val { + pubkey[k] = types.U8(v) + } + return pubkey, nil +} + +func BytesToPoISKeyInfo(g, n []byte) (PoISKeyInfo, error) { + if len(g) != PoISKeyLen || len(n) != PoISKeyLen { + return PoISKeyInfo{}, errors.New("[BytesToPoISKeyInfo] invalid length") + } + var poisKey PoISKeyInfo + for i := 0; i < PoISKeyLen; i++ { + poisKey.G[i] = types.U8(g[i]) + poisKey.N[i] = types.U8(n[i]) + } + return poisKey, nil +} +func BytesToBloomFilter(val []byte) (BloomFilter, error) { + if len(val) != BloomFilterLen { + return BloomFilter{}, errors.New("[BytesToBloomFilter] invalid length") + } + var bloomfilter BloomFilter + for i := 0; i < BloomFilterLen; i++ { + bloomfilter[i] = types.U64(val[i]) + } + return bloomfilter, nil +} + +func IsWorkerPublicKeyAllZero(puk WorkerPublicKey) bool { + for i := 0; i < WorkerPublicKeyLen; i++ { + if puk[i] != 0 { + return false + } + } + return true +} diff --git a/config/config.go b/config/config.go index a51525a..8ea08e5 100755 --- a/config/config.go +++ b/config/config.go @@ -7,52 +7,25 @@ package config -import ( - "context" - "time" - - "github.com/CESSProject/cess-go-sdk/chain" +const ( + SIZE_1KiB = 1024 + SIZE_1MiB = 1024 * SIZE_1KiB + SIZE_1GiB = 1024 * SIZE_1MiB + SIZE_1TiB = 1024 * SIZE_1GiB + + SegmentSize = 32 * SIZE_1MiB + FragmentSize = 8 * SIZE_1MiB + DataShards = 4 + ParShards = 8 ) -// Config describes a set of settings for a client -type Config struct { - Rpc []string - Mnemonic string - Name string - Timeout time.Duration -} - -// Option is a client config option that can be given to the client constructor -type Option func(cfg *Config) error - -// default service name const ( - CharacterName_Default = "sdk" - CharacterName_Client = "client" - CharacterName_Bucket = "bucket" - CharacterName_Deoss = "deoss" + MinBucketNameLength = 3 + MaxBucketNameLength = 63 + MaxDomainNameLength = 100 ) -// NewSDK constructs a new client from the Config. -// -// This function consumes the config. Do not reuse it (really!). -func (cfg *Config) NewSDK(ctx context.Context) (*chain.ChainClient, error) { - if cfg.Name == "" { - cfg.Name = CharacterName_Default - } - return chain.NewChainClient(ctx, cfg.Name, cfg.Rpc, cfg.Mnemonic, cfg.Timeout) -} - -// Apply applies the given options to the config, returning the first error -// encountered (if any). -func (cfg *Config) Apply(opts ...Option) error { - for _, opt := range opts { - if opt == nil { - continue - } - if err := opt(cfg); err != nil { - return err - } - } - return nil -} +// default name +const ( + CharacterName_Default = "cess-sdk-go" +) diff --git a/core/erasure/rs.go b/core/erasure/rs.go index a2550a5..bd2a17e 100644 --- a/core/erasure/rs.go +++ b/core/erasure/rs.go @@ -13,7 +13,7 @@ import ( "os" "path/filepath" - "github.com/CESSProject/cess-go-sdk/core/pattern" + "github.com/CESSProject/cess-go-sdk/config" "github.com/CESSProject/cess-go-sdk/utils" "github.com/klauspost/reedsolomon" ) @@ -35,13 +35,13 @@ func ReedSolomon(path string) ([]string, error) { if fstat.IsDir() { return nil, errors.New("not a file") } - if fstat.Size() != pattern.SegmentSize { + if fstat.Size() != config.SegmentSize { return nil, errors.New("invalid size") } basedir := filepath.Dir(path) - enc, err := reedsolomon.New(pattern.DataShards, pattern.ParShards) + enc, err := reedsolomon.New(config.DataShards, config.ParShards) if err != nil { return shardspath, err } @@ -94,12 +94,12 @@ func RSRestore(outpath string, shardspath []string) error { return nil } - enc, err := reedsolomon.New(pattern.DataShards, pattern.ParShards) + enc, err := reedsolomon.New(config.DataShards, config.ParShards) if err != nil { return err } - shards := make([][]byte, pattern.DataShards+pattern.ParShards) + shards := make([][]byte, config.DataShards+config.ParShards) for k, v := range shardspath { shards[k], err = os.ReadFile(v) if err != nil { @@ -128,7 +128,7 @@ func RSRestore(outpath string, shardspath []string) error { return err } defer f.Close() - err = enc.Join(f, shards, len(shards[0])*pattern.DataShards) + err = enc.Join(f, shards, len(shards[0])*config.DataShards) return err } @@ -146,7 +146,7 @@ func RSRestoreData(outpath string, sharddata [][]byte) error { return nil } - datashards, parshards := pattern.DataShards, pattern.ParShards + datashards, parshards := config.DataShards, config.ParShards enc, err := reedsolomon.New(datashards, parshards) if err != nil { diff --git a/core/process/file.go b/core/process/file.go new file mode 100644 index 0000000..e96189b --- /dev/null +++ b/core/process/file.go @@ -0,0 +1,362 @@ +/* + Copyright (C) CESS. All rights reserved. + Copyright (C) Cumulus Encrypted Storage System. All rights reserved. + + SPDX-License-Identifier: Apache-2.0 +*/ + +package process + +import ( + "bytes" + "fmt" + "io" + "mime/multipart" + "net/http" + "os" + "path/filepath" + "strings" + + "github.com/CESSProject/cess-go-sdk/utils" + "github.com/btcsuite/btcutil/base58" + "github.com/centrifuge/go-substrate-rpc-client/v4/signature" + "github.com/pkg/errors" +) + +var globalTransport = &http.Transport{ + DisableKeepAlives: true, +} + +// StoreFile stores files to the gateway +// +// Receive parameter: +// - url: gateway url +// - file: stored file +// - bucket: bucket for storing file +// - mnemonic: polkadot account mnemonic +// +// Return parameter: +// - string: [fid] unique identifier for the file. +// - error: error message. +// +// Preconditions: +// 1. Account requires purchasing space, refer to [BuySpace] interface. +// 2. Authorize the space usage rights of the account to the gateway account, +// refer to the [AuthorizeSpace] interface. +// 3. Make sure the name of the bucket is legal, use the [CheckBucketName] method to check. +// +// Explanation: +// - Account refers to the account where you configured mnemonic when creating an SDK. +// - CESS public gateway address: [http://deoss-pub-gateway.cess.cloud/] +// - CESS public gateway account: [cXhwBytXqrZLr1qM5NHJhCzEMckSTzNKw17ci2aHft6ETSQm9] +func StoreFile(url, file, bucket, mnemonic string) (string, error) { + fstat, err := os.Stat(file) + if err != nil { + + return "", err + } + + if fstat.IsDir() { + return "", errors.New("not a file") + } + + if fstat.Size() == 0 { + return "", errors.New("empty file") + } + + if !utils.CheckBucketName(bucket) { + return "", errors.New("invalid bucket name") + } + + keyringPair, err := signature.KeyringPairFromSecret(mnemonic, 0) + if err != nil { + return "", fmt.Errorf("[KeyringPairFromSecret] %v", err) + } + + acc, err := utils.EncodePublicKeyAsCessAccount(keyringPair.PublicKey) + if err != nil { + return "", fmt.Errorf("[EncodePublicKeyAsCessAccount] %v", err) + } + + // sign message + message := utils.GetRandomcode(16) + sig, err := utils.SignedSR25519WithMnemonic(keyringPair.URI, message) + if err != nil { + return "", fmt.Errorf("[SignedSR25519WithMnemonic] %v", err) + } + + body := new(bytes.Buffer) + writer := multipart.NewWriter(body) + // + formFile, err := writer.CreateFormFile("file", fstat.Name()) + if err != nil { + return "", err + } + + f, err := os.Open(file) + if err != nil { + return "", err + } + defer f.Close() + + _, err = io.Copy(formFile, f) + if err != nil { + return "", err + } + err = writer.Close() + if err != nil { + return "", err + } + + req, err := http.NewRequest(http.MethodPut, url, body) + if err != nil { + return "", err + } + + req.Header.Set("BucketName", bucket) + req.Header.Set("Account", acc) + req.Header.Set("Message", message) + req.Header.Set("Signature", base58.Encode(sig[:])) + req.Header.Set("Content-Type", writer.FormDataContentType()) + + client := &http.Client{} + client.Transport = globalTransport + resp, err := client.Do(req) + if err != nil { + return "", err + } + defer resp.Body.Close() + + respbody, err := io.ReadAll(resp.Body) + if err != nil { + return "", err + } + + if resp.StatusCode != http.StatusOK { + if len(respbody) > 0 { + return "", errors.New(string(respbody)) + } + return "", errors.New(fmt.Sprintf("upload failed, code: %d", resp.StatusCode)) + } + + return strings.TrimPrefix(strings.TrimSuffix(string(respbody), "\""), "\""), nil +} + +// StoreObject stores object to the gateway +// +// Receive parameter: +// - url: gateway url +// - bucket: the bucket for storing object, it will be created automatically. +// - mnemonic: polkadot account mnemonic +// - reader: strings, byte data, file streams, network streams, etc. +// +// Return parameter: +// - string: [fid] unique identifier for the file. +// - error: error message. +// +// Preconditions: +// 1. Account requires purchasing space, refer to [BuySpace] interface. +// 2. Authorize the space usage rights of the account to the gateway account, +// refer to the [AuthorizeSpace] interface. +// 3. Make sure the name of the bucket is legal, use the [CheckBucketName] method to check. +// +// Explanation: +// - Account refers to the account where you configured mnemonic when creating an SDK. +// - CESS public gateway address: [http://deoss-pub-gateway.cess.cloud/] +// - CESS public gateway account: [cXhwBytXqrZLr1qM5NHJhCzEMckSTzNKw17ci2aHft6ETSQm9] +func StoreObject(url string, bucket, mnemonic string, reader io.Reader) (string, error) { + if !utils.CheckBucketName(bucket) { + return "", errors.New("invalid bucket name") + } + + keyringPair, err := signature.KeyringPairFromSecret(mnemonic, 0) + if err != nil { + return "", fmt.Errorf("[KeyringPairFromSecret] %v", err) + } + + acc, err := utils.EncodePublicKeyAsCessAccount(keyringPair.PublicKey) + if err != nil { + return "", fmt.Errorf("[EncodePublicKeyAsCessAccount] %v", err) + } + + // sign message + message := utils.GetRandomcode(16) + sig, err := utils.SignedSR25519WithMnemonic(keyringPair.URI, message) + if err != nil { + return "", fmt.Errorf("[SignedSR25519WithMnemonic] %v", err) + } + + req, err := http.NewRequest(http.MethodPut, url, reader) + if err != nil { + return "", err + } + + req.Header.Set("BucketName", bucket) + req.Header.Set("Account", acc) + req.Header.Set("Message", message) + req.Header.Set("Signature", base58.Encode(sig[:])) + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{} + client.Transport = globalTransport + resp, err := client.Do(req) + if err != nil { + return "", err + } + defer resp.Body.Close() + + respbody, err := io.ReadAll(resp.Body) + if err != nil { + return "", err + } + + if resp.StatusCode != http.StatusOK { + if len(respbody) > 0 { + return "", errors.New(string(respbody)) + } + return "", errors.New(fmt.Sprintf("upload failed, code: %d", resp.StatusCode)) + } + + return strings.TrimPrefix(strings.TrimSuffix(string(respbody), "\""), "\""), nil +} + +// RetrieveFile downloads files from the gateway +// - url: gateway url +// - fid: fid +// - mnemonic: polkadot account mnemonic +// - savepath: file save path +// +// Return: +// - string: fid +// - error: error message +func RetrieveFile(url, fid, mnemonic, savepath string) error { + fstat, err := os.Stat(savepath) + if err == nil { + if fstat.IsDir() { + savepath = filepath.Join(savepath, fid) + } + if fstat.Size() > 0 { + return nil + } + } + + if url == "" { + return errors.New("empty url") + } + + if url[len(url)-1] != byte(47) { + url += "/" + } + + f, err := os.Create(savepath) + if err != nil { + return err + } + defer f.Close() + + req, err := http.NewRequest(http.MethodGet, url+fid, nil) + if err != nil { + return err + } + + keyringPair, err := signature.KeyringPairFromSecret(mnemonic, 0) + if err != nil { + return fmt.Errorf("[KeyringPairFromSecret] %v", err) + } + + acc, err := utils.EncodePublicKeyAsCessAccount(keyringPair.PublicKey) + if err != nil { + return fmt.Errorf("[EncodePublicKeyAsCessAccount] %v", err) + } + + // sign message + message := utils.GetRandomcode(16) + sig, err := utils.SignedSR25519WithMnemonic(keyringPair.URI, message) + if err != nil { + return fmt.Errorf("[SignedSR25519WithMnemonic] %v", err) + } + + req.Header.Set("Message", message) + req.Header.Set("Signature", base58.Encode(sig[:])) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Operation", "download") + req.Header.Set("Account", acc) + + client := &http.Client{} + client.Transport = globalTransport + resp, err := client.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + return errors.New("failed") + } + + _, err = io.Copy(f, resp.Body) + if err != nil { + return err + } + + return nil +} + +// RetrieveObject gets the object from the gateway +// - url: gateway url +// - fid: fid +// - mnemonic: polkadot account mnemonic +// +// Return: +// - io.ReadCloser: object +// - error: error message +func RetrieveObject(url, fid, mnemonic string) (io.ReadCloser, error) { + if url == "" { + return nil, errors.New("empty url") + } + + if url[len(url)-1] != byte(47) { + url += "/" + } + + req, err := http.NewRequest(http.MethodGet, url+fid, nil) + if err != nil { + return nil, err + } + + keyringPair, err := signature.KeyringPairFromSecret(mnemonic, 0) + if err != nil { + return nil, fmt.Errorf("[KeyringPairFromSecret] %v", err) + } + + acc, err := utils.EncodePublicKeyAsCessAccount(keyringPair.PublicKey) + if err != nil { + return nil, fmt.Errorf("[EncodePublicKeyAsCessAccount] %v", err) + } + + // sign message + message := utils.GetRandomcode(16) + sig, err := utils.SignedSR25519WithMnemonic(keyringPair.URI, message) + if err != nil { + return nil, fmt.Errorf("[SignedSR25519WithMnemonic] %v", err) + } + + req.Header.Set("Message", message) + req.Header.Set("Signature", base58.Encode(sig[:])) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Account", acc) + req.Header.Set("Operation", "download") + + client := &http.Client{} + client.Transport = globalTransport + resp, err := client.Do(req) + if err != nil { + return nil, err + } + + if resp.StatusCode != http.StatusOK { + return nil, errors.New(fmt.Sprintf("Retrieve failed, code: %d", resp.StatusCode)) + } + + return resp.Body, nil +} diff --git a/core/process/file_chunk.go b/core/process/file_chunk.go new file mode 100644 index 0000000..6bc0f1b --- /dev/null +++ b/core/process/file_chunk.go @@ -0,0 +1,249 @@ +/* + Copyright (C) CESS. All rights reserved. + Copyright (C) Cumulus Encrypted Storage System. All rights reserved. + + SPDX-License-Identifier: Apache-2.0 +*/ + +package process + +import ( + "bufio" + "bytes" + "fmt" + "io" + "mime/multipart" + "net/http" + "os" + "path/filepath" + "strings" + + "github.com/CESSProject/cess-go-sdk/config" + "github.com/CESSProject/cess-go-sdk/utils" + "github.com/btcsuite/btcutil/base58" + "github.com/centrifuge/go-substrate-rpc-client/v4/signature" + "github.com/pkg/errors" +) + +// UploadFileChunks upload file chunks in the directory to the gateway as much as possible, +// chunks will be removed after being uploaded, if the chunks are not transferred successfuly, jus +// +// Receive parameter: +// - url: the address of the gateway. +// - chunksDir: directory path to store file chunks, please do not mix it elsewhere. +// - bucket: the bucket name to store user data. +// - fname: the name of the file. +// - chunksNum: total number of file chunks. +// - totalSize: chunks total size (byte), can be obtained from the first return value of SplitFile +// +// Return parameter: +// - Reader: number of file chunks. +// - error: error message. +func UploadFileChunks(url, mnemonic, chunksDir, bucket, fname string, chunksNum int, totalSize int64) (string, error) { + entries, err := os.ReadDir(chunksDir) + if err != nil { + return "", errors.Wrap(err, "upload file chunk error") + } + if len(entries) == 0 { + return "", errors.Wrap(errors.New("empty dir"), "upload file chunk error") + } + if len(entries) > chunksNum { + return "", errors.Wrap(errors.New("bad chunks number"), "upload file chunk error") + } + var res string + for i := chunksNum - len(entries); i < chunksNum; i++ { + res, err = UploadFileChunk(url, mnemonic, chunksDir, bucket, fname, chunksNum, i, totalSize) + if err != nil { + return res, errors.Wrap(err, "upload file chunks error") + } + os.Remove(filepath.Join(chunksDir, fmt.Sprintf("chunk-%d", i))) + } + return res, nil +} + +// UploadFileChunk upload chunk of file to the gateway +// +// Receive parameter: +// - url: the address of the gateway. +// - chunksDir: directory path to store file chunks, please do not mix it elsewhere. +// - bucket: the bucket name to store user data. +// - fname: the name of the file. +// - chunksNum: total number of file chunks. +// - chunksId: index of the current chunk to be uploaded ([0,chunksNum)). +// - totalSize: chunks total size (byte), can be obtained from the first return value of SplitFile +// +// Return parameter: +// - Reader: number of file chunks. +// - error: error message. +func UploadFileChunk(url, mnemonic, chunksDir, bucket, fname string, chunksNum, chunksId int, totalSize int64) (string, error) { + + file := filepath.Join(chunksDir, fmt.Sprintf("chunk-%d", chunksId)) + fstat, err := os.Stat(file) + if err != nil { + return "", errors.Wrap(err, "upload file chunk error") + } + + if fstat.IsDir() { + return "", errors.Wrap(errors.New("not a file"), "upload file chunk error") + } + + if fstat.Size() == 0 { + return "", errors.New("empty file") + } + + if !utils.CheckBucketName(bucket) { + return "", errors.New("invalid bucket name") + } + + keyringPair, err := signature.KeyringPairFromSecret(mnemonic, 0) + if err != nil { + return "", fmt.Errorf("[KeyringPairFromSecret] %v", err) + } + + acc, err := utils.EncodePublicKeyAsCessAccount(keyringPair.PublicKey) + if err != nil { + return "", fmt.Errorf("[EncodePublicKeyAsCessAccount] %v", err) + } + + // sign message + message := utils.GetRandomcode(16) + sig, err := utils.SignedSR25519WithMnemonic(keyringPair.URI, message) + if err != nil { + return "", fmt.Errorf("[SignedSR25519WithMnemonic] %v", err) + } + + body := new(bytes.Buffer) + writer := multipart.NewWriter(body) + // + formFile, err := writer.CreateFormFile("file", fstat.Name()) + if err != nil { + return "", err + } + + f, err := os.Open(file) + if err != nil { + return "", err + } + defer f.Close() + + _, err = io.Copy(formFile, f) + if err != nil { + return "", err + } + err = writer.Close() + if err != nil { + return "", err + } + + req, err := http.NewRequest(http.MethodPut, url, body) + if err != nil { + return "", err + } + + req.Header.Set("BucketName", bucket) + req.Header.Set("Account", acc) + req.Header.Set("Message", message) + req.Header.Set("Signature", base58.Encode(sig[:])) + req.Header.Set("Content-Type", writer.FormDataContentType()) + req.Header.Set("FileName", fname) + req.Header.Set("BlockNumber", fmt.Sprint(chunksNum)) + req.Header.Set("BlockIndex", fmt.Sprint(chunksId)) + req.Header.Set("TotalSize", fmt.Sprint(totalSize)) + + client := &http.Client{} + client.Transport = globalTransport + resp, err := client.Do(req) + if err != nil { + return "", err + } + defer resp.Body.Close() + + respbody, err := io.ReadAll(resp.Body) + if err != nil { + return "", err + } + + if resp.StatusCode != http.StatusOK { + if len(respbody) > 0 { + return "", errors.New(string(respbody)) + } + return "", errors.New(fmt.Sprintf("upload failed, code: %d", resp.StatusCode)) + } + return strings.TrimPrefix(strings.TrimSuffix(string(respbody), "\""), "\""), nil +} + +// Split File into Chunks with standard size. +// It split file into chunks of the default size and fills the last chunk that does not meet the size. +// +// Receive parameter: +// - fpath: the path of the file to be split. +// - chunksDir: directory path to store file chunks, please do not mix it elsewhere. +// +// Return parameter: +// - int64: chunks total size (byte). +// - int: number of file chunks. +// - error: error message. +func SplitFileWithstandardSize(fpath, chunksDir string) (int64, int, error) { + return SplitFile(fpath, chunksDir, config.SegmentSize, true) +} + +// Split File into Chunks. +// +// Receive parameter: +// - fpath: the path of the file to be split. +// - chunksDir: directory path to store file chunks, please do not mix it elsewhere. +// - chunkSize: the size of each chunk, it does not exceed the file size +// +// Return parameter: +// - int64: chunks total size (byte). +// - int: number of file chunks. +// - error: error message. +func SplitFile(fpath, chunksDir string, chunkSize int64, filling bool) (int64, int, error) { + fstat, err := os.Stat(fpath) + if err != nil { + return 0, 0, err + } + if fstat.IsDir() { + return 0, 0, errors.New("not a file") + } + if fstat.Size() == 0 { + return 0, 0, errors.New("empty file") + } + if fstat.Size() < chunkSize { + chunkSize = fstat.Size() + } + count := fstat.Size() / chunkSize + if fstat.Size()%chunkSize != 0 { + count++ + } + buf := make([]byte, chunkSize) + f, err := os.Open(fpath) + if err != nil { + return 0, 0, err + } + defer f.Close() + reader := bufio.NewReader(f) + size := fstat.Size() + for i := int64(0); i < count; i++ { + n, err := reader.Read(buf) + if err != nil { + return 0, 0, err + } + if n <= 0 { + return 0, 0, errors.New("read a empty block") + } + if n < int(chunkSize) && filling { + if i+1 != count { + return 0, 0, errors.New("read file err") + } + copy(buf[n:], make([]byte, chunkSize-int64(n))) + size += chunkSize - int64(n) + n = int(chunkSize) + } + err = utils.WriteBufToFile(buf[:n], filepath.Join(chunksDir, fmt.Sprintf("chunk-%d", i))) + if err != nil { + return 0, 0, err + } + } + return size, int(count), nil +} diff --git a/core/process/process.go b/core/process/process.go index bb534c1..488ec7e 100755 --- a/core/process/process.go +++ b/core/process/process.go @@ -12,10 +12,11 @@ import ( "os" "path/filepath" + "github.com/CESSProject/cess-go-sdk/chain" + "github.com/CESSProject/cess-go-sdk/config" "github.com/CESSProject/cess-go-sdk/core/crypte" "github.com/CESSProject/cess-go-sdk/core/erasure" "github.com/CESSProject/cess-go-sdk/core/hashtree" - "github.com/CESSProject/cess-go-sdk/core/pattern" "github.com/CESSProject/cess-go-sdk/utils" "github.com/pkg/errors" ) @@ -29,7 +30,7 @@ import ( // - segmentDataInfo: segment and fragment information of the file. // - string: [fid] unique identifier for the file. // - error: error message. -func ProcessingData(file string) ([]pattern.SegmentDataInfo, string, error) { +func ProcessingData(file string) ([]chain.SegmentDataInfo, string, error) { segmentPath, err := cutfile(file) if err != nil { if segmentPath != nil { @@ -40,7 +41,7 @@ func ProcessingData(file string) ([]pattern.SegmentDataInfo, string, error) { return nil, "", errors.Wrapf(err, "[cutfile]") } - var segmentDataInfo = make([]pattern.SegmentDataInfo, len(segmentPath)) + var segmentDataInfo = make([]chain.SegmentDataInfo, len(segmentPath)) for i := 0; i < len(segmentPath); i++ { segmentDataInfo[i].SegmentHash = segmentPath[i] @@ -78,7 +79,7 @@ func ProcessingData(file string) ([]pattern.SegmentDataInfo, string, error) { // - segmentDataInfo: segment and fragment information of the file. // - string: [fid] unique identifier for the file. // - error: error message. -func ShardedEncryptionProcessing(file string, cipher string) ([]pattern.SegmentDataInfo, string, error) { +func ShardedEncryptionProcessing(file string, cipher string) ([]chain.SegmentDataInfo, string, error) { var err error var segmentPath []string if cipher != "" { @@ -112,7 +113,7 @@ func ShardedEncryptionProcessing(file string, cipher string) ([]pattern.SegmentD } } - var segmentDataInfo = make([]pattern.SegmentDataInfo, len(segmentPath)) + var segmentDataInfo = make([]chain.SegmentDataInfo, len(segmentPath)) for i := 0; i < len(segmentPath); i++ { segmentDataInfo[i].SegmentHash = segmentPath[i] @@ -152,13 +153,13 @@ func cutfile(file string) ([]string, error) { return nil, errors.New("empty file") } baseDir := filepath.Dir(file) - segmentCount := fstat.Size() / pattern.SegmentSize - if fstat.Size()%int64(pattern.SegmentSize) != 0 { + segmentCount := fstat.Size() / config.SegmentSize + if fstat.Size()%int64(config.SegmentSize) != 0 { segmentCount++ } segment := make([]string, segmentCount) - buf := make([]byte, pattern.SegmentSize) + buf := make([]byte, config.SegmentSize) f, err := os.Open(file) if err != nil { return segment, err @@ -167,7 +168,7 @@ func cutfile(file string) ([]string, error) { var num int for i := int64(0); i < segmentCount; i++ { - f.Seek(pattern.SegmentSize*i, 0) + f.Seek(config.SegmentSize*i, 0) num, err = f.Read(buf) if err != nil && err != io.EOF { return segment, err @@ -175,11 +176,11 @@ func cutfile(file string) ([]string, error) { if num == 0 { return segment, errors.New("read file is empty") } - if num < pattern.SegmentSize { + if num < config.SegmentSize { if i+1 != segmentCount { return segment, errors.New("read file err") } - copy(buf[num:], make([]byte, pattern.SegmentSize-num, pattern.SegmentSize-num)) + copy(buf[num:], make([]byte, config.SegmentSize-num, config.SegmentSize-num)) } hash, err := utils.CalcSHA256(buf) @@ -208,7 +209,7 @@ func cutFileWithEncryption(file string) ([]string, error) { return nil, errors.New("empty file") } baseDir := filepath.Dir(file) - segmentSize := pattern.SegmentSize - 16 + segmentSize := config.SegmentSize - 16 segmentCount := fstat.Size() / int64(segmentSize) if fstat.Size()%int64(segmentSize) != 0 { segmentCount++ diff --git a/core/sdk/sdk.go b/core/sdk/sdk.go deleted file mode 100755 index 83effa8..0000000 --- a/core/sdk/sdk.go +++ /dev/null @@ -1,533 +0,0 @@ -/* - Copyright (C) CESS. All rights reserved. - Copyright (C) Cumulus Encrypted Storage System. All rights reserved. - - SPDX-License-Identifier: Apache-2.0 -*/ - -package sdk - -import ( - "io" - "math/big" - - "github.com/CESSProject/cess-go-sdk/core/event" - "github.com/CESSProject/cess-go-sdk/core/pattern" - gsrpc "github.com/centrifuge/go-substrate-rpc-client/v4" - "github.com/centrifuge/go-substrate-rpc-client/v4/types" -) - -// CESS Go SDK Interface Description -type SDK interface { - // Audit-State - - // QueryChallengeVerifyExpiration Query Challenge Expiration Block High - QueryChallengeVerifyExpiration() (uint32, error) - // QueryChallengeInfo queries accountID's challenge information - // Tip: accountID can only be a storage node account - QueryChallengeInfo(accountID []byte, block int32) (bool, pattern.ChallengeInfo, error) - - // Audit-Extrinsics - - // SubmitIdleProof submits proof of idle data to the chain - // Tip: This method can only be used for storage nodes - SubmitIdleProof(idleProve []types.U8) (string, error) - // SubmitServiceProof submits proof of service data to the chain - // Tip: This method can only be used for storage nodes - SubmitServiceProof(serviceProof []types.U8) (string, error) - // SubmitIdleProofResult submits the proof verification results of idle data to the chain - // Tip: This method can only be used for storage nodes - SubmitIdleProofResult(totalProofHash []types.U8, front, rear types.U64, accumulator pattern.Accumulator, result types.Bool, sig types.Bytes, teePuk pattern.WorkerPublicKey) (string, error) - // SubmitServiceProofResult submits the proof verification results of service data to the chain - // Tip: This method can only be used for storage nodes - SubmitServiceProofResult(result types.Bool, sign types.Bytes, bloomFilter pattern.BloomFilter, teePuk pattern.WorkerPublicKey) (string, error) - - // Filebank-State - - // QueryBucketInfo query the bucket information of the accountID - QueryBucketInfo(accountID []byte, bucketName string) (pattern.BucketInfo, error) - // QueryAllBucket query all buckets of the accountID - QueryAllBucket(accountID []byte) ([]types.Bytes, error) - // QueryAllBucketString query all bucket names as string of the accountID - QueryAllBucketString(accountID []byte) ([]string, error) - // QueryStorageOrder query storage order information. - QueryStorageOrder(fid string) (pattern.StorageOrder, error) - // QueryFileMetadata queries the metadata of the roothash file. - QueryFileMetadata(fid string) (pattern.FileMetadata, error) - // QueryFileMetadataByBlock queries the metadata of the roothash file. - QueryFileMetadataByBlock(fid string, block uint64) (pattern.FileMetadata, error) - // QueryRestoralOrder queries a restore order info. - QueryRestoralOrder(roothash string) (pattern.RestoralOrderInfo, error) - QueryRestoralOrderList() ([]pattern.RestoralOrderInfo, error) - - // Filebank-Extrinsics - - // ClaimRestoralNoExistOrder is used to receive recovery orders from exiting miners. - ClaimRestoralNoExistOrder(accountID []byte, fid, restoralFragmentHash string) (string, error) - // ClaimRestoralOrder is used to collect restoration orders. - ClaimRestoralOrder(fragmentHash string) (string, error) - // CreateBucket creates a bucket for accountID - // For details on bucket naming rules, see: - // https://app.gitbook.com/o/kiTNX10jBU59sjnYZbiH/s/G1ekWsjn9OlGH381wiK2/get-started/deoss-gateway/step-1-create-a-bucket#naming-conventions-for-a-bucket - CreateBucket(accountID []byte, bucketName string) (string, error) - // DeleteBucket deletes buckets for accountID - // Tip: Only empty buckets can be deleted - DeleteBucket(accountID []byte, bucketName string) (string, error) - // DeleteFile deletes files for accountID - DeleteFile(accountID []byte, fid []string) (string, []pattern.FileHash, error) - // GenerateRestoralOrder generates data for restoration orders. - GenerateRestoralOrder(fid, fragmentHash string) (string, error) - // RestoralComplete reports order recovery completion. - RestoralComplete(restoralFragmentHash string) (string, error) - // SubmitFileReport submits a stored file report. - SubmitFileReport(index types.U8, roothash pattern.FileHash) (string, error) - ReportFile(index uint8, roothash string) (string, error) - // UploadDeclaration creates a storage order. - UploadDeclaration(filehash string, dealinfo []pattern.SegmentList, user pattern.UserBrief, filesize uint64) (string, error) - // GenerateStorageOrder for generating storage orders - GenerateStorageOrder(roothash string, segment []pattern.SegmentDataInfo, owner []byte, filename, buckname string, filesize uint64) (string, error) - // CertIdleSpace - CertIdleSpace(idleSignInfo pattern.SpaceProofInfo, teeSignWithAcc, teeSign types.Bytes, teePuk pattern.WorkerPublicKey) (string, error) - // ReplaceIdleSpace - ReplaceIdleSpace(idleSignInfo pattern.SpaceProofInfo, teeSignWithAcc, teeSign types.Bytes, teePuk pattern.WorkerPublicKey) (string, error) - // ReportTagCalculated - ReportTagCalculated(teeSig types.Bytes, tagSigInfo pattern.TagSigInfo) (string, error) - - // Oss-State - - // QueryAuthorizedAccountIDs queries all DeOSS accountIDs authorized by accountID - QueryAuthorizedAccountIDs(accountID []byte) ([]types.AccountID, error) - // QueryAuthorizedAccounts queries all DeOSS accounts authorized by accountID - QueryAuthorizedAccounts(accountID []byte) ([]string, error) - // QueryDeOSSInfo Query the DeOSS information registered by accountID account - QueryDeOSSInfo(accountID []byte) (pattern.OssInfo, error) - // QueryAllDeOSSInfo queries all deoss information - QueryAllDeOSSInfo() ([]pattern.OssInfo, error) - // QueryAllDeOSSPeerId queries peerID of all DeOSS - QueryAllDeOSSPeerId() ([]string, error) - - // Oss-Extrinsics - - // RegisterDeOSS register as deoss node - RegisterDeOSS(peerId []byte, domain string) (string, error) - // UpdateDeOSS updates the peerID and domain of deoss - // Tip: This method can only be used for DeOSS nodes - UpdateDeOSS(peerId string, domain string) (string, error) - // ExitDeoss exit deoss - // Tip: This method can only be used for DeOSS nodes - ExitDeOSS() (string, error) - // AuthorizeSpace authorizes space to oss account - // Tip: accountID can only be a DeOSS node account - AuthorizeSpace(accountID string) (string, error) - // UnAuthorizeSpace cancels space authorization - // Tip: accountID can only be a DeOSS node account - UnAuthorizeSpace(accountID string) (string, error) - - // Sminer-State - - // QueryExpenders queries expenders information - QueryExpenders() (pattern.ExpendersInfo, error) - // // QueryStorageMinerByAccount queries storage node information by account. - QueryStorageMinerByAccount(account string) (pattern.MinerInfo, error) - // QueryStorageMiner queries storage node information. - QueryStorageMiner(accountID []byte) (pattern.MinerInfo, error) - // QueryStorageMinerByBlock queries storage node information in specified block - // - if block < 0, then query the latest block - QueryStorageMinerByBlock(puk []byte, block int32) (pattern.MinerInfo, error) - // QueryAllSminerAccount queries the accounts of all storage miners. - QueryAllSminerAccount() ([]types.AccountID, error) - // QueryAllSminerAccountByBlock queries accounts of all storage miners in specified block. - // - if block < 0, then query the latest block - QueryAllSminerAccountByBlock(block int32) ([]types.AccountID, error) - // QueryRewardsMap queries rewardsMap for accountID - // Tip: accountID can only be a storage node account - QueryRewardsMap(accountID []byte) (pattern.MinerReward, error) - // QueryRewards queries rewards for accountID - // Tip: accountID can only be a storage node account - QueryRewards(accountID []byte) (pattern.RewardsType, error) - // QueryStorageMinerStakingStartBlock - QueryStorageMinerStakingStartBlock(puk []byte) (types.U32, error) - // QueryRestoralTarget queries the space recovery information of the exited storage node - // Tip: accountID can only be a storage node account - QueryRestoralTarget(accountID []byte) (pattern.RestoralTargetInfo, error) - // QueryRestoralTargetList queries the space recovery information of all exited storage nodes - QueryRestoralTargetList() ([]pattern.RestoralTargetInfo, error) - // QueryPendingReplacements queries the amount of idle data that can be replaced - // Tip: accountID can only be a storage node account - QueryPendingReplacements(accountID []byte) (types.U128, error) - // - QueryCompleteSnapShot(era uint32, block int32) (uint32, uint64, error) - - // Sminer-Extrinsics - - // - IncreaseDeclarationSpace(tibCount uint32) (string, error) - // RegisterSminer register sminer information - RegisterSminer(earnings string, peerId []byte, pledge uint64, tib_count uint32) (string, error) - // RegisterSminerAssignStaking - RegisterSminerAssignStaking(beneficiaryAcc string, peerId []byte, stakingAcc string, tib_count uint32) (string, error) - // RegisterSminerPOISKey register the pois key of sminer - RegisterSminerPOISKey(poisKey pattern.PoISKeyInfo, teeSignWithAcc, teeSign types.Bytes, teePuk pattern.WorkerPublicKey) (string, error) - // ExitSminer exit mining - ExitSminer(miner string) (string, error) - // UpdateEarningsAcc update earnings account. - UpdateEarningsAcc(puk []byte) (string, error) - UpdateEarningsAccount(earnings string) (string, error) - // UpdateSminerPeerId update miner peerid - UpdateSminerPeerId(peerid pattern.PeerId) (string, error) - // IncreaseStakingAmount increase staking amount. - IncreaseStakingAmount(miner string, tokens *big.Int) (string, error) - IncreaseStorageNodeStakingAmount(miner string, token string) (string, error) - // ClaimRewards is used to claim rewards. - ClaimRewards() (string, error) - // Withdraw is used to withdraw staking. - Withdraw() (string, error) - - // Staking-State - - // QueryAllValidatorCount queries all the validator count - QueryAllValidatorCount(block int) (uint32, error) - // - QueryValidatorsCount(block int) (uint32, error) - // - QueryNominatorCount(block int) (uint32, error) - // - QueryErasTotalStake(era uint32, block int) (string, error) - // - QueryCurrentEra(block int) (uint32, error) - // - //QueryeErasStakers(era uint32) ([]pattern.StakingExposure, error) - // - QueryStakingEraRewardPoints(era uint32) (pattern.StakingEraRewardPoints, error) - // - QueryNominatorsLatest() ([]pattern.StakingNominations, error) - // - QueryBondedList(block int32) ([]types.AccountID, error) - // - QueryValidatorCommission(account string, block int) (uint8, error) - // - QueryEraValidatorReward(era uint32) (string, error) - - // StorageHandler-State - - // QueryUserSpaceInfo queries the space information purchased by the user. - QueryUserSpaceInfo(puk []byte) (pattern.UserSpaceInfo, error) - QueryUserSpaceSt(puk []byte) (pattern.UserSpaceSt, error) - // QuerySpacePricePerGib query space price per GiB. - QuerySpacePricePerGib() (string, error) - // QueryTotalIdleSpace query total idle space - QueryTotalIdleSpace() (uint64, error) - // QueryTotalServiceSpace query total service space - QueryTotalServiceSpace() (uint64, error) - // QueryPurchasedSpace query purchased space - QueryPurchasedSpace() (uint64, error) - - // StorageHandler-Extrinsics - - // BuySpace for purchasing space. - BuySpace(count uint32) (string, error) - // ExpansionSpace for expansion space. - ExpansionSpace(count uint32) (string, error) - // RenewalSpace is used to extend the validity of space. - RenewalSpace(days uint32) (string, error) - - // TeeWorker-State - - // QueryTeeWorker queries the information of the Tee worker. - QueryTeeWorker(puk pattern.WorkerPublicKey) (pattern.TeeWorkerInfo, error) - // QueryTeeInfo queries the information of the Tee worker. - QueryTeeInfo(puk pattern.WorkerPublicKey) (pattern.TeeInfo, error) - // QueryMasterPublicKey queries the master publicKey. - QueryMasterPublicKey() ([]byte, error) - // QueryAllTeeWorkerMap queries the information of all tee workers. - QueryAllTeeWorkerMap() ([]pattern.TeeWorkerInfo, error) - // QueryAllTeeInfo queries the information of all tee workers. - QueryAllTeeInfo() ([]pattern.TeeInfo, error) - // QueryTeeWorkEndpoint queries the endpoint of tee workers. - QueryTeeWorkEndpoint(workPuk pattern.WorkerPublicKey) (string, error) - // - QueryWorkerAddedAt(workPuk pattern.WorkerPublicKey) (types.U32, error) - - // System - - // QueryBlockHeight queries the block height corresponding to the block hash, - // If the blockhash is empty, query the latest block height. - QueryBlockHeight(blockhash string) (uint32, error) - // QueryNodeSynchronizationSt returns the synchronization status of the current node. - QueryNodeSynchronizationSt() (bool, error) - // QueryAccountInfoByAccount query account information by account. - QueryAccountInfoByAccount(acc string) (types.AccountInfo, error) - // QueryAccountInfo query account information by public key. - QueryAccountInfo(puk []byte) (types.AccountInfo, error) - // GetTokenSymbol returns the token symbol - GetTokenSymbol() string - // GetNetworkEnv returns the network environment - GetNetworkEnv() string - // SysProperties returns the system properties. - SysProperties() (pattern.SysProperties, error) - // SyncState returns the system sync state. - SyncState() (pattern.SysSyncState, error) - // SysVersion returns the system version. - ChainVersion() (string, error) - // NetListening returns whether the current node is listening. - NetListening() (bool, error) - // - DecodeEventNameFromBlock(block uint64) ([]string, error) - // - DecodeEventNameFromBlockhash(blockhash types.Hash) ([]string, error) - // - QueryAllAccountInfoFromBlock(block int) ([]types.AccountInfo, error) - // - QueryTotalIssuance(block int) (string, error) - - // CessTreasury - QueryRoundReward(era uint32, block int32) (string, error) - - // TransferToken to dest. - // - // Receive parameter: - // - dest: target account. - // - amount: transfer amount. - // Return parameter: - // - string: transaction hash. - // - string: target account. - // - error: error message. - TransferToken(dest string, amount uint64) (string, string, error) - - // Other - - // GetSignatureAcc returns the signature account. - GetSignatureAcc() string - // GetSignatureAccPulickey returns the signature account public key. - GetSignatureAccPulickey() []byte - // GetSubstrateAPI returns Substrate API. - GetSubstrateAPI() *gsrpc.SubstrateAPI - // GetChainState returns chain node state. - GetChainState() bool - // SetChainState sets the state of the chain node. - SetChainState(state bool) - // GetSdkName return sdk name - GetSDKName() string - // GetCurrentRpcAddr return current rpc address - GetCurrentRpcAddr() string - // SetSdkName set sdk name - SetSDKName(name string) - // ReconnectRPC for reconnecting chains. - ReconnectRPC() error - // GetMetadata returns the metadata of the chain. - GetMetadata() *types.Metadata - // GetKeyEvents returns the events storage key. - GetKeyEvents() types.StorageKey - // GetURI returns URI. - GetURI() string - // GetTreasuryAccount returns the treasury account - GetTreasuryAccount() string - // Sign returns the signature of the msg with the private key of the signing account. - Sign(msg []byte) ([]byte, error) - // Verify the signature of the msg with the public key of the signing account. - Verify(msg []byte, sig []byte) (bool, error) - // Verify Polka Signature With JavaScript - VerifyPolkaSignatureWithJS(account, msg, signature string) (bool, error) - // Verify Polka Signature With Base58 - VerifyPolkaSignatureWithBase58(account, msg, signature string) (bool, error) - // - Close() - - // Upload file to CESS gateway. - // - // Receive parameter: - // - url: the address of the gateway. - // - file: uploaded file. - // - bucket: the bucket for storing files, it will be created automatically. - // Return parameter: - // - string: [fid] unique identifier for the file. - // - error: error message. - // Preconditions: - // 1. Account requires purchasing space, refer to [BuySpace] interface. - // 2. Authorize the space usage rights of the account to the gateway account, - // refer to the [AuthorizeSpace] interface. - // 3. Make sure the name of the bucket is legal, use the [CheckBucketName] method to check. - // Explanation: - // - Account refers to the account where you configured mnemonic when creating an SDK. - // - CESS public gateway address: [http://deoss-pub-gateway.cess.cloud/] - // - CESS public gateway account: [cXhwBytXqrZLr1qM5NHJhCzEMckSTzNKw17ci2aHft6ETSQm9] - StoreFile(url, file, bucket string) (string, error) - - // Upload object to CESS gateway. - // - // Receive parameter: - // - url: the address of the gateway. - // - reader: strings, byte data, file streams, network streams, etc. - // - bucket: the bucket for storing object, it will be created automatically. - // Return parameter: - // - string: [fid] unique identifier for the file. - // - error: error message. - // Preconditions: - // 1. Account requires purchasing space, refer to [BuySpace] interface. - // 2. Authorize the space usage rights of the account to the gateway account, - // refer to the [AuthorizeSpace] interface. - // 3. Make sure the name of the bucket is legal, use the [CheckBucketName] method to check. - // Explanation: - // - Account refers to the account where you configured mnemonic when creating an SDK. - // - CESS public gateway address: [http://deoss-pub-gateway.cess.cloud/] - // - CESS public gateway account: [cXhwBytXqrZLr1qM5NHJhCzEMckSTzNKw17ci2aHft6ETSQm9] - StoreObject(url string, reader io.Reader, bucket string) (string, error) - - // Download file from CESS public gateway. - // - // Receive parameter: - // - url: the address of the gateway. - // - fid: unique identifier for the file. - // - savepath: file save location. - // Return parameter: - // - error: error message. - RetrieveFile(url, fid, savepath string) error - - // Download object from CESS gateway. - // - // Receive parameter: - // - url: the address of the gateway. - // - fid: unique identifier for the file. - // Return parameter: - // - Reader: object stream. - // - error: error message. - RetrieveObject(url, fid string) (io.ReadCloser, error) - - // Split File into Chunks. - // - // Receive parameter: - // - fpath: the path of the file to be split. - // - chunksDir: directory path to store file chunks, please do not mix it elsewhere. - // - chunkSize: the size of each chunk, it does not exceed the file size - // Return parameter: - // - int64: chunks total size (byte). - // - int: number of file chunks. - // - error: error message. - SplitFile(fpath, chunksDir string, chunkSize int64, filling bool) (int64, int, error) - - // Split File into Chunks with standard size. - // It split file into chunks of the default size and fills the last chunk that does not meet the size. - // - // Receive parameter: - // - fpath: the path of the file to be split. - // - chunksDir: directory path to store file chunks, please do not mix it elsewhere. - // Return parameter: - // - int64: chunks total size (byte). - // - int: number of file chunks. - // - error: error message. - SplitFileWithstandardSize(fpath, chunksDir string) (int64, int, error) - - // Upload chunk of file to the gateway - // - // Receive parameter: - // - url: the address of the gateway. - // - chunksDir: directory path to store file chunks, please do not mix it elsewhere. - // - bucket: the bucket name to store user data. - // - fname: the name of the file. - // - chunksNum: total number of file chunks. - // - chunksId: index of the current chunk to be uploaded ([0,chunksNum)). - // - totalSize: chunks total size (byte), can be obtained from the first return value of SplitFile - // Return parameter: - // - Reader: number of file chunks. - // - error: error message. - UploadFileChunk(url, chunksDir, bucket, fname string, chunksNum, chunksId int, totalSize int64) (string, error) - - // Upload file chunks in the directory to the gateway as much as possible, chunks will be removed after being uploaded, if the chunks are not transferred successfuly, jus - // - // Receive parameter: - // - url: the address of the gateway. - // - chunksDir: directory path to store file chunks, please do not mix it elsewhere. - // - bucket: the bucket name to store user data. - // - fname: the name of the file. - // - chunksNum: total number of file chunks. - // - totalSize: chunks total size (byte), can be obtained from the first return value of SplitFile - // Return parameter: - // - Reader: number of file chunks. - // - error: error message. - UploadFileChunks(url, chunksDir, bucket, fname string, chunksNum int, totalSize int64) (string, error) - - // retrieve event - - // - RetrieveEvent_Audit_SubmitIdleProof(blockhash types.Hash) (event.Event_SubmitIdleProof, error) - // - RetrieveEvent_Audit_SubmitServiceProof(blockhash types.Hash) (event.Event_SubmitServiceProof, error) - // - RetrieveEvent_Audit_SubmitIdleVerifyResult(blockhash types.Hash) (event.Event_SubmitIdleVerifyResult, error) - // - RetrieveEvent_Audit_SubmitServiceVerifyResult(blockhash types.Hash) (event.Event_SubmitServiceVerifyResult, error) - // - RetrieveEvent_Oss_OssUpdate(blockhash types.Hash) (event.Event_OssUpdate, error) - // - RetrieveEvent_Oss_OssRegister(blockhash types.Hash) (event.Event_OssRegister, error) - // - RetrieveEvent_Oss_OssDestroy(blockhash types.Hash) (event.Event_OssDestroy, error) - // - RetrieveEvent_Oss_Authorize(blockhash types.Hash) (event.Event_Authorize, error) - // - RetrieveEvent_Oss_CancelAuthorize(blockhash types.Hash) (event.Event_CancelAuthorize, error) - // - RetrieveEvent_FileBank_UploadDeclaration(blockhash types.Hash) (event.Event_UploadDeclaration, error) - // - RetrieveEvent_FileBank_CreateBucket(blockhash types.Hash) (event.Event_CreateBucket, error) - // - RetrieveEvent_FileBank_DeleteFile(blockhash types.Hash) (event.Event_DeleteFile, error) - // - RetrieveEvent_FileBank_TransferReport(blockhash types.Hash) (event.Event_TransferReport, error) - // - RetrieveEvent_FileBank_ClaimRestoralOrder(blockhash types.Hash) (event.Event_ClaimRestoralOrder, error) - // - RetrieveEvent_FileBank_RecoveryCompleted(blockhash types.Hash) (event.Event_RecoveryCompleted, error) - // - RetrieveEvent_FileBank_IdleSpaceCert(blockhash types.Hash) (event.Event_IdleSpaceCert, error) - // - RetrieveEvent_FileBank_ReplaceIdleSpace(blockhash types.Hash) (event.Event_ReplaceIdleSpace, error) - // - RetrieveEvent_FileBank_CalculateReport(blockhash types.Hash) (event.Event_CalculateReport, error) - // - RetrieveEvent_Sminer_Registered(blockhash types.Hash) (event.Event_Registered, error) - // - RetrieveEvent_Sminer_RegisterPoisKey(blockhash types.Hash) (event.Event_RegisterPoisKey, error) - // - RetrieveEvent_Sminer_UpdataIp(blockhash types.Hash) (event.Event_UpdatePeerId, error) - // - RetrieveEvent_Sminer_UpdataBeneficiary(blockhash types.Hash) (event.Event_UpdateBeneficiary, error) - // - RetrieveEvent_Sminer_MinerExitPrep(blockhash types.Hash) (event.Event_MinerExitPrep, error) - // - RetrieveEvent_Sminer_IncreaseCollateral(blockhash types.Hash) (event.Event_IncreaseCollateral, error) - // - RetrieveEvent_Sminer_Receive(blockhash types.Hash) (event.Event_Receive, error) - // - RetrieveEvent_Sminer_Withdraw(blockhash types.Hash) (event.Event_Withdraw, error) - // - RetrieveEvent_Sminer_IncreaseDeclarationSpace(blockhash types.Hash) (event.Event_IncreaseDeclarationSpace, error) - // - RetrieveEvent_StorageHandler_BuySpace(blockhash types.Hash) (event.Event_BuySpace, error) - // - RetrieveEvent_StorageHandler_ExpansionSpace(blockhash types.Hash) (event.Event_ExpansionSpace, error) - // - RetrieveEvent_StorageHandler_RenewalSpace(blockhash types.Hash) (event.Event_RenewalSpace, error) - // - RetrieveEvent_Balances_Transfer(blockhash types.Hash) (types.EventBalancesTransfer, error) - // - RetrieveEvent_FileBank_GenRestoralOrder(blockhash types.Hash) (event.Event_GenerateRestoralOrder, error) - // - RetrieveAllEvent_FileBank_UploadDeclaration(blockhash types.Hash) ([]event.AllUploadDeclarationEvent, error) - // - RetrieveAllEvent_FileBank_StorageCompleted(blockhash types.Hash) ([]string, error) - // - RetrieveAllEvent_FileBank_DeleteFile(blockhash types.Hash) ([]event.AllDeleteFileEvent, error) - // - //RetrieveAllEvent(blockhash types.Hash) ([]string, []string, error) - // - RetrieveAllEventFromBlock(blockhash types.Hash) ([]string, map[string][]string, error) - // - RetrieveBlock(blocknumber uint64) ([]string, []event.ExtrinsicsInfo, []event.TransferInfo, string, string, string, string, int64, error) - // - RetrieveBlockAndAll(blocknumber uint64) ([]string, []event.ExtrinsicsInfo, []event.TransferInfo, []string, []string, string, string, string, string, string, int64, error) - // - ParseBlockData(blocknumber uint64) (event.BlockData, error) - // - InitExtrinsicsName() error -} diff --git a/defaults.go b/defaults.go index fe21937..2f474d9 100755 --- a/defaults.go +++ b/defaults.go @@ -7,7 +7,9 @@ package sdkgo -import "github.com/CESSProject/cess-go-sdk/core/pattern" +import ( + "time" +) // DefaultRpcAddrs configures the default rpc address var DefaultRpcAddrs = func(cfg *Config) error { @@ -21,7 +23,7 @@ var DefaultRpcAddrs = func(cfg *Config) error { // DefaultTimeout configures the default transaction waiting timeout var DefaultTimeout = func(cfg *Config) error { - return cfg.Apply(TransactionTimeout(pattern.BlockInterval)) + return cfg.Apply(TransactionTimeout(time.Second * 30)) } // Complete list of default options and when to fallback on them. diff --git a/example/evm/evm.go b/example/evm/evm.go index c299cee..83407f9 100644 --- a/example/evm/evm.go +++ b/example/evm/evm.go @@ -10,7 +10,6 @@ import ( cess "github.com/CESSProject/cess-go-sdk" "github.com/CESSProject/cess-go-sdk/chain" - "github.com/CESSProject/cess-go-sdk/core/pattern" "github.com/centrifuge/go-substrate-rpc-client/v4/types" ) @@ -42,7 +41,7 @@ func main() { value types.U256 gasLimit types.U64 maxFeePerGas types.U256 - accessList []pattern.AccessInfo + accessList []chain.AccessInfo ) s_h160, err := hex.DecodeString("1e3e1c69dfbd27d398e92da4844a9abdc2786ac0") diff --git a/example/file/file.go b/example/file/file.go index 310d764..36b8362 100755 --- a/example/file/file.go +++ b/example/file/file.go @@ -9,14 +9,12 @@ package main import ( "bytes" - "context" "fmt" "io" "log" "time" - cess "github.com/CESSProject/cess-go-sdk" - "github.com/CESSProject/cess-go-sdk/chain" + "github.com/CESSProject/cess-go-sdk/core/process" ) // Substrate well-known mnemonic: @@ -39,46 +37,28 @@ const UploadFile = "file.go" const BucketName = "myBucket" func main() { - // 1. new sdk - sdk, err := NewSDK() - if err != nil { - panic(err) - } - - // 2. buy space - _, err = sdk.BuySpace(1) - if err != nil { - panic(err) - } - - // 3. authorize space to deoss - _, err = sdk.AuthorizeSpace(PublicGatewayAccount) - if err != nil { - panic(err) - } - - // 4. upload file to deoss - fid, err := sdk.StoreFile(PublicGateway, UploadFile, BucketName) + // upload file to gateway + fid, err := process.StoreFile(PublicGateway, UploadFile, BucketName, MY_MNEMONIC) if err != nil { panic(err) } log.Println("fid:", fid) - // 5. downloag file from deoss - err = sdk.RetrieveFile(PublicGateway, fid, fmt.Sprintf("download_%d", time.Now().UnixNano())) + // downloag file from gateway + err = process.RetrieveFile(PublicGateway, fid, MY_MNEMONIC, fmt.Sprintf("download_%d", time.Now().UnixNano())) if err != nil { panic(err) } - // 6. upload object to deoss - fid, err = sdk.StoreObject(PublicGateway, bytes.NewReader([]byte("test date")), BucketName) + // upload object to gateway + fid, err = process.StoreObject(PublicGateway, BucketName, MY_MNEMONIC, bytes.NewReader([]byte("test date"))) if err != nil { panic(err) } log.Println("fid:", fid) - // 7. download object from deoss - body, err := sdk.RetrieveObject(PublicGateway, fid) + // download object from gateway + body, err := process.RetrieveObject(PublicGateway, fid, MY_MNEMONIC) if err != nil { panic(err) } @@ -89,12 +69,3 @@ func main() { } fmt.Println(string(data)) } - -func NewSDK() (*chain.ChainClient, error) { - return cess.New( - context.Background(), - cess.ConnectRpcAddrs(RPC_ADDRS), - cess.Mnemonic(MY_MNEMONIC), - cess.TransactionTimeout(time.Second*10), - ) -} diff --git a/example/new/sdk.go b/example/new/sdk.go index 487e30e..11094aa 100755 --- a/example/new/sdk.go +++ b/example/new/sdk.go @@ -22,7 +22,8 @@ import ( // Substrate well-known mnemonic: // -// https://github.com/substrate-developer-hub/substrate-developer-hub.github.io/issues/613 +// - cXgaee2N8E77JJv9gdsGAckv1Qsf3hqWYf7NL4q6ZuQzuAUtB +// - https://github.com/substrate-developer-hub/substrate-developer-hub.github.io/issues/613 var MY_MNEMONIC = "bottom drive obey lake curtain smoke basket hold race lonely fit walk" var RPC_ADDRS = []string{ @@ -38,19 +39,18 @@ func main() { sdk, err := cess.New( context.Background(), cess.ConnectRpcAddrs(RPC_ADDRS), - //cess.Mnemonic(MY_MNEMONIC), + cess.Mnemonic(MY_MNEMONIC), cess.TransactionTimeout(time.Second*10), ) if err != nil { panic(err) } - defer sdk.GetSubstrateAPI().Client.Close() + defer sdk.Close() - fmt.Println(sdk.ChainVersion()) + fmt.Println(sdk.SystemVersion()) fmt.Println(sdk.InitExtrinsicsName()) fmt.Println(sdk.GetCurrentRpcAddr()) - // - fmt.Println(sdk.QueryRoundReward(0, -1)) + return blockhash, err := sdk.GetSubstrateAPI().RPC.Chain.GetBlockHash(180) diff --git a/example/other/main.go b/example/other/main.go deleted file mode 100644 index d9f5ca3..0000000 --- a/example/other/main.go +++ /dev/null @@ -1,148 +0,0 @@ -/* - Copyright (C) CESS. All rights reserved. - Copyright (C) Cumulus Encrypted Storage System. All rights reserved. - - SPDX-License-Identifier: Apache-2.0 -*/ - -package main - -import ( - "errors" - "fmt" - "log" - - gsrpc "github.com/centrifuge/go-substrate-rpc-client/v4" - "github.com/centrifuge/go-substrate-rpc-client/v4/types" - "github.com/centrifuge/go-substrate-rpc-client/v4/types/codec" - "github.com/centrifuge/go-substrate-rpc-client/v4/xxhash" - "github.com/decred/base58" - "golang.org/x/crypto/blake2b" -) - -var RPC_ADDRS = []string{ - //testnet - "wss://testnet-rpc0.cess.cloud/ws/", - "wss://testnet-rpc1.cess.cloud/ws/", - "wss://testnet-rpc2.cess.cloud/ws/", -} - -func main() { - accounts, err := GetAllAccountInfoFromBlock(1) - if err != nil { - log.Fatal(err) - } - fmt.Println(len(accounts), " : ", accounts) -} - -func GetAllAccountInfoFromBlock(block int) ([]types.AccountInfo, error) { - var ( - err error - c *gsrpc.SubstrateAPI - ) - for i := 0; i < len(RPC_ADDRS); i++ { - c, err = gsrpc.NewSubstrateAPI(RPC_ADDRS[i]) - if err == nil { - break - } - } - if c == nil { - log.Fatal("all rpc addresses are unavailable") - } - - defer c.Client.Close() - - var data []types.AccountInfo - - key := createPrefixedKey("System", "Account") - - // get all account information from the latest block - if block < 0 { - keys, err := c.RPC.State.GetKeysLatest(key) - if err != nil { - return nil, err - } - set, err := c.RPC.State.QueryStorageAtLatest(keys) - if err != nil { - return nil, err - } - for _, elem := range set { - for _, change := range elem.Changes { - var storageData types.AccountInfo - if err := codec.Decode(change.StorageData, &storageData); err != nil { - fmt.Println("Decode StorageData:", err) - continue - } - var storageKey types.AccountID - if err := codec.Decode(change.StorageKey, &storageKey); err != nil { - fmt.Println("Decode StorageKey:", err) - continue - } - fmt.Println(encodePublicKeyAsAccount(storageKey[:])) - data = append(data, storageData) - } - } - return data, nil - } - - // get all account information from the block - - blockhash, err := c.RPC.Chain.GetBlockHash(uint64(block)) - if err != nil { - return data, err - } - - keys, err := c.RPC.State.GetKeys(key, blockhash) - if err != nil { - return nil, err - } - set, err := c.RPC.State.QueryStorageAt(keys, blockhash) - if err != nil { - return nil, err - } - for _, elem := range set { - for _, change := range elem.Changes { - if change.HasStorageData { - var storageData types.AccountInfo - if err := codec.Decode(change.StorageData, &storageData); err != nil { - fmt.Println("Decode StorageData err:", err) - continue - } - var storageKey types.AccountID - if err := codec.Decode(change.StorageKey, &storageKey); err != nil { - fmt.Println("Decode StorageKey err:", err) - continue - } - fmt.Println(encodePublicKeyAsAccount(storageKey[:])) - data = append(data, storageData) - } - } - } - return data, nil -} - -func createPrefixedKey(pallet, method string) []byte { - return append(xxhash.New128([]byte(pallet)).Sum(nil), xxhash.New128([]byte(method)).Sum(nil)...) -} - -func encodePublicKeyAsAccount(publicKey []byte) (string, error) { - if len(publicKey) != 32 { - return "", errors.New("invalid public key") - } - payload := appendBytes([]byte{0x50, 0xac}, publicKey) - input := appendBytes([]byte{0x53, 0x53, 0x35, 0x38, 0x50, 0x52, 0x45}, payload) - ck := blake2b.Sum512(input) - checkum := ck[:2] - address := base58.Encode(appendBytes(payload, checkum)) - if address == "" { - return address, errors.New("public key encoding failed") - } - return address, nil -} - -func appendBytes(data1, data2 []byte) []byte { - if data2 == nil { - return data1 - } - return append(data1, data2...) -} diff --git a/example/parseEvent/parseevent.go b/example/parseEvent/parseevent.go index 8de3144..7e314e6 100755 --- a/example/parseEvent/parseevent.go +++ b/example/parseEvent/parseevent.go @@ -6,7 +6,7 @@ import ( "time" cess "github.com/CESSProject/cess-go-sdk" - "github.com/CESSProject/cess-go-sdk/core/event" + "github.com/CESSProject/cess-go-sdk/chain" "github.com/centrifuge/go-substrate-rpc-client/v4/types" ) @@ -26,7 +26,7 @@ var RPC_ADDRS = []string{ } type MyEvent struct { - Sminer_FaucetTopUpMoney []event.Event_FaucetTopUpMoney + Sminer_FaucetTopUpMoney []chain.Event_FaucetTopUpMoney types.EventRecords } diff --git a/example/process/process.go b/example/process/process.go index 2c9d518..2c741ed 100755 --- a/example/process/process.go +++ b/example/process/process.go @@ -11,13 +11,13 @@ import ( "fmt" "log" - "github.com/CESSProject/cess-go-sdk/core/pattern" + "github.com/CESSProject/cess-go-sdk/chain" "github.com/CESSProject/cess-go-sdk/core/process" ) type result struct { Fid string - SegmentData []pattern.SegmentDataInfo + SegmentData []chain.SegmentDataInfo } func main() { diff --git a/go.mod b/go.mod index 7b854c8..70c82d3 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,9 @@ module github.com/CESSProject/cess-go-sdk go 1.20 require ( - github.com/CESSProject/go-keyring v0.0.0-20220614131247-ee3a8da30fde github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce github.com/cbergoon/merkletree v0.2.0 github.com/centrifuge/go-substrate-rpc-client/v4 v4.2.1 - github.com/decred/base58 v1.0.4 github.com/ethereum/go-ethereum v1.10.20 github.com/go-ping/ping v1.1.0 github.com/google/uuid v1.5.0 @@ -26,9 +24,12 @@ require ( require ( github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect + github.com/btcsuite/btcd v0.22.0-beta // indirect + github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/deckarep/golang-set v1.8.0 // indirect + github.com/decred/base58 v1.0.4 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/go-ole/go-ole v1.2.6 // indirect diff --git a/go.sum b/go.sum index 1ad9f28..9968d4f 100644 --- a/go.sum +++ b/go.sum @@ -1,18 +1,20 @@ -github.com/CESSProject/go-keyring v0.0.0-20220614131247-ee3a8da30fde h1:5MDRjjtg6PEhqyVjupwaapN96cOZiddOGAYwKQeaTu0= -github.com/CESSProject/go-keyring v0.0.0-20220614131247-ee3a8da30fde/go.mod h1:RUXBd3ROP98MYepEEa0Y0l/T0vQlIKqFJxI/ocdnRLM= github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRrLeDnvGIM= github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= +github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= +github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/cbergoon/merkletree v0.2.0 h1:Bttqr3OuoiZEo4ed1L7fTasHka9II+BF9fhBfbNEEoQ= @@ -36,6 +38,7 @@ github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5il github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/ethereum/go-ethereum v1.10.20 h1:75IW830ClSS40yrQC1ZCMZCt5I+zU16oqId2SiQwdQ4= github.com/ethereum/go-ethereum v1.10.20/go.mod h1:LWUN82TCHGpxB3En5HVmLLzPD7YSrEUFmFfN1nKkVN0= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -59,6 +62,7 @@ github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uM github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= @@ -78,6 +82,7 @@ github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/pierrec/xxHash v0.1.5 h1:n/jBpwTHiER4xYvK3/CdPVnLDPchj8eTJFFLUb4QHBo= github.com/pierrec/xxHash v0.1.5/go.mod h1:w2waW5Zoa/Wc4Yqe0wgrIYAGKqRMf7czn2HNKXmuL+I= @@ -119,11 +124,13 @@ golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20240213143201-ec583247a57a h1:HinSgX1tJRX3KsL//Gxynpw5CTOAIPhgL4W8PNiIpVE= golang.org/x/exp v0.0.0-20240213143201-ec583247a57a/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= diff --git a/options.go b/options.go index 29090ef..258d122 100755 --- a/options.go +++ b/options.go @@ -10,7 +10,7 @@ package sdkgo import ( "time" - "github.com/CESSProject/cess-go-sdk/core/pattern" + "github.com/CESSProject/cess-go-sdk/chain" ) // ConnectRpcAddrs configuration rpc address @@ -32,8 +32,8 @@ func Mnemonic(mnemonic string) Option { // TransactionTimeout configures the waiting timeout for a transaction func TransactionTimeout(timeout time.Duration) Option { return func(cfg *Config) error { - if timeout < pattern.BlockInterval { - cfg.Timeout = pattern.BlockInterval + if timeout < chain.BlockInterval { + cfg.Timeout = chain.BlockInterval } else { cfg.Timeout = timeout } diff --git a/sdk.go b/sdk.go index 0469a16..e5a32d2 100755 --- a/sdk.go +++ b/sdk.go @@ -11,15 +11,8 @@ import ( "context" "github.com/CESSProject/cess-go-sdk/chain" - "github.com/CESSProject/cess-go-sdk/config" ) -// Config describes a set of settings for the sdk. -type Config = config.Config - -// Option is a client config option that can be given to the client constructor -type Option = config.Option - // New constructs a new sdk client with the given options, falling back on // reasonable defaults. The defaults are: // @@ -30,11 +23,6 @@ type Option = config.Option // timeout: time.Duration(time.Second * 6) // // - The serviceName is used to specify the name of your service -// Warning: -// -// cess-bucket (cess storage service) must be set to bucket -// DeOSS (cess decentralized object storage service) must be set to deoss -// cess-cli (cess client) must be set to client func New(ctx context.Context, opts ...Option) (*chain.ChainClient, error) { return NewWithoutDefaults(ctx, append(opts, FallbackDefaults)...) } diff --git a/utils/bucket.go b/utils/bucket.go index 758fb03..49701fd 100755 --- a/utils/bucket.go +++ b/utils/bucket.go @@ -11,13 +11,13 @@ import ( "regexp" "strings" - "github.com/CESSProject/cess-go-sdk/core/pattern" + "github.com/CESSProject/cess-go-sdk/config" ) var re = regexp.MustCompile(`^[a-zA-Z0-9._-]+$`) func CheckBucketName(name string) bool { - if len(name) < pattern.MinBucketNameLength || len(name) > pattern.MaxBucketNameLength { + if len(name) < config.MinBucketNameLength || len(name) > config.MaxBucketNameLength { return false } diff --git a/utils/sign.go b/utils/sign.go new file mode 100644 index 0000000..746a76d --- /dev/null +++ b/utils/sign.go @@ -0,0 +1,132 @@ +/* + Copyright (C) CESS. All rights reserved. + Copyright (C) Cumulus Encrypted Storage System. All rights reserved. + + SPDX-License-Identifier: Apache-2.0 +*/ + +package utils + +import ( + "encoding/hex" + "errors" + "fmt" + "strconv" + "strings" + + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" + "github.com/vedhavyas/go-subkey/sr25519" +) + +// SignedSR25519WithMnemonic sign sr25519 with mnemonic +// - mnemonic: polkadot account mnemonic +// - msg: message +// +// Return: +// - []byte: sr25519 signature +// - error: error message +func SignedSR25519WithMnemonic(mnemonic string, msg string) ([]byte, error) { + if len(msg) <= 0 { + return nil, errors.New("SignedSR25519WithMnemonic: empty msg") + } + pri, err := sr25519.Scheme{}.FromPhrase(mnemonic, "") + if err != nil { + return nil, errors.New("SignedSR25519WithMnemonic: invalid mnemonic") + } + return pri.Sign([]byte(msg)) +} + +// VerifySR25519WithPublickey verify sr25519 signature with account public key +// - msg: message +// - sign: sr25519 signature +// - account: polkadot account +// +// Return: +// - bool: verification result +// - error: error message +func VerifySR25519WithPublickey(msg string, sign []byte, account string) (bool, error) { + if len(sign) <= 0 { + return false, errors.New("VerifySR25519WithPublickey: empty sign") + } + pk, err := ParsingPublickey(account) + if err != nil { + return false, errors.New("VerifySR25519WithPublickey: invalid account") + } + public, err := sr25519.Scheme{}.FromPublicKey(pk) + if err != nil { + return false, err + } + ok := public.Verify([]byte(msg), sign) + return ok, err +} + +// VerifyPolkadotJsHexSign verify signature signed with polkadot.js +// - account: polkadot account +// - msg: message +// - sign: signature +// +// Return: +// - bool: verification result +// - error: error message +// +// Tip: +// - https://polkadot.js.org/apps/#/signing +func VerifyPolkadotJsHexSign(account, msg, signature string) (bool, error) { + if len(msg) == 0 { + return false, errors.New("msg is empty") + } + + pkey, err := ParsingPublickey(account) + if err != nil { + return false, err + } + + pub, err := sr25519.Scheme{}.FromPublicKey(pkey) + if err != nil { + return false, err + } + + sign_bytes, err := hex.DecodeString(strings.TrimPrefix(signature, "0x")) + if err != nil { + return false, err + } + message := fmt.Sprintf("%s", msg) + ok := pub.Verify([]byte(message), sign_bytes) + return ok, nil +} + +// ParseEthAccFromEthSign parsing eth account public key from eth account signature +// - message: message +// - sign: eth signature +// +// Return: +// - string: eth account +// - error: error message +func ParseEthAccFromEthSign(message string, sign string) (string, error) { + // Hash the unsigned message using EIP-191 + hashedMessage := []byte("\x19Ethereum Signed Message:\n" + strconv.Itoa(len(message)) + message) + hash := crypto.Keccak256Hash(hashedMessage) + + // Get the bytes of the signed message + decodedMessage, err := hexutil.Decode(sign) + if err != nil { + return "", err + } + + // Handles cases where EIP-115 is not implemented (most wallets don't implement it) + if decodedMessage[64] == 27 || decodedMessage[64] == 28 { + decodedMessage[64] -= 27 + } + + // Recover a public key from the signed message + sigPublicKeyECDSA, err := crypto.SigToPub(hash.Bytes(), decodedMessage) + if sigPublicKeyECDSA == nil { + err = errors.New("could not get a public get from the message signature") + } + if err != nil { + return "", err + } + + return crypto.PubkeyToAddress(*sigPublicKeyECDSA).String(), nil +} diff --git a/utils/typ.go b/utils/typ.go deleted file mode 100644 index 248d78d..0000000 --- a/utils/typ.go +++ /dev/null @@ -1,68 +0,0 @@ -/* - Copyright (C) CESS. All rights reserved. - Copyright (C) Cumulus Encrypted Storage System. All rights reserved. - - SPDX-License-Identifier: Apache-2.0 -*/ - -package utils - -import ( - "errors" - - "github.com/CESSProject/cess-go-sdk/core/pattern" - "github.com/centrifuge/go-substrate-rpc-client/v4/types" -) - -func BytesToFileHash(val []byte) (pattern.FileHash, error) { - if len(val) != pattern.FileHashLen { - return pattern.FileHash{}, errors.New("[BytesToFileHash] invalid length") - } - var filehash pattern.FileHash - for k, v := range val { - filehash[k] = types.U8(v) - } - return filehash, nil -} - -func BytesToWorkPublickey(val []byte) (pattern.WorkerPublicKey, error) { - if len(val) != pattern.WorkerPublicKeyLen { - return pattern.WorkerPublicKey{}, errors.New("[BytesToWorkPublickey] invalid length") - } - var pubkey pattern.WorkerPublicKey - for k, v := range val { - pubkey[k] = types.U8(v) - } - return pubkey, nil -} - -func BytesToPoISKeyInfo(g, n []byte) (pattern.PoISKeyInfo, error) { - if len(g) != pattern.PoISKeyLen || len(n) != pattern.PoISKeyLen { - return pattern.PoISKeyInfo{}, errors.New("[BytesToPoISKeyInfo] invalid length") - } - var poisKey pattern.PoISKeyInfo - for i := 0; i < pattern.PoISKeyLen; i++ { - poisKey.G[i] = types.U8(g[i]) - poisKey.N[i] = types.U8(n[i]) - } - return poisKey, nil -} -func BytesToBloomFilter(val []byte) (pattern.BloomFilter, error) { - if len(val) != pattern.BloomFilterLen { - return pattern.BloomFilter{}, errors.New("[BytesToBloomFilter] invalid length") - } - var bloomfilter pattern.BloomFilter - for i := 0; i < pattern.BloomFilterLen; i++ { - bloomfilter[i] = types.U64(val[i]) - } - return bloomfilter, nil -} - -func IsWorkerPublicKeyAllZero(puk pattern.WorkerPublicKey) bool { - for i := 0; i < pattern.WorkerPublicKeyLen; i++ { - if puk[i] != 0 { - return false - } - } - return true -} diff --git a/version.go b/version.go index 3144802..139d097 100755 --- a/version.go +++ b/version.go @@ -8,4 +8,4 @@ package sdkgo // SDK Version -const Version = "0.5.0.25" +const Version = "0.5.2"