Skip to content

Commit

Permalink
Base gen (#64)
Browse files Browse the repository at this point in the history
* update CharacterName

* update sdk

* update examples

* update readme
  • Loading branch information
AstaFrode authored Jun 5, 2023
1 parent aa1a3e4 commit 311df94
Show file tree
Hide file tree
Showing 12 changed files with 146 additions and 289 deletions.
63 changes: 22 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

</div>

The go sdk implementation of the CESS network, which provides RPC calls, status queries, and access to the p2p storage network of the CESS chain.
The go sdk implementation of the CESS network, which provides RPC calls, status queries, block transactions and other functions.

## Reporting a Vulnerability
If you find out any vulnerability, Please send an email to [email protected], we are happy to communicate with you.
Expand All @@ -16,69 +16,50 @@ To get the package use the standard:
```
go get -u "github.com/CESSProject/sdk-go"
```
Using Go modules is recommended.

## Documentation & Examples
Please refer to https://pkg.go.dev/github.com/CESSProject/sdk-go

## Usage
Usually, you only care about how to access your data in the CESS network, you need to build such a web service yourself, this sdk will help you quickly realize data access.
Usually, you only care about how to access your data in the CESS network, you need to build such a web service yourself, this sdk will help you quickly realize data access.Note that the [p2p-go library](https://github.com/CESSProject/p2p-go) needs to be used to complete the data transmission.


#### Create an sdk client instance
The following is an example of creating an sdk client:
To create an sdk client, you need to provide some configuration information: your rpc address (if not, use the rpc address disclosed by CESS), your wallet private key, and transaction timeout. Please refer to the following examples:
```
cli, err := New(
config.DefaultName,
ConnectRpcAddrs([]string{""}),
ListenPort(15000),
Workspace("/"),
Mnemonic("xxx xxx ... xxx"),
TransactionTimeout(time.Duration(time.Second*10)),
config.CharacterName_Client,
ConnectRpcAddrs([]string{"wss://testnet-rpc0.cess.cloud/ws/", "wss://testnet-rpc1.cess.cloud/ws/"}),
Mnemonic("xxx xxx ... xxx"),
TransactionTimeout(time.Duration(time.Second*10)),
)
```
Creating a client requires you to configure some information, you can refer to the following configuration files:
```
# The rpc endpoint of the chain node
Rpc:
- "ws://127.0.0.1:9948/"
- "wss://testnet-rpc0.cess.cloud/ws/"
- "wss://testnet-rpc1.cess.cloud/ws/"
# Account mnemonic
Mnemonic: "xxx xxx xxx"
# Service workspace
Workspace: /
# Service running address
Address: "127.0.0.1"
# P2P communication port
P2P_Port: 8088
# Service listening port
HTTP_Port: 15000
```

#### Register as an oss role
Call the Register method to register. Note that the first parameter specifies that the role you register is oss, and its value can be any one of "oss","OSS","Deoss","DEOSS".
#### Register as a deoss role
Call the Register method to register. Note that the first parameter specifies that the role you register is deoss, If there is no error, you can view the transaction details through the returned transaction hash.
```
txhash, err := cli.Register("oss", "", 0)
txhash, _, err := cli.Register(cli.GetCharacterName(), cli.GetSignatureAccPulickey(), "", 0)
```

#### Process your documents according to the specifications of CESS
#### Process data according to the specifications of CESS
Call the ProcessingData method to process your file. You need to specify the file path. The method returns a segment list and the unique identifier hash of the file in the CESS network.
```
segmentInfo, roothash, err := cli.ProcessingData(filepath)
```

#### Store your files
Call the PutFile method to store your files. You need to specify a bucket to store the files. CESS will automatically create the bucket for you, provided that the name of the bucket is legal. You can call the CheckBucketName method in advance to check whether the name of the bucket meets the requirements.
After the storage is successful, it will return `count`. The `count` indicates the number of times your file is stored. A file can only be stored up to 5 times. If your file is not stored successfully after 5 times, you need to upload your file again.
#### Create storage order
Before storing data, you also need to create a data storage order, and you need to fill in the roothash and segmentInfo obtained in the previous step, as well as the user account for uploading data, data name, and bucket name.
```
count, err := cli.PutFile(publickey, segmentInfo, roothash, filename, buckname)
err := cli.GenerateStorageOrder(roothash, segmentInfo, owner, filename, bucketname)
```

#### Download file
Call the GetFile method to download the file you want, and this method will save the file you downloaded under the roothash name in the directory you specify.
```
filepath, err := n.Cli.GetFile(roothash, dir)
```
#### Store data to storage nodes
After creating the storage order, wait for one block to find the storage node information allocated in the order. The next step is to store the data to the storage node through the `WriteFileAction` method in the [p2p-go library](https://github.com/CESSProject/p2p-go).

After the storage node receives the data, it will automatically report this action. When all the storage nodes in the storage order have all reported, the data is considered to be stored successfully. As long as there is a storage node that does not report, it is regarded as a storage failure. After the timeout period in the order is exceeded, the storage nodes in the order will be reassigned randomly to start a new round of storage. You need to monitor this storage order, and re-give the data block to the newly allocated storage node until the data storage is successful. The `count` in the storage order indicates the number of times your data has been redistributed. An order can redistribute storage up to 5 times. If your data is still not successfully stored after 5 times, you need to re-upload your data.

#### Fetch your data
Call the `ReadFileAction` method in the [p2p-go library](https://github.com/CESSProject/p2p-go) to download all data blocks, and then restore the original data through the `ReedSolomon_Restore` method.

## License
Licensed under [Apache 2.0](https://github.com/CESSProject/sdk-go/blob/main/LICENSE)
10 changes: 9 additions & 1 deletion chain/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ import (
)

func (c *ChainSDK) QueryAssignedProof() ([][]pattern.ProofAssignmentInfo, error) {
defer func() {
if err := recover(); err != nil {
log.Println(utils.RecoverError(err))
}
}()
if !c.GetChainState() {
return nil, pattern.ERR_RPC_CONNECTION
}
var list [][]pattern.ProofAssignmentInfo
key := createPrefixedKey(pattern.AUDIT, pattern.UNVERIFYPROOF)
keys, err := c.api.RPC.State.GetKeysLatest(key)
Expand Down Expand Up @@ -47,7 +55,7 @@ func (c *ChainSDK) QueryAssignedProof() ([][]pattern.ProofAssignmentInfo, error)
func (c *ChainSDK) QueryTeeAssignedProof(puk []byte) ([]pattern.ProofAssignmentInfo, error) {
defer func() {
if err := recover(); err != nil {
log.Panicln(utils.RecoverError(err))
log.Println(utils.RecoverError(err))
}
}()
var data []pattern.ProofAssignmentInfo
Expand Down
39 changes: 14 additions & 25 deletions chain/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
package chain

import (
"fmt"
"io"
"log"
"os"
Expand Down Expand Up @@ -37,22 +36,18 @@ type ChainSDK struct {
rpcAddr []string
timeForBlockOut time.Duration
tokenSymbol string
stakingAcc string
signatureAcc string
name string
}

var _ sdk.SDK = (*ChainSDK)(nil)

func NewChainSDK(rpcs []string, name, mnemonic string, t time.Duration) (*ChainSDK, error) {
func NewChainSDK(name string, rpcs []string, mnemonic string, t time.Duration) (*ChainSDK, error) {
var (
err error
chainSDK = &ChainSDK{}
)

if name == "" {
return nil, fmt.Errorf("empty name")
}

defer log.SetOutput(os.Stdout)
log.SetOutput(io.Discard)

Expand Down Expand Up @@ -88,7 +83,7 @@ func NewChainSDK(rpcs []string, name, mnemonic string, t time.Duration) (*ChainS
if err != nil {
return nil, err
}
chainSDK.stakingAcc, err = utils.EncodePublicKeyAsCessAccount(chainSDK.keyring.PublicKey)
chainSDK.signatureAcc, err = utils.EncodePublicKeyAsCessAccount(chainSDK.keyring.PublicKey)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -133,30 +128,16 @@ func (c *ChainSDK) GetChainState() bool {
return c.chainState.Load()
}

func (c *ChainSDK) NewAccountId(pubkey []byte) types.AccountID {
acc, _ := types.NewAccountID(pubkey)
return *acc
}

func (c *ChainSDK) GetSignatureAcc() string {
acc, _ := utils.EncodePublicKeyAsCessAccount(c.keyring.PublicKey)
return acc
return c.signatureAcc
}

func (c *ChainSDK) GetKeyEvents() types.StorageKey {
return c.keyEvents
}

// ExtractAccountPublickey
func (c *ChainSDK) ExtractAccountPuk(account string) ([]byte, error) {
if account != "" {
return utils.ParsingPublickey(account)
}
return c.keyring.PublicKey, nil
}

func (c *ChainSDK) GetSignatureURIs() string {
return c.keyring.URI
func (c *ChainSDK) GetSignatureAccPulickey() []byte {
return c.keyring.PublicKey
}

func (c *ChainSDK) GetSubstrateAPI() *gsrpc.SubstrateAPI {
Expand All @@ -171,10 +152,18 @@ func (c *ChainSDK) GetTokenSymbol() string {
return c.tokenSymbol
}

func (c *ChainSDK) GetCharacterName() string {
return c.name
}

func (c *ChainSDK) Sign(msg []byte) ([]byte, error) {
return signature.Sign(msg, c.keyring.URI)
}

func (c *ChainSDK) Verify(msg []byte, sig []byte) (bool, error) {
return signature.Verify(msg, sig, c.keyring.URI)
}

func reconnectChainSDK(rpcAddr []string) (*gsrpc.SubstrateAPI, error) {
var err error
var api *gsrpc.SubstrateAPI
Expand Down
2 changes: 1 addition & 1 deletion chain/deoss.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
func (c *ChainSDK) QueryDeoss(pubkey []byte) ([]byte, error) {
defer func() {
if err := recover(); err != nil {
log.Panicln(utils.RecoverError(err))
log.Println(utils.RecoverError(err))
}
}()
var data pattern.PeerId
Expand Down
9 changes: 4 additions & 5 deletions chain/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func (c *ChainSDK) ProcessingData(path string) ([]pattern.SegmentDataInfo, strin
return nil, "", err
}
if fstat.IsDir() {
return nil, "", errors.New("Not a file")
return nil, "", errors.New("not a file")
}

baseDir := filepath.Dir(path)
Expand Down Expand Up @@ -116,7 +116,7 @@ func (c *ChainSDK) ProcessingData(path string) ([]pattern.SegmentDataInfo, strin
return segment, hex.EncodeToString(hTree.MerkleRoot()), err
}

func (c *ChainSDK) GenerateStorageOrder(roothash string, segment []pattern.SegmentDataInfo, owner []byte, filename, buckname string) error {
func (c *ChainSDK) GenerateStorageOrder(roothash string, segment []pattern.SegmentDataInfo, owner []byte, filename, buckname string) (string, error) {
var err error
var segmentList = make([]pattern.SegmentList, len(segment))
var user pattern.UserBrief
Expand All @@ -135,13 +135,12 @@ func (c *ChainSDK) GenerateStorageOrder(roothash string, segment []pattern.Segme
}
acc, err := types.NewAccountID(owner)
if err != nil {
return err
return "", err
}
user.User = *acc
user.BucketName = types.NewBytes([]byte(buckname))
user.FileName = types.NewBytes([]byte(filename))
_, err = c.UploadDeclaration(roothash, segmentList, user)
return err
return c.UploadDeclaration(roothash, segmentList, user)
}

func ExtractSegmenthash(segment []pattern.SegmentDataInfo) []string {
Expand Down
113 changes: 1 addition & 112 deletions chain/role.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func (c *ChainSDK) Register(role string, puk []byte, earnings string, pledge uin
if err != nil {
return txhash, acc, err
}
txhash, err = c.updateIncomeAcc(key, puk)
txhash, err = c.updateEarningsAcc(key, puk)
return txhash, earnings, err
}
}
Expand Down Expand Up @@ -194,117 +194,6 @@ func (c *ChainSDK) Register(role string, puk []byte, earnings string, pledge uin
}
}

func (c *ChainSDK) UpdateAddress(role, multiaddr string) (string, error) {
c.lock.Lock()
defer func() {
c.lock.Unlock()
if err := recover(); err != nil {
log.Println(utils.RecoverError(err))
}
}()

var (
err error
txhash string
call types.Call
accountInfo types.AccountInfo
)

if !c.GetChainState() {
return txhash, pattern.ERR_RPC_CONNECTION
}

switch role {
case pattern.Role_OSS, pattern.Role_DEOSS, "deoss", "oss", "Deoss", "DeOSS":
call, err = types.NewCall(c.metadata, pattern.TX_OSS_UPDATE, types.NewBytes([]byte(multiaddr)))
if err != nil {
return txhash, errors.Wrap(err, "[NewCall]")
}
case pattern.Role_BUCKET, "SMINER", "bucket", "Bucket", "Sminer", "sminer":
call, err = types.NewCall(c.metadata, pattern.TX_SMINER_UPDATEPEERID, types.NewBytes([]byte(multiaddr)))
if err != nil {
return txhash, errors.Wrap(err, "[NewCall]")
}
default:
return "", fmt.Errorf("Invalid role name")
}

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]")
}
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 {
return txhash, errors.Wrap(err, "[SubmitAndWatchExtrinsic]")
}
defer sub.Unsubscribe()

timeout := time.NewTimer(c.timeForBlockOut)
defer timeout.Stop()

for {
select {
case status := <-sub.Chan():
if status.IsInBlock {
events := event.EventRecords{}
txhash, _ = codec.EncodeToHex(status.AsInBlock)
h, err := c.api.RPC.State.GetStorageRaw(c.keyEvents, status.AsInBlock)
if err != nil {
return txhash, errors.Wrap(err, "[GetStorageRaw]")
}
err = types.EventRecordsRaw(*h).DecodeEventRecords(c.metadata, &events)
if err != nil {
return txhash, nil
}
switch role {
case pattern.Role_OSS, pattern.Role_DEOSS, "deoss", "oss", "Deoss", "DeOSS":
if len(events.Oss_OssUpdate) > 0 {
return txhash, nil
}
case pattern.Role_BUCKET, "SMINER", "bucket", "Bucket", "Sminer", "sminer":
if len(events.Sminer_UpdataIp) > 0 {
return txhash, nil
}
default:
return txhash, errors.New(pattern.ERR_Failed)
}
}
case err = <-sub.Err():
return txhash, errors.Wrap(err, "[sub]")
case <-timeout.C:
return txhash, pattern.ERR_RPC_TIMEOUT
}
}
}

func (c *ChainSDK) updateAddress(key types.StorageKey, name string, peerid pattern.PeerId) (string, error) {
var (
err error
Expand Down
Loading

0 comments on commit 311df94

Please sign in to comment.