diff --git a/docs/architecture/04-storage_provider_management.md b/docs/architecture/04-storage_provider_management.md index e69de29bb..810af5112 100644 --- a/docs/architecture/04-storage_provider_management.md +++ b/docs/architecture/04-storage_provider_management.md @@ -0,0 +1,195 @@ +# Storage Provider Management + +## Abstract + +SPs play a different role from Greenfield validators, although the same organizations or individuals can run both SPs +and validators if they follow all the rules and procedures to get elected. + +The SP module is responsible for managing and maintaining several storage providers in the BNB Greenfield Decentralize +Storage. + +- Metadata: The basic information about the SP, including address, tokens, status, and so on. +- Deposit: Each SP who wants to join the storage network should stake tokens to ensure that it can provide storage +services normally +- Slash: The data stored on the SP will be challenged from time to time. When a challenge is successful, the SP will be +slashed, and deduct some tokens. +- Reputation: We will introduce a reputation system to evaluate SP's service quality. Users can choose which SP to store +data based on reputation score. +- Exit: The storage provider has the right to out of the service and gets back the staked tokens. When the storage +provider has insufficient staked tokens or the reputation score is too low, InscriptionChain will force the storage +provider to exit the storage network. + +## Key Workflow + +### Join the network + +SPs have to register themselves first by depositing on the Greenfield blockchain as their "Service Stake". Greenfield +validators will go through a dedicated governance procedure to vote for the SPs of their election. SPs are encouraged to +advertise their information and prove to the community their capability, as SPs have to provide a professional storage +system with high-quality SLA. + +It will takes several transactions to join the greenfield storage network for storage provider. + +1. The funding account of sp should grant the governance module account to deduct tokens for staking. +2. The sp submit a `CreateStorageProvider` proposal to governance module +3. Deposit enough tokens for this proposal +4. The validators should vote for this proposal. Pass or reject. +5. When enough validators vote the proposal, then the storage provider will be auto created on chain. + +### Leave the network + +When the SPs join and leave the network, they have to follow a series of actions to ensure data redundancy for the +users; otherwise, their "Service Stake" will be fined. This is achieved through the data availability challenge and +validator governance votes. + +### Reputation + +We'll introduce a reputation system for storage provider to evaluate the quality of service of SP. + +## State + +### StorageProvider + +Storage Provider can be ont of several statuses: + +* `STATUS_IN_SERVICE`: The sp is in service. it can serve user's Create/Upload/Download request. +* `STATUS_IN_JAILED`: The sp was been slashed many times, and its deposit tokens is insufficient. +* `STATUS_GRACEFUL_EXITING`: The SP is exiting gracefully. All the object stored in it will be shifted to another sp. +* `STATUS_OUT_OF_SERVICE`: The SP is out of service. it can be a short-lived service unavailable. Users are unable + to store or get payload data on it. + +Storage providers metadata should be primarily stored and accessed by the `OperatorAddr`, an EIP712 account address +for the operator of the storage provider. Three additional indices are maintained per storage provider metadata in +order to fulfill required lookups for SealObject/Deposit/Slash/GetApproval. + +* StorageProvider: `0x21 | OperatorAddr -> ProtocolBuffer(StorageProvider)` +* StorageProviderByFundingAddress: `0x22 | FundingAddress -> OperatorAddr` +* StorageProviderBySealAddress: `0x23 | SealAddress -> OperatorAddr` +* StorageProviderByApprovalAddress: `0x24 | ApprovalAddress -> OperatorAddr` + +Each storage provider's state is stored in a `StorageProvider` struct. + +```protobuf +message StorageProvider { + option (gogoproto.equal) = false; + option (gogoproto.goproto_stringer) = false; + + // operator_address defines the address of the sp's operator; It also is the unqiue index key of sp. + string operator_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // fund_address is the account address of the storage provider for deposit, remuneration. + string funding_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // seal_address is the account address of the storage provider for sealObject + string seal_address = 3 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // approval_address is the account address of the storage provider for ack CreateBuclet/Object. + string approval_address = 4 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // total_deposit define the deposit token + string total_deposit = 5 [ + (cosmos_proto.scalar) = "cosmos.Int", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; + // status is the status of sp, which can be (in_service/read_only_service/graceful_exiting/out_of_service) + Status status = 6; + // endpoint is the service address of the storage provider + string endpoint = 7; + // description defines the description terms for the validator. + Description description = 8 [(gogoproto.nullable) = false]; +} +``` + +### Params +Params is a module-wide configuration structure that stores system parameters +and defines overall functioning of the sp module. + +```protobuf +// Params defines the parameters for the module. +message Params { + option (gogoproto.equal) = true; + option (gogoproto.goproto_stringer) = false; + + // deposit_denom defines the staking coin denomination. + string deposit_denom = 1; + // min_deposit_amount defines the minimum deposit amount for storage providers. + string min_deposit = 2 [ + (cosmos_proto.scalar) = "cosmos.Int", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int", + (gogoproto.nullable) = false + ]; +} +``` + +### Deposit Pool + +Sp module use its module account to manage all the staking tokens which deposit by storage providers. + +## Message + +### MsgCreateStorageProvider + +A storage provider is created using the `MsgCreateProvider` messages. + +```protobuf +message MsgCreateStorageProvider { + option (cosmos.msg.v1.signer) = "creator"; + + string creator = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + Description description = 2 [(gogoproto.nullable) = false]; + string sp_address = 3 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + string funding_address = 4 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + string seal_address = 5 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + string approval_address = 6 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + string endpoint = 7; + cosmos.base.v1beta1.Coin deposit = 8 [(gogoproto.nullable) = false]; +} +``` + +This message is expected to fail if: + +* another storage provider with this operator/seal/funding/approval address is already registered. +* the initial deposit tokens are of a denom not specified as the deposit denom of sp module +* the deposit tokens is insufficient + +### MsgEditStorageProvider + +The metadata of a storage provider can be edit using `MsgEditStorageProvider` messages. + +```protobuf +// MsgEditStorageProvider defines a SDK message for editing an existing sp. +message MsgEditStorageProvider { + option (cosmos.msg.v1.signer) = "sp_address"; + + string sp_address = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + string endpoint = 2; + Description description = 3 [(gogoproto.nullable) = false]; +} +``` + +This message is expected to fail if: + +* the storage provider is not exist +* the description fields are too large + +### MsgDeposit + +When the deposit tokens of a storage provider is insufficient, it can use `MsgDeposit` messages to resupply the +deposit tokens. + +```protobuf +// MsgDeposit defines a SDK message for deposit token for sp. +message MsgDeposit { + option (cosmos.msg.v1.signer) = "creator"; + + // creator is the msg signer, it should be sp address or sp's fund address + string creator = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // sp_address is the operator address of sp + string sp_address = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // deposit is a mount of token which used to deposit for SP + cosmos.base.v1beta1.Coin deposit = 3 [(gogoproto.nullable) = false]; +} +``` + +This message is expected to fail if: + +* the storage provider is not exist +* the deposit tokens are of a denom not specified as the deposit denom of sp module + diff --git a/docs/architecture/05-storage-metadata-models.md b/docs/architecture/05-storage-metadata-models.md index e69de29bb..0f7967de3 100644 --- a/docs/architecture/05-storage-metadata-models.md +++ b/docs/architecture/05-storage-metadata-models.md @@ -0,0 +1,417 @@ +# Storage MetaData Models + +## Abstract +The basic data models for Greenfield storage are: + +- bucket +- object +- group +- permission + +These metadata are stored as blockchain state into the persistent storage of the Greenfield blockchain. + +## Concepts + +### Bucket + +Bucket is the unit to group storage "objects". BucketName has to be globally unique. Every user account can create a +bucket. The account will become the "owner" of the bucket. + +Each bucket should be associated with its own Primary SP, and the payment accounts for Read and Store. The owner's +address will be the default payment account. + +### Object + +Object is the basic unit to store data on Greenfield. The metadata for the object will be stored on the Greenfield +blockchain: + +- name and ID +- owner +- bucket that hosts it +- size and timestamps +- content type +- checkSums for the storage pieces +- storage status +- associated SP information + +Object metadata is stored with the bucket name as the prefix of the key. It is possible to iterate through all +objects under the same bucket, but it may be a heavy-lifting job for a large bucket with lots of objects. + +### Group + +A Group is a collection of accounts with the same permissions. The group name is not allowed to be duplicated under the +same user. However, a group can not create or own any resource. A group can not be a member of another group either. + +A resource can only have a limited number of groups associated with it for permissions. This ensures that the on-chain +permission check can be finished within a constant time. + +## State + +The storage module keeps state of the following primary objects: + +* BucketInfo +* ObjectInfo +* GroupInfo + +These primary objects should be primarily stored and accessed by the `ID` which is a auto-incremented sequence. An +additional indices are maintained per primary objects in order to compatibility with the S3 object storage. + +* BucketInfo: `0x11 | hash(bucketName) -> BigEndian(bucketId)` +* ObjectInfo: `0x12 | hash(bucketName)_hash(objectName) -> BigEndian(objectId)` +* GroupInfo: `0x13 | OwnerAddr_hash(groupName) -> BigEndian(groupId)` + +* BucketInfoById: `0x21 | BigEndian(bucketId) -> ProtoBuf(BucketInfo)` +* ObjectInfoById: `0x22 | BigEndian(objectId) -> ProtoBuf(ObjectInfo)` +* GroupInfoById: `0x23 | BigEndian(groupId) -> ProtoBuf(GroupInfo)` + +```protobuf +message BucketInfo { + // owner is the account address of bucket creator, it is also the bucket owner. + string owner = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // bucket_name is a globally unique name of bucket + string bucket_name = 2; + // is_public define the highest permissions for bucket. When the bucket is public, everyone can get the object in it. + bool is_public = 3; + // id is the unique identification for bucket. + string id = 4 [ + (cosmos_proto.scalar) = "cosmos.Uint", + (gogoproto.customtype) = "Uint", + (gogoproto.nullable) = false + ]; + // source_type define the source of the bucket + SourceType source_type = 5; + // create_at define the block number when the bucket created. + int64 create_at = 6; + // payment_address is the address of the payment account + string payment_address = 7 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // primary_sp_address is the address of the primary sp. Objects belongs to this bucket will never + // leave this SP, unless you explicitly shift them to another SP. + string primary_sp_address = 8 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // read_quota defines the traffic quota for read + ReadQuota read_quota = 9; + // payment_price_time TODO(Owen): refine the comments + int64 payment_price_time = 10; + // payment_out_flows + repeated payment.OutFlowInUSD payment_out_flows = 11 [(gogoproto.nullable) = false]; +} + +message ObjectInfo { + string owner = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // bucket_name is the name of the bucket + string bucket_name = 2; + // object_name is the name of object + string object_name = 3; + // id is the unique identifier of object + string id = 4 [ + (cosmos_proto.scalar) = "cosmos.Uint", + (gogoproto.customtype) = "Uint", + (gogoproto.nullable) = false + ]; + // payloadSize is the total size of the object payload + uint64 payload_size = 5; + // is_public define the highest permissions for object. When the object is public, everyone can access it. + bool is_public = 6; + // content_type define the format of the object which should be a standard MIME type. + string content_type = 7; + // create_at define the block number when the object created + int64 create_at = 8; + // object_status define the upload status of the object. + ObjectStatus object_status = 9; + // redundancy_type define the type of the redundancy which can be multi-replication or EC. + RedundancyType redundancy_type = 10; + // source_type define the source of the object. + SourceType source_type = 11; + // checksums define the root hash of the pieces which stored in a SP. + repeated bytes checksums = 12; + // secondary_sp_addresses define the addresses of secondary_sps + repeated string secondary_sp_addresses = 13 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // lockedBalance + string lockedBalance = 14 [ + (cosmos_proto.scalar) = "cosmos.Int", + (gogoproto.customtype) = "github.com/cosmos/cosmos-sdk/types.Int" + ]; +} + +message GroupInfo { + // owner is the owner of the group. It can not changed once it created. + string owner = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // group_name is the name of group which is unique under an account. + string group_name = 2; + // source_type + SourceType source_type = 3; + // id is the unique identifier of group + string id = 4 [ + (cosmos_proto.scalar) = "cosmos.Uint", + (gogoproto.customtype) = "Uint", + (gogoproto.nullable) = false + ]; +} +``` + +### Params + +The storage module contains the following parameters, +they can be updated with governance. + +```protobuf +// Params defines the parameters for the module. +message Params { + // TODO: We should think more about the version-control of the storage params. + option (gogoproto.goproto_stringer) = false; + + // max_segment_size is the maximum size of a segment. default: 16M + uint64 max_segment_size = 1; + // redundant_data_check_num is the num of data chunks of EC redundancy algorithm + uint32 redundant_data_chunk_num = 2; + // redundant_data_check_num is the num of parity chunks of EC redundancy algorithm + uint32 redundant_parity_chunk_num = 3; + // max_payload_size is the maximum size of the payload, default: 2G + uint64 max_payload_size = 4; +} +``` + +* the max_segment_size/redundant_data_chunk_num/redundant_parity_chunk_num is for redundancy algorithm +* the max_payload_size is a limit on the size of objects uploaded by users + +## Keepers + +The storage module keeper provides access to query the parameters, bucketInfo, objectInfo, groupInfo and several +interface for Create/Delete/Update the resources. + + +## Messages + +### MsgCreateBucket + +Used to create bucket for user + +```protobuf +message MsgCreateBucket { + option (cosmos.msg.v1.signer) = "creator"; + + // creator is the account address of bucket creator, it is also the bucket owner. + string creator = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // bucket_name is a globally unique name of bucket + string bucket_name = 2; + // is_public means the bucket is private or public. if private, only bucket owner or grantee can read it, + // otherwise every greenfield user can read it. + bool is_public = 3; + // payment_address is an account address specified by bucket owner to pay the read fee. Default: creator + string payment_address = 4 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // primary_sp_address is the address of primary sp. + string primary_sp_address = 6 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // primary_sp_approval is the approval info of the primary SP which indicates that primary sp confirm the user's request. + Approval primary_sp_approval = 7; + // read_quota + ReadQuota read_quota = 8; +} +``` + +### MsgDeleteBucket + +Used to delete bucket for user. It is important to note that you cannot delete a non-empty bucket. + +```protobuf +message MsgDeleteBucket { + option (cosmos.msg.v1.signer) = "operator"; + + // creator is the account address of the grantee who has the DeleteBucket permission of the bucket to be deleted. + string operator = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // bucket_name is the name of the bucket to be deleted. + string bucket_name = 2; +} +``` + +### MsgUpdateBucketInfo +Used to update bucket info for user. + +```protobuf +message MsgUpdateBucketInfo { + option (cosmos.msg.v1.signer) = "operator"; + + // operator is the account address of the operator + string operator = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + + // bucket_name is the name of bucket which you'll update + string bucket_name = 2; + + // read_quota is the traffic quota that you read from primary sp + ReadQuota read_quota = 3; + + // payment_address is the account address of the payment account + string payment_address = 4 [(cosmos_proto.scalar) = "cosmos.AddressString"]; +} +``` + +### MsgCreateObject + +Used to create object under a bucket for user. + +```protobuf +message MsgCreateObject { + option (cosmos.msg.v1.signer) = "creator"; + + // creator is the account address of object uploader + string creator = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // bucket_name is the name of the bucket where the object is stored. + string bucket_name = 2; + // object_name is the name of object + string object_name = 3; + // payload_size is size of the object's payload + uint64 payload_size = 4; + // is_public means the bucket is private or public. if private, only bucket owner or grantee can access it, + // otherwise every greenfield user can access it. + bool is_public = 5; + // content_type is a standard MIME type describing the format of the object. + string content_type = 6; + // primary_sp_approval is the approval info of the primary SP which indicates that primary sp confirm the user's request. + Approval primary_sp_approval = 7; + // expect_checksums is a list of hashes which was generate by redundancy algorithm. + repeated bytes expect_checksums = 8; + // redundancy_type can be ec or replica + RedundancyType redundancy_type = 9; + // expect_secondarySPs is a list of StorageProvider address, which is optional + repeated string expect_secondary_sp_addresses = 10 [(cosmos_proto.scalar) = "cosmos.AddressString"]; +} + +``` +### MsgDeleteObject + +Used to delete object for user. + +```protobuf +message MsgDeleteObject { + option (cosmos.msg.v1.signer) = "operator"; + + // operator is the account address of the operator who has the DeleteObject permission of the object to be deleted. + string operator = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // bucket_name is the name of the bucket where the object which to be deleted is stored. + string bucket_name = 2; + // object_name is the name of the object which to be deleted. + string object_name = 3; +} + +``` +### MsgSealObject + +Used to seal object for storage provider. + +```protobuf +message MsgSealObject { + option (cosmos.msg.v1.signer) = "operator"; + + // operator is the account address of primary SP + string operator = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // bucket_name is the name of the bucket where the object is stored. + string bucket_name = 2; + // object_name is the name of object to be sealed. + string object_name = 3; + // secondary_sp_addresses is a list of storage provider which store the redundant data. + repeated string secondary_sp_addresses = 4 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // secondary_sp_signatures is the signature of the secondary sp that can + // acknowledge that the payload data has received and stored. + repeated bytes secondary_sp_signatures = 5; +} + +``` +### MsgCopyObject + +Used to copy object for user. + +```protobuf +message MsgCopyObject { + option (cosmos.msg.v1.signer) = "operator"; + + // operator is the account address of the operator who has the CopyObject permission of the object to be deleted. + string operator = 1; + // src_bucket_name is the name of the bucket where the object to be copied is located + string src_bucket_name = 2; + // dst_bucket_name is the name of the bucket where the object is copied to. + string dst_bucket_name = 3; + // src_object_name is the name of the object which to be copied + string src_object_name = 4; + // dst_object_name is the name of the object which is copied to + string dst_object_name = 5; + // primary_sp_approval is the approval info of the primary SP which indicates that primary sp confirm the user's request. + Approval dst_primary_sp_approval = 6; +} +``` +### MsgRejectSealObject + +Used to reject seal object for sp. + +```protobuf +message MsgRejectSealObject { + option (cosmos.msg.v1.signer) = "operator"; + // operator is the account address of the object owner + string operator = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // bucket_name is the name of the bucket where the object is stored. + string bucket_name = 2; + // object_name is the name of unsealed object to be reject. + string object_name = 3; +} +``` +### MsgCancelCreateObject + +Used to cancel create object for user. + +```protobuf +message MsgCancelCreateObject { + option (cosmos.msg.v1.signer) = "operator"; + // operator is the account address of the operator + string operator = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // bucket_name is the name of the bucket + string bucket_name = 2; + // object_name is the name of the object + string object_name = 3; +} +``` +### MsgCreateGroup + +Used to create group for user. + +```protobuf +message MsgCreateGroup { + option (cosmos.msg.v1.signer) = "creator"; + + // owner is the account address of group owner who create the group + string creator = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // group_name is the name of the group. it's not globally unique. + string group_name = 2; + // member_request is a list of member which to be add or remove + repeated string members = 3 [(cosmos_proto.scalar) = "cosmos.AddressString"]; +} +``` +### MsgDeleteGroup + +Used to delete group for user. + +```protobuf +message MsgDeleteGroup { + option (cosmos.msg.v1.signer) = "operator"; + + // operator is the account address of the operator who has the DeleteGroup permission of the group to be deleted. + string operator = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // group_name is the name of the group which to be deleted + string group_name = 2; +} + +``` +### MsgLeaveGroup + +Used to leave a group for group member + +```protobuf +message MsgLeaveGroup { + option (cosmos.msg.v1.signer) = "member"; + + // member is the account address of the member who want to leave the group + string member = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // group_owner is the owner of the group you want to leave + string group_owner = 2 [(cosmos_proto.scalar) = "cosmos.AddressString"]; + // group_name is the name of the group you want to leave + string group_name = 3; +} +``` + diff --git a/docs/tutorial/06-storage.md b/docs/tutorial/06-storage.md index e69de29bb..a85b40860 100644 --- a/docs/tutorial/06-storage.md +++ b/docs/tutorial/06-storage.md @@ -0,0 +1,18 @@ +# Using gnfd command to interact with storage module + +## HeadBucket + +```shell +gnfd query storage head-bucket [bucket-name] [flags] +``` + +## HeadObject + +```shell +gnfd query storage head-object [bucket-name] [object-name] [flags] +``` + +# Others operations + +This repo provides the command-line tool to createBucket, createObject, uploadObject, downloadObject and others +operations. You can go to see [greenfiled-cmd](https://github.com/bnb-chain/greenfield-cmd) for details. \ No newline at end of file diff --git a/docs/tutorial/07-storage-provider.md b/docs/tutorial/07-storage-provider.md index e69de29bb..f774f43b2 100644 --- a/docs/tutorial/07-storage-provider.md +++ b/docs/tutorial/07-storage-provider.md @@ -0,0 +1,94 @@ +# Using gnfd command to interact with bank module + +## QuickStart + +Start a local chain with 1 validator and 1 Storage provider +```shell +$ bash ./deployment/localup/localup.sh all 1 1 +``` + +Export the accounts priv key of sp + +```shell +$ bash ./deployment/localup/localup.sh export_sp_privkey 1 1 +``` + +check the status of sp + +```shell +bash ./deployment/localup/localup.sh sp_check 1 +``` + +## Create Storage Provider + +* Authorize the Gov Module Account to debit tokens from the Funding account of SP + +```shell +./build/bin/gnfd tx sp grant 0x7b5Fe22B5446f7C62Ea27B8BD71CeF94e03f3dF2 --spend-limit 1000000bnb --SPAddress 0x78FeF615b06251ecfA9Ba01B7DB2BFA892722dDC --from sp0_fund --home ./deployment/localup/.local/sp0 --keyring-backend test --node http://localhost:26750 +``` + +* submit-proposal +```shell +./build/bin/gnfd tx gov submit-proposal ./deployment/localup/create_sp.json --from sp0 --keyring-backend test --home ./deployment/localup/.local/sp0 --node http://localhost:26750 + +# create_sp.json +./create_sp.json +{ + "messages":[ + { + "@type":"/bnbchain.greenfield.sp.MsgCreateStorageProvider", + "description":{ + "moniker": "sp0", + "identity":"", + "website":"", + "security_contact":"", + "details":"" + }, + "sp_address":"0x78FeF615b06251ecfA9Ba01B7DB2BFA892722dDC", + "funding_address":"0x1d05CCD43A6c27fBCdfE6Ac727B0e9B889AAbC3B", + "seal_address": "0x78FeF615b06251ecfA9Ba01B7DB2BFA892722dDC", + "approval_address": "0x78FeF615b06251ecfA9Ba01B7DB2BFA892722dDC", + "endpoint": "sp0.greenfield.io", + "deposit":{ + "denom":"bnb", + "amount":"10000" + }, + "creator":"0x7b5Fe22B5446f7C62Ea27B8BD71CeF94e03f3dF2" + } +], + "metadata": "4pIMOgIGx1vZGU=", + "deposit": "1bnb" +} +``` + +* deposit tokens to the proposal + +```shell +./build/bin/gnfd tx gov deposit 1 10000bnb --from sp0 --keyring-backend test --home ./deployment/localup/.local/sp0 --node http://localhost:26750 +``` + +* voted by validator + +```shell +./build/bin/gnfd tx gov deposit 1 10000bnb --from sp0 --keyring-backend test --home ./deployment/localup/.local/sp0 --node http://localhost:26750 +``` + +* wait a VOTE_PERIOD(300s), and the check the status of sp + +```shell +./build/bin/gnfd query sp storage-providers --node http://localhost:26750 +``` + + +## Deposit + +```shell +gnfd tx sp deposit [sp-address] [value] [flags] +``` + + +## EditStorageProvider + +```shell +gnfd tx sp edit-storage-provider [sp-address] [flags] +``` \ No newline at end of file diff --git a/go.mod b/go.mod index 10c2efaa0..8a3596fe6 100644 --- a/go.mod +++ b/go.mod @@ -140,13 +140,13 @@ require ( github.com/jpillora/sizestr v1.0.0 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/klauspost/compress v1.15.11 // indirect - github.com/klauspost/cpuid/v2 v2.0.9 // indirect + github.com/klauspost/cpuid/v2 v2.2.4 // indirect github.com/lib/pq v1.10.6 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/magiconair/properties v1.8.6 // indirect github.com/manifoldco/promptui v0.9.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-runewidth v0.0.10 // indirect github.com/mattn/go-zglob v0.0.3 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect @@ -180,7 +180,7 @@ require ( github.com/regen-network/cosmos-proto v0.3.1 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/rs/cors v1.8.2 // indirect - github.com/rs/zerolog v1.27.0 // indirect + github.com/rs/zerolog v1.29.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/sergi/go-diff v1.2.0 // indirect diff --git a/go.sum b/go.sum index b9e604eb8..684df7dff 100644 --- a/go.sum +++ b/go.sum @@ -1063,8 +1063,9 @@ github.com/klauspost/compress v1.15.11/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrD github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= +github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/reedsolomon v1.9.3/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4= @@ -1256,8 +1257,9 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -1627,9 +1629,9 @@ github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XF github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= -github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs= -github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U= +github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.29.0 h1:Zes4hju04hjbvkVkOhdl2HpZa+0PmVwigmo8XoORE5w= +github.com/rs/zerolog v1.29.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -2256,6 +2258,7 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=